use std::vec;
use error;
use p4;
#[derive(Debug, Clone)]
pub struct DirsCommand<'p, 'f, 's> {
connection: &'p p4::P4,
dir: Vec<&'f str>,
client_only: bool,
stream: Option<&'s str>,
include_deleted: bool,
include_synced: bool,
ignore_case: bool,
}
impl<'p, 'f, 's> DirsCommand<'p, 'f, 's> {
pub fn new(connection: &'p p4::P4, dir: &'f str) -> Self {
Self {
connection,
dir: vec![dir],
client_only: false,
stream: None,
include_deleted: false,
include_synced: false,
ignore_case: false,
}
}
pub fn dir(mut self, dir: &'f str) -> Self {
self.dir.push(dir);
self
}
pub fn client_only(mut self, client_only: bool) -> Self {
self.client_only = client_only;
self
}
pub fn set_stream(mut self, stream: &'s str) -> Self {
self.stream = Some(stream);
self
}
pub fn include_deleted(mut self, include_deleted: bool) -> Self {
self.include_deleted = include_deleted;
self
}
pub fn include_synced(mut self, include_synced: bool) -> Self {
self.include_synced = include_synced;
self
}
pub fn ignore_case(mut self, ignore_case: bool) -> Self {
self.ignore_case = ignore_case;
self
}
pub fn run(self) -> Result<Dirs, error::P4Error> {
let mut cmd = self.connection.connect_with_retries(None);
cmd.arg("dirs");
if self.client_only {
cmd.arg("-C");
}
if let Some(stream) = self.stream {
cmd.args(&["-S", stream]);
}
if self.include_deleted {
cmd.arg("-D");
}
if self.include_synced {
cmd.arg("-H");
}
if self.ignore_case {
cmd.arg("-i");
}
for dir in self.dir {
cmd.arg(dir);
}
let data = cmd.output().map_err(|e| {
error::ErrorKind::SpawnFailed
.error()
.set_cause(e)
.set_context(format!("Command: {:?}", cmd))
})?;
let (_remains, (mut items, exit)) = dirs_parser::dirs(&data.stdout).map_err(|_| {
error::ErrorKind::ParseFailed
.error()
.set_context(format!("Command: {:?}", cmd))
})?;
items.push(exit);
Ok(Dirs(items))
}
}
pub type DirItem = error::Item<Dir>;
pub struct Dirs(Vec<DirItem>);
impl IntoIterator for Dirs {
type Item = DirItem;
type IntoIter = DirsIntoIter;
fn into_iter(self) -> DirsIntoIter {
DirsIntoIter(self.0.into_iter())
}
}
#[derive(Debug)]
pub struct DirsIntoIter(vec::IntoIter<DirItem>);
impl Iterator for DirsIntoIter {
type Item = DirItem;
#[inline]
fn next(&mut self) -> Option<DirItem> {
self.0.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
#[inline]
fn count(self) -> usize {
self.0.count()
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Dir {
pub dir: String,
non_exhaustive: (),
}
mod dirs_parser {
use super::super::parser::*;
named!(dir_<&[u8], super::Dir>,
do_parse!(
dir: dir >>
(
super::Dir {
dir: dir.dir.to_owned(),
non_exhaustive: (),
}
)
)
);
named!(item<&[u8], super::DirItem>,
alt!(
map!(dir_, data_to_item) |
map!(error, error_to_item) |
map!(info, info_to_item)
)
);
named!(pub dirs<&[u8], (Vec<super::DirItem>, super::DirItem)>,
pair!(
many0!(item),
map!(exit, exit_to_item)
)
);
}