Add local file conflict metadata

This commit is contained in:
Eric Wendland 2026-05-18 03:57:26 +02:00
commit 20c88af800
13 changed files with 673 additions and 15 deletions

View file

@ -220,6 +220,10 @@ pub enum CasCommand {
#[command(subcommand)]
command: CasRootCommand,
},
Conflict {
#[command(subcommand)]
command: CasConflictCommand,
},
}
#[derive(Debug, Subcommand)]
@ -229,6 +233,33 @@ pub enum CasRootCommand {
Scan { name: String },
}
#[derive(Debug, Subcommand)]
pub enum CasConflictCommand {
Record {
root: String,
path: String,
kind: String,
#[arg(long)]
detail: String,
#[arg(long)]
base_tree: Option<String>,
#[arg(long)]
local_tree: Option<String>,
#[arg(long)]
remote_tree: Option<String>,
},
List {
#[arg(long)]
root: Option<String>,
},
Resolve {
conflict_id: String,
resolution: String,
#[arg(long)]
note: Option<String>,
},
}
#[derive(Debug, Subcommand)]
pub enum KvCommand {
Create {
@ -480,6 +511,35 @@ fn request_for_command(command: Command) -> Result<ControlRequest> {
CasRootCommand::List => ControlRequest::CasRootList,
CasRootCommand::Scan { name } => ControlRequest::CasRootScan { name },
},
CasCommand::Conflict { command } => match command {
CasConflictCommand::Record {
root,
path,
kind,
detail,
base_tree,
local_tree,
remote_tree,
} => ControlRequest::CasConflictRecord {
root,
path,
kind,
detail,
base_tree: base_tree.map(Into::into),
local_tree: local_tree.map(Into::into),
remote_tree: remote_tree.map(Into::into),
},
CasConflictCommand::List { root } => ControlRequest::CasConflictList { root },
CasConflictCommand::Resolve {
conflict_id,
resolution,
note,
} => ControlRequest::CasConflictResolve {
conflict_id,
resolution,
note,
},
},
},
Command::Kv { command } => match command {
KvCommand::Create { name } => ControlRequest::KvCreate { name },
@ -744,6 +804,30 @@ fn print_response(response: ControlResponse, json: bool) -> Result<()> {
}
println!("note: {}", scan.note);
}
ControlResponse::CasConflictRecorded { conflict } => {
println!("recorded conflict: {}", conflict.id);
print_file_conflict(&conflict);
}
ControlResponse::CasConflictList { conflicts } => {
if conflicts.is_empty() {
println!("no file conflicts");
} else {
for conflict in conflicts {
println!(
"{}\t{}\t{}\t{}\t{}",
conflict.id,
conflict.root,
conflict.path,
conflict.kind.as_str(),
conflict.status.as_str()
);
}
}
}
ControlResponse::CasConflictResolved { conflict } => {
println!("resolved conflict: {}", conflict.id);
print_file_conflict(&conflict);
}
ControlResponse::KeychainStatus(status) => {
println!("initialized: {}", status.initialized);
println!("admin_keys: {}", status.admin_keys);
@ -1091,6 +1175,30 @@ fn print_service_report(report: ServiceReport, json: bool) -> Result<()> {
Ok(())
}
fn print_file_conflict(conflict: &geth_cas::FileConflict) {
println!("root: {}", conflict.root);
println!("resource: {}", conflict.resource);
println!("path: {}", conflict.path);
println!("kind: {}", conflict.kind.as_str());
println!("status: {}", conflict.status.as_str());
if let Some(hash) = &conflict.base_tree {
println!("base_tree: {hash}");
}
if let Some(hash) = &conflict.local_tree {
println!("local_tree: {hash}");
}
if let Some(hash) = &conflict.remote_tree {
println!("remote_tree: {hash}");
}
println!("detail: {}", conflict.detail);
if let Some(resolution) = &conflict.resolution {
println!("resolution: {}", resolution.as_str());
}
if let Some(note) = &conflict.resolution_note {
println!("resolution_note: {note}");
}
}
fn shell_quote_command(command: &[String]) -> String {
command
.iter()