File: blob.rb

package info (click to toggle)
ruby-grit 2.8.3-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 336 kB
  • sloc: ruby: 3,643; makefile: 4
file content (126 lines) | stat: -rw-r--r-- 3,695 bytes parent folder | download | duplicates (5)
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
module Grit

  class Blob
    DEFAULT_MIME_TYPE = "text/plain"

    attr_reader :id
    attr_reader :mode
    attr_reader :name

    # Create an unbaked Blob containing just the specified attributes
    #   +repo+ is the Repo
    #   +atts+ is a Hash of instance variable data
    #
    # Returns Grit::Blob (unbaked)
    def self.create(repo, atts)
      self.allocate.create_initialize(repo, atts)
    end

    # Initializer for Blob.create
    #   +repo+ is the Repo
    #   +atts+ is a Hash of instance variable data
    #
    # Returns Grit::Blob (unbaked)
    def create_initialize(repo, atts)
      @repo = repo
      atts.each do |k, v|
        instance_variable_set("@#{k}".to_sym, v)
      end
      self
    end

    # The size of this blob in bytes
    #
    # Returns Integer
    def size
      @size ||= @repo.git.cat_file({:s => true}, id).chomp.to_i
    end

    # The binary contents of this blob.
    #
    # Returns String
    def data
      @data ||= @repo.git.cat_file({:p => true}, id)
    end

    # The mime type of this file (based on the filename)
    #
    # Returns String
    def mime_type
      guesses = MIME::Types.type_for(self.name) rescue []
      guesses.first ? guesses.first.simplified : DEFAULT_MIME_TYPE
    end

    # The blame information for the given file at the given commit
    #
    # Returns Array: [Grit::Commit, Array: [<line>]]
    def self.blame(repo, commit, file)
      data = repo.git.blame({:p => true}, commit, '--', file)

      commits = {}
      blames = []
      info = nil

      data.split("\n").each do |line|
        parts = line.split(/\s+/, 2)
        case parts.first
          when /^[0-9A-Fa-f]{40}$/
            case line
              when /^([0-9A-Fa-f]{40}) (\d+) (\d+) (\d+)$/
                _, id, origin_line, final_line, group_lines = *line.match(/^([0-9A-Fa-f]{40}) (\d+) (\d+) (\d+)$/)
                info = {:id => id}
                blames << [nil, []]
              when /^([0-9A-Fa-f]{40}) (\d+) (\d+)$/
                _, id, origin_line, final_line = *line.match(/^([0-9A-Fa-f]{40}) (\d+) (\d+)$/)
                info = {:id => id}
            end
          when /^(author|committer)/
            case parts.first
              when /^(.+)-mail$/
                info["#{$1}_email".intern] = parts.last
              when /^(.+)-time$/
                info["#{$1}_date".intern] = Time.at(parts.last.to_i)
              when /^(author|committer)$/
                info[$1.intern] = parts.last
            end
          when /^filename/
            info[:filename] = parts.last
          when /^summary/
            info[:summary] = parts.last
          when ''
            c = commits[info[:id]]
            unless c
              c = Commit.create(repo, :id => info[:id],
                                      :author => Actor.from_string(info[:author] + ' ' + info[:author_email]),
                                      :authored_date => info[:author_date],
                                      :committer => Actor.from_string(info[:committer] + ' ' + info[:committer_email]),
                                      :committed_date => info[:committer_date],
                                      :message => info[:summary])
              commits[info[:id]] = c
            end
            _, text = *line.match(/^\t(.*)$/)
            blames.last[0] = c
            blames.last[1] << text
            info = nil
        end
      end

      blames
    end

    def basename
      File.basename(name)
    end

    # Pretty object inspection
    def inspect
      %Q{#<Grit::Blob "#{@id}">}
    end

    # Compares blobs by name
    def <=>(other)
      name <=> other.name
    end
  end # Blob

end # Grit