Skip to main content

Don’t delete the .git directory or any subdirectories

ID
ae450d5
date
2024-12-01 20:50:39+00:00
author
Alex Chan <alex@alexwlchan.net>
parent
9cf1631
message
Don't delete the `.git` directory or any subdirectories
changed files
4 files, 53 additions, 2 deletions

Changed files

CHANGELOG.md (759) → CHANGELOG.md (970)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index e6e0fd8..e536447 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,11 @@
 # Changelog
 
+## v1.2.1 - 2024-12-01
+
+Don't delete the `.git` directory or any subdirectories.
+
+Messing with the internal structure `.git` can cause issues for Git, so just leave it as-is, even if it contains empty folders.
+
 ## v1.2.0 - 2024-08-21
 
 Delete empty parent directories.

Cargo.lock (12734) → Cargo.lock (12734)

diff --git a/Cargo.lock b/Cargo.lock
index a7593e5..e39d3ae 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -127,7 +127,7 @@ dependencies = [
 
 [[package]]
 name = "emptydir"
-version = "1.2.0"
+version = "1.2.1"
 dependencies = [
  "clap",
  "colored",

Cargo.toml (200) → Cargo.toml (200)

diff --git a/Cargo.toml b/Cargo.toml
index 710384e..42958fa 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "emptydir"
-version = "1.2.0"
+version = "1.2.1"
 edition = "2021"
 
 [dependencies]

src/can_be_deleted.rs (4717) → src/can_be_deleted.rs (5954)

diff --git a/src/can_be_deleted.rs b/src/can_be_deleted.rs
index 285cdf1..22a9c94 100644
--- a/src/can_be_deleted.rs
+++ b/src/can_be_deleted.rs
@@ -19,6 +19,13 @@ fn get_names_in_directory(dir: &Path) -> io::Result<HashSet<OsString>> {
     Ok(HashSet::from_iter(names))
 }
 
+/// Returns True if this path any ancestor is a `.git` folder,
+/// False otherwise.
+pub fn is_in_git_folder(path: &Path) -> bool {
+    path.ancestors()
+        .any(|ancestor| ancestor.file_name().map_or(false, |name| name == ".git"))
+}
+
 pub fn can_be_deleted(path: &Path) -> bool {
     // This is a folder where I put files that I explicitly don't want
     // to include in my backups.
@@ -30,6 +37,24 @@ pub fn can_be_deleted(path: &Path) -> bool {
         _ => (),
     };
 
+    // Don't delete subfolders of a `.git` directory.
+    //
+    // For example, if you delete `.git/refs`, then Git can't detect
+    // the Git directory any more.  Observe:
+    //
+    //     $ git init .
+    //     Initialized empty Git repository in tmp.bTrs8ZaWjc/.git/
+    //
+    //     $ rm -rf .git/refs
+    //
+    //     $ git status
+    //     fatal: not a git repository (or any of the parent directories): .git
+    //
+    // Skipping these folders is fine.
+    if is_in_git_folder(path) {
+        return false;
+    }
+
     // This is the list of entries which I consider safe to delete.
     //
     // *  .DS_Store stores some folder attributes used for showing the folder
@@ -156,4 +181,24 @@ mod test_can_be_deleted {
 
         assert_eq!(can_be_deleted(&path), true);
     }
+
+    #[test]
+    fn the_dot_git_folder_cannot_be_deleted() {
+        let path = test_dir();
+        let git_dir = path.join(".git");
+
+        create_dir(&git_dir);
+
+        assert_eq!(can_be_deleted(&git_dir), false);
+    }
+
+    #[test]
+    fn any_subdir_of_the_dot_git_folder_cannot_be_deleted() {
+        let path = test_dir();
+        let refs_dir = path.join(".git/refs");
+
+        create_dir(&refs_dir);
+
+        assert_eq!(can_be_deleted(&refs_dir), false);
+    }
 }