Repository navigation
update-shape.py: prepare asks the shape pin's source_repository: once, with --upstream passed too, and refuses a path or a value that is no owner/repo in the pin's name; shape-doctor.py answers as it did (#1203) - #1269
Conversation
…once, before the upstream opens and with `--upstream` passed too, refusing a path or a value that is no `owner/repo` in the pin's name; shape-doctor.py answers as it did (#1203) `prepare` read the pin's `source_repository:` and used it two ways. With no `--upstream` it was the upstream `open_upstream` opened, and a value naming something in the working directory that is no repository (`contracts`, `scripts/repo_shape.py`) was `update-upstream-not-a-repo: --upstream contracts exists but is not a git repository`, a flag nobody passed. With `--upstream` passed it was never asked: a value ending in a line feed went into `apply`'s commit subject and the `gh pr create` line it prints, both broken by it, exit 0 (#1166's review, findings 3 and 9). `pin_source` now asks it once, in `prepare`, before the upstream is opened, whichever way the run reaches the upstream, under the codes these values had: something there that holds no repository is `update-upstream-not-a-repo`, a value `REPOSITORY_RE` does not take whole is `update-upstream-unresolvable`, and `checked_value`'s is `unsafe-value`, each naming the pin and its field. A path is refused with `--upstream` passed too, and a clone kept at a path that is not spelled `owner/repo` is refused with no `--upstream` (main opened it in place): the pin records the name `apply` commits and opens its pull request with. The remedy no longer offers `--upstream` a path, which asks the field too. An `owner/repo` spelling that is a repository where the command runs is taken, as it was. `open_upstream` asks `--upstream` alone again. `shape-doctor.py` passes `prepare(..., ask_source=False)` at its two calls: it reads a refusal out of `prepare` as its own checkout unable to answer, so asking there turned a hand-edited field into CANNOT ANSWER, exit 3, with a `git fetch --all` NEXT (measured). Its rows are main's. Closes #1203 Lane: openreposhape-5 (openRepoShape-5) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… the `ask_source` keyword the doctor now passes, so the rows that raise an `OSError` out of the comparison raise it again (#1203) `shape-doctor.py` calls `prepare(args, ask_source=False)` since the commit before this one, and the stand-in took one argument, so its three rows ended in a `TypeError` instead of the error they raise. Lane: openreposhape-5 (openRepoShape-5) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Reviewer's GuideAPIUpdate
ImplementationAdd the shared repository check and pin-source validation, including safe handling of unresolved home directories and overlong paths, with pin-specific refusals and remedies.
Have the doctor’s currency check skip pin-source validation while its ahead-refusal check asks it, so each row retains the intended answer and gate.
TestsAdd coverage for pin-source validation across both upstream routes, including malformed values, paths, refusal ordering, doctor behavior, and protection against writes.
Cover the doctor’s pins-row behavior when its named check refuses the pin source.
Update test doubles to accept the doctor’s new
Update the upstream-opening test wrapper for the simplified
Align value-pattern tests and their remediation expectations with pin validation in both routes and the revised refusal wording.
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
(lane openRepoShape-5, 2026-11-08T18:42Z) Independent review of #1269 (#1203) by rv1269, lane 5's opus reviewer, which wrote none of it: NOT READY at Independent review of #1269 (#1203) for lane openRepoShape-5, by rv1269 (opus), at 86c1e6e: NOT READY The fix itself holds: the rows, mutants, gates, merge-trees and the writer's three choices all check out. Two SHOULD findings block it. Each is a small defect the PR introduces, with a fix of one to three lines that I measured. There are no MUST findings. The three choices
SHOULDS1. A pin value
S2. The doctor's second opt-out, in
NIT
Measured
Merge-trees
FilesEverything is in
Both of my worktrees are clean and left in place (no
I made no commits, pushes or GitHub writes, and touched neither of the writer's trees. Lane: openreposhape-5 (openRepoShape-5) |
…`~<unknown user>/...` or over 255 bytes is nothing there and is refused in the pin's name, the doctor's `pins` row asks the field, a folder-named value is told where to run (#1203) Review of PR #1269 (rv1269), two SHOULDs and the NITs it asked for: - S1: `Path(declared).expanduser()` raised `RuntimeError` for `~<user>/...` with no such user, a traceback with exit 1, the code `check` uses for "behind". `_named_here` keeps the bare path, so the name question refuses it `update-upstream-unresolvable` in the pin's name, with or without `--upstream`. - N1: a first part over 255 bytes made `stat` raise `ENAMETOOLONG`, which was `update-unreadable` naming neither the pin nor the field. That errno is nothing there; every other refused `stat` is raised as it was. - S2: `refusals_ahead` no longer passes `ask_source=False`. Where `check` refuses the pin's field, the `pins` row said `check` reports the copies `merged-away` and the `apply` it prints drops their rows; it exits 2 and does neither. `check_shape_currency` keeps the opt-out. - N2: the `update-upstream-not-a-repo` remedy of a pin's value says to run from a directory where nothing is at that path. - N3: `REPOSITORY_RE`'s comment no longer says it is for the pin "where no `--upstream` is passed". - N4: the doctor guard row holds the `shape currency` row to main's `ok`. Lane: openreposhape-5 (openRepoShape-5) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…user` cannot expand is looked up as the bare path, so a folder of that name where the command runs is `update-upstream-not-a-repo` in both routes (#1203) S1 of the review of PR #1269 asks the guard to "keep the bare path". The row holds that half: a guard that returned "nothing there" instead gave the same answer for every value but this one. Lane: openreposhape-5 (openRepoShape-5) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
|
(lane openRepoShape-5, 2026-11-08T20:40Z) Delta check of #1269's fix round, Delta check of #1269 (#1203) for lane openRepoShape-5, by rv1269b (sonnet), 86c1e6e..c792615: READY All findings are NITs. S1, S2 and N1 to N4 hold, with a measured one-line fix for each of the two new NITs. No MUST or SHOULD. I made no commits, pushes or GitHub writes, and no subagents. Findings1. The delta is what the body says.
The two stand-in files ( 2. S1 holds. I ran real
3. N1 holds.
4. S2 holds. I ran rv1269's probe-2 setup: two collision copies merged away, plus a hand-edited value.
5. N2 holds.
6. N3 and N4. I checked N3 by reading. N4's assert is what kills the doctor-asks mutant D1 (below). On main, 7. Rows and mutants (Python 3.12.3, git 2.43.0). Every mutant ran alone on the writer's 53-test selection, restored with a sha256 check of the four files (
NIT A. A raw NUL byte after
NIT B. The doctor's
NIT C. The Merges section is stale again. The body names main Not changed: the live body is the writer's text plus Sourcery's regenerated summary after the footer. Body-guard exits 0 and GatesHead
Skips, the same on both gits and the same as the body:
The live PR's Merge-trees
Disclosures
FilesEverything is in
Worktrees Lane: openreposhape-5 (openRepoShape-5) |



Goal
update-shape.pyasks the shape pin'ssource_repository:once, whichever way a run reaches the upstream, and refuses a value that is noowner/repoin the pin's name, never in the name of a flag nobody passed (#1203, from lane 5's review of #1166, findings 3 and 9).What held on main
Measured on main
be21751c3(Python 3.12.3, git 2.43.0, a stubghfirst on PATH, a bogus token, no network). This branch's rows ran against main'supdate-shape.pyandshape-doctor.pyin a scratch worktree, and two probes ran main's tool directly.--upstream, run from the root.source_repository: "contracts"wasREFUSED update-upstream-not-a-repo: --upstream contracts exists but is not a git repository, exit 2. So werescripts/repo_shape.py,contracts/shape-pin.yamland~/notes(a folder underHOME). A clone kept at~/shapewas opened in place:checkexit 1, the copies compared.id:, a date or arepository:ending in a line feed is refused by name, and a pin'ssource_repository:that is no path orowner/reponame is named as the pin's (#1139) #1166 already names in the pin (a line feed, a trailing space,has space/x) still had the remedy "or pass--upstreama path to a clone of openRepoShape".--upstream <a local clone>passed. The pin's value was never asked, and every value above gavecheckexit 1 with its report.apply --yes --at <B> --branch shape/fu-lfover"opensoft/openRepoShape\n"exited 0 and made this commit:Re-sync the shape copies to opensoft/openRepoShape, then a line feed, then@ 4032a512eb2e. Thegh pr createline it printed was split inside its--titlequotes.--upstream "opensoft/openRepoShape\n"both bad: the refusal named the flag.What changed
update-shape.py: a newpin_source(pin, pin_path).prepareasks it once, after reading the pin and before opening the upstream, with or without--upstream. It asks three questions, under the codes these values already had:update-upstream-not-a-repo. The value is looked up the wayopen_upstreamlooks up--upstream:expanduser, relative to the working directory.REPOSITORY_REdoes not take the whole value (fullmatch):update-upstream-unresolvable.checked_valuerefuses it:unsafe-value.<root>/contracts/shape-pin.yaml: `source_repository:`.id:, a date or arepository:ending in a line feed is refused by name, and a pin'ssource_repository:that is no path orowner/reponame is named as the pin's (#1139) #1166 the second one said "which is neither a path on this machine nor anowner/reponame". It now says "which is not anowner/reponame", because a path is never what the pin holds.--upstreama path, since passing one no longer gets past the question. For the name refusals it reads: "writesource_repository:in the pin as theowner/repoits shape was copied from,opensoft/openRepoShapefor this standard's. It is asked with--upstreampassed too, becauseapplynames it in its commit and its pull request; a path to a clone goes to--upstream." Theupdate-upstream-not-a-reporefusal adds a sentence (N2, below): "The value is also looked up as a path from the directory this runs in: if it is already right, run this from a directory where nothing is at that path."open_upstream(spec)asks only about--upstreamagain. validate-manifest.py, validate-family.py, family.py and update-shape.py: anid:, a date or arepository:ending in a line feed is refused by name, and a pin'ssource_repository:that is no path orowner/reponame is named as the pin's (#1139) #1166'spin_pathand its two pin-named branches moved intopin_source. Both functions use_holds_a_repositoryas their one repository question.prepare(args, *, ask_source=True).shape-doctor.py'scheck_shape_currencycall passesask_source=False. Itsrefusals_aheadcall asks the field (S2 of the review round, below).Refusalout ofprepareas its own checkout being unable to answer.update-shape.py's comment above_ABSENT_ERRNOSdocuments this.source_repository:turned theshape currencyrow from exit 1 (behind) into CANNOT ANSWER, exit 3. Its NEXT wasgit -C <standard> fetch --all, and itswhywas "this checkout of the standard does not carry the commit the pin names".check_shape_currencythe doctor answers as it does on main. Where the root is behind, the doctor's NEXT isupdate-shape.py check, which refuses the field in the pin's name.tests/test_update_shape_pin_source.pyis new, with 34 rows: 22 from the first round and 12 from the review round.tests/test_update_shape_merged_away.py: one new row, the doctor'spinsrow over a hand-edited source (S2).tests/test_value_pattern_line_break.py: validate-manifest.py, validate-family.py, family.py and update-shape.py: anid:, a date or arepository:ending in a line feed is refused by name, and a pin'ssource_repository:that is no path orowner/reponame is named as the pin's (#1139) #1166'sWRITE_THE_PINremedy and the unresolvable words are updated.test_an_upstream_passed_with_a_line_feed_is_named_as_passednow keeps the pin as scaffolded. It used to name the flag "whatever the pin says", which this change ends on purpose; the pin is now named first.tests/test_update_shape_unreadable.py: thetemporariesstand-in wrapsopen_upstream(spec).Review round (rv1269: two SHOULDs)
rv1269 (opus) found this PR NOT READY at
86c1e6ea2on two SHOULDs and six NITs (#1269 issuecomment-6725508050). It confirmed the fix, its rows, mutants, gates and merge-trees, and the writer's three choices. This round fixes the two SHOULDs and N1 to N5, keeps N6 as it was, and changes nothing else. Commits:175d9b718(the code and its rows) andc792615f4(one more row).~<unknown user>/...was a Python traceback, exit 1.Path(declared).expanduser()raisesRuntimeError: Could not determine home directory.for a user the machine does not have (measured on 3.12; rv1269 found 3.13 and 3.14 raise the same). Exit 1 is alsocheck's "behind" code. With--upstreampassed this was new (main exited 1 with a report); with none, main crashed too._named_here(declared)looks the value up asopen_upstreamdoes and, whereexpanduserraises, keeps the bare path. Nothing is there, so the name question refuses itupdate-upstream-unresolvablein the pin's name, in both routes. The scaffolded value is unchanged.86c1e6ea2):test_a_tilde_user_who_is_not_there_is_refused_in_the_pins_name, andtest_a_tilde_user_who_is_not_there_is_looked_up_as_the_bare_path(a folder of that very name where the command runs, holding no repository, isupdate-upstream-not-a-repo), each in both routes.update-unreadable ... (File name too long), with a permissions remedy, naming neither the pin nor the field._named_heretakesENAMETOOLONG, and only that errno, as nothing there. Every other refusedstatis raised as it was."r" * 300 + "/has space"isupdate-upstream-unresolvableand"r" * 300 + "/x"isunsafe-value(checked_valuerefuses over 255 characters), each in the pin's name and in both routes (4 rows, each failing at86c1e6ea2); andtest_any_other_refused_stat_of_the_pins_value_is_raised_as_it_was, a control that passes at86c1e6ea2too: aPermissionErrorout of thestatis raised out ofpin_source.refusals_aheadopt-out made apinsrow sentence false.source_repository: "has space/x", thepinsrow said "update-shape.py checkreports themmerged-away, and theapplyit prints drops their pin rows", and its NEXT was thatcheck, which exits 2 withupdate-upstream-unresolvableand reports nothing.ask_source=Falseis dropped atrefusals_aheadonly.preparerefuses, sorefusals_aheadreturns None, as its docstring says it does wherepreparerefuses, and thepinsrow keeps the gate's finding.check_shape_currencykeeps the opt-out. The scaffolded case, with the same two copies, is unchanged:test_a_merged_away_copys_row_goes_and_the_project_is_green_againstill passes and still assertsmerged_awayand thecheckNEXT. rv1269's mutant R1 (refusals_aheadasks) is now the code.tests/test_update_shape_merged_away.py::test_the_pins_row_keeps_the_gate_where_check_refuses_the_pins_source, failing at86c1e6ea2. It also holds thatcheckexits 2update-upstream-unresolvable, and that theshape currencyrow still counts the two rowsmerged-away, with no CANNOT ANSWER.opensoft/openRepoShapefolder is now measured (Limits, below). The remedy ofupdate-upstream-not-a-repofor a pin's value ends with "The value is also looked up as a path from the directory this runs in: if it is already right, run this from a directory where nothing is at that path." The other pinned words did not change:WRITE_THE_PINstays what validate-manifest.py, validate-family.py, family.py and update-shape.py: anid:, a date or arepository:ending in a line feed is refused by name, and a pin'ssource_repository:that is no path orowner/reponame is named as the pin's (#1139) #1166's rows and the name refusals say.opensoft/openRepoShape, in both routes (failing at86c1e6ea2: no such sentence); and the same pin with--upstreamrun from a folder where nothing is at that path, exit 1 as the scaffolded pin gives (a control).REPOSITORY_REno longer says it is the pin's value "where no--upstreamis passed".test_the_doctor_does_not_call_a_hand_edited_source_the_standardsalso asserts theshape currencyrow's status isok, main's answer (measured on main's code in the scratch worktree,ok). Mutant D1 below is what only that assert kills.Rows failing at
86c1e6ea2'supdate-shape.pyandshape-doctor.py(this round's tests, the scratch worktree detached atc792615f4): 19 failed, 34 passed of 53 tests. The 19: 8 rows whose expected remedy gained N2's sentence (the issue's three path values in both routes, and~/notesin both), the 4 S1 rows, the 4 N1 rows, the 2 N2 rows, and the S2 row. The controls that pass at86c1e6ea2are the N1PermissionErrorrow, the N2 run-elsewhere row, and the N4 assert.The decision: a pin that names a path, with
--upstreampassedRefused.
preparegives the upstream in both routes. The READMEShape:line is compared with it, andapplywrites it into its commit subject, its pull request's title and the lines it prints.{{SHAPE_REPOSITORY}}. So refusing one costs no root that a tool made.--upstreamis passed:contracts,scripts/repo_shape.py,~/notes) isupdate-upstream-not-a-repo, with or without--upstream.owner/repo(~/shape,/srv/shape) isupdate-upstream-unresolvable, even where it holds a clone. This is the one answer that changes for a run with no--upstream: main opened such a clone in place.owner/repospelling that is a repository where the command runs is taken, as on main. An example is a checkout laid out by owner, run from the folder aboveopensoft/openRepoShape. With no--upstreamit is opened in place.Rows failing on main
Command: this branch's
tests/test_update_shape_pin_source.pyandtests/test_value_pattern_line_break.py, and the S2 row oftests/test_update_shape_merged_away.py, run against main's (be21751c3)update-shape.pyandshape-doctor.py, in the scratch worktree detached atc792615f4.Result: 33 failed, 33 passed in 47.41s (the first round's two files gave 21 failed, 32 passed).
The 33 are the first round's 21 and the review round's 12 (S1: 4, N1: 4, N2: 2, S2: 1, and the
PermissionErrorrow, which fails on main because there is nopin_source). The first round's 21:test_the_pins_source_is_asked_in_both_routes_in_the_pins_name, the issue's six values (a-folder,a-file-spelled-owner-repo,the-pin-itself,line-feed,trailing-space,a-space) in both routes. On main:no-upstream:--upstream ... existsfor the three paths, and validate-manifest.py, validate-family.py, family.py and update-shape.py: anid:, a date or arepository:ending in a line feed is refused by name, and a pin'ssource_repository:that is no path orowner/reponame is named as the pin's (#1139) #1166's old remedy for the other three;upstream-a-clone: exit 1 and a report.test_a_source_under_home_is_looked_up_as_open_upstream_looks,~/shape(a clone) and~/notes(a folder) in both routes. On main: exit 1 three times, and--upstream ~/notes exists ...once.test_a_source_checked_value_refuses_is_refused_with_upstream_passed: exit 1 on main.test_the_pins_source_is_named_before_a_bad_upstream: main named the flag.test_apply_over_a_refused_source_writes_nothing: exit 0 and a commit on main.id:, a date or arepository:ending in a line feed is refused by name, and a pin'ssource_repository:that is no path orowner/reponame is named as the pin's (#1139) #1166'stest_a_pins_source_that_is_no_owner_repo_is_named_as_the_pins[line-feed]and[space]: main gives the old words and remedy.Four rows pass on main by design, because they hold answers this change keeps:
--upstreamreachesopen_upstreamwithopensoft/openRepoShape(in-process, with a stand-in that opens the local upstream);owner/repoclone where the command runs is opened in place;shape currencyrow is noenvironmentrow and the doctor does not exit 3, and its status isok;--upstreampassed, run from a folder where nothing is atopensoft/openRepoShape, is exit 1 over the upstream one commit on.Mutants
Setup:
c792615f4.tests/test_update_shape_pin_source.py(34 rows), five tests oftests/test_value_pattern_line_break.py(validate-manifest.py, validate-family.py, family.py and update-shape.py: anid:, a date or arepository:ending in a line feed is refused by name, and a pin'ssource_repository:that is no path orowner/reponame is named as the pin's (#1139) #1166's threeupdate-shape.pyrows and the two pattern tests), and the S2 row oftests/test_update_shape_merged_away.py. The D1 runs are the doctor guard row alone.restored=yesfor all 21 mutants and for the three swaps of main's or86c1e6ea2's production files). At the end the worktree held the commit's bytes again, also checked by sha256.expandusermoved into_named_hereandpin_source.The review round's mutants:
RuntimeErrorguard removedreturn None)ENAMETOOLONGtest removedOSErrortaken as nothing therePermissionErrorrowrefusals_ahead(the inverse of rv1269's R1, which is the code now)~/notes(both routes each), the two N2 rows, the bare-path rows~/shape, the tilde and long-name rows, named-first, #1166's twoshape currencyrow asks the field and calls a refusal a plain FINDING (exit 1, noenvironment)The first round's mutants, run again:
--upstreamrouteupstream-a-clonerow, checked_value, named-first, apply, the S1, N1, N2 and S2 rows--upstreamrouteno-upstreamrow, #1166's three pin rows, the doctor row, the S1, N1, N2 and S2 rowsfullmatchput back tomatchREPOSITORY_REends in\Zsince #1166, somatchandfullmatchagree on every string (rv1269 checked 66,430)matchandREPOSITORY_RE's\Zput back to$~/notes, both routes; the bare-path and N2 rows~/shapeboth routes, theowner/repoclone where it runschecked_valuedroppedunsafe-valuerowsexpanduser~/notesboth routesno-upstreamrow but~/shape, named-first, the doctor row, #1166's three, the S1, N1, N2 and S2 rowsshape currencycall asks the fieldask_sourcedefaults to FalseRuns
Gates ran on the commit
c792615f4(dirty=0), with a stubghfirst on PATH,GH_TOKENbogus, an emptyGH_CONFIG_DIR, a blank git identity,GIT_SSH_COMMAND=false,GIT_CONFIG_GLOBAL=/dev/null, Python 3.12.3 and git-filter-repo 2.47.0./usr/bin/git):tests/test_update_shape*.pyfiles (this PR's new one among them),tests/test_value_pattern_line_break.py, the hygiene five (test_path_guard_hygiene,test_repo_hygiene,test_agents_md_codes,test_cli_reference,test_pinned_copy_text) andtest_no_auto_maintenance. 1352 passed, 5 skipped in 699s (the first round: 1339; this round adds 12 rows to the new file and 1 totest_update_shape_merged_away.py).shape-doctor.pychanged:test_shape_doctor,test_doctor_unreadable_pin,test_doctor_next_is_a_command,test_doctor_partial_clone,test_doctor_pin_restore_merges,test_shape_pin_files_not_a_list,test_pin_source_env_collisionsandtest_bom_reads. 824 passed, 3 skipped in 1045s.test_update_shape_add_symlink.py:832(junctions are NTFS's), 2test_no_auto_maintenance.py:222(the session began withGIT_CONFIG_GLOBALset) and 3test_shape_doctor.py:10516(the PowerShell line, Windows only).e1692c147and86c1e6ea2: gate A 1339 passed, 5 skipped and gate B 824 passed, 3 skipped, on both gits. A first doctor run on 2.47.1, ate1692c147, had failed three rows oftest_doctor_unreadable_pin.py: their stand-in forpreparetook one argument and the doctor now passesask_source.86c1e6ea2widens the stand-in. rv1269 re-ran both gates at86c1e6ea2with the same counts.86c1e6ea2and the mutants above ran on git 2.43.0.Merges
Run with
git merge-tree --write-tree <other> c792615f4(git 2.43.0) at 2026-11-08T19:34Z, at heads read fresh just before the push. All are clean (exit 0, no conflict line):9252ef208: tree63d3a0e7. Main is eight commits past this branch's basebe21751c3. shape_advisory.py and shape-doctor.py: a leg'sAGENTS.mdthis user cannot read leaves whether it is a leg unknown, sothe way inoffers neither command and points atwhat is here, andthe other way inand the Triad row are silent (#1110) #1159 and shape-doctor.py, validate-pins.py and validate-manifest.py: a root whose own.gitthis user cannot read is named.git: cannot be read (<reason>), so the doctor never reads it as DRIFTED, and both pinned validators refuse it, exit 2 (#1146) #1147 have merged, so they are no longer listed.shape:orfiles:is no block header, as it is none to the reader (#1220) #1231aca00dfd9(update-shape.py):487cf667.applyputs its REFUSED and ROLLED BACK report, and a failed push's account of the commit that stands, on stderr when nobody reads stdout any more, and a broken pipe on acopiedline is rolled back and raised as itself, not calledupdate-write-failed(#1218) #1241ab137eb5f(update-shape.py,tests/test_update_shape_unreadable.py):1fbe57e7.HEADthis user cannot open is named in the gate's words,spec: .git/modules/spec/HEAD: cannot be read (<reason>)orspec/.git/HEAD: ..., so thelegsandmembersrows read INVALID with the gate's line and never DRIFTED, andplacementnever calls the leg "not a git repository" (#1222) #12481b747f7ab:36531a9b..gitthis user cannot read is refusedgit-repo-unreadable, exit 2, not a traceback ornot-a-git-repo, and the doctor'smembersrow names it once, never drift (#1148) #1172ba81fd7d2:e13d0676.Main, #1248 and #1172 touch
shape-doctor.py. None of their added or removed lines inupdate-shape.py,shape-doctor.pyor the tests this PR touches mentionsopen_upstream,pin_path,prepare(,source_repository,WRITE_THE_PIN,REPOSITORY_RE,refusals_ahead,ask_source,pin_source,expanduserorENAMETOOLONG(read fromgit diffagainst each merge base). The rows on the merged tree with current main are left to the landing gate. Lane 3 says the later lander takes the refresh.Limits
source_repository:itself, as on main: where the pin names the standard's commit, its row isok. Naming it on the pin's side would mean teachingpin_restore, whose history walk reads pins withcheck_pin, the same question, and the path half of that question reads the working directory. That is a follow-up candidate, not this PR.open_upstreamdoes for--upstream. Soscripts/repo_shape.pyis refused when run from the root, and taken as anowner/reponame when run from elsewhere. For any one directory, both routes give the same answer.opensoft/openRepoShapewhere the command runs (an unpacked archive, say) refuses the scaffolded pin with--upstreampassed. On main only the run with no--upstreamrefused it. Measured by rv1269 and by this round's rows: the refusal isupdate-upstream-not-a-repoin the pin's name, in both routes, and its remedy now ends by saying to run it from a directory where nothing is at that path. That run answers as the scaffolded pin does (--upstreamroute: exit 1).shape currencyrow, over a hand-edited source and merged-away copies, still namesupdate-shape.py checkas its NEXT, and thatcheckrefuses in the pin's name (exit 2). The row answers as on main by design (the first bullet). Thepinsrow, which states whatcheckreports, asks the field since the review round.--upstream ~<unknown user>/xon the command line is still aRuntimeErrortraceback out ofopen_upstream(measured in process), as on main, and an argv value whose first part is over 255 bytes isupdate-unreadablenaming that path. Both name the value a person passed, not the pin. A follow-up candidate, not this PR.REPOSITORY_REtakes.and..as an owner, so../shapeisowner/repo-shaped. Unchanged.Closes #1203
Lane: openreposhape-5 (openRepoShape-5)
🤖 Generated with Claude Code
Summary by Sourcery
Validate the pin’s source repository consistently and keep shape-doctor reporting compatible with the new refusal behavior.
New Features:
source_repository:consistently before opening the upstream, regardless of whether--upstreamis provided.applyfrom writing changes for them.Bug Fixes:
--upstreamerrors.Enhancements:
Tests: