gitice/src/main.rs
ATechnoHazard 444dea3e03
Strip dir path prefix without moving
Signed-off-by: ATechnoHazard <amolele@gmail.com>
2020-10-19 03:02:08 +05:30

64 lines
2.4 KiB
Rust

use git2::Repository;
use serde::{Deserialize, Serialize};
use std::{collections::HashMap, fs, path::Path};
use walkdir::WalkDir;
#[derive(Debug, Serialize, Deserialize)]
struct PersistableRepo {
pub(crate) path: String,
pub(crate) remote_url: String,
pub(crate) head: String,
}
fn main() -> anyhow::Result<()> {
let dir = match std::env::args().nth(1) {
Some(d) => d,
None => {
println!("Usage:\n gitice <dir>\n");
return Ok(());
}
};
let mut repos: HashMap<String, PersistableRepo> = HashMap::new();
for entry in WalkDir::new(dir.clone()).into_iter().filter_map(|e| e.ok()) {
if entry.file_type().is_dir() {
let path = format!("{}/.git", entry.path().display());
let git_dir = Path::new(&path);
if git_dir.exists() {
let repo = Repository::open(git_dir)?;
if repo.is_empty()? {
continue;
}
let head = repo.head()?;
if let Some(head) = head.name() {
if let Ok(upstream) = repo.branch_upstream_name(head) {
if let Ok(remote) = repo.find_remote(
// This is a rather ugly hack, but not sure how else to get the required name
// doesn't seem to work with the full name such as `refs/remotes/origin/master`
upstream.as_str().unwrap().split('/').collect::<Vec<&str>>()[2],
) {
let path = entry
.path()
.to_string_lossy()
.strip_prefix(&dir)
.unwrap()
.to_string();
repos.insert(
path.clone(),
PersistableRepo {
path,
remote_url: remote.url().unwrap_or("None").to_owned(),
head: head.to_owned(),
},
);
}
}
};
}
};
}
fs::write("gitice.lock", toml::to_string(&repos)?).expect("could not write to lockfile!");
Ok(())
}