Skip to main content

perforce_cli/
lib.rs

1use std::path::{Path, PathBuf};
2
3use crate::cmd::Add;
4use crate::cmd::AdminEntry;
5#[cfg(not(feature = "lt2016_1"))]
6use crate::cmd::Aliases;
7use crate::cmd::Annotate;
8use crate::cmd::Archive;
9use crate::cmd::Attribute;
10#[cfg(not(feature = "lt2017_2"))]
11use crate::cmd::BackGroundTask;
12use crate::cmd::Branch;
13use crate::cmd::Branches;
14use crate::cmd::CachePurge;
15use crate::cmd::Change;
16use crate::cmd::Changes;
17use crate::cmd::Clean;
18use crate::cmd::Client;
19use crate::cmd::Describe;
20use crate::cmd::Diff;
21use crate::cmd::Diff2;
22use crate::cmd::Edit;
23use crate::cmd::FileLog;
24use crate::cmd::Print;
25use crate::cmd::Sync;
26use crate::cmd::Where;
27use crate::global::GlobalOpts;
28
29pub mod cmd;
30pub mod global;
31pub mod spawn;
32
33pub mod prelude {
34    pub use crate::cmd::*;
35    pub use crate::global::*;
36    pub use crate::spawn::*;
37}
38
39#[derive(Debug, Clone)]
40pub struct P4Cli {
41    bin: PathBuf,
42
43    global_opts: GlobalOpts,
44}
45
46impl Default for P4Cli {
47    fn default() -> Self {
48        Self {
49            bin: PathBuf::from("p4"),
50            global_opts: GlobalOpts::default(),
51        }
52    }
53}
54
55impl P4Cli {
56    /// Create a new Perforce command-line client.
57    ///
58    /// `bin` is the path to the Perforce command-line executable.
59    pub fn new(bin: impl Into<PathBuf>, global_opts: GlobalOpts) -> Self {
60        Self {
61            bin: bin.into(),
62            global_opts,
63        }
64    }
65
66    /// Set the Perforce command path.
67    pub fn bin(mut self, bin: impl Into<PathBuf>) -> Self {
68        self.set_bin(bin);
69        self
70    }
71
72    /// Set the global options.
73    pub fn global_opts(mut self, global_opts: GlobalOpts) -> Self {
74        self.set_global_opts(global_opts);
75        self
76    }
77
78    /// Get the Perforce command path.
79    pub fn get_bin(&self) -> &Path {
80        &self.bin
81    }
82
83    /// Get the global options.
84    pub fn get_global_opts(&self) -> &GlobalOpts {
85        &self.global_opts
86    }
87
88    /// Set the Perforce command path.
89    pub fn set_bin(&mut self, bin: impl Into<PathBuf>) {
90        self.bin = bin.into();
91    }
92
93    /// Set the global options.
94    pub fn set_global_opts(&mut self, global_opts: GlobalOpts) {
95        self.global_opts = global_opts;
96    }
97
98    /// Open files in a client workspace for addition to the depot.
99    pub fn add(&self) -> Add {
100        Add::new(self.bin.clone(), self.global_opts.clone())
101    }
102
103    /// Perform administrative operations on the server.
104    pub fn admin(&self) -> AdminEntry {
105        AdminEntry::new(self.bin.clone(), self.global_opts.clone())
106    }
107
108    /// Display command aliases that are currently defined in a .p4aliases file.
109    #[cfg(not(feature = "lt2016_1"))]
110    pub fn aliases(&self) -> Aliases {
111        Aliases::new(self.bin.clone(), self.global_opts.clone())
112    }
113
114    /// Print file lines along with their revisions.
115    pub fn annotate(&self) -> Annotate {
116        Annotate::new(self.bin.clone(), self.global_opts.clone())
117    }
118
119    /// Archive obsolete revisions to an archive depot.
120    pub fn archive(&self) -> Archive {
121        Archive::new(self.bin.clone(), self.global_opts.clone())
122    }
123
124    /// Set per-revision attributes on file revisions.
125    pub fn attribute(&self) -> Attribute {
126        Attribute::new(self.bin.clone(), self.global_opts.clone())
127    }
128
129    /// Run a background command or trigger on the server.
130    ///
131    /// The returned builder starts with no task target; call
132    /// [`BackGroundTask::execute`] (`-e`) or [`BackGroundTask::trigger`]
133    /// (`-t`) to select the required target before spawning.
134    #[cfg(not(feature = "lt2017_2"))]
135    pub fn bgtask(&self) -> BackGroundTask {
136        BackGroundTask::new(self.bin.clone(), self.global_opts.clone())
137    }
138
139    /// Create or edit a branch mapping and its view.
140    pub fn branch(&self) -> Branch {
141        Branch::new(self.bin.clone(), self.global_opts.clone())
142    }
143
144    /// List existing branch mappings.
145    pub fn branches(&self) -> Branches {
146        Branches::new(self.bin.clone(), self.global_opts.clone())
147    }
148
149    /// Reclaim disk space on a replicated server.
150    ///
151    /// The returned builder starts with no purge goal and has no effect;
152    /// call [`CachePurge::purge_all`] (`-a`), [`CachePurge::free_space`]
153    /// (`-f`), [`CachePurge::revision_count`] (`-m`), or
154    /// [`CachePurge::size`] (`-s`) to select the required goal before
155    /// spawning.
156    pub fn cachepurge(&self) -> CachePurge {
157        CachePurge::new(self.bin.clone(), self.global_opts.clone())
158    }
159
160    /// Restore client workspace files to match the state of corresponding
161    /// depot files.
162    ///
163    /// Without file arguments, the files in your local working directory are
164    /// used; pass file arguments to
165    /// [`ParameterizedSpawn::spawn_with`](crate::spawn::ParameterizedSpawn::spawn_with)
166    /// to limit the scope.
167    pub fn clean(&self) -> Clean {
168        Clean::new(self.bin.clone(), self.global_opts.clone())
169    }
170
171    /// Create or edit a client workspace specification and its view.
172    ///
173    /// The returned builder starts in the [`GeneralMode`](crate::cmd::client::GeneralMode)
174    /// state (`p4 client [-f] [-t template] [-T type] [name]`); call
175    /// transition methods such as [`Client::delete`](crate::cmd::client::Client::delete)
176    /// or [`Client::stdout`](crate::cmd::client::Client::stdout) to select
177    /// another syntax form.
178    pub fn client(&self) -> Client {
179        Client::new(self.bin.clone(), self.global_opts.clone())
180    }
181
182    /// Create or edit a client workspace specification and its view.
183    ///
184    /// This is an alias for [`Self::client`], corresponding to the `p4
185    /// workspace` command.
186    pub fn workspace(&self) -> Client {
187        Client::new(self.bin.clone(), self.global_opts.clone())
188    }
189
190    /// Create or edit a changelist specification.
191    pub fn change(&self) -> Change {
192        Change::new(self.bin.clone(), self.global_opts.clone())
193    }
194
195    /// Create or edit a changelist specification.
196    ///
197    /// This is an alias for [`Self::change`], corresponding to the `p4
198    /// changelist` command.
199    pub fn changelist(&self) -> Change {
200        Change::new(self.bin.clone(), self.global_opts.clone())
201    }
202
203    /// List submitted and pending changelists.
204    pub fn changes(&self) -> Changes {
205        Changes::new(self.bin.clone(), self.global_opts.clone())
206    }
207
208    /// List submitted and pending changelists.
209    ///
210    /// This is an alias for [`Self::changes`], corresponding to the `p4
211    /// changelists` command.
212    pub fn changelists(&self) -> Changes {
213        Changes::new(self.bin.clone(), self.global_opts.clone())
214    }
215
216    /// Display the details of one or more changelists.
217    pub fn describe(&self) -> Describe {
218        Describe::new(self.bin.clone(), self.global_opts.clone())
219    }
220
221    /// Diff workspace content against depot content, or diff stream specs.
222    pub fn diff(&self) -> Diff {
223        Diff::new(self.bin.clone(), self.global_opts.clone())
224    }
225
226    /// Compare the content at two depot paths, or compare two stream specs.
227    pub fn diff2(&self) -> Diff2 {
228        Diff2::new(self.bin.clone(), self.global_opts.clone())
229    }
230
231    /// Open files in a client workspace for edit.
232    pub fn edit(&self) -> Edit {
233        Edit::new(self.bin.clone(), self.global_opts.clone())
234    }
235
236    /// Print detailed information about the revisions of files.
237    pub fn filelog(&self) -> FileLog {
238        FileLog::new(self.bin.clone(), self.global_opts.clone())
239    }
240
241    /// Print the contents of depot file revisions.
242    pub fn print(&self) -> Print {
243        Print::new(self.bin.clone(), self.global_opts.clone())
244    }
245
246    /// Update the client workspace to reflect the contents of the depot.
247    pub fn sync(&self) -> Sync {
248        Sync::new(self.bin.clone(), self.global_opts.clone())
249    }
250
251    /// Show where a particular file is located, as determined by the client view.
252    pub fn r#where(&self) -> Where {
253        Where::new(self.bin.clone(), self.global_opts.clone())
254    }
255}
256
257#[cfg(test)]
258mod tests {
259    use super::*;
260
261    #[test]
262    fn default_uses_p4_from_path() {
263        let p4 = P4Cli::default();
264
265        assert_eq!(p4.get_bin(), Path::new("p4"));
266    }
267
268    #[test]
269    fn accepts_custom_bin_path() {
270        let p4 = P4Cli::new("C:\\tools\\p4.exe", GlobalOpts::default());
271
272        assert_eq!(p4.get_bin(), Path::new("C:\\tools\\p4.exe"));
273    }
274}