use std::vec;
use error;
use p4;
#[derive(Debug, Clone)]
pub struct FilesCommand<'p, 'f> {
connection: &'p p4::P4,
file: Vec<&'f str>,
list_revisions: bool,
syncable_only: bool,
ignore_case: bool,
max: Option<usize>,
}
impl<'p, 'f> FilesCommand<'p, 'f> {
pub fn new(connection: &'p p4::P4, file: &'f str) -> Self {
Self {
connection,
file: vec![file],
list_revisions: false,
syncable_only: false,
ignore_case: false,
max: None,
}
}
pub fn file(mut self, file: &'f str) -> Self {
self.file.push(file);
self
}
pub fn list_revisions(mut self, list_revisions: bool) -> Self {
self.list_revisions = list_revisions;
self
}
pub fn syncable_only(mut self, syncable_only: bool) -> Self {
self.syncable_only = syncable_only;
self
}
pub fn ignore_case(mut self, ignore_case: bool) -> Self {
self.ignore_case = ignore_case;
self
}
pub fn set_max(mut self, max: Option<usize>) -> Self {
self.max = max;
self
}
pub fn run(self) -> Result<Files, error::P4Error> {
let mut cmd = self.connection.connect_with_retries(None);
cmd.arg("files");
if self.list_revisions {
cmd.arg("-a");
}
if self.syncable_only {
cmd.arg("-e");
}
if self.ignore_case {
cmd.arg("-i");
}
if let Some(max) = self.max {
cmd.arg(format!("-m {}", max));
}
for file in self.file {
cmd.arg(file);
}
let data = cmd.output().map_err(|e| {
error::ErrorKind::SpawnFailed
.error()
.set_cause(e)
.set_context(format!("Command: {:?}", cmd))
})?;
let (_remains, (mut items, exit)) = files_parser::files(&data.stdout).map_err(|_| {
error::ErrorKind::ParseFailed
.error()
.set_context(format!("Command: {:?}", cmd))
})?;
items.push(exit);
Ok(Files(items))
}
}
pub type FileItem = error::Item<File>;
pub struct Files(Vec<FileItem>);
impl IntoIterator for Files {
type Item = FileItem;
type IntoIter = FilesIntoIter;
fn into_iter(self) -> FilesIntoIter {
FilesIntoIter(self.0.into_iter())
}
}
#[derive(Debug)]
pub struct FilesIntoIter(vec::IntoIter<FileItem>);
impl Iterator for FilesIntoIter {
type Item = FileItem;
#[inline]
fn next(&mut self) -> Option<FileItem> {
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 File {
pub depot_file: String,
pub rev: usize,
pub change: usize,
pub action: p4::Action,
pub file_type: p4::FileType,
pub time: p4::Time,
non_exhaustive: (),
}
mod files_parser {
use super::*;
use super::super::parser::*;
named!(file<&[u8], File>,
do_parse!(
depot_file: depot_file >>
rev: rev >>
change: change >>
action: action >>
file_type: file_type >>
time: time >>
(
File {
depot_file: depot_file.path.to_owned(),
rev: rev.rev,
change: change.change,
action: action.action.parse().expect("Unknown to capture all"),
file_type: file_type.ft.parse().expect("Unknown to capture all"),
time: p4::from_timestamp(time.time),
non_exhaustive: (),
}
)
)
);
named!(item<&[u8], FileItem>,
alt!(
map!(file, data_to_item) |
map!(error, error_to_item) |
map!(info, info_to_item)
)
);
named!(pub files<&[u8], (Vec<FileItem>, FileItem)>,
pair!(
many0!(item),
map!(exit, exit_to_item)
)
);
}