1#[cfg(not(feature = "lt2025_2"))]
2use std::ffi::OsStr;
3
4use std::path::PathBuf;
5use std::process::{Child, Command, Stdio};
6
7use super::{ExclusiveOption, SubCommand, Unselected};
8
9use crate::global::GlobalOpts;
10use crate::spawn::{ParameterizedSpawn, SpawnExt};
11
12#[cfg_attr(
21 not(feature = "lt2015_1"),
22 doc = " [`setldapusers`](Self::setldapusers),"
23)]
24#[cfg_attr(
25 not(feature = "lt2018_1"),
26 doc = " [`end_journal`](Self::end_journal),"
27)]
28#[cfg_attr(
29 not(feature = "lt2023_1"),
30 doc = " [`sysinfo`](Self::sysinfo), [`resource_monitor`](Self::resource_monitor),"
31)]
32#[cfg_attr(
33 not(feature = "lt2025_2"),
34 doc = " [`replica_filter_reconcile`](Self::replica_filter_reconcile),"
35)]
36#[derive(Debug, Clone, Default)]
38pub struct AdminEntry {
39 bin: PathBuf,
40
41 global_opts: GlobalOpts,
42}
43
44impl AdminEntry {
45 pub fn new(bin: impl Into<PathBuf>, global_opts: GlobalOpts) -> Self {
49 Self {
50 bin: bin.into(),
51 global_opts,
52 }
53 }
54
55 pub fn checkpoint(self) -> Admin<CheckPoint<Unselected>> {
61 Admin::new(self.bin, self.global_opts, CheckPoint::default())
62 }
63
64 pub fn journal(self) -> Admin<Journal> {
69 Admin::new(self.bin, self.global_opts, Journal::default())
70 }
71
72 pub fn stop(self) -> Admin<Stop> {
77 Admin::new(self.bin, self.global_opts, Stop)
78 }
79
80 pub fn restart(self) -> Admin<Restart> {
85 Admin::new(self.bin, self.global_opts, Restart)
86 }
87
88 pub fn updatespecdepot(self) -> Admin<UpdateSpecDepot<Unselected>> {
95 Admin::new(self.bin, self.global_opts, UpdateSpecDepot::default())
96 }
97
98 pub fn resetpassword(self) -> Admin<ResetPassword<Unselected>> {
103 Admin::new(self.bin, self.global_opts, ResetPassword::default())
104 }
105
106 #[cfg(not(feature = "lt2015_1"))]
113 pub fn setldapusers(self) -> Admin<SetLdapUsers> {
114 Admin::new(self.bin, self.global_opts, SetLdapUsers)
115 }
116
117 #[cfg(not(feature = "lt2018_1"))]
124 pub fn end_journal(self) -> Admin<EndJournal> {
125 Admin::new(self.bin, self.global_opts, EndJournal)
126 }
127
128 #[cfg_attr(
134 all(not(feature = "lt2023_1"), feature = "lt2024_2"),
135 doc = "Helix Core Server."
136 )]
137 #[cfg_attr(not(feature = "lt2024_2"), doc = "P4 Server.")]
138 #[cfg(not(feature = "lt2023_1"))]
139 pub fn sysinfo(self) -> Admin<SysInfo> {
140 Admin::new(self.bin, self.global_opts, SysInfo)
141 }
142
143 #[cfg_attr(
148 all(not(feature = "lt2023_1"), feature = "lt2024_1"),
149 doc = "Helix Core Server",
150 doc = "Administrator Guide."
151 )]
152 #[cfg_attr(
153 all(not(feature = "lt2024_1"), feature = "lt2024_2"),
154 doc = "the Helix Core Server Administrator Guide."
155 )]
156 #[cfg_attr(
157 not(feature = "lt2024_2"),
158 doc = "P4 Server",
159 doc = "Administration Documentation."
160 )]
161 #[cfg(not(feature = "lt2023_1"))]
162 pub fn resource_monitor(self) -> Admin<ResourceMonitor> {
163 Admin::new(self.bin, self.global_opts, ResourceMonitor)
164 }
165
166 #[cfg(not(feature = "lt2025_2"))]
173 pub fn replica_filter_reconcile(self) -> Admin<ReplicaFilterReconcile<Unselected>> {
174 Admin::new(
175 self.bin,
176 self.global_opts,
177 ReplicaFilterReconcile::default(),
178 )
179 }
180}
181
182#[derive(Debug, Clone, Default)]
184pub struct Admin<T: SubCommand> {
185 bin: PathBuf,
186
187 global_opts: GlobalOpts,
188
189 sub_command: T,
190}
191
192impl<T: SubCommand> SubCommand for Admin<T> {
193 fn name(&self) -> &str {
194 "admin"
195 }
196
197 fn inject_local_args(&self, command: &mut Command) {
198 self.sub_command.inject_args(command);
199 }
200
201 fn global_opts(&self) -> Option<&GlobalOpts> {
202 Some(&self.global_opts)
203 }
204}
205
206impl<T: SubCommand> Admin<T> {
213 fn spawn_piped(&mut self) -> Result<Child, std::io::Error> {
217 self.setup_command(&self.bin)
218 .stdout(Stdio::piped())
219 .stderr(Stdio::piped())
220 .spawn()
221 }
222}
223
224impl ParameterizedSpawn for Admin<Stop> {
225 type Input<'a> = ();
226 type Output<'a> = Child;
227 type Error = std::io::Error;
228
229 fn spawn_with<'a>(&mut self, (): Self::Input<'a>) -> Result<Self::Output<'a>, Self::Error> {
233 self.spawn_piped()
234 }
235}
236
237impl ParameterizedSpawn for Admin<Restart> {
238 type Input<'a> = ();
239 type Output<'a> = Child;
240 type Error = std::io::Error;
241
242 fn spawn_with<'a>(&mut self, (): Self::Input<'a>) -> Result<Self::Output<'a>, Self::Error> {
246 self.spawn_piped()
247 }
248}
249
250impl<S: ExclusiveOption> ParameterizedSpawn for Admin<UpdateSpecDepot<S>> {
251 type Input<'a> = ();
252 type Output<'a> = Child;
253 type Error = std::io::Error;
254
255 fn spawn_with<'a>(&mut self, (): Self::Input<'a>) -> Result<Self::Output<'a>, Self::Error> {
259 self.spawn_piped()
260 }
261}
262
263impl<T: ExclusiveOption> ParameterizedSpawn for Admin<ResetPassword<T>> {
264 type Input<'a> = ();
265 type Output<'a> = Child;
266 type Error = std::io::Error;
267
268 fn spawn_with<'a>(&mut self, (): Self::Input<'a>) -> Result<Self::Output<'a>, Self::Error> {
272 self.spawn_piped()
273 }
274}
275
276#[cfg(not(feature = "lt2015_1"))]
277impl ParameterizedSpawn for Admin<SetLdapUsers> {
278 type Input<'a> = ();
279 type Output<'a> = Child;
280 type Error = std::io::Error;
281
282 fn spawn_with<'a>(&mut self, (): Self::Input<'a>) -> Result<Self::Output<'a>, Self::Error> {
286 self.spawn_piped()
287 }
288}
289
290#[cfg(not(feature = "lt2018_1"))]
291impl ParameterizedSpawn for Admin<EndJournal> {
292 type Input<'a> = ();
293 type Output<'a> = Child;
294 type Error = std::io::Error;
295
296 fn spawn_with<'a>(&mut self, (): Self::Input<'a>) -> Result<Self::Output<'a>, Self::Error> {
300 self.spawn_piped()
301 }
302}
303
304#[cfg(not(feature = "lt2023_1"))]
305impl ParameterizedSpawn for Admin<SysInfo> {
306 type Input<'a> = ();
307 type Output<'a> = Child;
308 type Error = std::io::Error;
309
310 fn spawn_with<'a>(&mut self, (): Self::Input<'a>) -> Result<Self::Output<'a>, Self::Error> {
314 self.spawn_piped()
315 }
316}
317
318#[cfg(not(feature = "lt2023_1"))]
319impl ParameterizedSpawn for Admin<ResourceMonitor> {
320 type Input<'a> = ();
321 type Output<'a> = Child;
322 type Error = std::io::Error;
323
324 fn spawn_with<'a>(&mut self, (): Self::Input<'a>) -> Result<Self::Output<'a>, Self::Error> {
328 self.spawn_piped()
329 }
330}
331
332impl<T: SubCommand> Admin<T> {
333 pub fn new(bin: impl Into<PathBuf>, global_opts: GlobalOpts, sub_command: T) -> Self {
337 Self {
338 bin: bin.into(),
339 global_opts,
340 sub_command,
341 }
342 }
343
344 #[cfg_attr(
349 feature = "lt2014_2",
350 doc = "See the [Global Options](GlobalOpts) section."
351 )]
352 #[cfg_attr(
353 all(feature = "lt2015_1", not(feature = "lt2014_2")),
354 doc = "See the [“Global Options”](GlobalOpts) section."
355 )]
356 #[cfg_attr(
357 all(feature = "lt2017_1", not(feature = "lt2015_1")),
358 doc = "See [“Global Options”](GlobalOpts)."
359 )]
360 #[cfg_attr(
361 all(feature = "lt2018_2", not(feature = "lt2017_1")),
362 doc = "See [Global Options](GlobalOpts)."
363 )]
364 #[cfg_attr(not(feature = "lt2018_2"), doc = "See [Global options](GlobalOpts).")]
365 pub fn get_global_opts(&self) -> &GlobalOpts {
366 &self.global_opts
367 }
368
369 #[cfg_attr(
374 feature = "lt2014_2",
375 doc = "See the [Global Options](GlobalOpts) section."
376 )]
377 #[cfg_attr(
378 all(feature = "lt2015_1", not(feature = "lt2014_2")),
379 doc = "See the [“Global Options”](GlobalOpts) section."
380 )]
381 #[cfg_attr(
382 all(feature = "lt2017_1", not(feature = "lt2015_1")),
383 doc = "See [“Global Options”](GlobalOpts)."
384 )]
385 #[cfg_attr(
386 all(feature = "lt2018_2", not(feature = "lt2017_1")),
387 doc = "See [Global Options](GlobalOpts)."
388 )]
389 #[cfg_attr(not(feature = "lt2018_2"), doc = "See [Global options](GlobalOpts).")]
390 pub fn set_global_opts(&mut self, v: GlobalOpts) -> &mut Self {
391 self.global_opts = v;
392 self
393 }
394
395 #[cfg_attr(
400 feature = "lt2014_2",
401 doc = "See the [Global Options](GlobalOpts) section."
402 )]
403 #[cfg_attr(
404 all(feature = "lt2015_1", not(feature = "lt2014_2")),
405 doc = "See the [“Global Options”](GlobalOpts) section."
406 )]
407 #[cfg_attr(
408 all(feature = "lt2017_1", not(feature = "lt2015_1")),
409 doc = "See [“Global Options”](GlobalOpts)."
410 )]
411 #[cfg_attr(
412 all(feature = "lt2018_2", not(feature = "lt2017_1")),
413 doc = "See [Global Options](GlobalOpts)."
414 )]
415 #[cfg_attr(not(feature = "lt2018_2"), doc = "See [Global options](GlobalOpts).")]
416 pub fn global_opts(mut self, v: GlobalOpts) -> Self {
417 self.global_opts = v;
418 self
419 }
420}
421
422pub mod compression {
423 #[derive(Debug, Clone, Copy, Default)]
425 pub struct Both;
426
427 #[derive(Debug, Clone, Copy, Default)]
430 pub struct CheckPointOnly;
431}
432
433impl ExclusiveOption for compression::Both {
434 fn inject_args(&self, command: &mut Command) {
435 command.arg("-z");
436 }
437}
438
439impl ExclusiveOption for compression::CheckPointOnly {
440 fn inject_args(&self, command: &mut Command) {
441 command.arg("-Z");
442 }
443}
444
445#[cfg_attr(
446 feature = "lt2022_2",
447 doc = "`p4 admin checkpoint [-z | -Z] [prefix]`: take a checkpoint."
448)]
449#[cfg_attr(
450 all(feature = "lt2023_1", not(feature = "lt2022_2")),
451 doc = "`p4 admin checkpoint [[-z | -Z]] [prefix]`: take a checkpoint."
452)]
453#[cfg_attr(
454 not(feature = "lt2023_1"),
455 doc = "`p4 admin checkpoint [-z | -Z] [-p [-N threads] [-m]] [prefix]`: take a checkpoint."
456)]
457#[derive(Debug, Clone, Default)]
460pub struct CheckPoint<C = Unselected> {
461 compression: C,
462
463 #[cfg(not(feature = "lt2023_1"))]
465 parallel: bool,
466
467 #[cfg(not(feature = "lt2023_1"))]
469 threads: Option<u32>,
470
471 #[cfg(not(feature = "lt2023_1"))]
473 multiple_files: bool,
474}
475
476impl<C: ExclusiveOption> SubCommand for CheckPoint<C> {
477 fn name(&self) -> &str {
478 "checkpoint"
479 }
480
481 fn inject_local_args(&self, command: &mut Command) {
482 self.compression.inject_args(command);
483
484 #[cfg(not(feature = "lt2023_1"))]
485 {
486 if self.parallel {
487 command.arg("-p");
488 }
489 if let Some(threads) = self.threads {
490 command.arg("-N").arg(threads.to_string());
491 }
492 if self.multiple_files {
493 command.arg("-m");
494 }
495 }
496 }
497}
498
499impl<C: ExclusiveOption> ParameterizedSpawn for Admin<CheckPoint<C>> {
500 type Input<'a> = Option<&'a str>;
501 type Output<'a> = Child;
502 type Error = std::io::Error;
503
504 fn spawn_with<'a>(&mut self, prefix: Self::Input<'a>) -> Result<Self::Output<'a>, Self::Error> {
511 let mut command = self.setup_command(&self.bin);
512
513 if let Some(prefix) = prefix {
514 command.arg(prefix);
515 }
516 command
517 .stdout(Stdio::piped())
518 .stderr(Stdio::piped())
519 .spawn()
520 }
521}
522
523impl<C: ExclusiveOption> SpawnExt for Admin<CheckPoint<C>> {
524 fn spawn<'a>(&mut self) -> Result<Self::Output<'a>, Self::Error> {
525 self.spawn_with(None)
526 }
527}
528
529impl<C: ExclusiveOption> Admin<CheckPoint<C>> {
530 #[cfg(not(feature = "lt2023_1"))]
536 pub fn get_parallel(&self) -> bool {
537 self.sub_command.parallel
538 }
539
540 #[cfg(not(feature = "lt2023_1"))]
546 pub fn set_parallel(&mut self, parallel: bool) -> &mut Self {
547 self.sub_command.parallel = parallel;
548 self
549 }
550
551 #[cfg(not(feature = "lt2023_1"))]
557 pub fn parallel(mut self, parallel: bool) -> Self {
558 self.sub_command.parallel = parallel;
559 self
560 }
561
562 #[cfg(not(feature = "lt2023_1"))]
568 pub fn get_threads(&self) -> Option<&u32> {
569 self.sub_command.threads.as_ref()
570 }
571
572 #[cfg(not(feature = "lt2023_1"))]
578 pub fn set_threads(&mut self, threads: u32) -> &mut Self {
579 self.sub_command.threads = Some(threads);
580 self
581 }
582
583 #[cfg(not(feature = "lt2023_1"))]
589 pub fn threads(mut self, threads: u32) -> Self {
590 self.sub_command.threads = Some(threads);
591 self
592 }
593
594 #[cfg_attr(
602 all(not(feature = "lt2023_1"), feature = "lt2024_1"),
603 doc = "in Helix Core",
604 doc = "Server Administrator Guide. See also checkpoint examples."
605 )]
606 #[cfg_attr(
607 all(not(feature = "lt2024_1"), feature = "lt2024_2"),
608 doc = "in the Helix",
609 doc = "Core Server Administrator Guide. See also checkpoint examples."
610 )]
611 #[cfg_attr(
612 all(not(feature = "lt2024_2"), feature = "lt2025_1"),
613 doc = "in the P4",
614 doc = "Server Administration Documentation. See also checkpoint examples."
615 )]
616 #[cfg_attr(
617 not(feature = "lt2025_1"),
618 doc = "in the P4",
619 doc = "Server Administration Documentation. See also Checkpoint examples."
620 )]
621 #[cfg(not(feature = "lt2023_1"))]
622 pub fn get_multiple_files(&self) -> bool {
623 self.sub_command.multiple_files
624 }
625
626 #[cfg_attr(
634 all(not(feature = "lt2023_1"), feature = "lt2024_1"),
635 doc = "in Helix Core",
636 doc = "Server Administrator Guide. See also checkpoint examples."
637 )]
638 #[cfg_attr(
639 all(not(feature = "lt2024_1"), feature = "lt2024_2"),
640 doc = "in the Helix",
641 doc = "Core Server Administrator Guide. See also checkpoint examples."
642 )]
643 #[cfg_attr(
644 all(not(feature = "lt2024_2"), feature = "lt2025_1"),
645 doc = "in the P4",
646 doc = "Server Administration Documentation. See also checkpoint examples."
647 )]
648 #[cfg_attr(
649 not(feature = "lt2025_1"),
650 doc = "in the P4",
651 doc = "Server Administration Documentation. See also Checkpoint examples."
652 )]
653 #[cfg(not(feature = "lt2023_1"))]
654 pub fn set_multiple_files(&mut self, multiple_files: bool) -> &mut Self {
655 self.sub_command.multiple_files = multiple_files;
656 self
657 }
658
659 #[cfg_attr(
667 all(not(feature = "lt2023_1"), feature = "lt2024_1"),
668 doc = "in Helix Core",
669 doc = "Server Administrator Guide. See also checkpoint examples."
670 )]
671 #[cfg_attr(
672 all(not(feature = "lt2024_1"), feature = "lt2024_2"),
673 doc = "in the Helix",
674 doc = "Core Server Administrator Guide. See also checkpoint examples."
675 )]
676 #[cfg_attr(
677 all(not(feature = "lt2024_2"), feature = "lt2025_1"),
678 doc = "in the P4",
679 doc = "Server Administration Documentation. See also checkpoint examples."
680 )]
681 #[cfg_attr(
682 not(feature = "lt2025_1"),
683 doc = "in the P4",
684 doc = "Server Administration Documentation. See also Checkpoint examples."
685 )]
686 #[cfg(not(feature = "lt2023_1"))]
687 pub fn multiple_files(mut self, multiple_files: bool) -> Self {
688 self.sub_command.multiple_files = multiple_files;
689 self
690 }
691}
692
693impl Admin<CheckPoint<Unselected>> {
694 #[cfg_attr(
699 feature = "lt2022_2",
700 doc = "For `p4 admin checkpoint` and `p4 admin journal`, save the checkpoint",
701 doc = "and saved journal file in compressed (gzip) format, appending the `.gz`",
702 doc = "suffix to the files."
703 )]
704 #[cfg_attr(
705 all(feature = "lt2023_1", not(feature = "lt2022_2")),
706 doc = "For `p4 admin checkpoint -z` and `p4 admin journal -z`, save the",
707 doc = "checkpoint and journal file in compressed format. The `.gz` suffix is",
708 doc = "appended to compressed journals and checkpoint files, which are in",
709 doc = "gzip format. If you do not specify `-z` or `-Z`, no compression occurs."
710 )]
711 #[cfg_attr(
712 not(feature = "lt2023_1"),
713 doc = "Save the checkpoint and journal file in compressed format. The `.gz`",
714 doc = "suffix is appended to compressed journals and checkpoint files, which",
715 doc = "are in gzip format. If you do not specify `-z` or `-Z`, no compression",
716 doc = "occurs."
717 )]
718 pub fn compress_both(self) -> Admin<CheckPoint<compression::Both>> {
719 Admin {
720 bin: self.bin,
721 global_opts: self.global_opts,
722 sub_command: CheckPoint::<compression::Both> {
723 compression: compression::Both,
724 #[cfg(not(feature = "lt2023_1"))]
725 parallel: self.sub_command.parallel,
726 #[cfg(not(feature = "lt2023_1"))]
727 threads: self.sub_command.threads,
728 #[cfg(not(feature = "lt2023_1"))]
729 multiple_files: self.sub_command.multiple_files,
730 },
731 }
732 }
733
734 #[cfg_attr(
739 feature = "lt2017_2",
740 doc = "For `p4 admin checkpoint` and `p4 admin journal`, save the checkpoint",
741 doc = "in compressed (gzip) format, appending the `.gz` suffix to the file, but",
742 doc = "leave the journal uncompressed for use by replica servers."
743 )]
744 #[cfg_attr(
745 all(feature = "lt2022_2", not(feature = "lt2017_2")),
746 doc = "For `p4 admin checkpoint`, save the checkpoint in compressed (gzip)",
747 doc = "format, appending the `.gz` suffix to the file, but leave the journal",
748 doc = "uncompressed for use by replica servers."
749 )]
750 #[cfg_attr(
751 all(feature = "lt2023_1", not(feature = "lt2022_2")),
752 doc = "For `p4 admin checkpoint -Z`, save the checkpoint in compressed format,",
753 doc = "but leave the journal uncompressed for use by replica servers."
754 )]
755 #[cfg_attr(
756 not(feature = "lt2023_1"),
757 doc = "For `p4 admin checkpoint -Z`, save the checkpoint in compressed format,",
758 doc = "but leave the journal uncompressed for use by replica servers. The",
759 doc = "`.gz` suffix is appended to compressed journals and checkpoint files,",
760 doc = "which are in gzip format. If you do not specify `-z` or `-Z`, no",
761 doc = "compression occurs."
762 )]
763 pub fn compress_checkpoint_only(self) -> Admin<CheckPoint<compression::CheckPointOnly>> {
764 Admin {
765 bin: self.bin,
766 global_opts: self.global_opts,
767 sub_command: CheckPoint::<compression::CheckPointOnly> {
768 compression: compression::CheckPointOnly,
769 #[cfg(not(feature = "lt2023_1"))]
770 parallel: self.sub_command.parallel,
771 #[cfg(not(feature = "lt2023_1"))]
772 threads: self.sub_command.threads,
773 #[cfg(not(feature = "lt2023_1"))]
774 multiple_files: self.sub_command.multiple_files,
775 },
776 }
777 }
778}
779
780#[derive(Debug, Clone, Default)]
782pub struct Journal {
783 gzip: bool,
784}
785
786impl SubCommand for Journal {
787 fn name(&self) -> &str {
788 "journal"
789 }
790
791 fn inject_local_args(&self, command: &mut Command) {
792 if self.gzip {
793 command.arg("-z");
794 }
795 }
796}
797
798impl ParameterizedSpawn for Admin<Journal> {
799 type Input<'a> = Option<&'a str>;
800 type Output<'a> = Child;
801 type Error = std::io::Error;
802
803 fn spawn_with<'a>(&mut self, prefix: Self::Input<'a>) -> Result<Self::Output<'a>, Self::Error> {
810 let mut command = self.setup_command(&self.bin);
811
812 if let Some(prefix) = prefix {
813 command.arg(prefix);
814 }
815 command
816 .stdout(Stdio::piped())
817 .stderr(Stdio::piped())
818 .spawn()
819 }
820}
821
822impl SpawnExt for Admin<Journal> {
823 fn spawn<'a>(&mut self) -> Result<Self::Output<'a>, Self::Error> {
824 self.spawn_with(None)
825 }
826}
827
828impl Admin<Journal> {
829 #[cfg_attr(
834 feature = "lt2022_2",
835 doc = "For `p4 admin checkpoint` and `p4 admin journal`, save the checkpoint",
836 doc = "and saved journal file in compressed (gzip) format, appending the `.gz`",
837 doc = "suffix to the files."
838 )]
839 #[cfg_attr(
840 all(feature = "lt2023_1", not(feature = "lt2022_2")),
841 doc = "For `p4 admin checkpoint -z` and `p4 admin journal -z`, save the",
842 doc = "checkpoint and journal file in compressed format. The `.gz` suffix is",
843 doc = "appended to compressed journals and checkpoint files, which are in",
844 doc = "gzip format. If you do not specify `-z` or `-Z`, no compression occurs."
845 )]
846 #[cfg_attr(
847 not(feature = "lt2023_1"),
848 doc = "Save the journal file in compressed format. The `.gz` suffix is",
849 doc = "appended to compressed journals and checkpoint files, which are in",
850 doc = "gzip format. If you do not specify `-z`, no compression occurs."
851 )]
852 pub fn get_gzip(&self) -> bool {
853 self.sub_command.gzip
854 }
855
856 #[cfg_attr(
861 feature = "lt2022_2",
862 doc = "For `p4 admin checkpoint` and `p4 admin journal`, save the checkpoint",
863 doc = "and saved journal file in compressed (gzip) format, appending the `.gz`",
864 doc = "suffix to the files."
865 )]
866 #[cfg_attr(
867 all(feature = "lt2023_1", not(feature = "lt2022_2")),
868 doc = "For `p4 admin checkpoint -z` and `p4 admin journal -z`, save the",
869 doc = "checkpoint and journal file in compressed format. The `.gz` suffix is",
870 doc = "appended to compressed journals and checkpoint files, which are in",
871 doc = "gzip format. If you do not specify `-z` or `-Z`, no compression occurs."
872 )]
873 #[cfg_attr(
874 not(feature = "lt2023_1"),
875 doc = "Save the journal file in compressed format. The `.gz` suffix is",
876 doc = "appended to compressed journals and checkpoint files, which are in",
877 doc = "gzip format. If you do not specify `-z`, no compression occurs."
878 )]
879 pub fn set_gzip(&mut self, gzip: bool) -> &mut Self {
880 self.sub_command.gzip = gzip;
881 self
882 }
883
884 #[cfg_attr(
889 feature = "lt2022_2",
890 doc = "For `p4 admin checkpoint` and `p4 admin journal`, save the checkpoint",
891 doc = "and saved journal file in compressed (gzip) format, appending the `.gz`",
892 doc = "suffix to the files."
893 )]
894 #[cfg_attr(
895 all(feature = "lt2023_1", not(feature = "lt2022_2")),
896 doc = "For `p4 admin checkpoint -z` and `p4 admin journal -z`, save the",
897 doc = "checkpoint and journal file in compressed format. The `.gz` suffix is",
898 doc = "appended to compressed journals and checkpoint files, which are in",
899 doc = "gzip format. If you do not specify `-z` or `-Z`, no compression occurs."
900 )]
901 #[cfg_attr(
902 not(feature = "lt2023_1"),
903 doc = "Save the journal file in compressed format. The `.gz` suffix is",
904 doc = "appended to compressed journals and checkpoint files, which are in",
905 doc = "gzip format. If you do not specify `-z`, no compression occurs."
906 )]
907 pub fn gzip(mut self, gzip: bool) -> Self {
908 self.sub_command.gzip = gzip;
909 self
910 }
911}
912
913#[derive(Debug, Clone, Default)]
915pub struct Stop;
916
917impl SubCommand for Stop {
918 fn name(&self) -> &str {
919 "stop"
920 }
921
922 fn inject_local_args(&self, _: &mut Command) {}
923}
924
925#[derive(Debug, Clone, Default)]
927pub struct Restart;
928
929impl SubCommand for Restart {
930 fn name(&self) -> &str {
931 "restart"
932 }
933
934 fn inject_local_args(&self, _: &mut Command) {}
935}
936
937#[derive(Debug, Clone)]
939pub enum SpecifiedType {
940 Client,
941 Depot,
942 #[cfg(not(feature = "lt2018_1"))]
944 Repo,
945 Branch,
946 Label,
947 TypeMap,
948 Group,
949 User,
950 Job,
951 #[cfg(not(feature = "lt2016_1"))]
953 Stream,
954 #[cfg(not(feature = "lt2016_1"))]
956 Triggers,
957 #[cfg(not(feature = "lt2016_1"))]
959 Protect,
960 #[cfg(not(feature = "lt2016_1"))]
962 Server,
963 #[cfg(not(feature = "lt2016_1"))]
965 License,
966 #[cfg(not(feature = "lt2016_1"))]
968 JobSpec,
969}
970
971impl SpecifiedType {
972 pub(crate) fn to_str(&self) -> &str {
974 match self {
975 Self::Client => "client",
976 Self::Depot => "depot",
977 #[cfg(not(feature = "lt2018_1"))]
978 Self::Repo => "repo",
979 Self::Branch => "branch",
980 Self::Label => "label",
981 Self::TypeMap => "typemap",
982 Self::Group => "group",
983 Self::User => "user",
984 Self::Job => "job",
985 #[cfg(not(feature = "lt2016_1"))]
986 Self::Stream => "stream",
987 #[cfg(not(feature = "lt2016_1"))]
988 Self::Triggers => "triggers",
989 #[cfg(not(feature = "lt2016_1"))]
990 Self::Protect => "protect",
991 #[cfg(not(feature = "lt2016_1"))]
992 Self::Server => "server",
993 #[cfg(not(feature = "lt2016_1"))]
994 Self::License => "license",
995 #[cfg(not(feature = "lt2016_1"))]
996 Self::JobSpec => "jobspec",
997 }
998 }
999}
1000
1001pub mod spec {
1004 use super::SpecifiedType;
1005
1006 #[derive(Debug, Clone, Copy, Default)]
1008 pub struct All;
1009
1010 #[derive(Debug, Clone)]
1012 pub struct Selected(pub SpecifiedType);
1013}
1014
1015impl ExclusiveOption for spec::All {
1016 fn inject_args(&self, command: &mut Command) {
1017 command.arg("-a");
1018 }
1019}
1020
1021impl ExclusiveOption for spec::Selected {
1022 fn inject_args(&self, command: &mut Command) {
1023 command.arg("-s").arg(self.0.to_str());
1024 }
1025}
1026
1027#[derive(Debug, Clone, Default)]
1033pub struct UpdateSpecDepot<S = Unselected> {
1034 spec: S,
1035}
1036
1037impl<S: ExclusiveOption> SubCommand for UpdateSpecDepot<S> {
1038 fn name(&self) -> &str {
1039 "updatespecdepot"
1040 }
1041
1042 fn inject_local_args(&self, command: &mut Command) {
1043 self.spec.inject_args(command);
1044 }
1045}
1046
1047impl Admin<UpdateSpecDepot<Unselected>> {
1048 #[cfg_attr(
1053 feature = "lt2022_2",
1054 doc = "For `p4 admin updatespecdepot`, update the spec depot with all current",
1055 doc = "forms."
1056 )]
1057 #[cfg_attr(
1058 not(feature = "lt2022_2"),
1059 doc = "For `p4 admin updatespecdepot -a`, update the spec depot with all",
1060 doc = "current forms."
1061 )]
1062 pub fn all(self) -> Admin<UpdateSpecDepot<spec::All>> {
1063 Admin {
1064 bin: self.bin,
1065 global_opts: self.global_opts,
1066 sub_command: UpdateSpecDepot { spec: spec::All },
1067 }
1068 }
1069
1070 #[cfg_attr(
1075 feature = "lt2016_1",
1076 doc = "For `p4 admin updatespecdepot`, update the spec depot with forms of the",
1077 doc = "specified type, where type is one of `client`, `depot`, `branch`,",
1078 doc = "`label`, `typemap`, `group`, `user`, or `job`."
1079 )]
1080 #[cfg_attr(
1081 all(feature = "lt2018_1", not(feature = "lt2016_1")),
1082 doc = "For `p4 admin updatespecdepot`, update the spec depot with forms of the",
1083 doc = "specified type, where type is one of `client`, `depot`, `branch`,",
1084 doc = "`label`, `typemap`, `group`, `user`, `job`, `stream`, `triggers`,",
1085 doc = "`protect`, `server`, `license`, or `jobspec`."
1086 )]
1087 #[cfg_attr(
1088 all(feature = "lt2022_2", not(feature = "lt2018_1")),
1089 doc = "For `p4 admin updatespecdepot`, update the spec depot with forms of the",
1090 doc = "specified type, where type is one of `client`, `depot`, `repo`,",
1091 doc = "`branch`, `label`, `typemap`, `group`, `user`, `job`, `stream`,",
1092 doc = "`triggers`, `protect`, `server`, `license`, or `jobspec`."
1093 )]
1094 #[cfg_attr(
1095 not(feature = "lt2022_2"),
1096 doc = "For `p4 admin updatespecdepot -s`, update the spec depot with forms of",
1097 doc = "the specified type, where type is one of `client`, `depot`, `repo`,",
1098 doc = "`branch`, `label`, `typemap`, `group`, `user`, `job`, `stream`,",
1099 doc = "`triggers`, `protect`, `server`, `license`, or `jobspec`."
1100 )]
1101 pub fn specified_type(
1102 self,
1103 specified_type: SpecifiedType,
1104 ) -> Admin<UpdateSpecDepot<spec::Selected>> {
1105 Admin {
1106 bin: self.bin,
1107 global_opts: self.global_opts,
1108 sub_command: UpdateSpecDepot {
1109 spec: spec::Selected(specified_type),
1110 },
1111 }
1112 }
1113}
1114
1115impl Admin<UpdateSpecDepot<spec::Selected>> {
1116 #[cfg_attr(
1121 feature = "lt2016_1",
1122 doc = "For `p4 admin updatespecdepot`, update the spec depot with forms of the",
1123 doc = "specified type, where type is one of `client`, `depot`, `branch`,",
1124 doc = "`label`, `typemap`, `group`, `user`, or `job`."
1125 )]
1126 #[cfg_attr(
1127 all(feature = "lt2018_1", not(feature = "lt2016_1")),
1128 doc = "For `p4 admin updatespecdepot`, update the spec depot with forms of the",
1129 doc = "specified type, where type is one of `client`, `depot`, `branch`,",
1130 doc = "`label`, `typemap`, `group`, `user`, `job`, `stream`, `triggers`,",
1131 doc = "`protect`, `server`, `license`, or `jobspec`."
1132 )]
1133 #[cfg_attr(
1134 all(feature = "lt2022_2", not(feature = "lt2018_1")),
1135 doc = "For `p4 admin updatespecdepot`, update the spec depot with forms of the",
1136 doc = "specified type, where type is one of `client`, `depot`, `repo`,",
1137 doc = "`branch`, `label`, `typemap`, `group`, `user`, `job`, `stream`,",
1138 doc = "`triggers`, `protect`, `server`, `license`, or `jobspec`."
1139 )]
1140 #[cfg_attr(
1141 not(feature = "lt2022_2"),
1142 doc = "For `p4 admin updatespecdepot -s`, update the spec depot with forms of",
1143 doc = "the specified type, where type is one of `client`, `depot`, `repo`,",
1144 doc = "`branch`, `label`, `typemap`, `group`, `user`, `job`, `stream`,",
1145 doc = "`triggers`, `protect`, `server`, `license`, or `jobspec`."
1146 )]
1147 pub fn get_specified_type(&self) -> &SpecifiedType {
1148 &self.sub_command.spec.0
1149 }
1150
1151 #[cfg_attr(
1156 feature = "lt2016_1",
1157 doc = "For `p4 admin updatespecdepot`, update the spec depot with forms of the",
1158 doc = "specified type, where type is one of `client`, `depot`, `branch`,",
1159 doc = "`label`, `typemap`, `group`, `user`, or `job`."
1160 )]
1161 #[cfg_attr(
1162 all(feature = "lt2018_1", not(feature = "lt2016_1")),
1163 doc = "For `p4 admin updatespecdepot`, update the spec depot with forms of the",
1164 doc = "specified type, where type is one of `client`, `depot`, `branch`,",
1165 doc = "`label`, `typemap`, `group`, `user`, `job`, `stream`, `triggers`,",
1166 doc = "`protect`, `server`, `license`, or `jobspec`."
1167 )]
1168 #[cfg_attr(
1169 all(feature = "lt2022_2", not(feature = "lt2018_1")),
1170 doc = "For `p4 admin updatespecdepot`, update the spec depot with forms of the",
1171 doc = "specified type, where type is one of `client`, `depot`, `repo`,",
1172 doc = "`branch`, `label`, `typemap`, `group`, `user`, `job`, `stream`,",
1173 doc = "`triggers`, `protect`, `server`, `license`, or `jobspec`."
1174 )]
1175 #[cfg_attr(
1176 not(feature = "lt2022_2"),
1177 doc = "For `p4 admin updatespecdepot -s`, update the spec depot with forms of",
1178 doc = "the specified type, where type is one of `client`, `depot`, `repo`,",
1179 doc = "`branch`, `label`, `typemap`, `group`, `user`, `job`, `stream`,",
1180 doc = "`triggers`, `protect`, `server`, `license`, or `jobspec`."
1181 )]
1182 pub fn set_specified_type(&mut self, specified_type: SpecifiedType) -> &mut Self {
1183 self.sub_command.spec = spec::Selected(specified_type);
1184 self
1185 }
1186}
1187
1188pub mod set_password {
1191 #[derive(Debug, Clone, Copy, Default)]
1193 pub struct All;
1194
1195 #[derive(Debug, Clone)]
1197 pub struct User(pub String);
1198}
1199
1200impl ExclusiveOption for set_password::All {
1201 fn inject_args(&self, command: &mut Command) {
1202 command.arg("-a");
1203 }
1204}
1205
1206impl ExclusiveOption for set_password::User {
1207 fn inject_args(&self, command: &mut Command) {
1208 command.arg("-u").arg(&self.0);
1209 }
1210}
1211
1212#[cfg_attr(
1218 feature = "lt2025_2",
1219 doc = "`p4 admin resetpassword -a | -u user`: force users to reset their passwords."
1220)]
1221#[cfg_attr(
1222 not(feature = "lt2025_2"),
1223 doc = "`p4 admin resetpassword {-a | -u user} [-l]`: force users to reset their passwords."
1224)]
1225#[derive(Debug, Clone, Default)]
1226pub struct ResetPassword<T = Unselected> {
1227 set_password: T,
1228
1229 #[cfg(not(feature = "lt2025_2"))]
1231 super_user: bool,
1232}
1233
1234impl<T: ExclusiveOption> SubCommand for ResetPassword<T> {
1235 fn name(&self) -> &str {
1236 "resetpassword"
1237 }
1238
1239 fn inject_local_args(&self, command: &mut Command) {
1240 self.set_password.inject_args(command);
1241 #[cfg(not(feature = "lt2025_2"))]
1242 if self.super_user {
1243 command.arg("-l");
1244 }
1245 }
1246}
1247
1248impl Admin<ResetPassword<Unselected>> {
1249 #[cfg_attr(
1254 feature = "lt2023_1",
1255 doc = "Force password reset of all users with passwords, including the",
1256 doc = "superuser who issued the command. Only the passwords of users who",
1257 doc = "presently exist (and who have passwords) are reset."
1258 )]
1259 #[cfg_attr(not(feature = "lt2023_1"), doc = "All users.")]
1260 pub fn all(self) -> Admin<ResetPassword<set_password::All>> {
1261 Admin {
1262 bin: self.bin,
1263 global_opts: self.global_opts,
1264 sub_command: ResetPassword {
1265 set_password: set_password::All,
1266 #[cfg(not(feature = "lt2025_2"))]
1267 super_user: self.sub_command.super_user,
1268 },
1269 }
1270 }
1271
1272 #[cfg_attr(
1277 feature = "lt2023_1",
1278 doc = "Force a single user with an existing password to reset their password",
1279 doc = "before they can run another command."
1280 )]
1281 #[cfg_attr(not(feature = "lt2023_1"), doc = "The specified user.")]
1282 pub fn user(self, user: impl Into<String>) -> Admin<ResetPassword<set_password::User>> {
1283 Admin {
1284 bin: self.bin,
1285 global_opts: self.global_opts,
1286 sub_command: ResetPassword {
1287 set_password: set_password::User(user.into()),
1288 #[cfg(not(feature = "lt2025_2"))]
1289 super_user: self.sub_command.super_user,
1290 },
1291 }
1292 }
1293}
1294
1295impl Admin<ResetPassword<set_password::User>> {
1296 #[cfg_attr(
1301 feature = "lt2023_1",
1302 doc = "Force a single user with an existing password to reset their password",
1303 doc = "before they can run another command."
1304 )]
1305 #[cfg_attr(not(feature = "lt2023_1"), doc = "The specified user.")]
1306 pub fn get_user(&self) -> &str {
1307 &self.sub_command.set_password.0
1308 }
1309
1310 #[cfg_attr(
1315 feature = "lt2023_1",
1316 doc = "Force a single user with an existing password to reset their password",
1317 doc = "before they can run another command."
1318 )]
1319 #[cfg_attr(not(feature = "lt2023_1"), doc = "The specified user.")]
1320 pub fn set_user(&mut self, user: impl Into<String>) -> &mut Self {
1321 self.sub_command.set_password.0 = user.into();
1322 self
1323 }
1324}
1325
1326impl<T: ExclusiveOption> Admin<ResetPassword<T>> {
1327 #[cfg(not(feature = "lt2025_2"))]
1333 pub fn get_super_user(&self) -> bool {
1334 self.sub_command.super_user
1335 }
1336
1337 #[cfg(not(feature = "lt2025_2"))]
1343 pub fn set_super_user(&mut self, super_user: bool) -> &mut Self {
1344 self.sub_command.super_user = super_user;
1345 self
1346 }
1347
1348 #[cfg(not(feature = "lt2025_2"))]
1354 pub fn super_user(mut self, super_user: bool) -> Self {
1355 self.sub_command.super_user = super_user;
1356 self
1357 }
1358}
1359
1360#[cfg(not(feature = "lt2015_1"))]
1363#[derive(Debug, Clone, Default)]
1364pub struct SetLdapUsers;
1365
1366#[cfg(not(feature = "lt2015_1"))]
1367impl SubCommand for SetLdapUsers {
1368 fn name(&self) -> &str {
1369 "setldapusers"
1370 }
1371
1372 fn inject_local_args(&self, _: &mut Command) {}
1373}
1374
1375#[cfg(not(feature = "lt2018_1"))]
1378#[derive(Debug, Clone, Default)]
1379pub struct EndJournal;
1380
1381#[cfg(not(feature = "lt2018_1"))]
1382impl SubCommand for EndJournal {
1383 fn name(&self) -> &str {
1384 "end-journal"
1385 }
1386
1387 fn inject_local_args(&self, _: &mut Command) {}
1388}
1389
1390#[cfg(not(feature = "lt2023_1"))]
1393#[derive(Debug, Clone, Default)]
1394pub struct SysInfo;
1395
1396#[cfg(not(feature = "lt2023_1"))]
1397impl SubCommand for SysInfo {
1398 fn name(&self) -> &str {
1399 "sysinfo"
1400 }
1401
1402 fn inject_local_args(&self, _: &mut Command) {}
1403}
1404
1405#[cfg(not(feature = "lt2023_1"))]
1408#[derive(Debug, Clone, Default)]
1409pub struct ResourceMonitor;
1410
1411#[cfg(not(feature = "lt2023_1"))]
1412impl SubCommand for ResourceMonitor {
1413 fn name(&self) -> &str {
1414 "resource-monitor"
1415 }
1416
1417 fn inject_local_args(&self, _: &mut Command) {}
1418}
1419
1420#[cfg(not(feature = "lt2025_2"))]
1423pub mod reconcile {
1424 #[derive(Debug, Clone, Copy, Default)]
1426 pub struct RestrictOnly;
1427
1428 #[derive(Debug, Clone, Copy, Default)]
1430 pub struct ExpandOnly;
1431}
1432
1433#[cfg(not(feature = "lt2025_2"))]
1434impl ExclusiveOption for reconcile::RestrictOnly {
1435 fn inject_args(&self, command: &mut Command) {
1436 command.arg("--restrict-only");
1437 }
1438}
1439
1440#[cfg(not(feature = "lt2025_2"))]
1441impl ExclusiveOption for reconcile::ExpandOnly {
1442 fn inject_args(&self, command: &mut Command) {
1443 command.arg("--expand-only");
1444 }
1445}
1446
1447#[cfg(not(feature = "lt2025_2"))]
1455#[derive(Debug, Clone, Default)]
1456pub struct ReplicaFilterReconcile<M = Unselected> {
1457 reconcile: M,
1458}
1459
1460#[cfg(not(feature = "lt2025_2"))]
1461impl<M: ExclusiveOption> SubCommand for ReplicaFilterReconcile<M> {
1462 fn name(&self) -> &str {
1463 "replica-filter-reconcile"
1464 }
1465
1466 fn inject_local_args(&self, command: &mut Command) {
1467 self.reconcile.inject_args(command);
1468 }
1469}
1470
1471#[cfg(not(feature = "lt2025_2"))]
1472impl Admin<ReplicaFilterReconcile<Unselected>> {
1473 pub fn restrict_only(self) -> Admin<ReplicaFilterReconcile<reconcile::RestrictOnly>> {
1480 Admin {
1481 bin: self.bin,
1482 global_opts: self.global_opts,
1483 sub_command: ReplicaFilterReconcile {
1484 reconcile: reconcile::RestrictOnly,
1485 },
1486 }
1487 }
1488
1489 pub fn expand_only(self) -> Admin<ReplicaFilterReconcile<reconcile::ExpandOnly>> {
1496 Admin {
1497 bin: self.bin,
1498 global_opts: self.global_opts,
1499 sub_command: ReplicaFilterReconcile {
1500 reconcile: reconcile::ExpandOnly,
1501 },
1502 }
1503 }
1504}
1505
1506#[cfg(not(feature = "lt2025_2"))]
1507impl<M: ExclusiveOption> ParameterizedSpawn for Admin<ReplicaFilterReconcile<M>> {
1508 type Input<'a> = &'a [&'a OsStr];
1509 type Output<'a> = Child;
1510 type Error = std::io::Error;
1511
1512 fn spawn_with<'a>(&mut self, tables: Self::Input<'a>) -> Result<Self::Output<'a>, Self::Error> {
1518 self.setup_command(&self.bin)
1519 .args(tables)
1520 .stdout(Stdio::piped())
1521 .stderr(Stdio::piped())
1522 .spawn()
1523 }
1524}
1525
1526#[cfg(test)]
1527mod tests {
1528 use super::*;
1529 use crate::cmd::args_of;
1530
1531 #[test]
1534 fn stop() {
1535 let admin = AdminEntry::new("p4", GlobalOpts::new()).stop();
1536
1537 assert_eq!(args_of(&admin.setup_command("p4")), ["admin", "stop"]);
1538 }
1539
1540 #[test]
1541 fn restart() {
1542 let admin = AdminEntry::new("p4", GlobalOpts::new()).restart();
1543
1544 assert_eq!(args_of(&admin.setup_command("p4")), ["admin", "restart"]);
1545 }
1546
1547 #[cfg(not(feature = "lt2015_1"))]
1548 #[test]
1549 fn setldapusers() {
1550 let admin = AdminEntry::new("p4", GlobalOpts::new()).setldapusers();
1551
1552 assert_eq!(
1553 args_of(&admin.setup_command("p4")),
1554 ["admin", "setldapusers"]
1555 );
1556 }
1557
1558 #[cfg(not(feature = "lt2018_1"))]
1559 #[test]
1560 fn end_journal() {
1561 let admin = AdminEntry::new("p4", GlobalOpts::new()).end_journal();
1562
1563 assert_eq!(
1564 args_of(&admin.setup_command("p4")),
1565 ["admin", "end-journal"]
1566 );
1567 }
1568
1569 #[cfg(not(feature = "lt2023_1"))]
1570 #[test]
1571 fn sysinfo() {
1572 let admin = AdminEntry::new("p4", GlobalOpts::new()).sysinfo();
1573
1574 assert_eq!(args_of(&admin.setup_command("p4")), ["admin", "sysinfo"]);
1575 }
1576
1577 #[cfg(not(feature = "lt2023_1"))]
1578 #[test]
1579 fn resource_monitor() {
1580 let admin = AdminEntry::new("p4", GlobalOpts::new()).resource_monitor();
1581
1582 assert_eq!(
1583 args_of(&admin.setup_command("p4")),
1584 ["admin", "resource-monitor"]
1585 );
1586 }
1587
1588 #[test]
1589 fn checkpoint_compress_both() {
1590 let admin = AdminEntry::new("p4", GlobalOpts::new())
1591 .checkpoint()
1592 .compress_both();
1593
1594 assert_eq!(
1595 args_of(&admin.setup_command("p4")),
1596 ["admin", "checkpoint", "-z"]
1597 );
1598 }
1599
1600 #[test]
1601 fn checkpoint_compress_checkpoint_only() {
1602 let admin = AdminEntry::new("p4", GlobalOpts::new())
1603 .checkpoint()
1604 .compress_checkpoint_only();
1605
1606 assert_eq!(
1607 args_of(&admin.setup_command("p4")),
1608 ["admin", "checkpoint", "-Z"]
1609 );
1610 }
1611
1612 #[test]
1613 fn checkpoint_with_prefix() {
1614 let admin = AdminEntry::new("p4", GlobalOpts::new())
1615 .checkpoint()
1616 .compress_both();
1617
1618 let mut command = admin.setup_command("p4");
1621 command.arg("ckp");
1622
1623 assert_eq!(args_of(&command), ["admin", "checkpoint", "-z", "ckp"]);
1624 }
1625
1626 #[cfg(not(feature = "lt2023_1"))]
1627 #[test]
1628 fn checkpoint_parallel_options() {
1629 let mut admin = AdminEntry::new("p4", GlobalOpts::new()).checkpoint();
1630 admin
1631 .set_parallel(true)
1632 .set_threads(4)
1633 .set_multiple_files(true);
1634
1635 assert_eq!(
1636 args_of(&admin.setup_command("p4")),
1637 ["admin", "checkpoint", "-p", "-N", "4", "-m"]
1638 );
1639 }
1640
1641 #[test]
1642 fn journal_gzip() {
1643 let mut admin = AdminEntry::new("p4", GlobalOpts::new()).journal();
1644 admin.set_gzip(true);
1645
1646 assert_eq!(
1647 args_of(&admin.setup_command("p4")),
1648 ["admin", "journal", "-z"]
1649 );
1650 }
1651
1652 #[test]
1653 fn updatespecdepot_all() {
1654 let admin = AdminEntry::new("p4", GlobalOpts::new())
1655 .updatespecdepot()
1656 .all();
1657
1658 assert_eq!(
1659 args_of(&admin.setup_command("p4")),
1660 ["admin", "updatespecdepot", "-a"]
1661 );
1662 }
1663
1664 #[test]
1667 fn updatespecdepot_specified_type() {
1668 let admin = AdminEntry::new("p4", GlobalOpts::new())
1669 .updatespecdepot()
1670 .specified_type(SpecifiedType::Client);
1671
1672 assert_eq!(
1673 args_of(&admin.setup_command("p4")),
1674 ["admin", "updatespecdepot", "-s", "client"]
1675 );
1676 }
1677
1678 #[test]
1679 fn resetpassword_all() {
1680 let admin = AdminEntry::new("p4", GlobalOpts::new())
1681 .resetpassword()
1682 .all();
1683
1684 assert_eq!(
1685 args_of(&admin.setup_command("p4")),
1686 ["admin", "resetpassword", "-a"]
1687 );
1688 }
1689
1690 #[test]
1691 fn resetpassword_single_user() {
1692 let admin = AdminEntry::new("p4", GlobalOpts::new())
1693 .resetpassword()
1694 .user("bruno");
1695
1696 assert_eq!(
1697 args_of(&admin.setup_command("p4")),
1698 ["admin", "resetpassword", "-u", "bruno"]
1699 );
1700 }
1701
1702 #[cfg(not(feature = "lt2025_2"))]
1703 #[test]
1704 fn resetpassword_super_user() {
1705 let admin = AdminEntry::new("p4", GlobalOpts::new())
1706 .resetpassword()
1707 .super_user(true);
1708
1709 assert_eq!(
1710 args_of(&admin.setup_command("p4")),
1711 ["admin", "resetpassword", "-l"]
1712 );
1713 }
1714
1715 #[cfg(not(feature = "lt2025_2"))]
1716 #[test]
1717 fn replica_filter_reconcile_restrict_only() {
1718 let admin = AdminEntry::new("p4", GlobalOpts::new())
1719 .replica_filter_reconcile()
1720 .restrict_only();
1721
1722 assert_eq!(
1723 args_of(&admin.setup_command("p4")),
1724 ["admin", "replica-filter-reconcile", "--restrict-only"]
1725 );
1726 }
1727
1728 #[cfg(not(feature = "lt2025_2"))]
1729 #[test]
1730 fn replica_filter_reconcile_expand_only() {
1731 let admin = AdminEntry::new("p4", GlobalOpts::new())
1732 .replica_filter_reconcile()
1733 .expand_only();
1734
1735 assert_eq!(
1736 args_of(&admin.setup_command("p4")),
1737 ["admin", "replica-filter-reconcile", "--expand-only"]
1738 );
1739 }
1740
1741 #[test]
1742 fn global_opts_are_injected_once() {
1743 let global_opts = GlobalOpts::new().port("localhost:1666");
1744 let admin = AdminEntry::new("p4", global_opts).checkpoint();
1745
1746 assert_eq!(
1749 args_of(&admin.setup_command("p4")),
1750 ["-p", "localhost:1666", "admin", "checkpoint"]
1751 );
1752 }
1753}