1use std::{
2 ffi::OsStr,
3 path::{Path, PathBuf},
4 process::{Child, Command, Stdio},
5};
6
7use super::{ExclusiveOption, SubCommand, Unselected};
8
9use crate::global::GlobalOpts;
10use crate::spawn::ParameterizedSpawn;
11
12pub mod delete;
13pub mod inout;
14pub mod userorvis;
15
16pub use delete::{DeleteMode, LocalDeleteMode, TransferDeleteMode};
17#[cfg(not(feature = "lt2015_2"))]
18pub use delete::{RemoteDeleteMode, TransferRemoteDeleteMode};
19pub use userorvis::{TransferUVMode, UserOrVisibilityMode};
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq)]
59pub enum Visibility {
60 Public,
62
63 Restricted,
66}
67
68impl Visibility {
69 pub fn as_str(&self) -> &'static str {
71 match self {
72 Visibility::Public => "public",
73 Visibility::Restricted => "restricted",
74 }
75 }
76}
77
78#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
84pub struct RegularOperationMode;
85
86#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
88pub struct StdoutMode;
89
90#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
92pub struct StdinMode;
93
94#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
101pub struct ForceOperationMode;
102
103#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
106pub struct UpdateOperationMode;
107
108#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
111pub struct OnlyForceOperationMode;
112
113#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
116pub struct OnlyUpdateOperationMode;
117
118#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
125pub struct OriginalChangeListMode;
126
127#[cfg(not(feature = "lt2022_1"))]
130#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
131pub struct IdentityChangeListMode;
132
133#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
136pub struct OnlyOriginalChangeListMode;
137
138#[cfg(not(feature = "lt2015_2"))]
141#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
142pub struct OnlyIdentityChangeListMode;
143
144#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
154pub struct ArbitraryJobStatus;
155
156impl ExclusiveOption for ForceOperationMode {
161 fn inject_args(&self, command: &mut Command) {
162 command.arg("-f");
163 }
164}
165
166impl ExclusiveOption for UpdateOperationMode {
167 fn inject_args(&self, command: &mut Command) {
168 command.arg("-u");
169 }
170}
171
172impl ExclusiveOption for OnlyForceOperationMode {
173 fn inject_args(&self, command: &mut Command) {
174 command.arg("-f");
175 }
176}
177
178impl ExclusiveOption for OnlyUpdateOperationMode {
179 fn inject_args(&self, command: &mut Command) {
180 command.arg("-u");
181 }
182}
183
184impl ExclusiveOption for OriginalChangeListMode {
185 fn inject_args(&self, command: &mut Command) {
186 command.arg("-O");
187 }
188}
189
190#[cfg(not(feature = "lt2022_1"))]
191impl ExclusiveOption for IdentityChangeListMode {
192 fn inject_args(&self, command: &mut Command) {
193 command.arg("-I");
194 }
195}
196
197impl ExclusiveOption for OnlyOriginalChangeListMode {
198 fn inject_args(&self, command: &mut Command) {
199 command.arg("-O");
200 }
201}
202
203#[cfg(not(feature = "lt2015_2"))]
204impl ExclusiveOption for OnlyIdentityChangeListMode {
205 fn inject_args(&self, command: &mut Command) {
206 command.arg("-I");
207 }
208}
209
210impl ExclusiveOption for ArbitraryJobStatus {
211 fn inject_args(&self, command: &mut Command) {
212 command.arg("-s");
213 }
214}
215
216impl ExclusiveOption for RegularOperationMode {}
217
218impl ExclusiveOption for StdoutMode {
219 fn inject_args(&self, command: &mut Command) {
220 command.arg("-o");
221 }
222}
223
224impl ExclusiveOption for StdinMode {
225 fn inject_args(&self, command: &mut Command) {
226 command.arg("-i");
227 }
228}
229
230#[doc(hidden)]
239pub trait TakesChangeList {}
240
241impl TakesChangeList for RegularOperationMode {}
242impl TakesChangeList for StdoutMode {}
243
244#[cfg_attr(
276 not(feature = "lt2022_1"),
277 doc = " / [`IdentityChangeListMode`], or their"
278)]
279#[cfg_attr(feature = "lt2022_1", doc = " , or its")]
280#[cfg_attr(not(feature = "lt2022_1"), doc = "[`Self::identity`]/")]
288#[derive(Debug, Clone, Default)]
293pub struct Change<M = Unselected, P = Unselected, C = Unselected, S = Unselected> {
294 bin: PathBuf,
295
296 global_opts: GlobalOpts,
297
298 mode: M,
299
300 permission_mode: P,
301
302 changelist_mode: C,
303
304 job_status_mode: S,
305}
306
307impl Change<Unselected, Unselected, Unselected, Unselected> {
312 pub fn new(bin: impl Into<PathBuf>, global_opts: GlobalOpts) -> Self {
316 Self {
317 bin: bin.into(),
318 global_opts,
319 mode: Unselected,
320 permission_mode: Unselected,
321 changelist_mode: Unselected,
322 job_status_mode: Unselected,
323 }
324 }
325
326 pub fn delete(self) -> Change<DeleteMode<LocalDeleteMode>, Unselected, Unselected, Unselected> {
328 self.with_mode(DeleteMode {
329 loc: LocalDeleteMode,
330 })
331 }
332
333 #[cfg(not(feature = "lt2015_2"))]
341 pub fn server_id(
342 self,
343 server_id: impl Into<String>,
344 ) -> Change<DeleteMode<RemoteDeleteMode>, Unselected, Unselected, Unselected> {
345 self.with_mode(DeleteMode {
346 loc: RemoteDeleteMode {
347 server_id: server_id.into(),
348 },
349 })
350 }
351
352 pub fn stdout(self) -> Change<StdoutMode, Unselected, Unselected, Unselected> {
354 self.with_mode(StdoutMode)
355 }
356
357 pub fn stdin(self) -> Change<StdinMode, Unselected, Unselected, Unselected> {
359 self.with_mode(StdinMode)
360 }
361
362 pub fn visibility(
368 self,
369 visibility: Visibility,
370 ) -> Change<UserOrVisibilityMode, Unselected, Unselected, Unselected> {
371 self.with_mode(UserOrVisibilityMode {
372 visibility: Some(visibility),
373 user: None,
374 })
375 }
376
377 pub fn user(
383 self,
384 user: impl Into<String>,
385 ) -> Change<UserOrVisibilityMode, Unselected, Unselected, Unselected> {
386 self.with_mode(UserOrVisibilityMode {
387 user: Some(user.into()),
388 visibility: None,
389 })
390 }
391
392 pub fn arbitrary_job_status(
394 self,
395 ) -> Change<RegularOperationMode, Unselected, Unselected, ArbitraryJobStatus> {
396 Change {
397 bin: self.bin,
398 global_opts: self.global_opts,
399 mode: RegularOperationMode,
400 permission_mode: Unselected,
401 changelist_mode: Unselected,
402 job_status_mode: ArbitraryJobStatus,
403 }
404 }
405
406 pub fn force(self) -> Change<RegularOperationMode, ForceOperationMode, Unselected, Unselected> {
408 Change {
409 bin: self.bin,
410 global_opts: self.global_opts,
411 mode: RegularOperationMode,
412 permission_mode: ForceOperationMode,
413 changelist_mode: Unselected,
414 job_status_mode: Unselected,
415 }
416 }
417
418 pub fn update(
420 self,
421 ) -> Change<RegularOperationMode, UpdateOperationMode, Unselected, Unselected> {
422 Change {
423 bin: self.bin,
424 global_opts: self.global_opts,
425 mode: RegularOperationMode,
426 permission_mode: UpdateOperationMode,
427 changelist_mode: Unselected,
428 job_status_mode: Unselected,
429 }
430 }
431
432 pub fn original(
434 self,
435 ) -> Change<RegularOperationMode, Unselected, OriginalChangeListMode, Unselected> {
436 Change {
437 bin: self.bin,
438 global_opts: self.global_opts,
439 mode: RegularOperationMode,
440 permission_mode: Unselected,
441 changelist_mode: OriginalChangeListMode,
442 job_status_mode: Unselected,
443 }
444 }
445
446 #[cfg(not(feature = "lt2022_1"))]
448 pub fn identity(
449 self,
450 ) -> Change<RegularOperationMode, Unselected, IdentityChangeListMode, Unselected> {
451 Change {
452 bin: self.bin,
453 global_opts: self.global_opts,
454 mode: RegularOperationMode,
455 permission_mode: Unselected,
456 changelist_mode: IdentityChangeListMode,
457 job_status_mode: Unselected,
458 }
459 }
460}
461
462impl<M, P, C, S> Change<M, P, C, S> {
463 fn with_mode<OTHERMODE>(self, mode: OTHERMODE) -> Change<OTHERMODE, P, C, S> {
466 Change {
467 bin: self.bin,
468 global_opts: self.global_opts,
469 mode,
470 permission_mode: self.permission_mode,
471 changelist_mode: self.changelist_mode,
472 job_status_mode: self.job_status_mode,
473 }
474 }
475}
476
477impl<M, P, C, S> Change<M, P, C, S> {
482 pub fn get_bin(&self) -> &Path {
484 &self.bin
485 }
486
487 pub fn set_bin(&mut self, bin: impl Into<PathBuf>) -> &mut Self {
489 self.bin = bin.into();
490 self
491 }
492
493 pub fn bin(mut self, bin: impl Into<PathBuf>) -> Self {
495 self.set_bin(bin);
496 self
497 }
498
499 pub fn get_global_opts(&self) -> &GlobalOpts {
501 &self.global_opts
502 }
503
504 pub fn set_global_opts(&mut self, v: GlobalOpts) -> &mut Self {
506 self.global_opts = v;
507 self
508 }
509
510 pub fn global_opts(mut self, v: GlobalOpts) -> Self {
512 self.global_opts = v;
513 self
514 }
515}
516
517#[doc(hidden)]
522pub trait TransferStdoutMode {}
523
524impl TransferStdoutMode for Unselected {}
525impl TransferStdoutMode for ForceOperationMode {}
526
527impl<P, C, S> Change<RegularOperationMode, P, C, S> {
532 pub fn delete(self) -> Change<DeleteMode<LocalDeleteMode>, P, C, S>
538 where
539 P: TransferDeleteMode,
540 C: TransferDeleteMode,
541 {
542 Change {
543 bin: self.bin,
544 global_opts: self.global_opts,
545 mode: DeleteMode {
546 loc: LocalDeleteMode,
547 },
548 permission_mode: self.permission_mode,
549 changelist_mode: self.changelist_mode,
550 job_status_mode: self.job_status_mode,
551 }
552 }
553
554 pub fn stdout(self) -> Change<StdoutMode, P, C, S>
560 where
561 P: TransferStdoutMode,
562 {
563 Change {
564 bin: self.bin,
565 global_opts: self.global_opts,
566 mode: StdoutMode,
567 permission_mode: self.permission_mode,
568 changelist_mode: self.changelist_mode,
569 job_status_mode: self.job_status_mode,
570 }
571 }
572}
573
574#[cfg(not(feature = "lt2015_2"))]
577impl<P: TransferRemoteDeleteMode> Change<RegularOperationMode, P, Unselected, Unselected> {
578 pub fn server_id(
587 self,
588 server_id: impl Into<String>,
589 ) -> Change<DeleteMode<RemoteDeleteMode>, Unselected, Unselected, Unselected> {
590 Change {
591 bin: self.bin,
592 global_opts: self.global_opts,
593 mode: DeleteMode {
594 loc: RemoteDeleteMode {
595 server_id: server_id.into(),
596 },
597 },
598 permission_mode: Unselected,
599 changelist_mode: Unselected,
600 job_status_mode: Unselected,
601 }
602 }
603}
604
605impl<O, S> Change<RegularOperationMode, O, Unselected, S> {
608 pub fn stdin(self) -> Change<StdinMode, O, Unselected, S> {
614 Change {
615 bin: self.bin,
616 global_opts: self.global_opts,
617 mode: StdinMode,
618 permission_mode: self.permission_mode,
619 changelist_mode: Unselected,
620 job_status_mode: self.job_status_mode,
621 }
622 }
623}
624
625impl<O, C> Change<RegularOperationMode, O, C, Unselected> {
627 pub fn arbitrary_job_status(self) -> Change<RegularOperationMode, O, C, ArbitraryJobStatus> {
630 Change {
631 bin: self.bin,
632 global_opts: self.global_opts,
633 mode: self.mode,
634 permission_mode: self.permission_mode,
635 changelist_mode: self.changelist_mode,
636 job_status_mode: ArbitraryJobStatus,
637 }
638 }
639}
640
641impl<C, S> Change<RegularOperationMode, Unselected, C, S> {
643 pub fn force(self) -> Change<RegularOperationMode, ForceOperationMode, C, S> {
647 Change {
648 bin: self.bin,
649 global_opts: self.global_opts,
650 mode: self.mode,
651 permission_mode: ForceOperationMode,
652 changelist_mode: self.changelist_mode,
653 job_status_mode: self.job_status_mode,
654 }
655 }
656
657 pub fn update(self) -> Change<RegularOperationMode, UpdateOperationMode, C, S> {
661 Change {
662 bin: self.bin,
663 global_opts: self.global_opts,
664 mode: self.mode,
665 permission_mode: UpdateOperationMode,
666 changelist_mode: self.changelist_mode,
667 job_status_mode: self.job_status_mode,
668 }
669 }
670}
671
672impl<O, S> Change<RegularOperationMode, O, Unselected, S> {
674 pub fn original(self) -> Change<RegularOperationMode, O, OriginalChangeListMode, S> {
679 Change {
680 bin: self.bin,
681 global_opts: self.global_opts,
682 mode: self.mode,
683 permission_mode: self.permission_mode,
684 changelist_mode: OriginalChangeListMode,
685 job_status_mode: self.job_status_mode,
686 }
687 }
688
689 #[cfg(not(feature = "lt2022_1"))]
693 pub fn identity(self) -> Change<RegularOperationMode, O, IdentityChangeListMode, S> {
694 Change {
695 bin: self.bin,
696 global_opts: self.global_opts,
697 mode: self.mode,
698 permission_mode: self.permission_mode,
699 changelist_mode: IdentityChangeListMode,
700 job_status_mode: self.job_status_mode,
701 }
702 }
703}
704
705impl<O, C> Change<RegularOperationMode, O, C, Unselected> {
709 #[allow(clippy::type_complexity)]
719 pub fn visibility(
720 self,
721 visibility: Visibility,
722 ) -> Change<
723 UserOrVisibilityMode,
724 <(O, C) as TransferUVMode>::P,
725 <(O, C) as TransferUVMode>::C,
726 Unselected,
727 >
728 where
729 (O, C): TransferUVMode,
730 {
731 let (operation, change_ref) = (self.permission_mode, self.changelist_mode).transfer();
732 Change {
733 bin: self.bin,
734 global_opts: self.global_opts,
735 mode: UserOrVisibilityMode {
736 visibility: Some(visibility),
737 user: None,
738 },
739 permission_mode: operation,
740 changelist_mode: change_ref,
741 job_status_mode: Unselected,
742 }
743 }
744
745 #[allow(clippy::type_complexity)]
755 pub fn user(
756 self,
757 user: impl Into<String>,
758 ) -> Change<
759 UserOrVisibilityMode,
760 <(O, C) as TransferUVMode>::P,
761 <(O, C) as TransferUVMode>::C,
762 Unselected,
763 >
764 where
765 (O, C): TransferUVMode,
766 {
767 let (operation, change_ref) = (self.permission_mode, self.changelist_mode).transfer();
768 Change {
769 bin: self.bin,
770 global_opts: self.global_opts,
771 mode: UserOrVisibilityMode {
772 user: Some(user.into()),
773 visibility: None,
774 },
775 permission_mode: operation,
776 changelist_mode: change_ref,
777 job_status_mode: Unselected,
778 }
779 }
780}
781
782impl<M, O, C, S> SubCommand for Change<M, O, C, S>
787where
788 M: ExclusiveOption,
789 O: ExclusiveOption,
790 C: ExclusiveOption,
791 S: ExclusiveOption,
792{
793 fn name(&self) -> &str {
794 "change"
795 }
796
797 fn inject_local_args(&self, command: &mut Command) {
798 self.mode.inject_args(command);
799 self.job_status_mode.inject_args(command);
800 self.permission_mode.inject_args(command);
801 self.changelist_mode.inject_args(command);
802 }
803
804 fn global_opts(&self) -> Option<&GlobalOpts> {
805 Some(&self.global_opts)
806 }
807}
808
809impl<M, O, C, S, I> ParameterizedSpawn<(I,)> for Change<M, O, C, S>
814where
815 M: ExclusiveOption + TakesChangeList,
816 O: ExclusiveOption,
817 C: ExclusiveOption,
818 S: ExclusiveOption,
819 I: AsRef<OsStr>,
820{
821 type Output = Child;
822 type Error = std::io::Error;
823
824 fn spawn_with(&mut self, (changelist,): (I,)) -> Result<Self::Output, Self::Error> {
832 self.setup_command(&self.bin)
833 .arg(changelist)
834 .stdout(Stdio::piped())
835 .stderr(Stdio::piped())
836 .spawn()
837 }
838}
839
840impl<O, C, S> ParameterizedSpawn<()> for Change<RegularOperationMode, O, C, S>
843where
844 O: ExclusiveOption,
845 C: ExclusiveOption,
846 S: ExclusiveOption,
847{
848 type Output = Child;
849 type Error = std::io::Error;
850
851 fn spawn_with(&mut self, _: ()) -> Result<Self::Output, Self::Error> {
854 self.setup_command(&self.bin)
855 .stdout(Stdio::piped())
856 .stderr(Stdio::piped())
857 .spawn()
858 }
859}
860
861impl<O, C, S> ParameterizedSpawn<()> for Change<StdoutMode, O, C, S>
864where
865 O: ExclusiveOption,
866 C: ExclusiveOption,
867 S: ExclusiveOption,
868{
869 type Output = Child;
870 type Error = std::io::Error;
871
872 fn spawn_with(&mut self, _: ()) -> Result<Self::Output, Self::Error> {
875 self.setup_command(&self.bin)
876 .stdout(Stdio::piped())
877 .stderr(Stdio::piped())
878 .spawn()
879 }
880}
881
882impl<O, S> ParameterizedSpawn<()> for Change<StdinMode, O, Unselected, S>
883where
884 O: ExclusiveOption,
885 S: ExclusiveOption,
886{
887 type Output = Child;
888 type Error = std::io::Error;
889
890 fn spawn_with(&mut self, _: ()) -> Result<Self::Output, Self::Error> {
894 self.setup_command(&self.bin)
895 .stdin(Stdio::piped())
896 .stdout(Stdio::piped())
897 .stderr(Stdio::piped())
898 .spawn()
899 }
900}
901
902impl<O, S> ParameterizedSpawn<(Stdio,)> for Change<StdinMode, O, Unselected, S>
903where
904 O: ExclusiveOption,
905 S: ExclusiveOption,
906{
907 type Output = Child;
908 type Error = std::io::Error;
909
910 fn spawn_with(&mut self, (stdio,): (Stdio,)) -> Result<Self::Output, Self::Error> {
919 self.setup_command(&self.bin)
920 .stdin(stdio)
921 .stdout(Stdio::piped())
922 .stderr(Stdio::piped())
923 .spawn()
924 }
925}
926
927#[cfg(test)]
928mod tests {
929 use super::*;
930 use crate::cmd::args_of;
931
932 #[test]
933 fn bin_accessors_update_executable_path() {
934 let mut command = Change::new("p4", GlobalOpts::new());
935 assert_eq!(command.get_bin(), Path::new("p4"));
936
937 command.set_bin("/usr/local/bin/p4");
938 assert_eq!(command.get_bin(), Path::new("/usr/local/bin/p4"));
939
940 let command = command.bin("p4.exe");
941 assert_eq!(command.get_bin(), Path::new("p4.exe"));
942 }
943
944 #[test]
963 fn regular_form_injects_all_options() {
964 let change = Change::new("p4", GlobalOpts::new())
965 .arbitrary_job_status()
966 .force()
967 .original();
968
969 assert_eq!(
970 args_of(&change.setup_command("p4")),
971 ["change", "-s", "-f", "-O"]
972 );
973 }
974
975 #[test]
976 #[cfg(not(feature = "lt2022_1"))]
977 fn regular_form_update_and_identity() {
978 let change = Change::new("p4", GlobalOpts::new())
979 .arbitrary_job_status()
980 .update()
981 .identity();
982
983 assert_eq!(
984 args_of(&change.setup_command("p4")),
985 ["change", "-s", "-u", "-I"]
986 );
987 }
988
989 #[test]
990 fn entry_points_select_form_flags() {
991 let delete = Change::new("p4", GlobalOpts::new()).delete();
992 assert_eq!(args_of(&delete.setup_command("p4")), ["change", "-d"]);
993
994 let stdout = Change::new("p4", GlobalOpts::new()).stdout();
995 assert_eq!(args_of(&stdout.setup_command("p4")), ["change", "-o"]);
996
997 let stdin = Change::new("p4", GlobalOpts::new()).stdin();
998 assert_eq!(args_of(&stdin.setup_command("p4")), ["change", "-i"]);
999
1000 #[cfg(not(feature = "lt2015_2"))]
1001 {
1002 let remote = Change::new("p4", GlobalOpts::new()).server_id("remote-1");
1003 #[cfg(feature = "lt2022_1")]
1004 assert_eq!(
1005 args_of(&remote.setup_command("p4")),
1006 ["change", "-d", "-f", "--server=remote-1"]
1007 );
1008 #[cfg(not(feature = "lt2022_1"))]
1009 assert_eq!(
1010 args_of(&remote.setup_command("p4")),
1011 ["change", "-d", "-f", "--serverid=remote-1"]
1012 );
1013 }
1014 }
1015
1016 #[test]
1017 fn arbitrary_job_status_carries_into_delete_stdout_stdin() {
1018 let delete = Change::new("p4", GlobalOpts::new())
1020 .arbitrary_job_status()
1021 .delete();
1022 assert_eq!(args_of(&delete.setup_command("p4")), ["change", "-d", "-s"]);
1023
1024 let stdout = Change::new("p4", GlobalOpts::new())
1025 .arbitrary_job_status()
1026 .stdout();
1027 assert_eq!(args_of(&stdout.setup_command("p4")), ["change", "-o", "-s"]);
1028
1029 let stdin = Change::new("p4", GlobalOpts::new())
1030 .arbitrary_job_status()
1031 .stdin();
1032 assert_eq!(args_of(&stdin.setup_command("p4")), ["change", "-i", "-s"]);
1033 }
1034
1035 #[test]
1036 fn regular_to_delete_preserves_compatible_options() {
1037 let change = Change::new("p4", GlobalOpts::new())
1038 .arbitrary_job_status()
1039 .force()
1040 .original()
1041 .delete();
1042
1043 assert_eq!(
1044 args_of(&change.setup_command("p4")),
1045 ["change", "-d", "-s", "-f", "-O"]
1046 );
1047 }
1048
1049 #[test]
1050 #[cfg(not(feature = "lt2022_1"))]
1051 fn regular_to_stdout_preserves_identity() {
1052 let change = Change::new("p4", GlobalOpts::new())
1053 .arbitrary_job_status()
1054 .force()
1055 .identity()
1056 .stdout();
1057
1058 assert_eq!(
1059 args_of(&change.setup_command("p4")),
1060 ["change", "-o", "-s", "-f", "-I"]
1061 );
1062 }
1063
1064 #[test]
1065 fn regular_to_stdin_preserves_update() {
1066 let change = Change::new("p4", GlobalOpts::new())
1067 .arbitrary_job_status()
1068 .update()
1069 .stdin();
1070
1071 assert_eq!(
1072 args_of(&change.setup_command("p4")),
1073 ["change", "-i", "-s", "-u"]
1074 );
1075 }
1076
1077 #[test]
1078 #[cfg(not(feature = "lt2015_2"))]
1079 fn regular_to_remote_delete_folds_force_into_builtin() {
1080 let change = Change::new("p4", GlobalOpts::new())
1083 .force()
1084 .server_id("remote-1");
1085
1086 #[cfg(feature = "lt2022_1")]
1087 assert_eq!(
1088 args_of(&change.setup_command("p4")),
1089 ["change", "-d", "-f", "--server=remote-1"]
1090 );
1091 #[cfg(not(feature = "lt2022_1"))]
1092 assert_eq!(
1093 args_of(&change.setup_command("p4")),
1094 ["change", "-d", "-f", "--serverid=remote-1"]
1095 );
1096 }
1097
1098 #[test]
1099 fn regular_visibility_maps_to_only_states() {
1100 let forced = Change::new("p4", GlobalOpts::new())
1102 .force()
1103 .visibility(Visibility::Restricted);
1104 assert_eq!(
1105 args_of(&forced.setup_command("p4")),
1106 ["change", "-t", "restricted", "-f"]
1107 );
1108
1109 #[cfg(not(feature = "lt2022_1"))]
1111 {
1112 let identity = Change::new("p4", GlobalOpts::new())
1113 .identity()
1114 .visibility(Visibility::Public);
1115 assert_eq!(
1116 args_of(&identity.setup_command("p4")),
1117 ["change", "-t", "public", "-I"]
1118 );
1119 }
1120
1121 let plain = Change::new("p4", GlobalOpts::new())
1123 .visibility(Visibility::Restricted)
1124 .user("maria");
1125 assert_eq!(
1126 args_of(&plain.setup_command("p4")),
1127 ["change", "-t", "restricted", "-U", "maria"]
1128 );
1129 }
1130
1131 #[test]
1132 fn regular_user_maps_single_option() {
1133 let change = Change::new("p4", GlobalOpts::new())
1135 .force()
1136 .user("maria")
1137 .visibility(Visibility::Public);
1138
1139 assert_eq!(
1140 args_of(&change.setup_command("p4")),
1141 ["change", "-t", "public", "-U", "maria", "-f"]
1142 );
1143
1144 let original = Change::new("p4", GlobalOpts::new())
1146 .original()
1147 .user("maria");
1148
1149 assert_eq!(
1150 args_of(&original.setup_command("p4")),
1151 ["change", "-U", "maria", "-O"]
1152 );
1153 }
1154
1155 #[test]
1156 fn user_or_visibility_form_sets_values_and_selects_one_option() {
1157 let both = Change::new("p4", GlobalOpts::new())
1159 .user("maria")
1160 .visibility(Visibility::Public);
1161 assert_eq!(
1162 args_of(&both.setup_command("p4")),
1163 ["change", "-t", "public", "-U", "maria"]
1164 );
1165
1166 let forced = Change::new("p4", GlobalOpts::new())
1168 .visibility(Visibility::Restricted)
1169 .force();
1170 assert_eq!(
1171 args_of(&forced.setup_command("p4")),
1172 ["change", "-t", "restricted", "-f"]
1173 );
1174
1175 let updated = Change::new("p4", GlobalOpts::new()).user("maria").update();
1176 assert_eq!(
1177 args_of(&updated.setup_command("p4")),
1178 ["change", "-U", "maria", "-u"]
1179 );
1180
1181 let original = Change::new("p4", GlobalOpts::new())
1182 .user("maria")
1183 .original();
1184 assert_eq!(
1185 args_of(&original.setup_command("p4")),
1186 ["change", "-U", "maria", "-O"]
1187 );
1188
1189 #[cfg(not(feature = "lt2015_2"))]
1190 {
1191 let identity = Change::new("p4", GlobalOpts::new())
1192 .visibility(Visibility::Public)
1193 .identity();
1194 assert_eq!(
1195 args_of(&identity.setup_command("p4")),
1196 ["change", "-t", "public", "-I"]
1197 );
1198 }
1199 }
1200
1201 #[test]
1202 fn options_can_be_selected_inside_forms() {
1203 let delete = Change::new("p4", GlobalOpts::new())
1204 .delete()
1205 .arbitrary_job_status()
1206 .force()
1207 .original();
1208 assert_eq!(
1209 args_of(&delete.setup_command("p4")),
1210 ["change", "-d", "-s", "-f", "-O"]
1211 );
1212
1213 #[cfg(not(feature = "lt2022_1"))]
1214 {
1215 let stdout = Change::new("p4", GlobalOpts::new())
1216 .stdout()
1217 .arbitrary_job_status()
1218 .identity();
1219 assert_eq!(
1220 args_of(&stdout.setup_command("p4")),
1221 ["change", "-o", "-s", "-I"]
1222 );
1223 }
1224 #[cfg(feature = "lt2022_1")]
1225 {
1226 let stdout = Change::new("p4", GlobalOpts::new())
1227 .stdout()
1228 .arbitrary_job_status()
1229 .original();
1230 assert_eq!(
1231 args_of(&stdout.setup_command("p4")),
1232 ["change", "-o", "-s", "-O"]
1233 );
1234 }
1235
1236 let stdin = Change::new("p4", GlobalOpts::new())
1237 .stdin()
1238 .arbitrary_job_status()
1239 .update();
1240 assert_eq!(
1241 args_of(&stdin.setup_command("p4")),
1242 ["change", "-i", "-s", "-u"]
1243 );
1244 }
1245
1246 #[test]
1247 fn global_opts_are_injected_once() {
1248 let change = Change::new("p4", GlobalOpts::new()).delete();
1249
1250 assert_eq!(args_of(&change.setup_command("p4")), ["change", "-d"]);
1252 }
1253
1254 #[test]
1261 fn spawn_argument_counts_per_form() {
1262 let plain = Change::new("p4", GlobalOpts::new())
1264 .arbitrary_job_status()
1265 .force();
1266 assert_eq!(args_of(&plain.setup_command("p4")), ["change", "-s", "-f"]);
1267 let mut with_cl = plain.setup_command("p4");
1268 with_cl.arg("1234");
1269 assert_eq!(args_of(&with_cl), ["change", "-s", "-f", "1234"]);
1270
1271 let delete = Change::new("p4", GlobalOpts::new())
1273 .delete()
1274 .arbitrary_job_status()
1275 .force()
1276 .original();
1277 let mut delete_cl = delete.setup_command("p4");
1278 delete_cl.arg("1234");
1279 assert_eq!(
1280 args_of(&delete_cl),
1281 ["change", "-d", "-s", "-f", "-O", "1234"]
1282 );
1283
1284 #[cfg(not(feature = "lt2015_2"))]
1286 {
1287 let remote = Change::new("p4", GlobalOpts::new()).server_id("edge-1");
1288 let mut remote_cl = remote.setup_command("p4");
1289 remote_cl.arg("1234");
1290 #[cfg(feature = "lt2022_1")]
1291 assert_eq!(
1292 args_of(&remote_cl),
1293 ["change", "-d", "-f", "--server=edge-1", "1234"]
1294 );
1295 #[cfg(not(feature = "lt2022_1"))]
1296 assert_eq!(
1297 args_of(&remote_cl),
1298 ["change", "-d", "-f", "--serverid=edge-1", "1234"]
1299 );
1300 }
1301
1302 #[cfg(not(feature = "lt2022_1"))]
1304 {
1305 let stdout = Change::new("p4", GlobalOpts::new())
1306 .stdout()
1307 .arbitrary_job_status()
1308 .force()
1309 .identity();
1310 assert_eq!(
1311 args_of(&stdout.setup_command("p4")),
1312 ["change", "-o", "-s", "-f", "-I"]
1313 );
1314 let mut stdout_cl = stdout.setup_command("p4");
1315 stdout_cl.arg("1234");
1316 assert_eq!(
1317 args_of(&stdout_cl),
1318 ["change", "-o", "-s", "-f", "-I", "1234"]
1319 );
1320 }
1321 #[cfg(feature = "lt2022_1")]
1322 {
1323 let stdout = Change::new("p4", GlobalOpts::new())
1324 .stdout()
1325 .arbitrary_job_status()
1326 .force()
1327 .original();
1328 assert_eq!(
1329 args_of(&stdout.setup_command("p4")),
1330 ["change", "-o", "-s", "-f", "-O"]
1331 );
1332 let mut stdout_cl = stdout.setup_command("p4");
1333 stdout_cl.arg("1234");
1334 assert_eq!(
1335 args_of(&stdout_cl),
1336 ["change", "-o", "-s", "-f", "-O", "1234"]
1337 );
1338 }
1339
1340 let stdin = Change::new("p4", GlobalOpts::new())
1342 .stdin()
1343 .arbitrary_job_status()
1344 .update();
1345 assert_eq!(
1346 args_of(&stdin.setup_command("p4")),
1347 ["change", "-i", "-s", "-u"]
1348 );
1349
1350 let uov = Change::new("p4", GlobalOpts::new())
1352 .visibility(Visibility::Restricted)
1353 .user("maria")
1354 .force();
1355 let mut uov_cl = uov.setup_command("p4");
1356 uov_cl.arg("1234");
1357 assert_eq!(
1358 args_of(&uov_cl),
1359 ["change", "-t", "restricted", "-U", "maria", "-f", "1234"]
1360 );
1361 }
1362}