diff options
| author | ilovezfs | 2016-04-04 03:18:55 -0700 |
|---|---|---|
| committer | ilovezfs | 2016-04-05 07:25:27 -0700 |
| commit | fad235d8e82ae57b2004429a0297f313aafa3186 (patch) | |
| tree | 02b3a8bfbfa5c0ae7deafc0b70fdb52c6bff0b6e | |
| parent | 1b7e13df4f936dd318a23698b7b69bd2ca0e2487 (diff) | |
| download | brew-fad235d8e82ae57b2004429a0297f313aafa3186.tar.bz2 | |
tap: support --full even if installed
Makes `tap` re-runnable and unshallows when requested with `--full`.
Tapping with a different URL raises an exception.
The homebrew/core tap cannot be untapped with `untap` so running
`brew tap --full homebrew/core` is now a built-in way to get a full
clone of this tap without resorting to workarounds.
Closes #17.
Signed-off-by: ilovezfs <ilovezfs@icloud.com>
| -rw-r--r-- | Library/Homebrew/cmd/tap.rb | 6 | ||||
| -rw-r--r-- | Library/Homebrew/exceptions.rb | 29 | ||||
| -rw-r--r-- | Library/Homebrew/manpages/brew.1.md | 7 | ||||
| -rw-r--r-- | Library/Homebrew/tap.rb | 31 | ||||
| -rw-r--r-- | Library/Homebrew/test/test_tap.rb | 27 | ||||
| -rw-r--r-- | share/doc/homebrew/brew.1.html | 7 | ||||
| -rw-r--r-- | share/man/man1/brew.1 | 5 |
7 files changed, 101 insertions, 11 deletions
diff --git a/Library/Homebrew/cmd/tap.rb b/Library/Homebrew/cmd/tap.rb index 079365336..1bd378d69 100644 --- a/Library/Homebrew/cmd/tap.rb +++ b/Library/Homebrew/cmd/tap.rb @@ -17,8 +17,10 @@ module Homebrew tap.install :clone_target => ARGV.named[1], :full_clone => ARGV.include?("--full"), :quiet => ARGV.quieter? - rescue TapAlreadyTappedError => e - opoo e + rescue TapRemoteMismatchError => e + odie e + rescue TapAlreadyTappedError, TapAlreadyUnshallowError + # Do nothing. end end end diff --git a/Library/Homebrew/exceptions.rb b/Library/Homebrew/exceptions.rb index 79cfac012..dfd60549d 100644 --- a/Library/Homebrew/exceptions.rb +++ b/Library/Homebrew/exceptions.rb @@ -119,6 +119,23 @@ class TapUnavailableError < RuntimeError end end +class TapRemoteMismatchError < RuntimeError + attr_reader :name + attr_reader :expected_remote + attr_reader :actual_remote + + def initialize(name, expected_remote, actual_remote) + @name = name + @expected_remote = expected_remote + @actual_remote = actual_remote + + super <<-EOS.undent + Tap #{name} remote mismatch. + #{expected_remote} != #{actual_remote} + EOS + end +end + class TapAlreadyTappedError < RuntimeError attr_reader :name @@ -131,6 +148,18 @@ class TapAlreadyTappedError < RuntimeError end end +class TapAlreadyUnshallowError < RuntimeError + attr_reader :name + + def initialize(name) + @name = name + + super <<-EOS.undent + Tap #{name} already a full clone. + EOS + end +end + class TapPinStatusError < RuntimeError attr_reader :name, :pinned diff --git a/Library/Homebrew/manpages/brew.1.md b/Library/Homebrew/manpages/brew.1.md index 4863bcd5d..47b0517ef 100644 --- a/Library/Homebrew/manpages/brew.1.md +++ b/Library/Homebrew/manpages/brew.1.md @@ -394,7 +394,12 @@ With `--verbose` or `-v`, many commands print extra debugging information. Note using protocols other than HTTPS, e.g., SSH, GIT, HTTP, FTP(S), RSYNC. By default, the repository is cloned as a shallow copy (`--depth=1`), but - if `--full` is passed, a full clone will be used. + 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. + + `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 + `untap` if you need to modify the <URL>. * `tap` `--repair`: Migrate tapped formulae from symlink-based to directory-based structure. diff --git a/Library/Homebrew/tap.rb b/Library/Homebrew/tap.rb index 8f8e99e67..a2e21ca0a 100644 --- a/Library/Homebrew/tap.rb +++ b/Library/Homebrew/tap.rb @@ -158,6 +158,11 @@ class Tap path.directory? end + # True if this {Tap} is not a full clone. + def shallow? + (path/".git/shallow").exist? + end + # @private def core_tap? false @@ -171,17 +176,33 @@ class Tap # @option options [Boolean] :quiet If set, suppress all output. def install(options = {}) require "descriptions" - raise TapAlreadyTappedError, name if installed? - clear_cache + full_clone = options.fetch(:full_clone, false) quiet = options.fetch(:quiet, false) + requested_remote = options[:clone_target] || "https://github.com/#{user}/homebrew-#{repo}" + + if installed? + raise TapRemoteMismatchError.new(name, @remote, requested_remote) unless remote == requested_remote + raise TapAlreadyTappedError, name unless full_clone + raise TapAlreadyUnshallowError, name unless shallow? + end # ensure git is installed Utils.ensure_git_installed! + + if installed? + ohai "Unshallowing #{name}" unless quiet + args = %W[fetch --unshallow] + args << "-q" if quiet + path.cd { safe_system "git", *args } + return + end + + clear_cache + ohai "Tapping #{name}" unless quiet - remote = options[:clone_target] || "https://github.com/#{user}/homebrew-#{repo}" - args = %W[clone #{remote} #{path} --config core.autocrlf=false] - args << "--depth=1" unless options.fetch(:full_clone, false) + args = %W[clone #{requested_remote} #{path} --config core.autocrlf=false] + args << "--depth=1" unless full_clone args << "-q" if quiet begin diff --git a/Library/Homebrew/test/test_tap.rb b/Library/Homebrew/test/test_tap.rb index fa0602e94..0b2671698 100644 --- a/Library/Homebrew/test/test_tap.rb +++ b/Library/Homebrew/test/test_tap.rb @@ -164,7 +164,32 @@ class TapTest < Homebrew::TestCase end def test_install_tap_already_tapped_error - assert_raises(TapAlreadyTappedError) { @tap.install } + setup_git_repo + already_tapped_tap = Tap.new("Homebrew", "foo") + assert_equal true, already_tapped_tap.installed? + assert_raises(TapAlreadyTappedError) { already_tapped_tap.install } + end + + def test_install_tap_remote_match_already_tapped_error + setup_git_repo + already_tapped_tap = Tap.new("Homebrew", "foo") + assert_equal true, already_tapped_tap.installed? + right_remote = "#{@tap.remote}" + assert_raises(TapAlreadyTappedError) { already_tapped_tap.install :clone_target => right_remote } + end + + def test_install_tap_remote_mismatch_error + setup_git_repo + already_tapped_tap = Tap.new("Homebrew", "foo") + assert_equal true, already_tapped_tap.installed? + wrong_remote = "#{@tap.remote}-oops" + assert_raises(TapRemoteMismatchError) { already_tapped_tap.install :clone_target => wrong_remote } + end + + def test_install_tap_already_unshallow_error + setup_git_repo + already_tapped_tap = Tap.new("Homebrew", "foo") + assert_raises(TapAlreadyUnshallowError) { already_tapped_tap.install :full_clone => true } end def test_uninstall_tap_unavailable_error diff --git a/share/doc/homebrew/brew.1.html b/share/doc/homebrew/brew.1.html index 2997bcb03..37519d67e 100644 --- a/share/doc/homebrew/brew.1.html +++ b/share/doc/homebrew/brew.1.html @@ -303,7 +303,12 @@ assumptions, so taps can be cloned from places other than GitHub and using protocols other than HTTPS, e.g., SSH, GIT, HTTP, FTP(S), RSYNC.</p> <p>By default, the repository is cloned as a shallow copy (<code>--depth=1</code>), but -if <code>--full</code> is passed, a full clone will be used.</p></dd> +if <code>--full</code> is passed, a full clone will be used. To convert a shallow copy +to a full copy, you can retap passing <code>--full</code> without first untapping.</p> + +<p><code>tap</code> is re-runnable and exits successfully if there's nothing to do. +However, retapping with a different <var>URL</var> will cause an exception, so first +<code>untap</code> if you need to modify the <var>URL</var>.</p></dd> <dt><code>tap</code> <code>--repair</code></dt><dd><p>Migrate tapped formulae from symlink-based to directory-based structure.</p></dd> <dt><code>tap</code> <code>--list-official</code></dt><dd><p>List all official taps.</p></dd> <dt><code>tap</code> <code>--list-pinned</code></dt><dd><p>List all pinned taps.</p></dd> diff --git a/share/man/man1/brew.1 b/share/man/man1/brew.1 index 8f1167f31..c9adf6bea 100644 --- a/share/man/man1/brew.1 +++ b/share/man/man1/brew.1 @@ -416,7 +416,10 @@ With \fIURL\fR unspecified, taps a formula repository from GitHub using HTTPS\. With \fIURL\fR specified, taps a formula repository from anywhere, using any transport protocol that \fBgit\fR handles\. The one\-argument form of \fBtap\fR simplifies but also limits\. This two\-argument command makes no assumptions, so taps can be cloned from places other than GitHub and using protocols other than HTTPS, e\.g\., SSH, GIT, HTTP, FTP(S), RSYNC\. . .IP -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\. +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 +\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 \fBtap\fR \fB\-\-repair\fR |
