From 4bdc11ddc97ccf2c7b822e7485bab65f940a69e9 Mon Sep 17 00:00:00 2001 From: Rylan Polster Date: Mon, 25 Jan 2021 23:57:01 -0500 Subject: [PATCH 1/3] tap: fix renamed branches with `brew tap --repair` --- Library/Homebrew/cmd/tap.rb | 1 + Library/Homebrew/extend/git_repository.rb | 23 +++++++++++++++++++++++ Library/Homebrew/tap.rb | 16 ++++++++++++++++ 3 files changed, 40 insertions(+) diff --git a/Library/Homebrew/cmd/tap.rb b/Library/Homebrew/cmd/tap.rb index 2868cabbcb..d352143c7a 100644 --- a/Library/Homebrew/cmd/tap.rb +++ b/Library/Homebrew/cmd/tap.rb @@ -50,6 +50,7 @@ module Homebrew if args.repair? Tap.each(&:link_completions_and_manpages) + Tap.each(&:fix_remote_configuration) elsif args.list_pinned? puts Tap.select(&:pinned?).map(&:name) elsif args.no_named? diff --git a/Library/Homebrew/extend/git_repository.rb b/Library/Homebrew/extend/git_repository.rb index e490e12eee..b5a54742f8 100644 --- a/Library/Homebrew/extend/git_repository.rb +++ b/Library/Homebrew/extend/git_repository.rb @@ -54,6 +54,18 @@ module GitRepositoryExtension popen_git("rev-parse", "--abbrev-ref", "HEAD", safe: safe) end + # Change the name of a local branch + sig { params(old: String, new: String).void } + def git_rename_branch(old:, new:) + popen_git("branch", "-m", old, new) + end + + # Set an upstream branch for a local branch to track + sig { params(local: String, origin: String).void } + def git_branch_set_upstream(local:, origin:) + popen_git("branch", "-u", "origin/#{origin}", local) + end + # Gets the name of the default origin HEAD branch. sig { returns(T.nilable(String)) } def git_origin_branch @@ -72,6 +84,17 @@ module GitRepositoryExtension popen_git("show", "-s", "--format=%cd", "--date=short", "HEAD") end + # Returns true if the given branch exists on origin + sig { params(branch: String).returns(T::Boolean) } + def git_origin_has_branch?(branch) + popen_git("ls-remote", "--heads", "origin", branch).present? + end + + sig { void } + def git_origin_set_head_auto + popen_git("remote", "set-head", "origin", "--auto") + end + # Gets the full commit message of the specified commit, or of the HEAD commit if unspecified. sig { params(commit: String, safe: T::Boolean).returns(T.nilable(String)) } def git_commit_message(commit = "HEAD", safe: false) diff --git a/Library/Homebrew/tap.rb b/Library/Homebrew/tap.rb index 986e35dc13..9a49c29424 100644 --- a/Library/Homebrew/tap.rb +++ b/Library/Homebrew/tap.rb @@ -362,6 +362,22 @@ class Tap end end + def fix_remote_configuration + return unless remote.include? "github.com" + + current_upstream_head = path.git_origin_branch + return if path.git_origin_has_branch? current_upstream_head + + safe_system "git", "-C", path, "fetch", "origin" + path.git_origin_set_head_auto + + new_upstream_head = path.git_origin_branch + path.git_rename_branch old: current_upstream_head, new: new_upstream_head + path.git_branch_set_upstream local: new_upstream_head, origin: new_upstream_head + + ohai "#{name}: changed default branch name from #{current_upstream_head} to #{new_upstream_head}" + end + # Uninstall this {Tap}. def uninstall(manual: false) require "descriptions" From f508f8dc0c246669e2d746bf0ab12e8b2ca36d46 Mon Sep 17 00:00:00 2001 From: Rylan Polster Date: Thu, 28 Jan 2021 01:51:40 -0500 Subject: [PATCH 2/3] update: show message prompting `brew tap --repair` This message is shown when a fetch fails due to a branch rename --- Library/Homebrew/cmd/update-report.rb | 13 +++++++++++++ Library/Homebrew/cmd/update-reset.sh | 2 +- Library/Homebrew/cmd/update.sh | 27 ++++++++++++++++++++++++++- completions/zsh/_brew | 2 +- docs/Manpage.md | 2 +- manpages/brew.1 | 2 +- 6 files changed, 43 insertions(+), 5 deletions(-) diff --git a/Library/Homebrew/cmd/update-report.rb b/Library/Homebrew/cmd/update-report.rb index 61bcb03e1e..ceff93f79b 100644 --- a/Library/Homebrew/cmd/update-report.rb +++ b/Library/Homebrew/cmd/update-report.rb @@ -144,6 +144,19 @@ module Homebrew link_completions_manpages_and_docs Tap.each(&:link_completions_and_manpages) + failed_fetch_dirs = ENV["HOMEBREW_FAILED_FETCH_DIRS"]&.split("\n") + if failed_fetch_dirs.present? + failed_fetch_taps = failed_fetch_dirs.map { |dir| Tap.from_path(dir) } + + puts Formatter.headline "Some taps failed to update!", color: :red + puts <<~EOS + The following taps can not read their remote branches: + #{failed_fetch_taps.join("\n ")} + This may be happening because the remote branch was renamed. + Reset taps to point to the correct remote branches by running `brew tap --repair` + EOS + end + return if new_repository_version.blank? ohai "Homebrew was updated to version #{new_repository_version}" diff --git a/Library/Homebrew/cmd/update-reset.sh b/Library/Homebrew/cmd/update-reset.sh index 5bd5e08924..005fa9b5a1 100644 --- a/Library/Homebrew/cmd/update-reset.sh +++ b/Library/Homebrew/cmd/update-reset.sh @@ -1,6 +1,6 @@ #: * `update-reset` [ ...] #: -#: Fetch and reset Homebrew and all tap repositories (or any specified ) using `git`(1) to their latest `origin/master`. +#: Fetch and reset Homebrew and all tap repositories (or any specified ) using `git`(1) to their latest `origin/HEAD`. #: #: *Note:* this will destroy all your uncommitted or committed changes. diff --git a/Library/Homebrew/cmd/update.sh b/Library/Homebrew/cmd/update.sh index c5b8080c51..295857886e 100644 --- a/Library/Homebrew/cmd/update.sh +++ b/Library/Homebrew/cmd/update.sh @@ -483,7 +483,9 @@ EOS trap '{ /usr/bin/pkill -P $$; wait; exit 130; }' SIGINT local update_failed_file="$HOMEBREW_REPOSITORY/.git/UPDATE_FAILED" + local failed_fetch_dirs_file="$HOMEBREW_REPOSITORY/.git/FAILED_FETCH_DIRS" rm -f "$update_failed_file" + rm -f "$failed_fetch_dirs_file" for DIR in "$HOMEBREW_REPOSITORY" "$HOMEBREW_LIBRARY"/Taps/*/* do @@ -566,23 +568,38 @@ EOS echo "Fetching $DIR..." fi + local tmp_failure_file="$HOMEBREW_REPOSITORY/.git/TMP_FETCH_FAILURES" + rm -f "$tmp_failure_file" + if [[ -n "$HOMEBREW_UPDATE_PREINSTALL" ]] then git fetch --tags --force "${QUIET_ARGS[@]}" origin \ "refs/heads/$UPSTREAM_BRANCH_DIR:refs/remotes/origin/$UPSTREAM_BRANCH_DIR" 2>/dev/null else + # Capture stderr to tmp_failure_file if ! git fetch --tags --force "${QUIET_ARGS[@]}" origin \ - "refs/heads/$UPSTREAM_BRANCH_DIR:refs/remotes/origin/$UPSTREAM_BRANCH_DIR" + "refs/heads/$UPSTREAM_BRANCH_DIR:refs/remotes/origin/$UPSTREAM_BRANCH_DIR" 2>>"$tmp_failure_file" then + # Reprint fetch errors to stderr + [[ -f "$tmp_failure_file" ]] && cat "$tmp_failure_file" 1>&2 + if [[ "$UPSTREAM_SHA_HTTP_CODE" = "404" ]] then TAP="${DIR#$HOMEBREW_LIBRARY/Taps/}" echo "$TAP does not exist! Run \`brew untap $TAP\` to remove it." >>"$update_failed_file" else echo "Fetching $DIR failed!" >>"$update_failed_file" + + if [[ -f "$tmp_failure_file" ]] && + [[ "$(<"$tmp_failure_file")" = "fatal: couldn't find remote ref refs/heads/$UPSTREAM_BRANCH_DIR" ]] + then + echo "$DIR" >>"$failed_fetch_dirs_file" + fi fi fi fi + + rm -f "$tmp_failure_file" ) & done @@ -596,6 +613,13 @@ EOS export HOMEBREW_UPDATE_FAILED="1" fi + if [[ -f "$failed_fetch_dirs_file" ]] + then + HOMEBREW_FAILED_FETCH_DIRS="$(<"$failed_fetch_dirs_file")" + rm -f "$failed_fetch_dirs_file" + export HOMEBREW_FAILED_FETCH_DIRS + fi + for DIR in "$HOMEBREW_REPOSITORY" "$HOMEBREW_LIBRARY"/Taps/*/* do [[ -d "$DIR/.git" ]] || continue @@ -629,6 +653,7 @@ EOS if [[ -n "$HOMEBREW_UPDATED" || -n "$HOMEBREW_UPDATE_FAILED" || + -n "$HOMEBREW_FAILED_FETCH_DIRS" || -n "$HOMEBREW_UPDATE_FORCE" || -d "$HOMEBREW_LIBRARY/LinkedKegs" || ! -f "$HOMEBREW_CACHE/all_commands_list.txt" || diff --git a/completions/zsh/_brew b/completions/zsh/_brew index 27a92adb22..766c32adee 100644 --- a/completions/zsh/_brew +++ b/completions/zsh/_brew @@ -217,7 +217,7 @@ __brew_internal_commands() { 'update-license-data:Update SPDX license data in the Homebrew repository' 'update-python-resources:Update versions for PyPI resource blocks in formula' 'update-report:The Ruby implementation of `brew update`' - 'update-reset:Fetch and reset Homebrew and all tap repositories (or any specified repository) using `git`(1) to their latest `origin/master`' + 'update-reset:Fetch and reset Homebrew and all tap repositories (or any specified repository) using `git`(1) to their latest `origin/HEAD`' 'update-test:Run a test of `brew update` with a new repository clone' 'upgrade:Upgrade outdated casks and outdated, unpinned formulae using the same options they were originally installed with, plus any appended brew formula options' 'uses:Show formulae and casks that specify formula as a dependency; that is, show dependents of formula' diff --git a/docs/Manpage.md b/docs/Manpage.md index fa4072acb4..a596822af1 100644 --- a/docs/Manpage.md +++ b/docs/Manpage.md @@ -607,7 +607,7 @@ Fetch the newest version of Homebrew and all formulae from GitHub using `git`(1) ### `update-reset` [*`repository`* ...] -Fetch and reset Homebrew and all tap repositories (or any specified *`repository`*) using `git`(1) to their latest `origin/master`. +Fetch and reset Homebrew and all tap repositories (or any specified *`repository`*) using `git`(1) to their latest `origin/HEAD`. *Note:* this will destroy all your uncommitted or committed changes. diff --git a/manpages/brew.1 b/manpages/brew.1 index b1c21484ab..d5ec73d453 100644 --- a/manpages/brew.1 +++ b/manpages/brew.1 @@ -812,7 +812,7 @@ Run on auto\-updates (e\.g\. before \fBbrew install\fR)\. Skips some slower step Always do a slower, full update check (even if unnecessary)\. . .SS "\fBupdate\-reset\fR [\fIrepository\fR \.\.\.]" -Fetch and reset Homebrew and all tap repositories (or any specified \fIrepository\fR) using \fBgit\fR(1) to their latest \fBorigin/master\fR\. +Fetch and reset Homebrew and all tap repositories (or any specified \fIrepository\fR) using \fBgit\fR(1) to their latest \fBorigin/HEAD\fR\. . .P \fINote:\fR this will destroy all your uncommitted or committed changes\. From 84fc16c1c1846bcc768a724311c30c7bf98e2cbd Mon Sep 17 00:00:00 2001 From: Rylan Polster Date: Thu, 28 Jan 2021 09:10:07 -0500 Subject: [PATCH 3/3] Apply suggestions from code review Co-Authored-By: Mike McQuaid --- Library/Homebrew/cmd/update-report.rb | 2 +- Library/Homebrew/cmd/update.sh | 14 +++++++------- Library/Homebrew/tap.rb | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Library/Homebrew/cmd/update-report.rb b/Library/Homebrew/cmd/update-report.rb index ceff93f79b..b86f0adecb 100644 --- a/Library/Homebrew/cmd/update-report.rb +++ b/Library/Homebrew/cmd/update-report.rb @@ -152,7 +152,7 @@ module Homebrew puts <<~EOS The following taps can not read their remote branches: #{failed_fetch_taps.join("\n ")} - This may be happening because the remote branch was renamed. + This is happening because the remote branch was renamed or deleted. Reset taps to point to the correct remote branches by running `brew tap --repair` EOS end diff --git a/Library/Homebrew/cmd/update.sh b/Library/Homebrew/cmd/update.sh index 295857886e..92999d7b80 100644 --- a/Library/Homebrew/cmd/update.sh +++ b/Library/Homebrew/cmd/update.sh @@ -483,9 +483,9 @@ EOS trap '{ /usr/bin/pkill -P $$; wait; exit 130; }' SIGINT local update_failed_file="$HOMEBREW_REPOSITORY/.git/UPDATE_FAILED" - local failed_fetch_dirs_file="$HOMEBREW_REPOSITORY/.git/FAILED_FETCH_DIRS" + local missing_remote_ref_dirs_file="$HOMEBREW_REPOSITORY/.git/FAILED_FETCH_DIRS" rm -f "$update_failed_file" - rm -f "$failed_fetch_dirs_file" + rm -f "$missing_remote_ref_dirs_file" for DIR in "$HOMEBREW_REPOSITORY" "$HOMEBREW_LIBRARY"/Taps/*/* do @@ -593,7 +593,7 @@ EOS if [[ -f "$tmp_failure_file" ]] && [[ "$(<"$tmp_failure_file")" = "fatal: couldn't find remote ref refs/heads/$UPSTREAM_BRANCH_DIR" ]] then - echo "$DIR" >>"$failed_fetch_dirs_file" + echo "$DIR" >>"$missing_remote_ref_dirs_file" fi fi fi @@ -613,11 +613,11 @@ EOS export HOMEBREW_UPDATE_FAILED="1" fi - if [[ -f "$failed_fetch_dirs_file" ]] + if [[ -f "$missing_remote_ref_dirs_file" ]] then - HOMEBREW_FAILED_FETCH_DIRS="$(<"$failed_fetch_dirs_file")" - rm -f "$failed_fetch_dirs_file" - export HOMEBREW_FAILED_FETCH_DIRS + HOMEBREW_MISSING_REMOTE_REF_DIRS="$(<"$missing_remote_ref_dirs_file")" + rm -f "$missing_remote_ref_dirs_file" + export HOMEBREW_MISSING_REMOTE_REF_DIRS fi for DIR in "$HOMEBREW_REPOSITORY" "$HOMEBREW_LIBRARY"/Taps/*/* diff --git a/Library/Homebrew/tap.rb b/Library/Homebrew/tap.rb index 9a49c29424..9c1d44cbf1 100644 --- a/Library/Homebrew/tap.rb +++ b/Library/Homebrew/tap.rb @@ -375,7 +375,7 @@ class Tap path.git_rename_branch old: current_upstream_head, new: new_upstream_head path.git_branch_set_upstream local: new_upstream_head, origin: new_upstream_head - ohai "#{name}: changed default branch name from #{current_upstream_head} to #{new_upstream_head}" + ohai "#{name}: changed default branch name from #{current_upstream_head} to #{new_upstream_head}!" end # Uninstall this {Tap}.