aboutsummaryrefslogtreecommitdiffstats
path: root/Library/Homebrew/cmd/versions.rb
blob: 5a356cb885b18e227c4b845c6e4511c337ca66b3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
require 'formula'

module Homebrew extend self
  def versions
    raise "Please `brew install git` first" unless which "git"
    raise "Please `brew update' first" unless (HOMEBREW_REPOSITORY/".git").directory?

    raise FormulaUnspecifiedError if ARGV.named.empty?

    opoo <<-EOS.undent
      brew-versions is unsupported and may be removed soon.
      Please use the homebrew-versions tap instead:
        https://github.com/Homebrew/homebrew-versions
    EOS
    ARGV.formulae.all? do |f|
      if ARGV.include? '--compact'
        puts f.versions * " "
      else
        f.versions do |version, sha|
          print Tty.white.to_s
          print "#{version.to_s.ljust(8)} "
          print Tty.reset.to_s
          puts "git checkout #{sha} #{f.pretty_relative_path}"
        end
      end
    end
  end
end


class Formula
  def versions
    versions = []
    rev_list.each do |sha|
      version = version_for_sha sha
      unless versions.include? version or version.nil?
        yield version, sha if block_given?
        versions << version
      end
    end
    return versions
  end

  def bottle_filenames branch='HEAD'
    filenames = []
    rev_list(branch).each do |sha|
      filename = formula_for_sha(sha) do |f|
        bottle_block = f.class.send(:bottle)
        unless bottle_block.checksums.empty?
          revision = bottle_block.revision
          bottle_filename f, revision
        end
      end
      unless filenames.include? filename or filename.nil?
        filenames << filename
      end
    end
    filenames
  end

  def pretty_relative_path
    if Pathname.pwd == repository
      entry_name
    else
      repository/"#{entry_name}"
    end
  end

  private
    def repository
      @repository ||= begin
        if path.realpath.to_s =~ HOMEBREW_TAP_DIR_REGEX
          HOMEBREW_REPOSITORY/"Library/Taps/#$1-#$2"
        else
          HOMEBREW_REPOSITORY
        end
      end
    end

    def entry_name
      @entry_name ||= begin
        repository == HOMEBREW_REPOSITORY ? "Library/Formula/#{name}.rb" : "#{name}.rb"
      end
    end

    def rev_list branch='HEAD'
      repository.cd do
        `git rev-list --abbrev-commit #{branch} -- #{entry_name}`.split
      end
    end

    def text_from_sha sha
      repository.cd do
        `git cat-file blob #{sha}:#{entry_name}`
      end
    end

    def sha_for_version version
      rev_list.find{ |sha| version == version_for_sha(sha) }
    end

    IGNORED_EXCEPTIONS = [SyntaxError, TypeError, NameError,
                          ArgumentError, FormulaSpecificationError]

    def version_for_sha sha
      formula_for_sha(sha) {|f| f.version }
    end

    def formula_for_sha sha, &block
      mktemp do
        path = Pathname.new(Pathname.pwd+"#{name}.rb")
        path.write text_from_sha(sha)

        # Unload the class so Formula#version returns the correct value
        begin
          Formulary.unload_formula name
          nostdout { yield Formula.factory(path.to_s) }
        rescue *IGNORED_EXCEPTIONS => e
          # We rescue these so that we can skip bad versions and
          # continue walking the history
          ohai "#{e} in #{name} at revision #{sha}", e.backtrace if ARGV.debug?
        rescue FormulaUnavailableError
          # Suppress this error
        end
      end
    end
end