Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ that ship together already are.

```sh
python3 scripts/family.py init --org <org> --family <Name> --into .. [--reuse-empty-repo]
git -C <path> switch -c family/add-<project> # a branch first: see 3
git -C <path> switch -c family/add-<Project> # a branch first: see 3
python3 scripts/family.py add --family-root <path> --member <org>/<Project>
python3 scripts/family.py bump --family-root <path> --member <Project> --to <sha>
python3 scripts/family.py siblings --family-root <path>
Expand Down
43 changes: 35 additions & 8 deletions scripts/family.py
Original file line number Diff line number Diff line change
Expand Up @@ -710,21 +710,44 @@ def _switch_command(root: Path, branch: str) -> str:
return shell_line(["git", "-C", root, "switch", "-c", branch])


#: What every remedy that names `_switch_command` says next (#607): where an
#: earlier act left that branch, `switch -c` fails `fatal: a branch named
#: '<branch>' already exists` (exit 128). ANOTHER NAME COMES FIRST, because a
#: new branch starts where the holder stands now, which works in every
#: state. Going back to the old branch is right only where it holds work not
#: merged yet: one left behind a main that has moved on makes the act collide
#: with what main took in since, or find its member already there, and a
#: commit made on a detached HEAD is left behind by any `git switch <branch>`.
#: `git switch` keeps the branch's commits and refuses to overwrite a changed
#: file; nothing here names `switch -C`, which resets the branch.
#: IN WORDS, NOT A SECOND COMMAND: no one line works in both states in every
#: shell this file quotes for (PowerShell 5.1 has no `||`), and README lists
#: the kinds of line printed for PowerShell. The holder's
#: `validate-family.py` says the same words.
BRANCH_LEFT = ("If `git switch -c` says that branch already exists, an "
"earlier act left it: give the branch another name, which "
"starts it where the holder stands, or, only if that branch "
"holds work not merged yet, the same command with `switch` "
"in place of `switch -c` goes back to it and keeps every "
"commit on it.")


def _checked_branch(family: "Family", verb: str, suggested: str) -> str:
"""The branch `verb`'s ONE commit lands on: the one the holder stands
on, refused when that is the holder's tracking branch or there is none
(#487). Asked by the real run, after the refusals about the arguments
and the holder and before the member is read or anything is written;
`--dry-run` asks `_branch_said` instead."""
`--dry-run` asks `_branch_said` instead. The remedy's `switch -c` is
followed by `BRANCH_LEFT`, for a holder that has the branch (#607)."""
branch = _holder_branch(family.root)
if branch is not None and branch != family.tracking():
return branch
remedy = ("Remediation: these organisations are pull-request only, so "
"make a branch for the change and run the same command "
f"again:\n {_switch_command(family.root, suggested)}\n"
"then push that branch and open a pull request, as the NEXT "
"line the command ends with says. `--dry-run` runs on any "
"branch.")
f"{BRANCH_LEFT}\nThen push that branch and open a pull "
"request, as the NEXT line the command ends with says. "
"`--dry-run` runs on any branch.")
if branch is None:
raise Refusal(
"family-holder-detached",
Expand All @@ -743,7 +766,8 @@ def _checked_branch(family: "Family", verb: str, suggested: str) -> str:
def _branch_said(family: "Family", verb: str, suggested: str) -> list[str]:
"""The `branch` line a dry run prints (#487): where the real run's
commit lands, or that the real run refuses here, by its code, and the
command that makes a branch, on a line of its own."""
command that makes a branch, on a line of its own, then `BRANCH_LEFT`
as the real run's remedy says it (#607)."""
branch = _holder_branch(family.root)
tracking = family.tracking()
if branch is not None and branch != tracking:
Expand All @@ -755,7 +779,8 @@ def _branch_said(family: "Family", verb: str, suggested: str) -> list[str]:
f"{branch} is the holder's tracking branch"))
return [f"branch {where}, where a real {verb} refuses ({code}); "
"make a branch first:",
f" {_switch_command(family.root, suggested)}"]
f" {_switch_command(family.root, suggested)}",
f" {BRANCH_LEFT}"]


# ---------------------------------------------------------------------------
Expand Down Expand Up @@ -1862,7 +1887,9 @@ def _print_next_steps(args, work: Path, folder: Path | None) -> None:

