summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin Wernick <justin@worthe-it.co.za>2023-07-14 13:13:11 +0200
committerJustin Wernick <justin@worthe-it.co.za>2023-07-14 13:13:11 +0200
commit755e28d044aaff9a8aa0fa4700105564726ec33d (patch)
tree45eb98e20c340fc203737843cf43f766026d0c72
parent58664db6007920939d94977cc7382a5709b16558 (diff)
Add a housekeeping task, which does git gc
-rw-r--r--src/git.rs14
-rw-r--r--src/lib.rs19
-rw-r--r--src/parser.rs9
-rw-r--r--tests/cli.rs13
-rw-r--r--tests/cli_test_utils/git.rs9
5 files changed, 59 insertions, 5 deletions
diff --git a/src/git.rs b/src/git.rs
index d92b5a0..76ff326 100644
--- a/src/git.rs
+++ b/src/git.rs
@@ -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);
diff --git a/src/lib.rs b/src/lib.rs
index 809c62d..163e41b 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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")