Skip to main content

perforce_cli/cmd/change/
delete.rs

1use std::process::Command;
2
3use super::{
4    ArbitraryJobStatus, Change, ExclusiveOption, ForceOperationMode, OriginalChangeListMode,
5    TakesChangeList, Unselected,
6};
7
8// ---------------------------------------------------------------------------
9// Form dimension: the delete variants
10// ---------------------------------------------------------------------------
11
12/// Local variant of the delete form: `p4 change -d [-f -s -O] changelist`.
13///
14#[cfg_attr(
15    not(feature = "lt2015_2"),
16    doc = "The remote variant is [`RemoteDeleteMode`]."
17)]
18#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
19pub struct LocalDeleteMode;
20
21/// Remote variant of the delete form: `p4 change -d -f --serverid=X changelist`.
22#[cfg(not(feature = "lt2015_2"))]
23#[derive(Debug, Clone, PartialEq, Eq)]
24pub struct RemoteDeleteMode {
25    pub(super) server_id: String,
26}
27
28/// The delete form: `p4 change -d [-f -s -O] changelist`.
29///
30/// The `L` parameter distinguishes the [`LocalDeleteMode`] form from the
31#[cfg_attr(not(feature = "lt2015_2"), doc = "[`RemoteDeleteMode`] form.")]
32#[cfg_attr(feature = "lt2015_2", doc = "remote form.")]
33#[derive(Debug, Clone, PartialEq, Eq)]
34pub struct DeleteMode<L = LocalDeleteMode> {
35    pub(super) loc: L,
36}
37
38impl ExclusiveOption for LocalDeleteMode {}
39
40#[cfg(not(feature = "lt2015_2"))]
41impl ExclusiveOption for RemoteDeleteMode {
42    fn inject_args(&self, command: &mut Command) {
43        command.arg("-f");
44        #[cfg(feature = "lt2022_1")]
45        command.arg(format!("--server={}", self.server_id));
46        #[cfg(not(feature = "lt2022_1"))]
47        command.arg(format!("--serverid={}", self.server_id));
48    }
49}
50
51impl<L: ExclusiveOption> ExclusiveOption for DeleteMode<L> {
52    fn inject_args(&self, command: &mut Command) {
53        command.arg("-d");
54        self.loc.inject_args(command);
55    }
56}
57
58impl<L> TakesChangeList for DeleteMode<L> {}
59
60// ---------------------------------------------------------------------------
61// Mapping traits for entering the delete forms
62// ---------------------------------------------------------------------------
63
64/// Marker trait for the option states allowed when entering the local
65/// `-d` form from the edit form.
66///
67/// The same trait bounds both orthogonal dimensions of the transition:
68///
69/// - the operation dimension: `Unselected` and [`ForceOperationMode`],
70///   since `-d` accepts `-f` but not `-u`;
71/// - the changelist-reference dimension: `Unselected` and
72///   [`OriginalChangeListMode`], since `-d` accepts `-O` but not `-I`.
73///
74/// `Unselected` is shared by both dimensions and is therefore implemented
75/// only once.
76#[doc(hidden)]
77pub trait TransferDeleteMode {}
78
79// Operation dimension: `-d` accepts `-f` but not `-u`.
80impl TransferDeleteMode for Unselected {}
81impl TransferDeleteMode for ForceOperationMode {}
82
83// Changelist-reference dimension: `-d` accepts `-O` but not `-I`.
84impl TransferDeleteMode for OriginalChangeListMode {}
85
86/// Marks the operation modes allowed when entering the remote-delete form.
87///
88/// Only `Unselected` and `ForceOperationMode` are allowed: the remote
89/// delete form accepts neither `-u` nor any explicit `-f` (its `-f` is
90/// built in).
91#[cfg(not(feature = "lt2015_2"))]
92#[doc(hidden)]
93pub trait TransferRemoteDeleteMode {}
94
95#[cfg(not(feature = "lt2015_2"))]
96impl TransferRemoteDeleteMode for Unselected {}
97#[cfg(not(feature = "lt2015_2"))]
98impl TransferRemoteDeleteMode for ForceOperationMode {}
99
100// ---------------------------------------------------------------------------
101// DeleteMode<LocalDeleteMode>: `-f`, `-s`, `-O` may still be selected
102// ---------------------------------------------------------------------------
103
104impl<O, C> Change<DeleteMode<LocalDeleteMode>, O, C, Unselected> {
105    /// Selects `-s` in the delete form.
106    pub fn arbitrary_job_status(
107        self,
108    ) -> Change<DeleteMode<LocalDeleteMode>, O, C, ArbitraryJobStatus> {
109        Change {
110            bin: self.bin,
111            global_opts: self.global_opts,
112            mode: self.mode,
113            permission_mode: self.permission_mode,
114            changelist_mode: self.changelist_mode,
115            job_status_mode: ArbitraryJobStatus,
116        }
117    }
118}
119
120impl<C, S> Change<DeleteMode<LocalDeleteMode>, Unselected, C, S> {
121    /// Selects `-f` in the delete form (forcibly delete a submitted
122    /// changelist).
123    pub fn force(self) -> Change<DeleteMode<LocalDeleteMode>, ForceOperationMode, C, S> {
124        Change {
125            bin: self.bin,
126            global_opts: self.global_opts,
127            mode: self.mode,
128            permission_mode: ForceOperationMode,
129            changelist_mode: self.changelist_mode,
130            job_status_mode: self.job_status_mode,
131        }
132    }
133}
134
135impl<O, S> Change<DeleteMode<LocalDeleteMode>, O, Unselected, S> {
136    /// Selects `-O` in the delete form (reference by original changelist
137    /// number).
138    pub fn original(self) -> Change<DeleteMode<LocalDeleteMode>, O, OriginalChangeListMode, S> {
139        Change {
140            bin: self.bin,
141            global_opts: self.global_opts,
142            mode: self.mode,
143            permission_mode: self.permission_mode,
144            changelist_mode: OriginalChangeListMode,
145            job_status_mode: self.job_status_mode,
146        }
147    }
148}
149
150// Local delete -> remote delete: no `-s`/`-O`; `-u` is never allowed.
151#[cfg(not(feature = "lt2015_2"))]
152impl<O: TransferRemoteDeleteMode> Change<DeleteMode<LocalDeleteMode>, O, Unselected, Unselected> {
153    /// Transitions to the remote delete form.
154    ///
155    /// Available from the local delete form as long as neither `-s`,
156    /// `-O`, nor `-u` is selected (the remote delete form accepts no
157    /// extra options; its `-f` is built in). A previously selected `-f`
158    /// is simply dropped in favor of the built-in one.
159    ///
160    /// `server_id` is the server id of the commit server the changelist's
161    /// client is bound to.
162    pub fn server_id(
163        self,
164        server_id: impl Into<String>,
165    ) -> Change<DeleteMode<RemoteDeleteMode>, Unselected, Unselected, Unselected> {
166        Change {
167            bin: self.bin,
168            global_opts: self.global_opts,
169            mode: DeleteMode {
170                loc: RemoteDeleteMode {
171                    server_id: server_id.into(),
172                },
173            },
174            permission_mode: Unselected,
175            changelist_mode: Unselected,
176            job_status_mode: Unselected,
177        }
178    }
179}