Repository navigation
adopt-project.py: execute unsets the leg clone's remote.origin.url before git filter-repo, so under a Latin-1 locale a source under a directory named with the byte 0xE9 is extracted, where filter-repo died printing that url as U+FFFD, and every branch of the source is still rewritten as before (#1247) - #1251
Conversation
…` before `git filter-repo`, so under a Latin-1 locale a source under a directory named with the byte 0xE9 is extracted, where filter-repo died printing that url as U+FFFD, and every branch of the source is still rewritten as before (#1247) `_extract_leg` clones the source, and the clone's `remote.origin.url` is the source's path, byte for byte. `git filter-repo` prints that url as it removes `origin` (`NOTICE: Removing 'origin' remote ... (was <url>)`), decoded as UTF-8 with `errors='replace'`. Under a Latin-1 locale a directory `caf` plus U+00E9 is the byte 0xE9, the decode makes it U+FFFD, and a Latin-1 stdout cannot hold it: `execute` made both bare leg repositories and stopped at `REFUSED extracting the spec leg`, exit 2, with filter-repo's `UnicodeEncodeError` from `_migrate_origin_to_heads`. - `_extract_leg` now runs `git config --unset remote.origin.url` in the clone right after its `checkout -B`. filter-repo returns before its NOTICE when the clone has no url, and leaves the remote alone. It still makes each of the clone's `refs/remotes/origin/*` a branch before it asks for the url, so it rewrites every branch of the source as on main. - Not `git remote remove origin` (#1247's candidate 1): that takes the remote-tracking branches with it, and a leg whose tracking branch holds a `cherry-pick -x` of a commit only another branch reaches then keeps that commit's old id in its message, where main rewrites it. Measured: a different spec-leg tip, the same tree. - Not `LC_ALL=C.UTF-8` for the child (#1247's candidate 2): it depends on the host's locales, and on Windows `LC_ALL` does not set a pipe's encoding (read, not run). No `PYTHON*` variable reaches a launcher run with `python -E`. - `tests/test_adopt_filter_repo_origin_url.py`, two rows: `_extract_leg` itself under any locale (no url and every remote-tracking branch when filter-repo starts, no url in its output, the second branch made a branch, the leg pushed), and `plan`, `check` and `execute` for #1247's source in a Latin-1 locale the test builds, with no `PYTHON*` variable but `PYTHONUTF8=0`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Reviewer's GuideImplementationUnset only the cloned leg’s
TestsAdd regression coverage for the Latin-1 failure, retained branch rewriting, config-file isolation, missing-origin handling, and refusal of other unset failures.
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
RV1251: independent review of #1251 at (lane openRepoShape-4, independent reviewer RV1251, 2026-11-08T15:34:15Z) One SHOULD and two NITs. The fix works: the defect reproduces on main, the head cures it with both launchers, and the legs come out byte-identical to main's. But the new What was measuredHost: git 2.43.0, Python 3.12.3. git-filter-repo 2.47.0 ( 1. The defect reproduces on main, with no
On main the run ends The existing row
The writer's claim holds. 2. filter-repo 2.47.0's order (read in frvenv's
3. The legs are byte-identical to main's (my own probe,
4.
5. The rows.
6. Mutants (in my own worktree at the head). The rows are both new rows plus the two
7. Gate, UTF-8, pip's launcher, with the rules' environment.
Gate A, one pytest over 19 files:
Latin-1 (new file +
8. Merge-trees.
FindingsSHOULD-1: the unset names no file, so
NIT-1: under NIT-2: the body says the only difference left is a url-less Not run: Windows, another one-byte locale, a real pipx install, a filter-repo other than 2.47.0, and Lane: openreposhape-4 (openRepoShape-4) |
…mes the clone's own config file, so a `GIT_CONFIG` in the environment cannot send it to a file of the person's, and a clone with no such url (a global `clone.defaultRemoteName`) goes on, to fail where main fails (#1247) RV1251 reviewed #1251 at 825923c: one SHOULD and two NITs. - `_extract_leg` ran `git config --unset remote.origin.url` with no file. With `GIT_CONFIG` in the environment, git writes the file that variable names, so `execute` took the url out of a file of the person's, outside the clone, and ended REFUSED (exit 2) with both legs made; main ends `adoption verified` and leaves that file alone. The call now has `--file <work>/.git/config`. `--local` is no way round it: with `GIT_CONFIG` set, git 2.43 exits 129 (only one config file at a time). `.git` is a directory wherever `execute` reaches the clone: one `git clone` makes it, `work` is an absolute path (`_work_root`), and a `GIT_WORK_TREE` in the environment, which would make the clone another shape, stops `execute` at the legs' `git init --bare` first (measured on main). - With a global `clone.defaultRemoteName`, the clone's remote is not `origin`, there is no url, and git exits 5: the previous commit refused there, before any leg was pushed and with an empty output block, where main goes on and fails at `mounting the legs` (`No such remote 'origin'`, both legs pushed). `_extract_leg` now goes on from exit 5 and from no other exit; any other is refused as any failed command is. That setting is its own defect (main fails on it too) and is not mended here. - tests/test_adopt_filter_repo_origin_url.py, three new rows: `execute` with `GIT_CONFIG` naming a file that holds a `[remote "origin"]` url ends `adoption verified` and leaves the file byte for byte; `_extract_leg` itself goes on from exit 5 under a global `clone.defaultRemoteName` and pushes the leg; and an unset that fails for another reason (a `config.lock` in the clone, exit 255) is refused before `git filter-repo` runs. The shared setup of the earlier rows is now two helpers. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
F1251: fix round on #1251 for RV1251's NOT READY. New head Please do a DELTA review of SHOULD-1 (the unset named no config file): fixed.
NIT-1 (a clone with no
NIT-2: the PR body is corrected. The claim "depends on no locale and no variable" now says the fix names its config file, so Rows (
Mutants (each restored, sha256 checked; the five rows plus the two split-branch rows, UTF-8 and Latin-1 alike):
Gates, on a scratch merge of this head and
Merge-trees of Left, outside this PR: a global Lane: openreposhape-4 (openRepoShape-4) |
|
RD1251: independent delta review of #1251 at (lane openRepoShape-4, independent delta reviewer RD1251, 2026-11-08) No MUST and no SHOULD. RV1251's SHOULD-1 is cured and pinned by a row, the exit-5 carry-on is narrow, the two earlier rows are as strong as before, and the gate is green on a scratch merge with the current What was measuredHost: git 2.43.0, Python 3.12.3, git-filter-repo 2.47.0 (frvenv, pip's launcher) and the 1. SHOULD-1 is fixed. My own probe (
The old head fails a little differently from RV1251's run (the spec leg, not the code leg: my file held only the url, so the first unset left it at 0 bytes), the same root. The legs from head and merge hash the same as main's: 2. The exit-5 carry-on is narrow.
3. The refactor keeps the two earlier rows as strong as before. I diffed
4. The rows (new file, 5 rows, the same result in UTF-8 and Latin-1 and with pip's and the
On main the failures are the two earlier rows, the exit-5 row and the lock row; the GIT_CONFIG row passes (main leaves the file alone). On 5. Mutants in my own worktree at the head (sha256
M1 to M8 match F1251's table exactly (M1 to M3 re-run with the old file's two rows alongside, as point 3 says). 6. Gate on the scratch merges
7. Merge-trees (
FindingsNIT-1 (a comment that overstates). NIT-2 (optional hardening). NIT-3 (two survivors, both low value). MB (exit 3 gone on from) and MJ (exit 5 gone on from for the code leg only) survive: the lock row stands for "any other exit" (255) and the exit-5 row calls the code role only. If wanted, one NIT-4 (a detail of the PR body). The body's counts and merge-trees cite main Not run: Windows, another one-byte locale, a real pipx install, a git other than 2.43, a filter-repo other than 2.47.0. Lane: openreposhape-4 (openRepoShape-4) |
…does_not_spell_it_as_utf_8` are held under emulated UTF-8, Latin-1 and ASCII codecs, `validate-family.py` is held to call `escape_unencodable_stdout()` first, and the two rows that can judge under Latin-1 run there (#1214) RV1258's review of #1258 (S1, S2, N1, N3): - tests/test_adopt_template_values.py (S1): the premise guard on `test_a_utf8_source_directory_still_adopts_with_local_remotes` is gone, with the `A_NAME_HELD_AS_UTF_8` import it left unused there. The row passes under Latin-1 with the pip-installed git-filter-repo; with a launcher started as `python -E` it fails on #1247's traceback until #1251 lands, which is the row's own failure and not a premise it cannot judge. #1258 no longer carries a guard for #1251 to drop. - tests/test_non_utf8_name_helpers.py (S2): 20 rows hold `skip_where_the_locale_does_not_spell_it_as_utf_8` under `os.fsencode`, `os.fsdecode` and `sys.getfilesystemencoding` emulated as UTF-8, Latin-1 and ASCII have them: 15 for the question that skips each of five texts in each locale (none, "cannot spell", "writes", "reads") and for the reason's encoding, ending and ASCII, and 5 that hold the emulation to this run's real locale. A helper that built UTF-8's bytes with `surrogatepass`, or dropped, reordered or inverted a question, now fails them under CI's UTF-8 locale. - tests/test_bootstrap_spelling.py (N1): the first-statement row also reads the holder's `validate-family.py`, so a call moved after `parse_args` fails it. - tests/test_family_head_by_hand_bytes.py (N3): `test_surrogateescape_reads_the_issues_branch_as_caf_and_u_dce9` asks `os.fsdecode(b"\xe9")` in its `if`, in place of the helper, so under Latin-1 it passes where it skipped; under UTF-8 and ASCII it asserts as before. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
Sorry @brettheap, you've used your own review budget of 250,000 diff characters for the last 7 days. You can request another review in 6 days by commenting |
|



Closes #1247
(lane openRepoShape-4, 2026-11-08T14:44:07Z) Lane 3 places this PR; it carries no milestone here.
Head
abeac66dis a fix round for RV1251's review of825923c7(#1251 (comment)): one SHOULD and two NITs, set out under "Review round 1" below. The sections after that describe this head._extract_leg(adopt-project.py) now unsets the leg clone'sremote.origin.url, in the clone's own config file (--file <work>/.git/config), right after itscheckout -Band beforegit filter-reporuns. filter-repo then prints no url, so a Latin-1 stdout has no U+FFFD to choke on, and it still turns every remote-tracking branch into a branch first, so the legs are the ones main makes.The defect, reproduced on main
b1f45fa7, git 2.43.0, Python 3.12.3, git-filter-repo 2.47.0 (--versionprintsa40bce548d2c).#!.../frvenv/bin/python3, WITHOUT-E. So anyPYTHON*variable would reach filter-repo, and the reproduction sets none: noPYTHONIOENCODING, noPYTHONUTF8.test_stdout_encoding.py), and whether each is a test that cannot judge under a one-byte locale or a tool defect is not measured (W1196's leftovers; follows #1196) #1214 and adopt-project.py: under a one-byte locale such as Latin-1,checkreads a plan written in UTF-8 whose source is there, asking the plan's UTF-8 bytes where the spelling as written names nothing, rather than refusingplan-source-gone(#1078) #1106 build it (localedef -c,LOCPATH,LC_ALL=en_US.ISO-8859-1).make_source_repounder a directorycafplus U+00E9, made as the byte 0xE9. The probe runsplan,checkandexecute --local-remote-diras the existing row does, but without itsPYTHONIOENCODING=utf-8:strict.planexit 0,checkexit 0 (plan ok), andexecuteexit 2:Both bare leg repositories were left behind. So the defect does not need a
-Elauncher: a person in a Latin-1 locale sets noPYTHONIOENCODING, and pip's launcher fails as well.The existing row,
test_adopt_template_values.py::test_a_utf8_source_directory_still_adopts_with_local_remotes, under Latin-1 on main:PYTHONIOENCODING=utf-8:strictreaches filter-repo throughexecute's environment.-Eon the shebang (a model of the pipx launcher adopt-project.py: under a one-byte locale such as Latin-1,executestops extracting the spec leg of a source whose path holds U+00E9, becausegit filter-repoprints the clone's origin url as U+FFFD to a stdout that cannot hold it #1247 quotes), it FAILS with the traceback above. That matches W1196's log.-Edrops the variable: withPYTHONIOENCODING=bogus-codec, pip's launcher dies at start-up, while the-Ecopy prints its version.The fix, and the two candidates measured first
Candidate 1 in #1247,
git remote remove originbefore filter-repo, changes what the legs hold. It is rejected.git remote removedeletesrefs/remotes/origin/*with the remote. filter-repo then no longer makes the source's other branches into branches, and never rewrites them.executeon main and on candidate 1, over two ASCII sources with fixed dates. For each leg's bare repository the probe compared: every ref, every commit with its tree, parents and full message, and every reachable object.make_source_repo, one branch): identical.releasebranch whose commit R changesspecs/001-feature/tasks.md, no tag reaching it, and onmainagit cherry-pick -x R: the spec leg's tip differs,0316169eon main against82176493on candidate 1, with the same tree9ef5b676. On main its message reads(cherry picked from commit 407d03a0...), R as rewritten. Under candidate 1 it reads(cherry picked from commit 30e9dd30...), R's id in the source.checkdescribes. As a mutant, it fails the existingtest_adopt_split_branch.py::test_the_extraction_stops_at_a_source_branch_in_its_way(both rows,DID NOT RAISE CommandFailed). With it, a source branch in git's way no longer stops the extraction.Candidate 2,
LC_ALL=C.UTF-8for the child, depends on the host.python3 -E, a pipe's encoding isutf-8underLC_ALL=C.UTF-8. It is alsoutf-8underC,POSIXand a locale name that does not exist, because CPython falls back to C and turns on its UTF-8 mode.LC_ALLdoes not set a pipe's encoding (read, not run).PYTHON*variable is a cure, because a-Elauncher drops it.What this PR does: unset the url only (
git config --file <work>/.git/config --unset remote.origin.url). It depends on no locale. It names the clone's own config file, soGIT_CONFIGin the environment cannot redirect it to a file of the person's (RV1251's SHOULD-1, below). It goes on from a clone that has no url to unset, and from no other failure (NIT-1, below)._migrate_origin_to_heads(2.47.0) turnsrefs/remotes/origin/*intorefs/heads/*first. Then it returns whenremote.origin.urlis not in the config, before the NOTICE that printed the url and before its owngit remote rm origin.diffof the dumps: empty).execute): the url-less[remote "origin"]with its fetch refspec+refs/heads/*:refs/remotes/origin/*, andbranch.main.remote = originandbranch.main.merge = refs/heads/main. Nothing reads any of it._push_the_legpushes to the leg's url, and_mount_the_legsmounts the clone by its path. RV1251 measured that the mounted submodules hash the same as main's.runin_extract_leg(now with atry), with a comment. No pinned or template copy ofadopt-project.pyexists, and no document describes this step.Review round 1 (RV1251 at
825923c7)SHOULD-1, fixed: the unset named no config file.
GIT_CONFIGin the environment (a legacy variable git still reads) names the file a baregit configwrites.GIT_CONFIGnaming a file that holds[remote "origin"] url = ...and the standard source, inexecute:adoption verified, the file unchanged.825923c7: exit 2,REFUSED extracting the spec leg, both bare legs made and nothing pushed, and the file empty. The first leg's unset took the only key out of it, and filter-repo, reading that empty file as the config, died with aValueErroringet_config_settings. (RV1251's file ended in an unset exit 5 instead.)adoption verified, the file byte for byte as it was.run(["git", GIT_CONFIG, "--file", str(work / ".git" / "config"), "--unset", "remote.origin.url"], cwd=work).--localis no way round it: withGIT_CONFIGset, git 2.43 exits 129 (only one config file at a time).work / ".git"is a directory whereverexecutereaches the clone:git clone -q <source> <work>, andworkiswork_root / <name>, wherework_rootisos.path.realpath(--work-dir)or atempfile.mkdtempfolder (_work_root): an absolute path;GIT_DIRdoes not move a clone (measured: the clone has its own.git);GIT_WORK_TREEdoes make the clone another shape (the git dir isworkitself), butexecutestops on it first, on main and on this head alike, at the legs'git init --bare(REFUSED a git or gh command failed);could not lock config file ... No such file or directory), which is refused.git config --listalso reads the fileGIT_CONFIGnames (theValueErrorabove came from it), so underGIT_CONFIGit sees that file's settings, as on main. On this head the run endsadoption verifiedwith the legs main makes.NIT-1, handled: a clone with no
originurl. A globalclone.defaultRemoteName = upstreamgives the clone a remote that is notorigin, sogit config --unset remote.origin.urlhas no key and exits 5 (measured, git 2.43). It can happen.mounting the legs(No such remote 'origin'), after both legs are pushed.825923c7failed earlier, at the unset (exit 5, an empty output block), with nothing pushed._extract_leggoes on from exit 5 and from no other exit (GIT_CONFIG_KEY_ABSENT = 5). The run fails where main fails, not earlier and not worse. Any other exit of the unset (255 for a file git cannot lock, 129 for a usage it refuses) is refused as any failed command is.clone.defaultRemoteNameitself.executefails on it on main too. It is a follow-up for its own issue.remote.origin.url(measured); that too goes on, as main does.NIT-2, corrected in this body: the claim that the fix "depends on no locale and no variable" (it now names its config file, so
GIT_CONFIGcannot redirect it); the work clone's leftovers, now listed under "What stays in each work clone" (the url-less[remote "origin"],branch.main.remoteandbranch.main.merge); and the note that #1141 conflicts, dropped: it merges clean at0b8fb320.Rows
tests/test_adopt_filter_repo_origin_url.py, new, five rows:test_filter_repo_starts_with_no_origin_url_and_every_branch(any locale)._extract_legitself runs over an ASCII source with a second branch, withrunspied at thegit filter-repocall. When filter-repo starts, the clone has noremote.origin.urland still hasrefs/remotes/origin/mainandrefs/remotes/origin/beside. filter-repo's output holds neitherRemoving 'origin' remotenor the source path. Afterwards the clone hasrefs/heads/beside, and the leg holds the clone's HEAD.test_execute_adopts_a_source_named_in_latin1_under_latin1(Latin-1). It runsplan,checkandexecute --local-remote-dirfor adopt-project.py: under a one-byte locale such as Latin-1,executestops extracting the spec leg of a source whose path holds U+00E9, becausegit filter-repoprints the clone's origin url as U+FFFD to a stdout that cannot hold it #1247's source (a directorycafplus the byte 0xE9) in a Latin-1 locale the test builds as adopt-project.py: under a one-byte locale such as Latin-1,checkreads a plan written in UTF-8 whose source is there, asking the plan's UTF-8 bytes where the spelling as written names nothing, rather than refusingplan-source-gone(#1078) #1106 builds one. NoPYTHON*variable is set exceptPYTHONUTF8=0. It asserts no traceback,checkexit 0,executeexit 0 andadoption verified.localedef's words, where no Latin-1 locale can be built, and on Windows. It also skips where a name that is not UTF-8 cannot be made (skip_where_a_name_cannot_be_not_utf_8).test_execute_leaves_the_file_git_config_names_alone(new, SHOULD-1).executewithGIT_CONFIGnaming a file that holds a[remote "origin"]url:adoption verified, and the file is byte for byte as it was. The child gets none of the gate's locale variables, so the row runs alike under a UTF-8 and a Latin-1 gate.test_a_clone_with_no_origin_url_goes_on_to_filter_repo(new, NIT-1)._extract_legitself under a globalclone.defaultRemoteName = upstream: the unset exits 5 (recorded as it is raised), the clone'sremote.upstream.urlis the source, and the leg is pushed.test_an_unset_that_fails_for_any_other_reason_stops_the_leg(new, NIT-1). Aconfig.lockin the clone makes the unset exit 255:CommandFailed, beforegit filter-repoand with nothing pushed. It needs no git-filter-repo.extract_the_code_legandadopt_each_step. The file is ASCII with no backslash escape; each non-ASCII character is built withchrorbytes.Counts (5 rows; the same file in each tree):
-E-E_extract_legas ondffc4226; unchanged in5926ccca)825923c7(the previous head)The two earlier rows fail on main and pass here. The GIT_CONFIG row fails on
825923c7and passes here. The exit-5 row fails on825923c7and on main (no unset to record) and passes here. The lock row passes on825923c7, which refuses every exit; it guards the newexcept.Mutants
Each mutant was applied in a worktree at this head, the five rows plus the two
test_the_extraction_stops_at_a_source_branch_in_its_wayrows were run under UTF-8 and under Latin-1, andadopt-project.pywas restored with its sha256 checked after each one (RESTORED sha256 ok, tree as before).git filter-repogit remote remove origininstead--file <path>--localinstead of--file <path>(exit 129 underGIT_CONFIG)try)--file <work>/config, a path with no file (exit 5, carried on)Gates
All runs used
/usr/bin/python3 -m pytest -p no:cacheproviderwith one reused basetemp per run kind and-o tmp_path_retention_policy=failed, at most 2 pytest runs at a time. The environment had a stubghfirst on PATH,GH_TOKEN=bogus, an emptyGH_CONFIG_DIR,GIT_CONFIG_GLOBALan empty file andGIT_CONFIG_NOSYSTEM=1, and noGIT_ALLOW_PROTOCOL,GIT_SSH_COMMAND,GIT_CONFIG,LANES_*orPYTHON*variable. filter-repo was pip's launcher (a40bce548d2c) unless a row says otherwise.The tree gated is a scratch merge of this head and
origin/main5926ccca(built withmerge-treeandcommit-tree; its diff against main is this PR's two files). One hygiene row caught a path in the first attempt (/home/someone/...in the new test,test_no_committed_file_names_a_host_absolute_path); the row now nameshttps://example.invalid/keep-me.git, and everything below ran on the final head.Gate A, UTF-8 (
LC_ALL=C.UTF-8), one pytest, 23 files: 1518 passed, 3 skipped on the scratch merge.test_adopt_template_values.py,test_adopt_split_branch.pyandtest_adopt_e2e.py;_extract_legor_push_the_leg:test_adopt_filter_repo_failure.py,test_adopt_history_gitlinks.py,test_adopt_late_failure.pyandtest_adopt_plan_escapes.py;test_adopt_check_throwaway_repos.py,test_adopt_partial_clone_source.py,test_adopt_pins.py,test_adopt_git_rm_bytes.pyandtest_adopt_plan_partial_clone.py(new on main);test_repo_hygiene.py,test_path_guard_hygiene.py,test_cli_reference.pyandtest_scaffold_leg_path_collisions.py;test_no_auto_maintenance.py,test_non_utf8_git_failures.py,test_git_output_decoding.py,test_setup_project_repo_misdrawn.py,test_shape_advisory.pyandtest_openreposhape_package.py.5926ccca, the same 22 files without the new one: 1513 passed, 3 skipped. The head's extra 5 are the five rows.-rs): the same 3 on both, none for lack of git-filter-repo:test_adopt_check_throwaway_repos.py:482(a disk that keeps case) andtest_no_auto_maintenance.py:222x2 (GIT_CONFIG_GLOBALset).tests/test_shape_doctor.py, UTF-8, 4 shards from a bash script (449 ids): Head (scratch merge): 118, 110, 118 and 100 passed, with 3 skipped in the last shard (the PowerShell line, Windows only): 446 passed, 3 skipped. RV1251 and W1247 measured 446 passed and 3 skipped on main at11560eb9andb1f45fa7; it was not re-run on5926ccca, because this PR touches nothing the doctor reads.Latin-1 (the locale built as above,
PYTHONUTF8=0), the new file andtest_adopt_template_values.py:5926cccatest_adopt_template_values.py, pip launcher-Elaunchertest_stdout_encoding.py), and whether each is a test that cannot judge under a one-byte locale or a tool defect is not measured (W1196's leftovers; follows #1196) #1214's to judge, not this PR's:test_plan_refuses_a_flag_no_file_can_holdat--elected-byand--referencewith U+DCE9,test_plan_and_check_say_the_same_sentence, andtest_execute_refuses_a_local_source_directory_that_is_not_utf8(under Latin-1 the byte 0xE9 is valid text).-Eistest_a_utf8_source_directory_still_adopts_with_local_remotes, which this head fixes.Merge-trees
git merge-tree --write-treeof this head against:5926ccca, and the mergedadopt-project.pykeeps the--filecall.--planpath incheckandexecute, and the--local-remote-dirpath inexecute'sbare, leg andsplitlines, are named with_shown, as #1154 names--outand--work-dir, so a bidi control, an escape, a line feed or a byte that is not UTF-8 in either no longer reaches the terminal as it was typed (#1152) #1177 (5208e874) and adopt-project.py: a refused command's REFUSED block spells each character a terminal acts on in the command, its directory and what it printed, as_first_saidspells gh's, so--local-remote-dirno longer reaches the terminal raw there; a NOTE beforeNEXT:says when the source's path in its clone command holds a character a terminal does not show as itself; and rows pin six sites #1177's 148 left to chance (#1195) #1225 (73c9f57e), the only open PRs that touch_extract_leg: both clean, each keeps the--filecall..gitthis user cannot read is refusedsource-unreadable, naming that.git, socheckandexecuteno longer call a cloneplanmade with its.gitat mode 000 no longer whole and clone it again (#1099) #1141 (0b8fb320): clean. The earlier note that it conflicts is stale and is dropped.adopt-project.pyagainst the previous head: 26 clean, and adopt-project.py: the mount removes a path a case twin is at or under withgit rm -fand writes the twins the root keeps back from the index, so on a disk that ignores caseexecutekeeps a set the plan splits across repositories or drops (#1183) #1237 conflicts intests/test_adopt_check_throwaway_repos.pywith main alone. This round re-ran main, adopt-project.py: the--planpath incheckandexecute, and the--local-remote-dirpath inexecute'sbare, leg andsplitlines, are named with_shown, as #1154 names--outand--work-dir, so a bidi control, an escape, a line feed or a byte that is not UTF-8 in either no longer reaches the terminal as it was typed (#1152) #1177 and adopt-project.py: a refused command's REFUSED block spells each character a terminal acts on in the command, its directory and what it printed, as_first_saidspells gh's, so--local-remote-dirno longer reaches the terminal raw there; a NOTE beforeNEXT:says when the source's path in its clone command holds a character a terminal does not show as itself; and rows pin six sites #1177's 148 left to chance (#1195) #1225 (the only PRs that touch_extract_leg) and adopt-project.py: a recorded source whose.gitthis user cannot read is refusedsource-unreadable, naming that.git, socheckandexecuteno longer call a cloneplanmade with its.gitat mode 000 no longer whole and clone it again (#1099) #1141 (the one the earlier body got wrong).Overlap with #1214
#1214's WIP guard, in lane 4's unpushed work on
fix/1214-latin1-locale-tests, skipstest_a_utf8_source_directory_still_adopts_with_local_remotesunder Latin-1 by its UTF-8 premise.git ls-remotenames no1214branch).test_stdout_encoding.py), and whether each is a test that cannot judge under a one-byte locale or a tool defect is not measured (W1196's leftovers; follows #1196) #1214 and adopt-project.py: under a one-byte locale such as Latin-1,executestops extracting the spec leg of a source whose path holds U+00E9, becausegit filter-repoprints the clone's origin url as U+FFFD to a stdout that cannot hold it #1247 lands second drops that guard. With this fix the row passes under Latin-1 with either launcher, and this PR's Latin-1 row covers the defect either way.tests/test_adopt_template_values.pyor tests: 50 tests in 12 files fail under a Latin-1 locale before and after #1209 (ten of them rows oftest_stdout_encoding.py), and whether each is a test that cannot judge under a one-byte locale or a tool defect is not measured (W1196's leftovers; follows #1196) #1214's branch.Not done, and limits
-Elauncher here is a one-line copy of pip's.originare under--sensitive-data-removal, whichexecutenever passes.🤖 Generated with Claude Code
Lane: openreposhape-4 (openRepoShape-4)
Summary by Sourcery
Make project adoption robust to source paths that cannot be represented by the locale used by git-filter-repo.
Bug Fixes:
Enhancements:
Tests: