1use std::ffi::OsStr;
2use std::path::PathBuf;
3use std::process::{Child, Command, Stdio};
4
5use super::{ExclusiveOption, SubCommand, Unselected};
6
7use crate::global::GlobalOpts;
8use crate::spawn::{ParameterizedSpawn, SpawnExt};
9
10#[cfg_attr(
19 not(feature = "lt2015_1"),
20 doc = " [`setldapusers`](Self::setldapusers),"
21)]
22#[cfg_attr(
23 not(feature = "lt2018_1"),
24 doc = " [`end_journal`](Self::end_journal),"
25)]
26#[cfg_attr(
27 not(feature = "lt2023_1"),
28 doc = " [`sysinfo`](Self::sysinfo), [`resource_monitor`](Self::resource_monitor),"
29)]
30#[cfg_attr(
31 not(feature = "lt2025_2"),
32 doc = " [`replica_filter_reconcile`](Self::replica_filter_reconcile),"
33)]
34#[derive(Debug, Clone, Default)]
36pub struct AdminEntry {
37 bin: PathBuf,
38
39 global_opts: GlobalOpts,
40}
41
42impl AdminEntry {
43 pub fn new(bin: impl Into<PathBuf>, global_opts: GlobalOpts) -> Self {
47 Self {
48 bin: bin.into(),
49 global_opts,
50 }
51 }
52
53 pub fn checkpoint(self) -> Admin<CheckPoint<Unselected>> {
59 Admin::new(self.bin, self.global_opts, CheckPoint::default())
60 }
61
62 pub fn journal(self) -> Admin<Journal> {
67 Admin::new(self.bin, self.global_opts, Journal::default())
68 }
69
70 pub fn stop(self) -> Admin<Stop> {
75 Admin::new(self.bin, self.global_opts, Stop)
76 }
77
78 pub fn restart(self) -> Admin<Restart> {
83 Admin::new(self.bin, self.global_opts, Restart)
84 }
85
86 pub fn updatespecdepot(self) -> Admin<UpdateSpecDepot<Unselected>> {
93 Admin::new(self.bin, self.global_opts, UpdateSpecDepot::default())
94 }
95
96 pub fn resetpassword(self) -> Admin<ResetPassword<Unselected>> {
101 Admin::new(self.bin, self.global_opts, ResetPassword::default())
102 }
103
104 #[cfg(not(feature = "lt2015_1"))]
111 pub fn setldapusers(self) -> Admin<SetLdapUsers> {
112 Admin::new(self.bin, self.global_opts, SetLdapUsers)
113 }
114
115 #[cfg(not(feature = "lt2018_1"))]
122 pub fn end_journal(self) -> Admin<EndJournal> {
123 Admin::new(self.bin, self.global_opts, EndJournal)
124 }
125
126 #[cfg_attr(
132 all(not(feature = "lt2023_1"), feature = "lt2024_2"),
133 doc = "Helix Core Server."
134 )]
135 #[cfg_attr(not(feature = "lt2024_2"), doc = "P4 Server.")]
136 #[cfg(not(feature = "lt2023_1"))]
137 pub fn sysinfo(self) -> Admin<SysInfo> {
138 Admin::new(self.bin, self.global_opts, SysInfo)
139 }
140
141 #[cfg_attr(
146 all(not(feature = "lt2023_1"), feature = "lt2024_1"),
147 doc = "Helix Core Server",
148 doc = "Administrator Guide."
149 )]
150 #[cfg_attr(
151 all(not(feature = "lt2024_1"), feature = "lt2024_2"),
152 doc = "the Helix Core Server Administrator Guide."
153 )]
154 #[cfg_attr(
155 not(feature = "lt2024_2"),
156 doc = "P4 Server",
157 doc = "Administration Documentation."
158 )]
159 #[cfg(not(feature = "lt2023_1"))]
160 pub fn resource_monitor(self) -> Admin<ResourceMonitor> {
161 Admin::new(self.bin, self.global_opts, ResourceMonitor)
162 }
163
164 #[cfg(not(feature = "lt2025_2"))]
171 pub fn replica_filter_reconcile(self) -> Admin<ReplicaFilterReconcile<Unselected>> {
172 Admin::new(
173 self.bin,
174 self.global_opts,
175 ReplicaFilterReconcile::default(),
176 )
177 }
178}
179
180#[derive(Debug, Clone, Default)]
182pub struct Admin<T: SubCommand> {
183 bin: PathBuf,
184
185 global_opts: GlobalOpts,
186
187 sub_command: T,
188}
189
190impl<T: SubCommand> SubCommand for Admin<T> {
191 fn name(&self) -> &str {
192 "admin"
193 }
194
195 fn inject_local_args(&self, command: &mut Command) {
196 self.sub_command.inject_args(command);
197 }
198
199 fn global_opts(&self) -> Option<&GlobalOpts> {
200 Some(&self.global_opts)
201 }
202}
203
204impl<T: SubCommand> Admin<T> {
211 fn spawn_piped(&mut self) -> Result<Child, std::io::Error> {
215 self.setup_command(&self.bin)
216 .stdout(Stdio::piped())
217 .stderr(Stdio::piped())
218 .spawn()
219 }
220}
221
222impl ParameterizedSpawn for Admin<Stop> {
223 type Input<'a> = ();
224 type Output<'a> = Child;
225 type Error = std::io::Error;
226
227 fn spawn_with<'a>(&mut self, (): Self::Input<'a>) -> Result<Self::Output<'a>, Self::Error> {
231 self.spawn_piped()
232 }
233}
234
235impl ParameterizedSpawn for Admin<Restart> {
236 type Input<'a> = ();
237 type Output<'a> = Child;
238 type Error = std::io::Error;
239
240 fn spawn_with<'a>(&mut self, (): Self::Input<'a>) -> Result<Self::Output<'a>, Self::Error> {
244 self.spawn_piped()
245 }
246}
247
248impl<S: ExclusiveOption> ParameterizedSpawn for Admin<UpdateSpecDepot<S>> {
249 type Input<'a> = ();
250 type Output<'a> = Child;
251 type Error = std::io::Error;
252
253 fn spawn_with<'a>(&mut self, (): Self::Input<'a>) -> Result<Self::Output<'a>, Self::Error> {
257 self.spawn_piped()
258 }
259}
260
261impl<T: ExclusiveOption> ParameterizedSpawn for Admin<ResetPassword<T>> {
262 type Input<'a> = ();
263 type Output<'a> = Child;
264 type Error = std::io::Error;
265
266 fn spawn_with<'a>(&mut self, (): Self::Input<'a>) -> Result<Self::Output<'a>, Self::Error> {
270 self.spawn_piped()
271 }
272}
273
274#[cfg(not(feature = "lt2015_1"))]
275impl ParameterizedSpawn for Admin<SetLdapUsers> {
276 type Input<'a> = ();
277 type Output<'a> = Child;
278 type Error = std::io::Error;
279
280 fn spawn_with<'a>(&mut self, (): Self::Input<'a>) -> Result<Self::Output<'a>, Self::Error> {
284 self.spawn_piped()
285 }
286}
287
288#[cfg(not(feature = "lt2018_1"))]
289impl ParameterizedSpawn for Admin<EndJournal> {
290 type Input<'a> = ();
291 type Output<'a> = Child;
292 type Error = std::io::Error;
293
294 fn spawn_with<'a>(&mut self, (): Self::Input<'a>) -> Result<Self::Output<'a>, Self::Error> {
298 self.spawn_piped()
299 }
300}
301
302#[cfg(not(feature = "lt2023_1"))]
303impl ParameterizedSpawn for Admin<SysInfo> {
304 type Input<'a> = ();
305 type Output<'a> = Child;
306 type Error = std::io::Error;
307
308 fn spawn_with<'a>(&mut self, (): Self::Input<'a>) -> Result<Self::Output<'a>, Self::Error> {
312 self.spawn_piped()
313 }
314}
315
316#[cfg(not(feature = "lt2023_1"))]
317impl ParameterizedSpawn for Admin<ResourceMonitor> {
318 type Input<'a> = ();
319 type Output<'a> = Child;
320 type Error = std::io::Error;
321
322 fn spawn_with<'a>(&mut self, (): Self::Input<'a>) -> Result<Self::Output<'a>, Self::Error> {
326 self.spawn_piped()
327 }
328}
329
330impl<T: SubCommand> Admin<T> {
331 pub fn new(bin: impl Into<PathBuf>, global_opts: GlobalOpts, sub_command: T) -> Self {
335 Self {
336 bin: bin.into(),
337 global_opts,
338 sub_command,
339 }
340 }
341
342 #[cfg_attr(
347 feature = "lt2014_2",
348 doc = "See the [Global Options](GlobalOpts) section."
349 )]
350 #[cfg_attr(
351 all(feature = "lt2015_1", not(feature = "lt2014_2")),
352 doc = "See the [“Global Options”](GlobalOpts) section."
353 )]
354 #[cfg_attr(
355 all(feature = "lt2017_1", not(feature = "lt2015_1")),
356 doc = "See [“Global Options”](GlobalOpts)."
357 )]
358 #[cfg_attr(
359 all(feature = "lt2018_2", not(feature = "lt2017_1")),
360 doc = "See [Global Options](GlobalOpts)."
361 )]
362 #[cfg_attr(not(feature = "lt2018_2"), doc = "See [Global options](GlobalOpts).")]
363 pub fn get_global_opts(&self) -> &GlobalOpts {
364 &self.global_opts
365 }
366
367 #[cfg_attr(
372 feature = "lt2014_2",
373 doc = "See the [Global Options](GlobalOpts) section."
374 )]
375 #[cfg_attr(
376 all(feature = "lt2015_1", not(feature = "lt2014_2")),
377 doc = "See the [“Global Options”](GlobalOpts) section."
378 )]
379 #[cfg_attr(
380 all(feature = "lt2017_1", not(feature = "lt2015_1")),
381 doc = "See [“Global Options”](GlobalOpts)."
382 )]
383 #[cfg_attr(
384 all(feature = "lt2018_2", not(feature = "lt2017_1")),
385 doc = "See [Global Options](GlobalOpts)."
386 )]
387 #[cfg_attr(not(feature = "lt2018_2"), doc = "See [Global options](GlobalOpts).")]
388 pub fn set_global_opts(&mut self, v: GlobalOpts) -> &mut Self {
389 self.global_opts = v;
390 self
391 }
392
393 #[cfg_attr(
398 feature = "lt2014_2",
399 doc = "See the [Global Options](GlobalOpts) section."
400 )]
401 #[cfg_attr(
402 all(feature = "lt2015_1", not(feature = "lt2014_2")),
403 doc = "See the [“Global Options”](GlobalOpts) section."
404 )]
405 #[cfg_attr(
406 all(feature = "lt2017_1", not(feature = "lt2015_1")),
407 doc = "See [“Global Options”](GlobalOpts)."
408 )]
409 #[cfg_attr(
410 all(feature = "lt2018_2", not(feature = "lt2017_1")),
411 doc = "See [Global Options](GlobalOpts)."
412 )]
413 #[cfg_attr(not(feature = "lt2018_2"), doc = "See [Global options](GlobalOpts).")]
414 pub fn global_opts(mut self, v: GlobalOpts) -> Self {
415 self.global_opts = v;
416 self
417 }
418}
419
420pub mod compression {
421 #[derive(Debug, Clone, Copy, Default)]
423 pub struct Both;
424
425 #[derive(Debug, Clone, Copy, Default)]
428 pub struct CheckPointOnly;
429}
430
431impl ExclusiveOption for compression::Both {
432 fn inject_args(&self, command: &mut Command) {
433 command.arg("-z");
434 }
435}
436
437impl ExclusiveOption for compression::CheckPointOnly {
438 fn inject_args(&self, command: &mut Command) {
439 command.arg("-Z");
440 }
441}
442
443#[cfg_attr(
444 feature = "lt2022_2",
445 doc = "`p4 admin checkpoint [-z | -Z] [prefix]`: take a checkpoint."
446)]
447#[cfg_attr(
448 all(feature = "lt2023_1", not(feature = "lt2022_2")),
449 doc = "`p4 admin checkpoint [[-z | -Z]] [prefix]`: take a checkpoint."
450)]
451#[cfg_attr(
452 not(feature = "lt2023_1"),
453 doc = "`p4 admin checkpoint [-z | -Z] [-p [-N threads] [-m]] [prefix]`: take a checkpoint."
454)]
455#[derive(Debug, Clone, Default)]
458pub struct CheckPoint<C = Unselected> {
459 compression: C,
460
461 #[cfg(not(feature = "lt2023_1"))]
463 parallel: bool,
464
465 #[cfg(not(feature = "lt2023_1"))]
467 threads: Option<u32>,
468
469 #[cfg(not(feature = "lt2023_1"))]
471 multiple_files: bool,
472}
473
474impl<C: ExclusiveOption> SubCommand for CheckPoint<C> {
475 fn name(&self) -> &str {
476 "checkpoint"
477 }
478
479 fn inject_local_args(&self, command: &mut Command) {
480 self.compression.inject_args(command);
481
482 #[cfg(not(feature = "lt2023_1"))]
483 {
484 if self.parallel {
485 command.arg("-p");
486 }
487 if let Some(threads) = self.threads {
488 command.arg("-N").arg(threads.to_string());
489 }
490 if self.multiple_files {
491 command.arg("-m");
492 }
493 }
494 }
495}
496
497impl<C: ExclusiveOption> ParameterizedSpawn for Admin<CheckPoint<C>> {
498 type Input<'a> = &'a OsStr;
499 type Output<'a> = Child;
500 type Error = std::io::Error;
501
502 fn spawn_with<'a>(&mut self, prefix: Self::Input<'a>) -> Result<Self::Output<'a>, Self::Error> {
509 self.setup_command(&self.bin)
510 .arg(prefix)
511 .stdout(Stdio::piped())
512 .stderr(Stdio::piped())
513 .spawn()
514 }
515}
516
517impl<C: ExclusiveOption> SpawnExt for Admin<CheckPoint<C>> {
518 fn spawn<'a>(&mut self) -> Result<Self::Output<'a>, Self::Error> {
519 self.setup_command(&self.bin)
520 .stdout(Stdio::piped())
521 .stderr(Stdio::piped())
522 .spawn()
523 }
524}
525
526impl<C: ExclusiveOption> Admin<CheckPoint<C>> {
527 #[cfg(not(feature = "lt2023_1"))]
533 pub fn get_parallel(&self) -> bool {
534 self.sub_command.parallel
535 }
536
537 #[cfg(not(feature = "lt2023_1"))]
543 pub fn set_parallel(&mut self, parallel: bool) -> &mut Self {
544 self.sub_command.parallel = parallel;
545 self
546 }
547
548 #[cfg(not(feature = "lt2023_1"))]
554 pub fn parallel(mut self, parallel: bool) -> Self {
555 self.sub_command.parallel = parallel;
556 self
557 }
558
559 #[cfg(not(feature = "lt2023_1"))]
565 pub fn get_threads(&self) -> Option<&u32> {
566 self.sub_command.threads.as_ref()
567 }
568
569 #[cfg(not(feature = "lt2023_1"))]
575 pub fn set_threads(&mut self, threads: u32) -> &mut Self {
576 self.sub_command.threads = Some(threads);
577 self
578 }
579
580 #[cfg(not(feature = "lt2023_1"))]
586 pub fn threads(mut self, threads: u32) -> Self {
587 self.sub_command.threads = Some(threads);
588 self
589 }
590
591 #[cfg_attr(
599 all(not(feature = "lt2023_1"), feature = "lt2024_1"),
600 doc = "in Helix Core",
601 doc = "Server Administrator Guide. See also checkpoint examples."
602 )]
603 #[cfg_attr(
604 all(not(feature = "lt2024_1"), feature = "lt2024_2"),
605 doc = "in the Helix",
606 doc = "Core Server Administrator Guide. See also checkpoint examples."
607 )]
608 #[cfg_attr(
609 all(not(feature = "lt2024_2"), feature = "lt2025_1"),
610 doc = "in the P4",
611 doc = "Server Administration Documentation. See also checkpoint examples."
612 )]
613 #[cfg_attr(
614 not(feature = "lt2025_1"),
615 doc = "in the P4",
616 doc = "Server Administration Documentation. See also Checkpoint examples."
617 )]
618 #[cfg(not(feature = "lt2023_1"))]
619 pub fn get_multiple_files(&self) -> bool {
620 self.sub_command.multiple_files
621 }
622
623 #[cfg_attr(
631 all(not(feature = "lt2023_1"), feature = "lt2024_1"),
632 doc = "in Helix Core",
633 doc = "Server Administrator Guide. See also checkpoint examples."
634 )]
635 #[cfg_attr(
636 all(not(feature = "lt2024_1"), feature = "lt2024_2"),
637 doc = "in the Helix",
638 doc = "Core Server Administrator Guide. See also checkpoint examples."
639 )]
640 #[cfg_attr(
641 all(not(feature = "lt2024_2"), feature = "lt2025_1"),
642 doc = "in the P4",
643 doc = "Server Administration Documentation. See also checkpoint examples."
644 )]
645 #[cfg_attr(
646 not(feature = "lt2025_1"),
647 doc = "in the P4",
648 doc = "Server Administration Documentation. See also Checkpoint examples."
649 )]
650 #[cfg(not(feature = "lt2023_1"))]
651 pub fn set_multiple_files(&mut self, multiple_files: bool) -> &mut Self {
652 self.sub_command.multiple_files = multiple_files;
653 self
654 }
655
656 #[cfg_attr(
664 all(not(feature = "lt2023_1"), feature = "lt2024_1"),
665 doc = "in Helix Core",
666 doc = "Server Administrator Guide. See also checkpoint examples."
667 )]
668 #[cfg_attr(
669 all(not(feature = "lt2024_1"), feature = "lt2024_2"),
670 doc = "in the Helix",
671 doc = "Core Server Administrator Guide. See also checkpoint examples."
672 )]
673 #[cfg_attr(
674 all(not(feature = "lt2024_2"), feature = "lt2025_1"),
675 doc = "in the P4",
676 doc = "Server Administration Documentation. See also checkpoint examples."
677 )]
678 #[cfg_attr(
679 not(feature = "lt2025_1"),
680 doc = "in the P4",
681 doc = "Server Administration Documentation. See also Checkpoint examples."
682 )]
683 #[cfg(not(feature = "lt2023_1"))]
684 pub fn multiple_files(mut self, multiple_files: bool) -> Self {
685 self.sub_command.multiple_files = multiple_files;
686 self
687 }
688}
689
690impl Admin<CheckPoint<Unselected>> {
691 #[cfg_attr(
696 feature = "lt2022_2",
697 doc = "For `p4 admin checkpoint` and `p4 admin journal`, save the checkpoint",
698 doc = "and saved journal file in compressed (gzip) format, appending the `.gz`",
699 doc = "suffix to the files."
700 )]
701 #[cfg_attr(
702 all(feature = "lt2023_1", not(feature = "lt2022_2")),
703 doc = "For `p4 admin checkpoint -z` and `p4 admin journal -z`, save the",
704 doc = "checkpoint and journal file in compressed format. The `.gz` suffix is",
705 doc = "appended to compressed journals and checkpoint files, which are in",
706 doc = "gzip format. If you do not specify `-z` or `-Z`, no compression occurs."
707 )]
708 #[cfg_attr(
709 not(feature = "lt2023_1"),
710 doc = "Save the checkpoint and journal file in compressed format. The `.gz`",
711 doc = "suffix is appended to compressed journals and checkpoint files, which",
712 doc = "are in gzip format. If you do not specify `-z` or `-Z`, no compression",
713 doc = "occurs."
714 )]
715 pub fn compress_both(self) -> Admin<CheckPoint<compression::Both>> {
716 Admin {
717 bin: self.bin,
718 global_opts: self.global_opts,
719 sub_command: CheckPoint::<compression::Both> {
720 compression: compression::Both,
721 #[cfg(not(feature = "lt2023_1"))]
722 parallel: self.sub_command.parallel,
723 #[cfg(not(feature = "lt2023_1"))]
724 threads: self.sub_command.threads,
725 #[cfg(not(feature = "lt2023_1"))]
726 multiple_files: self.sub_command.multiple_files,
727 },
728 }
729 }
730
731 #[cfg_attr(
736 feature = "lt2017_2",
737 doc = "For `p4 admin checkpoint` and `p4 admin journal`, save the checkpoint",
738 doc = "in compressed (gzip) format, appending the `.gz` suffix to the file, but",
739 doc = "leave the journal uncompressed for use by replica servers."
740 )]
741 #[cfg_attr(
742 all(feature = "lt2022_2", not(feature = "lt2017_2")),
743 doc = "For `p4 admin checkpoint`, save the checkpoint in compressed (gzip)",
744 doc = "format, appending the `.gz` suffix to the file, but leave the journal",
745 doc = "uncompressed for use by replica servers."
746 )]
747 #[cfg_attr(
748 all(feature = "lt2023_1", not(feature = "lt2022_2")),
749 doc = "For `p4 admin checkpoint -Z`, save the checkpoint in compressed format,",
750 doc = "but leave the journal uncompressed for use by replica servers."
751 )]
752 #[cfg_attr(
753 not(feature = "lt2023_1"),
754 doc = "For `p4 admin checkpoint -Z`, save the checkpoint in compressed format,",
755 doc = "but leave the journal uncompressed for use by replica servers. The",
756 doc = "`.gz` suffix is appended to compressed journals and checkpoint files,",
757 doc = "which are in gzip format. If you do not specify `-z` or `-Z`, no",
758 doc = "compression occurs."
759 )]
760 pub fn compress_checkpoint_only(self) -> Admin<CheckPoint<compression::CheckPointOnly>> {
761 Admin {
762 bin: self.bin,
763 global_opts: self.global_opts,
764 sub_command: CheckPoint::<compression::CheckPointOnly> {
765 compression: compression::CheckPointOnly,
766 #[cfg(not(feature = "lt2023_1"))]
767 parallel: self.sub_command.parallel,
768 #[cfg(not(feature = "lt2023_1"))]
769 threads: self.sub_command.threads,
770 #[cfg(not(feature = "lt2023_1"))]
771 multiple_files: self.sub_command.multiple_files,
772 },
773 }
774 }
775}
776
777#[derive(Debug, Clone, Default)]
779pub struct Journal {
780 gzip: bool,
781}
782
783impl SubCommand for Journal {
784 fn name(&self) -> &str {
785 "journal"
786 }
787
788 fn inject_local_args(&self, command: &mut Command) {
789 if self.gzip {
790 command.arg("-z");
791 }
792 }
793}
794
795impl ParameterizedSpawn for Admin<Journal> {
796 type Input<'a> = &'a OsStr;
797 type Output<'a> = Child;
798 type Error = std::io::Error;
799
800 fn spawn_with<'a>(&mut self, prefix: Self::Input<'a>) -> Result<Self::Output<'a>, Self::Error> {
807 self.setup_command(&self.bin)
808 .arg(prefix)
809 .stdout(Stdio::piped())
810 .stderr(Stdio::piped())
811 .spawn()
812 }
813}
814
815impl SpawnExt for Admin<Journal> {
816 fn spawn<'a>(&mut self) -> Result<Self::Output<'a>, Self::Error> {
817 self.setup_command(&self.bin)
818 .stdout(Stdio::piped())
819 .stderr(Stdio::piped())
820 .spawn()
821 }
822}
823
824impl Admin<Journal> {
825 #[cfg_attr(
830 feature = "lt2022_2",
831 doc = "For `p4 admin checkpoint` and `p4 admin journal`, save the checkpoint",
832 doc = "and saved journal file in compressed (gzip) format, appending the `.gz`",
833 doc = "suffix to the files."
834 )]
835 #[cfg_attr(
836 all(feature = "lt2023_1", not(feature = "lt2022_2")),
837 doc = "For `p4 admin checkpoint -z` and `p4 admin journal -z`, save the",
838 doc = "checkpoint and journal file in compressed format. The `.gz` suffix is",
839 doc = "appended to compressed journals and checkpoint files, which are in",
840 doc = "gzip format. If you do not specify `-z` or `-Z`, no compression occurs."
841 )]
842 #[cfg_attr(
843 not(feature = "lt2023_1"),
844 doc = "Save the journal file in compressed format. The `.gz` suffix is",
845 doc = "appended to compressed journals and checkpoint files, which are in",
846 doc = "gzip format. If you do not specify `-z`, no compression occurs."
847 )]
848 pub fn get_gzip(&self) -> bool {
849 self.sub_command.gzip
850 }
851
852 #[cfg_attr(
857 feature = "lt2022_2",
858 doc = "For `p4 admin checkpoint` and `p4 admin journal`, save the checkpoint",
859 doc = "and saved journal file in compressed (gzip) format, appending the `.gz`",
860 doc = "suffix to the files."
861 )]
862 #[cfg_attr(
863 all(feature = "lt2023_1", not(feature = "lt2022_2")),
864 doc = "For `p4 admin checkpoint -z` and `p4 admin journal -z`, save the",
865 doc = "checkpoint and journal file in compressed format. The `.gz` suffix is",
866 doc = "appended to compressed journals and checkpoint files, which are in",
867 doc = "gzip format. If you do not specify `-z` or `-Z`, no compression occurs."
868 )]
869 #[cfg_attr(
870 not(feature = "lt2023_1"),
871 doc = "Save the journal file in compressed format. The `.gz` suffix is",
872 doc = "appended to compressed journals and checkpoint files, which are in",
873 doc = "gzip format. If you do not specify `-z`, no compression occurs."
874 )]
875 pub fn set_gzip(&mut self, gzip: bool) -> &mut Self {
876 self.sub_command.gzip = gzip;
877 self
878 }
879
880 #[cfg_attr(
885 feature = "lt2022_2",
886 doc = "For `p4 admin checkpoint` and `p4 admin journal`, save the checkpoint",
887 doc = "and saved journal file in compressed (gzip) format, appending the `.gz`",
888 doc = "suffix to the files."
889 )]
890 #[cfg_attr(
891 all(feature = "lt2023_1", not(feature = "lt2022_2")),
892 doc = "For `p4 admin checkpoint -z` and `p4 admin journal -z`, save the",
893 doc = "checkpoint and journal file in compressed format. The `.gz` suffix is",
894 doc = "appended to compressed journals and checkpoint files, which are in",
895 doc = "gzip format. If you do not specify `-z` or `-Z`, no compression occurs."
896 )]
897 #[cfg_attr(
898 not(feature = "lt2023_1"),
899 doc = "Save the journal file in compressed format. The `.gz` suffix is",
900 doc = "appended to compressed journals and checkpoint files, which are in",
901 doc = "gzip format. If you do not specify `-z`, no compression occurs."
902 )]
903 pub fn gzip(mut self, gzip: bool) -> Self {
904 self.sub_command.gzip = gzip;
905 self
906 }
907}
908
909#[derive(Debug, Clone, Default)]
911pub struct Stop;
912
913impl SubCommand for Stop {
914 fn name(&self) -> &str {
915 "stop"
916 }
917
918 fn inject_local_args(&self, _: &mut Command) {}
919}
920
921#[derive(Debug, Clone, Default)]
923pub struct Restart;
924
925impl SubCommand for Restart {
926 fn name(&self) -> &str {
927 "restart"
928 }
929
930 fn inject_local_args(&self, _: &mut Command) {}
931}
932
933#[derive(Debug, Clone)]
935pub enum SpecifiedType {
936 Client,
937 Depot,
938 #[cfg(not(feature = "lt2018_1"))]
940 Repo,
941 Branch,
942 Label,
943 TypeMap,
944 Group,
945 User,
946 Job,
947 #[cfg(not(feature = "lt2016_1"))]
949 Stream,
950 #[cfg(not(feature = "lt2016_1"))]
952 Triggers,
953 #[cfg(not(feature = "lt2016_1"))]
955 Protect,
956 #[cfg(not(feature = "lt2016_1"))]
958 Server,
959 #[cfg(not(feature = "lt2016_1"))]
961 License,
962 #[cfg(not(feature = "lt2016_1"))]
964 JobSpec,
965}
966
967impl SpecifiedType {
968 pub(crate) fn to_str(&self) -> &str {
970 match self {
971 Self::Client => "client",
972 Self::Depot => "depot",
973 #[cfg(not(feature = "lt2018_1"))]
974 Self::Repo => "repo",
975 Self::Branch => "branch",
976 Self::Label => "label",
977 Self::TypeMap => "typemap",
978 Self::Group => "group",
979 Self::User => "user",
980 Self::Job => "job",
981 #[cfg(not(feature = "lt2016_1"))]
982 Self::Stream => "stream",
983 #[cfg(not(feature = "lt2016_1"))]
984 Self::Triggers => "triggers",
985 #[cfg(not(feature = "lt2016_1"))]
986 Self::Protect => "protect",
987 #[cfg(not(feature = "lt2016_1"))]
988 Self::Server => "server",
989 #[cfg(not(feature = "lt2016_1"))]
990 Self::License => "license",
991 #[cfg(not(feature = "lt2016_1"))]
992 Self::JobSpec => "jobspec",
993 }
994 }
995}
996
997pub mod spec {
1000 use super::SpecifiedType;
1001
1002 #[derive(Debug, Clone, Copy, Default)]
1004 pub struct All;
1005
1006 #[derive(Debug, Clone)]
1008 pub struct Selected(pub SpecifiedType);
1009}
1010
1011impl ExclusiveOption for spec::All {
1012 fn inject_args(&self, command: &mut Command) {
1013 command.arg("-a");
1014 }
1015}
1016
1017impl ExclusiveOption for spec::Selected {
1018 fn inject_args(&self, command: &mut Command) {
1019 command.arg("-s").arg(self.0.to_str());
1020 }
1021}
1022
1023#[derive(Debug, Clone, Default)]
1029pub struct UpdateSpecDepot<S = Unselected> {
1030 spec: S,
1031}
1032
1033impl<S: ExclusiveOption> SubCommand for UpdateSpecDepot<S> {
1034 fn name(&self) -> &str {
1035 "updatespecdepot"
1036 }
1037
1038 fn inject_local_args(&self, command: &mut Command) {
1039 self.spec.inject_args(command);
1040 }
1041}
1042
1043impl Admin<UpdateSpecDepot<Unselected>> {
1044 #[cfg_attr(
1049 feature = "lt2022_2",
1050 doc = "For `p4 admin updatespecdepot`, update the spec depot with all current",
1051 doc = "forms."
1052 )]
1053 #[cfg_attr(
1054 not(feature = "lt2022_2"),
1055 doc = "For `p4 admin updatespecdepot -a`, update the spec depot with all",
1056 doc = "current forms."
1057 )]
1058 pub fn all(self) -> Admin<UpdateSpecDepot<spec::All>> {
1059 Admin {
1060 bin: self.bin,
1061 global_opts: self.global_opts,
1062 sub_command: UpdateSpecDepot { spec: spec::All },
1063 }
1064 }
1065
1066 #[cfg_attr(
1071 feature = "lt2016_1",
1072 doc = "For `p4 admin updatespecdepot`, update the spec depot with forms of the",
1073 doc = "specified type, where type is one of `client`, `depot`, `branch`,",
1074 doc = "`label`, `typemap`, `group`, `user`, or `job`."
1075 )]
1076 #[cfg_attr(
1077 all(feature = "lt2018_1", not(feature = "lt2016_1")),
1078 doc = "For `p4 admin updatespecdepot`, update the spec depot with forms of the",
1079 doc = "specified type, where type is one of `client`, `depot`, `branch`,",
1080 doc = "`label`, `typemap`, `group`, `user`, `job`, `stream`, `triggers`,",
1081 doc = "`protect`, `server`, `license`, or `jobspec`."
1082 )]
1083 #[cfg_attr(
1084 all(feature = "lt2022_2", not(feature = "lt2018_1")),
1085 doc = "For `p4 admin updatespecdepot`, update the spec depot with forms of the",
1086 doc = "specified type, where type is one of `client`, `depot`, `repo`,",
1087 doc = "`branch`, `label`, `typemap`, `group`, `user`, `job`, `stream`,",
1088 doc = "`triggers`, `protect`, `server`, `license`, or `jobspec`."
1089 )]
1090 #[cfg_attr(
1091 not(feature = "lt2022_2"),
1092 doc = "For `p4 admin updatespecdepot -s`, update the spec depot with forms of",
1093 doc = "the specified type, where type is one of `client`, `depot`, `repo`,",
1094 doc = "`branch`, `label`, `typemap`, `group`, `user`, `job`, `stream`,",
1095 doc = "`triggers`, `protect`, `server`, `license`, or `jobspec`."
1096 )]
1097 pub fn specified_type(
1098 self,
1099 specified_type: SpecifiedType,
1100 ) -> Admin<UpdateSpecDepot<spec::Selected>> {
1101 Admin {
1102 bin: self.bin,
1103 global_opts: self.global_opts,
1104 sub_command: UpdateSpecDepot {
1105 spec: spec::Selected(specified_type),
1106 },
1107 }
1108 }
1109}
1110
1111impl Admin<UpdateSpecDepot<spec::Selected>> {
1112 #[cfg_attr(
1117 feature = "lt2016_1",
1118 doc = "For `p4 admin updatespecdepot`, update the spec depot with forms of the",
1119 doc = "specified type, where type is one of `client`, `depot`, `branch`,",
1120 doc = "`label`, `typemap`, `group`, `user`, or `job`."
1121 )]
1122 #[cfg_attr(
1123 all(feature = "lt2018_1", not(feature = "lt2016_1")),
1124 doc = "For `p4 admin updatespecdepot`, update the spec depot with forms of the",
1125 doc = "specified type, where type is one of `client`, `depot`, `branch`,",
1126 doc = "`label`, `typemap`, `group`, `user`, `job`, `stream`, `triggers`,",
1127 doc = "`protect`, `server`, `license`, or `jobspec`."
1128 )]
1129 #[cfg_attr(
1130 all(feature = "lt2022_2", not(feature = "lt2018_1")),
1131 doc = "For `p4 admin updatespecdepot`, update the spec depot with forms of the",
1132 doc = "specified type, where type is one of `client`, `depot`, `repo`,",
1133 doc = "`branch`, `label`, `typemap`, `group`, `user`, `job`, `stream`,",
1134 doc = "`triggers`, `protect`, `server`, `license`, or `jobspec`."
1135 )]
1136 #[cfg_attr(
1137 not(feature = "lt2022_2"),
1138 doc = "For `p4 admin updatespecdepot -s`, update the spec depot with forms of",
1139 doc = "the specified type, where type is one of `client`, `depot`, `repo`,",
1140 doc = "`branch`, `label`, `typemap`, `group`, `user`, `job`, `stream`,",
1141 doc = "`triggers`, `protect`, `server`, `license`, or `jobspec`."
1142 )]
1143 pub fn get_specified_type(&self) -> &SpecifiedType {
1144 &self.sub_command.spec.0
1145 }
1146
1147 #[cfg_attr(
1152 feature = "lt2016_1",
1153 doc = "For `p4 admin updatespecdepot`, update the spec depot with forms of the",
1154 doc = "specified type, where type is one of `client`, `depot`, `branch`,",
1155 doc = "`label`, `typemap`, `group`, `user`, or `job`."
1156 )]
1157 #[cfg_attr(
1158 all(feature = "lt2018_1", not(feature = "lt2016_1")),
1159 doc = "For `p4 admin updatespecdepot`, update the spec depot with forms of the",
1160 doc = "specified type, where type is one of `client`, `depot`, `branch`,",
1161 doc = "`label`, `typemap`, `group`, `user`, `job`, `stream`, `triggers`,",
1162 doc = "`protect`, `server`, `license`, or `jobspec`."
1163 )]
1164 #[cfg_attr(
1165 all(feature = "lt2022_2", not(feature = "lt2018_1")),
1166 doc = "For `p4 admin updatespecdepot`, update the spec depot with forms of the",
1167 doc = "specified type, where type is one of `client`, `depot`, `repo`,",
1168 doc = "`branch`, `label`, `typemap`, `group`, `user`, `job`, `stream`,",
1169 doc = "`triggers`, `protect`, `server`, `license`, or `jobspec`."
1170 )]
1171 #[cfg_attr(
1172 not(feature = "lt2022_2"),
1173 doc = "For `p4 admin updatespecdepot -s`, update the spec depot with forms of",
1174 doc = "the specified type, where type is one of `client`, `depot`, `repo`,",
1175 doc = "`branch`, `label`, `typemap`, `group`, `user`, `job`, `stream`,",
1176 doc = "`triggers`, `protect`, `server`, `license`, or `jobspec`."
1177 )]
1178 pub fn set_specified_type(&mut self, specified_type: SpecifiedType) -> &mut Self {
1179 self.sub_command.spec = spec::Selected(specified_type);
1180 self
1181 }
1182}
1183
1184pub mod set_password {
1187 #[derive(Debug, Clone, Copy, Default)]
1189 pub struct All;
1190
1191 #[derive(Debug, Clone)]
1193 pub struct User(pub String);
1194}
1195
1196impl ExclusiveOption for set_password::All {
1197 fn inject_args(&self, command: &mut Command) {
1198 command.arg("-a");
1199 }
1200}
1201
1202impl ExclusiveOption for set_password::User {
1203 fn inject_args(&self, command: &mut Command) {
1204 command.arg("-u").arg(&self.0);
1205 }
1206}
1207
1208#[cfg_attr(
1214 feature = "lt2025_2",
1215 doc = "`p4 admin resetpassword -a | -u user`: force users to reset their passwords."
1216)]
1217#[cfg_attr(
1218 not(feature = "lt2025_2"),
1219 doc = "`p4 admin resetpassword {-a | -u user} [-l]`: force users to reset their passwords."
1220)]
1221#[derive(Debug, Clone, Default)]
1222pub struct ResetPassword<T = Unselected> {
1223 set_password: T,
1224
1225 #[cfg(not(feature = "lt2025_2"))]
1227 super_user: bool,
1228}
1229
1230impl<T: ExclusiveOption> SubCommand for ResetPassword<T> {
1231 fn name(&self) -> &str {
1232 "resetpassword"
1233 }
1234
1235 fn inject_local_args(&self, command: &mut Command) {
1236 self.set_password.inject_args(command);
1237 #[cfg(not(feature = "lt2025_2"))]
1238 if self.super_user {
1239 command.arg("-l");
1240 }
1241 }
1242}
1243
1244impl Admin<ResetPassword<Unselected>> {
1245 #[cfg_attr(
1250 feature = "lt2023_1",
1251 doc = "Force password reset of all users with passwords, including the",
1252 doc = "superuser who issued the command. Only the passwords of users who",
1253 doc = "presently exist (and who have passwords) are reset."
1254 )]
1255 #[cfg_attr(not(feature = "lt2023_1"), doc = "All users.")]
1256 pub fn all(self) -> Admin<ResetPassword<set_password::All>> {
1257 Admin {
1258 bin: self.bin,
1259 global_opts: self.global_opts,
1260 sub_command: ResetPassword {
1261 set_password: set_password::All,
1262 #[cfg(not(feature = "lt2025_2"))]
1263 super_user: self.sub_command.super_user,
1264 },
1265 }
1266 }
1267
1268 #[cfg_attr(
1273 feature = "lt2023_1",
1274 doc = "Force a single user with an existing password to reset their password",
1275 doc = "before they can run another command."
1276 )]
1277 #[cfg_attr(not(feature = "lt2023_1"), doc = "The specified user.")]
1278 pub fn user(self, user: impl Into<String>) -> Admin<ResetPassword<set_password::User>> {
1279 Admin {
1280 bin: self.bin,
1281 global_opts: self.global_opts,
1282 sub_command: ResetPassword {
1283 set_password: set_password::User(user.into()),
1284 #[cfg(not(feature = "lt2025_2"))]
1285 super_user: self.sub_command.super_user,
1286 },
1287 }
1288 }
1289}
1290
1291impl Admin<ResetPassword<set_password::User>> {
1292 #[cfg_attr(
1297 feature = "lt2023_1",
1298 doc = "Force a single user with an existing password to reset their password",
1299 doc = "before they can run another command."
1300 )]
1301 #[cfg_attr(not(feature = "lt2023_1"), doc = "The specified user.")]
1302 pub fn get_user(&self) -> &str {
1303 &self.sub_command.set_password.0
1304 }
1305
1306 #[cfg_attr(
1311 feature = "lt2023_1",
1312 doc = "Force a single user with an existing password to reset their password",
1313 doc = "before they can run another command."
1314 )]
1315 #[cfg_attr(not(feature = "lt2023_1"), doc = "The specified user.")]
1316 pub fn set_user(&mut self, user: impl Into<String>) -> &mut Self {
1317 self.sub_command.set_password.0 = user.into();
1318 self
1319 }
1320}
1321
1322impl<T: ExclusiveOption> Admin<ResetPassword<T>> {
1323 #[cfg(not(feature = "lt2025_2"))]
1329 pub fn get_super_user(&self) -> bool {
1330 self.sub_command.super_user
1331 }
1332
1333 #[cfg(not(feature = "lt2025_2"))]
1339 pub fn set_super_user(&mut self, super_user: bool) -> &mut Self {
1340 self.sub_command.super_user = super_user;
1341 self
1342 }
1343
1344 #[cfg(not(feature = "lt2025_2"))]
1350 pub fn super_user(mut self, super_user: bool) -> Self {
1351 self.sub_command.super_user = super_user;
1352 self
1353 }
1354}
1355
1356#[cfg(not(feature = "lt2015_1"))]
1359#[derive(Debug, Clone, Default)]
1360pub struct SetLdapUsers;
1361
1362#[cfg(not(feature = "lt2015_1"))]
1363impl SubCommand for SetLdapUsers {
1364 fn name(&self) -> &str {
1365 "setldapusers"
1366 }
1367
1368 fn inject_local_args(&self, _: &mut Command) {}
1369}
1370
1371#[cfg(not(feature = "lt2018_1"))]
1374#[derive(Debug, Clone, Default)]
1375pub struct EndJournal;
1376
1377#[cfg(not(feature = "lt2018_1"))]
1378impl SubCommand for EndJournal {
1379 fn name(&self) -> &str {
1380 "end-journal"
1381 }
1382
1383 fn inject_local_args(&self, _: &mut Command) {}
1384}
1385
1386#[cfg(not(feature = "lt2023_1"))]
1389#[derive(Debug, Clone, Default)]
1390pub struct SysInfo;
1391
1392#[cfg(not(feature = "lt2023_1"))]
1393impl SubCommand for SysInfo {
1394 fn name(&self) -> &str {
1395 "sysinfo"
1396 }
1397
1398 fn inject_local_args(&self, _: &mut Command) {}
1399}
1400
1401#[cfg(not(feature = "lt2023_1"))]
1404#[derive(Debug, Clone, Default)]
1405pub struct ResourceMonitor;
1406
1407#[cfg(not(feature = "lt2023_1"))]
1408impl SubCommand for ResourceMonitor {
1409 fn name(&self) -> &str {
1410 "resource-monitor"
1411 }
1412
1413 fn inject_local_args(&self, _: &mut Command) {}
1414}
1415
1416#[cfg(not(feature = "lt2025_2"))]
1419pub mod reconcile {
1420 #[derive(Debug, Clone, Copy, Default)]
1422 pub struct RestrictOnly;
1423
1424 #[derive(Debug, Clone, Copy, Default)]
1426 pub struct ExpandOnly;
1427}
1428
1429#[cfg(not(feature = "lt2025_2"))]
1430impl ExclusiveOption for reconcile::RestrictOnly {
1431 fn inject_args(&self, command: &mut Command) {
1432 command.arg("--restrict-only");
1433 }
1434}
1435
1436#[cfg(not(feature = "lt2025_2"))]
1437impl ExclusiveOption for reconcile::ExpandOnly {
1438 fn inject_args(&self, command: &mut Command) {
1439 command.arg("--expand-only");
1440 }
1441}
1442
1443#[cfg(not(feature = "lt2025_2"))]
1451#[derive(Debug, Clone, Default)]
1452pub struct ReplicaFilterReconcile<M = Unselected> {
1453 reconcile: M,
1454}
1455
1456#[cfg(not(feature = "lt2025_2"))]
1457impl<M: ExclusiveOption> SubCommand for ReplicaFilterReconcile<M> {
1458 fn name(&self) -> &str {
1459 "replica-filter-reconcile"
1460 }
1461
1462 fn inject_local_args(&self, command: &mut Command) {
1463 self.reconcile.inject_args(command);
1464 }
1465}
1466
1467#[cfg(not(feature = "lt2025_2"))]
1468impl Admin<ReplicaFilterReconcile<Unselected>> {
1469 pub fn restrict_only(self) -> Admin<ReplicaFilterReconcile<reconcile::RestrictOnly>> {
1476 Admin {
1477 bin: self.bin,
1478 global_opts: self.global_opts,
1479 sub_command: ReplicaFilterReconcile {
1480 reconcile: reconcile::RestrictOnly,
1481 },
1482 }
1483 }
1484
1485 pub fn expand_only(self) -> Admin<ReplicaFilterReconcile<reconcile::ExpandOnly>> {
1492 Admin {
1493 bin: self.bin,
1494 global_opts: self.global_opts,
1495 sub_command: ReplicaFilterReconcile {
1496 reconcile: reconcile::ExpandOnly,
1497 },
1498 }
1499 }
1500}
1501
1502#[cfg(not(feature = "lt2025_2"))]
1503impl<M: ExclusiveOption> ParameterizedSpawn for Admin<ReplicaFilterReconcile<M>> {
1504 type Input<'a> = &'a [&'a OsStr];
1505 type Output<'a> = Child;
1506 type Error = std::io::Error;
1507
1508 fn spawn_with<'a>(&mut self, tables: Self::Input<'a>) -> Result<Self::Output<'a>, Self::Error> {
1514 self.setup_command(&self.bin)
1515 .args(tables)
1516 .stdout(Stdio::piped())
1517 .stderr(Stdio::piped())
1518 .spawn()
1519 }
1520}
1521
1522#[cfg(test)]
1523mod tests {
1524 use super::*;
1525 use crate::cmd::args_of;
1526
1527 #[test]
1530 fn stop() {
1531 let admin = AdminEntry::new("p4", GlobalOpts::new()).stop();
1532
1533 assert_eq!(args_of(&admin.setup_command("p4")), ["admin", "stop"]);
1534 }
1535
1536 #[test]
1537 fn restart() {
1538 let admin = AdminEntry::new("p4", GlobalOpts::new()).restart();
1539
1540 assert_eq!(args_of(&admin.setup_command("p4")), ["admin", "restart"]);
1541 }
1542
1543 #[cfg(not(feature = "lt2015_1"))]
1544 #[test]
1545 fn setldapusers() {
1546 let admin = AdminEntry::new("p4", GlobalOpts::new()).setldapusers();
1547
1548 assert_eq!(
1549 args_of(&admin.setup_command("p4")),
1550 ["admin", "setldapusers"]
1551 );
1552 }
1553
1554 #[cfg(not(feature = "lt2018_1"))]
1555 #[test]
1556 fn end_journal() {
1557 let admin = AdminEntry::new("p4", GlobalOpts::new()).end_journal();
1558
1559 assert_eq!(
1560 args_of(&admin.setup_command("p4")),
1561 ["admin", "end-journal"]
1562 );
1563 }
1564
1565 #[cfg(not(feature = "lt2023_1"))]
1566 #[test]
1567 fn sysinfo() {
1568 let admin = AdminEntry::new("p4", GlobalOpts::new()).sysinfo();
1569
1570 assert_eq!(args_of(&admin.setup_command("p4")), ["admin", "sysinfo"]);
1571 }
1572
1573 #[cfg(not(feature = "lt2023_1"))]
1574 #[test]
1575 fn resource_monitor() {
1576 let admin = AdminEntry::new("p4", GlobalOpts::new()).resource_monitor();
1577
1578 assert_eq!(
1579 args_of(&admin.setup_command("p4")),
1580 ["admin", "resource-monitor"]
1581 );
1582 }
1583
1584 #[test]
1585 fn checkpoint_compress_both() {
1586 let admin = AdminEntry::new("p4", GlobalOpts::new())
1587 .checkpoint()
1588 .compress_both();
1589
1590 assert_eq!(
1591 args_of(&admin.setup_command("p4")),
1592 ["admin", "checkpoint", "-z"]
1593 );
1594 }
1595
1596 #[test]
1597 fn checkpoint_compress_checkpoint_only() {
1598 let admin = AdminEntry::new("p4", GlobalOpts::new())
1599 .checkpoint()
1600 .compress_checkpoint_only();
1601
1602 assert_eq!(
1603 args_of(&admin.setup_command("p4")),
1604 ["admin", "checkpoint", "-Z"]
1605 );
1606 }
1607
1608 #[test]
1609 fn checkpoint_with_prefix() {
1610 let admin = AdminEntry::new("p4", GlobalOpts::new())
1611 .checkpoint()
1612 .compress_both();
1613
1614 let mut command = admin.setup_command("p4");
1617 command.arg("ckp");
1618
1619 assert_eq!(args_of(&command), ["admin", "checkpoint", "-z", "ckp"]);
1620 }
1621
1622 #[cfg(not(feature = "lt2023_1"))]
1623 #[test]
1624 fn checkpoint_parallel_options() {
1625 let mut admin = AdminEntry::new("p4", GlobalOpts::new()).checkpoint();
1626 admin
1627 .set_parallel(true)
1628 .set_threads(4)
1629 .set_multiple_files(true);
1630
1631 assert_eq!(
1632 args_of(&admin.setup_command("p4")),
1633 ["admin", "checkpoint", "-p", "-N", "4", "-m"]
1634 );
1635 }
1636
1637 #[test]
1638 fn journal_gzip() {
1639 let mut admin = AdminEntry::new("p4", GlobalOpts::new()).journal();
1640 admin.set_gzip(true);
1641
1642 assert_eq!(
1643 args_of(&admin.setup_command("p4")),
1644 ["admin", "journal", "-z"]
1645 );
1646 }
1647
1648 #[test]
1649 fn updatespecdepot_all() {
1650 let admin = AdminEntry::new("p4", GlobalOpts::new())
1651 .updatespecdepot()
1652 .all();
1653
1654 assert_eq!(
1655 args_of(&admin.setup_command("p4")),
1656 ["admin", "updatespecdepot", "-a"]
1657 );
1658 }
1659
1660 #[test]
1663 fn updatespecdepot_specified_type() {
1664 let admin = AdminEntry::new("p4", GlobalOpts::new())
1665 .updatespecdepot()
1666 .specified_type(SpecifiedType::Client);
1667
1668 assert_eq!(
1669 args_of(&admin.setup_command("p4")),
1670 ["admin", "updatespecdepot", "-s", "client"]
1671 );
1672 }
1673
1674 #[test]
1675 fn resetpassword_all() {
1676 let admin = AdminEntry::new("p4", GlobalOpts::new())
1677 .resetpassword()
1678 .all();
1679
1680 assert_eq!(
1681 args_of(&admin.setup_command("p4")),
1682 ["admin", "resetpassword", "-a"]
1683 );
1684 }
1685
1686 #[test]
1687 fn resetpassword_single_user() {
1688 let admin = AdminEntry::new("p4", GlobalOpts::new())
1689 .resetpassword()
1690 .user("bruno");
1691
1692 assert_eq!(
1693 args_of(&admin.setup_command("p4")),
1694 ["admin", "resetpassword", "-u", "bruno"]
1695 );
1696 }
1697
1698 #[cfg(not(feature = "lt2025_2"))]
1699 #[test]
1700 fn resetpassword_super_user() {
1701 let admin = AdminEntry::new("p4", GlobalOpts::new())
1702 .resetpassword()
1703 .super_user(true);
1704
1705 assert_eq!(
1706 args_of(&admin.setup_command("p4")),
1707 ["admin", "resetpassword", "-l"]
1708 );
1709 }
1710
1711 #[cfg(not(feature = "lt2025_2"))]
1712 #[test]
1713 fn replica_filter_reconcile_restrict_only() {
1714 let admin = AdminEntry::new("p4", GlobalOpts::new())
1715 .replica_filter_reconcile()
1716 .restrict_only();
1717
1718 assert_eq!(
1719 args_of(&admin.setup_command("p4")),
1720 ["admin", "replica-filter-reconcile", "--restrict-only"]
1721 );
1722 }
1723
1724 #[cfg(not(feature = "lt2025_2"))]
1725 #[test]
1726 fn replica_filter_reconcile_expand_only() {
1727 let admin = AdminEntry::new("p4", GlobalOpts::new())
1728 .replica_filter_reconcile()
1729 .expand_only();
1730
1731 assert_eq!(
1732 args_of(&admin.setup_command("p4")),
1733 ["admin", "replica-filter-reconcile", "--expand-only"]
1734 );
1735 }
1736
1737 #[test]
1738 fn global_opts_are_injected_once() {
1739 let global_opts = GlobalOpts::new().port("localhost:1666");
1740 let admin = AdminEntry::new("p4", global_opts).checkpoint();
1741
1742 assert_eq!(
1745 args_of(&admin.setup_command("p4")),
1746 ["-p", "localhost:1666", "admin", "checkpoint"]
1747 );
1748 }
1749}