Skip to main content

Merge pull request #27 from alexwlchan/ignore-dot-git-directory

ID
3ff4e69
date
2024-12-01 20:54:05+00:00
author
Alex Chan <alex@alexwlchan.net>
parents
9bdfafa, ae450d5
message
Merge pull request #27 from alexwlchan/ignore-dot-git-directory

Don't delete the `.git` directory or any subdirectories
changed files
5 files, 66 additions, 6 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 6326bb4..323593c 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 9d91b49..eda23c2 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]

README.md (3224) → README.md (3575)

diff --git a/README.md b/README.md
index b823d46..ca454b6 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
 This tool looks for empty directories and deletes them.
 
 ```console
-$ emptydir 
+$ emptydir
 ```
 
 More specifically, it deletes directories which are completely empty, or which only contain files/folders which I don't think are worth keeping (e.g. `.DS_Store` or `__pycache__`).
@@ -90,9 +90,18 @@ $ emptydir
 
 Currently the list of files/folders which I consider safe to delete is hard-coded in `can_be_deleted.rs`:
 
-*   `.DS_Store` stores some folder attributes used for showing the folder in the Finder, which I don't need to keep
-*   `__pycache__` is the bytecode cache in Python projects, which is pointless if the original Python files have been removed
-*   `.venv` is the name I use for virtual environments, which I can asily regenerate if necessary
+*  .DS_Store stores some folder attributes used for showing the folder
+   in the Finder, which I don't need to keep
+*  `.ipynb_checkpoints` is a folder used by Jupyter Notebooks, but not
+   important if I've deleted the notebooks
+*  `.jekyll-cache` is a cache directory used by Jekyll sites, but
+   can be easily regenerated and will be rebuilt regularly as part
+   of the Jekyll build process
+*  `.venv` is the name I use for virtual environments, which I can
+   easily regenerate if necessary
+*  `__pycache__` is the bytecode cache in Python projects, which is
+   pointless if the original Python files have been removed
+*  `Thumbs.db` is a file that contains thumbnails on Windows systems
 
 If you want to change that list, you need to modify the source code and compile a new version -- it's not a configurable setting.
 

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);
+    }
 }