Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add a command to clean the store from empty directories #77

Merged
merged 19 commits into from
Nov 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions src/nu-git-manager/fs/dir.nu
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use path.nu ["path sanitize"]

# clean all empty directories recursively, starting from a list of empty leaves
#
# /!\ this command will return sanitized paths /!\
export def clean-empty-directories-rec []: list<path> -> list<path> {
let deleted = unfold $in {|directories|
let next = $directories | each {|it|
rm --force $it

let parent = $it | path dirname;
if (ls $parent | is-empty) {
$parent | path sanitize
}
}

if ($next | is-empty) {
{out: $directories}
} else {
{out: $directories, next: $next}
}
}

$deleted | flatten
}
49 changes: 47 additions & 2 deletions src/nu-git-manager/mod.nu
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ use fs/cache.nu [
get-repo-store-cache-path, check-cache-file, add-to-cache, remove-from-cache, open-cache,
save-cache, clean-cache-dir
]
use fs/dir.nu [clean-empty-directories-rec]
use fs/path.nu ["path sanitize"]
use git/url.nu [parse-git-url, get-fetch-push-urls]
use error/error.nu [throw-error]

Expand Down Expand Up @@ -318,11 +320,54 @@ export def "gm remove" [
}
}

rm --recursive --force --verbose ($root | path join $repo_to_remove)
let repo_to_remove = $root | path join $repo_to_remove

rm --recursive --force --verbose $repo_to_remove

let cache_file = get-repo-store-cache-path
check-cache-file $cache_file
remove-from-cache $cache_file ($root | path join $repo_to_remove)
remove-from-cache $cache_file $repo_to_remove

if (ls ($repo_to_remove | path dirname) | is-empty) {
let deleted = [($repo_to_remove | path dirname)] | clean-empty-directories-rec

print "the following empty directories have been removed:"
print $deleted
} else {
print "no empty directory to clean"
}

null
}

# clean the store
#
# this command will mainly remove empty directory recursively.
#
# /!\ this command will return sanitized paths. /!\
#
# Examples
# clean the store
# > gm clean
#
# list the leaves of the store that would have to be cleaned
# > gm clean --list
export def "gm clean" [
--list # only list without cleaning
]: nothing -> list<path> {
let empty_directories_in_store = ls (gm status | get root.path | path join "**")
| where (ls $it.name | is-empty)
| get name
| path expand
| each { path sanitize }
let cached_repos = gm list --full-path

let empty_non_repo_directories_in_store = $empty_directories_in_store
| where not ($cached_repos | any {|repo| $it | str starts-with $repo})

if $list {
return $empty_non_repo_directories_in_store
}

$empty_non_repo_directories_in_store | clean-empty-directories-rec
}
37 changes: 37 additions & 0 deletions tests/gm.nu
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,43 @@ export def remove [] {
}
}

export def store-cleaning-after-remove [] {
run-with-env --prepare-cache {
gm clone https://github.com/amtoine/nu-git-manager --depth 1
gm remove "github.com/amtoine/nu-git-manager" --no-confirm

# NOTE: the root should not exist anymore because there was only one repo in it and it's
# been cleaned
assert not ($env.GIT_REPOS_HOME | path exists)
}
}

export def store-cleaning [] {
run-with-env --prepare-cache {
gm clone https://github.com/amtoine/nu-git-manager --depth 1

let repo = (
$env.GIT_REPOS_HOME | path join "github.com/amtoine/nu-git-manager" | path sanitize
)

rm --force --recursive --verbose $repo

let expected = [($repo | path dirname)]
assert equal (gm clean --list) $expected

let expected = [
($repo | path dirname)
($repo | path dirname --num-levels 2)
($repo | path dirname --num-levels 3)
]
assert equal (gm clean) $expected

# NOTE: the root should not exist anymore because there was only one repo in it and it's
# been cleaned
assert not ($env.GIT_REPOS_HOME | path exists)
}
}

export def user-import [] {
^$nu.current-exe --commands "use ./src/nu-git-manager/ *"
}
42 changes: 42 additions & 0 deletions tests/mod.nu
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use ../src/nu-git-manager/fs/cache.nu [
save-cache, clean-cache-dir
]
use ../src/nu-git-manager/fs/path.nu "path sanitize"
use ../src/nu-git-manager/fs/dir.nu [clean-empty-directories-rec]

export def path-sanitization [] {
assert equal ('\foo\bar' | path sanitize) "/foo/bar"
Expand Down Expand Up @@ -240,3 +241,44 @@ export def install-package [] {
rm --recursive --force --verbose $env.NUPM_HOME
}
}

export def store-cleaning [] {
with-env {GIT_REPOS_HOME: ($nu.home-path | path join ".local/share/nu-git-manager-tests")} {
mkdir $env.GIT_REPOS_HOME
# NOTE: this is to make sure the root of the test is not empty
# we don't want the test to go remove empty directories outside...
touch ($env.GIT_REPOS_HOME | path join ".lock")

let empty_directories = [
foo/bar/
bar/
baz/foo/bar/
]

let actual = $empty_directories
| each {|it|
let path = $env.GIT_REPOS_HOME | path join $it | path sanitize

print $"making `($path)`"
mkdir $path

$path
}
| clean-empty-directories-rec
| str replace ($env.GIT_REPOS_HOME | path sanitize) ''
| str trim --char '/'
let expected = [
"foo/bar",
"bar",
"baz/foo/bar",
"foo",
"baz/foo",
"baz",
"",
]

assert equal $actual $expected

rm --recursive --verbose --force $env.GIT_REPOS_HOME
}
}