1use std::path;
2use std::vec;
3
4use error;
5use p4;
6
7#[derive(Debug, Clone)]
30pub struct WhereCommand<'p, 'f> {
31 connection: &'p p4::P4,
32 file: Vec<&'f str>,
33}
34
35impl<'p, 'f> WhereCommand<'p, 'f> {
36 pub fn new(connection: &'p p4::P4) -> Self {
37 Self {
38 connection,
39 file: vec![],
40 }
41 }
42
43 pub fn file(mut self, file: &'f str) -> Self {
45 self.file.push(file);
46 self
47 }
48
49 pub fn run(self) -> Result<Files, error::P4Error> {
51 let mut cmd = self.connection.connect_with_retries(None);
52 cmd.arg("where");
53 for file in self.file {
54 cmd.arg(file);
55 }
56 let data = cmd.output().map_err(|e| {
57 error::ErrorKind::SpawnFailed
58 .error()
59 .set_cause(e)
60 .set_context(format!("Command: {:?}", cmd))
61 })?;
62 let (_remains, (mut items, exit)) = where_parser::where_(&data.stdout).map_err(|_| {
63 error::ErrorKind::ParseFailed
64 .error()
65 .set_context(format!("Command: {:?}", cmd))
66 })?;
67 items.push(exit);
68 Ok(Files(items))
69 }
70}
71
72pub type FileItem = error::Item<File>;
73
74pub struct Files(Vec<FileItem>);
75
76impl IntoIterator for Files {
77 type Item = FileItem;
78 type IntoIter = FilesIntoIter;
79
80 fn into_iter(self) -> FilesIntoIter {
81 FilesIntoIter(self.0.into_iter())
82 }
83}
84
85#[derive(Debug)]
86pub struct FilesIntoIter(vec::IntoIter<FileItem>);
87
88impl Iterator for FilesIntoIter {
89 type Item = FileItem;
90
91 #[inline]
92 fn next(&mut self) -> Option<FileItem> {
93 self.0.next()
94 }
95
96 #[inline]
97 fn size_hint(&self) -> (usize, Option<usize>) {
98 self.0.size_hint()
99 }
100
101 #[inline]
102 fn count(self) -> usize {
103 self.0.count()
104 }
105}
106
107#[derive(Debug, Clone, PartialEq, Eq)]
108pub struct File {
109 pub depot_file: String,
110 pub client_file: String,
111 pub path: path::PathBuf,
112 non_exhaustive: (),
113}
114
115mod where_parser {
116 use super::*;
117
118 use super::super::parser::*;
119
120 named!(file<&[u8], File>,
121 do_parse!(
122 depot_file: depot_file >>
123 client_file: client_file >>
124 path: path >>
125 (
126 File {
127 depot_file: depot_file.path.to_owned(),
128 client_file: client_file.path.to_owned(),
129 path: path::PathBuf::from(path.path),
130 non_exhaustive: (),
131 }
132 )
133 )
134 );
135
136 named!(item<&[u8], FileItem>,
137 alt!(
138 map!(file, data_to_item) |
139 map!(error, error_to_item) |
140 map!(info, info_to_item)
141 )
142 );
143
144 named!(pub where_<&[u8], (Vec<FileItem>, FileItem)>,
145 pair!(
146 many0!(item),
147 map!(exit, exit_to_item)
148 )
149 );
150}