Follow-up to the independent review of this branch.
- A folder whose name ends in a space was checked under one name and opened
under another, so a link behind it could still carry a delete out of the
working directory. WorkingTree.Resolve now refuses any part that Windows
does not open literally (empty, trailing dot or space, a colon), and the
recovery file's stored paths must also pass the path validator.
- A link is recognized by having a target, not by the reparse-point
attribute: folders under a cloud-sync root carry that attribute without
being links, and recovery refused to write into them.
- Cleanup of a failed clone moved to WorkingTree.DeleteDirectory, which
removes a link inside the folder as a link and never enters it; it is
tested, where the previous change to that cleanup was not.
- The destination's old content is removed whatever it is: a file, a hard
link, a file link, a folder link. Only the name in the working tree goes.
- The git-folder rule is the one git has: .git and GIT~1 (with trailing
dots, spaces or a stream suffix). git~2 and up are ordinary names again.
The rule now runs before the trailing-dot rule, whose suggestion for
".git." was ".git" itself; every suggestion re-validates clean.
- Shared parent folders are checked for links once per materialization.
- A bare repository with a recovery file gets a clear message.
- Tests remove the junctions they create, and a hard-link test replaces
reliance on the symlink test that needs a privilege.
Refs #141
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Signed-off-by: James Maes <james@kof22.com>
Path recovery materializes the working tree itself instead of using a git
checkout, and it was less careful than one: the list of previously written
files in .git\gclo-recovery.json decided what to delete without being
checked, a path segment named .git was valid, writes followed links, and
cleanup of a failed clone followed directory links.
- New internal WorkingTree is the only way the recovery writes or deletes
a file. The target must resolve inside the working directory, must not
be in a .git folder (in any spelling Windows opens as that folder: letter
case, the GIT~1 short name, trailing dots and spaces, a stream suffix),
and must not be reached through a link. An existing file is removed and
created anew, never written through.
- The recovery file's stored paths are validated when it is loaded. A file
that lists a path outside the working tree fails the row with a message
that says how to rebuild it; nothing is deleted.
- WindowsPathValidator treats .git and its aliases as an invalid segment,
with a suggested replacement, so a tree entry or a rename can no longer
land in git's own folder.
- Cleanup of a failed clone skips links when clearing attributes.
Threat model: T3 and T4 updated.
Closes#141
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Signed-off-by: James Maes <james@kof22.com>