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
12#[derive(Debug, Clone, Default)]
18pub struct StandardPrintMode {
19 all_revisions: bool,
20
21 from_archive_depots: bool,
22
23 suppress_keyword_expansion: bool,
24
25 #[cfg(not(feature = "lt2023_1"))]
26 line_ending: Option<LineEnding>,
27
28 #[cfg(not(feature = "lt2023_1"))]
29 charset: Option<String>,
30
31 #[cfg(not(feature = "lt2023_1"))]
32 utf8bom: Option<Utf8Bom>,
33
34 limit: Option<u64>,
35
36 #[cfg(not(feature = "lt2022_1"))]
37 offset: Option<u64>,
38
39 #[cfg(not(feature = "lt2022_1"))]
40 size: Option<u64>,
41
42 redirect_output: Option<PathBuf>,
43
44 quiet_mode: bool,
45
46 #[cfg(not(feature = "lt2026_1"))]
47 ignore_changeview: bool,
48}
49
50impl ExclusiveOption for StandardPrintMode {
51 fn inject_args(&self, command: &mut Command) {
52 if self.all_revisions {
53 command.arg("-a");
54 }
55
56 if self.from_archive_depots {
57 command.arg("-A");
58 }
59
60 if self.suppress_keyword_expansion {
61 #[cfg(feature = "lt2022_1")]
62 {
63 command.arg("-k");
64 }
65 #[cfg(not(feature = "lt2022_1"))]
66 {
67 command.arg("-K");
68 }
69 }
70
71 if let Some(output) = &self.redirect_output {
72 command.arg("-o").arg(output);
73 }
74
75 if self.quiet_mode {
76 command.arg("-q");
77 }
78
79 if let Some(max) = self.limit {
80 command.arg("-m").arg(max.to_string());
81 }
82
83 #[cfg(not(feature = "lt2022_1"))]
84 {
85 if let Some(offset) = self.offset {
86 command.arg("--offset").arg(offset.to_string());
87 }
88
89 if let Some(size) = self.size {
90 command.arg("--size").arg(size.to_string());
91 }
92 }
93
94 #[cfg(not(feature = "lt2023_1"))]
95 {
96 if let Some(charset) = &self.charset {
97 command.arg("-Q").arg(charset);
98 }
99
100 if let Some(utf8bom) = &self.utf8bom {
101 command.arg("-B").arg(utf8bom.as_str());
102 }
103
104 if let Some(line_ending) = &self.line_ending {
105 command.arg("-L").arg(line_ending.as_str());
106 }
107 }
108
109 #[cfg(not(feature = "lt2026_1"))]
110 {
111 if self.ignore_changeview {
112 command.arg("--ignore-changeview");
113 }
114 }
115 }
116}
117
118#[derive(Debug, Clone, Copy, Default)]
124pub struct UnloadDepotMode;
125
126impl ExclusiveOption for UnloadDepotMode {
127 fn inject_args(&self, command: &mut Command) {
128 command.arg("-U");
129 }
130}
131
132#[cfg(not(feature = "lt2024_2"))]
138#[derive(Debug, Clone, Default)]
139pub struct AttributeTraitMode {
140 all_revisions: bool,
141
142 redirect_output: Option<PathBuf>,
143
144 quiet_mode: bool,
145
146 attribute: String,
147
148 #[cfg(not(feature = "lt2026_1"))]
149 ignore_changeview: bool,
150}
151
152#[cfg(not(feature = "lt2024_2"))]
153impl ExclusiveOption for AttributeTraitMode {
154 fn inject_args(&self, command: &mut Command) {
155 command.arg("-T").arg(&self.attribute);
156
157 if self.all_revisions {
158 command.arg("-a");
159 }
160
161 if let Some(output) = &self.redirect_output {
162 command.arg("-o").arg(output);
163 }
164
165 if self.quiet_mode {
166 command.arg("-q");
167 }
168
169 #[cfg(not(feature = "lt2026_1"))]
170 {
171 if self.ignore_changeview {
172 command.arg("--ignore-changeview");
173 }
174 }
175 }
176}
177
178#[cfg(not(feature = "lt2023_1"))]
181#[derive(Debug, Clone, Copy, PartialEq, Eq)]
182pub enum Utf8Bom {
183 No,
185 Yes,
187 WindowsOnly,
189}
190
191#[cfg(not(feature = "lt2023_1"))]
192impl Utf8Bom {
193 pub fn as_str(&self) -> &'static str {
195 match self {
196 Utf8Bom::No => "0",
197 Utf8Bom::Yes => "1",
198 Utf8Bom::WindowsOnly => "2",
199 }
200 }
201}
202
203#[cfg(not(feature = "lt2023_1"))]
205#[derive(Debug, Clone, Copy, PartialEq, Eq)]
206pub enum LineEnding {
207 Unix,
209 Win,
211 Mac,
213}
214
215#[cfg(not(feature = "lt2023_1"))]
216impl LineEnding {
217 pub fn as_str(&self) -> &'static str {
219 match self {
220 LineEnding::Unix => "unix",
221 LineEnding::Win => "win",
222 LineEnding::Mac => "mac",
223 }
224 }
225}
226
227#[cfg_attr(
228 feature = "lt2015_1",
229 doc = "`p4 [g-opts] print [-a -A -k -o outfile -q -m max -U] file[revRange] ...`"
230)]
231#[cfg_attr(
232 all(feature = "lt2016_1", not(feature = "lt2015_1")),
233 doc = "`p4 [g-opts] print [-a -A -k -q] [-m max] [-o outfile] file[revRange] …`",
234 doc = "",
235 doc = "`p4 [g-opts] print -U unloadfile …`"
236)]
237#[cfg_attr(
238 all(feature = "lt2018_1", not(feature = "lt2016_1")),
239 doc = "`p4 [g-opts] print [-a -A -k -q] [-m max] [-o outfile] file[revRange] ...`",
240 doc = "",
241 doc = "`p4 [g-opts] print -U unloadfile ...`"
242)]
243#[cfg_attr(
244 all(feature = "lt2022_1", not(feature = "lt2018_1")),
245 doc = "`p4 [g-opts] print [-a -A -k -q] [-m max] [-o outfile] FileSpec[revSpec]`",
246 doc = "",
247 doc = "`p4 [g-opts] print -U unload[FileSpec]`"
248)]
249#[cfg_attr(
250 all(feature = "lt2023_1", not(feature = "lt2022_1")),
251 doc = "`p4 [g-opts] print [-a -A -K -q] [-m max] --offset bytesToSkip --size bytesToPrint [-o outfile] FileSpec[revSpec]`",
252 doc = "",
253 doc = "`p4 [g-opts] print -U unload[FileSpec]`"
254)]
255#[cfg_attr(
256 all(feature = "lt2024_2", not(feature = "lt2023_1")),
257 doc = "`p4 print [-a -A -K -o localFile -q -m max --offset offset --size size -Q charset -B utf8bom -L line-ending] file[revRange] ...`",
258 doc = "",
259 doc = "`p4 print -U unloadfile ...`"
260)]
261#[cfg_attr(
262 all(feature = "lt2026_1", not(feature = "lt2024_2")),
263 doc = "`p4 print [-a -A -K -o localFile -q -m max --offset offset --size size -Q charset -B utf8bom -L line-ending] file[revRange] ...`",
264 doc = "",
265 doc = "`p4 print -U unloadfile ...`",
266 doc = "",
267 doc = "`p4 print -T attribute [-a -q -o localFile] file ...`"
268)]
269#[cfg_attr(
270 not(feature = "lt2026_1"),
271 doc = "`p4 print [-a -A -K -o localFile -q -m max --offset offset --size size -Q charset -B utf8bom -L line-ending] [--ignore-changeview] file[revRange] ...`",
272 doc = "",
273 doc = "`p4 print -U unloadfile ...`",
274 doc = "",
275 doc = "`p4 print -T attribute [-a -q -o localFile] [--ignore-changeview] file ...`"
276)]
277#[cfg_attr(
281 feature = "lt2024_2",
282 doc = "The `M` type parameter tracks which of the two forms of the command is in use at compile time. The default [`Unselected`] state prints files without local options; setting any standard option such as [`Self::all_revisions`] transitions to [`StandardPrintMode`], and [`Self::from_unload_depot`] transitions to [`UnloadDepotMode`]."
283)]
284#[cfg_attr(
285 not(feature = "lt2024_2"),
286 doc = "The `M` type parameter tracks which of the three forms of the command is in use at compile time. The default [`Unselected`] state prints files without local options; setting any standard option such as [`Self::all_revisions`] transitions to [`StandardPrintMode`], [`Self::from_unload_depot`] transitions to [`UnloadDepotMode`], and [`Self::extract_attribute`] transitions to [`AttributeTraitMode`]."
287)]
288#[derive(Debug, Clone, Default)]
289pub struct Print<M = Unselected> {
290 bin: PathBuf,
291
292 global_opts: GlobalOpts,
293
294 mode: M,
295}
296
297impl Print<Unselected> {
298 pub fn new(bin: impl Into<PathBuf>, global_opts: GlobalOpts) -> Self {
302 Self {
303 bin: bin.into(),
304 global_opts,
305 mode: Unselected,
306 }
307 }
308
309 pub fn from_unload_depot(self) -> Print<UnloadDepotMode> {
319 Print {
320 bin: self.bin,
321 global_opts: self.global_opts,
322 mode: UnloadDepotMode,
323 }
324 }
325
326 #[cfg(not(feature = "lt2024_2"))]
340 pub fn extract_attribute(self, name: impl Into<String>) -> Print<AttributeTraitMode> {
341 Print {
342 bin: self.bin,
343 global_opts: self.global_opts,
344 mode: AttributeTraitMode {
345 all_revisions: false,
346 redirect_output: None,
347 quiet_mode: false,
348 attribute: name.into(),
349 #[cfg(not(feature = "lt2026_1"))]
350 ignore_changeview: false,
351 },
352 }
353 }
354
355 pub fn all_revisions(self, v: bool) -> Print<StandardPrintMode> {
364 Print {
365 bin: self.bin,
366 global_opts: self.global_opts,
367 mode: StandardPrintMode {
368 all_revisions: v,
369 ..StandardPrintMode::default()
370 },
371 }
372 }
373
374 #[cfg_attr(
379 feature = "lt2023_1",
380 doc = "Attempt to print a file stored in an archive depot."
381 )]
382 #[cfg_attr(not(feature = "lt2023_1"), doc = "Print files in archive depots.")]
383 pub fn archive_depots(self, v: bool) -> Print<StandardPrintMode> {
386 Print {
387 bin: self.bin,
388 global_opts: self.global_opts,
389 mode: StandardPrintMode {
390 from_archive_depots: v,
391 ..StandardPrintMode::default()
392 },
393 }
394 }
395
396 #[cfg_attr(feature = "lt2022_1", doc = "-k")]
399 #[cfg_attr(not(feature = "lt2022_1"), doc = "-K")]
400 #[cfg_attr(feature = "lt2023_1", doc = "Suppress RCS keyword expansion.")]
402 #[cfg_attr(
403 not(feature = "lt2023_1"),
404 doc = "Suppress RCS keyword expansion. This replaced the `-k` flag in",
405 doc = "2022.1, which is now an alias for `-K` for backwards compatibility."
406 )]
407 pub fn suppress_keyword_expansion(self, v: bool) -> Print<StandardPrintMode> {
410 Print {
411 bin: self.bin,
412 global_opts: self.global_opts,
413 mode: StandardPrintMode {
414 suppress_keyword_expansion: v,
415 ..StandardPrintMode::default()
416 },
417 }
418 }
419
420 #[cfg_attr(feature = "lt2023_1", doc = "-o outfile")]
423 #[cfg_attr(not(feature = "lt2023_1"), doc = "-o localfile")]
424 #[cfg_attr(
426 feature = "lt2018_2",
427 doc = "Redirect output to the specified output file on the local disk,",
428 doc = "preserving the same file type, attributes, and/or permission bits",
429 doc = "as the original file in the depot."
430 )]
431 #[cfg_attr(
432 all(feature = "lt2023_1", not(feature = "lt2018_2")),
433 doc = "Redirect output to the specified output file (`outfile`) on the",
434 doc = "local disk. This preserves the same file type, attributes, and/or",
435 doc = "permission bits as the original file (`FileSpec`) in the depot.",
436 doc = "Multiple files can be written by using wildcards in the",
437 doc = "`localFile` argument that match wildcards in the depot",
438 doc = "(`FileSpec`) argument. For example: To print the contents of a",
439 doc = "directory and directories under that directory, use the `...`",
440 doc = "wildcard: `p4 print -o c:/tmp/main-copy/... //depot/main/...` To",
441 doc = "print all files that match readme.txt or readme.pdf, you might",
442 doc = "specify `p4 print -o readme.* //depot/readme.*`"
443 )]
444 #[cfg_attr(
445 not(feature = "lt2023_1"),
446 doc = "Redirect output to the specified output file (`localfile`) on the",
447 doc = "local disk. This preserves the same file type, attributes, and/or",
448 doc = "permission bits as the original file (`FileSpec`) in the depot.",
449 doc = "Multiple files can be written by using wildcards in the",
450 doc = "`localFile` argument that match wildcards in the depot",
451 doc = "(`FileSpec`) argument. For example: To print the contents of a",
452 doc = "directory and directories under that directory, use the `...`",
453 doc = "wildcard: `p4 print -o c:/tmp/main-copy/... //depot/main/...` To",
454 doc = "print all files that match readme.txt or readme.pdf, you might",
455 doc = "specify `p4 print -o readme.* //depot/readme.*`"
456 )]
457 pub fn redirect_output(self, v: impl Into<PathBuf>) -> Print<StandardPrintMode> {
460 Print {
461 bin: self.bin,
462 global_opts: self.global_opts,
463 mode: StandardPrintMode {
464 redirect_output: Some(v.into()),
465 ..StandardPrintMode::default()
466 },
467 }
468 }
469
470 #[cfg_attr(feature = "lt2018_1", doc = "Perforce.")]
476 #[cfg_attr(
477 all(feature = "lt2019_1", not(feature = "lt2018_1")),
478 doc = "Helix Server."
479 )]
480 #[cfg_attr(
481 all(feature = "lt2021_1", not(feature = "lt2019_1")),
482 doc = "Helix server."
483 )]
484 #[cfg_attr(
485 all(feature = "lt2024_1", not(feature = "lt2021_1")),
486 doc = "Helix Server."
487 )]
488 #[cfg_attr(
489 all(feature = "lt2024_2", not(feature = "lt2024_1")),
490 doc = "Helix Core Server."
491 )]
492 #[cfg_attr(not(feature = "lt2024_2"), doc = "P4 Server.")]
493 pub fn quiet_mode(self, v: bool) -> Print<StandardPrintMode> {
496 Print {
497 bin: self.bin,
498 global_opts: self.global_opts,
499 mode: StandardPrintMode {
500 quiet_mode: v,
501 ..StandardPrintMode::default()
502 },
503 }
504 }
505
506 pub fn limit(self, v: u64) -> Print<StandardPrintMode> {
514 Print {
515 bin: self.bin,
516 global_opts: self.global_opts,
517 mode: StandardPrintMode {
518 limit: Some(v),
519 ..StandardPrintMode::default()
520 },
521 }
522 }
523
524 #[cfg(not(feature = "lt2022_1"))]
533 pub fn offset(self, v: u64) -> Print<StandardPrintMode> {
534 Print {
535 bin: self.bin,
536 global_opts: self.global_opts,
537 mode: StandardPrintMode {
538 offset: Some(v),
539 ..StandardPrintMode::default()
540 },
541 }
542 }
543
544 #[cfg(not(feature = "lt2022_1"))]
554 pub fn size(self, v: u64) -> Print<StandardPrintMode> {
555 Print {
556 bin: self.bin,
557 global_opts: self.global_opts,
558 mode: StandardPrintMode {
559 size: Some(v),
560 ..StandardPrintMode::default()
561 },
562 }
563 }
564
565 #[cfg(not(feature = "lt2023_1"))]
575 pub fn charset(self, v: impl Into<String>) -> Print<StandardPrintMode> {
576 Print {
577 bin: self.bin,
578 global_opts: self.global_opts,
579 mode: StandardPrintMode {
580 charset: Some(v.into()),
581 ..StandardPrintMode::default()
582 },
583 }
584 }
585
586 #[cfg(not(feature = "lt2023_1"))]
597 pub fn write_utf8bom(self, v: bool) -> Print<StandardPrintMode> {
598 Print {
599 bin: self.bin,
600 global_opts: self.global_opts,
601 mode: StandardPrintMode {
602 utf8bom: Some(if v { Utf8Bom::Yes } else { Utf8Bom::No }),
603 ..StandardPrintMode::default()
604 },
605 }
606 }
607
608 #[cfg(not(feature = "lt2023_1"))]
617 pub fn write_utf8bom_windows_only(self) -> Print<StandardPrintMode> {
618 Print {
619 bin: self.bin,
620 global_opts: self.global_opts,
621 mode: StandardPrintMode {
622 utf8bom: Some(Utf8Bom::WindowsOnly),
623 ..StandardPrintMode::default()
624 },
625 }
626 }
627
628 #[cfg(not(feature = "lt2023_1"))]
637 pub fn line_ending_unix(self) -> Print<StandardPrintMode> {
638 Print {
639 bin: self.bin,
640 global_opts: self.global_opts,
641 mode: StandardPrintMode {
642 line_ending: Some(LineEnding::Unix),
643 ..StandardPrintMode::default()
644 },
645 }
646 }
647
648 #[cfg(not(feature = "lt2023_1"))]
657 pub fn line_ending_win(self) -> Print<StandardPrintMode> {
658 Print {
659 bin: self.bin,
660 global_opts: self.global_opts,
661 mode: StandardPrintMode {
662 line_ending: Some(LineEnding::Win),
663 ..StandardPrintMode::default()
664 },
665 }
666 }
667
668 #[cfg(not(feature = "lt2023_1"))]
677 pub fn line_ending_mac(self) -> Print<StandardPrintMode> {
678 Print {
679 bin: self.bin,
680 global_opts: self.global_opts,
681 mode: StandardPrintMode {
682 line_ending: Some(LineEnding::Mac),
683 ..StandardPrintMode::default()
684 },
685 }
686 }
687
688 #[cfg(not(feature = "lt2026_1"))]
697 pub fn ignore_changeview(self, v: bool) -> Print<StandardPrintMode> {
698 Print {
699 bin: self.bin,
700 global_opts: self.global_opts,
701 mode: StandardPrintMode {
702 ignore_changeview: v,
703 ..StandardPrintMode::default()
704 },
705 }
706 }
707}
708
709impl<M: ExclusiveOption, S, I> ParameterizedSpawn<(S,)> for Print<M>
710where
711 S: IntoIterator<Item = I>,
712 I: AsRef<OsStr>,
713{
714 type Output = Child;
715 type Error = std::io::Error;
716
717 fn spawn_with(&mut self, (files,): (S,)) -> Result<Self::Output, Self::Error> {
721 self.setup_command(&self.bin)
722 .args(files)
723 .stdout(Stdio::piped())
724 .stderr(Stdio::piped())
725 .spawn()
726 }
727}
728
729impl<M: ExclusiveOption> Print<M> {
730 #[cfg_attr(
735 feature = "lt2014_2",
736 doc = "See the [Global Options](GlobalOpts) section."
737 )]
738 #[cfg_attr(
739 all(feature = "lt2015_1", not(feature = "lt2014_2")),
740 doc = "See the [“Global Options”](GlobalOpts) section."
741 )]
742 #[cfg_attr(
743 all(feature = "lt2017_1", not(feature = "lt2015_1")),
744 doc = "See [“Global Options”](GlobalOpts)."
745 )]
746 #[cfg_attr(
747 all(feature = "lt2018_2", not(feature = "lt2017_1")),
748 doc = "See [Global Options](GlobalOpts)."
749 )]
750 #[cfg_attr(not(feature = "lt2018_2"), doc = "See [Global options](GlobalOpts).")]
751 pub fn get_global_opts(&self) -> &GlobalOpts {
752 &self.global_opts
753 }
754
755 #[cfg_attr(
760 feature = "lt2014_2",
761 doc = "See the [Global Options](GlobalOpts) section."
762 )]
763 #[cfg_attr(
764 all(feature = "lt2015_1", not(feature = "lt2014_2")),
765 doc = "See the [“Global Options”](GlobalOpts) section."
766 )]
767 #[cfg_attr(
768 all(feature = "lt2017_1", not(feature = "lt2015_1")),
769 doc = "See [“Global Options”](GlobalOpts)."
770 )]
771 #[cfg_attr(
772 all(feature = "lt2018_2", not(feature = "lt2017_1")),
773 doc = "See [Global Options](GlobalOpts)."
774 )]
775 #[cfg_attr(not(feature = "lt2018_2"), doc = "See [Global options](GlobalOpts).")]
776 pub fn set_global_opts(&mut self, v: GlobalOpts) -> &mut Self {
777 self.global_opts = v;
778 self
779 }
780
781 #[cfg_attr(
786 feature = "lt2014_2",
787 doc = "See the [Global Options](GlobalOpts) section."
788 )]
789 #[cfg_attr(
790 all(feature = "lt2015_1", not(feature = "lt2014_2")),
791 doc = "See the [“Global Options”](GlobalOpts) section."
792 )]
793 #[cfg_attr(
794 all(feature = "lt2017_1", not(feature = "lt2015_1")),
795 doc = "See [“Global Options”](GlobalOpts)."
796 )]
797 #[cfg_attr(
798 all(feature = "lt2018_2", not(feature = "lt2017_1")),
799 doc = "See [Global Options](GlobalOpts)."
800 )]
801 #[cfg_attr(not(feature = "lt2018_2"), doc = "See [Global options](GlobalOpts).")]
802 pub fn global_opts(mut self, v: GlobalOpts) -> Self {
803 self.global_opts = v;
804 self
805 }
806}
807
808impl Print<StandardPrintMode> {
809 pub fn get_all_revisions(&self) -> bool {
816 self.mode.all_revisions
817 }
818
819 pub fn set_all_revisions(&mut self, v: bool) -> &mut Self {
826 self.mode.all_revisions = v;
827 self
828 }
829
830 pub fn all_revisions(mut self, v: bool) -> Self {
837 self.mode.all_revisions = v;
838 self
839 }
840
841 #[cfg_attr(
846 feature = "lt2023_1",
847 doc = "Attempt to print a file stored in an archive depot."
848 )]
849 #[cfg_attr(not(feature = "lt2023_1"), doc = "Print files in archive depots.")]
850 pub fn get_archive_depots(&self) -> bool {
851 self.mode.from_archive_depots
852 }
853
854 #[cfg_attr(
859 feature = "lt2023_1",
860 doc = "Attempt to print a file stored in an archive depot."
861 )]
862 #[cfg_attr(not(feature = "lt2023_1"), doc = "Print files in archive depots.")]
863 pub fn set_archive_depots(&mut self, v: bool) -> &mut Self {
864 self.mode.from_archive_depots = v;
865 self
866 }
867
868 #[cfg_attr(
873 feature = "lt2023_1",
874 doc = "Attempt to print a file stored in an archive depot."
875 )]
876 #[cfg_attr(not(feature = "lt2023_1"), doc = "Print files in archive depots.")]
877 pub fn archive_depots(mut self, v: bool) -> Self {
878 self.mode.from_archive_depots = v;
879 self
880 }
881
882 #[cfg_attr(feature = "lt2022_1", doc = "-k")]
885 #[cfg_attr(not(feature = "lt2022_1"), doc = "-K")]
886 #[cfg_attr(feature = "lt2023_1", doc = "Suppress RCS keyword expansion.")]
888 #[cfg_attr(
889 not(feature = "lt2023_1"),
890 doc = "Suppress RCS keyword expansion. This replaced the `-k` flag in",
891 doc = "2022.1, which is now an alias for `-K` for backwards compatibility."
892 )]
893 pub fn get_suppress_keyword_expansion(&self) -> bool {
894 self.mode.suppress_keyword_expansion
895 }
896
897 #[cfg_attr(feature = "lt2022_1", doc = "-k")]
900 #[cfg_attr(not(feature = "lt2022_1"), doc = "-K")]
901 #[cfg_attr(feature = "lt2023_1", doc = "Suppress RCS keyword expansion.")]
903 #[cfg_attr(
904 not(feature = "lt2023_1"),
905 doc = "Suppress RCS keyword expansion. This replaced the `-k` flag in",
906 doc = "2022.1, which is now an alias for `-K` for backwards compatibility."
907 )]
908 pub fn set_suppress_keyword_expansion(&mut self, v: bool) -> &mut Self {
909 self.mode.suppress_keyword_expansion = v;
910 self
911 }
912
913 #[cfg_attr(feature = "lt2022_1", doc = "-k")]
916 #[cfg_attr(not(feature = "lt2022_1"), doc = "-K")]
917 #[cfg_attr(feature = "lt2023_1", doc = "Suppress RCS keyword expansion.")]
919 #[cfg_attr(
920 not(feature = "lt2023_1"),
921 doc = "Suppress RCS keyword expansion. This replaced the `-k` flag in",
922 doc = "2022.1, which is now an alias for `-K` for backwards compatibility."
923 )]
924 pub fn suppress_keyword_expansion(mut self, v: bool) -> Self {
925 self.mode.suppress_keyword_expansion = v;
926 self
927 }
928
929 #[cfg_attr(feature = "lt2023_1", doc = "-o outfile")]
932 #[cfg_attr(not(feature = "lt2023_1"), doc = "-o localfile")]
933 #[cfg_attr(
935 feature = "lt2018_2",
936 doc = "Redirect output to the specified output file on the local disk,",
937 doc = "preserving the same file type, attributes, and/or permission bits",
938 doc = "as the original file in the depot."
939 )]
940 #[cfg_attr(
941 all(feature = "lt2023_1", not(feature = "lt2018_2")),
942 doc = "Redirect output to the specified output file (`outfile`) on the",
943 doc = "local disk. This preserves the same file type, attributes, and/or",
944 doc = "permission bits as the original file (`FileSpec`) in the depot.",
945 doc = "Multiple files can be written by using wildcards in the",
946 doc = "`localFile` argument that match wildcards in the depot",
947 doc = "(`FileSpec`) argument. For example: To print the contents of a",
948 doc = "directory and directories under that directory, use the `...`",
949 doc = "wildcard: `p4 print -o c:/tmp/main-copy/... //depot/main/...` To",
950 doc = "print all files that match readme.txt or readme.pdf, you might",
951 doc = "specify `p4 print -o readme.* //depot/readme.*`"
952 )]
953 #[cfg_attr(
954 not(feature = "lt2023_1"),
955 doc = "Redirect output to the specified output file (`localfile`) on the",
956 doc = "local disk. This preserves the same file type, attributes, and/or",
957 doc = "permission bits as the original file (`FileSpec`) in the depot.",
958 doc = "Multiple files can be written by using wildcards in the",
959 doc = "`localFile` argument that match wildcards in the depot",
960 doc = "(`FileSpec`) argument. For example: To print the contents of a",
961 doc = "directory and directories under that directory, use the `...`",
962 doc = "wildcard: `p4 print -o c:/tmp/main-copy/... //depot/main/...` To",
963 doc = "print all files that match readme.txt or readme.pdf, you might",
964 doc = "specify `p4 print -o readme.* //depot/readme.*`"
965 )]
966 pub fn get_redirect_output(&self) -> Option<&PathBuf> {
967 self.mode.redirect_output.as_ref()
968 }
969
970 #[cfg_attr(feature = "lt2023_1", doc = "-o outfile")]
973 #[cfg_attr(not(feature = "lt2023_1"), doc = "-o localfile")]
974 #[cfg_attr(
976 feature = "lt2018_2",
977 doc = "Redirect output to the specified output file on the local disk,",
978 doc = "preserving the same file type, attributes, and/or permission bits",
979 doc = "as the original file in the depot."
980 )]
981 #[cfg_attr(
982 all(feature = "lt2023_1", not(feature = "lt2018_2")),
983 doc = "Redirect output to the specified output file (`outfile`) on the",
984 doc = "local disk. This preserves the same file type, attributes, and/or",
985 doc = "permission bits as the original file (`FileSpec`) in the depot.",
986 doc = "Multiple files can be written by using wildcards in the",
987 doc = "`localFile` argument that match wildcards in the depot",
988 doc = "(`FileSpec`) argument. For example: To print the contents of a",
989 doc = "directory and directories under that directory, use the `...`",
990 doc = "wildcard: `p4 print -o c:/tmp/main-copy/... //depot/main/...` To",
991 doc = "print all files that match readme.txt or readme.pdf, you might",
992 doc = "specify `p4 print -o readme.* //depot/readme.*`"
993 )]
994 #[cfg_attr(
995 not(feature = "lt2023_1"),
996 doc = "Redirect output to the specified output file (`localfile`) on the",
997 doc = "local disk. This preserves the same file type, attributes, and/or",
998 doc = "permission bits as the original file (`FileSpec`) in the depot.",
999 doc = "Multiple files can be written by using wildcards in the",
1000 doc = "`localFile` argument that match wildcards in the depot",
1001 doc = "(`FileSpec`) argument. For example: To print the contents of a",
1002 doc = "directory and directories under that directory, use the `...`",
1003 doc = "wildcard: `p4 print -o c:/tmp/main-copy/... //depot/main/...` To",
1004 doc = "print all files that match readme.txt or readme.pdf, you might",
1005 doc = "specify `p4 print -o readme.* //depot/readme.*`"
1006 )]
1007 pub fn set_redirect_output(&mut self, v: impl Into<PathBuf>) -> &mut Self {
1008 self.mode.redirect_output = Some(v.into());
1009 self
1010 }
1011
1012 #[cfg_attr(feature = "lt2023_1", doc = "-o outfile")]
1015 #[cfg_attr(not(feature = "lt2023_1"), doc = "-o localfile")]
1016 #[cfg_attr(
1018 feature = "lt2018_2",
1019 doc = "Redirect output to the specified output file on the local disk,",
1020 doc = "preserving the same file type, attributes, and/or permission bits",
1021 doc = "as the original file in the depot."
1022 )]
1023 #[cfg_attr(
1024 all(feature = "lt2023_1", not(feature = "lt2018_2")),
1025 doc = "Redirect output to the specified output file (`outfile`) on the",
1026 doc = "local disk. This preserves the same file type, attributes, and/or",
1027 doc = "permission bits as the original file (`FileSpec`) in the depot.",
1028 doc = "Multiple files can be written by using wildcards in the",
1029 doc = "`localFile` argument that match wildcards in the depot",
1030 doc = "(`FileSpec`) argument. For example: To print the contents of a",
1031 doc = "directory and directories under that directory, use the `...`",
1032 doc = "wildcard: `p4 print -o c:/tmp/main-copy/... //depot/main/...` To",
1033 doc = "print all files that match readme.txt or readme.pdf, you might",
1034 doc = "specify `p4 print -o readme.* //depot/readme.*`"
1035 )]
1036 #[cfg_attr(
1037 not(feature = "lt2023_1"),
1038 doc = "Redirect output to the specified output file (`localfile`) on the",
1039 doc = "local disk. This preserves the same file type, attributes, and/or",
1040 doc = "permission bits as the original file (`FileSpec`) in the depot.",
1041 doc = "Multiple files can be written by using wildcards in the",
1042 doc = "`localFile` argument that match wildcards in the depot",
1043 doc = "(`FileSpec`) argument. For example: To print the contents of a",
1044 doc = "directory and directories under that directory, use the `...`",
1045 doc = "wildcard: `p4 print -o c:/tmp/main-copy/... //depot/main/...` To",
1046 doc = "print all files that match readme.txt or readme.pdf, you might",
1047 doc = "specify `p4 print -o readme.* //depot/readme.*`"
1048 )]
1049 pub fn redirect_output(mut self, v: impl Into<PathBuf>) -> Self {
1050 self.mode.redirect_output = Some(v.into());
1051 self
1052 }
1053
1054 #[cfg_attr(feature = "lt2018_1", doc = "Perforce.")]
1060 #[cfg_attr(
1061 all(feature = "lt2019_1", not(feature = "lt2018_1")),
1062 doc = "Helix Server."
1063 )]
1064 #[cfg_attr(
1065 all(feature = "lt2021_1", not(feature = "lt2019_1")),
1066 doc = "Helix server."
1067 )]
1068 #[cfg_attr(
1069 all(feature = "lt2024_1", not(feature = "lt2021_1")),
1070 doc = "Helix Server."
1071 )]
1072 #[cfg_attr(
1073 all(feature = "lt2024_2", not(feature = "lt2024_1")),
1074 doc = "Helix Core Server."
1075 )]
1076 #[cfg_attr(not(feature = "lt2024_2"), doc = "P4 Server.")]
1077 pub fn get_quiet_mode(&self) -> bool {
1078 self.mode.quiet_mode
1079 }
1080
1081 #[cfg_attr(feature = "lt2018_1", doc = "Perforce.")]
1087 #[cfg_attr(
1088 all(feature = "lt2019_1", not(feature = "lt2018_1")),
1089 doc = "Helix Server."
1090 )]
1091 #[cfg_attr(
1092 all(feature = "lt2021_1", not(feature = "lt2019_1")),
1093 doc = "Helix server."
1094 )]
1095 #[cfg_attr(
1096 all(feature = "lt2024_1", not(feature = "lt2021_1")),
1097 doc = "Helix Server."
1098 )]
1099 #[cfg_attr(
1100 all(feature = "lt2024_2", not(feature = "lt2024_1")),
1101 doc = "Helix Core Server."
1102 )]
1103 #[cfg_attr(not(feature = "lt2024_2"), doc = "P4 Server.")]
1104 pub fn set_quiet_mode(&mut self, v: bool) -> &mut Self {
1105 self.mode.quiet_mode = v;
1106 self
1107 }
1108
1109 #[cfg_attr(feature = "lt2018_1", doc = "Perforce.")]
1115 #[cfg_attr(
1116 all(feature = "lt2019_1", not(feature = "lt2018_1")),
1117 doc = "Helix Server."
1118 )]
1119 #[cfg_attr(
1120 all(feature = "lt2021_1", not(feature = "lt2019_1")),
1121 doc = "Helix server."
1122 )]
1123 #[cfg_attr(
1124 all(feature = "lt2024_1", not(feature = "lt2021_1")),
1125 doc = "Helix Server."
1126 )]
1127 #[cfg_attr(
1128 all(feature = "lt2024_2", not(feature = "lt2024_1")),
1129 doc = "Helix Core Server."
1130 )]
1131 #[cfg_attr(not(feature = "lt2024_2"), doc = "P4 Server.")]
1132 pub fn quiet_mode(mut self, v: bool) -> Self {
1133 self.mode.quiet_mode = v;
1134 self
1135 }
1136
1137 pub fn get_limit(&self) -> Option<u64> {
1143 self.mode.limit
1144 }
1145
1146 pub fn set_limit(&mut self, v: u64) -> &mut Self {
1152 self.mode.limit = Some(v);
1153 self
1154 }
1155
1156 pub fn limit(mut self, v: u64) -> Self {
1162 self.mode.limit = Some(v);
1163 self
1164 }
1165
1166 #[cfg(not(feature = "lt2022_1"))]
1173 pub fn get_offset(&self) -> Option<u64> {
1174 self.mode.offset
1175 }
1176
1177 #[cfg(not(feature = "lt2022_1"))]
1184 pub fn set_offset(&mut self, v: u64) -> &mut Self {
1185 self.mode.offset = Some(v);
1186 self
1187 }
1188
1189 #[cfg(not(feature = "lt2022_1"))]
1196 pub fn offset(mut self, v: u64) -> Self {
1197 self.mode.offset = Some(v);
1198 self
1199 }
1200
1201 #[cfg(not(feature = "lt2022_1"))]
1209 pub fn get_size(&self) -> Option<u64> {
1210 self.mode.size
1211 }
1212
1213 #[cfg(not(feature = "lt2022_1"))]
1221 pub fn set_size(&mut self, v: u64) -> &mut Self {
1222 self.mode.size = Some(v);
1223 self
1224 }
1225
1226 #[cfg(not(feature = "lt2022_1"))]
1234 pub fn size(mut self, v: u64) -> Self {
1235 self.mode.size = Some(v);
1236 self
1237 }
1238
1239 #[cfg(not(feature = "lt2023_1"))]
1247 pub fn get_charset(&self) -> Option<&str> {
1248 self.mode.charset.as_deref()
1249 }
1250
1251 #[cfg(not(feature = "lt2023_1"))]
1259 pub fn set_charset(&mut self, v: impl Into<String>) -> &mut Self {
1260 self.mode.charset = Some(v.into());
1261 self
1262 }
1263
1264 #[cfg(not(feature = "lt2023_1"))]
1272 pub fn charset(mut self, v: impl Into<String>) -> Self {
1273 self.mode.charset = Some(v.into());
1274 self
1275 }
1276
1277 #[cfg(not(feature = "lt2023_1"))]
1284 pub fn get_utf8bom(&self) -> Option<Utf8Bom> {
1285 self.mode.utf8bom
1286 }
1287
1288 #[cfg(not(feature = "lt2023_1"))]
1297 pub fn set_write_utf8bom(&mut self, v: bool) -> &mut Self {
1298 self.mode.utf8bom = Some(if v { Utf8Bom::Yes } else { Utf8Bom::No });
1299 self
1300 }
1301
1302 #[cfg(not(feature = "lt2023_1"))]
1311 pub fn write_utf8bom(mut self, v: bool) -> Self {
1312 self.mode.utf8bom = Some(if v { Utf8Bom::Yes } else { Utf8Bom::No });
1313 self
1314 }
1315
1316 #[cfg(not(feature = "lt2023_1"))]
1323 pub fn set_write_utf8bom_windows_only(&mut self) -> &mut Self {
1324 self.mode.utf8bom = Some(Utf8Bom::WindowsOnly);
1325 self
1326 }
1327
1328 #[cfg(not(feature = "lt2023_1"))]
1335 pub fn write_utf8bom_windows_only(mut self) -> Self {
1336 self.mode.utf8bom = Some(Utf8Bom::WindowsOnly);
1337 self
1338 }
1339
1340 #[cfg(not(feature = "lt2023_1"))]
1350 pub fn get_line_ending(&self) -> Option<LineEnding> {
1351 self.mode.line_ending
1352 }
1353
1354 #[cfg(not(feature = "lt2023_1"))]
1361 pub fn set_line_ending_unix(&mut self) -> &mut Self {
1362 self.mode.line_ending = Some(LineEnding::Unix);
1363 self
1364 }
1365
1366 #[cfg(not(feature = "lt2023_1"))]
1373 pub fn line_ending_unix(mut self) -> Self {
1374 self.mode.line_ending = Some(LineEnding::Unix);
1375 self
1376 }
1377
1378 #[cfg(not(feature = "lt2023_1"))]
1385 pub fn set_line_ending_win(&mut self) -> &mut Self {
1386 self.mode.line_ending = Some(LineEnding::Win);
1387 self
1388 }
1389
1390 #[cfg(not(feature = "lt2023_1"))]
1397 pub fn line_ending_win(mut self) -> Self {
1398 self.mode.line_ending = Some(LineEnding::Win);
1399 self
1400 }
1401
1402 #[cfg(not(feature = "lt2023_1"))]
1409 pub fn set_line_ending_mac(&mut self) -> &mut Self {
1410 self.mode.line_ending = Some(LineEnding::Mac);
1411 self
1412 }
1413
1414 #[cfg(not(feature = "lt2023_1"))]
1421 pub fn line_ending_mac(mut self) -> Self {
1422 self.mode.line_ending = Some(LineEnding::Mac);
1423 self
1424 }
1425
1426 #[cfg(not(feature = "lt2026_1"))]
1433 pub fn get_ignore_changeview(&self) -> bool {
1434 self.mode.ignore_changeview
1435 }
1436
1437 #[cfg(not(feature = "lt2026_1"))]
1444 pub fn set_ignore_changeview(&mut self, v: bool) -> &mut Self {
1445 self.mode.ignore_changeview = v;
1446 self
1447 }
1448
1449 #[cfg(not(feature = "lt2026_1"))]
1456 pub fn ignore_changeview(mut self, v: bool) -> Self {
1457 self.mode.ignore_changeview = v;
1458 self
1459 }
1460}
1461
1462#[cfg(not(feature = "lt2024_2"))]
1463impl Print<AttributeTraitMode> {
1464 pub fn get_attribute(&self) -> &str {
1471 &self.mode.attribute
1472 }
1473
1474 pub fn set_attribute(&mut self, v: impl Into<String>) -> &mut Self {
1481 self.mode.attribute = v.into();
1482 self
1483 }
1484
1485 pub fn attribute(mut self, v: impl Into<String>) -> Self {
1492 self.mode.attribute = v.into();
1493 self
1494 }
1495
1496 pub fn get_all_revisions(&self) -> bool {
1503 self.mode.all_revisions
1504 }
1505
1506 pub fn set_all_revisions(&mut self, v: bool) -> &mut Self {
1513 self.mode.all_revisions = v;
1514 self
1515 }
1516
1517 pub fn all_revisions(mut self, v: bool) -> Self {
1524 self.mode.all_revisions = v;
1525 self
1526 }
1527
1528 #[cfg_attr(feature = "lt2023_1", doc = "-o outfile")]
1531 #[cfg_attr(not(feature = "lt2023_1"), doc = "-o localfile")]
1532 pub fn get_redirect_output(&self) -> Option<&PathBuf> {
1537 self.mode.redirect_output.as_ref()
1538 }
1539
1540 #[cfg_attr(feature = "lt2023_1", doc = "-o outfile")]
1543 #[cfg_attr(not(feature = "lt2023_1"), doc = "-o localfile")]
1544 pub fn set_redirect_output(&mut self, v: impl Into<PathBuf>) -> &mut Self {
1549 self.mode.redirect_output = Some(v.into());
1550 self
1551 }
1552
1553 #[cfg_attr(feature = "lt2023_1", doc = "-o outfile")]
1556 #[cfg_attr(not(feature = "lt2023_1"), doc = "-o localfile")]
1557 pub fn redirect_output(mut self, v: impl Into<PathBuf>) -> Self {
1562 self.mode.redirect_output = Some(v.into());
1563 self
1564 }
1565
1566 pub fn get_quiet_mode(&self) -> bool {
1573 self.mode.quiet_mode
1574 }
1575
1576 pub fn set_quiet_mode(&mut self, v: bool) -> &mut Self {
1583 self.mode.quiet_mode = v;
1584 self
1585 }
1586
1587 pub fn quiet_mode(mut self, v: bool) -> Self {
1594 self.mode.quiet_mode = v;
1595 self
1596 }
1597
1598 #[cfg(not(feature = "lt2026_1"))]
1605 pub fn get_ignore_changeview(&self) -> bool {
1606 self.mode.ignore_changeview
1607 }
1608
1609 #[cfg(not(feature = "lt2026_1"))]
1616 pub fn set_ignore_changeview(&mut self, v: bool) -> &mut Self {
1617 self.mode.ignore_changeview = v;
1618 self
1619 }
1620
1621 #[cfg(not(feature = "lt2026_1"))]
1628 pub fn ignore_changeview(mut self, v: bool) -> Self {
1629 self.mode.ignore_changeview = v;
1630 self
1631 }
1632}
1633
1634impl<M: ExclusiveOption> SubCommand for Print<M> {
1635 fn name(&self) -> &str {
1636 "print"
1637 }
1638
1639 fn inject_local_args(&self, command: &mut Command) {
1640 self.mode.inject_args(command);
1641 }
1642
1643 fn global_opts(&self) -> Option<&GlobalOpts> {
1644 Some(&self.global_opts)
1645 }
1646}
1647
1648#[cfg(test)]
1649mod tests {
1650 use super::*;
1651 use crate::cmd::args_of;
1652
1653 #[test]
1656 fn without_options() {
1657 let print = Print::new("p4", GlobalOpts::new());
1658
1659 assert_eq!(args_of(&print.setup_command("p4")), ["print"]);
1660 }
1661
1662 #[test]
1663 fn standard_mode_all_options() {
1664 let print = Print::new("p4", GlobalOpts::new())
1665 .all_revisions(true)
1666 .archive_depots(true)
1667 .suppress_keyword_expansion(true)
1668 .redirect_output("out.bin")
1669 .quiet_mode(true)
1670 .limit(5);
1671 #[cfg(not(feature = "lt2022_1"))]
1672 let print = print.offset(100).size(200);
1673 #[cfg(not(feature = "lt2023_1"))]
1674 let print = print.charset("utf8").write_utf8bom(true).line_ending_unix();
1675 #[cfg(not(feature = "lt2026_1"))]
1676 let print = print.ignore_changeview(true);
1677
1678 let mut expected = vec!["print", "-a", "-A"];
1679 #[cfg(feature = "lt2022_1")]
1680 expected.push("-k");
1681 #[cfg(not(feature = "lt2022_1"))]
1682 expected.push("-K");
1683 expected.extend(["-o", "out.bin", "-q", "-m", "5"]);
1684 #[cfg(not(feature = "lt2022_1"))]
1685 expected.extend(["--offset", "100", "--size", "200"]);
1686 #[cfg(not(feature = "lt2023_1"))]
1687 expected.extend(["-Q", "utf8", "-B", "1", "-L", "unix"]);
1688 #[cfg(not(feature = "lt2026_1"))]
1689 expected.push("--ignore-changeview");
1690
1691 assert_eq!(args_of(&print.setup_command("p4")), expected);
1692 }
1693
1694 #[test]
1695 fn standard_mode_set_style() {
1696 let mut print = Print::new("p4", GlobalOpts::new()).limit(5);
1697 print.set_all_revisions(true).set_quiet_mode(true);
1698 #[cfg(not(feature = "lt2022_1"))]
1699 print.set_offset(100).set_size(200);
1700
1701 let expected = {
1702 #[cfg_attr(feature = "lt2022_1", allow(unused_mut))]
1703 let mut v = vec!["print", "-a", "-q", "-m", "5"];
1704 #[cfg(not(feature = "lt2022_1"))]
1705 v.extend(["--offset", "100", "--size", "200"]);
1706 v
1707 };
1708
1709 assert_eq!(args_of(&print.setup_command("p4")), expected);
1710 }
1711
1712 #[test]
1713 fn unload_depot_mode() {
1714 let print = Print::new("p4", GlobalOpts::new()).from_unload_depot();
1715
1716 assert_eq!(args_of(&print.setup_command("p4")), ["print", "-U"]);
1717 }
1718
1719 #[cfg(not(feature = "lt2023_1"))]
1720 #[test]
1721 fn line_ending_is_passed_as_separate_args() {
1722 let print = Print::new("p4", GlobalOpts::new()).line_ending_win();
1723
1724 assert_eq!(print.get_line_ending(), Some(LineEnding::Win));
1725 assert_eq!(args_of(&print.setup_command("p4")), ["print", "-L", "win"]);
1726 }
1727
1728 #[cfg(not(feature = "lt2023_1"))]
1729 #[test]
1730 fn write_utf8bom_bool() {
1731 let yes = Print::new("p4", GlobalOpts::new()).write_utf8bom(true);
1732 assert_eq!(yes.get_utf8bom(), Some(Utf8Bom::Yes));
1733 assert_eq!(args_of(&yes.setup_command("p4")), ["print", "-B", "1"]);
1734
1735 let no = Print::new("p4", GlobalOpts::new()).write_utf8bom(false);
1736 assert_eq!(no.get_utf8bom(), Some(Utf8Bom::No));
1737 assert_eq!(args_of(&no.setup_command("p4")), ["print", "-B", "0"]);
1738 }
1739
1740 #[cfg(not(feature = "lt2023_1"))]
1741 #[test]
1742 fn write_utf8bom_windows_only() {
1743 let print = Print::new("p4", GlobalOpts::new()).write_utf8bom_windows_only();
1744
1745 assert_eq!(print.get_utf8bom(), Some(Utf8Bom::WindowsOnly));
1746 assert_eq!(args_of(&print.setup_command("p4")), ["print", "-B", "2"]);
1747 }
1748
1749 #[cfg(not(feature = "lt2023_1"))]
1750 #[test]
1751 fn utf8bom_set_style_can_replace() {
1752 let mut print = Print::new("p4", GlobalOpts::new()).write_utf8bom(true);
1753 print.set_write_utf8bom(false);
1754 assert_eq!(print.get_utf8bom(), Some(Utf8Bom::No));
1755
1756 print.set_write_utf8bom_windows_only();
1757 assert_eq!(print.get_utf8bom(), Some(Utf8Bom::WindowsOnly));
1758 assert_eq!(args_of(&print.setup_command("p4")), ["print", "-B", "2"]);
1759 }
1760
1761 #[cfg(not(feature = "lt2024_2"))]
1762 #[test]
1763 fn attribute_trait_mode() {
1764 let print = Print::new("p4", GlobalOpts::new()).extract_attribute("desc");
1765
1766 assert_eq!(print.get_attribute(), "desc");
1767 assert_eq!(args_of(&print.setup_command("p4")), ["print", "-T", "desc"]);
1768 }
1769
1770 #[cfg(not(feature = "lt2024_2"))]
1771 #[test]
1772 fn attribute_trait_mode_with_allowed_options() {
1773 let print = Print::new("p4", GlobalOpts::new())
1774 .extract_attribute("desc")
1775 .all_revisions(true)
1776 .quiet_mode(true)
1777 .redirect_output("out.bin");
1778 #[cfg(not(feature = "lt2026_1"))]
1779 let print = print.ignore_changeview(true);
1780
1781 let mut expected = vec!["print", "-T", "desc", "-a", "-o", "out.bin", "-q"];
1782 #[cfg(not(feature = "lt2026_1"))]
1783 expected.push("--ignore-changeview");
1784
1785 assert_eq!(args_of(&print.setup_command("p4")), expected);
1786 }
1787
1788 #[cfg(not(feature = "lt2024_2"))]
1789 #[test]
1790 fn attribute_name_can_be_replaced() {
1791 let mut print = Print::new("p4", GlobalOpts::new()).extract_attribute("old");
1792 print.set_attribute("new");
1793
1794 assert_eq!(print.get_attribute(), "new");
1795 assert_eq!(args_of(&print.setup_command("p4")), ["print", "-T", "new"]);
1796 }
1797
1798 #[cfg(not(feature = "lt2026_1"))]
1799 #[test]
1800 fn ignore_changeview_standard_mode() {
1801 let print = Print::new("p4", GlobalOpts::new()).ignore_changeview(true);
1802
1803 assert!(print.get_ignore_changeview());
1804 assert_eq!(
1805 args_of(&print.setup_command("p4")),
1806 ["print", "--ignore-changeview"]
1807 );
1808 }
1809}