diff options
author | Justin Wernick <justin@worthe-it.co.za> | 2023-07-14 13:13:11 +0200 |
---|---|---|
committer | Justin Wernick <justin@worthe-it.co.za> | 2023-07-14 13:13:11 +0200 |
commit | 755e28d044aaff9a8aa0fa4700105564726ec33d (patch) | |
tree | 45eb98e20c340fc203737843cf43f766026d0c72 | |
parent | 58664db6007920939d94977cc7382a5709b16558 (diff) |
Add a housekeeping task, which does git gc
-rw-r--r-- | src/git.rs | 14 | ||||
-rw-r--r-- | src/lib.rs | 19 | ||||
-rw-r--r-- | src/parser.rs | 9 | ||||
-rw-r--r-- | tests/cli.rs | 13 | ||||
-rw-r--r-- | tests/cli_test_utils/git.rs | 9 |
5 files changed, 59 insertions, 5 deletions
@@ -234,6 +234,20 @@ pub fn set_branch(directory: &Path, branch: &str) -> Result<(), ShackleError> { } } +pub fn housekeeping(directory: &Path) -> Result<(), ShackleError> { + if !is_valid_git_repo_path(directory)? { + return Err(ShackleError::InvalidDirectory); + } + + Command::new("git") + .arg("gc") + .current_dir(directory) + .spawn()? + .wait()?; + + Ok(()) +} + pub fn delete(directory: &Path) -> Result<(), ShackleError> { if !is_valid_git_repo_path(directory)? { return Err(ShackleError::InvalidDirectory); @@ -63,6 +63,25 @@ pub fn run_command(user_input: &str) -> Result<ControlFlow<(), ()>, ShackleError git::delete(&directory)?; println!("Successfully deleted \"{}\"", directory.display()); } + Ok(ShackleCommand::Housekeeping(HousekeepingArgs { directory })) => match directory { + Some(directory) => { + git::housekeeping(&directory)?; + println!( + "Successfully did housekeeping on \"{}\"", + directory.display() + ); + } + None => { + let list = git::list()?; + for repo in list { + git::housekeeping(&repo.path)?; + println!( + "Successfully did housekeeping on \"{}\"", + repo.path.display() + ); + } + } + }, Ok(ShackleCommand::GitUploadPack(upload_pack_args)) => { git::upload_pack(&upload_pack_args)?; } diff --git a/src/parser.rs b/src/parser.rs index b429572..5806cec 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -18,6 +18,8 @@ pub enum ShackleCommand { SetBranch(SetBranchArgs), /// Deletes a repository Delete(DeleteArgs), + /// Does any housekeeping, like deleting unreachable objects and repacking more efficiently + Housekeeping(HousekeepingArgs), /// Quit the shell Exit, /// Server side command required to git fetch from the server @@ -74,6 +76,13 @@ pub struct DeleteArgs { } #[derive(Parser, Clone, Debug, PartialEq, Eq)] +pub struct HousekeepingArgs { + /// The full relative path of the repository, for example + /// git/shuckie/repo.git. If omitted, all repos will be checked. + pub directory: Option<PathBuf>, +} + +#[derive(Parser, Clone, Debug, PartialEq, Eq)] pub struct GitUploadPackArgs { /// Do not try <directory>/.git/ if <directory> is no Git directory #[arg(long, default_value_t = true)] diff --git a/tests/cli.rs b/tests/cli.rs index 0520e89..598152b 100644 --- a/tests/cli.rs +++ b/tests/cli.rs @@ -273,7 +273,6 @@ fn can_delete_a_repo() -> Result<()> { } #[test] -#[ignore] fn git_housekeeping_repacks_objects() -> Result<()> { let mut c = TestContext::new_interactive()?; let repo_path = personal_repo_path(REPO_NAME); @@ -284,11 +283,15 @@ fn git_housekeeping_repacks_objects() -> Result<()> { let checkout_dir = create_clone(&c, &repo_dir, REPO_NAME); create_commit(&checkout_dir)?; + push(&checkout_dir, "main"); + + let packs_dir = repo_dir.join("objects").join("pack"); + + assert_eq!(packs_dir.read_dir()?.count(), 0); + c.p.send_line(&format!("housekeeping {repo_path}"))?; + c.p.exp_string(&format!("Successfully did housekeeping on \"{repo_path}\""))?; + assert!(packs_dir.read_dir()?.count() > 0); - // push to the repo - // check that objects exist, not packs - // run housekeeping - // check that only packs exist Ok(()) } diff --git a/tests/cli_test_utils/git.rs b/tests/cli_test_utils/git.rs index 150af45..fe6e1bd 100644 --- a/tests/cli_test_utils/git.rs +++ b/tests/cli_test_utils/git.rs @@ -46,6 +46,15 @@ pub fn create_commit(repo_dir: &Path) -> Result<String> { Ok(commit_hash) } +pub fn push(local_repo_dir: &Path, branch: &str) { + Command::new("git") + .args(["push", "origin", branch]) + .current_dir(&local_repo_dir) + .timeout(std::time::Duration::from_secs(3)) + .assert() + .success(); +} + pub fn verify_repo_exists(repo_dir: &Path) { Command::new("git") .arg("rev-list") |