Files
radicle-git/radicle-surf/examples/diff.rs
T
Fintan Halpenny d657572dfd radicle-surf: remove file_system::path
The file_system types, Label & Path, are overengineered. It's more
natural to use the Path and PathBuf types provided by the std library.

This replaces any mention of Label with String and any use of the old
Path with either std::path::Path or std::path::PathBuf, depending on
what kind of ownwership is needed.

Anywhere a "root" directory is needed `PathBuf::new()` is used,
i.e. an empty `PathBuf`. Otherwise `Path::new` can used to pass
directory, or in fact a &str can also be used since it implements
AsRef<Path>.

The `File` and `Directory` types also contain there relative paths,
which can be retrieved while traversing the Tree.

Note the special file name `"special/faux\\path"` requires the use of an
escaping string construction, i.e. `r"special/faux\\path"`.

Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
2022-11-24 12:08:44 +00:00

120 lines
3.7 KiB
Rust

// This file is part of radicle-surf
// <https://github.com/radicle-dev/radicle-surf>
//
// Copyright (C) 2019-2020 The Radicle Team <dev@radicle.xyz>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 3 or
// later as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
extern crate radicle_surf;
use std::{env::Args, str::FromStr, time::Instant};
use radicle_git_ext::Oid;
use radicle_surf::{diff::Diff, git};
fn main() {
let options = get_options_or_exit();
let repo = init_repository_or_exit(&options.path_to_repo);
let head_oid = match options.head_revision {
HeadRevision::Head => repo.head_oid().unwrap(),
HeadRevision::Commit(id) => Oid::from_str(&id).unwrap(),
};
let base_oid = Oid::from_str(&options.base_revision).unwrap();
let now = Instant::now();
let elapsed_nanos = now.elapsed().as_nanos();
let diff = repo.diff(base_oid, head_oid).unwrap();
print_diff_summary(&diff, elapsed_nanos);
}
fn get_options_or_exit() -> Options {
match Options::parse(std::env::args()) {
Ok(options) => options,
Err(message) => {
println!("{}", message);
std::process::exit(1);
},
}
}
fn init_repository_or_exit(path_to_repo: &str) -> git::Repository {
match git::Repository::open(path_to_repo) {
Ok(repo) => repo,
Err(e) => {
println!("Failed to create repository: {:?}", e);
std::process::exit(1);
},
}
}
fn print_diff_summary(diff: &Diff, elapsed_nanos: u128) {
diff.created.iter().for_each(|created| {
println!("+++ {:?}", created.path);
});
diff.deleted.iter().for_each(|deleted| {
println!("--- {:?}", deleted.path);
});
diff.modified.iter().for_each(|modified| {
println!("mod {:?}", modified.path);
});
println!(
"created {} / deleted {} / modified {} / total {}",
diff.created.len(),
diff.deleted.len(),
diff.modified.len(),
diff.created.len() + diff.deleted.len() + diff.modified.len()
);
println!("diff took {} nanos ", elapsed_nanos);
}
struct Options {
path_to_repo: String,
base_revision: String,
head_revision: HeadRevision,
}
enum HeadRevision {
Head,
Commit(String),
}
impl Options {
fn parse(args: Args) -> Result<Self, String> {
let args: Vec<String> = args.collect();
if args.len() != 4 {
return Err(format!(
"Usage: {} <path-to-repo> <base-revision> <head-revision>\n\
\tpath-to-repo: Path to the directory containing .git subdirectory\n\
\tbase-revision: Git commit ID of the base revision (one that will be considered less recent)\n\
\thead-revision: Git commit ID of the head revision (one that will be considered more recent) or 'HEAD' to use current git HEAD\n",
args[0]));
}
let path_to_repo = args[1].clone();
let base_revision = args[2].clone();
let head_revision = {
if args[3].eq_ignore_ascii_case("HEAD") {
HeadRevision::Head
} else {
HeadRevision::Commit(args[3].clone())
}
};
Ok(Options {
path_to_repo,
base_revision,
head_revision,
})
}
}