Class: Amp::Core::Repositories::Git::PackFile
- Inherits:
-
Object
- Object
- Amp::Core::Repositories::Git::PackFile
- Includes:
- Support
- Defined in:
- lib/amp-git/repo_format/packfile.rb
Overview
PackFile
Git uses it’s “gc” command to pack loose objects into PackFiles. This is one file, preferably with an index (though not requiring one), which stores a number of objects in a very simple raw form.
The index is not necessary. It is simply preferable because otherwise you have to uncompress each object in a raw, then calculate the hash of the object, just to find out where each object is and what its hash is.
Defined Under Namespace
Classes: PackFileEntry
Constant Summary collapse
- OBJ_COMMIT =
1
- OBJ_TREE =
2
- OBJ_BLOB =
3
- OBJ_TAG =
4
- OBJ_OFS_DELTA =
6
- OBJ_REF_DELTA =
7
- DATA_START_OFFSET =
12
- PREFIX_NAME_LOOKUP =
{OBJ_COMMIT => 'commit', OBJ_TREE => 'tree', OBJ_BLOB => 'blob', OBJ_TAG => 'tag'}
Instance Attribute Summary collapse
-
#index ⇒ Object
readonly
Returns the value of attribute index.
-
#name ⇒ Object
readonly
Returns the value of attribute name.
-
#size ⇒ Object
readonly
Returns the value of attribute size.
-
#version ⇒ Object
readonly
Returns the value of attribute version.
Instance Method Summary collapse
- #cache_entry(entry) ⇒ Object
- #cached_offset(given_hash) ⇒ Object
-
#initialize(name, opener) ⇒ PackFile
constructor
Initializes a PackFile.
-
#object_for_hash(given_hash) ⇒ RawObject
Gets an object in the Git system with the provided SHA1 hash identifier.
Constructor Details
#initialize(name, opener) ⇒ PackFile
Initializes a PackFile. Parses the header for some information but that’s about it. It will however determine if there is an index file, and if so, it will load that for fast lookups later. It also verifies the fourcc of the packfile.
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 |
# File 'lib/amp-git/repo_format/packfile.rb', line 197 def initialize(name, opener) @name = name @opener = opener opener.open(name, "r") do |fp| # Check signature unless fp.read(4) == "PACK" raise ArgumentError.new("#{name} is not a packfile.") end @version = fp.read(4).unpack("N").first @size = fp.read(4).unpack("N").first cur = fp.tell fp.seek(0, IO::SEEK_END) @end_of_data = fp.tell - 20 end possible_index_path = name[0..(name.size - File.extname(name).size - 1)] + ".idx" if File.exist? possible_index_path # use a persistent file pointer fp = File.open(possible_index_path, "r") @index = PackFileIndex.parse(fp) end @offset_cache = {} end |
Instance Attribute Details
#index ⇒ Object (readonly)
Returns the value of attribute index.
178 179 180 |
# File 'lib/amp-git/repo_format/packfile.rb', line 178 def index @index end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
178 179 180 |
# File 'lib/amp-git/repo_format/packfile.rb', line 178 def name @name end |
#size ⇒ Object (readonly)
Returns the value of attribute size.
178 179 180 |
# File 'lib/amp-git/repo_format/packfile.rb', line 178 def size @size end |
#version ⇒ Object (readonly)
Returns the value of attribute version.
178 179 180 |
# File 'lib/amp-git/repo_format/packfile.rb', line 178 def version @version end |
Instance Method Details
#cache_entry(entry) ⇒ Object
224 225 226 |
# File 'lib/amp-git/repo_format/packfile.rb', line 224 def cache_entry(entry) @offset_cache[entry.hash_id] = entry.offset end |
#cached_offset(given_hash) ⇒ Object
220 221 222 |
# File 'lib/amp-git/repo_format/packfile.rb', line 220 def cached_offset(given_hash) @offset_cache[given_hash] end |
#object_for_hash(given_hash) ⇒ RawObject
Gets an object in the Git system with the provided SHA1 hash identifier. If this packfile has an associated index file, that will be used. Otherwise, the packfile can be scanned from the beginning to the end, caching offsets as it goes, enabling easy lookup later. Either way, a RawObject or a subclass of it will be returned, or nil if no matching object is found.
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 |
# File 'lib/amp-git/repo_format/packfile.rb', line 238 def object_for_hash(given_hash) @opener.open(name, "r") do |fp| given_hash.force_encoding("ASCII-8BIT") if given_hash.respond_to?(:force_encoding) entry = nil if index starting_at = index.offset_for_hash(given_hash) return PackFileEntry.at(starting_at, fp).to_raw_object else starting_at = cached_offset(given_hash) || DATA_START_OFFSET fp.seek(starting_at, IO::SEEK_SET) while fp.tell < @end_of_data entry = PackFileEntry.read(fp) cache_entry(entry) return entry.to_raw_object if entry.hash_id == given_hash end end end nil end |