dotcli: add dot setup folders (XDG short-name migration)
Adds a dot setup subcommand family (idempotent, re-runnable machine-setup tasks) with a folders task that brings the 8 standard XDG user directories under a fixed short-name convention (Desktop -> .desktop, Documents -> doc, Downloads -> dwn, Music -> mus, Pictures -> pic, Videos -> vid, Templates/Public -> .ignoreme), hardcoded rather than read from ~/.config/user-dirs.dirs -- that file is a separate, manually tracked dotfile whose values can drift or go stale, and the migration must not depend on it being correct. The nested Pictures/Screenshots folder is renamed to pic/screenshots in the same pass. Content left behind in a legacy full-named folder by a fresh XDG-defaults install -- empty or not -- is merged into its short-named replacement. A same-named collision between a legacy folder and its target is never overwritten: it is skipped, reported, and the legacy folder is left in place rather than deleted while something in it could not be merged. --dry-run previews what would move/skip without touching the filesystem. xdg-user-dirs-update runs once afterward to notify running apps/portals.
This commit is contained in:
@@ -41,20 +41,50 @@ duplication point, and a README command-table row.
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
- [ ] `dot setup folders` on a fresh scratch `$HOME` (all 8 legacy folders
|
||||
- [x] `dot setup folders` on a fresh scratch `$HOME` (all 8 legacy folders
|
||||
present and empty) renames them to their short-name targets per the
|
||||
mapping table, including `Pictures/Screenshots→pic/screenshots`, and
|
||||
leaves the tracked `user-dirs.dirs` short names in place
|
||||
- [ ] The fake `xdg-user-dirs-update` (PATH-prepended, logging its invocation
|
||||
- [x] The fake `xdg-user-dirs-update` (PATH-prepended, logging its invocation
|
||||
per the project's existing fake-`sudo`/fake-`pacman` testing pattern)
|
||||
is invoked exactly once after a successful migration
|
||||
- [ ] Bare `dot setup` on a fresh scratch `$HOME` runs the `folders` task as
|
||||
- [x] Bare `dot setup` on a fresh scratch `$HOME` runs the `folders` task as
|
||||
part of running everything
|
||||
- [ ] `dot setup folders help` and `dot setup help` print usage and make no
|
||||
- [x] `dot setup folders help` and `dot setup help` print usage and make no
|
||||
filesystem changes
|
||||
- [ ] Re-running `dot setup folders` after a clean migration is a no-op
|
||||
- [x] Re-running `dot setup folders` after a clean migration is a no-op
|
||||
(idempotent)
|
||||
- [ ] `~/.github/README.md` has a command-table row for `dot setup`
|
||||
- [x] `~/.github/README.md` has a command-table row for `dot setup`
|
||||
(and its `folders` task) with paths relative to `$HOME`
|
||||
- [ ] `~/.config/dot/tests/dot.fish` covers the above cases and
|
||||
- [x] `~/.config/dot/tests/dot.fish` covers the above cases and
|
||||
`fishtape ~/.config/dot/tests/dot.fish` passes
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- The desired short names for `dot setup folders` are read directly from the
|
||||
tracked `~/.config/user-dirs.dirs` (parsed via `grep`/`string match`, not
|
||||
sourced as shell), per the parent spec's decision that this file is the
|
||||
single source of truth. This machine's real `user-dirs.dirs` was
|
||||
deliberately left untouched/untracked and no live migration was run against
|
||||
this machine's actual home directory — the user chose "code + tests only"
|
||||
scope for this task (a real rename of `~/Desktop`, `~/Documents`, etc. is a
|
||||
separate, explicit action to take later), so only the scratch-`$HOME`
|
||||
fishtape fixtures exercise the short-name `user-dirs.dirs` content.
|
||||
Tracking the real file and running the real migration remains open.
|
||||
- During `/review-uncommitted`, the spec-fidelity pass caught a real bug: the
|
||||
nested `Pictures/Screenshots→pic/screenshots` move ran unconditionally,
|
||||
before checking whether `Pictures` held other, unrelated content — so a
|
||||
`Pictures` folder with both `Screenshots/` and some other file got
|
||||
partially mutated (Screenshots pulled out) while still being reported as
|
||||
"left in place." Fixed by gating the Screenshots move on the rest of the
|
||||
folder being empty too; added a regression test for this case
|
||||
("Screenshots is not peeled off... when Pictures still has other
|
||||
content").
|
||||
- Completions (`~/.config/fish/completions/dot.fish`) got a `dot setup`
|
||||
block mirroring `dot kde`'s per-subcommand completion entries, even though
|
||||
the task's required "completions/help-glob duplication point" is already
|
||||
satisfied automatically by the existing generic directory glob (no changes
|
||||
were needed there for `dot setup`/`dot help` to discover the new nested
|
||||
command). The added completions are a small polish addition beyond the
|
||||
strict letter of the acceptance criteria, consistent with the existing
|
||||
`kde` subcommand's treatment.
|
||||
|
||||
@@ -19,12 +19,34 @@ rule.
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
- [ ] A legacy folder with real content (a real file, not just an empty
|
||||
- [x] A legacy folder with real content (a real file, not just an empty
|
||||
directory) refuses to migrate without `--yes`, prints what would have
|
||||
been moved, and leaves the folder and its contents untouched
|
||||
- [ ] The same legacy folder migrates successfully when `--yes` is passed
|
||||
- [ ] A legacy folder containing only a stray dotfile/metadata file (e.g. a
|
||||
- [x] The same legacy folder migrates successfully when `--yes` is passed
|
||||
- [x] A legacy folder containing only a stray dotfile/metadata file (e.g. a
|
||||
fake `.directory`) is still treated as non-empty and triggers the same
|
||||
confirmation gate
|
||||
- [ ] `~/.config/dot/tests/dot.fish` covers the above cases and
|
||||
- [x] `~/.config/dot/tests/dot.fish` covers the above cases and
|
||||
`fishtape ~/.config/dot/tests/dot.fish` passes
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- `--yes`'s actual move reuses the exact same branch shape as the existing
|
||||
silent-empty path (rename `Screenshots` → `screenshots` when present, then
|
||||
`rmdir` the legacy folder), extended to also `mv` any remaining top-level
|
||||
entries into the target first. Screenshots is always moved as one atomic
|
||||
unit — its individual files are never mv'd/reported separately — so a
|
||||
non-empty `Screenshots` (own acceptance criterion in the parent spec) is
|
||||
gated and migrated the same way a non-empty top-level file would be.
|
||||
- Collision handling (no-clobber `mv -n`, reporting skipped files, leaving the
|
||||
legacy folder in place on a collision) is explicitly out of scope here —
|
||||
it's owned by 0008-folders-collision-handling.md, per that task's own
|
||||
frontmatter/spec section. The `--yes` path added here uses a plain `mv`.
|
||||
- `/review-uncommitted` flagged two minor issues, both fixed: a stale comment
|
||||
claiming a helper variable was used by both the silent-empty and `--yes`
|
||||
paths when it was only read by the latter, and a duplicated `find`
|
||||
invocation computing the same top-level listing twice under one condition
|
||||
(now computed once and reused). It also flagged the non-empty "would move"
|
||||
preview listing recursively-nested files individually instead of treating
|
||||
`Screenshots` as one unit like the real move does — fixed so the preview
|
||||
and the actual move share the same top-level-entries list.
|
||||
|
||||
@@ -18,15 +18,38 @@ $to`, which had no collision protection at all.
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
- [ ] A filename collision between a legacy folder and its already-populated
|
||||
- [x] A filename collision between a legacy folder and its already-populated
|
||||
short-named target is skipped, not overwritten (the target's existing
|
||||
file is preserved byte-for-byte)
|
||||
- [ ] The skipped collision is reported to the user
|
||||
- [ ] The legacy folder is left in place (not removed) when a collision
|
||||
- [x] The skipped collision is reported to the user
|
||||
- [x] The legacy folder is left in place (not removed) when a collision
|
||||
occurred, even though `--yes` was given and other non-colliding files
|
||||
in it were moved
|
||||
- [ ] Re-running `dot setup folders` after a collision was reported and left
|
||||
- [x] Re-running `dot setup folders` after a collision was reported and left
|
||||
in place behaves consistently (doesn't lose the previously-skipped
|
||||
file, doesn't re-move already-migrated files)
|
||||
- [ ] `~/.config/dot/tests/dot.fish` covers the above cases and
|
||||
- [x] `~/.config/dot/tests/dot.fish` covers the above cases and
|
||||
`fishtape ~/.config/dot/tests/dot.fish` passes
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- The two prior branches (silent-empty merge vs. `--yes`-confirmed merge)
|
||||
were unified into one `if test (count $other_entries) -eq 0; or set -q
|
||||
_flag_yes` branch, since the collision-detection/no-clobber logic is
|
||||
identical either way. This has one side effect beyond the letter of the
|
||||
acceptance criteria (which frame collision handling around the `--yes`
|
||||
path): a legacy folder that's otherwise "empty" except for an emptyish
|
||||
nested `Screenshots` dir now also gets collision-checked against an
|
||||
already-populated `pic/screenshots` on the silent, no-`--yes` path. This
|
||||
closes the same unguarded-`mv` gap the spec calls out as the motivating
|
||||
problem (the old code's silent-path `mv $screenshots_path
|
||||
$target_path/screenshots` had no collision protection at all either), so
|
||||
it was kept rather than special-cased away. Covered by its own test
|
||||
("a silent-path Screenshots collision ...").
|
||||
- Collision detection is a pre-check (`test -e $target_path/...`) before an
|
||||
actual `mv -n`, rather than relying on `mv -n`'s exit code alone, so each
|
||||
colliding entry can be individually identified and reported by path.
|
||||
- `/review-uncommitted` (risk: Medium, standards: 0 hard violations, spec:
|
||||
0 missing/wrong requirements) raised no changes needed; the one scope note
|
||||
it flagged (the silent-path Screenshots case above) was a deliberate,
|
||||
judged-correct decision rather than an oversight.
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
---
|
||||
spec: dot-setup-folders
|
||||
blocked-by: 0008-folders-collision-handling
|
||||
---
|
||||
|
||||
## What to build
|
||||
|
||||
Remove the `--yes` confirmation gate that 0007/0008 built: a legacy folder
|
||||
with real content in it is migrated unconditionally now, the same as an
|
||||
empty one, since the collision handling from 0008 already makes the merge
|
||||
non-destructive on its own (a same-named entry is never overwritten, and the
|
||||
legacy folder is kept whenever any collision occurred). The `--yes` gate
|
||||
turned out to protect against a scenario collision handling already
|
||||
prevents, while making the everyday case — a machine that already has real
|
||||
files in `~/Documents`, `~/Pictures`, etc. — a silent no-op unless the flag
|
||||
was remembered, which defeats the point of the task.
|
||||
|
||||
In its place:
|
||||
|
||||
- `dot setup folders` always attempts the merge for every legacy folder,
|
||||
content or none.
|
||||
- A new `--dry-run` flag replaces `--yes` in the flag slot: it reports what
|
||||
would move and what would be skipped as a collision, without touching the
|
||||
filesystem at all (no `mkdir`, no `mv`/`rmdir`, no `xdg-user-dirs-update`).
|
||||
- A real (non-dry-run) run now reports what it moved per legacy folder
|
||||
(e.g. `moved 12 entries from ~/Documents to ~/doc`), instead of staying
|
||||
silent on success. A folder where nothing top-level moved (already empty,
|
||||
or everything in it collided) prints no such line — only non-trivial moves
|
||||
and collisions produce output.
|
||||
- `--yes` is removed outright (not kept as a silent no-op): passing it now
|
||||
fails with argparse's standard unknown-option error.
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
- [x] A legacy folder with real content merges on a plain `dot setup
|
||||
folders`, with no flag required
|
||||
- [x] A real run prints `moved N entries from ~/<legacy> to ~/<target>` for a
|
||||
folder where top-level entries actually moved, and nothing for a
|
||||
folder where none did
|
||||
- [x] A real run prints a dedicated line when the nested Screenshots folder
|
||||
itself is moved (e.g. `moved ~/Pictures/Screenshots to ~/pic/screenshots`)
|
||||
- [x] Collision detection/reporting and the "leave the legacy folder in
|
||||
place when a collision occurred" behavior from 0008 are unchanged
|
||||
under the new unconditional default
|
||||
- [x] `--dry-run` reports the same would-move/would-skip information without
|
||||
creating any target directory, moving/removing anything, or invoking
|
||||
`xdg-user-dirs-update`
|
||||
- [x] `dot setup folders --yes` fails with an unknown-option error (argparse
|
||||
default), rather than being silently accepted or gated on
|
||||
- [x] `dot setup folders help` output no longer mentions `--yes` and
|
||||
documents `--dry-run` instead
|
||||
- [x] Idempotency holds: re-running after a clean merge, and re-running
|
||||
after a collision was reported, both behave the same as before
|
||||
- [x] `~/.config/dot/tests/dot.fish` is updated to exercise the above
|
||||
(replacing the old `--yes`-gated cases) and
|
||||
`fishtape ~/.config/dot/tests/dot.fish` passes
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- The `--yes` gate and the `screenshots_emptyish`/`other_entries` machinery
|
||||
that computed it were deleted outright rather than special-cased away:
|
||||
once merging is unconditional, that machinery had no remaining purpose
|
||||
(it existed solely to decide "empty enough to skip the gate").
|
||||
- `mkdir -p $target_path` and the final `xdg-user-dirs-update` are both now
|
||||
guarded by `not set -q _flag_dry_run`, making `--dry-run` a true no-op
|
||||
rather than "no-op except for directory scaffolding."
|
||||
- Collision detection (`test -e $target_path/...`) runs identically in both
|
||||
modes; `--dry-run` only gates the actual `mv`/`rmdir`/`mkdir` calls, so the
|
||||
reported would-move/would-skip split is exactly what a real run would do.
|
||||
- Success reporting is per-legacy-folder and suppressed at zero: a folder
|
||||
that was already empty (or whose only entries all collided) prints
|
||||
nothing, so a routine re-run stays quiet like before.
|
||||
- All prior collision/idempotency/Screenshots test scenarios were kept,
|
||||
just re-pointed at the plain `dot setup folders` invocation instead of
|
||||
`--yes`; two scenarios that only differed by which code branch (`--yes`
|
||||
vs. silent-empty) they exercised now hit the same branch, but were both
|
||||
kept since they still cover distinct fixture shapes (Pictures with vs.
|
||||
without unrelated top-level content alongside a colliding Screenshots).
|
||||
- `fishtape ~/.config/dot/tests/dot.fish` passes (178 tests).
|
||||
@@ -0,0 +1,64 @@
|
||||
---
|
||||
spec: dot-setup-folders
|
||||
blocked-by: 000b-folders-unconditional-merge
|
||||
---
|
||||
|
||||
## What to build
|
||||
|
||||
Stop reading the short-name target from `~/.config/user-dirs.dirs` and
|
||||
hardcode the legacy-name -> short-name mapping directly in
|
||||
`_dot_setup_folders`, dropping the dependency on that file entirely.
|
||||
|
||||
The original design treated the tracked `user-dirs.dirs` as the single
|
||||
source of truth for target names, assuming someone would hand-edit it to
|
||||
the short names before ever running the command. On this machine that
|
||||
never happened: the tracked file still had the stock XDG defaults
|
||||
(`XDG_DOCUMENTS_DIR="$HOME/Documents"`, etc.), so `target_path` resolved to
|
||||
the exact same directory as `legacy_path` for every folder. The migration
|
||||
logic then reported every entry as a "collision" against itself instead of
|
||||
moving anything -- a confusing, silent-feeling failure rather than an
|
||||
actual migration.
|
||||
|
||||
The short names are fixed (`.desktop`, `doc`, `dwn`, `mus`, `pic`, `vid`,
|
||||
`.ignoreme`) and not meant to be configurable, so there's nothing to read
|
||||
from a file in the first place. `user-dirs.dirs` remains a separate,
|
||||
manually tracked dotfile (edited and tracked by hand, like any other
|
||||
dotfile) for apps/`xdg-user-dirs-update` to consult -- `dot setup folders`
|
||||
itself no longer reads it, requires its presence, or writes to it.
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
- [x] `_dot_setup_folders` no longer reads, parses, or requires
|
||||
`~/.config/user-dirs.dirs`; the legacy->short-name mapping is a fixed
|
||||
table in the function itself
|
||||
- [x] Migration works identically whether `user-dirs.dirs` is absent,
|
||||
empty, or declares stale/full-name values (the exact real-world case)
|
||||
- [x] `user-dirs.dirs` is left byte-for-byte untouched by `dot setup
|
||||
folders` when present, and no file is created when absent
|
||||
- [x] `dot setup folders help` no longer describes reading target names
|
||||
from `user-dirs.dirs`
|
||||
- [x] `~/.config/dot/tests/dot.fish` no longer seeds a `user-dirs.dirs`
|
||||
fixture as a migration precondition, and covers the stale/missing
|
||||
cases above; `fishtape ~/.config/dot/tests/dot.fish` passes
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- Replaced the `xdg_vars`/`grep`/`string match` parsing of `user-dirs.dirs`
|
||||
with two parallel hardcoded arrays, `legacy_names` and `target_names`,
|
||||
indexed together -- same shape the code already used for `legacy_names`
|
||||
alone, just extended to cover the target side too.
|
||||
- The early `if not test -f $user_dirs; return 1` guard was deleted outright
|
||||
rather than kept as a soft check: there's nothing left for the function to
|
||||
read from that file, so requiring its existence would just be a
|
||||
vestigial, unjustifiable precondition.
|
||||
- Removed the `short_name_user_dirs` fixture and its seeding step from every
|
||||
test scenario (it was previously duplicated into ~15 scenarios as a
|
||||
migration precondition); added two new scenarios instead: one reproducing
|
||||
the exact real-machine bug (stale full-name `user-dirs.dirs` values) and
|
||||
one confirming migration works with no `user-dirs.dirs` file at all.
|
||||
- Verified against this machine's real, still-stale `~/.config/user-dirs.dirs`
|
||||
via `_dot_setup_folders --dry-run`: previously reported every entry in
|
||||
Desktop/Documents/Downloads/Pictures/Videos as a collision against
|
||||
itself; now correctly reports `would move N entries from ~/Documents to
|
||||
~/doc` etc.
|
||||
- `fishtape ~/.config/dot/tests/dot.fish` passes (183 tests).
|
||||
134
.config/dot/commands/setup/folders.fish
Normal file
134
.config/dot/commands/setup/folders.fish
Normal file
@@ -0,0 +1,134 @@
|
||||
function _dot_setup_folders_usage
|
||||
echo "usage: dot setup folders [--dry-run]
|
||||
|
||||
Brings the 8 standard XDG user directories under the project's fixed
|
||||
short-name convention (Desktop -> .desktop, Documents -> doc, Downloads ->
|
||||
dwn, Music -> mus, Pictures -> pic, Videos -> vid, Templates/Public ->
|
||||
.ignoreme). This mapping is fixed and does not depend on
|
||||
~/.config/user-dirs.dirs, which is a separate, manually tracked dotfile
|
||||
this command never reads or writes.
|
||||
|
||||
Content left behind in a legacy full-named folder (e.g. ~/Documents) by a
|
||||
fresh XDG-defaults install -- empty or not -- is merged into its short-named
|
||||
replacement. A nested Pictures/Screenshots folder is renamed to
|
||||
pic/screenshots as part of the same pass.
|
||||
|
||||
An entry that collides by name with something already in the short-named
|
||||
target is never overwritten: it's skipped, reported, and its legacy folder is
|
||||
left in place (not removed) even when everything else in it migrated.
|
||||
|
||||
--dry-run report what would move and what would be skipped as a
|
||||
collision, without changing anything on disk
|
||||
|
||||
Runs xdg-user-dirs-update once afterwards to notify running apps/portals
|
||||
(skipped under --dry-run)."
|
||||
end
|
||||
|
||||
function _dot_setup_folders
|
||||
if test "$argv[1]" = help
|
||||
_dot_setup_folders_usage
|
||||
return 0
|
||||
end
|
||||
|
||||
argparse 'dry-run' -- $argv
|
||||
or return 1
|
||||
|
||||
# Fixed legacy-name -> short-name mapping. Deliberately hardcoded rather
|
||||
# than read from ~/.config/user-dirs.dirs: that file is a separate,
|
||||
# manually tracked dotfile whose XDG_*_DIR values can drift or go stale
|
||||
# (or never get edited to the short names at all), and this command's
|
||||
# own migration logic must not depend on it being correct.
|
||||
set -l legacy_names Desktop Documents Downloads Music Pictures Videos Templates Public
|
||||
set -l target_names .desktop doc dwn mus pic vid .ignoreme .ignoreme
|
||||
|
||||
for i in (seq (count $legacy_names))
|
||||
set -l legacy_name $legacy_names[$i]
|
||||
set -l target_rel $target_names[$i]
|
||||
set -l target_path $HOME/$target_rel
|
||||
set -l legacy_path $HOME/$legacy_name
|
||||
|
||||
if not set -q _flag_dry_run
|
||||
mkdir -p $target_path
|
||||
end
|
||||
|
||||
if not test -d $legacy_path
|
||||
continue
|
||||
end
|
||||
|
||||
# Screenshots is always moved as one atomic unit (renamed to
|
||||
# lowercase screenshots), so its individual files must never appear
|
||||
# as separate move/report entries.
|
||||
set -l screenshots_path $legacy_path/Screenshots
|
||||
set -l top_level_entries (find $legacy_path -mindepth 1 -maxdepth 1 -not -name Screenshots)
|
||||
|
||||
# No-clobber: an entry whose name already exists in the target is
|
||||
# never moved over. It's collected here and reported below; its
|
||||
# legacy folder is left in place (not removed) if any collision
|
||||
# occurred, even though everything else in it migrated successfully.
|
||||
set -l collisions
|
||||
set -l movable_entries
|
||||
set -l screenshots_movable 0
|
||||
|
||||
if test -d $screenshots_path
|
||||
if test -e $target_path/screenshots
|
||||
set -a collisions $screenshots_path
|
||||
else
|
||||
set screenshots_movable 1
|
||||
end
|
||||
end
|
||||
|
||||
for entry in $top_level_entries
|
||||
if test -e $target_path/(path basename $entry)
|
||||
set -a collisions $entry
|
||||
else
|
||||
set -a movable_entries $entry
|
||||
end
|
||||
end
|
||||
|
||||
set -l movable_count (count $movable_entries)
|
||||
set -l entry_word entries
|
||||
test $movable_count -eq 1
|
||||
and set entry_word entry
|
||||
|
||||
if set -q _flag_dry_run
|
||||
if test $screenshots_movable -eq 1
|
||||
echo "dot setup folders: would move $screenshots_path to $target_path/screenshots"
|
||||
end
|
||||
if test $movable_count -gt 0
|
||||
echo "dot setup folders: would move $movable_count $entry_word from ~/$legacy_name to ~/$target_rel"
|
||||
end
|
||||
if test (count $collisions) -gt 0
|
||||
echo "dot setup folders: ~/$legacy_name has entries already present in ~/$target_rel, would skip (not overwritten):"
|
||||
for c in $collisions
|
||||
echo " $c"
|
||||
end
|
||||
echo "dot setup folders: ~/$legacy_name would remain in place due to the collision(s) above"
|
||||
end
|
||||
continue
|
||||
end
|
||||
|
||||
if test $screenshots_movable -eq 1
|
||||
mv -n $screenshots_path $target_path/screenshots
|
||||
echo "dot setup folders: moved $screenshots_path to $target_path/screenshots"
|
||||
end
|
||||
|
||||
if test $movable_count -gt 0
|
||||
mv -n $movable_entries $target_path/
|
||||
echo "dot setup folders: moved $movable_count $entry_word from ~/$legacy_name to ~/$target_rel"
|
||||
end
|
||||
|
||||
if test (count $collisions) -gt 0
|
||||
echo "dot setup folders: ~/$legacy_name has entries already present in ~/$target_rel, skipping (not overwritten):"
|
||||
for c in $collisions
|
||||
echo " $c"
|
||||
end
|
||||
echo "dot setup folders: leaving ~/$legacy_name in place due to the collision(s) above"
|
||||
else
|
||||
rmdir $legacy_path
|
||||
end
|
||||
end
|
||||
|
||||
if not set -q _flag_dry_run
|
||||
xdg-user-dirs-update
|
||||
end
|
||||
end
|
||||
35
.config/dot/commands/setup/setup.fish
Normal file
35
.config/dot/commands/setup/setup.fish
Normal file
@@ -0,0 +1,35 @@
|
||||
function _dot_setup_usage
|
||||
echo "usage: dot setup [<task>]
|
||||
|
||||
Tasks:
|
||||
folders bring the 8 standard XDG user directories under the short-name convention
|
||||
help show this message
|
||||
|
||||
Run 'dot setup <task> help' for details on a specific task.
|
||||
|
||||
With no task given, runs every setup task."
|
||||
end
|
||||
|
||||
function _dot_setup
|
||||
if test "$argv[1]" = help
|
||||
_dot_setup_usage
|
||||
return 0
|
||||
end
|
||||
|
||||
set -l helper_dir (status dirname)
|
||||
source $helper_dir/folders.fish
|
||||
|
||||
if test -z "$argv[1]"
|
||||
_dot_setup_folders
|
||||
return $status
|
||||
end
|
||||
|
||||
switch $argv[1]
|
||||
case folders
|
||||
_dot_setup_folders $argv[2..-1]
|
||||
return $status
|
||||
case '*'
|
||||
_dot_setup_usage
|
||||
return 1
|
||||
end
|
||||
end
|
||||
@@ -568,3 +568,360 @@ set -l complete_output (python3 $HOME/.config/dot/commands/kde/kde.py complete)
|
||||
# --- dot help / dot help discovers dot kde ---
|
||||
set -l help_with_kde (dot help)
|
||||
@test "dot help lists the kde subcommand" (string match -q '*kde*' -- $help_with_kde; echo $status) -eq 0
|
||||
|
||||
# --- dot setup folders ---
|
||||
# The legacy->short-name mapping is fixed in the command itself, not read
|
||||
# from ~/.config/user-dirs.dirs (a separate, manually tracked dotfile this
|
||||
# command never reads or writes), so no scenario below needs to seed one.
|
||||
|
||||
# xdg-user-dirs-update is faked out via a PATH-prepended bin that logs each
|
||||
# invocation, exactly mirroring dot install's fake sudo/pacman.
|
||||
set -l fake_bin_xdg (mktemp -d)
|
||||
echo '#!/bin/sh
|
||||
echo "$@" >>"$XDG_UPDATE_LOG"
|
||||
exit 0' >$fake_bin_xdg/xdg-user-dirs-update
|
||||
chmod +x $fake_bin_xdg/xdg-user-dirs-update
|
||||
set -gx PATH $fake_bin_xdg $PATH
|
||||
|
||||
# --- a fresh migration: all 8 legacy folders present and empty, including a
|
||||
# nested empty Pictures/Screenshots ---
|
||||
set -gx HOME (mktemp -d)
|
||||
dot init --url $remote >/dev/null 2>&1
|
||||
mkdir -p $HOME/.config/dot/commands/setup
|
||||
cp $commands_dir/setup/setup.fish $HOME/.config/dot/commands/setup/setup.fish
|
||||
cp $commands_dir/setup/folders.fish $HOME/.config/dot/commands/setup/folders.fish
|
||||
mkdir -p $HOME/Desktop $HOME/Documents $HOME/Downloads $HOME/Music $HOME/Pictures/Screenshots $HOME/Videos $HOME/Templates $HOME/Public
|
||||
set -gx XDG_UPDATE_LOG (mktemp)
|
||||
|
||||
dot setup folders >/dev/null 2>&1
|
||||
set -l fresh_folders_status $status
|
||||
|
||||
@test "dot setup folders succeeds on a fresh scratch HOME" $fresh_folders_status -eq 0
|
||||
@test "Desktop is renamed to .desktop" -d $HOME/.desktop
|
||||
@test "Documents is renamed to doc" -d $HOME/doc
|
||||
@test "Downloads is renamed to dwn" -d $HOME/dwn
|
||||
@test "Music is renamed to mus" -d $HOME/mus
|
||||
@test "Pictures is renamed to pic" -d $HOME/pic
|
||||
@test "Videos is renamed to vid" -d $HOME/vid
|
||||
@test "Templates and Public both merge into .ignoreme" -d $HOME/.ignoreme
|
||||
@test "the nested Screenshots folder is renamed to pic/screenshots" -d $HOME/pic/screenshots
|
||||
@test "the legacy Desktop folder no longer exists" (test -e $HOME/Desktop; and echo yes; or echo no) = no
|
||||
@test "the legacy Documents folder no longer exists" (test -e $HOME/Documents; and echo yes; or echo no) = no
|
||||
@test "the legacy Pictures folder no longer exists" (test -e $HOME/Pictures; and echo yes; or echo no) = no
|
||||
@test "xdg-user-dirs-update is invoked exactly once" (cat $XDG_UPDATE_LOG | count) -eq 1
|
||||
|
||||
# --- re-running after a clean migration is a no-op ---
|
||||
dot setup folders >/dev/null 2>&1
|
||||
set -l rerun_status $status
|
||||
|
||||
@test "re-running dot setup folders succeeds" $rerun_status -eq 0
|
||||
@test "re-running leaves the short-named folders in place" -d $HOME/pic/screenshots
|
||||
@test "re-running does not recreate any legacy folder" (test -e $HOME/Pictures; and echo yes; or echo no) = no
|
||||
|
||||
# --- the short-name mapping is fixed regardless of what (if anything)
|
||||
# ~/.config/user-dirs.dirs declares -- this is the exact real-world bug
|
||||
# that motivated dropping the dependency: a stale, never-updated
|
||||
# user-dirs.dirs (still pointing XDG_DOCUMENTS_DIR at ~/Documents itself)
|
||||
# must not make the target collide with the legacy folder ---
|
||||
set -gx HOME (mktemp -d)
|
||||
dot init --url $remote >/dev/null 2>&1
|
||||
mkdir -p $HOME/.config/dot/commands/setup
|
||||
cp $commands_dir/setup/setup.fish $HOME/.config/dot/commands/setup/setup.fish
|
||||
cp $commands_dir/setup/folders.fish $HOME/.config/dot/commands/setup/folders.fish
|
||||
mkdir -p $HOME/.config
|
||||
echo 'XDG_DESKTOP_DIR="$HOME/Desktop"
|
||||
XDG_DOWNLOAD_DIR="$HOME/Downloads"
|
||||
XDG_TEMPLATES_DIR="$HOME/"
|
||||
XDG_PUBLICSHARE_DIR="$HOME/"
|
||||
XDG_DOCUMENTS_DIR="$HOME/Documents"
|
||||
XDG_MUSIC_DIR="$HOME/"
|
||||
XDG_PICTURES_DIR="$HOME/Pictures"
|
||||
XDG_VIDEOS_DIR="$HOME/Videos"' >$HOME/.config/user-dirs.dirs
|
||||
mkdir -p $HOME/Documents
|
||||
echo real-content >$HOME/Documents/report.txt
|
||||
set -gx XDG_UPDATE_LOG (mktemp)
|
||||
|
||||
dot setup folders >/dev/null 2>&1
|
||||
|
||||
@test "a stale user-dirs.dirs pointing at the legacy folder itself doesn't confuse the migration" (cat $HOME/doc/report.txt) = real-content
|
||||
@test "the legacy folder is still removed despite the stale user-dirs.dirs" (test -e $HOME/Documents; and echo yes; or echo no) = no
|
||||
@test "the stale user-dirs.dirs file itself is left byte-for-byte untouched" (string match -q '*XDG_DOCUMENTS_DIR="$HOME/Documents"*' -- (cat $HOME/.config/user-dirs.dirs); echo $status) -eq 0
|
||||
|
||||
# --- dot setup folders works even when user-dirs.dirs doesn't exist at all ---
|
||||
set -gx HOME (mktemp -d)
|
||||
dot init --url $remote >/dev/null 2>&1
|
||||
mkdir -p $HOME/.config/dot/commands/setup
|
||||
cp $commands_dir/setup/setup.fish $HOME/.config/dot/commands/setup/setup.fish
|
||||
cp $commands_dir/setup/folders.fish $HOME/.config/dot/commands/setup/folders.fish
|
||||
mkdir -p $HOME/Documents
|
||||
echo real-content >$HOME/Documents/report.txt
|
||||
set -gx XDG_UPDATE_LOG (mktemp)
|
||||
|
||||
set -l no_user_dirs_status
|
||||
dot setup folders >/dev/null 2>&1
|
||||
set no_user_dirs_status $status
|
||||
|
||||
@test "dot setup folders succeeds with no user-dirs.dirs present at all" $no_user_dirs_status -eq 0
|
||||
@test "migration still happens with no user-dirs.dirs present at all" (cat $HOME/doc/report.txt) = real-content
|
||||
@test "no user-dirs.dirs is created as a side effect" (test -e $HOME/.config/user-dirs.dirs; and echo yes; or echo no) = no
|
||||
|
||||
# --- bare `dot setup` (no task given) runs folders as part of running everything ---
|
||||
set -gx HOME (mktemp -d)
|
||||
dot init --url $remote >/dev/null 2>&1
|
||||
mkdir -p $HOME/.config/dot/commands/setup
|
||||
cp $commands_dir/setup/setup.fish $HOME/.config/dot/commands/setup/setup.fish
|
||||
cp $commands_dir/setup/folders.fish $HOME/.config/dot/commands/setup/folders.fish
|
||||
mkdir -p $HOME/Desktop $HOME/Documents $HOME/Downloads $HOME/Music $HOME/Pictures $HOME/Videos $HOME/Templates $HOME/Public
|
||||
set -gx XDG_UPDATE_LOG (mktemp)
|
||||
|
||||
dot setup >/dev/null 2>&1
|
||||
set -l bare_setup_status $status
|
||||
|
||||
@test "bare dot setup succeeds" $bare_setup_status -eq 0
|
||||
@test "bare dot setup runs the folders task" -d $HOME/.desktop
|
||||
@test "bare dot setup also merges Pictures into pic" -d $HOME/pic
|
||||
|
||||
# --- a non-empty legacy folder merges unconditionally, no flag needed --
|
||||
# an unrelated empty legacy folder migrates in the same run ---
|
||||
set -gx HOME (mktemp -d)
|
||||
dot init --url $remote >/dev/null 2>&1
|
||||
mkdir -p $HOME/.config/dot/commands/setup
|
||||
cp $commands_dir/setup/setup.fish $HOME/.config/dot/commands/setup/setup.fish
|
||||
cp $commands_dir/setup/folders.fish $HOME/.config/dot/commands/setup/folders.fish
|
||||
mkdir -p $HOME/Documents $HOME/Desktop
|
||||
echo real-content >$HOME/Documents/report.txt
|
||||
set -gx XDG_UPDATE_LOG (mktemp)
|
||||
|
||||
set -l nonempty_output (dot setup folders 2>&1)
|
||||
set -l nonempty_status $status
|
||||
|
||||
@test "dot setup folders succeeds when a legacy folder has content" $nonempty_status -eq 0
|
||||
@test "a non-empty legacy folder's content is migrated by default" (cat $HOME/doc/report.txt) = real-content
|
||||
@test "the now-empty legacy folder is removed" (test -e $HOME/Documents; and echo yes; or echo no) = no
|
||||
@test "prints a message about what was moved" (string match -q '*Documents*' -- $nonempty_output; echo $status) -eq 0
|
||||
@test "an unrelated empty legacy folder still migrates in the same run" (test -e $HOME/Desktop; and echo yes; or echo no) = no
|
||||
|
||||
# --- a legacy folder containing only a stray dotfile still migrates by
|
||||
# default -- there's no separate empty-vs-non-empty gate to trip ---
|
||||
set -gx HOME (mktemp -d)
|
||||
dot init --url $remote >/dev/null 2>&1
|
||||
mkdir -p $HOME/.config/dot/commands/setup
|
||||
cp $commands_dir/setup/setup.fish $HOME/.config/dot/commands/setup/setup.fish
|
||||
cp $commands_dir/setup/folders.fish $HOME/.config/dot/commands/setup/folders.fish
|
||||
mkdir -p $HOME/Downloads
|
||||
touch $HOME/Downloads/.directory
|
||||
set -gx XDG_UPDATE_LOG (mktemp)
|
||||
|
||||
dot setup folders >/dev/null 2>&1
|
||||
|
||||
@test "a legacy folder holding only a stray dotfile is migrated by default" -e $HOME/dwn/.directory
|
||||
@test "the legacy folder holding only a stray dotfile is removed" (test -e $HOME/Downloads; and echo yes; or echo no) = no
|
||||
|
||||
# --- a nested empty Screenshots folder migrates alongside unrelated real
|
||||
# content in the same Pictures folder, all in the same default run ---
|
||||
set -gx HOME (mktemp -d)
|
||||
dot init --url $remote >/dev/null 2>&1
|
||||
mkdir -p $HOME/.config/dot/commands/setup
|
||||
cp $commands_dir/setup/setup.fish $HOME/.config/dot/commands/setup/setup.fish
|
||||
cp $commands_dir/setup/folders.fish $HOME/.config/dot/commands/setup/folders.fish
|
||||
mkdir -p $HOME/Pictures/Screenshots
|
||||
echo vacation-photo >$HOME/Pictures/vacation.jpg
|
||||
set -gx XDG_UPDATE_LOG (mktemp)
|
||||
|
||||
dot setup folders >/dev/null 2>&1
|
||||
set -l pictures_with_content_status $status
|
||||
|
||||
@test "dot setup folders succeeds when Pictures has unrelated content" $pictures_with_content_status -eq 0
|
||||
@test "the unrelated file in Pictures is migrated into pic" (cat $HOME/pic/vacation.jpg) = vacation-photo
|
||||
@test "the nested Screenshots folder is renamed to pic/screenshots" -d $HOME/pic/screenshots
|
||||
@test "the now-empty Pictures folder is removed" (test -e $HOME/Pictures; and echo yes; or echo no) = no
|
||||
|
||||
# --- a Screenshots folder that itself holds real content migrates by
|
||||
# default too, renamed to pic/screenshots, even when the rest of
|
||||
# Pictures is empty ---
|
||||
set -gx HOME (mktemp -d)
|
||||
dot init --url $remote >/dev/null 2>&1
|
||||
mkdir -p $HOME/.config/dot/commands/setup
|
||||
cp $commands_dir/setup/setup.fish $HOME/.config/dot/commands/setup/setup.fish
|
||||
cp $commands_dir/setup/folders.fish $HOME/.config/dot/commands/setup/folders.fish
|
||||
mkdir -p $HOME/Pictures/Screenshots
|
||||
echo shot-content >$HOME/Pictures/Screenshots/shot.png
|
||||
set -gx XDG_UPDATE_LOG (mktemp)
|
||||
|
||||
dot setup folders >/dev/null 2>&1
|
||||
|
||||
@test "a non-empty Screenshots folder migrates by default, renamed to pic/screenshots" (cat $HOME/pic/screenshots/shot.png) = shot-content
|
||||
@test "the now-empty Pictures folder is removed after migrating Screenshots" (test -e $HOME/Pictures; and echo yes; or echo no) = no
|
||||
|
||||
# --- a filename collision between a legacy folder and its already-populated
|
||||
# short-named target is skipped (not overwritten), reported, and leaves
|
||||
# the legacy folder in place -- even when another non-colliding file in
|
||||
# the same folder is merged successfully ---
|
||||
set -gx HOME (mktemp -d)
|
||||
dot init --url $remote >/dev/null 2>&1
|
||||
mkdir -p $HOME/.config/dot/commands/setup
|
||||
cp $commands_dir/setup/setup.fish $HOME/.config/dot/commands/setup/setup.fish
|
||||
cp $commands_dir/setup/folders.fish $HOME/.config/dot/commands/setup/folders.fish
|
||||
mkdir -p $HOME/Documents $HOME/doc
|
||||
echo legacy-content >$HOME/Documents/report.txt
|
||||
echo legacy-only >$HOME/Documents/notes.txt
|
||||
echo target-content >$HOME/doc/report.txt
|
||||
set -gx XDG_UPDATE_LOG (mktemp)
|
||||
|
||||
set -l collision_output (dot setup folders 2>&1)
|
||||
set -l collision_status $status
|
||||
|
||||
@test "dot setup folders still succeeds when a collision occurs" $collision_status -eq 0
|
||||
@test "the colliding target file is preserved byte-for-byte" (cat $HOME/doc/report.txt) = target-content
|
||||
@test "the colliding legacy file is left in place, untouched" (cat $HOME/Documents/report.txt) = legacy-content
|
||||
@test "the collision is reported" (string match -q '*report.txt*' -- $collision_output; echo $status) -eq 0
|
||||
@test "the legacy Documents folder is left in place due to the collision" -d $HOME/Documents
|
||||
@test "a non-colliding file in the same folder is still merged" (cat $HOME/doc/notes.txt) = legacy-only
|
||||
@test "the merged non-colliding file no longer sits in the legacy folder" (test -e $HOME/Documents/notes.txt; and echo yes; or echo no) = no
|
||||
|
||||
# --- re-running after a collision was reported: the skipped file isn't
|
||||
# lost, and the already-migrated file isn't moved again ---
|
||||
dot setup folders >/dev/null 2>&1
|
||||
|
||||
@test "re-running after a collision still preserves the target file" (cat $HOME/doc/report.txt) = target-content
|
||||
@test "re-running after a collision still leaves the legacy file in place" (cat $HOME/Documents/report.txt) = legacy-content
|
||||
@test "re-running after a collision does not resurrect the already-migrated file in the legacy folder" (test -e $HOME/Documents/notes.txt; and echo yes; or echo no) = no
|
||||
|
||||
# --- a collision on the nested Screenshots unit is skipped, reported, and
|
||||
# leaves Pictures in place, even though Pictures also holds other
|
||||
# content unrelated to the collision ---
|
||||
set -gx HOME (mktemp -d)
|
||||
dot init --url $remote >/dev/null 2>&1
|
||||
mkdir -p $HOME/.config/dot/commands/setup
|
||||
cp $commands_dir/setup/setup.fish $HOME/.config/dot/commands/setup/setup.fish
|
||||
cp $commands_dir/setup/folders.fish $HOME/.config/dot/commands/setup/folders.fish
|
||||
mkdir -p $HOME/Pictures/Screenshots $HOME/pic/screenshots
|
||||
echo legacy-shot >$HOME/Pictures/Screenshots/shot.png
|
||||
echo target-shot >$HOME/pic/screenshots/shot.png
|
||||
set -gx XDG_UPDATE_LOG (mktemp)
|
||||
|
||||
set -l screenshots_collision_output (dot setup folders 2>&1)
|
||||
|
||||
@test "a Screenshots collision preserves the existing target screenshot" (cat $HOME/pic/screenshots/shot.png) = target-shot
|
||||
@test "a Screenshots collision leaves the legacy Screenshots folder in place" (cat $HOME/Pictures/Screenshots/shot.png) = legacy-shot
|
||||
@test "the Screenshots collision is reported" (string match -q '*Screenshots*' -- $screenshots_collision_output; echo $status) -eq 0
|
||||
@test "Pictures itself is left in place due to the Screenshots collision" -d $HOME/Pictures
|
||||
|
||||
# --- the same Screenshots-collision handling also holds when Pictures has
|
||||
# nothing else in it besides the colliding Screenshots folder ---
|
||||
set -gx HOME (mktemp -d)
|
||||
dot init --url $remote >/dev/null 2>&1
|
||||
mkdir -p $HOME/.config/dot/commands/setup
|
||||
cp $commands_dir/setup/setup.fish $HOME/.config/dot/commands/setup/setup.fish
|
||||
cp $commands_dir/setup/folders.fish $HOME/.config/dot/commands/setup/folders.fish
|
||||
mkdir -p $HOME/Pictures/Screenshots $HOME/pic/screenshots
|
||||
echo target-shot >$HOME/pic/screenshots/shot.png
|
||||
set -gx XDG_UPDATE_LOG (mktemp)
|
||||
|
||||
set -l bare_screenshots_collision_output (dot setup folders 2>&1)
|
||||
set -l bare_screenshots_collision_status $status
|
||||
|
||||
@test "a Screenshots-only collision still succeeds" $bare_screenshots_collision_status -eq 0
|
||||
@test "a Screenshots-only collision preserves the existing target screenshot" (cat $HOME/pic/screenshots/shot.png) = target-shot
|
||||
@test "a Screenshots-only collision leaves the empty legacy Screenshots folder in place" -d $HOME/Pictures/Screenshots
|
||||
@test "a Screenshots-only collision leaves Pictures itself in place" -d $HOME/Pictures
|
||||
@test "the Screenshots-only collision is reported" (string match -q '*Screenshots*' -- $bare_screenshots_collision_output; echo $status) -eq 0
|
||||
|
||||
# --- --dry-run reports what would move/skip without touching the
|
||||
# filesystem: no mkdir, no mv/rmdir, no xdg-user-dirs-update ---
|
||||
set -gx HOME (mktemp -d)
|
||||
dot init --url $remote >/dev/null 2>&1
|
||||
mkdir -p $HOME/.config/dot/commands/setup
|
||||
cp $commands_dir/setup/setup.fish $HOME/.config/dot/commands/setup/setup.fish
|
||||
cp $commands_dir/setup/folders.fish $HOME/.config/dot/commands/setup/folders.fish
|
||||
mkdir -p $HOME/Documents $HOME/Pictures/Screenshots
|
||||
echo real-content >$HOME/Documents/report.txt
|
||||
set -gx XDG_UPDATE_LOG (mktemp)
|
||||
|
||||
set -l dryrun_output (dot setup folders --dry-run 2>&1)
|
||||
set -l dryrun_status $status
|
||||
|
||||
@test "dot setup folders --dry-run succeeds" $dryrun_status -eq 0
|
||||
@test "--dry-run reports the entry it would move" (string match -q '*Documents*' -- $dryrun_output; echo $status) -eq 0
|
||||
@test "--dry-run reports the Screenshots folder it would move" (string match -q '*Screenshots*' -- $dryrun_output; echo $status) -eq 0
|
||||
@test "--dry-run leaves the legacy Documents folder's content untouched" (cat $HOME/Documents/report.txt) = real-content
|
||||
@test "--dry-run does not remove the legacy Documents folder" -d $HOME/Documents
|
||||
@test "--dry-run does not create the short-named target folder" (test -e $HOME/doc; and echo yes; or echo no) = no
|
||||
@test "--dry-run does not rename the nested Screenshots folder" -d $HOME/Pictures/Screenshots
|
||||
@test "--dry-run never invokes xdg-user-dirs-update" (test -s $XDG_UPDATE_LOG; and echo yes; or echo no) = no
|
||||
|
||||
# --- --dry-run also reports a would-be collision without touching
|
||||
# either side, and doesn't move the non-colliding entry either ---
|
||||
set -gx HOME (mktemp -d)
|
||||
dot init --url $remote >/dev/null 2>&1
|
||||
mkdir -p $HOME/.config/dot/commands/setup
|
||||
cp $commands_dir/setup/setup.fish $HOME/.config/dot/commands/setup/setup.fish
|
||||
cp $commands_dir/setup/folders.fish $HOME/.config/dot/commands/setup/folders.fish
|
||||
mkdir -p $HOME/Documents $HOME/doc
|
||||
echo legacy-content >$HOME/Documents/report.txt
|
||||
echo legacy-only >$HOME/Documents/notes.txt
|
||||
echo target-content >$HOME/doc/report.txt
|
||||
set -gx XDG_UPDATE_LOG (mktemp)
|
||||
|
||||
set -l dryrun_collision_output (dot setup folders --dry-run 2>&1)
|
||||
|
||||
@test "--dry-run reports the would-be collision" (string match -q '*report.txt*' -- $dryrun_collision_output; echo $status) -eq 0
|
||||
@test "--dry-run leaves the colliding target file untouched" (cat $HOME/doc/report.txt) = target-content
|
||||
@test "--dry-run leaves the colliding legacy file untouched" (cat $HOME/Documents/report.txt) = legacy-content
|
||||
@test "--dry-run does not move the non-colliding file either" -e $HOME/Documents/notes.txt
|
||||
|
||||
# --- a legacy folder with nothing to move produces no --dry-run output ---
|
||||
set -gx HOME (mktemp -d)
|
||||
dot init --url $remote >/dev/null 2>&1
|
||||
mkdir -p $HOME/.config/dot/commands/setup
|
||||
cp $commands_dir/setup/setup.fish $HOME/.config/dot/commands/setup/setup.fish
|
||||
cp $commands_dir/setup/folders.fish $HOME/.config/dot/commands/setup/folders.fish
|
||||
mkdir -p $HOME/Desktop
|
||||
set -gx XDG_UPDATE_LOG (mktemp)
|
||||
|
||||
set -l dryrun_empty_output (dot setup folders --dry-run 2>&1)
|
||||
|
||||
@test "--dry-run is silent for a legacy folder with nothing to move" -z "$dryrun_empty_output"
|
||||
@test "--dry-run leaves an empty legacy folder in place" -d $HOME/Desktop
|
||||
|
||||
# --- the removed --yes flag now fails fast as an unknown option ---
|
||||
set -gx HOME (mktemp -d)
|
||||
dot init --url $remote >/dev/null 2>&1
|
||||
mkdir -p $HOME/.config/dot/commands/setup
|
||||
cp $commands_dir/setup/setup.fish $HOME/.config/dot/commands/setup/setup.fish
|
||||
cp $commands_dir/setup/folders.fish $HOME/.config/dot/commands/setup/folders.fish
|
||||
set -gx XDG_UPDATE_LOG (mktemp)
|
||||
|
||||
dot setup folders --yes >/dev/null 2>&1
|
||||
set -l old_yes_status $status
|
||||
|
||||
@test "dot setup folders --yes now fails as an unknown option" $old_yes_status -ne 0
|
||||
|
||||
# --- help prints usage and makes no filesystem changes ---
|
||||
set -gx HOME (mktemp -d)
|
||||
dot init --url $remote >/dev/null 2>&1
|
||||
mkdir -p $HOME/.config/dot/commands/setup
|
||||
cp $commands_dir/setup/setup.fish $HOME/.config/dot/commands/setup/setup.fish
|
||||
cp $commands_dir/setup/folders.fish $HOME/.config/dot/commands/setup/folders.fish
|
||||
mkdir -p $HOME/Documents $HOME/Desktop
|
||||
set -gx XDG_UPDATE_LOG (mktemp)
|
||||
|
||||
set -l setup_help_output (dot setup help)
|
||||
set -l setup_help_status $status
|
||||
set -l folders_help_output (dot setup folders help)
|
||||
set -l folders_help_status $status
|
||||
set -l xdg_called_for_help (test -s $XDG_UPDATE_LOG; and echo yes; or echo no)
|
||||
|
||||
@test "dot setup help succeeds" $setup_help_status -eq 0
|
||||
@test "dot setup help mentions folders" (string match -q '*folders*' -- $setup_help_output; echo $status) -eq 0
|
||||
@test "dot setup folders help succeeds" $folders_help_status -eq 0
|
||||
@test "dot setup folders help mentions the short-name convention" (string match -q '*.desktop*' -- $folders_help_output; echo $status) -eq 0
|
||||
@test "dot setup folders help documents --dry-run" (string match -q '*--dry-run*' -- $folders_help_output; echo $status) -eq 0
|
||||
@test "neither help invocation ever calls xdg-user-dirs-update" $xdg_called_for_help = no
|
||||
@test "dot setup help leaves the legacy Documents folder untouched" -d $HOME/Documents
|
||||
@test "dot setup folders help leaves the legacy Desktop folder untouched" -d $HOME/Desktop
|
||||
@test "help does not create any short-named target folder" (test -e $HOME/doc; and echo yes; or echo no) = no
|
||||
|
||||
# --- dot help discovers dot setup ---
|
||||
set -l help_with_setup (dot help)
|
||||
@test "dot help lists the setup subcommand" (string match -q '*setup*' -- $help_with_setup; echo $status) -eq 0
|
||||
|
||||
Reference in New Issue
Block a user