use clap::{Arg, ArgMatches, SubCommand};
use commands::{default_explain, BasicOptions, StaticSubcommand};
use error::Error;
use libpijul::fs_representation::{RepoPath, RepoRoot};
use libpijul::status::{unrecorded_changes, ChangeType};
use rand;
use std::path::{Path, PathBuf};
use std::rc::Rc;
const UNRECORDED_FILES: &'static str = r#"
Changes not yet recorded:
(use "pijul record ..." to record a new patch)
"#;
const UNTRACKED_FILES: &'static str = r#"
Untracked files:
(use "pijul add <file>..." to track them)
"#;
const CONFLICTED_FILES: &'static str = r#"
Unresolved conflicts:
(fix conflicts and record the resolution with "pijul record ...")
"#;
pub fn invocation() -> StaticSubcommand {
SubCommand::with_name("status")
.about("Show working tree status")
.arg(
Arg::with_name("repository")
.long("repository")
.takes_value(true)
.help("Local repository."),
)
.arg(
Arg::with_name("short")
.long("short")
.short("s")
.help("Output in short format"),
)
}
pub fn explain(r: Result<(), Error>) {
default_explain(r)
}
pub fn run(args: &ArgMatches) -> Result<(), Error> {
let opts = BasicOptions::from_args(args)?;
let current_branch = opts.branch();
let repo = opts.open_and_grow_repo(409600)?;
let short = args.is_present("short");
let (unrecorded, untracked, conflicts) = {
let mut txn = repo.mut_txn_begin(rand::thread_rng())?;
let mut unrecorded = unrecorded_changes(&mut txn, &opts.repo_root, ¤t_branch)?;
unrecorded.sort_unstable();
let mut untracked: Vec<RepoPath<PathBuf>> = opts
.repo_root
.untracked_files(&txn, &opts.repo_root.repo_root)
.collect();
untracked.sort_unstable();
let mut conflicts = txn.list_conflict_files(¤t_branch, &[])?;
conflicts.sort_unstable();
(unrecorded, untracked, conflicts)
};
if short {
print_shortstatus(&opts.cwd, &opts.repo_root, unrecorded, untracked, conflicts);
} else {
print_longstatus(¤t_branch, unrecorded, untracked, conflicts);
}
Ok(())
}
fn print_longstatus(
branch: &str,
changed: Vec<(Rc<RepoPath<PathBuf>>, ChangeType)>,
untracked: Vec<RepoPath<PathBuf>>,
conflicts: Vec<RepoPath<PathBuf>>,
) {
println!("On branch {}", branch);
if changed.is_empty() && untracked.is_empty() && conflicts.is_empty() {
println!("Nothing to record, working tree clean");
}
if !conflicts.is_empty() {
println!("{}", CONFLICTED_FILES);
for f in conflicts {
println!(" {}", f.display());
}
}
if !changed.is_empty() {
println!("{}", UNRECORDED_FILES);
for (f, t) in changed {
println!(" {:10} {}", t.long(), f.display());
}
}
if !untracked.is_empty() {
println!("{}", UNTRACKED_FILES);
for f in untracked {
println!(" {}", f.display());
}
}
}
fn print_shortstatus(
cwd: &Path,
repo_root: &RepoRoot<impl AsRef<Path>>,
changed: Vec<(Rc<RepoPath<PathBuf>>, ChangeType)>,
untracked: Vec<RepoPath<PathBuf>>,
conflicts: Vec<RepoPath<PathBuf>>,
) {
for f in conflicts {
debug!("{:?} {:?}", repo_root.repo_root.as_ref(), f.as_path());
println!(
"C {}",
pathdiff::diff_paths(&repo_root.repo_root.as_ref().join(f.as_path()), &cwd)
.unwrap()
.display()
);
}
for (f, t) in changed {
debug!("{:?} {:?}", repo_root.repo_root.as_ref(), f.as_path());
println!(
"{} {}",
t.short(),
pathdiff::diff_paths(&repo_root.repo_root.as_ref().join(f.as_path()), &cwd)
.unwrap()
.display()
)
}
for f in untracked {
debug!("{:?} {:?}", f.as_path(), cwd);
println!(
"? {}",
pathdiff::diff_paths(&repo_root.repo_root.as_ref().join(f.as_path()), &cwd)
.unwrap()
.display()
)
}
}