Skip to main content

perforce_cli/cmd/change/
userorvis.rs

1use std::process::Command;
2
3#[cfg(not(feature = "lt2022_1"))]
4use super::IdentityChangeListMode;
5#[cfg(not(feature = "lt2015_2"))]
6use super::OnlyIdentityChangeListMode;
7use super::{
8    Change, ExclusiveOption, ForceOperationMode, OnlyForceOperationMode,
9    OnlyOriginalChangeListMode, OnlyUpdateOperationMode, OriginalChangeListMode, TakesChangeList,
10    Unselected, UpdateOperationMode, Visibility,
11};
12
13// ---------------------------------------------------------------------------
14// Form dimension: the merged `-t` / `-U` form
15// ---------------------------------------------------------------------------
16
17/// The change-type / owner-transfer form:
18/// `p4 change -t restricted | public [-U user] [-f|-u|-O|-I] changelist`.
19///
20/// The `-t` and `-U` syntax forms of `p4 change` describe the same
21/// operation — changing the type and/or the owner of a changelist — so both
22/// are encoded by this single type. At least one of the two values is always
23/// set: entry points and builder methods only ever assign a value, never
24/// clear one.
25///
26/// The form accepts at most one of `-f`, `-u`, `-O`, `-I` (carried by the
27/// `Only*` modes) and never `-s`.
28#[derive(Debug, Clone, PartialEq, Eq)]
29pub struct UserOrVisibilityMode {
30    pub(super) visibility: Option<Visibility>,
31
32    pub(super) user: Option<String>,
33}
34
35impl ExclusiveOption for UserOrVisibilityMode {
36    fn inject_args(&self, command: &mut Command) {
37        if let Some(visibility) = &self.visibility {
38            command.arg("-t").arg(visibility.as_str());
39        }
40
41        if let Some(user) = &self.user {
42            command.arg("-U").arg(user);
43        }
44    }
45}
46
47impl TakesChangeList for UserOrVisibilityMode {}
48
49// ---------------------------------------------------------------------------
50// Mapping trait for entering the form
51// ---------------------------------------------------------------------------
52
53/// Maps the combined `(operation, changelist-reference)` selection when
54/// entering the `-t` / `-U` form.
55///
56/// Only the five legal combinations of that form (`nothing`, `-f`, `-u`,
57/// `-O`, `-I`) implement this, so `-f` together with `-O` (and similar)
58/// fails to compile rather than silently dropping one option.
59///
60/// The output states are associated types so callers never have to specify
61/// them: they are uniquely determined by the input combination.
62#[doc(hidden)]
63pub trait TransferUVMode {
64    type P;
65    type C;
66    fn transfer(self) -> (Self::P, Self::C);
67}
68
69impl TransferUVMode for (Unselected, Unselected) {
70    type P = Unselected;
71    type C = Unselected;
72    fn transfer(self) -> (Unselected, Unselected) {
73        (Unselected, Unselected)
74    }
75}
76
77impl TransferUVMode for (ForceOperationMode, Unselected) {
78    type P = OnlyForceOperationMode;
79    type C = Unselected;
80    fn transfer(self) -> (OnlyForceOperationMode, Unselected) {
81        (OnlyForceOperationMode, Unselected)
82    }
83}
84
85impl TransferUVMode for (UpdateOperationMode, Unselected) {
86    type P = OnlyUpdateOperationMode;
87    type C = Unselected;
88    fn transfer(self) -> (OnlyUpdateOperationMode, Unselected) {
89        (OnlyUpdateOperationMode, Unselected)
90    }
91}
92
93impl TransferUVMode for (Unselected, OriginalChangeListMode) {
94    type P = Unselected;
95    type C = OnlyOriginalChangeListMode;
96    fn transfer(self) -> (Unselected, OnlyOriginalChangeListMode) {
97        (Unselected, OnlyOriginalChangeListMode)
98    }
99}
100
101#[cfg(not(feature = "lt2022_1"))]
102impl TransferUVMode for (Unselected, IdentityChangeListMode) {
103    type P = Unselected;
104    type C = OnlyIdentityChangeListMode;
105    fn transfer(self) -> (Unselected, OnlyIdentityChangeListMode) {
106        (Unselected, OnlyIdentityChangeListMode)
107    }
108}
109
110// ---------------------------------------------------------------------------
111// UserOrVisibilityMode: setting the form values
112// ---------------------------------------------------------------------------
113
114impl<O, C> Change<UserOrVisibilityMode, O, C, Unselected> {
115    /// Sets the new owner (`-U user`) of the changelist.
116    ///
117    /// `user` is the user the changelist is transferred to.
118    pub fn user(mut self, user: impl Into<String>) -> Self {
119        self.mode.user = Some(user.into());
120        self
121    }
122
123    /// Sets the new owner (`-U user`) of the changelist.
124    ///
125    /// `user` is the user the changelist is transferred to.
126    pub fn set_user(&mut self, user: impl Into<String>) -> &mut Self {
127        self.mode.user = Some(user.into());
128        self
129    }
130
131    /// Returns the new owner (`-U user`) of the changelist, if set.
132    pub fn get_user(&self) -> Option<&str> {
133        self.mode.user.as_deref()
134    }
135
136    /// Sets the changelist visibility (`-t restricted | public`).
137    ///
138    /// `visibility` selects the new changelist type.
139    pub fn visibility(mut self, visibility: Visibility) -> Self {
140        self.mode.visibility = Some(visibility);
141        self
142    }
143
144    /// Sets the changelist visibility (`-t restricted | public`).
145    ///
146    /// `visibility` selects the new changelist type.
147    pub fn set_visibility(&mut self, visibility: Visibility) -> &mut Self {
148        self.mode.visibility = Some(visibility);
149        self
150    }
151
152    /// Returns the changelist visibility (`-t restricted | public`), if set.
153    pub fn get_visibility(&self) -> Option<Visibility> {
154        self.mode.visibility
155    }
156}
157
158// ---------------------------------------------------------------------------
159// UserOrVisibilityMode: selecting the single extra option
160// ---------------------------------------------------------------------------
161
162// The form accepts at most one of `-f`, `-u`, `-O`, `-I`, so each selection
163// method is only available while neither dimension has been selected yet.
164impl Change<UserOrVisibilityMode, Unselected, Unselected, Unselected> {
165    /// Selects `-f` (force the type/owner change).
166    ///
167    #[cfg_attr(
168        not(feature = "lt2015_2"),
169        doc = "Mutually exclusive with `-u`, `-O`, and `-I`."
170    )]
171    #[cfg_attr(feature = "lt2015_2", doc = "Mutually exclusive with `-u` and `-O`.")]
172    pub fn force(
173        self,
174    ) -> Change<UserOrVisibilityMode, OnlyForceOperationMode, Unselected, Unselected> {
175        Change {
176            bin: self.bin,
177            global_opts: self.global_opts,
178            mode: self.mode,
179            permission_mode: OnlyForceOperationMode,
180            changelist_mode: Unselected,
181            job_status_mode: Unselected,
182        }
183    }
184
185    /// Selects `-u` (update a submitted changelist).
186    ///
187    #[cfg_attr(
188        not(feature = "lt2015_2"),
189        doc = "Mutually exclusive with `-f`, `-O`, and `-I`."
190    )]
191    #[cfg_attr(feature = "lt2015_2", doc = "Mutually exclusive with `-f` and `-O`.")]
192    pub fn update(
193        self,
194    ) -> Change<UserOrVisibilityMode, OnlyUpdateOperationMode, Unselected, Unselected> {
195        Change {
196            bin: self.bin,
197            global_opts: self.global_opts,
198            mode: self.mode,
199            permission_mode: OnlyUpdateOperationMode,
200            changelist_mode: Unselected,
201            job_status_mode: Unselected,
202        }
203    }
204
205    /// Selects `-O`: interpret the changelist number as the original,
206    /// pre-renumber number.
207    ///
208    #[cfg_attr(
209        not(feature = "lt2015_2"),
210        doc = "Mutually exclusive with `-f`, `-u`, and `-I`."
211    )]
212    #[cfg_attr(feature = "lt2015_2", doc = "Mutually exclusive with `-f` and `-u`.")]
213    pub fn original(
214        self,
215    ) -> Change<UserOrVisibilityMode, Unselected, OnlyOriginalChangeListMode, Unselected> {
216        Change {
217            bin: self.bin,
218            global_opts: self.global_opts,
219            mode: self.mode,
220            permission_mode: Unselected,
221            changelist_mode: OnlyOriginalChangeListMode,
222            job_status_mode: Unselected,
223        }
224    }
225
226    /// Selects `-I`: interpret the changelist number as the Identity field.
227    ///
228    /// Mutually exclusive with `-f`, `-u`, and `-O`.
229    #[cfg(not(feature = "lt2015_2"))]
230    pub fn identity(
231        self,
232    ) -> Change<UserOrVisibilityMode, Unselected, OnlyIdentityChangeListMode, Unselected> {
233        Change {
234            bin: self.bin,
235            global_opts: self.global_opts,
236            mode: self.mode,
237            permission_mode: Unselected,
238            changelist_mode: OnlyIdentityChangeListMode,
239            job_status_mode: Unselected,
240        }
241    }
242}