Skip to content

Commit 471f5a8

Browse files
committed
Sanatize object ref sent to cat-file command
1 parent 604a9a2 commit 471f5a8

File tree

6 files changed

+217
-63
lines changed

6 files changed

+217
-63
lines changed

lib/git/base.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -650,7 +650,7 @@ def ls_tree(objectish, opts = {})
650650
end
651651

652652
def cat_file(objectish)
653-
self.lib.object_contents(objectish)
653+
self.lib.cat_file(objectish)
654654
end
655655

656656
# The name of the branch HEAD refers to or 'HEAD' if detached

lib/git/lib.rb

Lines changed: 134 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -353,21 +353,104 @@ def name_rev(commit_ish)
353353

354354
alias :namerev :name_rev
355355

356-
def object_type(sha)
357-
command('cat-file', '-t', sha)
356+
# Output the contents or other properties of one or more objects.
357+
#
358+
# @see https://git-scm.com/docs/git-cat-file git-cat-file
359+
#
360+
# @param object [String] the object whose contents to return
361+
# @param opts [Hash] the options for this command
362+
# @option opts [Boolean] :tag
363+
# @option opts [Boolean] :size
364+
# @option opts
365+
#
366+
#
367+
# @return [String] the object contents
368+
#
369+
# @raise [ArgumentError] if object is a string starting with a hyphen
370+
#
371+
def cat_file_contents(object, &block)
372+
assert_args_are_not_options('object', object)
373+
374+
if block_given?
375+
Tempfile.create do |file|
376+
# If a block is given, write the output from the process to a temporary
377+
# file and then yield the file to the block
378+
#
379+
command('cat-file', "-p", object, out: file, err: file)
380+
file.rewind
381+
yield file
382+
end
383+
else
384+
# If a block is not given, return the file contents as a string
385+
command('cat-file', '-p', object)
386+
end
358387
end
359388

360-
def object_size(sha)
361-
command('cat-file', '-s', sha).to_i
389+
alias :object_contents :cat_file_contents
390+
391+
# Get the type for the given object
392+
#
393+
# @see https://git-scm.com/docs/git-cat-file git-cat-file
394+
#
395+
# @param object [String] the object to get the type
396+
#
397+
# @return [String] the object type
398+
#
399+
# @raise [ArgumentError] if object is a string starting with a hyphen
400+
#
401+
def cat_file_type(object)
402+
assert_args_are_not_options('object', object)
403+
404+
command('cat-file', '-t', object)
362405
end
363406

364-
# returns useful array of raw commit object data
365-
def commit_data(sha)
366-
sha = sha.to_s
367-
cdata = command_lines('cat-file', 'commit', sha)
368-
process_commit_data(cdata, sha)
407+
alias :object_type :cat_file_type
408+
409+
# Get the size for the given object
410+
#
411+
# @see https://git-scm.com/docs/git-cat-file git-cat-file
412+
#
413+
# @param object [String] the object to get the type
414+
#
415+
# @return [String] the object type
416+
#
417+
# @raise [ArgumentError] if object is a string starting with a hyphen
418+
#
419+
def cat_file_size(object)
420+
assert_args_are_not_options('object', object)
421+
422+
command('cat-file', '-s', object).to_i
369423
end
370424

