Skip to content

openRepoShape, setup.sh and install.sh: under the C locale a $OPENREPOSHAPE_REPO URL or path, or a ref, with a letter past ASCII is refused as "a control character", so --version, --install and --preflight refuse what v1.1.0 ran #940

Closed

Description

@brettheap

Goal: under the C locale (and POSIX) the launcher, setup.sh and install.sh take a repository URL or path, or a ref, that holds a letter past ASCII (/srv/café/openRepoShape.git) the way they take it under C.UTF-8, and still refuse every control character. One rule, #760's byte rule, in every place that asks, so the three scripts and the package agree.

Filed by lane openRepoShape-2 on Brett Heap's word ("file all", 2026-10-18T14:45:31Z).

Lands on: main at 50178305, the v1.1.1 release commit. Every path:line below is read there. None of the six open PRs touches openRepoShape, setup.sh, install.sh, src/openreposhape/ or their test files (the coordinator's check, 2026-10-18T14:48Z).

Lines

  • The launcher's checked_repo refuses a URL or path with a letter past ASCII under C, and says it "carries a control character".
  • The launcher's ref_character_fault does the same to a ref.
    • The line is openRepoShape:915-917: *[![:print:]]*) printf '%s' "$what carries a control character, which is not a branch, tag or commit this tool will pass to `git checkout`." ;;. refuse_bad_values calls it at :1000, and ref_fault at :889. A ref with a letter past ASCII is no control character, and git takes one (git check-ref-format --branch café exits 0, measured).
    • Measured with OPENREPOSHAPE_REF set to café (63 61 66 C3 A9) and an ASCII local repository:
      • under C, --version, a scaffold run, --install (with and without OPENREPOSHAPE_RECORD_REF=1) and --doctor each exit 2 with $OPENREPOSHAPE_REF carries a control character, ..., and no request is sent;
      • under C.UTF-8, --version prints it (exit 0), a scaffold run sends 2 requests, and --install without the record installs;
      • under C.UTF-8, --install with the record and --doctor exit 2 with ref_fault's shape refusal, $OPENREPOSHAPE_REF is 'café', which is not a branch, tag or commit ...: a ref starts with an ASCII letter or digit, uses only ASCII letters, ....
    • So for a ref the outcome differs for the runs that never ask the shape (--version, a scaffold run, --install without the record), and the words are wrong for the rest.
  • setup.sh's two guards refuse the same under C, and the launcher passes the value to setup.sh as it was typed.
    • Guard 1, setup.sh:207-210: -*|*[![:print:]]* on $SHAPE_REPO, which is $OPENREPOSHAPE_REPO (or the default). The launcher exports the clone URL it made as $OPENREPOSHAPE_REPO (openRepoShape:1360), so a value the launcher passes still meets this guard.
    • Guard 2, setup.sh:242-245: *[![:print:]]* on $SHAPE_REF, which is the --shape-ref argument and not $OPENREPOSHAPE_REF. It runs after the length check and before the shape case.
    • Both run only on the self-bootstrap path, after is_shape_checkout found no checkout (:114-119). README.md:348-350's curl ... setup.sh | bash -s -- is that path with no launcher.
    • Measured with a setup.sh outside any checkout, --preflight, a stub gh:
      • OPENREPOSHAPE_REPO = the café path, under C: exit 2, OPENREPOSHAPE_REPO is not a value this tool will put on a `git clone` command line: it starts with '-' or carries a control character. .... Under C.UTF-8: the clone was made and the preflight ran (exit 1 here, the stub gh is not logged in).
      • --shape-ref café with an ASCII repository, under C: exit 2, --shape-ref carries a control character, .... Under C.UTF-8: exit 2, --shape-ref is 'café', which is not a branch, tag or commit ...: ... uses only ASCII letters .... Both refuse; only the words differ.
      • The launcher and setup.sh together, LC_ALL=C, the café path, --preflight with a local setup.sh outside any checkout: both as they are at 50178305, exit 2 from the launcher; the launcher moved and setup.sh as it is, exit 2 from setup.sh:208; both moved, the clone was made and the preflight ran. So the launcher and setup.sh move in one change.
  • install.sh refuses the same under C, in the same wrong words, and it has two more uses of the same class.
    • checked_repo, install.sh:136-138: *[![:print:]]* before the owner/name checks. An owner/name on github.com is ASCII (:139-145 refuse anything else), so café is refused under both locales: $OPENREPOSHAPE_REPO carries a control character; it must be an owner/name ... under C, $OPENREPOSHAPE_REPO is '...', which is not an owner/name on github.com ... under C.UTF-8 (measured, exit 2, no request, for the café path and for acme/café). Only the words differ.
    • checked_version, :172-174 (café as the version: the version carries a control character ... under C, the shape refusal under C.UTF-8), and the option check, :453-455 (-café: an option carries a control character ... under C, unknown option '-café' ... under C.UTF-8). All exit 2 with no request, in both locales.
    • :226, which decides whether a redirect's location is named in a fault, is the same class and is left to the writer.
  • The package's openRepoShape --version prints the same path under C with exit 0, so the two --version commands disagree.

