diff options
| author | Mike McQuaid | 2016-02-12 13:25:37 +0000 |
|---|---|---|
| committer | Mike McQuaid | 2016-02-15 08:54:03 +0000 |
| commit | 775c4eedd7f6342ccfe7fe802a5935cb78ab050d (patch) | |
| tree | d79b59ed969608b11d413288d03e21c32f306857 /Library/Homebrew/cmd/update.sh | |
| parent | b389953f5b1b0ec98c069f155c280d60b94eeafb (diff) | |
| download | brew-775c4eedd7f6342ccfe7fe802a5935cb78ab050d.tar.bz2 | |
Promote update-bash to the default updater.
Also, rename the existing updater to `update-ruby` to allow using as
a fallback. It will eventually be removed.
Closes Homebrew/homebrew#49109.
Signed-off-by: Mike McQuaid <mike@mikemcquaid.com>
Diffstat (limited to 'Library/Homebrew/cmd/update.sh')
| -rw-r--r-- | Library/Homebrew/cmd/update.sh | 355 |
1 files changed, 355 insertions, 0 deletions
diff --git a/Library/Homebrew/cmd/update.sh b/Library/Homebrew/cmd/update.sh new file mode 100644 index 000000000..d9226cfb9 --- /dev/null +++ b/Library/Homebrew/cmd/update.sh @@ -0,0 +1,355 @@ +brew() { + "$HOMEBREW_BREW_FILE" "$@" +} + +git() { + [[ -n "$HOMEBREW_GIT" ]] || odie "HOMEBREW_GIT is unset!" + "$HOMEBREW_GIT" "$@" +} + +which_git() { + local git_path + local active_developer_dir + + if [[ -n "$HOMEBREW_GIT" ]] + then + git_path="$HOMEBREW_GIT" + elif [[ -n "$GIT" ]] + then + git_path="$GIT" + else + git_path="git" + fi + + git_path="$(which "$git_path" 2>/dev/null)" + + if [[ -n "$git_path" ]] + then + git_path="$(chdir "${git_path%/*}" && pwd -P)/${git_path##*/}" + fi + + if [[ -n "$HOMEBREW_OSX" && "$git_path" = "/usr/bin/git" ]] + then + active_developer_dir="$('/usr/bin/xcode-select' -print-path 2>/dev/null)" + if [[ -n "$active_developer_dir" && -x "$active_developer_dir/usr/bin/git" ]] + then + git_path="$active_developer_dir/usr/bin/git" + else + git_path="" + fi + fi + echo "$git_path" +} + +git_init_if_necessary() { + set -e + trap '{ rm -rf .git; exit 1; }' EXIT + + if [[ ! -d ".git" ]] + then + git init + git config --bool core.autocrlf false + git config remote.origin.url https://github.com/Homebrew/homebrew.git + git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*" + git fetch origin + git reset --hard origin/master + SKIP_FETCH_HOMEBREW_REPOSITORY=1 + fi + + set +e + trap - EXIT + + if [[ "$(git remote show origin -n)" = *"mxcl/homebrew"* ]] + then + git remote set-url origin https://github.com/Homebrew/homebrew.git && + git remote set-url --delete origin ".*mxcl\/homebrew.*" + fi +} + +rename_taps_dir_if_necessary() { + local tap_dir + local tap_dir_basename + local user + local repo + + for tap_dir in "$HOMEBREW_LIBRARY"/Taps/* + do + [[ -d "$tap_dir/.git" ]] || continue + tap_dir_basename="${tap_dir##*/}" + if [[ "$tap_dir_basename" = *"-"* ]] + then + # only replace the *last* dash: yes, tap filenames suck + user="$(echo "${tap_dir_basename%-*}" | tr "[:upper:]" "[:lower:]")" + repo="$(echo "${tap_dir_basename:${#user}+1}" | tr "[:upper:]" "[:lower:]")" + mkdir -p "$HOMEBREW_LIBRARY/Taps/$user" + mv "$tap_dir", "$HOMEBREW_LIBRARY/Taps/$user/homebrew-$repo" + + if [[ ${#${tap_dir_basename//[^\-]}} -gt 1 ]] + then + echo "Homebrew changed the structure of Taps like <someuser>/<sometap>." >&2 + echo "So you may need to rename $HOMEBREW_LIBRARY/Taps/$user/homebrew-$repo manually." >&2 + fi + else + echo "Homebrew changed the structure of Taps like <someuser>/<sometap>. " >&2 + echo "$tap_dir is an incorrect Tap path." >&2 + echo "So you may need to rename it to $HOMEBREW_LIBRARY/Taps/<someuser>/homebrew-<sometap> manually." >&2 + fi + done +} + +repo_var() { + local repo_var + + repo_var="$1" + if [[ "$repo_var" = "$HOMEBREW_REPOSITORY" ]] + then + repo_var="" + else + repo_var="${repo_var#"$HOMEBREW_LIBRARY/Taps"}" + repo_var="$(echo -n "$repo_var" | tr -C "A-Za-z0-9" "_" | tr "[:lower:]" "[:upper:]")" + fi + echo "$repo_var" +} + +upstream_branch() { + local upstream_branch + + upstream_branch="$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null)" + upstream_branch="${upstream_branch#refs/remotes/origin/}" + [[ -z "$upstream_branch" ]] && upstream_branch="master" + echo "$upstream_branch" +} + +read_current_revision() { + git rev-parse -q --verify HEAD +} + +pop_stash() { + [[ -z "$STASHED" ]] && return + git stash pop "${QUIET_ARGS[@]}" + if [[ -n "$HOMEBREW_VERBOSE" ]] + then + echo "Restoring your stashed changes to $DIR:" + git status --short --untracked-files + fi + unset STASHED +} + +pop_stash_message() { + [[ -z "$STASHED" ]] && return + echo "To restore the stashed changes to $DIR run:" + echo " 'cd $DIR && git stash pop'" + unset STASHED +} + +reset_on_interrupt() { + if [[ "$INITIAL_BRANCH" != "$UPSTREAM_BRANCH" && -n "$INITIAL_BRANCH" ]] + then + git checkout "$INITIAL_BRANCH" + fi + + if [[ -n "$INITIAL_REVISION" ]] + then + git reset --hard "$INITIAL_REVISION" "${QUIET_ARGS[@]}" + fi + + if [[ "$INITIAL_BRANCH" != "$UPSTREAM_BRANCH" && -n "$INITIAL_BRANCH" ]] + then + pop_stash + else + pop_stash_message + fi + + exit 130 +} + +pull() { + local DIR + local TAP_VAR + + DIR="$1" + cd "$DIR" || return + TAP_VAR=$(repo_var "$DIR") + unset STASHED + + # The upstream repository's default branch may not be master; + # check refs/remotes/origin/HEAD to see what the default + # origin branch name is, and use that. If not set, fall back to "master". + INITIAL_BRANCH="$(git symbolic-ref --short HEAD 2>/dev/null)" + UPSTREAM_BRANCH="$(upstream_branch)" + + # Used for testing purposes, e.g., for testing formula migration after + # renaming it in the currently checked-out branch. To test run + # "brew update --simulate-from-current-branch" + if [[ -n "$HOMEBREW_SIMULATE_FROM_CURRENT_BRANCH" ]] + then + INITIAL_REVISION="$(git rev-parse -q --verify "$UPSTREAM_BRANCH")" + CURRENT_REVISION="$(read_current_revision)" + export HOMEBREW_UPDATE_BEFORE"$TAP_VAR"="$INITIAL_REVISION" + export HOMEBREW_UPDATE_AFTER"$TAP_VAR"="$CURRENT_REVISION" + if ! git merge-base --is-ancestor "$INITIAL_REVISION" "$CURRENT_REVISION" + then + odie "Your $DIR HEAD is not a descendant of $UPSTREAM_BRANCH!" + fi + return + fi + + trap reset_on_interrupt SIGINT + + if [[ -n "$(git status --untracked-files=all --porcelain 2>/dev/null)" ]] + then + if [[ -n "$HOMEBREW_VERBOSE" ]] + then + echo "Stashing uncommitted changes to $DIR." + git status --short --untracked-files=all + fi + git -c "user.email=brew-update@localhost" \ + -c "user.name=brew update" \ + stash save --include-untracked "${QUIET_ARGS[@]}" + git reset --hard "${QUIET_ARGS[@]}" + STASHED="1" + fi + + if [[ "$INITIAL_BRANCH" != "$UPSTREAM_BRANCH" && -n "$INITIAL_BRANCH" ]] + then + # Recreate and check out `#{upstream_branch}` if unable to fast-forward + # it to `origin/#{@upstream_branch}`. Otherwise, just check it out. + if git merge-base --is-ancestor "$UPSTREAM_BRANCH" "origin/$UPSTREAM_BRANCH" &>/dev/null + then + git checkout --force "$UPSTREAM_BRANCH" "${QUIET_ARGS[@]}" + else + git checkout --force -B "$UPSTREAM_BRANCH" "origin/$UPSTREAM_BRANCH" "${QUIET_ARGS[@]}" + fi + fi + + INITIAL_REVISION="$(read_current_revision)" + export HOMEBREW_UPDATE_BEFORE"$TAP_VAR"="$INITIAL_REVISION" + + # ensure we don't munge line endings on checkout + git config core.autocrlf false + + if [[ -n "$HOMEBREW_REBASE" ]] + then + git rebase "${QUIET_ARGS[@]}" "origin/$UPSTREAM_BRANCH" + else + git merge --no-edit --ff "${QUIET_ARGS[@]}" "origin/$UPSTREAM_BRANCH" + fi + + export HOMEBREW_UPDATE_AFTER"$TAP_VAR"="$(read_current_revision)" + + trap '' SIGINT + + if [[ "$INITIAL_BRANCH" != "$UPSTREAM_BRANCH" && -n "$INITIAL_BRANCH" ]] + then + git checkout "$INITIAL_BRANCH" "${QUIET_ARGS[@]}" + pop_stash + else + pop_stash_message + fi + + trap - SIGINT +} + +homebrew-update() { + local option + local DIR + local UPSTREAM_BRANCH + + for option in "$@" + do + case "$option" in + --help) brew update --help; exit $? ;; + --verbose) HOMEBREW_VERBOSE=1 ;; + --debug) HOMEBREW_DEBUG=1;; + --rebase) HOMEBREW_REBASE=1 ;; + --simulate-from-current-branch) HOMEBREW_SIMULATE_FROM_CURRENT_BRANCH=1 ;; + --*) ;; + -*) + [[ "$option" = *v* ]] && HOMEBREW_VERBOSE=1; + [[ "$option" = *d* ]] && HOMEBREW_DEBUG=1; + ;; + *) + odie <<-EOS +This command updates brew itself, and does not take formula names. +Use 'brew upgrade <formula>'. +EOS + ;; + esac + done + + if [[ -n "$HOMEBREW_DEBUG" ]] + then + set -x + fi + + # check permissions + if [[ "$HOMEBREW_PREFIX" = "/usr/local" && ! -w /usr/local ]] + then + odie "/usr/local must be writable!" + fi + + if [[ ! -w "$HOMEBREW_REPOSITORY" ]] + then + odie "$HOMEBREW_REPOSITORY must be writable!" + fi + + HOMEBREW_GIT="$(which_git)" + if [[ -z "$HOMEBREW_GIT" ]] + then + brew install git + HOMEBREW_GIT="$(which_git)" + if [[ -z "$HOMEBREW_GIT" ]] + then + odie "Git must be installed and in your PATH!" + fi + fi + export GIT_TERMINAL_PROMPT="0" + export GIT_ASKPASS="false" + export GIT_SSH_COMMAND="ssh -oBatchMode=yes" + + if [[ -z "$HOMEBREW_VERBOSE" ]] + then + QUIET_ARGS=(-q) + else + QUIET_ARGS=() + fi + + # ensure GIT_CONFIG is unset as we need to operate on .git/config + unset GIT_CONFIG + + chdir "$HOMEBREW_REPOSITORY" + git_init_if_necessary + # rename Taps directories + # this procedure will be removed in the future if it seems unnecessary + rename_taps_dir_if_necessary + + # kill all of subprocess on interrupt + trap '{ pkill -P $$; wait; exit 130; }' SIGINT + + for DIR in "$HOMEBREW_REPOSITORY" "$HOMEBREW_LIBRARY"/Taps/*/* + do + [[ -d "$DIR/.git" ]] || continue + [[ -n "$SKIP_FETCH_HOMEBREW_REPOSITORY" && "$DIR" = "$HOMEBREW_REPOSITORY" ]] && continue + cd "$DIR" || continue + UPSTREAM_BRANCH="$(upstream_branch)" + # the refspec ensures that the default upstream branch gets updated + ( + git fetch "${QUIET_ARGS[@]}" origin \ + "refs/heads/$UPSTREAM_BRANCH:refs/remotes/origin/$UPSTREAM_BRANCH" || \ + odie "Fetching $DIR failed!" + ) & + done + + wait + trap - SIGINT + + for DIR in "$HOMEBREW_REPOSITORY" "$HOMEBREW_LIBRARY"/Taps/*/* + do + [[ -d "$DIR/.git" ]] || continue + pull "$DIR" + done + + chdir "$HOMEBREW_REPOSITORY" + brew update-report "$@" + return $? +} |
