| M | bin/ | 11 | +++++++++-- |
| M | test/ | 13 | +++++++++++++ |
@@ -1288,6 +1288,10 @@ repo_rm() {
12881288 trash=$FORGE_STATE/trash/$owner12891289 mkdir -p "$trash"12901290 t=$(date -u +%Y%m%dT%H%M%SZ)1291+ # Two removals in one second get .2, .3, ...: mv onto an existing1292+ # directory would put the repo inside it.1293+ n=11294+ while [ -e "$trash/$name.git.$t" ]; do n=$((n + 1)) t=${t%%.*}.$n; done12911295 mv "$FORGE_ROOT/$1.git" "$trash/$name.git.$t"12921296 # The time it was removed, which gc counts from.12931297 touch "$trash/$name.git.$t"@@ -1308,8 +1312,11 @@ repo_restore() {
13081312 owner=${1%%/*} name=${1#*/}13091313 valid_name "$owner" && valid_name "$name" && [ "$owner/$name" = "$1" ] || die "invalid repo: $1"13101314 [ ! -e "$FORGE_ROOT/$1.git" ] || die "$1 exists; remove or rename it first"1311- from=$(ls -d "$FORGE_STATE/trash/$owner/$name.git."* 2>/dev/null | sort | tail -n 1)1312- [ -n "$from" ] || die "no removed $1 in the trash"1315+ # Newest last: by the time after <name>.git., then by the .N of a second1316+ # removal within that second (names may hold dots, times don't).1317+ when=$(cd "$FORGE_STATE/trash/$owner" 2>/dev/null && for x in "$name.git."*; do [ -e "$x" ] && printf '%s\n' "${x#"$name.git."}"; done | sort -t . -k 1,1 -k 2,2n | tail -n 1)1318+ [ -n "$when" ] || die "no removed $1 in the trash"1319+ from=$FORGE_STATE/trash/$owner/$name.git.$when13131320 mkdir -p "$FORGE_ROOT/$owner"13141321 mv "$from" "$FORGE_ROOT/$1.git"13151322 repo_setup "$FORGE_ROOT/$1.git"@@ -55,3 +55,16 @@ eq "$(ls "$FORGE_ROOT/.forge/trash/dami" | grep -c '^greet\.git\.')" 1
5555 ok env FORGE_TRASH_DAYS=0 "$FORGE" gc --age 05656 output | grep -q '^removed trash dami/greet\.git\.' || fail "gc removed no trash"5757 eq "$(ls "$FORGE_ROOT/.forge/trash/dami" | grep -c '^greet\.git\.' || true)" 058+59+# A dotted name removed twice, likely within one second: two entries side60+# by side, never one inside the other, and restore takes the newer.61+repo dami/klot.ski62+git --git-dir="$FORGE_ROOT/dami/klot.ski.git" config forge.mark first63+ok forge repo rm dami/klot.ski64+repo dami/klot.ski65+git --git-dir="$FORGE_ROOT/dami/klot.ski.git" config forge.mark second66+ok forge repo rm dami/klot.ski67+eq "$(ls "$FORGE_ROOT/.forge/trash/dami" | grep -c '^klot\.ski\.git\.')" 268+eq "$(find "$FORGE_ROOT/.forge/trash" -mindepth 3 -maxdepth 3 -name '*.git.*' | wc -l | tr -d ' ')" 069+ok forge repo restore dami/klot.ski70+eq "$(git --git-dir="$FORGE_ROOT/dami/klot.ski.git" config forge.mark)" second