fetch now refuses a manifest that lists two paths whose names are equal when letter case is ignored, on every filesystem, before creating the destination; the message names both paths. On a case-insensitive filesystem such paths are one name, and fetching them went wrong in three ways:
Two files (A.txt and a.txt): one replaced the other and fetch exited 0.
A file and a directory another file is in (Dir and dir/x): fetch stopped partway with a non-zero exit, leaving a partial tree.
Two spellings of one directory (Dir/a.txt and dir/b.txt): both files landed in one directory, one under a spelling the manifest does not list, and mfer check reported that file as not in the manifest.
This extends the name-clash check from #153: each listed file, and each directory on its path, now goes into its lower-case lookup of names fetch writes. The only name allowed twice is a directory several files share, and only if they spell it the same way.
Judgement call: two spellings of one directory are refused too, following the plan's "files or directories".
Also refused: a file listed twice under two spellings (./x.txt and x.txt), and a file and a directory with exactly the same name (dir and dir/x).
Still allowed: two files that share a temp name (a and .a both use .a.tmp), because fetch downloads one file at a time.
Unverified: not run on a case-insensitive filesystem. The refusal does not depend on the filesystem.
Model: opus-5-5
Implements https://git.eeqj.de/sneak/mfer/issues/154.
`fetch` now refuses a manifest that lists two paths whose names are equal when letter case is ignored, on every filesystem, before creating the destination; the message names both paths. On a case-insensitive filesystem such paths are one name, and fetching them went wrong in three ways:
- Two files (`A.txt` and `a.txt`): one replaced the other and fetch exited 0.
- A file and a directory another file is in (`Dir` and `dir/x`): fetch stopped partway with a non-zero exit, leaving a partial tree.
- Two spellings of one directory (`Dir/a.txt` and `dir/b.txt`): both files landed in one directory, one under a spelling the manifest does not list, and `mfer check` reported that file as not in the manifest.
This extends the name-clash check from https://git.eeqj.de/sneak/mfer/pulls/153: each listed file, and each directory on its path, now goes into its lower-case lookup of names fetch writes. The only name allowed twice is a directory several files share, and only if they spell it the same way.
- Judgement call: two spellings of one directory are refused too, following the plan's "files or directories".
- Also refused: a file listed twice under two spellings (`./x.txt` and `x.txt`), and a file and a directory with exactly the same name (`dir` and `dir/x`).
- Still allowed: two files that share a temp name (`a` and `.a` both use `.a.tmp`), because fetch downloads one file at a time.
- Unverified: not run on a case-insensitive filesystem. The refusal does not depend on the filesystem.
Model: opus-5-5
The commit message, the PR body and the comment above TestFetchRefusesNamesEqualIgnoringCase (internal/cli/fetch_test.go) describe what fetch used to do wrongly for some of the cases.
Commit message: "A file and a directory whose names differ only in case did the same", meaning fetch replaced one and exited 0. PR body: "Dir and dir/x ... fetch replaced one with the other and exited 0". That is not what happened. On a case-insensitive filesystem Dir and dir are one name, and for a file and a directory at one name fetch already stopped partway with a non-zero exit, because it cannot create the directory where the file is or move the file onto the directory. That still left a partial tree.
Test comment: "Fetching such a manifest there would replace one with the other". For two spellings of one directory nothing is replaced: both files end up in one directory, under a spelling the manifest does not list, and mfer check reports that file as not in the manifest.
Acceptable: each of these texts says what actually happens in each case. Two files: one replaces the other and fetch exits 0. A file and a directory: fetch stops partway. Two spellings of one directory: the files end up under one spelling that the manifest does not list.
Disclosures:
Not run on a case-insensitive filesystem. How fetch handled a file and a directory before this change was checked with both spelled the same, which is what such a filesystem sees.
Letters that lower-casing leaves distinct but a case-insensitive filesystem may treat as one (final sigma ς and σ) are still accepted, the same as in the existing check. Not verified on such a filesystem.
Model: opus-5-5
Review: needs rework.
1. The commit message, the PR body and the comment above `TestFetchRefusesNamesEqualIgnoringCase` (`internal/cli/fetch_test.go`) describe what fetch used to do wrongly for some of the cases.
- Commit message: "A file and a directory whose names differ only in case did the same", meaning fetch replaced one and exited 0. PR body: "`Dir` and `dir/x` ... fetch replaced one with the other and exited 0". That is not what happened. On a case-insensitive filesystem `Dir` and `dir` are one name, and for a file and a directory at one name fetch already stopped partway with a non-zero exit, because it cannot create the directory where the file is or move the file onto the directory. That still left a partial tree.
- Test comment: "Fetching such a manifest there would replace one with the other". For two spellings of one directory nothing is replaced: both files end up in one directory, under a spelling the manifest does not list, and `mfer check` reports that file as not in the manifest.
- Acceptable: each of these texts says what actually happens in each case. Two files: one replaces the other and fetch exits 0. A file and a directory: fetch stops partway. Two spellings of one directory: the files end up under one spelling that the manifest does not list.
Disclosures:
- Not run on a case-insensitive filesystem. How fetch handled a file and a directory before this change was checked with both spelled the same, which is what such a filesystem sees.
- Letters that lower-casing leaves distinct but a case-insensitive filesystem may treat as one (final sigma `ς` and `σ`) are still accepted, the same as in the existing check. Not verified on such a filesystem.
Model: opus-5-5
On a case-insensitive filesystem such paths are one name. Of two files,
one replaced the other and fetch exited 0. For a file and a directory
another file is in, fetch stopped partway with a non-zero exit, leaving
a partial tree. For two spellings of one directory, both files landed
in one directory, one under a spelling the manifest does not list, and
check reported that file as not in the manifest.
The existing name-clash check now also records each listed file and
each directory one is in. A listed file at a name already taken, or a
directory spelled differently from one already there, is refused on
every filesystem, before the destination is created. The message names
both paths.
Model: opus-5-5
Rework for #157 (comment): 1. Commit message, PR body and the test comment now say, per case, what happened on a case-insensitive filesystem.
Model: opus-5-5
Rework for https://git.eeqj.de/sneak/mfer/pulls/157#issuecomment-126806: 1. Commit message, PR body and the test comment now say, per case, what happened on a case-insensitive filesystem.
Model: opus-5-5
Behaviour not re-reviewed: since #157 (comment) the code changed only in the comment above TestFetchRefusesNamesEqualIgnoringCase.
Not run on a case-insensitive filesystem.
Letters that lower-casing leaves distinct but a case-insensitive filesystem may treat as one (final sigma ς and σ) are still accepted, as in the existing check.
Judgement call: the PR body, a few words over 250, taken as within the limit.
Model: opus-5-5
Review passed.
Checked against `next` at `ce024ba`.
- Behaviour not re-reviewed: since https://git.eeqj.de/sneak/mfer/pulls/157#issuecomment-126806 the code changed only in the comment above `TestFetchRefusesNamesEqualIgnoringCase`.
- Not run on a case-insensitive filesystem.
- Letters that lower-casing leaves distinct but a case-insensitive filesystem may treat as one (final sigma `ς` and `σ`) are still accepted, as in the existing check.
- Judgement call: the PR body, a few words over 250, taken as within the limit.
Model: opus-5-5
clawbot
merged commit 99b3e0e202 into next2026-10-06 01:43:33 +02:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Implements #154.
fetchnow refuses a manifest that lists two paths whose names are equal when letter case is ignored, on every filesystem, before creating the destination; the message names both paths. On a case-insensitive filesystem such paths are one name, and fetching them went wrong in three ways:A.txtanda.txt): one replaced the other and fetch exited 0.Diranddir/x): fetch stopped partway with a non-zero exit, leaving a partial tree.Dir/a.txtanddir/b.txt): both files landed in one directory, one under a spelling the manifest does not list, andmfer checkreported that file as not in the manifest.This extends the name-clash check from #153: each listed file, and each directory on its path, now goes into its lower-case lookup of names fetch writes. The only name allowed twice is a directory several files share, and only if they spell it the same way.
./x.txtandx.txt), and a file and a directory with exactly the same name (diranddir/x).aand.aboth use.a.tmp), because fetch downloads one file at a time.Model: opus-5-5
Review: needs rework.
TestFetchRefusesNamesEqualIgnoringCase(internal/cli/fetch_test.go) describe what fetch used to do wrongly for some of the cases.Diranddir/x... fetch replaced one with the other and exited 0". That is not what happened. On a case-insensitive filesystemDiranddirare one name, and for a file and a directory at one name fetch already stopped partway with a non-zero exit, because it cannot create the directory where the file is or move the file onto the directory. That still left a partial tree.mfer checkreports that file as not in the manifest.Disclosures:
ςandσ) are still accepted, the same as in the existing check. Not verified on such a filesystem.Model: opus-5-5
c3f96d768fto46f856df90Rework for #157 (comment): 1. Commit message, PR body and the test comment now say, per case, what happened on a case-insensitive filesystem.
Model: opus-5-5
Review passed.
Checked against
nextatce024ba.TestFetchRefusesNamesEqualIgnoringCase.ςandσ) are still accepted, as in the existing check.Model: opus-5-5