Module: Git::Repository::ObjectOperations
- Included in:
- Git::Repository
- Defined in:
- lib/git/repository/object_operations.rb
Overview
Facade methods for raw git object store queries
Included by Git::Repository.
Instance Method Summary collapse
-
#add_tag(name, *options)
Create a new tag.
-
#archive(treeish, file = nil, opts = {}) ⇒ String
Create an archive of the repository tree and write it to a file.
-
#cat_file_commit(object) ⇒ Hash
Returns parsed commit data for the given git object.
-
#cat_file_contents(object)
Returns the raw content of a git object, or streams it into a tempfile.
-
#cat_file_size(object) ⇒ Integer
Returns the size of a git object in bytes.
-
#cat_file_tag(object) ⇒ Hash
Returns parsed tag data for the given annotated tag object.
-
#cat_file_type(object) ⇒ String
Returns the type of a git object.
-
#delete_tag(name) ⇒ String
Delete a tag.
-
#full_tree(objectish) ⇒ Array<String>
Returns all recursive entries for a given tree object.
-
#gblob(objectish) ⇒ Git::Object::Blob
Returns a blob object for the given object reference.
-
#gcommit(objectish) ⇒ Git::Object::Commit
Returns a commit object for the given object reference.
-
#grep(pattern, path_limiter = nil, opts = {}) ⇒ Hash<String, Array<Array(Integer, String)>>
Search tracked file contents in a git tree for a pattern.
-
#gtree(objectish) ⇒ Git::Object::Tree
Returns a tree object for the given object reference.
-
#ls_tree(objectish, opts = {}) ⇒ Hash<String, Hash<String, Hash>>
List the objects in a git tree.
-
#name_rev(commit_ish) ⇒ String?
Find the first symbolic name for a commit-ish.
-
#object(objectish) ⇒ Git::Object::Blob, ...
Returns the appropriate git object for the given object reference.
-
#rev_parse(objectish) ⇒ String
Resolve a revision specifier to its full object ID.
-
#tag(tag_name) ⇒ Git::Object::Tag
Returns a tag object for the given tag name.
-
#tag_sha(tag_name) ⇒ String
Returns the SHA of a named tag.
-
#tags ⇒ Array<Git::Object::Tag>
Returns all tags in the repository as tag objects.
-
#tree_depth(objectish) ⇒ Integer
Returns the number of entries in a tree.
Instance Method Details
#add_tag(name, options = {}) ⇒ Git::Object::Tag #add_tag(name, target, options = {}) ⇒ Git::Object::Tag #add_tag(name, delete: true) ⇒ String
Create a new tag
828 829 830 831 832 833 834 835 836 837 838 839 |
# File 'lib/git/repository/object_operations.rb', line 828 def add_tag(name, *) opts = .last.is_a?(Hash) ? .pop : {} target = .first return Private.add_tag_delete_deprecated(self, name, target, opts) if opts[:d] || opts[:delete] opts = opts.except(:d, :delete) SharedPrivate.assert_valid_opts!(ADD_TAG_ALLOWED_OPTS, **opts) Private.(opts) Git::Commands::Tag::Create.new(@execution_context).call(name, target, **opts) tag(name) end |
#archive(treeish, file = nil, opts = {}) ⇒ String
Create an archive of the repository tree and write it to a file
Writes the archive content to a file and returns the file path. The
default format is zip. Pass format: 'tar' for an uncompressed tar
archive, or format: 'tgz' for a gzip-compressed tar archive
(equivalent to format: 'tar' with add_gzip: true).
When no file path is given, a temporary file is created and its path
is returned.
File replacement behavior when file is given:
The archive is first written to a staging file in the same directory as
file. This means write permission is required on the parent directory
of file, not just on file itself. Once the archive is fully written,
the staging file atomically replaces file via rename.
If file already exists, only its numeric permission bits are applied to
the new archive; ownership, ACLs, and extended attributes are not
transferred. If file does not exist, the archive receives the standard
file creation mode (0666 & ~umask). On Windows, File.chmod has no
effect, so the archive always receives the default creation mode
regardless of whether file already exists.
If file is a symlink that does not point to a directory, the symlink
itself is replaced by the new archive file rather than writing through
the link to its target. A symlink that points to a directory is treated
as a directory and rejected with ArgumentError.
556 557 558 559 560 561 562 563 564 565 566 567 568 |
# File 'lib/git/repository/object_operations.rb', line 556 def archive(treeish, file = nil, opts = {}) SharedPrivate.assert_valid_opts!(ARCHIVE_ALLOWED_OPTS, **opts) raise ArgumentError, "#{file.inspect} is a directory" if file && File.directory?(file) tmp = Private.write_archive_tmp(@execution_context, treeish, opts, dest_dir: Private.staging_dir_for(file)) return tmp unless file Private.atomic_replace(tmp, file) file rescue StandardError FileUtils.rm_f(tmp) if tmp raise end |
#cat_file_commit(object) ⇒ Hash
Returns parsed commit data for the given git object
172 173 174 175 |
# File 'lib/git/repository/object_operations.rb', line 172 def cat_file_commit(object) result = Git::Commands::CatFile::Raw.new(@execution_context).call('commit', object) Git::Parsers::CatFile.parse_commit(result.stdout.split("\n"), object) end |
#cat_file_contents(object) ⇒ String #cat_file_contents(object) {|file| ... } ⇒ Object
Returns the raw content of a git object, or streams it into a tempfile
Without a block, the full content is buffered in memory and returned as a
String. With a block, git output is streamed directly to disk without
memory buffering — safe for large blobs.
77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/git/repository/object_operations.rb', line 77 def cat_file_contents(object) raise ArgumentError, "Invalid object: '#{object}'" if object&.start_with?('-') return Git::Commands::CatFile::Raw.new(@execution_context).call(object, p: true).stdout unless block_given? # Stream git output directly to a tempfile to avoid buffering large # object content in memory when a block is given. Tempfile.create do |file| file.binmode Git::Commands::CatFile::Raw.new(@execution_context).call(object, p: true, out: file) file.rewind yield file end end |
#cat_file_size(object) ⇒ Integer
Returns the size of a git object in bytes
110 111 112 113 114 |
# File 'lib/git/repository/object_operations.rb', line 110 def cat_file_size(object) raise ArgumentError, "Invalid object: '#{object}'" if object&.start_with?('-') Git::Commands::CatFile::Raw.new(@execution_context).call(object, s: true).stdout.chomp.to_i end |
#cat_file_tag(object) ⇒ Hash
Returns parsed tag data for the given annotated tag object
Does not work with lightweight tags. To list all annotated tags in a repository:
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
219 220 221 222 223 224 |
# File 'lib/git/repository/object_operations.rb', line 219 def cat_file_tag(object) raise ArgumentError, "Invalid object: '#{object}'" if object&.start_with?('-') tdata = Git::Commands::CatFile::Raw.new(@execution_context).call('tag', object).stdout.split("\n") Git::Parsers::CatFile.parse_tag(tdata, object) end |
#cat_file_type(object) ⇒ String
Returns the type of a git object
135 136 137 138 139 |
# File 'lib/git/repository/object_operations.rb', line 135 def cat_file_type(object) raise ArgumentError, "Invalid object: '#{object}'" if object&.start_with?('-') Git::Commands::CatFile::Raw.new(@execution_context).call(object, t: true).stdout.chomp end |
#delete_tag(name) ⇒ String
Delete a tag
852 853 854 855 856 857 |
# File 'lib/git/repository/object_operations.rb', line 852 def delete_tag(name) result = Git::Commands::Tag::Delete.new(@execution_context).call(name) raise Git::FailedError, result if result.status.exitstatus.positive? result.stdout end |
#full_tree(objectish) ⇒ Array<String>
Returns all recursive entries for a given tree object
Equivalent to running git ls-tree -r <objectish> and splitting the
output on newlines. Each returned line describes a single entry in the
tree in the format produced by git ls-tree: <mode> <type> <object>\t<file>.
306 307 308 |
# File 'lib/git/repository/object_operations.rb', line 306 def full_tree(objectish) Git::Commands::LsTree.new(@execution_context).call(objectish, r: true).stdout.split("\n") end |
#gblob(objectish) ⇒ Git::Object::Blob
Returns a blob object for the given object reference
The returned object is lazy: no git command is invoked until a property (e.g. Object::AbstractObject#sha, Object::AbstractObject#contents) is accessed on the result.
586 587 588 |
# File 'lib/git/repository/object_operations.rb', line 586 def gblob(objectish) Git::Object.new(self, objectish, 'blob') end |
#gcommit(objectish) ⇒ Git::Object::Commit
Returns a commit object for the given object reference
The returned object is lazy: no git command is invoked until a property (e.g. Object::AbstractObject#sha, Object::Commit#message) is accessed on the result.
610 611 612 |
# File 'lib/git/repository/object_operations.rb', line 610 def gcommit(objectish) Git::Object.new(self, objectish, 'commit') end |
#grep(pattern, path_limiter = nil, opts = {}) ⇒ Hash<String, Array<Array(Integer, String)>>
Search tracked file contents in a git tree for a pattern
Runs git grep against the given tree-ish and returns every match as a
filename-keyed hash of [line_number, text] pairs.
464 465 466 467 468 469 470 471 472 473 |
# File 'lib/git/repository/object_operations.rb', line 464 def grep(pattern, path_limiter = nil, opts = {}) SharedPrivate.assert_valid_opts!(GREP_ALLOWED_OPTS, **opts) opts = opts.dup object = opts.delete(:object) || 'HEAD' opts[:pathspec] = Array(path_limiter).map(&:to_s) if path_limiter result = Git::Commands::Grep.new(@execution_context).call( object, pattern:, **opts, no_color: true, line_number: true, null: true ) Private.parse_grep_result(result) end |
#gtree(objectish) ⇒ Git::Object::Tree
Returns a tree object for the given object reference
The returned object is lazy: no git command is invoked until a property (e.g. Object::AbstractObject#sha, Object::Tree#children) is accessed on the result.
630 631 632 |
# File 'lib/git/repository/object_operations.rb', line 630 def gtree(objectish) Git::Object.new(self, objectish, 'tree') end |
#ls_tree(objectish, opts = {}) ⇒ Hash<String, Hash<String, Hash>>
List the objects in a git tree
Runs git ls-tree against the given sha and returns a Hash of tree
entries organised by object type.
397 398 399 400 401 402 403 404 405 |
# File 'lib/git/repository/object_operations.rb', line 397 def ls_tree(objectish, opts = {}) SharedPrivate.assert_valid_opts!(LS_TREE_ALLOWED_OPTS, **opts) paths = Array(opts[:path]).compact r_value = opts[:recursive] = {} [:r] = r_value unless r_value.nil? result = Git::Commands::LsTree.new(@execution_context).call(objectish, *paths, **) Git::Parsers::LsTree.parse(result.stdout) end |
#name_rev(commit_ish) ⇒ String?
Find the first symbolic name for a commit-ish
350 351 352 353 354 |
# File 'lib/git/repository/object_operations.rb', line 350 def name_rev(commit_ish) raise ArgumentError, "Invalid commit_ish: '#{commit_ish}'" if commit_ish&.start_with?('-') Git::Commands::NameRev.new(@execution_context).call(commit_ish).stdout.split[1] end |
#object(objectish) ⇒ Git::Object::Blob, ...
Returns the appropriate git object for the given object reference
Runs git cat-file -t to determine the object type, then constructs
and returns the corresponding Git::Object::* subclass instance.
682 683 684 |
# File 'lib/git/repository/object_operations.rb', line 682 def object(objectish) Git::Object.new(self, objectish) end |
#rev_parse(objectish) ⇒ String
Resolve a revision specifier to its full object ID
Passes the given revision specifier to git rev-parse and returns the
full object ID.
251 252 253 |
# File 'lib/git/repository/object_operations.rb', line 251 def rev_parse(objectish) Git::Commands::RevParse.new(@execution_context).call(objectish, '--', revs_only: true).stdout end |
#tag(tag_name) ⇒ Git::Object::Tag
Returns a tag object for the given tag name
Returns a Object::Tag for tag_name. The returned object is
either an annotated or a lightweight tag depending on the underlying
ref type.
654 655 656 |
# File 'lib/git/repository/object_operations.rb', line 654 def tag(tag_name) Git::Object::Tag.new(self, tag_name) end |
#tag_sha(tag_name) ⇒ String
Returns the SHA of a named tag
Returns an empty string when the tag does not exist.
273 274 275 276 277 278 279 |
# File 'lib/git/repository/object_operations.rb', line 273 def tag_sha(tag_name) = File.(File.join(@execution_context.git_dir, 'refs', 'tags')) head = File.(File.join(, tag_name)) return File.read(head).chomp if head.start_with?("#{}#{File::SEPARATOR}") && File.file?(head) Private.show_ref_tag_sha(@execution_context, tag_name) end |
#tags ⇒ Array<Git::Object::Tag>
Returns all tags in the repository as tag objects
Runs git tag --list with a machine-readable format, parses the output,
and returns a Object::Tag for each tag name.
702 703 704 705 |
# File 'lib/git/repository/object_operations.rb', line 702 def result = Git::Commands::Tag::List.new(@execution_context).call(format: Git::Parsers::Tag::FORMAT_STRING) Git::Parsers::Tag.parse_list(result.stdout).map { |info| tag(info.name) } end |
#tree_depth(objectish) ⇒ Integer
Returns the number of entries in a tree
Runs git ls-tree -r <objectish> and counts output lines.
This matches Git::Lib#tree_depth behavior in the 4.x branch.
327 328 329 |
# File 'lib/git/repository/object_operations.rb', line 327 def tree_depth(objectish) Git::Commands::LsTree.new(@execution_context).call(objectish, r: true).stdout.each_line.count end |