Sha256: ab27c1a5e286f340655dcde2fc1d0bc3ee41bbe6d7ed7bea2769814701eb8053

Contents?: true

Size: 1.83 KB

Versions: 1

Compression:

Stored size: 1.83 KB

Contents

# frozen_string_literal: true

module GitLS
  # Parse a .git/index file
  # Format documented here: https://git-scm.com/docs/index-format
  class Parser
    HEADER = 'A4' + # 4-byte signature:
             # The signature is { 'D', 'I', 'R', 'C' } (stands for "dircache")
             'N' + # 4-byte version number:
             # The current supported versions are 2, 3 and 4.
             'N' # 32-bit number of index entries.

    def initialize(file)
      @file = file
      raise ::GitLS::Error, 'not a git dir or .git/index file' unless valid?
    end

    def files
      headers

      @files = Array.new(length)
      case git_version
      when 2 then files_2
      when 3 then files_3
      when 4 then raise ::GitLS::Error, "4 is complicated git version, it's not done yet"
      else raise ::GitLS::Error, 'Unrecognized git version'
      end
      @files
    end

    private

    def files_2
      @files.map! do
        @file.pos += 62 # skip 62 bytes (40 bytes of stat, 20 bytes of sha, 2 bytes flags)
        ret = @file.readline("\0").chop
        @file.pos += 7 - ((ret.bytesize - 2) % 8) # 1-8 bytes padding of nuls
        ret
      end
    end

    def files_3
      @files.map! do
        @file.pos += 60 # skip 60 bytes (40 bytes of stat, 20 bytes of sha)
        flags = @file.read(2) # 2 bytes flags
        # skip extend flags if extended flags bit set
        @file.pos += 2 if flags && (flags.unpack1('n') & 0b0100_0000_0000_0000).positive?

        ret = @file.readline("\0").chop
        @file.pos += 7 - ((ret.bytesize - 2) % 8) # 1-8 bytes padding of nuls
        ret
      end
    end

    def headers
      @headers ||= @file.read(12).unpack(::GitLS::Parser::HEADER)
    end

    def valid?
      headers[0] == 'DIRC'
    end

    def git_version
      @git_version = headers[1]
    end

    def length
      headers[2]
    end
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
git_ls-0.1.0 lib/git_ls/parser.rb