mirror of
https://github.com/msfjarvis/gitice
synced 2025-08-14 14:07:01 +05:30
64 lines
2.4 KiB
Rust
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(())
|
|
}
|