Something went wrong. Try again.
wip: was testing using yrs as a merge driver for git conflicts
Something went wrong. Try again.
3.7 kB · 123 lines
Rust
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124//! `git yrs-merge refresh` — update stale .yrs/ sidecars after a merge.//!//! Designed to run as a post-merge hook. After git auto-merges files//! (without invoking the merge driver), the .yrs/ sidecars may be stale.//! This command reads the merged content and regenerates sidecars.
use std::fs;use std::io;use std::path::Path;use std::process::Command;
use crate::sidecar;
/// Run `git yrs-merge refresh`.pub fn run(verbose: bool) -> io::Result<()> { // Check if .yrs/ directory exists if !Path::new(".yrs").exists() { if verbose { eprintln!("git-yrs-merge: no .yrs/ directory, nothing to refresh"); } return Ok(()); }
// Get list of files changed in the merge let changed_files = get_changed_files()?;
if changed_files.is_empty() { if verbose { eprintln!("git-yrs-merge: no changed files to refresh"); } return Ok(()); }
let mut refreshed = 0;
for file_path in &changed_files { let sidecar_path = sidecar::sidecar_path(file_path);
// Only refresh files that have an existing sidecar if !sidecar_path.exists() { continue; }
// Read current content let content = match fs::read_to_string(file_path) { Ok(c) => c, Err(_) => continue, // file might have been deleted };
// Check if sidecar is stale let sidecar_data = match fs::read(&sidecar_path) { Ok(d) => d, Err(_) => continue, };
if sidecar::validate_sidecar(&sidecar_data, &content) { continue; // sidecar is fine }
// Regenerate sidecar from current content let new_sidecar = sidecar::create_sidecar_from_text(&content); sidecar::write_sidecar(file_path, &new_sidecar)?;
if verbose { eprintln!("git-yrs-merge: refreshed sidecar for {}", file_path); } refreshed += 1; }
// Stage refreshed sidecars if refreshed > 0 { let output = Command::new("git") .args(["add", ".yrs/"]) .output()?;
if !output.status.success() { eprintln!( "git-yrs-merge: warning: failed to stage .yrs/: {}", String::from_utf8_lossy(&output.stderr) ); }
eprintln!("git-yrs-merge: refreshed {} sidecar(s)", refreshed); } else if verbose { eprintln!("git-yrs-merge: all sidecars are up to date"); }
Ok(())}
/// Get the list of files changed in the most recent merge/pull.fn get_changed_files() -> io::Result<Vec<String>> { // Try using MERGE_HEAD first (during merge) // Fall back to comparing HEAD with HEAD@{1} (after merge) let output = Command::new("git") .args(["diff", "--name-only", "HEAD@{1}", "HEAD"]) .output()?;
if output.status.success() { let files: Vec<String> = String::from_utf8_lossy(&output.stdout) .lines() .filter(|l| !l.is_empty() && !l.starts_with(".yrs/")) .map(|l| l.to_string()) .collect(); Ok(files) } else { // Fallback: list all tracked files (less efficient but always works) let output = Command::new("git") .args(["ls-files"]) .output()?;
if output.status.success() { let files: Vec<String> = String::from_utf8_lossy(&output.stdout) .lines() .filter(|l| !l.is_empty() && !l.starts_with(".yrs/")) .map(|l| l.to_string()) .collect(); Ok(files) } else { Ok(Vec::new()) } }}