1use std::{
2 ffi::OsStr,
3 path::PathBuf,
4 process::{Child, Command, Stdio},
5};
6
7use super::{DiffOptions, ExclusiveOption, SubCommand, Unselected};
8
9use crate::global::GlobalOpts;
10use crate::spawn::ParameterizedSpawn;
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18pub enum DisplayOptions {
19 OpenedChangedOrMissing,
24
25 ResolvedThenModified,
30
31 UnopenedMissing,
36
37 UnopenedChanged,
42
43 #[cfg_attr(
49 feature = "lt2014_2",
50 doc = "If you use the `-f` flag together with the `-sl` flag, files that are open for edit are also compared and their status is listed."
51 )]
52 #[cfg_attr(
53 not(feature = "lt2014_2"),
54 doc = "If you use the `-f` option together with the `-sl` option, files that are open for edit are also compared and their status is listed."
55 )]
56 ListWithStatus,
60
61 OpenedIdentical,
66}
67
68impl DisplayOptions {
69 pub fn as_str(&self) -> &'static str {
71 match self {
72 DisplayOptions::OpenedChangedOrMissing => "-sa",
73 DisplayOptions::ResolvedThenModified => "-sb",
74 DisplayOptions::UnopenedMissing => "-sd",
75 DisplayOptions::UnopenedChanged => "-se",
76 DisplayOptions::ListWithStatus => "-sl",
77 DisplayOptions::OpenedIdentical => "-sr",
78 }
79 }
80}
81
82#[derive(Debug, Clone, Copy, PartialEq, Eq)]
87pub struct WorkspaceDisplayMode {
88 display_opts: DisplayOptions,
89}
90
91impl ExclusiveOption for WorkspaceDisplayMode {
92 fn inject_args(&self, command: &mut Command) {
93 command.arg(self.display_opts.as_str());
94 }
95}
96
97#[derive(Debug, Clone, Copy, PartialEq, Eq)]
102pub struct WorkspaceRegularMode {
103 limit: u64,
104}
105
106impl ExclusiveOption for WorkspaceRegularMode {
107 fn inject_args(&self, command: &mut Command) {
108 command.arg("-m").arg(self.limit.to_string());
109 }
110}
111
112#[derive(Debug, Clone, Default)]
123pub struct WorkspaceMode<M = Unselected> {
124 force: bool,
125
126 differing_only: bool,
127
128 diff_nontext: bool,
129
130 mode: M,
131}
132
133impl<M: ExclusiveOption> ExclusiveOption for WorkspaceMode<M> {
134 fn inject_args(&self, command: &mut Command) {
135 if self.force {
136 command.arg("-f");
137 }
138
139 if self.diff_nontext {
140 command.arg("-t");
141 }
142
143 if self.differing_only {
144 command.arg("-Od");
145 }
146
147 self.mode.inject_args(command);
148 }
149}
150
151#[cfg(not(feature = "lt2019_1"))]
158#[derive(Debug, Clone, Default, PartialEq, Eq)]
159pub struct StreamSpecMode;
160
161#[cfg(not(feature = "lt2019_1"))]
162impl ExclusiveOption for StreamSpecMode {
163 fn inject_args(&self, command: &mut Command) {
164 command.arg("-As");
165 }
166}
167
168#[cfg_attr(
169 feature = "lt2014_2",
170 doc = "`p4 [g-opts] diff [-dflags -f -m max -Od -sa -sb -sd -se -sr -sl -t] [file[rev#]...]`"
171)]
172#[cfg_attr(
173 all(feature = "lt2015_1", not(feature = "lt2014_2")),
174 doc = "`p4 [g-opts] diff [-doptions -f -m max -Od -sa -sb -sd -se -sr -sl -t] [file[rev#]...]`"
175)]
176#[cfg_attr(
177 all(feature = "lt2016_1", not(feature = "lt2015_1")),
178 doc = "`p4 [g-opts] diff [-doptions] [-f -t -Od] [-m max] [-soptions] [file[rev] …]`"
179)]
180#[cfg_attr(
181 all(feature = "lt2019_1", not(feature = "lt2016_1")),
182 doc = "`p4 [g-opts] diff [-doptions] [-f -t -Od] [-m max] [-soptions] [file[rev] ...]`"
183)]
184#[cfg_attr(
185 not(feature = "lt2019_1"),
186 doc = "`p4 [g-opts] diff [-doptions] [-f -t -Od] [-m max] [-soptions] [file[rev] ...]`",
187 doc = "",
188 doc = "`p4 [g-opts] diff [-doptions] -As [streamname[@change]]`"
189)]
190#[cfg_attr(not(feature = "lt2019_1"), doc = "Also for stream spec comparison.")]
195#[cfg_attr(
197 feature = "lt2019_1",
198 doc = "The `M` type parameter tracks the command mode at compile time. The default [`Unselected`] state offers the workspace content options; [`Self::force`], [`Self::differing_only`], and [`Self::diff_nontext`] transition to the [`WorkspaceMode`] state."
199)]
200#[cfg_attr(
201 not(feature = "lt2019_1"),
202 doc = "The `M` type parameter tracks the command mode at compile time. The default [`Unselected`] state offers neither the workspace content options nor `-As`; [`Self::force`], [`Self::differing_only`], and [`Self::diff_nontext`] transition to the [`WorkspaceMode`] state, while [`Self::stream_spec_mode`] transitions to the [`StreamSpecMode`] state."
203)]
204#[derive(Debug, Clone, Default)]
205pub struct Diff<M = Unselected> {
206 bin: PathBuf,
207
208 global_opts: GlobalOpts,
209
210 diff_opts: Option<DiffOptions>,
211
212 mode: M,
213}
214
215impl Diff<Unselected> {
216 pub fn new(bin: impl Into<PathBuf>, global_opts: GlobalOpts) -> Self {
220 Self {
221 bin: bin.into(),
222 global_opts,
223 diff_opts: None,
224 mode: Unselected,
225 }
226 }
227
228 pub fn force(self, v: bool) -> Diff<WorkspaceMode<Unselected>> {
238 Diff {
239 bin: self.bin,
240 global_opts: self.global_opts,
241 diff_opts: self.diff_opts,
242 mode: WorkspaceMode {
243 force: v,
244 differing_only: false,
245 diff_nontext: false,
246 mode: Unselected,
247 },
248 }
249 }
250
251 pub fn differing_only(self, v: bool) -> Diff<WorkspaceMode<Unselected>> {
260 Diff {
261 bin: self.bin,
262 global_opts: self.global_opts,
263 diff_opts: self.diff_opts,
264 mode: WorkspaceMode {
265 force: false,
266 differing_only: v,
267 diff_nontext: false,
268 mode: Unselected,
269 },
270 }
271 }
272
273 pub fn diff_nontext(self, v: bool) -> Diff<WorkspaceMode<Unselected>> {
282 Diff {
283 bin: self.bin,
284 global_opts: self.global_opts,
285 diff_opts: self.diff_opts,
286 mode: WorkspaceMode {
287 force: false,
288 differing_only: false,
289 diff_nontext: v,
290 mode: Unselected,
291 },
292 }
293 }
294
295 #[cfg_attr(
304 feature = "lt2024_2",
305 doc = "Limitation: Although this option requires the user have at least the `list` access to the stream path, it ignores any other entry in the protections table, including any minus sign (`-`) that would otherwise block the operation."
306 )]
307 #[cfg_attr(
308 not(feature = "lt2024_2"),
309 doc = "Although this option requires the user have at least the `list` access to the stream path, it ignores any other entry in the protections table, including any minus sign (`-`) that would otherwise block the operation."
310 )]
311 #[cfg(not(feature = "lt2019_1"))]
317 pub fn stream_spec_mode(self) -> Diff<StreamSpecMode> {
318 Diff {
319 bin: self.bin,
320 global_opts: self.global_opts,
321 diff_opts: self.diff_opts,
322 mode: StreamSpecMode,
323 }
324 }
325}
326
327impl<M> Diff<M> {
328 #[cfg_attr(
333 feature = "lt2014_2",
334 doc = "Pass flags to the underlying diff routine (see the Usage Notes below for details)"
335 )]
336 #[cfg_attr(
337 all(feature = "lt2015_1", not(feature = "lt2014_2")),
338 doc = "Pass options to the underlying diff routine (see the Usage Notes below for details)."
339 )]
340 #[cfg_attr(
341 all(feature = "lt2024_1", not(feature = "lt2015_1")),
342 doc = "Pass options to the underlying diff routine (see Usage Notes for details)."
343 )]
344 #[cfg_attr(
345 not(feature = "lt2024_1"),
346 doc = "Pass options to the underlying diff routine (see Usage notes for details)."
347 )]
348 pub fn get_diff_options(&self) -> Option<&DiffOptions> {
349 self.diff_opts.as_ref()
350 }
351
352 #[cfg_attr(
357 feature = "lt2014_2",
358 doc = "Pass flags to the underlying diff routine (see the Usage Notes below for details)"
359 )]
360 #[cfg_attr(
361 all(feature = "lt2015_1", not(feature = "lt2014_2")),
362 doc = "Pass options to the underlying diff routine (see the Usage Notes below for details)."
363 )]
364 #[cfg_attr(
365 all(feature = "lt2024_1", not(feature = "lt2015_1")),
366 doc = "Pass options to the underlying diff routine (see Usage Notes for details)."
367 )]
368 #[cfg_attr(
369 not(feature = "lt2024_1"),
370 doc = "Pass options to the underlying diff routine (see Usage notes for details)."
371 )]
372 pub fn set_diff_options(&mut self, v: impl Into<DiffOptions>) -> &mut Self {
373 self.diff_opts = Some(v.into());
374 self
375 }
376
377 #[cfg_attr(
382 feature = "lt2014_2",
383 doc = "Pass flags to the underlying diff routine (see the Usage Notes below for details)"
384 )]
385 #[cfg_attr(
386 all(feature = "lt2015_1", not(feature = "lt2014_2")),
387 doc = "Pass options to the underlying diff routine (see the Usage Notes below for details)."
388 )]
389 #[cfg_attr(
390 all(feature = "lt2024_1", not(feature = "lt2015_1")),
391 doc = "Pass options to the underlying diff routine (see Usage Notes for details)."
392 )]
393 #[cfg_attr(
394 not(feature = "lt2024_1"),
395 doc = "Pass options to the underlying diff routine (see Usage notes for details)."
396 )]
397 pub fn diff_options(mut self, v: impl Into<DiffOptions>) -> Self {
398 self.diff_opts = Some(v.into());
399 self
400 }
401}
402
403impl<M: ExclusiveOption> Diff<M> {
404 #[cfg_attr(
409 feature = "lt2014_2",
410 doc = "See the [Global Options](GlobalOpts) section."
411 )]
412 #[cfg_attr(
413 all(feature = "lt2015_1", not(feature = "lt2014_2")),
414 doc = "See the [“Global Options”](GlobalOpts) section."
415 )]
416 #[cfg_attr(
417 all(feature = "lt2017_1", not(feature = "lt2015_1")),
418 doc = "See [“Global Options”](GlobalOpts)."
419 )]
420 #[cfg_attr(
421 all(feature = "lt2018_2", not(feature = "lt2017_1")),
422 doc = "See [Global Options](GlobalOpts)."
423 )]
424 #[cfg_attr(not(feature = "lt2018_2"), doc = "See [Global options](GlobalOpts).")]
425 pub fn get_global_opts(&self) -> &GlobalOpts {
426 &self.global_opts
427 }
428
429 #[cfg_attr(
434 feature = "lt2014_2",
435 doc = "See the [Global Options](GlobalOpts) section."
436 )]
437 #[cfg_attr(
438 all(feature = "lt2015_1", not(feature = "lt2014_2")),
439 doc = "See the [“Global Options”](GlobalOpts) section."
440 )]
441 #[cfg_attr(
442 all(feature = "lt2017_1", not(feature = "lt2015_1")),
443 doc = "See [“Global Options”](GlobalOpts)."
444 )]
445 #[cfg_attr(
446 all(feature = "lt2018_2", not(feature = "lt2017_1")),
447 doc = "See [Global Options](GlobalOpts)."
448 )]
449 #[cfg_attr(not(feature = "lt2018_2"), doc = "See [Global options](GlobalOpts).")]
450 pub fn set_global_opts(&mut self, v: GlobalOpts) -> &mut Self {
451 self.global_opts = v;
452 self
453 }
454
455 #[cfg_attr(
460 feature = "lt2014_2",
461 doc = "See the [Global Options](GlobalOpts) section."
462 )]
463 #[cfg_attr(
464 all(feature = "lt2015_1", not(feature = "lt2014_2")),
465 doc = "See the [“Global Options”](GlobalOpts) section."
466 )]
467 #[cfg_attr(
468 all(feature = "lt2017_1", not(feature = "lt2015_1")),
469 doc = "See [“Global Options”](GlobalOpts)."
470 )]
471 #[cfg_attr(
472 all(feature = "lt2018_2", not(feature = "lt2017_1")),
473 doc = "See [Global Options](GlobalOpts)."
474 )]
475 #[cfg_attr(not(feature = "lt2018_2"), doc = "See [Global options](GlobalOpts).")]
476 pub fn global_opts(mut self, v: GlobalOpts) -> Self {
477 self.global_opts = v;
478 self
479 }
480}
481
482impl<M> Diff<WorkspaceMode<M>> {
483 pub fn get_force(&self) -> bool {
490 self.mode.force
491 }
492
493 pub fn set_force(&mut self, v: bool) -> &mut Self {
500 self.mode.force = v;
501 self
502 }
503
504 pub fn force(mut self, v: bool) -> Self {
511 self.mode.force = v;
512 self
513 }
514
515 pub fn get_differing_only(&self) -> bool {
521 self.mode.differing_only
522 }
523
524 pub fn set_differing_only(&mut self, v: bool) -> &mut Self {
530 self.mode.differing_only = v;
531 self
532 }
533
534 pub fn differing_only(mut self, v: bool) -> Self {
540 self.mode.differing_only = v;
541 self
542 }
543
544 pub fn get_diff_nontext(&self) -> bool {
550 self.mode.diff_nontext
551 }
552
553 pub fn set_diff_nontext(&mut self, v: bool) -> &mut Self {
559 self.mode.diff_nontext = v;
560 self
561 }
562
563 pub fn diff_nontext(mut self, v: bool) -> Self {
569 self.mode.diff_nontext = v;
570 self
571 }
572}
573
574impl Diff<WorkspaceMode<Unselected>> {
575 #[cfg_attr(feature = "lt2015_1", doc = "-sa, -sb, -sd, -se, -sr, -sl file ...")]
578 #[cfg_attr(not(feature = "lt2015_1"), doc = "-soptions")]
579 #[cfg_attr(
581 feature = "lt2015_1",
582 doc = "Pass one of the display options; see the individual option descriptions for details."
583 )]
584 #[cfg_attr(
585 all(feature = "lt2024_1", not(feature = "lt2015_1")),
586 doc = "Pass display options to the underlying diff routine (see Usage Notes for details)."
587 )]
588 #[cfg_attr(
589 not(feature = "lt2024_1"),
590 doc = "Pass display options to the underlying diff routine (see Usage notes for details)."
591 )]
592 pub fn display_options(self, v: DisplayOptions) -> Diff<WorkspaceMode<WorkspaceDisplayMode>> {
596 Diff {
597 bin: self.bin,
598 global_opts: self.global_opts,
599 diff_opts: self.diff_opts,
600 mode: WorkspaceMode {
601 force: self.mode.force,
602 differing_only: self.mode.differing_only,
603 diff_nontext: self.mode.diff_nontext,
604 mode: WorkspaceDisplayMode { display_opts: v },
605 },
606 }
607 }
608
609 #[cfg_attr(
614 feature = "lt2014_2",
615 doc = "Limit output to diffs (or status) of only the first `max` files, unless the `-s` flag is used, in which case the `-m` flag is ignored."
616 )]
617 #[cfg_attr(
618 not(feature = "lt2014_2"),
619 doc = "Limit output to diffs (or status) of only the first `max` files, unless the `-s` option is used, in which case the `-m` option is ignored."
620 )]
621 pub fn limit(self, max: u64) -> Diff<WorkspaceMode<WorkspaceRegularMode>> {
625 Diff {
626 bin: self.bin,
627 global_opts: self.global_opts,
628 diff_opts: self.diff_opts,
629 mode: WorkspaceMode {
630 force: self.mode.force,
631 differing_only: self.mode.differing_only,
632 diff_nontext: self.mode.diff_nontext,
633 mode: WorkspaceRegularMode { limit: max },
634 },
635 }
636 }
637}
638
639impl Diff<WorkspaceMode<WorkspaceDisplayMode>> {
640 #[cfg_attr(feature = "lt2015_1", doc = "-sa, -sb, -sd, -se, -sr, -sl file ...")]
643 #[cfg_attr(not(feature = "lt2015_1"), doc = "-soptions")]
644 #[cfg_attr(
646 feature = "lt2015_1",
647 doc = "Pass one of the display options; see the individual option descriptions for details."
648 )]
649 #[cfg_attr(
650 all(feature = "lt2024_1", not(feature = "lt2015_1")),
651 doc = "Pass display options to the underlying diff routine (see Usage Notes for details)."
652 )]
653 #[cfg_attr(
654 not(feature = "lt2024_1"),
655 doc = "Pass display options to the underlying diff routine (see Usage notes for details)."
656 )]
657 pub fn get_display_options(&self) -> &DisplayOptions {
658 &self.mode.mode.display_opts
659 }
660
661 #[cfg_attr(feature = "lt2015_1", doc = "-sa, -sb, -sd, -se, -sr, -sl file ...")]
664 #[cfg_attr(not(feature = "lt2015_1"), doc = "-soptions")]
665 #[cfg_attr(
667 feature = "lt2015_1",
668 doc = "Pass one of the display options; see the individual option descriptions for details."
669 )]
670 #[cfg_attr(
671 all(feature = "lt2024_1", not(feature = "lt2015_1")),
672 doc = "Pass display options to the underlying diff routine (see Usage Notes for details)."
673 )]
674 #[cfg_attr(
675 not(feature = "lt2024_1"),
676 doc = "Pass display options to the underlying diff routine (see Usage notes for details)."
677 )]
678 pub fn set_display_options(&mut self, v: DisplayOptions) -> &mut Self {
679 self.mode.mode.display_opts = v;
680 self
681 }
682}
683
684impl Diff<WorkspaceMode<WorkspaceRegularMode>> {
685 #[cfg_attr(
690 feature = "lt2014_2",
691 doc = "Limit output to diffs (or status) of only the first `max` files, unless the `-s` flag is used, in which case the `-m` flag is ignored."
692 )]
693 #[cfg_attr(
694 not(feature = "lt2014_2"),
695 doc = "Limit output to diffs (or status) of only the first `max` files, unless the `-s` option is used, in which case the `-m` option is ignored."
696 )]
697 pub fn get_limit(&self) -> u64 {
698 self.mode.mode.limit
699 }
700
701 #[cfg_attr(
706 feature = "lt2014_2",
707 doc = "Limit output to diffs (or status) of only the first `max` files, unless the `-s` flag is used, in which case the `-m` flag is ignored."
708 )]
709 #[cfg_attr(
710 not(feature = "lt2014_2"),
711 doc = "Limit output to diffs (or status) of only the first `max` files, unless the `-s` option is used, in which case the `-m` option is ignored."
712 )]
713 pub fn set_limit(&mut self, v: u64) -> &mut Self {
714 self.mode.mode.limit = v;
715 self
716 }
717}
718
719impl<M: ExclusiveOption> SubCommand for Diff<M> {
720 fn name(&self) -> &str {
721 "diff"
722 }
723
724 fn inject_local_args(&self, command: &mut Command) {
725 if let Some(diff_opts) = &self.diff_opts {
726 diff_opts.inject_arg(command);
727 }
728
729 self.mode.inject_args(command);
730 }
731
732 fn global_opts(&self) -> Option<&GlobalOpts> {
733 Some(&self.global_opts)
734 }
735}
736
737impl<S, I> ParameterizedSpawn<(S,)> for Diff<Unselected>
738where
739 S: IntoIterator<Item = I>,
740 I: AsRef<OsStr>,
741{
742 type Output = Child;
743 type Error = std::io::Error;
744
745 fn spawn_with(&mut self, (files,): (S,)) -> Result<Self::Output, Self::Error> {
749 self.setup_command(&self.bin)
750 .args(files)
751 .stdout(Stdio::piped())
752 .stderr(Stdio::piped())
753 .spawn()
754 }
755}
756
757impl<M: ExclusiveOption, S, I> ParameterizedSpawn<(S,)> for Diff<WorkspaceMode<M>>
758where
759 S: IntoIterator<Item = I>,
760 I: AsRef<OsStr>,
761{
762 type Output = Child;
763 type Error = std::io::Error;
764
765 fn spawn_with(&mut self, (files,): (S,)) -> Result<Self::Output, Self::Error> {
769 self.setup_command(&self.bin)
770 .args(files)
771 .stdout(Stdio::piped())
772 .stderr(Stdio::piped())
773 .spawn()
774 }
775}
776
777#[cfg(not(feature = "lt2019_1"))]
778impl<I> ParameterizedSpawn<(I,)> for Diff<StreamSpecMode>
779where
780 I: AsRef<OsStr>,
781{
782 type Output = Child;
783 type Error = std::io::Error;
784
785 fn spawn_with(&mut self, (stream_spec,): (I,)) -> Result<Self::Output, Self::Error> {
797 self.setup_command(&self.bin)
798 .arg(stream_spec)
799 .stdout(Stdio::piped())
800 .stderr(Stdio::piped())
801 .spawn()
802 }
803}
804
805#[cfg(not(feature = "lt2019_1"))]
806impl ParameterizedSpawn<()> for Diff<StreamSpecMode> {
807 type Output = Child;
808 type Error = std::io::Error;
809
810 fn spawn_with(&mut self, _: ()) -> Result<Self::Output, Self::Error> {
815 self.setup_command(&self.bin)
816 .stdout(Stdio::piped())
817 .stderr(Stdio::piped())
818 .spawn()
819 }
820}
821
822#[cfg(test)]
823mod tests {
824 use super::*;
825 use crate::cmd::DiffOptionsBuilder;
826 use crate::cmd::args_of;
827
828 #[test]
831 fn without_options() {
832 let diff = Diff::new("p4", GlobalOpts::new());
833
834 assert_eq!(args_of(&diff.setup_command("p4")), ["diff"]);
835 }
836
837 #[test]
838 fn workspace_mode_via_force() {
839 let diff = Diff::new("p4", GlobalOpts::new()).force(true);
840
841 assert!(diff.get_force());
842 assert_eq!(args_of(&diff.setup_command("p4")), ["diff", "-f"]);
843 }
844
845 #[test]
846 fn workspace_mode_via_differing_only() {
847 let diff = Diff::new("p4", GlobalOpts::new()).differing_only(true);
848
849 assert_eq!(args_of(&diff.setup_command("p4")), ["diff", "-Od"]);
850 }
851
852 #[test]
853 fn workspace_mode_via_diff_nontext() {
854 let diff = Diff::new("p4", GlobalOpts::new()).diff_nontext(true);
855
856 assert_eq!(args_of(&diff.setup_command("p4")), ["diff", "-t"]);
857 }
858
859 #[test]
860 fn workspace_mode_combines_options() {
861 let mut diff = Diff::new("p4", GlobalOpts::new()).diff_nontext(true);
862 diff.set_force(true).set_differing_only(true);
863
864 assert_eq!(
865 args_of(&diff.setup_command("p4")),
866 ["diff", "-f", "-t", "-Od"]
867 );
868 }
869
870 #[test]
871 fn workspace_mode_preserves_diff_options() {
872 let mut diff = Diff::new("p4", GlobalOpts::new())
873 .diff_options(DiffOptionsBuilder::unified(None))
874 .force(true);
875 diff.set_diff_options(DiffOptionsBuilder::summary());
876
877 assert_eq!(args_of(&diff.setup_command("p4")), ["diff", "-ds", "-f"]);
878 }
879
880 #[test]
881 fn display_mode_injects_filter() {
882 let diff = Diff::new("p4", GlobalOpts::new())
883 .force(true)
884 .display_options(DisplayOptions::UnopenedChanged);
885
886 assert_eq!(diff.get_display_options(), &DisplayOptions::UnopenedChanged);
887 assert_eq!(args_of(&diff.setup_command("p4")), ["diff", "-f", "-se"]);
888 }
889
890 #[test]
891 fn display_mode_flag_mapping() {
892 assert_eq!(DisplayOptions::OpenedChangedOrMissing.as_str(), "-sa");
893 assert_eq!(DisplayOptions::ResolvedThenModified.as_str(), "-sb");
894 assert_eq!(DisplayOptions::UnopenedMissing.as_str(), "-sd");
895 assert_eq!(DisplayOptions::UnopenedChanged.as_str(), "-se");
896 assert_eq!(DisplayOptions::ListWithStatus.as_str(), "-sl");
897 assert_eq!(DisplayOptions::OpenedIdentical.as_str(), "-sr");
898 }
899
900 #[test]
901 fn regular_mode_injects_limit() {
902 let diff = Diff::new("p4", GlobalOpts::new()).force(false).limit(10);
903
904 assert_eq!(diff.get_limit(), 10);
905 assert_eq!(args_of(&diff.setup_command("p4")), ["diff", "-m", "10"]);
906 }
907
908 #[cfg(not(feature = "lt2019_1"))]
909 #[test]
910 fn stream_spec_mode_bare() {
911 let diff = Diff::new("p4", GlobalOpts::new()).stream_spec_mode();
912
913 assert_eq!(args_of(&diff.setup_command("p4")), ["diff", "-As"]);
914 }
915
916 #[cfg(not(feature = "lt2019_1"))]
917 #[test]
918 fn stream_spec_mode_with_spec() {
919 let diff = Diff::new("p4", GlobalOpts::new()).stream_spec_mode();
920
921 let mut command = diff.setup_command("p4");
924 command.arg("myStream@head");
925
926 assert_eq!(args_of(&command), ["diff", "-As", "myStream@head"]);
927 }
928
929 #[cfg(not(feature = "lt2019_1"))]
930 #[test]
931 fn stream_spec_mode_preserves_diff_options() {
932 let diff = Diff::new("p4", GlobalOpts::new())
933 .diff_options(DiffOptionsBuilder::unified(None))
934 .stream_spec_mode();
935
936 let mut command = diff.setup_command("p4");
939 command.arg("myStream");
940
941 assert_eq!(args_of(&command), ["diff", "-du", "-As", "myStream"]);
942 }
943}