use std::collections::{BTreeMap, BTreeSet};
use crate::path::{validate_rel_dir_path, validate_rel_path};
use crate::svndiff::{SvndiffVersion, encode_fulltext_with_options};
use crate::{Capability, EditorCommand, NodeKind, RaSvnSession, SvnError};
use super::util::{
CopyKind, DirCreateMode, FileContentMode, SvndiffMode, TokenGen, dir_prefixes, parent_dir,
select_svndiff_version,
};
mod build;
mod plan;
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Debug)]
pub struct CommitBuilder {
base_rev: Option<u64>,
svndiff: SvndiffMode,
zlib_level: u32,
window_size: usize,
changes: Vec<Change>,
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Debug)]
enum Change {
PutFile {
path: String,
contents: Vec<u8>,
mode: FileContentMode,
},
MkdirP {
path: String,
mode: DirCreateMode,
},
Delete {
path: String,
},
Copy {
from_path: String,
from_rev: Option<u64>,
to_path: String,
kind: CopyKind,
},
FileProp {
path: String,
name: String,
value: Option<Vec<u8>>,
},
DirProp {
path: String,
name: String,
value: Option<Vec<u8>>,
},
}
impl CommitBuilder {
pub fn new() -> Self {
Self {
base_rev: None,
svndiff: SvndiffMode::Auto,
zlib_level: 5,
window_size: 64 * 1024,
changes: Vec::new(),
}
}
pub fn with_base_rev(mut self, base_rev: u64) -> Self {
self.base_rev = Some(base_rev);
self
}
pub fn with_svndiff(mut self, svndiff: SvndiffMode) -> Self {
self.svndiff = svndiff;
self
}
pub fn with_zlib_level(mut self, level: u32) -> Self {
self.zlib_level = level;
self
}
pub fn with_window_size(mut self, window_size: usize) -> Self {
self.window_size = window_size;
self
}
fn put_file_with_mode(
mut self,
path: impl Into<String>,
contents: impl Into<Vec<u8>>,
mode: FileContentMode,
) -> Self {
self.changes.push(Change::PutFile {
path: path.into(),
contents: contents.into(),
mode,
});
self
}
pub fn put_file(self, path: impl Into<String>, contents: impl Into<Vec<u8>>) -> Self {
self.put_file_with_mode(path, contents, FileContentMode::AddOrReplace)
}
pub fn add_file(self, path: impl Into<String>, contents: impl Into<Vec<u8>>) -> Self {
self.put_file_with_mode(path, contents, FileContentMode::Add)
}
pub fn replace_file(self, path: impl Into<String>, contents: impl Into<Vec<u8>>) -> Self {
self.put_file_with_mode(path, contents, FileContentMode::Replace)
}
fn mkdir_with_mode(mut self, path: impl Into<String>, mode: DirCreateMode) -> Self {
self.changes.push(Change::MkdirP {
path: path.into(),
mode,
});
self
}
pub fn mkdir_p(self, path: impl Into<String>) -> Self {
self.mkdir_with_mode(path, DirCreateMode::Ensure)
}
pub fn add_dir(self, path: impl Into<String>) -> Self {
self.mkdir_with_mode(path, DirCreateMode::Add)
}
pub fn delete(mut self, path: impl Into<String>) -> Self {
self.changes.push(Change::Delete { path: path.into() });
self
}
fn copy_with_kind(
mut self,
from_path: impl Into<String>,
from_rev: Option<u64>,
to_path: impl Into<String>,
kind: CopyKind,
) -> Self {
self.changes.push(Change::Copy {
from_path: from_path.into(),
from_rev,
to_path: to_path.into(),
kind,
});
self
}
pub fn copy(self, from_path: impl Into<String>, to_path: impl Into<String>) -> Self {
self.copy_with_kind(from_path, None, to_path, CopyKind::Any)
}
pub fn copy_from_rev(
self,
from_path: impl Into<String>,
from_rev: u64,
to_path: impl Into<String>,
) -> Self {
self.copy_with_kind(from_path, Some(from_rev), to_path, CopyKind::Any)
}
pub fn copy_file(self, from_path: impl Into<String>, to_path: impl Into<String>) -> Self {
self.copy_with_kind(from_path, None, to_path, CopyKind::File)
}
pub fn copy_file_from_rev(
self,
from_path: impl Into<String>,
from_rev: u64,
to_path: impl Into<String>,
) -> Self {
self.copy_with_kind(from_path, Some(from_rev), to_path, CopyKind::File)
}
pub fn copy_dir(self, from_path: impl Into<String>, to_path: impl Into<String>) -> Self {
self.copy_with_kind(from_path, None, to_path, CopyKind::Dir)
}
pub fn copy_dir_from_rev(
self,
from_path: impl Into<String>,
from_rev: u64,
to_path: impl Into<String>,
) -> Self {
self.copy_with_kind(from_path, Some(from_rev), to_path, CopyKind::Dir)
}
pub fn move_path(self, from_path: impl Into<String>, to_path: impl Into<String>) -> Self {
let from_path = from_path.into();
self.copy(from_path.clone(), to_path).delete(from_path)
}
pub fn move_path_from_rev(
self,
from_path: impl Into<String>,
from_rev: u64,
to_path: impl Into<String>,
) -> Self {
let from_path = from_path.into();
self.copy_from_rev(from_path.clone(), from_rev, to_path)
.delete(from_path)
}
pub fn move_file(self, from_path: impl Into<String>, to_path: impl Into<String>) -> Self {
let from_path = from_path.into();
self.copy_file(from_path.clone(), to_path).delete(from_path)
}
pub fn move_file_from_rev(
self,
from_path: impl Into<String>,
from_rev: u64,
to_path: impl Into<String>,
) -> Self {
let from_path = from_path.into();
self.copy_file_from_rev(from_path.clone(), from_rev, to_path)
.delete(from_path)
}
pub fn move_dir(self, from_path: impl Into<String>, to_path: impl Into<String>) -> Self {
let from_path = from_path.into();
self.copy_dir(from_path.clone(), to_path).delete(from_path)
}
pub fn move_dir_from_rev(
self,
from_path: impl Into<String>,
from_rev: u64,
to_path: impl Into<String>,
) -> Self {
let from_path = from_path.into();
self.copy_dir_from_rev(from_path.clone(), from_rev, to_path)
.delete(from_path)
}
pub fn file_prop(
mut self,
path: impl Into<String>,
name: impl Into<String>,
value: Option<Vec<u8>>,
) -> Self {
self.changes.push(Change::FileProp {
path: path.into(),
name: name.into(),
value,
});
self
}
pub fn set_file_prop(
self,
path: impl Into<String>,
name: impl Into<String>,
value: impl Into<Vec<u8>>,
) -> Self {
self.file_prop(path, name, Some(value.into()))
}
pub fn delete_file_prop(self, path: impl Into<String>, name: impl Into<String>) -> Self {
self.file_prop(path, name, None)
}
pub fn dir_prop(
mut self,
path: impl Into<String>,
name: impl Into<String>,
value: Option<Vec<u8>>,
) -> Self {
self.changes.push(Change::DirProp {
path: path.into(),
name: name.into(),
value,
});
self
}
pub fn set_dir_prop(
self,
path: impl Into<String>,
name: impl Into<String>,
value: impl Into<Vec<u8>>,
) -> Self {
self.dir_prop(path, name, Some(value.into()))
}
pub fn delete_dir_prop(self, path: impl Into<String>, name: impl Into<String>) -> Self {
self.dir_prop(path, name, None)
}
}
impl Default for CommitBuilder {
fn default() -> Self {
Self::new()
}
}