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