Support enabling auto-updates for non-GitHub taps

This commit is contained in:
Eli Young 2018-04-12 16:14:02 -07:00
parent 50059990e2
commit 8734848829
7 changed files with 79 additions and 7 deletions

View File

@ -1,7 +1,7 @@
#: * `tap`: #: * `tap`:
#: List all installed taps. #: List all installed taps.
#: #:
#: * `tap` [`--full`] <user>`/`<repo> [<URL>]: #: * `tap` [`--full`] [`--force-auto-update`] <user>`/`<repo> [<URL>]:
#: Tap a formula repository. #: Tap a formula repository.
#: #:
#: With <URL> unspecified, taps a formula repository from GitHub using HTTPS. #: With <URL> unspecified, taps a formula repository from GitHub using HTTPS.
@ -18,6 +18,10 @@
#: if `--full` is passed, a full clone will be used. To convert a shallow copy #: if `--full` is passed, a full clone will be used. To convert a shallow copy
#: to a full copy, you can retap passing `--full` without first untapping. #: to a full copy, you can retap passing `--full` without first untapping.
#: #:
#: By default, only taps hosted on GitHub are auto-updated (for performance
#: reasons). If `--force-auto-update` is passed, this tap will be auto-updated
#: even if it is not hosted on GitHub.
#:
#: `tap` is re-runnable and exits successfully if there's nothing to do. #: `tap` is re-runnable and exits successfully if there's nothing to do.
#: However, retapping with a different <URL> will cause an exception, so first #: However, retapping with a different <URL> will cause an exception, so first
#: `untap` if you need to modify the <URL>. #: `untap` if you need to modify the <URL>.
@ -44,6 +48,7 @@ module Homebrew
tap = Tap.fetch(ARGV.named[0]) tap = Tap.fetch(ARGV.named[0])
begin begin
tap.install clone_target: ARGV.named[1], tap.install clone_target: ARGV.named[1],
force_auto_update: force_auto_update?,
full_clone: full_clone?, full_clone: full_clone?,
quiet: ARGV.quieter? quiet: ARGV.quieter?
rescue TapRemoteMismatchError => e rescue TapRemoteMismatchError => e
@ -56,4 +61,9 @@ module Homebrew
def full_clone? def full_clone?
ARGV.include?("--full") || ARGV.homebrew_developer? ARGV.include?("--full") || ARGV.homebrew_developer?
end end
def force_auto_update?
# if no relevant flag is present, return nil, meaning "no change"
true if ARGV.include?("--force-auto-update")
end
end end

View File

@ -493,8 +493,12 @@ EOS
[[ -z "$HOMEBREW_UPDATE_FORCE" ]] && [[ "$UPSTREAM_SHA_HTTP_CODE" = "304" ]] && exit [[ -z "$HOMEBREW_UPDATE_FORCE" ]] && [[ "$UPSTREAM_SHA_HTTP_CODE" = "304" ]] && exit
elif [[ -n "$HOMEBREW_UPDATE_PREINSTALL" ]] elif [[ -n "$HOMEBREW_UPDATE_PREINSTALL" ]]
then then
# Don't try to do a `git fetch` that may take longer than expected. FORCE_AUTO_UPDATE="$(git config homebrew.forceautoupdate 2>/dev/null || echo "false")"
exit if [[ "$FORCE_AUTO_UPDATE" != "true" ]]
then
# Don't try to do a `git fetch` that may take longer than expected.
exit
fi
fi fi
if [[ -n "$HOMEBREW_VERBOSE" ]] if [[ -n "$HOMEBREW_VERBOSE" ]]

View File

