use std::{
ffi::OsStr,
path::{Path, PathBuf},
process::{Child, Command, Stdio},
};
use super::SubCommand;
use crate::global::GlobalOpts;
use crate::spawn::ParameterizedSpawn;
#[cfg_attr(feature = "lt2015_1", doc = "`p4 [g-opts] where [file ...]`")]
#[cfg_attr(
all(feature = "lt2016_1", not(feature = "lt2015_1")),
doc = "`p4 [g-opts] where [file …]`"
)]
#[cfg_attr(not(feature = "lt2016_1"), doc = "`p4 [g-opts] where [file ...]`")]
#[cfg_attr(
feature = "lt2023_2",
doc = "Show where a particular file is located, as determined by the client view.",
doc = "",
doc = "`p4 where` uses the client view and root (as set in `p4 client`) to print files'",
doc = "locations relative to the top of the depot, relative to the top of the client",
doc = "workspace, and relative to the top of the local OS directory tree. The command",
doc = "does not check to see if the file exists; it merely reports where the file",
doc = "*would be* located if it *did* exist.",
doc = "",
doc = "For each file provided as a parameter, a set of mappings is output. Each set",
doc = "of mappings is composed of lines consisting of three parts: the first part",
doc = "is the filename expressed in depot syntax, the second part is the filename",
doc = "expressed in client syntax, and the third is the local OS path of the file."
)]
#[cfg_attr(
not(feature = "lt2023_2"),
doc = "Show how the specified files are mapped by the client view.",
doc = "",
doc = "`p4 where` uses the client view and root to print files locations relative to",
doc = "the top of the depot, relative to the top of the client workspace, and",
doc = "relative to the top of the local OS directory tree. The client mappings are",
doc = "set by the `p4 client` command. The `p4 where` command does not check to see",
doc = "whether the file exists. Instead, it reports where the file *would be*",
doc = "located if it *did* exist.",
doc = "",
doc = "The command accepts wildcards, such as `p4 where *.html`",
doc = "",
doc = "For each file provided as a parameter, a set of mappings is output. Each set",
doc = "of mappings consists of:",
doc = "",
doc = "- the filename in depot syntax. such as `//depot/project1/my-file.html`",
doc = "- the filename in client syntax, such as `//maria/depot/project1/my-file.html`",
doc = "- the filename in local syntax, which is the local operating system path,",
doc = "such as `C:\\Users\\maria\\project1\\my-file.html`"
)]
#[derive(Debug, Clone, Default)]
pub struct Where {
bin: PathBuf,
global_opts: GlobalOpts,
}
impl SubCommand for Where {
fn name(&self) -> &str {
"where"
}
fn inject_local_args(&self, _: &mut Command) {}
fn global_opts(&self) -> Option<&GlobalOpts> {
Some(&self.global_opts)
}
}
impl<S, I> ParameterizedSpawn<(S,)> for Where
where
S: IntoIterator<Item = I>,
I: AsRef<OsStr>,
{
type Output = Child;
type Error = std::io::Error;
fn spawn_with(&mut self, (files,): (S,)) -> Result<Self::Output, Self::Error> {
self.setup_command(&self.bin)
.args(files)
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()
}
}
impl Where {
pub fn get_bin(&self) -> &Path {
&self.bin
}
pub fn set_bin(&mut self, bin: impl Into<PathBuf>) -> &mut Self {
self.bin = bin.into();
self
}
pub fn bin(mut self, bin: impl Into<PathBuf>) -> Self {
self.set_bin(bin);
self
}
pub fn new(bin: impl Into<PathBuf>, global_opts: GlobalOpts) -> Self {
Self {
bin: bin.into(),
global_opts,
}
}
#[cfg_attr(
feature = "lt2014_2",
doc = "See the [Global Options](GlobalOpts) section."
)]
#[cfg_attr(
all(feature = "lt2015_1", not(feature = "lt2014_2")),
doc = "See the [“Global Options”](GlobalOpts) section."
)]
#[cfg_attr(
all(feature = "lt2017_1", not(feature = "lt2015_1")),
doc = "See [“Global Options”](GlobalOpts)."
)]
#[cfg_attr(
all(feature = "lt2018_2", not(feature = "lt2017_1")),
doc = "See [Global Options](GlobalOpts)."
)]
#[cfg_attr(not(feature = "lt2018_2"), doc = "See [Global options](GlobalOpts).")]
pub fn get_global_opts(&self) -> &GlobalOpts {
&self.global_opts
}
#[cfg_attr(
feature = "lt2014_2",
doc = "See the [Global Options](GlobalOpts) section."
)]
#[cfg_attr(
all(feature = "lt2015_1", not(feature = "lt2014_2")),
doc = "See the [“Global Options”](GlobalOpts) section."
)]
#[cfg_attr(
all(feature = "lt2017_1", not(feature = "lt2015_1")),
doc = "See [“Global Options”](GlobalOpts)."
)]
#[cfg_attr(
all(feature = "lt2018_2", not(feature = "lt2017_1")),
doc = "See [Global Options](GlobalOpts)."
)]
#[cfg_attr(not(feature = "lt2018_2"), doc = "See [Global options](GlobalOpts).")]
pub fn set_global_opts(&mut self, v: GlobalOpts) -> &mut Self {
self.global_opts = v;
self
}
#[cfg_attr(
feature = "lt2014_2",
doc = "See the [Global Options](GlobalOpts) section."
)]
#[cfg_attr(
all(feature = "lt2015_1", not(feature = "lt2014_2")),
doc = "See the [“Global Options”](GlobalOpts) section."
)]
#[cfg_attr(
all(feature = "lt2017_1", not(feature = "lt2015_1")),
doc = "See [“Global Options”](GlobalOpts)."
)]
#[cfg_attr(
all(feature = "lt2018_2", not(feature = "lt2017_1")),
doc = "See [Global Options](GlobalOpts)."
)]
#[cfg_attr(not(feature = "lt2018_2"), doc = "See [Global options](GlobalOpts).")]
pub fn global_opts(mut self, v: GlobalOpts) -> Self {
self.global_opts = v;
self
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::cmd::args_of;
#[test]
fn bin_accessors_update_executable_path() {
let mut command = Where::new("p4", GlobalOpts::new());
assert_eq!(command.get_bin(), Path::new("p4"));
command.set_bin("/usr/local/bin/p4");
assert_eq!(command.get_bin(), Path::new("/usr/local/bin/p4"));
let command = command.bin("p4.exe");
assert_eq!(command.get_bin(), Path::new("p4.exe"));
}
#[test]
fn without_options() {
let r#where = Where::new("p4", GlobalOpts::new());
assert_eq!(args_of(&r#where.setup_command("p4")), ["where"]);
}
#[test]
fn with_global_opts() {
let r#where = Where::new(
"p4",
GlobalOpts::new().port("localhost:1666").quiet_mode(true),
);
assert_eq!(
args_of(&r#where.setup_command("p4")),
["-p", "localhost:1666", "-q", "where"]
);
}
#[test]
fn with_files() {
let r#where = Where::new("p4", GlobalOpts::new());
assert_eq!(
args_of(r#where.setup_command("p4").args(["file.c"])),
["where", "file.c"]
);
}
}