Split from `cmd_init` for #136. A BRANCH FIRST (#487): the holder stands
on its tracking branch, where `add` refuses to commit, so the block
opens with the `git switch -c` that makes the branch `add` suggests.
opens with the `git switch -c` that makes a branch for it. Its member
is `<Project>`, the one placeholder the `--member` under it says
(#607); `add`'s own refusal names the branch lowercased.

ONE COMMAND A LINE, `cd` apart from `make siblings`: Windows PowerShell
5.1, the shell `setup-project.py` documents, rejects `&&` between two
Expand All @@ -1888,7 +1915,7 @@ def _print_next_steps(args, work: Path, folder: Path | None) -> None:
print(f"""
NEXT STEPS

{switch} family/add-<project>
{switch} family/add-<Project>
{_add_command(work, args.org)}
cd {shell_quoted(work)}
make siblings
Expand Down
2 changes: 1 addition & 1 deletion templates/family-root/AGENTS-shape.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Run openRepoShape's `scripts/family.py` FROM a checkout of the standard,
against this holder:

```sh
git -C <path> switch -c family/add-<project> # a branch first: see below
git -C <path> switch -c family/add-<Project> # a branch first: see below
python3 scripts/family.py add --family-root <path> --member <org>/<Project>
python3 scripts/family.py bump --family-root <path> --member <Project> --to <40 hex> \
--trailer "Lane: <name>" --trailer "Co-Authored-By: <who>"
Expand Down
2 changes: 1 addition & 1 deletion templates/family-root/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ project the row claims and not merely a repository at the right commit.
From a checkout of `{{SHAPE_REPOSITORY}}`:

```sh
git -C <path> switch -c family/add-<project>
git -C <path> switch -c family/add-<Project>
python3 scripts/family.py add --family-root <path> --member {{ORG}}/<Project>
python3 scripts/family.py bump --family-root <path> --member <Project> --to <40 hex>
python3 scripts/family.py remove --family-root <path> --member <Project>
Expand Down
28 changes: 24 additions & 4 deletions templates/family-root/scripts/validate-family.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,23 @@
#: and in `--member` alike (#539).
PROJECT_PLACEHOLDER = "<Project>"

#: What a remedy that names `_switch_line` says at the end of its prose
#: (#607): where an earlier act left that branch, `switch -c` fails `fatal: a
#: branch named '<branch>' already exists` (exit 128). Another name comes
#: first: it starts the branch where the holder stands now, which works in
#: every state. The same command with `switch` for `switch -c` goes back to
#: the old branch, which is right only where it holds work not merged yet;
#: it keeps its commits, and nothing here names `switch -C`, which resets it.
#: In words, not a second command: this report is read in CI too, where the
#: checkout has none of the person's branches to ask about. `family.py`'s
#: `BRANCH_LEFT`, word for word.
BRANCH_LEFT = ("If `git switch -c` says that branch already exists, an "
"earlier act left it: give the branch another name, which "
"starts it where the holder stands, or, only if that branch "
"holds work not merged yet, the same command with `switch` "
"in place of `switch -c` goes back to it and keeps every "
"commit on it.")


def _switch_line(root: Path, verb: str, name: str | None) -> str:
"""`git -C <holder> switch -c family/<verb>-<member>`: the branch
Expand All @@ -129,7 +146,9 @@ def _switch_line(root: Path, verb: str, name: str | None) -> str:
`name` is the member's row `id:` for `remove` and its project for
`add`, lowercased; None says `PROJECT_PLACEHOLDER`, the one the
`--member` beside it says. POSIX-quoted, as every other line this file
prints is."""
prints is. Every remedy that names it ends its prose with `BRANCH_LEFT`
(#607); openRepoShape's own tests read this file's source and fail one
that does not."""
if name is None:
return (f"git -C {shlex.quote(str(root))} switch -c "
f"family/{verb}-{PROJECT_PLACEHOLDER}")
Expand Down Expand Up @@ -401,7 +420,7 @@ def _check_member_gitlink(root: Path, path: str, commit: str, project: str,
"command below mounts and pins it in one commit, on a branch "
"other than the holder's tracking branch, which it refuses, so "
"the first makes one; a row with no submodule is a claim about a "
"tree that is not here.\n"
f"tree that is not here. {BRANCH_LEFT}\n"
f" {_switch_line(root, 'add', project)}\n"
f" {PYTHON} scripts/family.py add --family-root "
f"{shlex.quote(str(root))} --member <org>/{shlex.quote(project)}")
Expand Down Expand Up @@ -784,7 +803,7 @@ def _check_member_ids_unique(root: Path, members: list,
f"`{PYTHON} scripts/family.py remove "
f"--family-root {shlex.quote(str(root))} --member "
f"{shlex.quote(project)}` takes the later row, {project}, out; "
f"name {first} there instead to keep {project}.")
f"name {first} there instead to keep {project}. {BRANCH_LEFT}")


def _gitmodules_sections(root: Path) -> dict[str, dict[str, str]]:
Expand Down Expand Up @@ -1122,7 +1141,8 @@ def _check_gitlinks_named(root: Path, gitlinks: dict[str, str],
f"{GITMODULES} section out too, then mount it with the third, "
"from a checkout of openRepoShape: family.py add writes its row "
"and its gitlink in one commit, and names the object store git "
"rm leaves under .git/modules if one is still there.\n"
"rm leaves under .git/modules if one is still there. "
f"{BRANCH_LEFT}\n"
f" {_switch_line(root, 'add', project)}\n"
f" git rm -- {shlex.quote(path)}\n"
f" {PYTHON} scripts/family.py add --family-root "
Expand Down
Loading
Loading