425+
alias :object_size :cat_file_size
426+
427+
# Return a hash of commit data
428+
#
429+
# @see https://git-scm.com/docs/git-cat-file git-cat-file
430+
#
431+
# @param object [String] the object to get the type
432+
#
433+
# @return [Hash] commit data
434+
#
435+
# The returned commit data has the following keys:
436+
# * tree [String]
437+
# * parent [Array<String>]
438+
# * author [String] the author name, email, and commit timestamp
439+
# * committer [String] the committer name, email, and merge timestamp
440+
# * message [String] the commit message
441+
# * gpgsig [String] the public signing key of the commit (if signed)
442+
#
443+
# @raise [ArgumentError] if object is a string starting with a hyphen
444+
#
445+
def cat_file_commit(object)
446+
assert_args_are_not_options('object', object)
447+
448+
cdata = command_lines('cat-file', 'commit', object)
449+
process_commit_data(cdata, object)
450+
end
451+
452+
alias :commit_data :cat_file_commit
453+
371454
def process_commit_data(data, sha)
372455
hsh = {
373456
'sha' => sha,
@@ -402,12 +485,50 @@ def each_cat_file_header(data)
402485
end
403486
end
404487

405-
def tag_data(name)
406-
sha = sha.to_s
407-
tdata = command_lines('cat-file', 'tag', name)
408-
process_tag_data(tdata, name)
488+
# Return a hash of annotated tag data
489+
#
490+
# Does not work with lightweight tags. List all annotated tags in your repository with the following command:
491+
#
492+
# ```sh
493+
# git for-each-ref --format='%(refname:strip=2)' refs/tags | while read tag; do git cat-file tag $tag >/dev/null 2>&1 && echo $tag; done
494+
# ```
495+
#
496+
# @see https://git-scm.com/docs/git-cat-file git-cat-file
497+
#
498+
# @param object [String] the tag to retrieve
499+
#
500+
# @return [Hash] tag data
501+
#
502+
# Example tag data returned:
503+
# ```ruby
504+
# {
505+
# "name" => "annotated_tag",
506+
# "object" => "46abbf07e3c564c723c7c039a43ab3a39e5d02dd",
507+
# "type" => "commit",
508+
# "tag" => "annotated_tag",
509+
# "tagger" => "Scott Chacon <schacon@gmail.com> 1724799270 -0700",
510+
# "message" => "Creating an annotated tag\n"
511+
# }
512+
# ```
513+
#
514+
# The returned commit data has the following keys:
515+
# * object [String] the sha of the tag object
516+
# * type [String]
517+
# * tag [String] tag name
518+
# * tagger [String] the name and email of the user who created the tag and the timestamp of when the tag was created
519+
# * message [String] the tag message
520+
#
521+
# @raise [ArgumentError] if object is a string starting with a hyphen
522+
#
523+
def cat_file_tag(object)
524+
assert_args_are_not_options('object', object)
525+
526+
tdata = command_lines('cat-file', 'tag', object)
527+
process_tag_data(tdata, object)
409528
end
410529

530+
alias :tag_data :cat_file_tag
531+
411532
def process_tag_data(data, name)
412533
hsh = { 'name' => name }
413534

@@ -461,22 +582,6 @@ def process_commit_log_data(data)
461582
return hsh_array
462583
end
463584

464-
def object_contents(sha, &block)
465-
if block_given?
466-
Tempfile.create do |file|
467-
# If a block is given, write the output from the process to a temporary
468-
# file and then yield the file to the block
469-
#
470-
command('cat-file', "-p", sha, out: file, err: file)
471-
file.rewind
472-
yield file
473-
end
474-
else
475-
# If a block is not given, return stdout
476-
command('cat-file', '-p', sha)
477-
end
478-
end
479-
480585
def ls_tree(sha, opts = {})
481586
data = { 'blob' => {}, 'tree' => {}, 'commit' => {} }
482587

lib/git/object.rb

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ def sha
2727
end
2828

2929
def size
30-
@size ||= @base.lib.object_size(@objectish)
30+
@size ||= @base.lib.cat_file_size(@objectish)
3131
end
3232

3333
# Get the object's contents.
@@ -38,9 +38,9 @@ def size
3838
# Use this for large files so that they are not held in memory.
3939
def contents(&block)
4040
if block_given?
41-
@base.lib.object_contents(@objectish, &block)
41+
@base.lib.cat_file_contents(@objectish, &block)
4242
else
43-
@contents ||= @base.lib.object_contents(@objectish)
43+
@contents ||= @base.lib.cat_file_contents(@objectish)
4444
end
4545
end
4646

@@ -237,7 +237,7 @@ def commit?
237237
def check_commit
238238
return if @tree
239239

240-
data = @base.lib.commit_data(@objectish)
240+
data = @base.lib.cat_file_commit(@objectish)
241241
set_commit(data)
242242
end
243243

@@ -254,7 +254,7 @@ def initialize(base, sha, name)
254254
end
255255

256256
def annotated?
257-
@annotated ||= (@base.lib.object_type(self.name) == 'tag')
257+
@annotated ||= (@base.lib.cat_file_type(self.name) == 'tag')
258258
end
259259

260260
def message
@@ -279,7 +279,7 @@ def check_tag
279279
if !self.annotated?
280280
@message = @tagger = nil
281281
else
282-
tdata = @base.lib.tag_data(@name)
282+
tdata = @base.lib.cat_file_tag(@name)
283283
@message = tdata['message'].chomp
284284
@tagger = Git::Author.new(tdata['tagger'])
285285
end
@@ -300,7 +300,7 @@ def self.new(base, objectish, type = nil, is_tag = false)
300300
return Git::Object::Tag.new(base, sha, objectish)
301301
end
302302

303-
type ||= base.lib.object_type(objectish)
303+
type ||= base.lib.cat_file_type(objectish)
304304
klass =
305305
case type
306306
when /blob/ then Blob

0 commit comments

Comments
 (0)