use subversion::{
client::{CheckoutOptions, CommitOptions, Context, CopyOptions, MergeSourcesOptions},
Depth, Revision,
};
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("Branch Merge Example using merge_peg\n");
let temp_dir = tempfile::tempdir()?;
let repo_path = temp_dir.path().join("repo");
let trunk_wc = temp_dir.path().join("trunk");
let branch_wc = temp_dir.path().join("branch");
println!("Creating repository...");
subversion::repos::Repos::create(&repo_path)?;
let mut ctx = Context::new()?;
let trunk_url = format!("file://{}", repo_path.display());
println!("Checking out trunk...");
ctx.checkout(
trunk_url.as_str(),
&trunk_wc,
&CheckoutOptions {
peg_revision: Revision::Head,
revision: Revision::Head,
depth: Depth::Infinity,
ignore_externals: false,
allow_unver_obstructions: false,
},
)?;
println!("Creating initial files...");
let readme = trunk_wc.join("README.md");
std::fs::write(&readme, "# My Project\n\nInitial version\n")?;
let src_file = trunk_wc.join("main.rs");
std::fs::write(
&src_file,
"fn main() {\n println!(\"Hello, world!\");\n}\n",
)?;
ctx.add(&readme, &subversion::client::AddOptions::default())?;
ctx.add(&src_file, &subversion::client::AddOptions::default())?;
let mut rev1 = 0i64;
ctx.commit(
&[trunk_wc.to_str().unwrap()],
&CommitOptions::default(),
std::collections::HashMap::new(),
None,
&mut |info| {
rev1 = info.revision().as_i64();
println!(" Committed revision {}", rev1);
Ok(())
},
)?;
println!("\nCreating branch...");
let branch_url = format!("{}/branch", repo_path.display());
let mut copy_opts = CopyOptions::new();
ctx.copy(
&[(trunk_url.as_str(), Some(Revision::Head))],
&branch_url,
&mut copy_opts,
)?;
println!(" Branch created at: {}", branch_url);
println!("\nChecking out branch...");
let branch_url_obj = format!("file://{}", branch_url);
ctx.checkout(
branch_url_obj.as_str(),
&branch_wc,
&CheckoutOptions {
peg_revision: Revision::Head,
revision: Revision::Head,
depth: Depth::Infinity,
ignore_externals: false,
allow_unver_obstructions: false,
},
)?;
println!("\nMaking changes in branch...");
let branch_readme = branch_wc.join("README.md");
std::fs::write(
&branch_readme,
"# My Project\n\nInitial version\n\n## New Feature\n\nAdded cool feature!\n",
)?;
let branch_src = branch_wc.join("main.rs");
std::fs::write(
&branch_src,
"fn main() {\n println!(\"Hello, world!\");\n println!(\"New feature added!\");\n}\n",
)?;
let mut rev2 = 0i64;
ctx.commit(
&[branch_wc.to_str().unwrap()],
&CommitOptions::default(),
std::collections::HashMap::new(),
None,
&mut |info| {
rev2 = info.revision().as_i64();
println!(" Committed revision {} to branch", rev2);
Ok(())
},
)?;
println!("\n=== Merging branch to trunk ===\n");
println!("1. Using automatic merge (empty ranges)...");
let merge_opts = MergeSourcesOptions {
ignore_mergeinfo: false,
diff_ignore_ancestry: false,
force_delete: false,
record_only: false,
dry_run: false,
allow_mixed_rev: true,
merge_options: None,
};
match ctx.merge_peg(
&branch_url_obj,
&[], &Revision::Head,
trunk_wc.to_str().unwrap(),
Depth::Infinity,
&merge_opts,
) {
Ok(()) => {
println!(" ✓ Merge completed successfully!");
let merged_readme = std::fs::read_to_string(&readme)?;
if merged_readme.contains("New Feature") {
println!(" ✓ Changes from branch are present in trunk");
}
}
Err(e) => {
eprintln!(" ✗ Merge failed: {}", e);
println!("\n2. Trying with explicit revision range...");
let ranges = vec![subversion::mergeinfo::MergeRange::new(
subversion::Revnum::from(rev1 as u64),
subversion::Revnum::from(rev2 as u64),
true, )];
ctx.merge_peg(
&branch_url_obj,
&ranges,
&Revision::Number(subversion::Revnum::from(rev2 as u64)),
trunk_wc.to_str().unwrap(),
Depth::Infinity,
&merge_opts,
)?;
println!(" ✓ Merge with explicit range succeeded!");
}
}
println!("\n=== Merged Content ===\n");
let merged_readme = std::fs::read_to_string(&readme)?;
println!("README.md:");
println!("{}", merged_readme);
let merged_src = std::fs::read_to_string(&src_file)?;
println!("\nmain.rs:");
println!("{}", merged_src);
println!("\n=== Committing merge ===\n");
ctx.commit(
&[trunk_wc.to_str().unwrap()],
&CommitOptions::default(),
std::collections::HashMap::new(),
None,
&mut |info| {
println!(" Merge committed as revision {}", info.revision().as_i64());
Ok(())
},
)?;
println!("\n=== Example completed successfully! ===");
println!("\nThis example demonstrated:");
println!(" • Creating a repository and trunk");
println!(" • Creating a branch with copy");
println!(" • Making changes in the branch");
println!(" • Merging with merge_peg (automatic and explicit ranges)");
println!(" • Committing the merge result");
Ok(())
}