use std::{
ffi::OsStr,
path::PathBuf,
process::{Child, Command, Stdio},
};
use super::{ExclusiveOption, SubCommand, Unselected};
use crate::global::GlobalOpts;
use crate::spawn::ParameterizedSpawn;
#[derive(Debug, Clone, Default)]
pub struct ParallelConfig {
pub threads: u64,
pub batch_files: Option<u64>,
pub batch_size_bytes: Option<u64>,
pub min_files: Option<u64>,
pub min_size_bytes: Option<u64>,
}
impl ParallelConfig {
pub fn as_arg(&self) -> String {
let mut parts = vec![format!("threads={}", self.threads)];
if let Some(v) = self.batch_files {
parts.push(format!("batch={}", v));
}
if let Some(v) = self.batch_size_bytes {
parts.push(format!("batchsize={}", v));
}
if let Some(v) = self.min_files {
parts.push(format!("min={}", v));
}
if let Some(v) = self.min_size_bytes {
parts.push(format!("minsize={}", v));
}
parts.join(",")
}
}
#[derive(Debug, Clone, Copy)]
pub enum StreamSpecVersion {
MaxInFilelists,
Current,
ChangeNumber(u32),
}
impl StreamSpecVersion {
pub fn max_in_filelists() -> Self {
StreamSpecVersion::MaxInFilelists
}
pub fn current() -> Self {
StreamSpecVersion::Current
}
pub fn at_change(n: u32) -> Self {
StreamSpecVersion::ChangeNumber(n)
}
pub fn inject_arg(&self, command: &mut Command) {
match self {
StreamSpecVersion::MaxInFilelists => {
command.arg("--use-stream-change");
}
StreamSpecVersion::Current => {
command.arg("--use-stream-change=0");
}
StreamSpecVersion::ChangeNumber(n) => {
command.arg(format!("--use-stream-change={}", n));
}
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct PreviewResult;
impl ExclusiveOption for PreviewResult {
fn inject_args(&self, command: &mut Command) {
command.arg("-n");
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct PreviewNetworkTraffic;
impl ExclusiveOption for PreviewNetworkTraffic {
fn inject_args(&self, command: &mut Command) {
command.arg("-N");
}
}
#[derive(Debug, Clone, Default)]
pub struct ForceRegularMode {
force: bool,
metadata_only: bool,
reopen_moved_files: bool,
}
impl ExclusiveOption for ForceRegularMode {
fn inject_args(&self, command: &mut Command) {
if self.force {
command.arg("-f");
}
if self.metadata_only {
command.arg("-k");
}
if self.reopen_moved_files {
command.arg("-r");
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct SafeCheckMode;
impl ExclusiveOption for SafeCheckMode {
fn inject_args(&self, command: &mut Command) {
command.arg("-s");
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct PopulateMode;
impl ExclusiveOption for PopulateMode {
fn inject_args(&self, command: &mut Command) {
command.arg("-p");
}
}
#[derive(Debug, Clone, Default)]
pub struct RegularMode<Mode = Unselected, P = Unselected> {
verify_edge_replication: bool,
script_list_mode: bool,
suppress_keyword_expansion: bool,
quiet_mode: bool,
limit: Option<u64>,
parallel: Option<ParallelConfig>,
stream_spec_version: Option<StreamSpecVersion>,
mode: Mode,
preview: P,
}
impl<Mode: ExclusiveOption, P: ExclusiveOption> ExclusiveOption for RegularMode<Mode, P> {
fn inject_args(&self, command: &mut Command) {
if self.verify_edge_replication {
command.arg("-E");
}
if self.script_list_mode {
command.arg("-L");
}
if self.suppress_keyword_expansion {
command.arg("-K");
}
if self.quiet_mode {
command.arg("-q");
}
self.mode.inject_args(command);
self.preview.inject_args(command);
if let Some(max) = self.limit {
command.arg("-m").arg(max.to_string());
}
if let Some(parallel) = &self.parallel {
command.arg(format!("--parallel={}", parallel.as_arg()));
}
if let Some(version) = &self.stream_spec_version {
version.inject_arg(command);
}
}
}
#[derive(Debug, Clone)]
pub struct SyncTimeMode {
sync_time: String,
}
impl ExclusiveOption for SyncTimeMode {
fn inject_args(&self, command: &mut Command) {
command
.arg("-k")
.arg(format!("--sync-time={}", self.sync_time));
}
}
#[derive(Debug, Clone, Default)]
pub struct Sync<M = Unselected> {
bin: PathBuf,
global_opts: GlobalOpts,
mode: M,
}
impl Sync<Unselected> {
pub fn new(bin: impl Into<PathBuf>, global_opts: GlobalOpts) -> Self {
Self {
bin: bin.into(),
global_opts,
mode: Unselected,
}
}
pub fn sync_time(self, time: impl Into<String>) -> Sync<SyncTimeMode> {
Sync {
bin: self.bin,
global_opts: self.global_opts,
mode: SyncTimeMode {
sync_time: time.into(),
},
}
}
pub fn enable_safe_check(self) -> Sync<RegularMode<SafeCheckMode>> {
Sync {
bin: self.bin,
global_opts: self.global_opts,
mode: RegularMode {
mode: SafeCheckMode,
..RegularMode::default()
},
}
}
pub fn populate_client_workspace(self) -> Sync<RegularMode<PopulateMode>> {
Sync {
bin: self.bin,
global_opts: self.global_opts,
mode: RegularMode {
mode: PopulateMode,
..RegularMode::default()
},
}
}
pub fn verify_edge_replication(self, v: bool) -> Sync<RegularMode> {
Sync {
bin: self.bin,
global_opts: self.global_opts,
mode: RegularMode {
verify_edge_replication: v,
..RegularMode::default()
},
}
}
pub fn script_list_mode(self, v: bool) -> Sync<RegularMode> {
Sync {
bin: self.bin,
global_opts: self.global_opts,
mode: RegularMode {
script_list_mode: v,
..RegularMode::default()
},
}
}
pub fn suppress_keyword_expansion(self, v: bool) -> Sync<RegularMode> {
Sync {
bin: self.bin,
global_opts: self.global_opts,
mode: RegularMode {
suppress_keyword_expansion: v,
..RegularMode::default()
},
}
}
pub fn quiet_mode(self, v: bool) -> Sync<RegularMode> {
Sync {
bin: self.bin,
global_opts: self.global_opts,
mode: RegularMode {
quiet_mode: v,
..RegularMode::default()
},
}
}
pub fn limit(self, v: u64) -> Sync<RegularMode> {
Sync {
bin: self.bin,
global_opts: self.global_opts,
mode: RegularMode {
limit: Some(v),
..RegularMode::default()
},
}
}
pub fn parallel(self, v: ParallelConfig) -> Sync<RegularMode> {
Sync {
bin: self.bin,
global_opts: self.global_opts,
mode: RegularMode {
parallel: Some(v),
..RegularMode::default()
},
}
}
pub fn stream_spec_version(self, v: StreamSpecVersion) -> Sync<RegularMode> {
Sync {
bin: self.bin,
global_opts: self.global_opts,
mode: RegularMode {
stream_spec_version: Some(v),
..RegularMode::default()
},
}
}
pub fn sc_max_change_number(self) -> Sync<RegularMode> {
self.stream_spec_version(StreamSpecVersion::MaxInFilelists)
}
pub fn sc_current_stream_spec(self) -> Sync<RegularMode> {
self.stream_spec_version(StreamSpecVersion::Current)
}
pub fn sc_change_number(self, n: u32) -> Sync<RegularMode> {
self.stream_spec_version(StreamSpecVersion::ChangeNumber(n))
}
pub fn preview_result(self) -> Sync<RegularMode<Unselected, PreviewResult>> {
Sync {
bin: self.bin,
global_opts: self.global_opts,
mode: RegularMode {
preview: PreviewResult,
..RegularMode::default()
},
}
}
pub fn preview_network_traffic(self) -> Sync<RegularMode<Unselected, PreviewNetworkTraffic>> {
Sync {
bin: self.bin,
global_opts: self.global_opts,
mode: RegularMode {
preview: PreviewNetworkTraffic,
..RegularMode::default()
},
}
}
pub fn force(self, v: bool) -> Sync<RegularMode<ForceRegularMode>> {
Sync {
bin: self.bin,
global_opts: self.global_opts,
mode: RegularMode {
mode: ForceRegularMode {
force: v,
..ForceRegularMode::default()
},
..RegularMode::default()
},
}
}
pub fn metadata_only(self, v: bool) -> Sync<RegularMode<ForceRegularMode>> {
Sync {
bin: self.bin,
global_opts: self.global_opts,
mode: RegularMode {
mode: ForceRegularMode {
metadata_only: v,
..ForceRegularMode::default()
},
..RegularMode::default()
},
}
}
pub fn reopen_moved_files(self, v: bool) -> Sync<RegularMode<ForceRegularMode>> {
Sync {
bin: self.bin,
global_opts: self.global_opts,
mode: RegularMode {
mode: ForceRegularMode {
reopen_moved_files: v,
..ForceRegularMode::default()
},
..RegularMode::default()
},
}
}
}
impl<Mode: ExclusiveOption, P: ExclusiveOption> Sync<RegularMode<Mode, P>> {
pub fn get_verify_edge_replication(&self) -> bool {
self.mode.verify_edge_replication
}
pub fn set_verify_edge_replication(&mut self, v: bool) -> &mut Self {
self.mode.verify_edge_replication = v;
self
}
pub fn verify_edge_replication(mut self, v: bool) -> Self {
self.mode.verify_edge_replication = v;
self
}
pub fn get_script_list_mode(&self) -> bool {
self.mode.script_list_mode
}
pub fn set_script_list_mode(&mut self, v: bool) -> &mut Self {
self.mode.script_list_mode = v;
self
}
pub fn script_list_mode(mut self, v: bool) -> Self {
self.mode.script_list_mode = v;
self
}
pub fn get_suppress_keyword_expansion(&self) -> bool {
self.mode.suppress_keyword_expansion
}
pub fn set_suppress_keyword_expansion(&mut self, v: bool) -> &mut Self {
self.mode.suppress_keyword_expansion = v;
self
}
pub fn suppress_keyword_expansion(mut self, v: bool) -> Self {
self.mode.suppress_keyword_expansion = v;
self
}
pub fn get_quiet_mode(&self) -> bool {
self.mode.quiet_mode
}
pub fn set_quiet_mode(&mut self, v: bool) -> &mut Self {
self.mode.quiet_mode = v;
self
}
pub fn quiet_mode(mut self, v: bool) -> Self {
self.mode.quiet_mode = v;
self
}
pub fn get_limit(&self) -> Option<u64> {
self.mode.limit
}
pub fn set_limit(&mut self, v: u64) -> &mut Self {
self.mode.limit = Some(v);
self
}
pub fn limit(mut self, v: u64) -> Self {
self.mode.limit = Some(v);
self
}
pub fn get_parallel(&self) -> Option<&ParallelConfig> {
self.mode.parallel.as_ref()
}
pub fn set_parallel(&mut self, v: ParallelConfig) -> &mut Self {
self.mode.parallel = Some(v);
self
}
pub fn parallel(mut self, v: ParallelConfig) -> Self {
self.mode.parallel = Some(v);
self
}
pub fn get_stream_spec_version(&self) -> Option<StreamSpecVersion> {
self.mode.stream_spec_version
}
pub fn set_stream_spec_version(&mut self, v: StreamSpecVersion) -> &mut Self {
self.mode.stream_spec_version = Some(v);
self
}
pub fn stream_spec_version(mut self, v: StreamSpecVersion) -> Self {
self.mode.stream_spec_version = Some(v);
self
}
pub fn set_sc_max_change_number(&mut self) -> &mut Self {
self.mode.stream_spec_version = Some(StreamSpecVersion::MaxInFilelists);
self
}
pub fn sc_max_change_number(mut self) -> Self {
self.mode.stream_spec_version = Some(StreamSpecVersion::MaxInFilelists);
self
}
pub fn set_sc_current_stream_spec(&mut self) -> &mut Self {
self.mode.stream_spec_version = Some(StreamSpecVersion::Current);
self
}
pub fn sc_current_stream_spec(mut self) -> Self {
self.mode.stream_spec_version = Some(StreamSpecVersion::Current);
self
}
pub fn set_sc_change_number(&mut self, n: u32) -> &mut Self {
self.mode.stream_spec_version = Some(StreamSpecVersion::ChangeNumber(n));
self
}
pub fn sc_change_number(mut self, n: u32) -> Self {
self.mode.stream_spec_version = Some(StreamSpecVersion::ChangeNumber(n));
self
}
}
impl<P: ExclusiveOption> Sync<RegularMode<Unselected, P>> {
pub fn force(self, v: bool) -> Sync<RegularMode<ForceRegularMode, P>> {
Sync {
bin: self.bin,
global_opts: self.global_opts,
mode: RegularMode {
verify_edge_replication: self.mode.verify_edge_replication,
script_list_mode: self.mode.script_list_mode,
suppress_keyword_expansion: self.mode.suppress_keyword_expansion,
quiet_mode: self.mode.quiet_mode,
limit: self.mode.limit,
parallel: self.mode.parallel,
stream_spec_version: self.mode.stream_spec_version,
mode: ForceRegularMode {
force: v,
..ForceRegularMode::default()
},
preview: self.mode.preview,
},
}
}
pub fn metadata_only(self, v: bool) -> Sync<RegularMode<ForceRegularMode, P>> {
Sync {
bin: self.bin,
global_opts: self.global_opts,
mode: RegularMode {
verify_edge_replication: self.mode.verify_edge_replication,
script_list_mode: self.mode.script_list_mode,
suppress_keyword_expansion: self.mode.suppress_keyword_expansion,
quiet_mode: self.mode.quiet_mode,
limit: self.mode.limit,
parallel: self.mode.parallel,
stream_spec_version: self.mode.stream_spec_version,
mode: ForceRegularMode {
metadata_only: v,
..ForceRegularMode::default()
},
preview: self.mode.preview,
},
}
}
pub fn reopen_moved_files(self, v: bool) -> Sync<RegularMode<ForceRegularMode, P>> {
Sync {
bin: self.bin,
global_opts: self.global_opts,
mode: RegularMode {
verify_edge_replication: self.mode.verify_edge_replication,
script_list_mode: self.mode.script_list_mode,
suppress_keyword_expansion: self.mode.suppress_keyword_expansion,
quiet_mode: self.mode.quiet_mode,
limit: self.mode.limit,
parallel: self.mode.parallel,
stream_spec_version: self.mode.stream_spec_version,
mode: ForceRegularMode {
reopen_moved_files: v,
..ForceRegularMode::default()
},
preview: self.mode.preview,
},
}
}
pub fn safe_check(self) -> Sync<RegularMode<SafeCheckMode, P>> {
Sync {
bin: self.bin,
global_opts: self.global_opts,
mode: RegularMode {
verify_edge_replication: self.mode.verify_edge_replication,
script_list_mode: self.mode.script_list_mode,
suppress_keyword_expansion: self.mode.suppress_keyword_expansion,
quiet_mode: self.mode.quiet_mode,
limit: self.mode.limit,
parallel: self.mode.parallel,
stream_spec_version: self.mode.stream_spec_version,
mode: SafeCheckMode,
preview: self.mode.preview,
},
}
}
pub fn populate(self) -> Sync<RegularMode<PopulateMode, P>> {
Sync {
bin: self.bin,
global_opts: self.global_opts,
mode: RegularMode {
verify_edge_replication: self.mode.verify_edge_replication,
script_list_mode: self.mode.script_list_mode,
suppress_keyword_expansion: self.mode.suppress_keyword_expansion,
quiet_mode: self.mode.quiet_mode,
limit: self.mode.limit,
parallel: self.mode.parallel,
stream_spec_version: self.mode.stream_spec_version,
mode: PopulateMode,
preview: self.mode.preview,
},
}
}
}
impl<Mode: ExclusiveOption> Sync<RegularMode<Mode, Unselected>> {
pub fn preview_result(self) -> Sync<RegularMode<Mode, PreviewResult>> {
Sync {
bin: self.bin,
global_opts: self.global_opts,
mode: RegularMode {
verify_edge_replication: self.mode.verify_edge_replication,
script_list_mode: self.mode.script_list_mode,
suppress_keyword_expansion: self.mode.suppress_keyword_expansion,
quiet_mode: self.mode.quiet_mode,
limit: self.mode.limit,
parallel: self.mode.parallel,
stream_spec_version: self.mode.stream_spec_version,
mode: self.mode.mode,
preview: PreviewResult,
},
}
}
pub fn preview_network_traffic(self) -> Sync<RegularMode<Mode, PreviewNetworkTraffic>> {
Sync {
bin: self.bin,
global_opts: self.global_opts,
mode: RegularMode {
verify_edge_replication: self.mode.verify_edge_replication,
script_list_mode: self.mode.script_list_mode,
suppress_keyword_expansion: self.mode.suppress_keyword_expansion,
quiet_mode: self.mode.quiet_mode,
limit: self.mode.limit,
parallel: self.mode.parallel,
stream_spec_version: self.mode.stream_spec_version,
mode: self.mode.mode,
preview: PreviewNetworkTraffic,
},
}
}
}
impl<P: ExclusiveOption> Sync<RegularMode<ForceRegularMode, P>> {
pub fn get_force(&self) -> bool {
self.mode.mode.force
}
pub fn set_force(&mut self, v: bool) -> &mut Self {
self.mode.mode.force = v;
self
}
pub fn force(mut self, v: bool) -> Self {
self.mode.mode.force = v;
self
}
pub fn get_metadata_only(&self) -> bool {
self.mode.mode.metadata_only
}
pub fn set_metadata_only(&mut self, v: bool) -> &mut Self {
self.mode.mode.metadata_only = v;
self
}
pub fn metadata_only(mut self, v: bool) -> Self {
self.mode.mode.metadata_only = v;
self
}
pub fn get_reopen_moved_files(&self) -> bool {
self.mode.mode.reopen_moved_files
}
pub fn set_reopen_moved_files(&mut self, v: bool) -> &mut Self {
self.mode.mode.reopen_moved_files = v;
self
}
pub fn reopen_moved_files(mut self, v: bool) -> Self {
self.mode.mode.reopen_moved_files = v;
self
}
}
impl Sync<SyncTimeMode> {
pub fn get_sync_time(&self) -> &str {
&self.mode.sync_time
}
pub fn set_sync_time(&mut self, v: impl Into<String>) -> &mut Self {
self.mode.sync_time = v.into();
self
}
pub fn sync_time(mut self, v: impl Into<String>) -> Self {
self.mode.sync_time = v.into();
self
}
}
impl<M: ExclusiveOption> ParameterizedSpawn for Sync<M> {
type Input<'a> = &'a [&'a OsStr];
type Output<'a> = Child;
type Error = std::io::Error;
fn spawn_with<'a>(&mut self, files: Self::Input<'a>) -> Result<Self::Output<'a>, Self::Error> {
self.setup_command(&self.bin)
.args(files)
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()
}
}
impl<M: ExclusiveOption> Sync<M> {
pub fn get_global_opts(&self) -> &GlobalOpts {
&self.global_opts
}
pub fn set_global_opts(&mut self, v: GlobalOpts) -> &mut Self {
self.global_opts = v;
self
}
pub fn global_opts(mut self, v: GlobalOpts) -> Self {
self.global_opts = v;
self
}
}
impl<M: ExclusiveOption> SubCommand for Sync<M> {
fn name(&self) -> &str {
"sync"
}
fn inject_local_args(&self, command: &mut Command) {
self.mode.inject_args(command);
}
fn global_opts(&self) -> Option<&GlobalOpts> {
Some(&self.global_opts)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::cmd::args_of;
#[test]
fn without_options() {
let sync = Sync::new("p4", GlobalOpts::new());
assert_eq!(args_of(&sync.setup_command("p4")), ["sync"]);
}
#[test]
fn sync_time_mode() {
let sync = Sync::new("p4", GlobalOpts::new()).sync_time("2024/01/01");
assert_eq!(
args_of(&sync.setup_command("p4")),
["sync", "-k", "--sync-time=2024/01/01"]
);
}
#[test]
fn sync_time_mode_epoch() {
let sync = Sync::new("p4", GlobalOpts::new()).sync_time("1700000000");
assert_eq!(
args_of(&sync.setup_command("p4")),
["sync", "-k", "--sync-time=1700000000"]
);
}
#[test]
fn sync_time_set_style() {
let mut sync = Sync::new("p4", GlobalOpts::new()).sync_time("2024/01/01");
sync.set_sync_time("2024/06/01");
assert_eq!(sync.get_sync_time(), "2024/06/01");
assert_eq!(
args_of(&sync.setup_command("p4")),
["sync", "-k", "--sync-time=2024/06/01"]
);
}
#[test]
fn regular_mode_common_options() {
let sync = Sync::new("p4", GlobalOpts::new())
.verify_edge_replication(true)
.script_list_mode(true)
.suppress_keyword_expansion(true)
.quiet_mode(true)
.limit(5);
assert_eq!(
args_of(&sync.setup_command("p4")),
["sync", "-E", "-L", "-K", "-q", "-m", "5"]
);
}
#[test]
fn regular_mode_force_options() {
let sync = Sync::new("p4", GlobalOpts::new())
.force(true)
.metadata_only(true)
.reopen_moved_files(true);
assert_eq!(
args_of(&sync.setup_command("p4")),
["sync", "-f", "-k", "-r"]
);
}
#[test]
fn regular_mode_combined() {
let sync = Sync::new("p4", GlobalOpts::new())
.quiet_mode(true)
.force(true)
.limit(10);
assert_eq!(
args_of(&sync.setup_command("p4")),
["sync", "-q", "-f", "-m", "10"]
);
}
#[test]
fn regular_mode_preview_result() {
let sync = Sync::new("p4", GlobalOpts::new()).preview_result();
assert_eq!(args_of(&sync.setup_command("p4")), ["sync", "-n"]);
}
#[test]
fn regular_mode_preview_network_traffic() {
let sync = Sync::new("p4", GlobalOpts::new()).preview_network_traffic();
assert_eq!(args_of(&sync.setup_command("p4")), ["sync", "-N"]);
}
#[test]
fn regular_mode_preview_with_options() {
let sync = Sync::new("p4", GlobalOpts::new())
.quiet_mode(true)
.preview_result()
.limit(3);
assert_eq!(
args_of(&sync.setup_command("p4")),
["sync", "-q", "-n", "-m", "3"]
);
}
#[test]
fn regular_mode_parallel() {
let sync = Sync::new("p4", GlobalOpts::new()).parallel(ParallelConfig {
threads: 4,
batch_files: Some(8),
batch_size_bytes: None,
min_files: Some(9),
min_size_bytes: None,
});
assert_eq!(
args_of(&sync.setup_command("p4")),
["sync", "--parallel=threads=4,batch=8,min=9"]
);
}
#[test]
fn regular_mode_stream_spec_auto() {
let sync = Sync::new("p4", GlobalOpts::new())
.stream_spec_version(StreamSpecVersion::MaxInFilelists);
assert_eq!(
args_of(&sync.setup_command("p4")),
["sync", "--use-stream-change"]
);
}
#[test]
fn regular_mode_stream_spec_current() {
let sync =
Sync::new("p4", GlobalOpts::new()).stream_spec_version(StreamSpecVersion::Current);
assert_eq!(
args_of(&sync.setup_command("p4")),
["sync", "--use-stream-change=0"]
);
}
#[test]
fn regular_mode_stream_spec_specific() {
let sync = Sync::new("p4", GlobalOpts::new())
.stream_spec_version(StreamSpecVersion::ChangeNumber(123));
assert_eq!(
args_of(&sync.setup_command("p4")),
["sync", "--use-stream-change=123"]
);
}
#[test]
fn safe_check_mode() {
let sync = Sync::new("p4", GlobalOpts::new()).enable_safe_check();
assert_eq!(args_of(&sync.setup_command("p4")), ["sync", "-s"]);
}
#[test]
fn safe_check_mode_with_options() {
let sync = Sync::new("p4", GlobalOpts::new())
.enable_safe_check()
.quiet_mode(true)
.limit(5);
assert_eq!(
args_of(&sync.setup_command("p4")),
["sync", "-q", "-s", "-m", "5"]
);
}
#[test]
fn populate_mode() {
let sync = Sync::new("p4", GlobalOpts::new()).populate_client_workspace();
assert_eq!(args_of(&sync.setup_command("p4")), ["sync", "-p"]);
}
#[test]
fn populate_mode_with_options() {
let sync = Sync::new("p4", GlobalOpts::new())
.populate_client_workspace()
.quiet_mode(true)
.limit(5);
assert_eq!(
args_of(&sync.setup_command("p4")),
["sync", "-q", "-p", "-m", "5"]
);
}
#[test]
fn transition_to_safe_check_from_regular() {
let sync = Sync::new("p4", GlobalOpts::new())
.quiet_mode(true)
.limit(5)
.safe_check();
assert_eq!(
args_of(&sync.setup_command("p4")),
["sync", "-q", "-s", "-m", "5"]
);
}
#[test]
fn transition_to_populate_from_regular() {
let sync = Sync::new("p4", GlobalOpts::new())
.quiet_mode(true)
.limit(5)
.populate();
assert_eq!(
args_of(&sync.setup_command("p4")),
["sync", "-q", "-p", "-m", "5"]
);
}
#[test]
fn transition_preserves_preview() {
let sync = Sync::new("p4", GlobalOpts::new())
.preview_result()
.quiet_mode(true)
.safe_check();
assert_eq!(
args_of(&sync.setup_command("p4")),
["sync", "-q", "-s", "-n"]
);
}
#[test]
fn force_mode_blocks_safe_check() {
let sync = Sync::new("p4", GlobalOpts::new())
.force(true)
.quiet_mode(true);
assert_eq!(args_of(&sync.setup_command("p4")), ["sync", "-q", "-f"]);
}
#[test]
fn all_regular_options_order() {
let sync = Sync::new("p4", GlobalOpts::new())
.verify_edge_replication(true)
.script_list_mode(true)
.suppress_keyword_expansion(true)
.quiet_mode(true)
.force(true)
.metadata_only(true)
.reopen_moved_files(true)
.limit(5)
.parallel(ParallelConfig {
threads: 2,
batch_files: None,
batch_size_bytes: None,
min_files: None,
min_size_bytes: None,
})
.stream_spec_version(StreamSpecVersion::Current);
assert_eq!(
args_of(&sync.setup_command("p4")),
[
"sync",
"-E",
"-L",
"-K",
"-q",
"-f",
"-k",
"-r",
"-m",
"5",
"--parallel=threads=2",
"--use-stream-change=0",
]
);
}
}