1use std::ffi::OsStr;
2
3use std::path::PathBuf;
4use std::process::{Child, Command, Stdio};
5
6use super::{ExclusiveOption, SubCommand, Unselected};
7
8use crate::global::GlobalOpts;
9use crate::spawn::ParameterizedSpawn;
10
11#[cfg_attr(
20 not(feature = "lt2015_1"),
21 doc = " [`setldapusers`](Self::setldapusers),"
22)]
23#[cfg_attr(
24 not(feature = "lt2018_1"),
25 doc = " [`end_journal`](Self::end_journal),"
26)]
27#[cfg_attr(
28 not(feature = "lt2023_1"),
29 doc = " [`sysinfo`](Self::sysinfo), [`resource_monitor`](Self::resource_monitor),"
30)]
31#[cfg_attr(
32 not(feature = "lt2025_2"),
33 doc = " [`replica_filter_reconcile`](Self::replica_filter_reconcile),"
34)]
35#[derive(Debug, Clone, Default)]
37pub struct AdminEntry {
38 bin: PathBuf,
39
40 global_opts: GlobalOpts,
41}
42
43impl AdminEntry {
44 pub fn new(bin: impl Into<PathBuf>, global_opts: GlobalOpts) -> Self {
48 Self {
49 bin: bin.into(),
50 global_opts,
51 }
52 }
53
54 pub fn checkpoint(self) -> Admin<CheckPoint<Unselected>> {
60 Admin::new(self.bin, self.global_opts, CheckPoint::default())
61 }
62
63 pub fn journal(self) -> Admin<Journal> {
68 Admin::new(self.bin, self.global_opts, Journal::default())
69 }
70
71 pub fn stop(self) -> Admin<Stop> {
76 Admin::new(self.bin, self.global_opts, Stop)
77 }
78
79 pub fn restart(self) -> Admin<Restart> {
84 Admin::new(self.bin, self.global_opts, Restart)
85 }
86
87 pub fn updatespecdepot(self) -> Admin<UpdateSpecDepot<Unselected>> {
94 Admin::new(self.bin, self.global_opts, UpdateSpecDepot::default())
95 }
96
97 pub fn resetpassword(self) -> Admin<ResetPassword<Unselected>> {
102 Admin::new(self.bin, self.global_opts, ResetPassword::default())
103 }
104
105 #[cfg(not(feature = "lt2015_1"))]
112 pub fn setldapusers(self) -> Admin<SetLdapUsers> {
113 Admin::new(self.bin, self.global_opts, SetLdapUsers)
114 }
115
116 #[cfg(not(feature = "lt2018_1"))]
123 pub fn end_journal(self) -> Admin<EndJournal> {
124 Admin::new(self.bin, self.global_opts, EndJournal)
125 }
126
127 #[cfg_attr(
133 all(not(feature = "lt2023_1"), feature = "lt2024_2"),
134 doc = "Helix Core Server."
135 )]
136 #[cfg_attr(not(feature = "lt2024_2"), doc = "P4 Server.")]
137 #[cfg(not(feature = "lt2023_1"))]
138 pub fn sysinfo(self) -> Admin<SysInfo> {
139 Admin::new(self.bin, self.global_opts, SysInfo)
140 }
141
142 #[cfg_attr(
147 all(not(feature = "lt2023_1"), feature = "lt2024_1"),
148 doc = "Helix Core Server",
149 doc = "Administrator Guide."
150 )]
151 #[cfg_attr(
152 all(not(feature = "lt2024_1"), feature = "lt2024_2"),
153 doc = "the Helix Core Server Administrator Guide."
154 )]
155 #[cfg_attr(
156 not(feature = "lt2024_2"),
157 doc = "P4 Server",
158 doc = "Administration Documentation."
159 )]
160 #[cfg(not(feature = "lt2023_1"))]
161 pub fn resource_monitor(self) -> Admin<ResourceMonitor> {
162 Admin::new(self.bin, self.global_opts, ResourceMonitor)
163 }
164
165 #[cfg(not(feature = "lt2025_2"))]
172 pub fn replica_filter_reconcile(self) -> Admin<ReplicaFilterReconcile<Unselected>> {
173 Admin::new(
174 self.bin,
175 self.global_opts,
176 ReplicaFilterReconcile::default(),
177 )
178 }
179}
180
181#[derive(Debug, Clone, Default)]
183pub struct Admin<T: SubCommand> {
184 bin: PathBuf,
185
186 global_opts: GlobalOpts,
187
188 sub_command: T,
189}
190
191impl<T: SubCommand> SubCommand for Admin<T> {
192 fn name(&self) -> &str {
193 "admin"
194 }
195
196 fn inject_local_args(&self, command: &mut Command) {
197 self.sub_command.inject_args(command);
198 }
199
200 fn global_opts(&self) -> Option<&GlobalOpts> {
201 Some(&self.global_opts)
202 }
203}
204
205impl<T: SubCommand> Admin<T> {
212 fn spawn_piped(&mut self) -> Result<Child, std::io::Error> {
216 self.setup_command(&self.bin)
217 .stdout(Stdio::piped())
218 .stderr(Stdio::piped())
219 .spawn()
220 }
221}
222
223impl ParameterizedSpawn<()> for Admin<Stop> {
224 type Output = Child;
225 type Error = std::io::Error;
226
227 fn spawn_with(&mut self, (): ()) -> Result<Self::Output, Self::Error> {
231 self.spawn_piped()
232 }
233}
234
235impl ParameterizedSpawn<()> for Admin<Restart> {
236 type Output = Child;
237 type Error = std::io::Error;
238
239 fn spawn_with(&mut self, (): ()) -> Result<Self::Output, Self::Error> {
243 self.spawn_piped()
244 }
245}
246
247impl<S: ExclusiveOption> ParameterizedSpawn<()> for Admin<UpdateSpecDepot<S>> {
248 type Output = Child;
249 type Error = std::io::Error;
250
251 fn spawn_with(&mut self, (): ()) -> Result<Self::Output, Self::Error> {
255 self.spawn_piped()
256 }
257}
258
259impl<T: ExclusiveOption> ParameterizedSpawn<()> for Admin<ResetPassword<T>> {
260 type Output = Child;
261 type Error = std::io::Error;
262
263 fn spawn_with(&mut self, (): ()) -> Result<Self::Output, Self::Error> {
267 self.spawn_piped()
268 }
269}
270
271#[cfg(not(feature = "lt2015_1"))]
272impl ParameterizedSpawn<()> for Admin<SetLdapUsers> {
273 type Output = Child;
274 type Error = std::io::Error;
275
276 fn spawn_with(&mut self, (): ()) -> Result<Self::Output, Self::Error> {
280 self.spawn_piped()
281 }
282}
283
284#[cfg(not(feature = "lt2018_1"))]
285impl ParameterizedSpawn<()> for Admin<EndJournal> {
286 type Output = Child;
287 type Error = std::io::Error;
288
289 fn spawn_with(&mut self, (): ()) -> Result<Self::Output, Self::Error> {
293 self.spawn_piped()
294 }
295}
296
297#[cfg(not(feature = "lt2023_1"))]
298impl ParameterizedSpawn<()> for Admin<SysInfo> {
299 type Output = Child;
300 type Error = std::io::Error;
301
302 fn spawn_with(&mut self, (): ()) -> Result<Self::Output, Self::Error> {
306 self.spawn_piped()
307 }
308}
309
310#[cfg(not(feature = "lt2023_1"))]
311impl ParameterizedSpawn<()> for Admin<ResourceMonitor> {
312 type Output = Child;
313 type Error = std::io::Error;
314
315 fn spawn_with(&mut self, (): ()) -> Result<Self::Output, Self::Error> {
319 self.spawn_piped()
320 }
321}
322
323impl<T: SubCommand> Admin<T> {
324 pub fn new(bin: impl Into<PathBuf>, global_opts: GlobalOpts, sub_command: T) -> Self {
328 Self {
329 bin: bin.into(),
330 global_opts,
331 sub_command,
332 }
333 }
334
335 #[cfg_attr(
340 feature = "lt2014_2",
341 doc = "See the [Global Options](GlobalOpts) section."
342 )]
343 #[cfg_attr(
344 all(feature = "lt2015_1", not(feature = "lt2014_2")),
345 doc = "See the [“Global Options”](GlobalOpts) section."
346 )]
347 #[cfg_attr(
348 all(feature = "lt2017_1", not(feature = "lt2015_1")),
349 doc = "See [“Global Options”](GlobalOpts)."
350 )]
351 #[cfg_attr(
352 all(feature = "lt2018_2", not(feature = "lt2017_1")),
353 doc = "See [Global Options](GlobalOpts)."
354 )]
355 #[cfg_attr(not(feature = "lt2018_2"), doc = "See [Global options](GlobalOpts).")]
356 pub fn get_global_opts(&self) -> &GlobalOpts {
357 &self.global_opts
358 }
359
360 #[cfg_attr(
365 feature = "lt2014_2",
366 doc = "See the [Global Options](GlobalOpts) section."
367 )]
368 #[cfg_attr(
369 all(feature = "lt2015_1", not(feature = "lt2014_2")),
370 doc = "See the [“Global Options”](GlobalOpts) section."
371 )]
372 #[cfg_attr(
373 all(feature = "lt2017_1", not(feature = "lt2015_1")),
374 doc = "See [“Global Options”](GlobalOpts)."
375 )]
376 #[cfg_attr(
377 all(feature = "lt2018_2", not(feature = "lt2017_1")),
378 doc = "See [Global Options](GlobalOpts)."
379 )]
380 #[cfg_attr(not(feature = "lt2018_2"), doc = "See [Global options](GlobalOpts).")]
381 pub fn set_global_opts(&mut self, v: GlobalOpts) -> &mut Self {
382 self.global_opts = v;
383 self
384 }
385
386 #[cfg_attr(
391 feature = "lt2014_2",
392 doc = "See the [Global Options](GlobalOpts) section."
393 )]
394 #[cfg_attr(
395 all(feature = "lt2015_1", not(feature = "lt2014_2")),
396 doc = "See the [“Global Options”](GlobalOpts) section."
397 )]
398 #[cfg_attr(
399 all(feature = "lt2017_1", not(feature = "lt2015_1")),
400 doc = "See [“Global Options”](GlobalOpts)."
401 )]
402 #[cfg_attr(
403 all(feature = "lt2018_2", not(feature = "lt2017_1")),
404 doc = "See [Global Options](GlobalOpts)."
405 )]
406 #[cfg_attr(not(feature = "lt2018_2"), doc = "See [Global options](GlobalOpts).")]
407 pub fn global_opts(mut self, v: GlobalOpts) -> Self {
408 self.global_opts = v;
409 self
410 }
411}
412
413pub mod compression {
414 #[derive(Debug, Clone, Copy, Default)]
416 pub struct Both;
417
418 #[derive(Debug, Clone, Copy, Default)]
421 pub struct CheckPointOnly;
422}
423
424impl ExclusiveOption for compression::Both {
425 fn inject_args(&self, command: &mut Command) {
426 command.arg("-z");
427 }
428}
429
430impl ExclusiveOption for compression::CheckPointOnly {
431 fn inject_args(&self, command: &mut Command) {
432 command.arg("-Z");
433 }
434}
435
436#[cfg_attr(
437 feature = "lt2022_2",
438 doc = "`p4 admin checkpoint [-z | -Z] [prefix]`: take a checkpoint."
439)]
440#[cfg_attr(
441 all(feature = "lt2023_1", not(feature = "lt2022_2")),
442 doc = "`p4 admin checkpoint [[-z | -Z]] [prefix]`: take a checkpoint."
443)]
444#[cfg_attr(
445 not(feature = "lt2023_1"),
446 doc = "`p4 admin checkpoint [-z | -Z] [-p [-N threads] [-m]] [prefix]`: take a checkpoint."
447)]
448#[derive(Debug, Clone, Default)]
451pub struct CheckPoint<C = Unselected> {
452 compression: C,
453
454 #[cfg(not(feature = "lt2023_1"))]
456 parallel: bool,
457
458 #[cfg(not(feature = "lt2023_1"))]
460 threads: Option<u32>,
461
462 #[cfg(not(feature = "lt2023_1"))]
464 multiple_files: bool,
465}
466
467impl<C: ExclusiveOption> SubCommand for CheckPoint<C> {
468 fn name(&self) -> &str {
469 "checkpoint"
470 }
471
472 fn inject_local_args(&self, command: &mut Command) {
473 self.compression.inject_args(command);
474
475 #[cfg(not(feature = "lt2023_1"))]
476 {
477 if self.parallel {
478 command.arg("-p");
479 }
480 if let Some(threads) = self.threads {
481 command.arg("-N").arg(threads.to_string());
482 }
483 if self.multiple_files {
484 command.arg("-m");
485 }
486 }
487 }
488}
489
490impl<C: ExclusiveOption, I> ParameterizedSpawn<(I,)> for Admin<CheckPoint<C>>
491where
492 I: AsRef<OsStr>,
493{
494 type Output = Child;
495 type Error = std::io::Error;
496
497 fn spawn_with(&mut self, (prefix,): (I,)) -> Result<Self::Output, Self::Error> {
504 self.setup_command(&self.bin)
505 .arg(prefix)
506 .stdout(Stdio::piped())
507 .stderr(Stdio::piped())
508 .spawn()
509 }
510}
511
512impl<C: ExclusiveOption> ParameterizedSpawn<()> for Admin<CheckPoint<C>> {
513 type Output = Child;
514 type Error = std::io::Error;
515
516 fn spawn_with(&mut self, _: ()) -> Result<Self::Output, Self::Error> {
523 self.setup_command(&self.bin)
524 .stdout(Stdio::piped())
525 .stderr(Stdio::piped())
526 .spawn()
527 }
528}
529
530impl<C: ExclusiveOption> Admin<CheckPoint<C>> {
531 #[cfg(not(feature = "lt2023_1"))]
537 pub fn get_parallel(&self) -> bool {
538 self.sub_command.parallel
539 }
540
541 #[cfg(not(feature = "lt2023_1"))]
547 pub fn set_parallel(&mut self, parallel: bool) -> &mut Self {
548 self.sub_command.parallel = parallel;
549 self
550 }
551
552 #[cfg(not(feature = "lt2023_1"))]
558 pub fn parallel(mut self, parallel: bool) -> Self {
559 self.sub_command.parallel = parallel;
560 self
561 }
562
563 #[cfg(not(feature = "lt2023_1"))]
569 pub fn get_threads(&self) -> Option<&u32> {
570 self.sub_command.threads.as_ref()
571 }
572
573 #[cfg(not(feature = "lt2023_1"))]
579 pub fn set_threads(&mut self, threads: u32) -> &mut Self {
580 self.sub_command.threads = Some(threads);
581 self
582 }
583
584 #[cfg(not(feature = "lt2023_1"))]
590 pub fn threads(mut self, threads: u32) -> Self {
591 self.sub_command.threads = Some(threads);
592 self
593 }
594
595 #[cfg_attr(
603 all(not(feature = "lt2023_1"), feature = "lt2024_1"),
604 doc = "in Helix Core",
605 doc = "Server Administrator Guide. See also checkpoint examples."
606 )]
607 #[cfg_attr(
608 all(not(feature = "lt2024_1"), feature = "lt2024_2"),
609 doc = "in the Helix",
610 doc = "Core Server Administrator Guide. See also checkpoint examples."
611 )]
612 #[cfg_attr(
613 all(not(feature = "lt2024_2"), feature = "lt2025_1"),
614 doc = "in the P4",
615 doc = "Server Administration Documentation. See also checkpoint examples."
616 )]
617 #[cfg_attr(
618 not(feature = "lt2025_1"),
619 doc = "in the P4",
620 doc = "Server Administration Documentation. See also Checkpoint examples."
621 )]
622 #[cfg(not(feature = "lt2023_1"))]
623 pub fn get_multiple_files(&self) -> bool {
624 self.sub_command.multiple_files
625 }
626
627 #[cfg_attr(
635 all(not(feature = "lt2023_1"), feature = "lt2024_1"),
636 doc = "in Helix Core",
637 doc = "Server Administrator Guide. See also checkpoint examples."
638 )]
639 #[cfg_attr(
640 all(not(feature = "lt2024_1"), feature = "lt2024_2"),
641 doc = "in the Helix",
642 doc = "Core Server Administrator Guide. See also checkpoint examples."
643 )]
644 #[cfg_attr(
645 all(not(feature = "lt2024_2"), feature = "lt2025_1"),
646 doc = "in the P4",
647 doc = "Server Administration Documentation. See also checkpoint examples."
648 )]
649 #[cfg_attr(
650 not(feature = "lt2025_1"),
651 doc = "in the P4",
652 doc = "Server Administration Documentation. See also Checkpoint examples."
653 )]
654 #[cfg(not(feature = "lt2023_1"))]
655 pub fn set_multiple_files(&mut self, multiple_files: bool) -> &mut Self {
656 self.sub_command.multiple_files = multiple_files;
657 self
658 }
659
660 #[cfg_attr(
668 all(not(feature = "lt2023_1"), feature = "lt2024_1"),
669 doc = "in Helix Core",
670 doc = "Server Administrator Guide. See also checkpoint examples."
671 )]
672 #[cfg_attr(
673 all(not(feature = "lt2024_1"), feature = "lt2024_2"),
674 doc = "in the Helix",
675 doc = "Core Server Administrator Guide. See also checkpoint examples."
676 )]
677 #[cfg_attr(
678 all(not(feature = "lt2024_2"), feature = "lt2025_1"),
679 doc = "in the P4",
680 doc = "Server Administration Documentation. See also checkpoint examples."
681 )]
682 #[cfg_attr(
683 not(feature = "lt2025_1"),
684 doc = "in the P4",
685 doc = "Server Administration Documentation. See also Checkpoint examples."
686 )]
687 #[cfg(not(feature = "lt2023_1"))]
688 pub fn multiple_files(mut self, multiple_files: bool) -> Self {
689 self.sub_command.multiple_files = multiple_files;
690 self
691 }
692}
693
694impl Admin<CheckPoint<Unselected>> {
695 #[cfg_attr(
700 feature = "lt2022_2",
701 doc = "For `p4 admin checkpoint` and `p4 admin journal`, save the checkpoint",
702 doc = "and saved journal file in compressed (gzip) format, appending the `.gz`",
703 doc = "suffix to the files."
704 )]
705 #[cfg_attr(
706 all(feature = "lt2023_1", not(feature = "lt2022_2")),
707 doc = "For `p4 admin checkpoint -z` and `p4 admin journal -z`, save the",
708 doc = "checkpoint and journal file in compressed format. The `.gz` suffix is",
709 doc = "appended to compressed journals and checkpoint files, which are in",
710 doc = "gzip format. If you do not specify `-z` or `-Z`, no compression occurs."
711 )]
712 #[cfg_attr(
713 not(feature = "lt2023_1"),
714 doc = "Save the checkpoint and journal file in compressed format. The `.gz`",
715 doc = "suffix is appended to compressed journals and checkpoint files, which",
716 doc = "are in gzip format. If you do not specify `-z` or `-Z`, no compression",
717 doc = "occurs."
718 )]
719 pub fn compress_both(self) -> Admin<CheckPoint<compression::Both>> {
720 Admin {
721 bin: self.bin,
722 global_opts: self.global_opts,
723 sub_command: CheckPoint::<compression::Both> {
724 compression: compression::Both,
725 #[cfg(not(feature = "lt2023_1"))]
726 parallel: self.sub_command.parallel,
727 #[cfg(not(feature = "lt2023_1"))]
728 threads: self.sub_command.threads,
729 #[cfg(not(feature = "lt2023_1"))]
730 multiple_files: self.sub_command.multiple_files,
731 },
732 }
733 }
734
735 #[cfg_attr(
740 feature = "lt2017_2",
741 doc = "For `p4 admin checkpoint` and `p4 admin journal`, save the checkpoint",
742 doc = "in compressed (gzip) format, appending the `.gz` suffix to the file, but",
743 doc = "leave the journal uncompressed for use by replica servers."
744 )]
745 #[cfg_attr(
746 all(feature = "lt2022_2", not(feature = "lt2017_2")),
747 doc = "For `p4 admin checkpoint`, save the checkpoint in compressed (gzip)",
748 doc = "format, appending the `.gz` suffix to the file, but leave the journal",
749 doc = "uncompressed for use by replica servers."
750 )]
751 #[cfg_attr(
752 all(feature = "lt2023_1", not(feature = "lt2022_2")),
753 doc = "For `p4 admin checkpoint -Z`, save the checkpoint in compressed format,",
754 doc = "but leave the journal uncompressed for use by replica servers."
755 )]
756 #[cfg_attr(
757 not(feature = "lt2023_1"),
758 doc = "For `p4 admin checkpoint -Z`, save the checkpoint in compressed format,",
759 doc = "but leave the journal uncompressed for use by replica servers. The",
760 doc = "`.gz` suffix is appended to compressed journals and checkpoint files,",
761 doc = "which are in gzip format. If you do not specify `-z` or `-Z`, no",
762 doc = "compression occurs."
763 )]
764 pub fn compress_checkpoint_only(self) -> Admin<CheckPoint<compression::CheckPointOnly>> {
765 Admin {
766 bin: self.bin,
767 global_opts: self.global_opts,
768 sub_command: CheckPoint::<compression::CheckPointOnly> {
769 compression: compression::CheckPointOnly,
770 #[cfg(not(feature = "lt2023_1"))]
771 parallel: self.sub_command.parallel,
772 #[cfg(not(feature = "lt2023_1"))]
773 threads: self.sub_command.threads,
774 #[cfg(not(feature = "lt2023_1"))]
775 multiple_files: self.sub_command.multiple_files,
776 },
777 }
778 }
779}
780
781#[derive(Debug, Clone, Default)]
783pub struct Journal {
784 gzip: bool,
785}
786
787impl SubCommand for Journal {
788 fn name(&self) -> &str {
789 "journal"
790 }
791
792 fn inject_local_args(&self, command: &mut Command) {
793 if self.gzip {
794 command.arg("-z");
795 }
796 }
797}
798
799impl<I> ParameterizedSpawn<(I,)> for Admin<Journal>
800where
801 I: AsRef<OsStr>,
802{
803 type Output = Child;
804 type Error = std::io::Error;
805
806 fn spawn_with(&mut self, (prefix,): (I,)) -> Result<Self::Output, Self::Error> {
813 self.setup_command(&self.bin)
814 .arg(prefix)
815 .stdout(Stdio::piped())
816 .stderr(Stdio::piped())
817 .spawn()
818 }
819}
820
821impl ParameterizedSpawn<()> for Admin<Journal> {
822 type Output = Child;
823 type Error = std::io::Error;
824
825 fn spawn_with(&mut self, _: ()) -> Result<Self::Output, Self::Error> {
830 self.setup_command(&self.bin)
831 .stdout(Stdio::piped())
832 .stderr(Stdio::piped())
833 .spawn()
834 }
835}
836
837impl Admin<Journal> {
838 #[cfg_attr(
843 feature = "lt2022_2",
844 doc = "For `p4 admin checkpoint` and `p4 admin journal`, save the checkpoint",
845 doc = "and saved journal file in compressed (gzip) format, appending the `.gz`",
846 doc = "suffix to the files."
847 )]
848 #[cfg_attr(
849 all(feature = "lt2023_1", not(feature = "lt2022_2")),
850 doc = "For `p4 admin checkpoint -z` and `p4 admin journal -z`, save the",
851 doc = "checkpoint and journal file in compressed format. The `.gz` suffix is",
852 doc = "appended to compressed journals and checkpoint files, which are in",
853 doc = "gzip format. If you do not specify `-z` or `-Z`, no compression occurs."
854 )]
855 #[cfg_attr(
856 not(feature = "lt2023_1"),
857 doc = "Save the journal file in compressed format. The `.gz` suffix is",
858 doc = "appended to compressed journals and checkpoint files, which are in",
859 doc = "gzip format. If you do not specify `-z`, no compression occurs."
860 )]
861 pub fn get_gzip(&self) -> bool {
862 self.sub_command.gzip
863 }
864
865 #[cfg_attr(
870 feature = "lt2022_2",
871 doc = "For `p4 admin checkpoint` and `p4 admin journal`, save the checkpoint",
872 doc = "and saved journal file in compressed (gzip) format, appending the `.gz`",
873 doc = "suffix to the files."
874 )]
875 #[cfg_attr(
876 all(feature = "lt2023_1", not(feature = "lt2022_2")),
877 doc = "For `p4 admin checkpoint -z` and `p4 admin journal -z`, save the",
878 doc = "checkpoint and journal file in compressed format. The `.gz` suffix is",
879 doc = "appended to compressed journals and checkpoint files, which are in",
880 doc = "gzip format. If you do not specify `-z` or `-Z`, no compression occurs."
881 )]
882 #[cfg_attr(
883 not(feature = "lt2023_1"),
884 doc = "Save the journal file in compressed format. The `.gz` suffix is",
885 doc = "appended to compressed journals and checkpoint files, which are in",
886 doc = "gzip format. If you do not specify `-z`, no compression occurs."
887 )]
888 pub fn set_gzip(&mut self, gzip: bool) -> &mut Self {
889 self.sub_command.gzip = gzip;
890 self
891 }
892
893 #[cfg_attr(
898 feature = "lt2022_2",
899 doc = "For `p4 admin checkpoint` and `p4 admin journal`, save the checkpoint",
900 doc = "and saved journal file in compressed (gzip) format, appending the `.gz`",
901 doc = "suffix to the files."
902 )]
903 #[cfg_attr(
904 all(feature = "lt2023_1", not(feature = "lt2022_2")),
905 doc = "For `p4 admin checkpoint -z` and `p4 admin journal -z`, save the",
906 doc = "checkpoint and journal file in compressed format. The `.gz` suffix is",
907 doc = "appended to compressed journals and checkpoint files, which are in",
908 doc = "gzip format. If you do not specify `-z` or `-Z`, no compression occurs."
909 )]
910 #[cfg_attr(
911 not(feature = "lt2023_1"),
912 doc = "Save the journal file in compressed format. The `.gz` suffix is",
913 doc = "appended to compressed journals and checkpoint files, which are in",
914 doc = "gzip format. If you do not specify `-z`, no compression occurs."
915 )]
916 pub fn gzip(mut self, gzip: bool) -> Self {
917 self.sub_command.gzip = gzip;
918 self
919 }
920}
921
922#[derive(Debug, Clone, Default)]
924pub struct Stop;
925
926impl SubCommand for Stop {
927 fn name(&self) -> &str {
928 "stop"
929 }
930
931 fn inject_local_args(&self, _: &mut Command) {}
932}
933
934#[derive(Debug, Clone, Default)]
936pub struct Restart;
937
938impl SubCommand for Restart {
939 fn name(&self) -> &str {
940 "restart"
941 }
942
943 fn inject_local_args(&self, _: &mut Command) {}
944}
945
946#[derive(Debug, Clone)]
948pub enum SpecifiedType {
949 Client,
950 Depot,
951 #[cfg(not(feature = "lt2018_1"))]
953 Repo,
954 Branch,
955 Label,
956 TypeMap,
957 Group,
958 User,
959 Job,
960 #[cfg(not(feature = "lt2016_1"))]
962 Stream,
963 #[cfg(not(feature = "lt2016_1"))]
965 Triggers,
966 #[cfg(not(feature = "lt2016_1"))]
968 Protect,
969 #[cfg(not(feature = "lt2016_1"))]
971 Server,
972 #[cfg(not(feature = "lt2016_1"))]
974 License,
975 #[cfg(not(feature = "lt2016_1"))]
977 JobSpec,
978}
979
980impl SpecifiedType {
981 pub(crate) fn to_str(&self) -> &str {
983 match self {
984 Self::Client => "client",
985 Self::Depot => "depot",
986 #[cfg(not(feature = "lt2018_1"))]
987 Self::Repo => "repo",
988 Self::Branch => "branch",
989 Self::Label => "label",
990 Self::TypeMap => "typemap",
991 Self::Group => "group",
992 Self::User => "user",
993 Self::Job => "job",
994 #[cfg(not(feature = "lt2016_1"))]
995 Self::Stream => "stream",
996 #[cfg(not(feature = "lt2016_1"))]
997 Self::Triggers => "triggers",
998 #[cfg(not(feature = "lt2016_1"))]
999 Self::Protect => "protect",
1000 #[cfg(not(feature = "lt2016_1"))]
1001 Self::Server => "server",
1002 #[cfg(not(feature = "lt2016_1"))]
1003 Self::License => "license",
1004 #[cfg(not(feature = "lt2016_1"))]
1005 Self::JobSpec => "jobspec",
1006 }
1007 }
1008}
1009
1010pub mod spec {
1013 use super::SpecifiedType;
1014
1015 #[derive(Debug, Clone, Copy, Default)]
1017 pub struct All;
1018
1019 #[derive(Debug, Clone)]
1021 pub struct Selected(pub SpecifiedType);
1022}
1023
1024impl ExclusiveOption for spec::All {
1025 fn inject_args(&self, command: &mut Command) {
1026 command.arg("-a");
1027 }
1028}
1029
1030impl ExclusiveOption for spec::Selected {
1031 fn inject_args(&self, command: &mut Command) {
1032 command.arg("-s").arg(self.0.to_str());
1033 }
1034}
1035
1036#[derive(Debug, Clone, Default)]
1042pub struct UpdateSpecDepot<S = Unselected> {
1043 spec: S,
1044}
1045
1046impl<S: ExclusiveOption> SubCommand for UpdateSpecDepot<S> {
1047 fn name(&self) -> &str {
1048 "updatespecdepot"
1049 }
1050
1051 fn inject_local_args(&self, command: &mut Command) {
1052 self.spec.inject_args(command);
1053 }
1054}
1055
1056impl Admin<UpdateSpecDepot<Unselected>> {
1057 #[cfg_attr(
1062 feature = "lt2022_2",
1063 doc = "For `p4 admin updatespecdepot`, update the spec depot with all current",
1064 doc = "forms."
1065 )]
1066 #[cfg_attr(
1067 not(feature = "lt2022_2"),
1068 doc = "For `p4 admin updatespecdepot -a`, update the spec depot with all",
1069 doc = "current forms."
1070 )]
1071 pub fn all(self) -> Admin<UpdateSpecDepot<spec::All>> {
1072 Admin {
1073 bin: self.bin,
1074 global_opts: self.global_opts,
1075 sub_command: UpdateSpecDepot { spec: spec::All },
1076 }
1077 }
1078
1079 #[cfg_attr(
1084 feature = "lt2016_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`, `branch`,",
1087 doc = "`label`, `typemap`, `group`, `user`, or `job`."
1088 )]
1089 #[cfg_attr(
1090 all(feature = "lt2018_1", not(feature = "lt2016_1")),
1091 doc = "For `p4 admin updatespecdepot`, update the spec depot with forms of the",
1092 doc = "specified type, where type is one of `client`, `depot`, `branch`,",
1093 doc = "`label`, `typemap`, `group`, `user`, `job`, `stream`, `triggers`,",
1094 doc = "`protect`, `server`, `license`, or `jobspec`."
1095 )]
1096 #[cfg_attr(
1097 all(feature = "lt2022_2", not(feature = "lt2018_1")),
1098 doc = "For `p4 admin updatespecdepot`, update the spec depot with forms of the",
1099 doc = "specified type, where type is one of `client`, `depot`, `repo`,",
1100 doc = "`branch`, `label`, `typemap`, `group`, `user`, `job`, `stream`,",
1101 doc = "`triggers`, `protect`, `server`, `license`, or `jobspec`."
1102 )]
1103 #[cfg_attr(
1104 not(feature = "lt2022_2"),
1105 doc = "For `p4 admin updatespecdepot -s`, update the spec depot with forms of",
1106 doc = "the specified type, where type is one of `client`, `depot`, `repo`,",
1107 doc = "`branch`, `label`, `typemap`, `group`, `user`, `job`, `stream`,",
1108 doc = "`triggers`, `protect`, `server`, `license`, or `jobspec`."
1109 )]
1110 pub fn specified_type(
1111 self,
1112 specified_type: SpecifiedType,
1113 ) -> Admin<UpdateSpecDepot<spec::Selected>> {
1114 Admin {
1115 bin: self.bin,
1116 global_opts: self.global_opts,
1117 sub_command: UpdateSpecDepot {
1118 spec: spec::Selected(specified_type),
1119 },
1120 }
1121 }
1122}
1123
1124impl Admin<UpdateSpecDepot<spec::Selected>> {
1125 #[cfg_attr(
1130 feature = "lt2016_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`, `branch`,",
1133 doc = "`label`, `typemap`, `group`, `user`, or `job`."
1134 )]
1135 #[cfg_attr(
1136 all(feature = "lt2018_1", not(feature = "lt2016_1")),
1137 doc = "For `p4 admin updatespecdepot`, update the spec depot with forms of the",
1138 doc = "specified type, where type is one of `client`, `depot`, `branch`,",
1139 doc = "`label`, `typemap`, `group`, `user`, `job`, `stream`, `triggers`,",
1140 doc = "`protect`, `server`, `license`, or `jobspec`."
1141 )]
1142 #[cfg_attr(
1143 all(feature = "lt2022_2", not(feature = "lt2018_1")),
1144 doc = "For `p4 admin updatespecdepot`, update the spec depot with forms of the",
1145 doc = "specified type, where type is one of `client`, `depot`, `repo`,",
1146 doc = "`branch`, `label`, `typemap`, `group`, `user`, `job`, `stream`,",
1147 doc = "`triggers`, `protect`, `server`, `license`, or `jobspec`."
1148 )]
1149 #[cfg_attr(
1150 not(feature = "lt2022_2"),
1151 doc = "For `p4 admin updatespecdepot -s`, update the spec depot with forms of",
1152 doc = "the specified type, where type is one of `client`, `depot`, `repo`,",
1153 doc = "`branch`, `label`, `typemap`, `group`, `user`, `job`, `stream`,",
1154 doc = "`triggers`, `protect`, `server`, `license`, or `jobspec`."
1155 )]
1156 pub fn get_specified_type(&self) -> &SpecifiedType {
1157 &self.sub_command.spec.0
1158 }
1159
1160 #[cfg_attr(
1165 feature = "lt2016_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`, `branch`,",
1168 doc = "`label`, `typemap`, `group`, `user`, or `job`."
1169 )]
1170 #[cfg_attr(
1171 all(feature = "lt2018_1", not(feature = "lt2016_1")),
1172 doc = "For `p4 admin updatespecdepot`, update the spec depot with forms of the",
1173 doc = "specified type, where type is one of `client`, `depot`, `branch`,",
1174 doc = "`label`, `typemap`, `group`, `user`, `job`, `stream`, `triggers`,",
1175 doc = "`protect`, `server`, `license`, or `jobspec`."
1176 )]
1177 #[cfg_attr(
1178 all(feature = "lt2022_2", not(feature = "lt2018_1")),
1179 doc = "For `p4 admin updatespecdepot`, update the spec depot with forms of the",
1180 doc = "specified type, where type is one of `client`, `depot`, `repo`,",
1181 doc = "`branch`, `label`, `typemap`, `group`, `user`, `job`, `stream`,",
1182 doc = "`triggers`, `protect`, `server`, `license`, or `jobspec`."
1183 )]
1184 #[cfg_attr(
1185 not(feature = "lt2022_2"),
1186 doc = "For `p4 admin updatespecdepot -s`, update the spec depot with forms of",
1187 doc = "the specified type, where type is one of `client`, `depot`, `repo`,",
1188 doc = "`branch`, `label`, `typemap`, `group`, `user`, `job`, `stream`,",
1189 doc = "`triggers`, `protect`, `server`, `license`, or `jobspec`."
1190 )]
1191 pub fn set_specified_type(&mut self, specified_type: SpecifiedType) -> &mut Self {
1192 self.sub_command.spec = spec::Selected(specified_type);
1193 self
1194 }
1195}
1196
1197pub mod set_password {
1200 #[derive(Debug, Clone, Copy, Default)]
1202 pub struct All;
1203
1204 #[derive(Debug, Clone)]
1206 pub struct User(pub String);
1207}
1208
1209impl ExclusiveOption for set_password::All {
1210 fn inject_args(&self, command: &mut Command) {
1211 command.arg("-a");
1212 }
1213}
1214
1215impl ExclusiveOption for set_password::User {
1216 fn inject_args(&self, command: &mut Command) {
1217 command.arg("-u").arg(&self.0);
1218 }
1219}
1220
1221#[cfg_attr(
1227 feature = "lt2025_2",
1228 doc = "`p4 admin resetpassword -a | -u user`: force users to reset their passwords."
1229)]
1230#[cfg_attr(
1231 not(feature = "lt2025_2"),
1232 doc = "`p4 admin resetpassword {-a | -u user} [-l]`: force users to reset their passwords."
1233)]
1234#[derive(Debug, Clone, Default)]
1235pub struct ResetPassword<T = Unselected> {
1236 set_password: T,
1237
1238 #[cfg(not(feature = "lt2025_2"))]
1240 super_user: bool,
1241}
1242
1243impl<T: ExclusiveOption> SubCommand for ResetPassword<T> {
1244 fn name(&self) -> &str {
1245 "resetpassword"
1246 }
1247
1248 fn inject_local_args(&self, command: &mut Command) {
1249 self.set_password.inject_args(command);
1250 #[cfg(not(feature = "lt2025_2"))]
1251 if self.super_user {
1252 command.arg("-l");
1253 }
1254 }
1255}
1256
1257impl Admin<ResetPassword<Unselected>> {
1258 #[cfg_attr(
1263 feature = "lt2023_1",
1264 doc = "Force password reset of all users with passwords, including the",
1265 doc = "superuser who issued the command. Only the passwords of users who",
1266 doc = "presently exist (and who have passwords) are reset."
1267 )]
1268 #[cfg_attr(not(feature = "lt2023_1"), doc = "All users.")]
1269 pub fn all(self) -> Admin<ResetPassword<set_password::All>> {
1270 Admin {
1271 bin: self.bin,
1272 global_opts: self.global_opts,
1273 sub_command: ResetPassword {
1274 set_password: set_password::All,
1275 #[cfg(not(feature = "lt2025_2"))]
1276 super_user: self.sub_command.super_user,
1277 },
1278 }
1279 }
1280
1281 #[cfg_attr(
1286 feature = "lt2023_1",
1287 doc = "Force a single user with an existing password to reset their password",
1288 doc = "before they can run another command."
1289 )]
1290 #[cfg_attr(not(feature = "lt2023_1"), doc = "The specified user.")]
1291 pub fn user(self, user: impl Into<String>) -> Admin<ResetPassword<set_password::User>> {
1292 Admin {
1293 bin: self.bin,
1294 global_opts: self.global_opts,
1295 sub_command: ResetPassword {
1296 set_password: set_password::User(user.into()),
1297 #[cfg(not(feature = "lt2025_2"))]
1298 super_user: self.sub_command.super_user,
1299 },
1300 }
1301 }
1302}
1303
1304impl Admin<ResetPassword<set_password::User>> {
1305 #[cfg_attr(
1310 feature = "lt2023_1",
1311 doc = "Force a single user with an existing password to reset their password",
1312 doc = "before they can run another command."
1313 )]
1314 #[cfg_attr(not(feature = "lt2023_1"), doc = "The specified user.")]
1315 pub fn get_user(&self) -> &str {
1316 &self.sub_command.set_password.0
1317 }
1318
1319 #[cfg_attr(
1324 feature = "lt2023_1",
1325 doc = "Force a single user with an existing password to reset their password",
1326 doc = "before they can run another command."
1327 )]
1328 #[cfg_attr(not(feature = "lt2023_1"), doc = "The specified user.")]
1329 pub fn set_user(&mut self, user: impl Into<String>) -> &mut Self {
1330 self.sub_command.set_password.0 = user.into();
1331 self
1332 }
1333}
1334
1335impl<T: ExclusiveOption> Admin<ResetPassword<T>> {
1336 #[cfg(not(feature = "lt2025_2"))]
1342 pub fn get_super_user(&self) -> bool {
1343 self.sub_command.super_user
1344 }
1345
1346 #[cfg(not(feature = "lt2025_2"))]
1352 pub fn set_super_user(&mut self, super_user: bool) -> &mut Self {
1353 self.sub_command.super_user = super_user;
1354 self
1355 }
1356
1357 #[cfg(not(feature = "lt2025_2"))]
1363 pub fn super_user(mut self, super_user: bool) -> Self {
1364 self.sub_command.super_user = super_user;
1365 self
1366 }
1367}
1368
1369#[cfg(not(feature = "lt2015_1"))]
1372#[derive(Debug, Clone, Default)]
1373pub struct SetLdapUsers;
1374
1375#[cfg(not(feature = "lt2015_1"))]
1376impl SubCommand for SetLdapUsers {
1377 fn name(&self) -> &str {
1378 "setldapusers"
1379 }
1380
1381 fn inject_local_args(&self, _: &mut Command) {}
1382}
1383
1384#[cfg(not(feature = "lt2018_1"))]
1387#[derive(Debug, Clone, Default)]
1388pub struct EndJournal;
1389
1390#[cfg(not(feature = "lt2018_1"))]
1391impl SubCommand for EndJournal {
1392 fn name(&self) -> &str {
1393 "end-journal"
1394 }
1395
1396 fn inject_local_args(&self, _: &mut Command) {}
1397}
1398
1399#[cfg(not(feature = "lt2023_1"))]
1402#[derive(Debug, Clone, Default)]
1403pub struct SysInfo;
1404
1405#[cfg(not(feature = "lt2023_1"))]
1406impl SubCommand for SysInfo {
1407 fn name(&self) -> &str {
1408 "sysinfo"
1409 }
1410
1411 fn inject_local_args(&self, _: &mut Command) {}
1412}
1413
1414#[cfg(not(feature = "lt2023_1"))]
1417#[derive(Debug, Clone, Default)]
1418pub struct ResourceMonitor;
1419
1420#[cfg(not(feature = "lt2023_1"))]
1421impl SubCommand for ResourceMonitor {
1422 fn name(&self) -> &str {
1423 "resource-monitor"
1424 }
1425
1426 fn inject_local_args(&self, _: &mut Command) {}
1427}
1428
1429#[cfg(not(feature = "lt2025_2"))]
1432pub mod reconcile {
1433 #[derive(Debug, Clone, Copy, Default)]
1435 pub struct RestrictOnly;
1436
1437 #[derive(Debug, Clone, Copy, Default)]
1439 pub struct ExpandOnly;
1440}
1441
1442#[cfg(not(feature = "lt2025_2"))]
1443impl ExclusiveOption for reconcile::RestrictOnly {
1444 fn inject_args(&self, command: &mut Command) {
1445 command.arg("--restrict-only");
1446 }
1447}
1448
1449#[cfg(not(feature = "lt2025_2"))]
1450impl ExclusiveOption for reconcile::ExpandOnly {
1451 fn inject_args(&self, command: &mut Command) {
1452 command.arg("--expand-only");
1453 }
1454}
1455
1456#[cfg(not(feature = "lt2025_2"))]
1464#[derive(Debug, Clone, Default)]
1465pub struct ReplicaFilterReconcile<M = Unselected> {
1466 reconcile: M,
1467}
1468
1469#[cfg(not(feature = "lt2025_2"))]
1470impl<M: ExclusiveOption> SubCommand for ReplicaFilterReconcile<M> {
1471 fn name(&self) -> &str {
1472 "replica-filter-reconcile"
1473 }
1474
1475 fn inject_local_args(&self, command: &mut Command) {
1476 self.reconcile.inject_args(command);
1477 }
1478}
1479
1480#[cfg(not(feature = "lt2025_2"))]
1481impl Admin<ReplicaFilterReconcile<Unselected>> {
1482 pub fn restrict_only(self) -> Admin<ReplicaFilterReconcile<reconcile::RestrictOnly>> {
1489 Admin {
1490 bin: self.bin,
1491 global_opts: self.global_opts,
1492 sub_command: ReplicaFilterReconcile {
1493 reconcile: reconcile::RestrictOnly,
1494 },
1495 }
1496 }
1497
1498 pub fn expand_only(self) -> Admin<ReplicaFilterReconcile<reconcile::ExpandOnly>> {
1505 Admin {
1506 bin: self.bin,
1507 global_opts: self.global_opts,
1508 sub_command: ReplicaFilterReconcile {
1509 reconcile: reconcile::ExpandOnly,
1510 },
1511 }
1512 }
1513}
1514
1515#[cfg(not(feature = "lt2025_2"))]
1516impl<M: ExclusiveOption, S, I> ParameterizedSpawn<(S,)> for Admin<ReplicaFilterReconcile<M>>
1517where
1518 S: IntoIterator<Item = I>,
1519 I: AsRef<OsStr>,
1520{
1521 type Output = Child;
1522 type Error = std::io::Error;
1523
1524 fn spawn_with(&mut self, (tables,): (S,)) -> Result<Self::Output, Self::Error> {
1530 self.setup_command(&self.bin)
1531 .args(tables)
1532 .stdout(Stdio::piped())
1533 .stderr(Stdio::piped())
1534 .spawn()
1535 }
1536}
1537
1538#[cfg(test)]
1539mod tests {
1540 use super::*;
1541 use crate::cmd::args_of;
1542
1543 #[test]
1546 fn stop() {
1547 let admin = AdminEntry::new("p4", GlobalOpts::new()).stop();
1548
1549 assert_eq!(args_of(&admin.setup_command("p4")), ["admin", "stop"]);
1550 }
1551
1552 #[test]
1553 fn restart() {
1554 let admin = AdminEntry::new("p4", GlobalOpts::new()).restart();
1555
1556 assert_eq!(args_of(&admin.setup_command("p4")), ["admin", "restart"]);
1557 }
1558
1559 #[cfg(not(feature = "lt2015_1"))]
1560 #[test]
1561 fn setldapusers() {
1562 let admin = AdminEntry::new("p4", GlobalOpts::new()).setldapusers();
1563
1564 assert_eq!(
1565 args_of(&admin.setup_command("p4")),
1566 ["admin", "setldapusers"]
1567 );
1568 }
1569
1570 #[cfg(not(feature = "lt2018_1"))]
1571 #[test]
1572 fn end_journal() {
1573 let admin = AdminEntry::new("p4", GlobalOpts::new()).end_journal();
1574
1575 assert_eq!(
1576 args_of(&admin.setup_command("p4")),
1577 ["admin", "end-journal"]
1578 );
1579 }
1580
1581 #[cfg(not(feature = "lt2023_1"))]
1582 #[test]
1583 fn sysinfo() {
1584 let admin = AdminEntry::new("p4", GlobalOpts::new()).sysinfo();
1585
1586 assert_eq!(args_of(&admin.setup_command("p4")), ["admin", "sysinfo"]);
1587 }
1588
1589 #[cfg(not(feature = "lt2023_1"))]
1590 #[test]
1591 fn resource_monitor() {
1592 let admin = AdminEntry::new("p4", GlobalOpts::new()).resource_monitor();
1593
1594 assert_eq!(
1595 args_of(&admin.setup_command("p4")),
1596 ["admin", "resource-monitor"]
1597 );
1598 }
1599
1600 #[test]
1601 fn checkpoint_compress_both() {
1602 let admin = AdminEntry::new("p4", GlobalOpts::new())
1603 .checkpoint()
1604 .compress_both();
1605
1606 assert_eq!(
1607 args_of(&admin.setup_command("p4")),
1608 ["admin", "checkpoint", "-z"]
1609 );
1610 }
1611
1612 #[test]
1613 fn checkpoint_compress_checkpoint_only() {
1614 let admin = AdminEntry::new("p4", GlobalOpts::new())
1615 .checkpoint()
1616 .compress_checkpoint_only();
1617
1618 assert_eq!(
1619 args_of(&admin.setup_command("p4")),
1620 ["admin", "checkpoint", "-Z"]
1621 );
1622 }
1623
1624 #[test]
1625 fn checkpoint_with_prefix() {
1626 let admin = AdminEntry::new("p4", GlobalOpts::new())
1627 .checkpoint()
1628 .compress_both();
1629
1630 let mut command = admin.setup_command("p4");
1633 command.arg("ckp");
1634
1635 assert_eq!(args_of(&command), ["admin", "checkpoint", "-z", "ckp"]);
1636 }
1637
1638 #[cfg(not(feature = "lt2023_1"))]
1639 #[test]
1640 fn checkpoint_parallel_options() {
1641 let mut admin = AdminEntry::new("p4", GlobalOpts::new()).checkpoint();
1642 admin
1643 .set_parallel(true)
1644 .set_threads(4)
1645 .set_multiple_files(true);
1646
1647 assert_eq!(
1648 args_of(&admin.setup_command("p4")),
1649 ["admin", "checkpoint", "-p", "-N", "4", "-m"]
1650 );
1651 }
1652
1653 #[test]
1654 fn journal_gzip() {
1655 let mut admin = AdminEntry::new("p4", GlobalOpts::new()).journal();
1656 admin.set_gzip(true);
1657
1658 assert_eq!(
1659 args_of(&admin.setup_command("p4")),
1660 ["admin", "journal", "-z"]
1661 );
1662 }
1663
1664 #[test]
1665 fn updatespecdepot_all() {
1666 let admin = AdminEntry::new("p4", GlobalOpts::new())
1667 .updatespecdepot()
1668 .all();
1669
1670 assert_eq!(
1671 args_of(&admin.setup_command("p4")),
1672 ["admin", "updatespecdepot", "-a"]
1673 );
1674 }
1675
1676 #[test]
1679 fn updatespecdepot_specified_type() {
1680 let admin = AdminEntry::new("p4", GlobalOpts::new())
1681 .updatespecdepot()
1682 .specified_type(SpecifiedType::Client);
1683
1684 assert_eq!(
1685 args_of(&admin.setup_command("p4")),
1686 ["admin", "updatespecdepot", "-s", "client"]
1687 );
1688 }
1689
1690 #[test]
1691 fn resetpassword_all() {
1692 let admin = AdminEntry::new("p4", GlobalOpts::new())
1693 .resetpassword()
1694 .all();
1695
1696 assert_eq!(
1697 args_of(&admin.setup_command("p4")),
1698 ["admin", "resetpassword", "-a"]
1699 );
1700 }
1701
1702 #[test]
1703 fn resetpassword_single_user() {
1704 let admin = AdminEntry::new("p4", GlobalOpts::new())
1705 .resetpassword()
1706 .user("bruno");
1707
1708 assert_eq!(
1709 args_of(&admin.setup_command("p4")),
1710 ["admin", "resetpassword", "-u", "bruno"]
1711 );
1712 }
1713
1714 #[cfg(not(feature = "lt2025_2"))]
1715 #[test]
1716 fn resetpassword_super_user() {
1717 let admin = AdminEntry::new("p4", GlobalOpts::new())
1718 .resetpassword()
1719 .super_user(true);
1720
1721 assert_eq!(
1722 args_of(&admin.setup_command("p4")),
1723 ["admin", "resetpassword", "-l"]
1724 );
1725 }
1726
1727 #[cfg(not(feature = "lt2025_2"))]
1728 #[test]
1729 fn replica_filter_reconcile_restrict_only() {
1730 let admin = AdminEntry::new("p4", GlobalOpts::new())
1731 .replica_filter_reconcile()
1732 .restrict_only();
1733
1734 assert_eq!(
1735 args_of(&admin.setup_command("p4")),
1736 ["admin", "replica-filter-reconcile", "--restrict-only"]
1737 );
1738 }
1739
1740 #[cfg(not(feature = "lt2025_2"))]
1741 #[test]
1742 fn replica_filter_reconcile_expand_only() {
1743 let admin = AdminEntry::new("p4", GlobalOpts::new())
1744 .replica_filter_reconcile()
1745 .expand_only();
1746
1747 assert_eq!(
1748 args_of(&admin.setup_command("p4")),
1749 ["admin", "replica-filter-reconcile", "--expand-only"]
1750 );
1751 }
1752
1753 #[test]
1754 fn global_opts_are_injected_once() {
1755 let global_opts = GlobalOpts::new().port("localhost:1666");
1756 let admin = AdminEntry::new("p4", global_opts).checkpoint();
1757
1758 assert_eq!(
1761 args_of(&admin.setup_command("p4")),
1762 ["-p", "localhost:1666", "admin", "checkpoint"]
1763 );
1764 }
1765}