use crate::repository::*;
use libpijul::change::*;
use libpijul::pristine::MutTxnT;
use std::collections::BTreeMap;
use std::path::PathBuf;
#[derive(Clap, Debug)]
pub struct Diff {
#[clap(long = "repository")]
pub repo_path: Option<PathBuf>,
#[clap(long = "json")]
pub json: bool,
#[clap(long = "channel")]
pub channel: Option<String>,
#[clap(long = "tag")]
pub tag: bool,
pub prefixes: Vec<PathBuf>,
}
impl Diff {
pub fn run(self) -> Result<(), anyhow::Error> {
let mut repo = Repository::find_root(self.repo_path.clone())?;
let mut txn = repo.pristine.mut_txn_begin();
let mut channel =
txn.open_or_create_channel(repo.config.get_current_channel(self.channel.as_ref()))?;
let mut state = libpijul::RecordBuilder::new();
repo.working_copy.record_prefixes(
&mut txn,
&mut channel,
&repo.changes,
&mut state,
&repo.path,
&self.prefixes,
)?;
let rec = state.finish();
if rec.actions.is_empty() {
return Ok(());
}
let actions = rec
.actions
.into_iter()
.map(|rec| rec.globalize(&txn))
.collect();
let mut change = LocalChange3::make_change(
&txn,
&channel,
actions,
rec.contents,
ChangeHeader::default(),
Vec::new(),
);
let (dependencies, extra_known) = if self.tag {
full_dependencies(&txn, &channel)
} else {
dependencies(&txn, &channel, change.changes.iter())
};
change.dependencies = dependencies;
change.extra_known = extra_known;
if self.json {
let mut changes = BTreeMap::new();
for ch in change.changes.iter() {
changes.entry(ch.path()).or_insert(Vec::new()).push(Status {
operation: match ch {
Record::FileMove { .. } => "file move",
Record::FileDel { .. } => "file del",
Record::FileUndel { .. } => "file undel",
Record::SolveNameConflict { .. } => "solve name conflict",
Record::UnsolveNameConflict { .. } => "unsolve name conflict",
Record::FileAdd { .. } => "file add",
Record::Edit { .. } => "edit",
Record::Replacement { .. } => "replacement",
Record::SolveOrderConflict { .. } => "solve order conflict",
Record::UnsolveOrderConflict { .. } => "unsolve order conflict",
Record::ResurrectZombies { .. } => "resurrect zombies",
},
line: ch.line(),
});
}
serde_json::to_writer_pretty(&mut std::io::stdout(), &changes)?;
println!("");
} else {
change.write(
&repo.changes,
None,
|local: &libpijul::change::Local, _| -> String {
format!("{}:{}", local.path, local.line)
},
true,
&mut std::io::stdout(),
)?
}
Ok(())
}
}
#[derive(Debug, Serialize)]
struct Status {
operation: &'static str,
line: Option<usize>,
}