diff options
| author | Simon Sigurdhsson | 2013-03-11 16:41:08 +0100 |
|---|---|---|
| committer | Mike McQuaid | 2013-03-30 19:50:47 +0000 |
| commit | 85eb73ced7316171a3e5087e601f3c182b8859ed (patch) | |
| tree | d48851b6277651af254f603198b0f38270745cff | |
| parent | ee7224c8ecb8e6d58b3bc40aee962d81035bf3b9 (diff) | |
| download | homebrew-85eb73ced7316171a3e5087e601f3c182b8859ed.tar.bz2 | |
brew-pin: prevent selected formulae from upgrade.
* Added `pin` et. al. to manpage.
* Added `brew pin` to `brew.1` * Added `brew unpin` to `brew.1`
* Added `brew list --pinned` to `brew.1`
* Added information about frozen formulae to `brew upgrade` in `brew.1`
* Added `pin` et.al. to completion scripts.
* Unpin formulae when uninstalling them
* Unpin and re-pin formulae when upgrading (avoids stale symlink)
References #18386.
Closes #18515.
Signed-off-by: Mike McQuaid <mike@mikemcquaid.com>
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | Library/Contributions/brew_bash_completion.sh | 8 | ||||
| -rw-r--r-- | Library/Contributions/brew_fish_completion.fish | 3 | ||||
| -rw-r--r-- | Library/Contributions/brew_zsh_completion.zsh | 5 | ||||
| -rw-r--r-- | Library/Contributions/manpages/brew.1.md | 19 | ||||
| -rw-r--r-- | Library/Homebrew/cmd/list.rb | 17 | ||||
| -rw-r--r-- | Library/Homebrew/cmd/pin.rb | 16 | ||||
| -rw-r--r-- | Library/Homebrew/cmd/uninstall.rb | 2 | ||||
| -rw-r--r-- | Library/Homebrew/cmd/unpin.rb | 16 | ||||
| -rw-r--r-- | Library/Homebrew/cmd/upgrade.rb | 20 | ||||
| -rw-r--r-- | Library/Homebrew/formula.rb | 19 | ||||
| -rw-r--r-- | Library/Homebrew/formula_pin.rb | 36 | ||||
| -rw-r--r-- | share/man/man1/brew.1 | 17 |
13 files changed, 168 insertions, 11 deletions
diff --git a/.gitignore b/.gitignore index 022c5e137..c5d39ab2d 100644 --- a/.gitignore +++ b/.gitignore @@ -9,5 +9,6 @@ !/share/man/man1/brew.1 .DS_Store /Library/LinkedKegs +/Library/PinnedKegs /Library/Taps /Library/Formula/.gitignore diff --git a/Library/Contributions/brew_bash_completion.sh b/Library/Contributions/brew_bash_completion.sh index 069567423..98c140d23 100644 --- a/Library/Contributions/brew_bash_completion.sh +++ b/Library/Contributions/brew_bash_completion.sh @@ -238,10 +238,12 @@ _brew_list () return elif __brewcomp_words_include "--verbose"; then return + elif __brewcomp_words_include "--pinned"; then + return elif __brewcomp_words_include "--versions"; then return else - __brewcomp "--unbrewed --verbose --versions" + __brewcomp "--unbrewed --verbose --pinned --versions" return fi ;; @@ -400,11 +402,13 @@ _brew () options outdated prune + pin search tap test uninstall remove rm unlink + unpin untap update upgrade @@ -435,9 +439,11 @@ _brew () missing) __brew_complete_formulae ;; options) _brew_options ;; outdated) _brew_outdated ;; + pin) _brew_complete_formulae ;; search|-S) _brew_search ;; tap) __brew_complete_taps ;; uninstall|remove|rm) _brew_uninstall ;; + unpin) __brew_complete_formulae ;; untap) __brew_complete_tapped ;; update) _brew_update ;; uses) _brew_uses ;; diff --git a/Library/Contributions/brew_fish_completion.fish b/Library/Contributions/brew_fish_completion.fish index e037ae480..df13a6f05 100644 --- a/Library/Contributions/brew_fish_completion.fish +++ b/Library/Contributions/brew_fish_completion.fish @@ -32,7 +32,7 @@ function __fish_complete_brew_argument return 0 end - if contains -- $cmd cleanup link ln missing rm remove test unlink uninstall upgrade + if contains -- $cmd cleanup link ln missing rm remove test unlink uninstall upgrade pin unpin ls (brew --prefix)/Cellar return 0 end @@ -148,6 +148,7 @@ complete -c brew -s f -l force -n '__fish_complete_brew_command link ln' -d "Ove complete -c brew -s n -l dry-run -n '__fish_complete_brew_command link ln' -d "Show which files would be deleted" complete -c brew -l unbrewed -n '__fish_complete_brew_command list ls' -d "List files in Homebrew prefix not installed by Homebrew" +complete -c brew -l pinned -n '__fish_complete_brew_command list ls' -d "Show the version number for (specified) pinned formulae" complete -c brew -l versions -n '__fish_complete_brew_command list ls' -d "Show the version number for specified formulae" complete -c brew -n '__fish_complete_brew_command log' -u diff --git a/Library/Contributions/brew_zsh_completion.zsh b/Library/Contributions/brew_zsh_completion.zsh index cabd73420..57c1f4ed5 100644 --- a/Library/Contributions/brew_zsh_completion.zsh +++ b/Library/Contributions/brew_zsh_completion.zsh @@ -34,11 +34,13 @@ _1st_arguments=( 'log:git commit log for a formula' 'missing:check all installed formuale for missing dependencies.' 'outdated:list formulae for which a newer version is available' + 'pin:pin specified formulae' 'prune:remove dead links' 'remove:remove a formula' 'search:search for a formula (/regex/ or string)' 'server:start a local web app that lets you browse formulae (requires Sinatra)' 'unlink:unlink a formula' + 'unpin:unpin specified formulae' 'update:freshen up links' 'upgrade:upgrade outdated formulae' 'uses:show formulae which depend on a formula' @@ -71,6 +73,7 @@ case "$words[1]" in list|ls) _arguments \ '(--unbrewed)--unbrewed[files in brew --prefix not controlled by brew]' \ + '(--pinned)--pinned[list all versions of pinned formulae]' \ '(--versions)--versions[list all installed versions of a formula]' \ '1: :->forms' && return 0 @@ -81,7 +84,7 @@ case "$words[1]" in install|home|homepage|log|info|abv|uses|cat|deps|edit|options) _brew_all_formulae _wanted formulae expl 'all formulae' compadd -a formulae ;; - remove|rm|uninstall|unlink|cleanup|link|ln) + remove|rm|uninstall|unlink|cleanup|link|ln|pin|unpin) _brew_installed_formulae _wanted installed_formulae expl 'installed formulae' compadd -a installed_formulae ;; upgrade) diff --git a/Library/Contributions/manpages/brew.1.md b/Library/Contributions/manpages/brew.1.md index 93df07341..eb86ba32f 100644 --- a/Library/Contributions/manpages/brew.1.md +++ b/Library/Contributions/manpages/brew.1.md @@ -195,7 +195,7 @@ Note that these flags should only appear after a command. be linked or which would be deleted by `brew link --overwrite`, but will not actually link or delete any files. - * `ls, list [--unbrewed] [--versions]` [<formulae>]: + * `ls, list [--unbrewed] [--versions] [--pinned]` [<formulae>]: Without any arguments, list all installed formulae. If <formulae> are given, list the installed files for <formulae>. @@ -208,6 +208,10 @@ Note that these flags should only appear after a command. If `--versions` is passed, show the version number for installed formulae, or only the specified formulae if <formulae> are given. + If `--pinned` is passed, show the versions of pinned formulae, or only the + specified (pinned) formulae if <formulae> are given. + See also [`pin`][], [`unpin`][]. + * `log [git-log-options]` <formula> ...: Show the git log for the given formulae. Options that `git-log`(1) recognizes can be passed before the formula list. @@ -233,6 +237,10 @@ Note that these flags should only appear after a command. If `--quiet` is passed, list only the names of outdated brews. Otherwise, the versions are printed as well. + * `pin` <formulae>: + Pin the specified <formulae>, preventing them from being upgraded when + issuing the `brew upgrade` command without arguments. See also [`unpin`][]. + * `prune`: Remove dead symlinks from the Homebrew prefix. This is generally not needed, but can be useful when doing DIY installations. @@ -273,6 +281,10 @@ Note that these flags should only appear after a command. Unsymlink <formula> from the Homebrew prefix. This can be useful for temporarily disabling a formula: `brew unlink foo && commands && brew link foo`. + * `unpin` <formulae>: + Unpin <formulae>, allowing them to be upgraded by `brew upgrade`. See also + [`pin`][]. + * `untap` <tap>: Remove a tapped repository. @@ -283,9 +295,10 @@ Note that these flags should only appear after a command. If `--rebase` is specified then `git pull --rebase` is used. * `upgrade` [<formulae>]: - Upgrade outdated brews. + Upgrade outdated, non-pinned brews. - If <formulae> are given, upgrade only the specified brews. + If <formulae> are given, upgrade only the specified brews (but do so even + if they are pinned; see [`pin`][], [`unpin`][]). * `uses [--installed] [--recursive]` <formula>: Show the formulae that specify <formula> as a dependency. diff --git a/Library/Homebrew/cmd/list.rb b/Library/Homebrew/cmd/list.rb index 4b0aa4a13..3ce3b18e3 100644 --- a/Library/Homebrew/cmd/list.rb +++ b/Library/Homebrew/cmd/list.rb @@ -8,7 +8,10 @@ module Homebrew extend self # Things below use the CELLAR, which doesn't until the first formula is installed. return unless HOMEBREW_CELLAR.exist? - if ARGV.include? '--versions' + if ARGV.include? '--pinned' + require 'formula' + list_pinned + elsif ARGV.include? '--versions' list_versions elsif ARGV.named.empty? ENV['CLICOLOR'] = nil @@ -48,6 +51,18 @@ private puts "#{d.basename} #{versions*' '}" end end + + def list_pinned + if ARGV.named.empty? + HOMEBREW_CELLAR.children.select{ |pn| pn.directory? } + else + ARGV.named.map{ |n| HOMEBREW_CELLAR+n }.select{ |pn| pn.exist? } + end.select do |d| + Formula.factory(d.basename.to_s).pinned? + end.each do |d| + puts "#{d.basename}" + end + end end class PrettyListing diff --git a/Library/Homebrew/cmd/pin.rb b/Library/Homebrew/cmd/pin.rb new file mode 100644 index 000000000..26b487a0d --- /dev/null +++ b/Library/Homebrew/cmd/pin.rb @@ -0,0 +1,16 @@ +require 'formula' + +module Homebrew extend self + def pin + if Process.uid.zero? and not File.stat(HOMEBREW_BREW_FILE).uid.zero? + abort "Cowardly refusing to `sudo pin'" + end + raise FormulaUnspecifiedError if ARGV.named.empty? + ARGV.formulae.each do |fmla| + f = Formula.factory(fmla.to_s) + onoe "Cannot pin uninstalled formula #{f.name}!" unless f.pinable? + opoo "Formula #{f.name} already pinned!" if f.pinable? and f.pinned? + f.pin if f.pinable? and not f.pinned? + end + end +end diff --git a/Library/Homebrew/cmd/uninstall.rb b/Library/Homebrew/cmd/uninstall.rb index 19ad6eeb5..5a7479f9c 100644 --- a/Library/Homebrew/cmd/uninstall.rb +++ b/Library/Homebrew/cmd/uninstall.rb @@ -10,6 +10,7 @@ module Homebrew extend self keg.lock do puts "Uninstalling #{keg}..." keg.unlink + Formula.factory(keg.fname).unpin keg.uninstall rm_opt_link keg.fname end @@ -28,6 +29,7 @@ module Homebrew extend self if keg.directory? keg = Keg.new(keg) keg.unlink + Formula.factory(keg.fname).unpin keg.rmtree end end diff --git a/Library/Homebrew/cmd/unpin.rb b/Library/Homebrew/cmd/unpin.rb new file mode 100644 index 000000000..6855db4bf --- /dev/null +++ b/Library/Homebrew/cmd/unpin.rb @@ -0,0 +1,16 @@ +require 'formula' + +module Homebrew extend self + def unpin + if Process.uid.zero? and not File.stat(HOMEBREW_BREW_FILE).uid.zero? + abort "Cowardly refusing to `sudo unpin'" + end + raise FormulaUnspecifiedError if ARGV.named.empty? + ARGV.formulae.each do |fmla| + f = Formula.factory(fmla.to_s) + onoe "Cannot unpin uninstalled formula #{f.name}!" unless f.pinable? + opoo "Formula #{f.name} already unpinned!" if f.pinable? and not f.pinned? + f.unpin if f.pinable? and f.pinned? + end + end +end diff --git a/Library/Homebrew/cmd/upgrade.rb b/Library/Homebrew/cmd/upgrade.rb index b5effee50..af2e4a0e1 100644 --- a/Library/Homebrew/cmd/upgrade.rb +++ b/Library/Homebrew/cmd/upgrade.rb @@ -18,8 +18,10 @@ module Homebrew extend self if ARGV.named.empty? require 'cmd/outdated' + upgrade_pinned = false outdated = Homebrew.outdated_brews else + upgrade_pinned = true outdated = ARGV.formulae.select do |f| if f.installed? onoe "#{f}-#{f.installed_version} already installed" @@ -32,10 +34,19 @@ module Homebrew extend self exit 1 if outdated.empty? end - if outdated.length > 1 + unless upgrade_pinned + pinned = outdated.select { |f| f.pinned? } + outdated -= pinned + end + + if outdated.length > 0 oh1 "Upgrading #{outdated.length} outdated package#{outdated.length.plural_s}, with result:" puts outdated.map{ |f| "#{f.name} #{f.version}" } * ", " end + if not upgrade_pinned and pinned.length > 0 + oh1 "Not upgrading #{pinned.length} pinned package#{outdated.length.plural_s}:" + puts pinned.map{ |f| "#{f.name} #{f.version}" } * ", " + end outdated.each do |f| upgrade_formula f @@ -60,6 +71,13 @@ module Homebrew extend self installer.install installer.caveats installer.finish + + # If the formula was pinned, and we were force-upgrading it, unpin and + # pin it again to get a symlink pointing to the correct keg. + if f.pinned? + f.unpin + f.pin + end rescue FormulaInstallationAlreadyAttemptedError # We already attempted to upgrade f as part of the dependency tree of # another formula. In that case, don't generate an error, just move on. diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb index 80e2e478c..1d9c1034c 100644 --- a/Library/Homebrew/formula.rb +++ b/Library/Homebrew/formula.rb @@ -2,6 +2,7 @@ require 'download_strategy' require 'dependency_collector' require 'formula_support' require 'formula_lock' +require 'formula_pin' require 'hardware' require 'bottles' require 'patches' @@ -68,6 +69,8 @@ class Formula # make sure to strip "--" from the start of options self.class.build.add opt[/--(.+)$/, 1], desc end + + @pin = FormulaPin.new(self) end def url; @active_spec.url; end @@ -80,6 +83,22 @@ class Formula installed_prefix.children.length > 0 rescue false end + def pinable? + @pin.pinable? + end + + def pinned? + @pin.pinned? + end + + def pin + @pin.pin + end + + def unpin + @pin.unpin + end + def linked_keg HOMEBREW_REPOSITORY/'Library/LinkedKegs'/@name end diff --git a/Library/Homebrew/formula_pin.rb b/Library/Homebrew/formula_pin.rb new file mode 100644 index 000000000..cdffd7fc0 --- /dev/null +++ b/Library/Homebrew/formula_pin.rb @@ -0,0 +1,36 @@ +require 'formula' +require 'fileutils' + +class FormulaPin + HOMEBREW_PINNED = HOMEBREW_LIBRARY/'PinnedKegs' + + def initialize(formula) + @formula = formula + @name = formula.name + HOMEBREW_PINNED.mkdir unless HOMEBREW_PINNED.exist? + @path = HOMEBREW_PINNED/@name + end + + def pin_at(version) + version_path = @formula.installed_prefix.parent.join(version) + FileUtils.ln_s version_path, @path unless pinned? or not version_path.exist? + end + + def pin + versions = @formula.installed_prefix.parent.children.map { |item| item.basename.to_s } + version = versions.map { |item| Version.new(item) }.sort[0].to_s + pin_at(version) + end + + def unpin + FileUtils.rm @path if pinned? + end + + def pinned? + @path.exist? + end + + def pinable? + @formula.installed_prefix.parent.children.length > 0 + end +end diff --git a/share/man/man1/brew.1 b/share/man/man1/brew.1 index 952e87876..96886e6b7 100644 --- a/share/man/man1/brew.1 +++ b/share/man/man1/brew.1 @@ -215,7 +215,7 @@ If \fB\-\-overwrite\fR is passed, Homebrew will delete files which already exist If \fB\-\-dry\-run\fR or \fB\-n\fR is passed, Homebrew will list all files which would be linked or which would be deleted by \fBbrew link \-\-overwrite\fR, but will not actually link or delete any files\. . .TP -\fBls, list [\-\-unbrewed] [\-\-versions]\fR [\fIformulae\fR] +\fBls, list [\-\-unbrewed] [\-\-versions] [\-\-pinned]\fR [\fIformulae\fR] Without any arguments, list all installed formulae\. . .IP @@ -227,6 +227,9 @@ If \fB\-\-unbrewed\fR is passed, list all files in the Homebrew prefix not insta .IP If \fB\-\-versions\fR is passed, show the version number for installed formulae, or only the specified formulae if \fIformulae\fR are given\. . +.IP +If \fB\-\-pinned\fR is passed, show the versions of pinned formulae, or only the specified (pinned) formulae if \fIformulae\fR are given\. See also [\fBpin\fR][], [\fBunpin\fR][]\. +. .TP \fBlog [git\-log\-options]\fR \fIformula\fR \.\.\. Show the git log for the given formulae\. Options that \fBgit\-log\fR(1) recognizes can be passed before the formula list\. @@ -259,6 +262,10 @@ Show formulae that have an updated version available\. If \fB\-\-quiet\fR is passed, list only the names of outdated brews\. Otherwise, the versions are printed as well\. . .TP +\fBpin\fR \fIformulae\fR +Pin the specified \fIformulae\fR, preventing them from being upgraded when issuing the \fBbrew upgrade\fR command without arguments\. See also [\fBunpin\fR][]\. +. +.TP \fBprune\fR Remove dead symlinks from the Homebrew prefix\. This is generally not needed, but can be useful when doing DIY installations\. . @@ -302,6 +309,10 @@ Example: \fBbrew install jruby && brew test jruby\fR Unsymlink \fIformula\fR from the Homebrew prefix\. This can be useful for temporarily disabling a formula: \fBbrew unlink foo && commands && brew link foo\fR\. . .TP +\fBunpin\fR \fIformulae\fR +Unpin \fIformulae\fR, allowing them to be upgraded by \fBbrew upgrade\fR\. See also [\fBpin\fR][]\. +. +.TP \fBuntap\fR \fItap\fR Remove a tapped repository\. . @@ -314,10 +325,10 @@ If \fB\-\-rebase\fR is specified then \fBgit pull \-\-rebase\fR is used\. . .TP \fBupgrade\fR [\fIformulae\fR] -Upgrade outdated brews\. +Upgrade outdated, non\-pinned brews\. . .IP -If \fIformulae\fR are given, upgrade only the specified brews\. +If \fIformulae\fR are given, upgrade only the specified brews (but do so even if they are pinned; see [\fBpin\fR][], [\fBunpin\fR][])\. . .TP \fBuses [\-\-installed] [\-\-recursive]\fR \fIformula\fR |
