1use std::{
2 ffi::OsStr,
3 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_global_opts(&self) -> &GlobalOpts {
484 &self.global_opts
485 }
486
487 pub fn set_global_opts(&mut self, v: GlobalOpts) -> &mut Self {
489 self.global_opts = v;
490 self
491 }
492
493 pub fn global_opts(mut self, v: GlobalOpts) -> Self {
495 self.global_opts = v;
496 self
497 }
498}
499
500#[doc(hidden)]
505pub trait TransferStdoutMode {}
506
507impl TransferStdoutMode for Unselected {}
508impl TransferStdoutMode for ForceOperationMode {}
509
510impl<P, C, S> Change<RegularOperationMode, P, C, S> {
515 pub fn delete(self) -> Change<DeleteMode<LocalDeleteMode>, P, C, S>
521 where
522 P: TransferDeleteMode,
523 C: TransferDeleteMode,
524 {
525 Change {
526 bin: self.bin,
527 global_opts: self.global_opts,
528 mode: DeleteMode {
529 loc: LocalDeleteMode,
530 },
531 permission_mode: self.permission_mode,
532 changelist_mode: self.changelist_mode,
533 job_status_mode: self.job_status_mode,
534 }
535 }
536
537 pub fn stdout(self) -> Change<StdoutMode, P, C, S>
543 where
544 P: TransferStdoutMode,
545 {
546 Change {
547 bin: self.bin,
548 global_opts: self.global_opts,
549 mode: StdoutMode,
550 permission_mode: self.permission_mode,
551 changelist_mode: self.changelist_mode,
552 job_status_mode: self.job_status_mode,
553 }
554 }
555}
556
557#[cfg(not(feature = "lt2015_2"))]
560impl<P: TransferRemoteDeleteMode> Change<RegularOperationMode, P, Unselected, Unselected> {
561 pub fn server_id(
570 self,
571 server_id: impl Into<String>,
572 ) -> Change<DeleteMode<RemoteDeleteMode>, Unselected, Unselected, Unselected> {
573 Change {
574 bin: self.bin,
575 global_opts: self.global_opts,
576 mode: DeleteMode {
577 loc: RemoteDeleteMode {
578 server_id: server_id.into(),
579 },
580 },
581 permission_mode: Unselected,
582 changelist_mode: Unselected,
583 job_status_mode: Unselected,
584 }
585 }
586}
587
588impl<O, S> Change<RegularOperationMode, O, Unselected, S> {
591 pub fn stdin(self) -> Change<StdinMode, O, Unselected, S> {
597 Change {
598 bin: self.bin,
599 global_opts: self.global_opts,
600 mode: StdinMode,
601 permission_mode: self.permission_mode,
602 changelist_mode: Unselected,
603 job_status_mode: self.job_status_mode,
604 }
605 }
606}
607
608impl<O, C> Change<RegularOperationMode, O, C, Unselected> {
610 pub fn arbitrary_job_status(self) -> Change<RegularOperationMode, O, C, ArbitraryJobStatus> {
613 Change {
614 bin: self.bin,
615 global_opts: self.global_opts,
616 mode: self.mode,
617 permission_mode: self.permission_mode,
618 changelist_mode: self.changelist_mode,
619 job_status_mode: ArbitraryJobStatus,
620 }
621 }
622}
623
624impl<C, S> Change<RegularOperationMode, Unselected, C, S> {
626 pub fn force(self) -> Change<RegularOperationMode, ForceOperationMode, C, S> {
630 Change {
631 bin: self.bin,
632 global_opts: self.global_opts,
633 mode: self.mode,
634 permission_mode: ForceOperationMode,
635 changelist_mode: self.changelist_mode,
636 job_status_mode: self.job_status_mode,
637 }
638 }
639
640 pub fn update(self) -> Change<RegularOperationMode, UpdateOperationMode, C, S> {
644 Change {
645 bin: self.bin,
646 global_opts: self.global_opts,
647 mode: self.mode,
648 permission_mode: UpdateOperationMode,
649 changelist_mode: self.changelist_mode,
650 job_status_mode: self.job_status_mode,
651 }
652 }
653}
654
655impl<O, S> Change<RegularOperationMode, O, Unselected, S> {
657 pub fn original(self) -> Change<RegularOperationMode, O, OriginalChangeListMode, S> {
662 Change {
663 bin: self.bin,
664 global_opts: self.global_opts,
665 mode: self.mode,
666 permission_mode: self.permission_mode,
667 changelist_mode: OriginalChangeListMode,
668 job_status_mode: self.job_status_mode,
669 }
670 }
671
672 #[cfg(not(feature = "lt2022_1"))]
676 pub fn identity(self) -> Change<RegularOperationMode, O, IdentityChangeListMode, S> {
677 Change {
678 bin: self.bin,
679 global_opts: self.global_opts,
680 mode: self.mode,
681 permission_mode: self.permission_mode,
682 changelist_mode: IdentityChangeListMode,
683 job_status_mode: self.job_status_mode,
684 }
685 }
686}
687
688impl<O, C> Change<RegularOperationMode, O, C, Unselected> {
692 #[allow(clippy::type_complexity)]
702 pub fn visibility(
703 self,
704 visibility: Visibility,
705 ) -> Change<
706 UserOrVisibilityMode,
707 <(O, C) as TransferUVMode>::P,
708 <(O, C) as TransferUVMode>::C,
709 Unselected,
710 >
711 where
712 (O, C): TransferUVMode,
713 {
714 let (operation, change_ref) = (self.permission_mode, self.changelist_mode).transfer();
715 Change {
716 bin: self.bin,
717 global_opts: self.global_opts,
718 mode: UserOrVisibilityMode {
719 visibility: Some(visibility),
720 user: None,
721 },
722 permission_mode: operation,
723 changelist_mode: change_ref,
724 job_status_mode: Unselected,
725 }
726 }
727
728 #[allow(clippy::type_complexity)]
738 pub fn user(
739 self,
740 user: impl Into<String>,
741 ) -> Change<
742 UserOrVisibilityMode,
743 <(O, C) as TransferUVMode>::P,
744 <(O, C) as TransferUVMode>::C,
745 Unselected,
746 >
747 where
748 (O, C): TransferUVMode,
749 {
750 let (operation, change_ref) = (self.permission_mode, self.changelist_mode).transfer();
751 Change {
752 bin: self.bin,
753 global_opts: self.global_opts,
754 mode: UserOrVisibilityMode {
755 user: Some(user.into()),
756 visibility: None,
757 },
758 permission_mode: operation,
759 changelist_mode: change_ref,
760 job_status_mode: Unselected,
761 }
762 }
763}
764
765impl<F, O, C, S> SubCommand for Change<F, O, C, S>
770where
771 F: ExclusiveOption,
772 O: ExclusiveOption,
773 C: ExclusiveOption,
774 S: ExclusiveOption,
775{
776 fn name(&self) -> &str {
777 "change"
778 }
779
780 fn inject_local_args(&self, command: &mut Command) {
781 self.mode.inject_args(command);
782 self.job_status_mode.inject_args(command);
783 self.permission_mode.inject_args(command);
784 self.changelist_mode.inject_args(command);
785 }
786
787 fn global_opts(&self) -> Option<&GlobalOpts> {
788 Some(&self.global_opts)
789 }
790}
791
792impl<F, O, C, S, I> ParameterizedSpawn<(I,)> for Change<F, O, C, S>
797where
798 F: ExclusiveOption + TakesChangeList,
799 O: ExclusiveOption,
800 C: ExclusiveOption,
801 S: ExclusiveOption,
802 I: AsRef<OsStr>,
803{
804 type Output = Child;
805 type Error = std::io::Error;
806
807 fn spawn_with(&mut self, (changelist,): (I,)) -> Result<Self::Output, Self::Error> {
815 self.setup_command(&self.bin)
816 .arg(changelist)
817 .stdout(Stdio::piped())
818 .stderr(Stdio::piped())
819 .spawn()
820 }
821}
822
823impl<O, C, S> ParameterizedSpawn<()> for Change<RegularOperationMode, O, C, S>
826where
827 O: ExclusiveOption,
828 C: ExclusiveOption,
829 S: ExclusiveOption,
830{
831 type Output = Child;
832 type Error = std::io::Error;
833
834 fn spawn_with(&mut self, _: ()) -> Result<Self::Output, Self::Error> {
837 self.setup_command(&self.bin)
838 .stdout(Stdio::piped())
839 .stderr(Stdio::piped())
840 .spawn()
841 }
842}
843
844impl<O, C, S> ParameterizedSpawn<()> for Change<StdoutMode, O, C, S>
847where
848 O: ExclusiveOption,
849 C: ExclusiveOption,
850 S: ExclusiveOption,
851{
852 type Output = Child;
853 type Error = std::io::Error;
854
855 fn spawn_with(&mut self, _: ()) -> Result<Self::Output, Self::Error> {
858 self.setup_command(&self.bin)
859 .stdout(Stdio::piped())
860 .stderr(Stdio::piped())
861 .spawn()
862 }
863}
864
865impl<O, S> ParameterizedSpawn<()> for Change<StdinMode, O, Unselected, S>
866where
867 O: ExclusiveOption,
868 S: ExclusiveOption,
869{
870 type Output = Child;
871 type Error = std::io::Error;
872
873 fn spawn_with(&mut self, _: ()) -> Result<Self::Output, Self::Error> {
877 self.setup_command(&self.bin)
878 .stdin(Stdio::piped())
879 .stdout(Stdio::piped())
880 .stderr(Stdio::piped())
881 .spawn()
882 }
883}
884
885impl<O, S> ParameterizedSpawn<(Stdio,)> for Change<StdinMode, O, Unselected, S>
886where
887 O: ExclusiveOption,
888 S: ExclusiveOption,
889{
890 type Output = Child;
891 type Error = std::io::Error;
892
893 fn spawn_with(&mut self, (stdio,): (Stdio,)) -> Result<Self::Output, Self::Error> {
902 self.setup_command(&self.bin)
903 .stdin(stdio)
904 .stdout(Stdio::piped())
905 .stderr(Stdio::piped())
906 .spawn()
907 }
908}
909
910#[cfg(test)]
911mod tests {
912 use super::*;
913 use crate::cmd::args_of;
914
915 #[test]
934 fn regular_form_injects_all_options() {
935 let change = Change::new("p4", GlobalOpts::new())
936 .arbitrary_job_status()
937 .force()
938 .original();
939
940 assert_eq!(
941 args_of(&change.setup_command("p4")),
942 ["change", "-s", "-f", "-O"]
943 );
944 }
945
946 #[test]
947 #[cfg(not(feature = "lt2022_1"))]
948 fn regular_form_update_and_identity() {
949 let change = Change::new("p4", GlobalOpts::new())
950 .arbitrary_job_status()
951 .update()
952 .identity();
953
954 assert_eq!(
955 args_of(&change.setup_command("p4")),
956 ["change", "-s", "-u", "-I"]
957 );
958 }
959
960 #[test]
961 fn entry_points_select_form_flags() {
962 let delete = Change::new("p4", GlobalOpts::new()).delete();
963 assert_eq!(args_of(&delete.setup_command("p4")), ["change", "-d"]);
964
965 let stdout = Change::new("p4", GlobalOpts::new()).stdout();
966 assert_eq!(args_of(&stdout.setup_command("p4")), ["change", "-o"]);
967
968 let stdin = Change::new("p4", GlobalOpts::new()).stdin();
969 assert_eq!(args_of(&stdin.setup_command("p4")), ["change", "-i"]);
970
971 #[cfg(not(feature = "lt2015_2"))]
972 {
973 let remote = Change::new("p4", GlobalOpts::new()).server_id("remote-1");
974 #[cfg(feature = "lt2022_1")]
975 assert_eq!(
976 args_of(&remote.setup_command("p4")),
977 ["change", "-d", "-f", "--server=remote-1"]
978 );
979 #[cfg(not(feature = "lt2022_1"))]
980 assert_eq!(
981 args_of(&remote.setup_command("p4")),
982 ["change", "-d", "-f", "--serverid=remote-1"]
983 );
984 }
985 }
986
987 #[test]
988 fn arbitrary_job_status_carries_into_delete_stdout_stdin() {
989 let delete = Change::new("p4", GlobalOpts::new())
991 .arbitrary_job_status()
992 .delete();
993 assert_eq!(args_of(&delete.setup_command("p4")), ["change", "-d", "-s"]);
994
995 let stdout = Change::new("p4", GlobalOpts::new())
996 .arbitrary_job_status()
997 .stdout();
998 assert_eq!(args_of(&stdout.setup_command("p4")), ["change", "-o", "-s"]);
999
1000 let stdin = Change::new("p4", GlobalOpts::new())
1001 .arbitrary_job_status()
1002 .stdin();
1003 assert_eq!(args_of(&stdin.setup_command("p4")), ["change", "-i", "-s"]);
1004 }
1005
1006 #[test]
1007 fn regular_to_delete_preserves_compatible_options() {
1008 let change = Change::new("p4", GlobalOpts::new())
1009 .arbitrary_job_status()
1010 .force()
1011 .original()
1012 .delete();
1013
1014 assert_eq!(
1015 args_of(&change.setup_command("p4")),
1016 ["change", "-d", "-s", "-f", "-O"]
1017 );
1018 }
1019
1020 #[test]
1021 #[cfg(not(feature = "lt2022_1"))]
1022 fn regular_to_stdout_preserves_identity() {
1023 let change = Change::new("p4", GlobalOpts::new())
1024 .arbitrary_job_status()
1025 .force()
1026 .identity()
1027 .stdout();
1028
1029 assert_eq!(
1030 args_of(&change.setup_command("p4")),
1031 ["change", "-o", "-s", "-f", "-I"]
1032 );
1033 }
1034
1035 #[test]
1036 fn regular_to_stdin_preserves_update() {
1037 let change = Change::new("p4", GlobalOpts::new())
1038 .arbitrary_job_status()
1039 .update()
1040 .stdin();
1041
1042 assert_eq!(
1043 args_of(&change.setup_command("p4")),
1044 ["change", "-i", "-s", "-u"]
1045 );
1046 }
1047
1048 #[test]
1049 #[cfg(not(feature = "lt2015_2"))]
1050 fn regular_to_remote_delete_folds_force_into_builtin() {
1051 let change = Change::new("p4", GlobalOpts::new())
1054 .force()
1055 .server_id("remote-1");
1056
1057 #[cfg(feature = "lt2022_1")]
1058 assert_eq!(
1059 args_of(&change.setup_command("p4")),
1060 ["change", "-d", "-f", "--server=remote-1"]
1061 );
1062 #[cfg(not(feature = "lt2022_1"))]
1063 assert_eq!(
1064 args_of(&change.setup_command("p4")),
1065 ["change", "-d", "-f", "--serverid=remote-1"]
1066 );
1067 }
1068
1069 #[test]
1070 fn regular_visibility_maps_to_only_states() {
1071 let forced = Change::new("p4", GlobalOpts::new())
1073 .force()
1074 .visibility(Visibility::Restricted);
1075 assert_eq!(
1076 args_of(&forced.setup_command("p4")),
1077 ["change", "-t", "restricted", "-f"]
1078 );
1079
1080 #[cfg(not(feature = "lt2022_1"))]
1082 {
1083 let identity = Change::new("p4", GlobalOpts::new())
1084 .identity()
1085 .visibility(Visibility::Public);
1086 assert_eq!(
1087 args_of(&identity.setup_command("p4")),
1088 ["change", "-t", "public", "-I"]
1089 );
1090 }
1091
1092 let plain = Change::new("p4", GlobalOpts::new())
1094 .visibility(Visibility::Restricted)
1095 .user("maria");
1096 assert_eq!(
1097 args_of(&plain.setup_command("p4")),
1098 ["change", "-t", "restricted", "-U", "maria"]
1099 );
1100 }
1101
1102 #[test]
1103 fn regular_user_maps_single_option() {
1104 let change = Change::new("p4", GlobalOpts::new())
1106 .force()
1107 .user("maria")
1108 .visibility(Visibility::Public);
1109
1110 assert_eq!(
1111 args_of(&change.setup_command("p4")),
1112 ["change", "-t", "public", "-U", "maria", "-f"]
1113 );
1114
1115 let original = Change::new("p4", GlobalOpts::new())
1117 .original()
1118 .user("maria");
1119
1120 assert_eq!(
1121 args_of(&original.setup_command("p4")),
1122 ["change", "-U", "maria", "-O"]
1123 );
1124 }
1125
1126 #[test]
1127 fn user_or_visibility_form_sets_values_and_selects_one_option() {
1128 let both = Change::new("p4", GlobalOpts::new())
1130 .user("maria")
1131 .visibility(Visibility::Public);
1132 assert_eq!(
1133 args_of(&both.setup_command("p4")),
1134 ["change", "-t", "public", "-U", "maria"]
1135 );
1136
1137 let forced = Change::new("p4", GlobalOpts::new())
1139 .visibility(Visibility::Restricted)
1140 .force();
1141 assert_eq!(
1142 args_of(&forced.setup_command("p4")),
1143 ["change", "-t", "restricted", "-f"]
1144 );
1145
1146 let updated = Change::new("p4", GlobalOpts::new()).user("maria").update();
1147 assert_eq!(
1148 args_of(&updated.setup_command("p4")),
1149 ["change", "-U", "maria", "-u"]
1150 );
1151
1152 let original = Change::new("p4", GlobalOpts::new())
1153 .user("maria")
1154 .original();
1155 assert_eq!(
1156 args_of(&original.setup_command("p4")),
1157 ["change", "-U", "maria", "-O"]
1158 );
1159
1160 #[cfg(not(feature = "lt2015_2"))]
1161 {
1162 let identity = Change::new("p4", GlobalOpts::new())
1163 .visibility(Visibility::Public)
1164 .identity();
1165 assert_eq!(
1166 args_of(&identity.setup_command("p4")),
1167 ["change", "-t", "public", "-I"]
1168 );
1169 }
1170 }
1171
1172 #[test]
1173 fn options_can_be_selected_inside_forms() {
1174 let delete = Change::new("p4", GlobalOpts::new())
1175 .delete()
1176 .arbitrary_job_status()
1177 .force()
1178 .original();
1179 assert_eq!(
1180 args_of(&delete.setup_command("p4")),
1181 ["change", "-d", "-s", "-f", "-O"]
1182 );
1183
1184 #[cfg(not(feature = "lt2022_1"))]
1185 {
1186 let stdout = Change::new("p4", GlobalOpts::new())
1187 .stdout()
1188 .arbitrary_job_status()
1189 .identity();
1190 assert_eq!(
1191 args_of(&stdout.setup_command("p4")),
1192 ["change", "-o", "-s", "-I"]
1193 );
1194 }
1195 #[cfg(feature = "lt2022_1")]
1196 {
1197 let stdout = Change::new("p4", GlobalOpts::new())
1198 .stdout()
1199 .arbitrary_job_status()
1200 .original();
1201 assert_eq!(
1202 args_of(&stdout.setup_command("p4")),
1203 ["change", "-o", "-s", "-O"]
1204 );
1205 }
1206
1207 let stdin = Change::new("p4", GlobalOpts::new())
1208 .stdin()
1209 .arbitrary_job_status()
1210 .update();
1211 assert_eq!(
1212 args_of(&stdin.setup_command("p4")),
1213 ["change", "-i", "-s", "-u"]
1214 );
1215 }
1216
1217 #[test]
1218 fn global_opts_are_injected_once() {
1219 let change = Change::new("p4", GlobalOpts::new()).delete();
1220
1221 assert_eq!(args_of(&change.setup_command("p4")), ["change", "-d"]);
1223 }
1224
1225 #[test]
1232 fn spawn_argument_counts_per_form() {
1233 let plain = Change::new("p4", GlobalOpts::new())
1235 .arbitrary_job_status()
1236 .force();
1237 assert_eq!(args_of(&plain.setup_command("p4")), ["change", "-s", "-f"]);
1238 let mut with_cl = plain.setup_command("p4");
1239 with_cl.arg("1234");
1240 assert_eq!(args_of(&with_cl), ["change", "-s", "-f", "1234"]);
1241
1242 let delete = Change::new("p4", GlobalOpts::new())
1244 .delete()
1245 .arbitrary_job_status()
1246 .force()
1247 .original();
1248 let mut delete_cl = delete.setup_command("p4");
1249 delete_cl.arg("1234");
1250 assert_eq!(
1251 args_of(&delete_cl),
1252 ["change", "-d", "-s", "-f", "-O", "1234"]
1253 );
1254
1255 #[cfg(not(feature = "lt2015_2"))]
1257 {
1258 let remote = Change::new("p4", GlobalOpts::new()).server_id("edge-1");
1259 let mut remote_cl = remote.setup_command("p4");
1260 remote_cl.arg("1234");
1261 #[cfg(feature = "lt2022_1")]
1262 assert_eq!(
1263 args_of(&remote_cl),
1264 ["change", "-d", "-f", "--server=edge-1", "1234"]
1265 );
1266 #[cfg(not(feature = "lt2022_1"))]
1267 assert_eq!(
1268 args_of(&remote_cl),
1269 ["change", "-d", "-f", "--serverid=edge-1", "1234"]
1270 );
1271 }
1272
1273 #[cfg(not(feature = "lt2022_1"))]
1275 {
1276 let stdout = Change::new("p4", GlobalOpts::new())
1277 .stdout()
1278 .arbitrary_job_status()
1279 .force()
1280 .identity();
1281 assert_eq!(
1282 args_of(&stdout.setup_command("p4")),
1283 ["change", "-o", "-s", "-f", "-I"]
1284 );
1285 let mut stdout_cl = stdout.setup_command("p4");
1286 stdout_cl.arg("1234");
1287 assert_eq!(
1288 args_of(&stdout_cl),
1289 ["change", "-o", "-s", "-f", "-I", "1234"]
1290 );
1291 }
1292 #[cfg(feature = "lt2022_1")]
1293 {
1294 let stdout = Change::new("p4", GlobalOpts::new())
1295 .stdout()
1296 .arbitrary_job_status()
1297 .force()
1298 .original();
1299 assert_eq!(
1300 args_of(&stdout.setup_command("p4")),
1301 ["change", "-o", "-s", "-f", "-O"]
1302 );
1303 let mut stdout_cl = stdout.setup_command("p4");
1304 stdout_cl.arg("1234");
1305 assert_eq!(
1306 args_of(&stdout_cl),
1307 ["change", "-o", "-s", "-f", "-O", "1234"]
1308 );
1309 }
1310
1311 let stdin = Change::new("p4", GlobalOpts::new())
1313 .stdin()
1314 .arbitrary_job_status()
1315 .update();
1316 assert_eq!(
1317 args_of(&stdin.setup_command("p4")),
1318 ["change", "-i", "-s", "-u"]
1319 );
1320
1321 let uov = Change::new("p4", GlobalOpts::new())
1323 .visibility(Visibility::Restricted)
1324 .user("maria")
1325 .force();
1326 let mut uov_cl = uov.setup_command("p4");
1327 uov_cl.arg("1234");
1328 assert_eq!(
1329 args_of(&uov_cl),
1330 ["change", "-t", "restricted", "-U", "maria", "-f", "1234"]
1331 );
1332 }
1333}