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