1use std::{
2 ffi::OsStr,
3 path::PathBuf,
4 process::{Child, Command, Stdio},
5};
6
7use super::SubCommand;
8
9use crate::global::GlobalOpts;
10use crate::spawn::ParameterizedSpawn;
11
12#[cfg_attr(feature = "lt2015_1", doc = "`p4 [g-opts] where [file ...]`")]
13#[cfg_attr(
14 all(feature = "lt2016_1", not(feature = "lt2015_1")),
15 doc = "`p4 [g-opts] where [file …]`"
16)]
17#[cfg_attr(not(feature = "lt2016_1"), doc = "`p4 [g-opts] where [file ...]`")]
18#[cfg_attr(
20 feature = "lt2023_2",
21 doc = "Show where a particular file is located, as determined by the client view.",
22 doc = "",
23 doc = "`p4 where` uses the client view and root (as set in `p4 client`) to print files'",
24 doc = "locations relative to the top of the depot, relative to the top of the client",
25 doc = "workspace, and relative to the top of the local OS directory tree. The command",
26 doc = "does not check to see if the file exists; it merely reports where the file",
27 doc = "*would be* located if it *did* exist.",
28 doc = "",
29 doc = "For each file provided as a parameter, a set of mappings is output. Each set",
30 doc = "of mappings is composed of lines consisting of three parts: the first part",
31 doc = "is the filename expressed in depot syntax, the second part is the filename",
32 doc = "expressed in client syntax, and the third is the local OS path of the file."
33)]
34#[cfg_attr(
35 not(feature = "lt2023_2"),
36 doc = "Show how the specified files are mapped by the client view.",
37 doc = "",
38 doc = "`p4 where` uses the client view and root to print files locations relative to",
39 doc = "the top of the depot, relative to the top of the client workspace, and",
40 doc = "relative to the top of the local OS directory tree. The client mappings are",
41 doc = "set by the `p4 client` command. The `p4 where` command does not check to see",
42 doc = "whether the file exists. Instead, it reports where the file *would be*",
43 doc = "located if it *did* exist.",
44 doc = "",
45 doc = "The command accepts wildcards, such as `p4 where *.html`",
46 doc = "",
47 doc = "For each file provided as a parameter, a set of mappings is output. Each set",
48 doc = "of mappings consists of:",
49 doc = "",
50 doc = "- the filename in depot syntax. such as `//depot/project1/my-file.html`",
51 doc = "- the filename in client syntax, such as `//maria/depot/project1/my-file.html`",
52 doc = "- the filename in local syntax, which is the local operating system path,",
53 doc = "such as `C:\\Users\\maria\\project1\\my-file.html`"
54)]
55#[derive(Debug, Clone, Default)]
56pub struct Where {
57 bin: PathBuf,
58
59 global_opts: GlobalOpts,
60}
61
62impl SubCommand for Where {
63 fn name(&self) -> &str {
64 "where"
65 }
66
67 fn inject_local_args(&self, _: &mut Command) {}
68
69 fn global_opts(&self) -> Option<&GlobalOpts> {
70 Some(&self.global_opts)
71 }
72}
73
74impl<S, I> ParameterizedSpawn<(S,)> for Where
75where
76 S: IntoIterator<Item = I>,
77 I: AsRef<OsStr>,
78{
79 type Output = Child;
80 type Error = std::io::Error;
81
82 fn spawn_with(&mut self, (files,): (S,)) -> Result<Self::Output, Self::Error> {
88 self.setup_command(&self.bin)
89 .args(files)
90 .stdout(Stdio::piped())
91 .stderr(Stdio::piped())
92 .spawn()
93 }
94}
95
96impl Where {
97 pub fn new(bin: impl Into<PathBuf>, global_opts: GlobalOpts) -> Self {
101 Self {
102 bin: bin.into(),
103 global_opts,
104 }
105 }
106
107 #[cfg_attr(
112 feature = "lt2014_2",
113 doc = "See the [Global Options](GlobalOpts) section."
114 )]
115 #[cfg_attr(
116 all(feature = "lt2015_1", not(feature = "lt2014_2")),
117 doc = "See the [“Global Options”](GlobalOpts) section."
118 )]
119 #[cfg_attr(
120 all(feature = "lt2017_1", not(feature = "lt2015_1")),
121 doc = "See [“Global Options”](GlobalOpts)."
122 )]
123 #[cfg_attr(
124 all(feature = "lt2018_2", not(feature = "lt2017_1")),
125 doc = "See [Global Options](GlobalOpts)."
126 )]
127 #[cfg_attr(not(feature = "lt2018_2"), doc = "See [Global options](GlobalOpts).")]
128 pub fn get_global_opts(&self) -> &GlobalOpts {
129 &self.global_opts
130 }
131
132 #[cfg_attr(
137 feature = "lt2014_2",
138 doc = "See the [Global Options](GlobalOpts) section."
139 )]
140 #[cfg_attr(
141 all(feature = "lt2015_1", not(feature = "lt2014_2")),
142 doc = "See the [“Global Options”](GlobalOpts) section."
143 )]
144 #[cfg_attr(
145 all(feature = "lt2017_1", not(feature = "lt2015_1")),
146 doc = "See [“Global Options”](GlobalOpts)."
147 )]
148 #[cfg_attr(
149 all(feature = "lt2018_2", not(feature = "lt2017_1")),
150 doc = "See [Global Options](GlobalOpts)."
151 )]
152 #[cfg_attr(not(feature = "lt2018_2"), doc = "See [Global options](GlobalOpts).")]
153 pub fn set_global_opts(&mut self, v: GlobalOpts) -> &mut Self {
154 self.global_opts = v;
155 self
156 }
157
158 #[cfg_attr(
163 feature = "lt2014_2",
164 doc = "See the [Global Options](GlobalOpts) section."
165 )]
166 #[cfg_attr(
167 all(feature = "lt2015_1", not(feature = "lt2014_2")),
168 doc = "See the [“Global Options”](GlobalOpts) section."
169 )]
170 #[cfg_attr(
171 all(feature = "lt2017_1", not(feature = "lt2015_1")),
172 doc = "See [“Global Options”](GlobalOpts)."
173 )]
174 #[cfg_attr(
175 all(feature = "lt2018_2", not(feature = "lt2017_1")),
176 doc = "See [Global Options](GlobalOpts)."
177 )]
178 #[cfg_attr(not(feature = "lt2018_2"), doc = "See [Global options](GlobalOpts).")]
179 pub fn global_opts(mut self, v: GlobalOpts) -> Self {
180 self.global_opts = v;
181 self
182 }
183}
184
185#[cfg(test)]
186mod tests {
187 use super::*;
188 use crate::cmd::args_of;
189
190 #[test]
193 fn without_options() {
194 let r#where = Where::new("p4", GlobalOpts::new());
195
196 assert_eq!(args_of(&r#where.setup_command("p4")), ["where"]);
197 }
198
199 #[test]
200 fn with_global_opts() {
201 let r#where = Where::new(
202 "p4",
203 GlobalOpts::new().port("localhost:1666").quiet_mode(true),
204 );
205
206 assert_eq!(
207 args_of(&r#where.setup_command("p4")),
208 ["-p", "localhost:1666", "-q", "where"]
209 );
210 }
211
212 #[test]
213 fn with_files() {
214 let r#where = Where::new("p4", GlobalOpts::new());
215
216 assert_eq!(
217 args_of(r#where.setup_command("p4").args(["file.c"])),
218 ["where", "file.c"]
219 );
220 }
221}