Skip to content
This repository
Browse code

Merge remote branch 'origin/github'

  • Loading branch information...
commit 9042243dc486031bb1eb3427ece27db18a06e234 2 parents e4d4461 + 087676c
Ryan Tomayko authored
15  lib/grit/commit.rb
@@ -252,6 +252,21 @@ def notes
252 252
       ret
253 253
     end
254 254
 
  255
+    # Calculates the commit's Patch ID. The Patch ID is essentially the SHA1
  256
+    # of the diff that the commit is introducing.
  257
+    #
  258
+    # Returns the 40 character hex String if a patch-id could be calculated
  259
+    #   or nil otherwise.
  260
+    def patch_id
  261
+      show = @repo.git.show({}, @id)
  262
+      patch_line = @repo.git.native(:patch_id, :input => show)
  263
+      if patch_line =~ /^([0-9a-f]{40}) [0-9a-f]{40}\n$/
  264
+        $1
  265
+      else
  266
+        nil
  267
+      end
  268
+    end
  269
+
255 270
     # Pretty object inspection
256 271
     def inspect
257 272
       %Q{#<Grit::Commit "#{@id}">}
4  lib/grit/git.rb
@@ -52,6 +52,10 @@ def put_raw_object(content, type)
52 52
       ruby_git.put_raw_object(content, type)
53 53
     end
54 54
 
  55
+    def get_raw_object(object_id)
  56
+      ruby_git.get_raw_object_by_sha1(object_id).content
  57
+    end
  58
+
55 59
     def object_exists?(object_id)
56 60
       ruby_git.object_exists?(object_id)
57 61
     end
43  lib/grit/index.rb
@@ -12,6 +12,10 @@ class Index
12 12
     # which the next commit will be based.
13 13
     attr_accessor :current_tree
14 14
 
  15
+    # Public: if a tree or commit is written, this stores the size of that object
  16
+    attr_reader :last_tree_size
  17
+    attr_reader :last_commit_size
  18
+
15 19
     # Initialize a new Index object.
16 20
     #
17 21
     # repo - The Grit::Repo to which the index belongs.
@@ -71,16 +75,16 @@ def read_tree(tree)
71 75
     #           :parents        - Array of String commit SHA1s or Grit::Commit
72 76
     #                             objects to attach this commit to to form a 
73 77
     #                             new head (default: nil).
74  
-    #           :actor          - The Grit::Actor details of the user making 
  78
+    #           :actor          - The Grit::Actor details of the user making
75 79
     #                             the commit (default: nil).
76 80
     #           :last_tree      - The String SHA1 of a tree to compare with
77  
-    #                             in order to avoid making empty commits 
  81
+    #                             in order to avoid making empty commits
78 82
     #                             (default: nil).
79 83
     #           :head           - The String branch name to write this head to
80  
-    #                             (default: "master").
81  
-    #           :committed_date - The Time that the commit was made.  
  84
+    #                             (default: nil).
  85
+    #           :committed_date - The Time that the commit was made.
82 86
     #                             (Default: Time.now)
83  
-    #           :authored_date  - The Time that the commit was authored.  
  87
+    #           :authored_date  - The Time that the commit was authored.
84 88
     #                             (Default: committed_date)
85 89
     #
86 90
     # The legacy argument style looks like:
@@ -97,7 +101,9 @@ def read_tree(tree)
97 101
     #
98 102
     # Returns a String of the SHA1 of the new commit.
99 103
     def commit(message, parents = nil, actor = nil, last_tree = nil, head = 'master')
  104
+      commit_tree_sha = nil
100 105
       if parents.is_a?(Hash)
  106
+        commit_tree_sha = parents[:commit_tree_sha]
101 107
         actor          = parents[:actor]
102 108
         committer      = parents[:committer]
103 109
         author         = parents[:author]
@@ -111,7 +117,11 @@ def commit(message, parents = nil, actor = nil, last_tree = nil, head = 'master'
111 117
       committer ||= actor
112 118
       author    ||= committer
113 119
 
114  
-      tree_sha1 = write_tree(self.tree, self.current_tree)
  120
+      if commit_tree_sha
  121
+        tree_sha1 = commit_tree_sha
  122
+      else
  123
+        tree_sha1 = write_tree(self.tree, self.current_tree)
  124
+      end
115 125
 
116 126
       # don't write identical commits
117 127
       return false if tree_sha1 == last_tree
@@ -135,9 +145,12 @@ def commit(message, parents = nil, actor = nil, last_tree = nil, head = 'master'
135 145
       contents << ''
136 146
       contents << message
137 147
 
138  
-      commit_sha1 = self.repo.git.put_raw_object(contents.join("\n"), 'commit')
  148
+      contents = contents.join("\n")
  149
+      @last_commit_size = contents.size
  150
+      commit_sha1 = self.repo.git.put_raw_object(contents, 'commit')
139 151
 
140  
-      self.repo.update_ref(head, commit_sha1)
  152
+      self.repo.update_ref(head, commit_sha1) if head
  153
+      commit_sha1
141 154
     end
142 155
 
143 156
     # Recursively write a tree to the index.
@@ -149,10 +162,12 @@ def commit(message, parents = nil, actor = nil, last_tree = nil, head = 'master'
149 162
     #            this tree will be based (default: nil).
150 163
     #
151 164
     # Returns the String SHA1 String of the tree.
152  
-    def write_tree(tree, now_tree = nil)
  165
+    def write_tree(tree = nil, now_tree = nil)
  166
+      tree = self.tree if !tree
153 167
       tree_contents = {}
154 168
 
155 169
       # fill in original tree
  170
+      now_tree = read_tree(now_tree) if(now_tree && now_tree.is_a?(String))
156 171
       now_tree.contents.each do |obj|
157 172
         sha = [obj.id].pack("H*")
158 173
         k = obj.name
@@ -164,6 +179,15 @@ def write_tree(tree, now_tree = nil)
164 179
       # overwrite with new tree contents
165 180
       tree.each do |k, v|
166 181
         case v
  182
+          when Array
  183
+            sha, mode = v
  184
+            if sha.size == 40        # must be a sha
  185
+              sha = [sha].pack("H*")
  186
+              mode = mode.to_i.to_s  # leading 0s not allowed
  187
+              k = k.split('/').last  # slashes not allowed
  188
+              str = "%s %s\0%s" % [mode, k, sha]
  189
+              tree_contents[k] = str
  190
+            end
167 191
           when String
168 192
             sha = write_blob(v)
169 193
             sha = [sha].pack("H*")
@@ -181,6 +205,7 @@ def write_tree(tree, now_tree = nil)
181 205
       end
182 206
 
183 207
       tr = tree_contents.sort.map { |k, v| v }.join('')
  208
+      @last_tree_size = tr.size
184 209
       self.repo.git.put_raw_object(tr, 'tree')
185 210
     end
186 211
 
49  lib/grit/repo.rb
@@ -346,6 +346,21 @@ def refs
346 346
       [ Head.find_all(self), Tag.find_all(self), Remote.find_all(self) ].flatten
347 347
     end
348 348
 
  349
+    # returns an array of hashes representing all references
  350
+    def refs_list
  351
+      refs = self.git.for_each_ref
  352
+      refarr = refs.split("\n").map do |line|
  353
+        shatype, ref = line.split("\t")
  354
+        sha, type = shatype.split(' ')
  355
+        [ref, sha, type]
  356
+      end
  357
+      refarr
  358
+    end
  359
+
  360
+    def delete_ref(ref)
  361
+      self.git.native(:update_ref, {:d => true}, ref)
  362
+    end
  363
+
349 364
     def commit_stats(start = 'master', max_count = 10, skip = 0)
350 365
       options = {:max_count => max_count,
351 366
                  :skip => skip}
@@ -376,6 +391,11 @@ def commits_between(from, to)
376 391
       Commit.find_all(self, "#{from}..#{to}").reverse
377 392
     end
378 393
 
  394
+    def fast_forwardable?(to, from)
  395
+      mb = self.git.native(:merge_base, {}, [to, from]).strip
  396
+      mb == from
  397
+    end
  398
+
379 399
     # The Commits objects that are newer than the specified date.
380 400
     # Commits are returned in chronological order.
381 401
     #   +start+ is the branch/commit name (default 'master')
@@ -470,6 +490,35 @@ def tree(treeish = 'master', paths = [])
470 490
       Tree.construct(self, treeish, paths)
471 491
     end
472 492
 
  493
+    # quick way to get a simple array of hashes of the entries
  494
+    # of a single tree or recursive tree listing from a given 
  495
+    # sha or reference
  496
+    #   +treeish+ is the reference (default 'master')
  497
+    #   +options+ is a hash or options - currently only takes :recursive
  498
+    #
  499
+    # Examples
  500
+    #   repo.lstree('master', :recursive => true)
  501
+    #
  502
+    # Returns array of hashes - one per tree entry
  503
+    def lstree(treeish = 'master', options = {})
  504
+      # check recursive option
  505
+      opts = {:timeout => false, :l => true, :t => true}
  506
+      if options[:recursive]
  507
+        opts[:r] = true
  508
+      end
  509
+      # mode, type, sha, size, path
  510
+      revs = self.git.native(:ls_tree, opts, treeish)
  511
+      lines = revs.split("\n")
  512
+      revs = lines.map do |a|
  513
+        stuff, path = a.split("\t")
  514
+        mode, type, sha, size = stuff.split(" ")
  515
+        entry = {:mode => mode, :type => type, :sha => sha, :path => path}
  516
+        entry[:size] = size.strip.to_i if size.strip != '-'
  517
+        entry
  518
+      end
  519
+      revs
  520
+    end
  521
+
473 522
     # The Blob object for the given id
474 523
     #   +id+ is the SHA1 id of the blob
475 524
     #
37  lib/grit/tag.rb
@@ -18,6 +18,32 @@ def self.find_all(repo, options = {})
18 18
       end
19 19
     end
20 20
 
  21
+    # Writes a new tag object from a hash
  22
+    #  +repo+ is a Grit repo
  23
+    #  +hash+ is the hash of tag values
  24
+    #
  25
+    # Returns a hash with +sha+ and +size+ of the created object
  26
+    def self.create_tag_object(repo, hash, default_actor = nil)
  27
+      tagger = hash[:tagger]
  28
+      if !tagger
  29
+        tagger = default_actor ? default_actor : Actor.new("none", "none@none")
  30
+        tagger_date = Time.now
  31
+      else
  32
+        tagger_date = tagger[:date] ? Time.parse(tagger[:date]) : Time.now
  33
+        tagger = Actor.new(tagger[:name], tagger[:email])
  34
+      end
  35
+      data = []
  36
+      data << "object #{hash[:object]}"
  37
+      data << "type #{hash[:type]}"
  38
+      data << "tag #{hash[:tag]}"
  39
+      data << "tagger #{tagger.output(tagger_date)}"
  40
+      data << ""
  41
+      data << hash[:message]
  42
+      data = data.join("\n")
  43
+      sha = repo.git.put_raw_object(data, 'tag')
  44
+      { :sha => sha, :size => data.size }
  45
+    end
  46
+
21 47
     # Parses the results from `cat-file -p`
22 48
     #
23 49
     # data - String tag object data.  Example:
@@ -34,9 +60,9 @@ def self.parse_tag_data(data)
34 60
       return unless data =~ /^object/
35 61
       parsed = {}
36 62
       lines  = data.split("\n")
37  
-      lines.shift # type commit
38  
-      lines.shift # tag name
39  
-      lines.shift
  63
+      parsed[:object] = lines.shift.sub(/^object /, '')
  64
+      parsed[:type] = lines.shift.sub(/^type /, '')
  65
+      parsed[:tag] = lines.shift.sub(/^tag /, '')
40 66
       author_line = lines.shift
41 67
       parsed[:tagger], parsed[:tag_date] = Commit.actor(author_line)
42 68
       if !parsed[:tagger] || !parsed[:tagger].name
@@ -49,6 +75,11 @@ def self.parse_tag_data(data)
49 75
         parsed[:message] << lines.shift
50 76
       end
51 77
       parsed[:message] = parsed[:message] * "\n"
  78
+      parsed[:pgp] = []
  79
+      while lines.first
  80
+        parsed[:pgp] << lines.shift
  81
+      end
  82
+      parsed[:pgp] = parsed[:pgp] * "\n"
52 83
       parsed
53 84
     end
54 85
 
7  test/test_commit.rb
@@ -193,6 +193,13 @@ def test_to_patch
193 193
     assert patch.include?("1.7.")
194 194
   end
195 195
 
  196
+  # patch_id
  197
+  
  198
+  def test_patch_id
  199
+    @c = Commit.create(@r, :id => '80f136f500dfdb8c3e8abf4ae716f875f0a1b57f')
  200
+    assert_equal '9450b04e4f83ad0067199c9e9e338197d1835cbb', @c.patch_id
  201
+  end
  202
+
196 203
   # inspect
197 204
 
198 205
   def test_inspect

0 notes on commit 9042243

Please sign in to comment.
Something went wrong with that request. Please try again.