@ -201,7 +201,9 @@ class Tap
# install this {Tap}. # install this {Tap}.
# #
# @param [Hash] options # @param [Hash] options
# @option options [String] :clone_targe If passed, it will be used as the clone remote. # @option options [String] :clone_target If passed, it will be used as the clone remote.
# @option options [Boolean, nil] :force_auto_update If present, whether to override the
# logic that skips non-GitHub repositories during auto-updates.
# @option options [Boolean] :full_clone If set as true, full clone will be used. # @option options [Boolean] :full_clone If set as true, full clone will be used.
# @option options [Boolean] :quiet If set, suppress all output. # @option options [Boolean] :quiet If set, suppress all output.
def install(options = {}) def install(options = {})
@ -210,12 +212,14 @@ class Tap
full_clone = options.fetch(:full_clone, false) full_clone = options.fetch(:full_clone, false)
quiet = options.fetch(:quiet, false) quiet = options.fetch(:quiet, false)
requested_remote = options[:clone_target] || default_remote requested_remote = options[:clone_target] || default_remote
# if :force_auto_update is unset, use nil, meaning "no change"
force_auto_update = options.fetch(:force_auto_update, nil)
if official? && DEPRECATED_OFFICIAL_TAPS.include?(repo) if official? && DEPRECATED_OFFICIAL_TAPS.include?(repo)
odie "#{name} was deprecated. This tap is now empty as all its formulae were migrated." odie "#{name} was deprecated. This tap is now empty as all its formulae were migrated."
end end
if installed? if installed? && force_auto_update.nil?
raise TapAlreadyTappedError, name unless full_clone raise TapAlreadyTappedError, name unless full_clone
raise TapAlreadyUnshallowError, name unless shallow? raise TapAlreadyUnshallowError, name unless shallow?
end end
@ -224,6 +228,11 @@ class Tap
Utils.ensure_git_installed! Utils.ensure_git_installed!
if installed? if installed?
unless force_auto_update.nil?
config["forceautoupdate"] = force_auto_update
return if !full_clone || !shallow?
end
if options[:clone_target] && requested_remote != remote if options[:clone_target] && requested_remote != remote
raise TapRemoteMismatchError.new(name, @remote, requested_remote) raise TapRemoteMismatchError.new(name, @remote, requested_remote)
end end
@ -259,6 +268,8 @@ class Tap
raise raise
end end
config["forceautoupdate"] = force_auto_update unless force_auto_update.nil?
link_completions_and_manpages link_completions_and_manpages
formula_count = formula_files.size formula_count = formula_files.size

View File

@ -55,11 +55,26 @@ describe "brew tap", :integration_test do
.and not_to_output.to_stderr .and not_to_output.to_stderr
.and be_a_success .and be_a_success
expect { brew "tap", "--force-auto-update", "homebrew/bar", path/".git" }
.to output(/Tapped/).to_stdout
.and output(/Cloning/).to_stderr
.and be_a_success
expect { brew "untap", "homebrew/bar" }
.to output(/Untapped/).to_stdout
.and not_to_output.to_stderr
.and be_a_success
expect { brew "tap", "homebrew/bar", path/".git", "-q", "--full" } expect { brew "tap", "homebrew/bar", path/".git", "-q", "--full" }
.to be_a_success .to be_a_success
.and not_to_output.to_stdout .and not_to_output.to_stdout
.and not_to_output.to_stderr .and not_to_output.to_stderr
expect { brew "tap", "--force-auto-update", "homebrew/bar" }
.to be_a_success
.and not_to_output.to_stdout
.and not_to_output.to_stderr
expect { brew "untap", "homebrew/bar" } expect { brew "untap", "homebrew/bar" }
.to output(/Untapped/).to_stdout .to output(/Untapped/).to_stdout
.and not_to_output.to_stderr .and not_to_output.to_stderr

View File

