diff options
| -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 | 
