Skip to content
Open
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
8 changes: 6 additions & 2 deletions ci.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,8 +268,12 @@ def switch_branch(path, branch):
except CalledProcessError:
cur_branch = check_output('git rev-parse HEAD'.split(), cwd=path).decode().strip()
if cur_branch != branch:
branches = check_output('git ls-remote --heads origin'.split(), cwd=path)
branches = [line.split("/")[-1] for line in branches.decode().strip().split("\n")]
raw_branches = check_output('git ls-remote --heads origin'.split(), cwd=path)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stepping back: git can answer "does this branch exist?" on its own, so none of this listing and splitting is really needed.

if call(f'git ls-remote --heads --exit-code origin refs/heads/{branch}'.split(), cwd=path) == 0:

--exit-code returns 0 if the branch exists and 2 if it doesn't (I checked). That replaces the list, the loop and the in branches test, and there's no text to parse, so the bug this PR fixes can't happen in the first place.

It's also a lot less work: right now we ask the server for the full list of branches once per dependency (13 in .gitmodules), and for a repo like percona/grafana that's thousands of branch names downloaded to check one.

Not blocking — just worth knowing the whole block could go away.

branches = []
for line in raw_branches.decode().strip().split("\n"):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The whitespace check on the next line and the value stored two lines down don't match: the check looks at line.strip(), but what gets appended is the original line. Anything after the branch name comes along for the ride.

>>> line = "def456\trefs/heads/main\r"
>>> bool(line.strip())                    # passes the check below
True
>>> line.split("refs/heads/", 1)[-1]
'main\r'                                 # stored like this, and 'main\r' != 'main'

So the branch is reported as missing even though it's right there — the same wrong outcome this PR is fixing, except a stray \r is invisible in the log, so the name looks correct.

The .strip() on this line doesn't cover it either: it only trims the very start and end of the whole output, so only the last line would be cleaned up.

If stray whitespace is worth guarding against, the stored value needs cleaning too — line.strip().split(...), or use .splitlines() here, which handles Windows-style line endings for you.

if not line.strip():

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Flip side of the comment above: if stray whitespace can't happen, this check isn't needed at all.

.strip() on the previous line has already removed anything around the edges, and git ls-remote doesn't print blank lines in the middle. So this can only trigger for the single empty string you get from completely empty output — and an empty entry couldn't have caused a wrong match anyway, exactly as before this PR.

So it's one or the other: either clean the stored value (comment above), or drop this check plus the raw_branches variable and keep the original one-liner:

branches = [line.split("refs/heads/", 1)[-1] for line in check_output(...).decode().strip().split("\n")]

Right now we pay for the check but don't get the protection.

continue
branches.append(line.split("refs/heads/", 1)[-1])

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[-1] means a line we don't recognise gets stored as if it were a branch name:

>>> "some unexpected output".split("refs/heads/", 1)[-1]
'some unexpected output'

That goes into branches, never matches anything, and the script exits with the same confusing Can' find branch: <name> this PR is trying to get rid of — with nothing pointing at the real cause.

Skipping such lines outright makes it obvious:

if "refs/heads/" not in line:
    continue
branches.append(line.split("refs/heads/", 1)[1])

Worth doing because the output isn't fixed forever: git 2.46 renamed --heads to --branches and now treats --heads as the old spelling.


if branch in branches:
print(f'Switch to branch: {branch} (from {cur_branch})')
Expand Down
Loading