@ -209,6 +209,31 @@ describe Tap do
expect { already_tapped_tap.install full_clone: true }.to raise_error(TapAlreadyUnshallowError) expect { already_tapped_tap.install full_clone: true }.to raise_error(TapAlreadyUnshallowError)
end end
describe "force_auto_update" do
before do
setup_git_repo
end
let(:already_tapped_tap) { described_class.new("Homebrew", "foo") }
it "defaults to nil" do
expect(already_tapped_tap).to be_installed
expect(already_tapped_tap.config["forceautoupdate"]).to be_nil
end
it "enables forced auto-updates when true" do
expect(already_tapped_tap).to be_installed
already_tapped_tap.install force_auto_update: true
expect(already_tapped_tap.config["forceautoupdate"]).to eq("true")
end
it "disables forced auto-updates when false" do
expect(already_tapped_tap).to be_installed
already_tapped_tap.install force_auto_update: false
expect(already_tapped_tap.config["forceautoupdate"]).to eq("false")
end
end
specify "Git error" do specify "Git error" do
tap = described_class.new("user", "repo") tap = described_class.new("user", "repo")

View File

@ -448,7 +448,7 @@ With `--verbose` or `-v`, many commands print extra debugging information. Note
* `tap`: * `tap`:
List all installed taps. List all installed taps.
* `tap` [`--full`] `user``/``repo` [`URL`]: * `tap` [`--full`] [`--force-auto-update`] `user``/``repo` [`URL`]:
Tap a formula repository. Tap a formula repository.
With `URL` unspecified, taps a formula repository from GitHub using HTTPS. With `URL` unspecified, taps a formula repository from GitHub using HTTPS.
@ -465,6 +465,10 @@ With `--verbose` or `-v`, many commands print extra debugging information. Note
if `--full` is passed, a full clone will be used. To convert a shallow copy if `--full` is passed, a full clone will be used. To convert a shallow copy
to a full copy, you can retap passing `--full` without first untapping. to a full copy, you can retap passing `--full` without first untapping.
By default, only taps hosted on GitHub are auto-updated (for performance
reasons). If `--force-auto-update` is passed, this tap will be auto-updated
even if it is not hosted on GitHub.
`tap` is re-runnable and exits successfully if there's nothing to do. `tap` is re-runnable and exits successfully if there's nothing to do.
However, retapping with a different `URL` will cause an exception, so first However, retapping with a different `URL` will cause an exception, so first
`untap` if you need to modify the `URL`. `untap` if you need to modify the `URL`.

View File

@ -463,7 +463,7 @@ Symlink all of the specific \fIversion\fR of \fIformula\fR\'s install to Homebre
List all installed taps\. List all installed taps\.
. .
.TP .TP
\fBtap\fR [\fB\-\-full\fR] \fIuser\fR\fB/\fR\fIrepo\fR [\fIURL\fR] \fBtap\fR [\fB\-\-full\fR] [\fB\-\-force\-auto\-update\fR] \fIuser\fR\fB/\fR\fIrepo\fR [\fIURL\fR]
Tap a formula repository\. Tap a formula repository\.
. .
.IP .IP
@ -476,6 +476,9 @@ With \fIURL\fR specified, taps a formula repository from anywhere, using any tra
By default, the repository is cloned as a shallow copy (\fB\-\-depth=1\fR), but if \fB\-\-full\fR is passed, a full clone will be used\. To convert a shallow copy to a full copy, you can retap passing \fB\-\-full\fR without first untapping\. By default, the repository is cloned as a shallow copy (\fB\-\-depth=1\fR), but if \fB\-\-full\fR is passed, a full clone will be used\. To convert a shallow copy to a full copy, you can retap passing \fB\-\-full\fR without first untapping\.
. .
.IP .IP
By default, only taps hosted on GitHub are auto\-updated (for performance reasons)\. If \fB\-\-force\-auto\-update\fR is passed, this tap will be auto\-updated even if it is not hosted on GitHub\.
.
.IP
\fBtap\fR is re\-runnable and exits successfully if there\'s nothing to do\. However, retapping with a different \fIURL\fR will cause an exception, so first \fBuntap\fR if you need to modify the \fIURL\fR\. \fBtap\fR is re\-runnable and exits successfully if there\'s nothing to do\. However, retapping with a different \fIURL\fR will cause an exception, so first \fBuntap\fR if you need to modify the \fIURL\fR\.
. .
.TP .TP