What is checked today

The fix, and what it costs

Direction

  • Move together, in one change: checked_repo (openRepoShape:811-813), ref_character_fault (:915-917), setup.sh's guards (:207-210, :242-245), and install.sh's checked_repo (:136-138), checked_version (:172-174) and option check (:453-455), to the rule above. misdrawn_characters stays first where it is. No refusal's words change: "carries a control character" is then true of what it names.
  • Keep setup.sh as it is otherwise. It gets no misdrawn_characters here: the rule puts C where C.UTF-8 is (above). Whether setup.sh should refuse install.sh and openRepoShape: a $OPENREPOSHAPE_BIN_DIR holding a bidi override, U+200B, U+2028 or U+FEFF passes #804's control-character check and is echoed as typed, so the PATH note can show a directory as another #837's characters is the writer's call to note under "Not changed", or to file.
  • Reword what says the repository and ref are held to [![:print:]]: openRepoShape:605-608, :797-801 and :866-871, install.sh:128-130 and :477-479, and the docstring at tests/test_openreposhape_command.py:2401-2406.
  • Decide the lone 9B as above, and write it into the comment where the rule is, as :632-634 does.

Verify

  • tests/test_openreposhape_command.py, tests/test_setup_sh.py and tests/test_install_sh.py pass on Linux.
  • New cases, one table in tests/conftest.py read by all three files, as setup.sh, install.sh and the openRepoShape command: each keeps its own copy of the old ref rule (*..* | *.lock), so a ref git refuses part by part (a.lock/b, a/.b, a//b) clones the standard before it fails #874's REF_PARTS is, so the three agree:
    • café (a path, a URL and an scp address for the repository, and a ref) under C and C.UTF-8, in each place: the launcher's --version, a scaffold run (the fake gh and curl are asked, as under C.UTF-8), --install from a file, --doctor (a fake git sees the clone) and --preflight; setup.sh's two guards; install.sh's three checks (refused, in the words C.UTF-8 gives);
    • every control still refused in both locales, in each place: an escape, U+009B, DEL, TAB, U+0085, U+0080, U+009F and a trailing newline, and a leading - for both repository guards. setup.sh and install.sh hold none of these but a newline today;
    • U+202E and U+200B refused by code point under C;
    • the lone 9B and the lone E9 pass in both locales, which pins the decision;
    • a lone E9 then U+009B is refused, as C1_BIN_DIRS has it.
  • Mutants: each arm of the rule dropped from each place, as above: all killed, the seven that survive today included.
  • A clean pair still prints openRepoShape (opensoft/openRepoShape @ main).

Overlaps

Parent: #459: the launcher's own items went there, such as #649's machine: block and drive-letter lines, and setup.sh and install.sh are its subject.

Milestone: v1.2.0. v1.1.1 is released, and lane 3 places issues. It needs a value a person set in their own environment: a URL or path with a letter past ASCII, in a shell at C or POSIX. It is a change from v1.1.0 (above), but the usual owner/name is untouched, the outcome is right for every control character, and --doctor's clone and setup.sh refused this value long before. #872 (lane 2's, in v1.1.1) made the change, so lane 3 may place this as a v1.1.x back-port (#850) instead.

🤖 Generated with Claude Code

Activity

  1. added this to the v1.2.0 milestone on Oct 18, 2026
  2. added a commit that references this issue on Oct 18, 2026
  3. brettheap commented on Oct 18, 2026

    @brettheap
    ContributorAuthor

    CLAIMED — lane openRepoShape-2, session 81650e29-c906-4fe8-96c9-55580bfe0c44@Eagle, 2026-10-18T17:38:56Z, for #940

    Logged in lanes/log/openRepoShape-2.md at d252426f0b31dca8fd2e1cc5e23abc65741fa344.

    The three reads (lane-collision-protocol Rule 1):

    1. existing `CLAIMED —` comments on opensoft/openRepoShape#940:
       none
    2. `gh pr list --repo opensoft/openRepoShape --state all --search "#940"`, kept where the row or its body names `#940`:
    947	standard.py: the package's `openRepoShape` refuses a repository or ref holding U+202E, U+200B or another character the launcher refuses, by code point, before `--version` or any `git` call names it, and refuses `a.lock/b`, `a/.b`, `a//b`, `a/b/` and `a.` before it clones, in the launcher's words (#939, #941)	l3-939-941-package-standard	OPEN
    3. `git ls-remote --heads git@github.com:opensoft/openRepoShape` branches naming `940` as a whole token:
       none
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions