From 5eff1508ac2ca26f20a79d5a34b86cd97123dfce Mon Sep 17 00:00:00 2001 From: Harsh Shandilya Date: Mon, 9 Nov 2020 06:32:06 +0530 Subject: [PATCH] Split across multiple files Signed-off-by: Harsh Shandilya --- src/git.rs | 83 +++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 95 ++++------------------------------------------------ src/model.rs | 7 ++++ 3 files changed, 96 insertions(+), 89 deletions(-) create mode 100644 src/git.rs create mode 100644 src/model.rs diff --git a/src/git.rs b/src/git.rs new file mode 100644 index 0000000..3aa83c0 --- /dev/null +++ b/src/git.rs @@ -0,0 +1,83 @@ +use crate::model::PersistableRepo; +use git2::Repository; +use std::{ + collections::HashMap, + fs, + path::{Path, PathBuf}, + process::Command, +}; +use walkdir::WalkDir; + +pub(crate) fn freeze_repos(dir: &str) -> anyhow::Result<()> { + let mut repos: HashMap = HashMap::new(); + for entry in WalkDir::new(dir).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::>()[2], + ) { + let path = entry + .path() + .strip_prefix(Path::new(dir))? + .to_str() + .unwrap() + .to_string(); + repos.insert( + path, + PersistableRepo { + 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!"); + println!( + "Successfully generated lockfile with {} repos", + &repos.len() + ); + Ok(()) +} + +pub(crate) fn thaw_repos(dir: &str, lockfile: &str) -> anyhow::Result<()> { + let lockfile = fs::read_to_string(lockfile) + .unwrap_or_else(|_| panic!("unable to read lockfile from {}", lockfile)); + let repos: HashMap = toml::from_str(&lockfile)?; + + for (name, repo) in repos { + println!("Cloning {} from {}", &name, &repo.remote_url); + let output = Command::new("git") + .args(&[ + "clone", + &repo.remote_url, + PathBuf::from(&dir).join(&name).to_str().unwrap(), + ]) + .output() + .expect("Failed to run `git clone`. Perhaps git is not installed?"); + + if output.status.success() { + println!("Thawed {} successfully.", name) + } else { + println!("{}", std::str::from_utf8(&output.stderr)?) + } + } + + Ok(()) +} diff --git a/src/main.rs b/src/main.rs index cba1917..1517c76 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,20 +1,11 @@ +pub(crate) mod git; +pub(crate) mod model; + +use git::freeze_repos; +use git::thaw_repos; + use anyhow::anyhow; use clap::{crate_version, App, AppSettings, Arg}; -use git2::Repository; -use serde::{Deserialize, Serialize}; -use std::{ - collections::HashMap, - fs, - path::{Path, PathBuf}, - process::Command, -}; -use walkdir::WalkDir; - -#[derive(Debug, Serialize, Deserialize)] -struct PersistableRepo { - pub(crate) remote_url: String, - pub(crate) head: String, -} fn main() -> anyhow::Result<()> { let matches = App::new("gitice") @@ -62,77 +53,3 @@ fn main() -> anyhow::Result<()> { Ok(()) } - -fn freeze_repos(dir: &str) -> anyhow::Result<()> { - let mut repos: HashMap = HashMap::new(); - for entry in WalkDir::new(dir).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::>()[2], - ) { - let path = entry - .path() - .strip_prefix(Path::new(dir))? - .to_str() - .unwrap() - .to_string(); - repos.insert( - path, - PersistableRepo { - 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!"); - println!( - "Successfully generated lockfile with {} repos", - &repos.len() - ); - Ok(()) -} - -fn thaw_repos(dir: &str, lockfile: &str) -> anyhow::Result<()> { - let lockfile = fs::read_to_string(lockfile) - .unwrap_or_else(|_| panic!("unable to read lockfile from {}", lockfile)); - let repos: HashMap = toml::from_str(&lockfile)?; - - for (name, repo) in repos { - println!("Cloning {} from {}", &name, &repo.remote_url); - let output = Command::new("git") - .args(&[ - "clone", - &repo.remote_url, - PathBuf::from(&dir).join(&name).to_str().unwrap(), - ]) - .output() - .expect("Failed to run `git clone`. Perhaps git is not installed?"); - - if output.status.success() { - println!("Thawed {} successfully.", name) - } else { - println!("{}", std::str::from_utf8(&output.stderr)?) - } - } - - Ok(()) -} diff --git a/src/model.rs b/src/model.rs new file mode 100644 index 0000000..a732ecc --- /dev/null +++ b/src/model.rs @@ -0,0 +1,7 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize)] +pub(crate) struct PersistableRepo { + pub(crate) remote_url: String, + pub(crate) head: String, +}