#![warn(clippy::pedantic)]
#![warn(clippy::nursery)]
use std::collections::HashMap;
use std::fs::{File, Metadata};
use std::path::{Path, PathBuf};
use std::time::Instant;
use serde::{Deserialize, Serialize};
mod object;
mod workarea;
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
struct ContributorId(String);
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
struct ChannelId(String);
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
struct PatchId(String);
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
struct FileId(String);
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
struct SpanNodeId(String);
struct Remote {
url: String,
name: String,
}
struct Contributor {
id: ContributorId,
emails: Vec<String>,
nickname: String,
realname: Option<String>,
public_keys: Vec<String>,
}
struct Channel {
id: ChannelId,
name: String,
remotes: Vec<Remote>,
main_remote: Option<Remote>,
patches: Vec<PatchId>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
struct Patch {
id: PatchId,
authors: Vec<ContributorId>,
recorder: ContributorId,
metadata: HashMap<String, String>,
affected_files: Vec<FileId>,
contents: String,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
struct FileInfo {
id: FileId,
root_span: SpanNodeId,
name_changes: Vec<(PatchId, FilenameOperation)>,
spans: Vec<SpanNode>,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
enum FilenameOperation {
Add { filename: PathBuf },
Rename { filename: PathBuf },
Delete,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
struct SpanNode {
id: SpanNodeId,
span: Span,
added_by: Vec<PatchId>,
deleted_by: Vec<PatchId>,
preceding_nodes: Vec<SpanNodeId>,
successor_nodes: Vec<SpanNodeId>,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
struct Span {
patch: PatchId,
start: usize,
len: usize,
}
type DiffAlgorithm = fn(File, File) -> Diff;
struct Diff(Vec<DiffSpan>);
struct DiffSpan {
left: Vec<u8>,
right: Vec<u8>,
}
struct Log {
entries: Vec<LogEntry>,
}
enum LogEntry {
CreatePatch(PatchId),
}
type RevertAlgorithm = fn(Patch) -> Patch;
trait Id {
fn id(&self) -> &str;
}
impl Id for Patch {
fn id(&self) -> &str {
&self.id.0
}
}
impl Id for FileInfo {
fn id(&self) -> &str {
&self.id.0
}
}
trait StagingArea {
fn list_files() -> std::io::Result<Metadata>;
fn open_file(path: &Path) -> std::io::Result<File>;
fn file_metadata(path: &Path) -> std::io::Result<Metadata>;
fn is_file_changed(path: &Path, since: Instant) -> std::io::Result<bool>;
}
trait Repository {
fn archive(&self) -> Vec<u8>;
fn remotes(&self) -> Vec<Remote>;
fn main_remote(&self) -> Option<Remote>;
fn set_main_remote(&mut self, remote: Option<Remote>);
fn add_remote(&mut self, remote: Remote);
fn delete_remote(&mut self, remote: Remote);
fn push(&self, remote: Remote);
fn pull(&mut self, remote: Remote);
fn all_contributors(&self) -> Vec<ContributorId>;
fn contributor(&self, id: ContributorId) -> Contributor;
fn credit(&self, filename: &Path, byte: usize) -> Option<ContributorId>;
fn all_channels(&self) -> Vec<ChannelId>;
fn active_channel(&self) -> ChannelId;
fn channel(&self, id: ChannelId) -> Channel;
fn create_channel(&mut self, channel: Channel);
fn change_channel(&mut self, id: ChannelId) -> Channel;
fn rename_channel(&mut self, id: ChannelId, name: &str) -> Channel;
fn delete_channel(&mut self, id: ChannelId);
fn add_patches_to_channel(&mut self, channel: ChannelId, patches: &[PatchId]) -> Channel;
fn add_channel_to_channel(&mut self, channel: ChannelId, plus: ChannelId) -> Channel;
fn all_patches(&self) -> Vec<PatchId>;
fn active_patches(&self) -> Vec<PatchId>;
fn patch(&self, id: PatchId) -> Option<Patch>;
fn create_patch(&mut self, patch: Patch);
fn delete_patch(&mut self, id: PatchId);
fn set_active_patches(&mut self, ids: &[PatchId]);
fn combine_patches(&mut self, patches: &[PatchId]) -> Patch;
fn active_files(&self) -> Vec<FileId>;
fn file(&self, id: FileId) -> Option<FileInfo>;
fn write_file_from_patch(&self, id: FileId, patch: PatchId) -> Vec<u8>;
}
|