Having fun with Git

1 2 3 Page 2
Page 2 of 3
<span style="color: #003399;">String</span> treeHash<span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">try</span><span style="color: #009900;">(</span><span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">InputStream</span> inputStream <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">InflaterInputStream</span><span style="color: #009900;">(</span><span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">FileInputStream</span><span style="color: #009900;">(</span>commitFile<span style="color: #009900;">)</span><span style="color: #009900;">)</span><span style="color: #009900;">)</span> <span style="color: #009900;">{</span>
    <span style="color: #003399;">String</span> type <span style="color: #339933;">=</span> <span style="color: #003399;">Util</span>.<span style="color: #006633;">stringUntil</span><span style="color: #009900;">(</span>inputStream, <span style="color: #0000ff;">' '</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">long</span> length <span style="color: #339933;">=</span> <span style="color: #003399;">Long</span>.<span style="color: #006633;">valueOf</span><span style="color: #009900;">(</span><span style="color: #003399;">Util</span>.<span style="color: #006633;">stringUntil</span><span style="color: #009900;">(</span>inputStream, <span style="color: #009900;">(</span><span style="color: #000066; font-weight: bold;">char</span><span style="color: #009900;">)</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">)</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
    <span style="color: #003399;">Util</span>.<span style="color: #006633;">stringUntil</span><span style="color: #009900;">(</span>inputStream, <span style="color: #0000ff;">' '</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
    treeHash <span style="color: #339933;">=</span> <span style="color: #003399;">Util</span>.<span style="color: #006633;">stringUntil</span><span style="color: #009900;">(</span>inputStream, <span style="color: #0000ff;">'<span style="color: #000099; font-weight: bold;">\n</span>'</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
    <span style="color: #003399;">System</span>.<span style="color: #006633;">out</span>.<span style="color: #006633;">println</span><span style="color: #009900;">(</span><span style="color: #0000ff;">"Tree hash: "</span> <span style="color: #339933;">+</span> treeHash<span style="color: #009900;">)</span><span style="color: #339933;">;</span>
<span style="color: #009900;">}</span>
 
<span style="color: #003399;">File</span> rootTreeFile <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">File</span><span style="color: #009900;">(</span>repository,
       <span style="color: #0000ff;">"objects/"</span> <span style="color: #339933;">+</span> treeHash.<span style="color: #006633;">substring</span><span style="color: #009900;">(</span><span style="color: #cc66cc;">0</span>,<span style="color: #cc66cc;">2</span><span style="color: #009900;">)</span> <span style="color: #339933;">+</span> <span style="color: #0000ff;">"/"</span> <span style="color: #339933;">+</span> treeHash.<span style="color: #006633;">substring</span><span style="color: #009900;">(</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">)</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">try</span><span style="color: #009900;">(</span><span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">InputStream</span> inputStream <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">InflaterInputStream</span><span style="color: #009900;">(</span><span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">FileInputStream</span><span style="color: #009900;">(</span>rootTreeFile<span style="color: #009900;">)</span><span style="color: #009900;">)</span><span style="color: #009900;">)</span> <span style="color: #009900;">{</span>
    <span style="color: #003399;">System</span>.<span style="color: #006633;">out</span>.<span style="color: #006633;">println</span><span style="color: #009900;">(</span><span style="color: #003399;">Util</span>.<span style="color: #006633;">asString</span><span style="color: #009900;">(</span>inputStream<span style="color: #009900;">)</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
<span style="color: #009900;">}</span>

Looking at the tree hash file is not as straight forward, however:

tree 130 100644 FOO æ?â?²ÑÖCK?)®wZØÂä?S?
100644 FOO.txt ýc?Õô¹ìmìªGAk?X?ï'&
100644 README Wýs?ºyâx+@îR°X040000 lib ?ñG»Ñ?¼>&8´. ?úË¢i[o

The next part of this article will show how to deal with this.

Parsing a directory tree

The tree file has what looks like a lot of garbage. But don’t panic. Just like with the commit object, the tree object starts with the type (“tree”) and the size (130). After this, it will list each file or directory. Each tree entry consists of permissions (which also tells us whether this is a file or a directory), the file name and the hash of the entry, but this time as a binary number. We can read through the entries and find the file we want. We can then just print out the contents of this file:

<span style="color: #003399;">File</span> rootTreeFile <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">File</span><span style="color: #009900;">(</span>repository,
        <span style="color: #0000ff;">"objects/"</span> <span style="color: #339933;">+</span> treeHash.<span style="color: #006633;">substring</span><span style="color: #009900;">(</span><span style="color: #cc66cc;">0</span>,<span style="color: #cc66cc;">2</span><span style="color: #009900;">)</span> <span style="color: #339933;">+</span> <span style="color: #0000ff;">"/"</span> <span style="color: #339933;">+</span> treeHash.<span style="color: #006633;">substring</span><span style="color: #009900;">(</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">)</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
Map<span style="color: #339933;"><</span>string ,String<span style="color: #339933;">></span> entries <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> HashMap<span style="color: #339933;"><></span><span style="color: #009900;">(</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">try</span><span style="color: #009900;">(</span><span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">InputStream</span> inputStream <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">InflaterInputStream</span><span style="color: #009900;">(</span><span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">FileInputStream</span><span style="color: #009900;">(</span>rootTreeFile<span style="color: #009900;">)</span><span style="color: #009900;">)</span><span style="color: #009900;">)</span> <span style="color: #009900;">{</span>
    <span style="color: #003399;">String</span> type <span style="color: #339933;">=</span> <span style="color: #003399;">Util</span>.<span style="color: #006633;">stringUntil</span><span style="color: #009900;">(</span>inputStream, <span style="color: #0000ff;">' '</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">long</span> length <span style="color: #339933;">=</span> <span style="color: #003399;">Long</span>.<span style="color: #006633;">valueOf</span><span style="color: #009900;">(</span><span style="color: #003399;">Util</span>.<span style="color: #006633;">stringUntil</span><span style="color: #009900;">(</span>inputStream, <span style="color: #009900;">(</span><span style="color: #000066; font-weight: bold;">char</span><span style="color: #009900;">)</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">)</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
 
    <span style="color: #000000; font-weight: bold;">while</span> <span style="color: #009900;">(</span><span style="color: #000066; font-weight: bold;">true</span><span style="color: #009900;">)</span> <span style="color: #009900;">{</span>
        <span style="color: #003399;">String</span> octalMode <span style="color: #339933;">=</span> <span style="color: #003399;">Util</span>.<span style="color: #006633;">leftPad</span><span style="color: #009900;">(</span><span style="color: #003399;">Util</span>.<span style="color: #006633;">stringUntil</span><span style="color: #009900;">(</span>inputStream, <span style="color: #0000ff;">' '</span><span style="color: #009900;">)</span>, <span style="color: #cc66cc;">6</span>, <span style="color: #0000ff;">'0'</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">(</span>octalMode <span style="color: #339933;">==</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">)</span> <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span>
 
        <span style="color: #003399;">String</span> path <span style="color: #339933;">=</span> <span style="color: #003399;">Util</span>.<span style="color: #006633;">stringUntil</span><span style="color: #009900;">(</span>inputStream, <span style="color: #009900;">(</span><span style="color: #000066; font-weight: bold;">char</span><span style="color: #009900;">)</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
        StringBuilder hash <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> StringBuilder<span style="color: #009900;">(</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">(</span><span style="color: #000066; font-weight: bold;">int</span> i<span style="color: #339933;">=</span><span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> i<span style="color: #339933;">&</span>lt<span style="color: #339933;">;</span><span style="color: #cc66cc;">20</span><span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">)</span> <span style="color: #009900;">{</span>
            hash.<span style="color: #006633;">append</span><span style="color: #009900;">(</span><span style="color: #003399;">Util</span>.<span style="color: #006633;">leftPad</span><span style="color: #009900;">(</span><span style="color: #003399;">Integer</span>.<span style="color: #006633;">toHexString</span><span style="color: #009900;">(</span>inputStream.<span style="color: #006633;">read</span><span style="color: #009900;">(</span><span style="color: #009900;">)</span><span style="color: #009900;">)</span>, <span style="color: #cc66cc;">2</span>, <span style="color: #0000ff;">'0'</span><span style="color: #009900;">)</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">}</span>
        entries.<span style="color: #006633;">put</span><span style="color: #009900;">(</span>path, hash.<span style="color: #006633;">toString</span><span style="color: #009900;">(</span><span style="color: #009900;">)</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">}</span>
<span style="color: #009900;">}</span>
 
<span style="color: #003399;">System</span>.<span style="color: #006633;">out</span>.<span style="color: #006633;">println</span><span style="color: #009900;">(</span>entries<span style="color: #009900;">)</span><span style="color: #339933;">;</span>
<span style="color: #339933;"></</span>string<span style="color: #339933;">></span>

Here’s an example of a parsed directory listing. I have not showed the octalMode for each file, but this can be extremely useful to separate between directories (which octalMode starts with 0) and files:

{FOO.txt=fd6385d5f4b9ec6decaa47416b7f96588aef2726,
lib=8ff147bbd18fbc3e2638b42ea09cfacba2695b6f,
README=57fd19a7738eba1e79e2782b161a40ee52b05801,
FOO=e69de29bb2d1d6434b8b29ae775ad8c2e48c5391}

Reading a file

This leads us to the end of our journey – how to read the contents of a file. Once we have the entries of a tree, it’s a simple matter of looking up the hash for a filename and parsing that file. As before, the file contents will start with the type (“blob” – which means “data”, I guess) and file size:

Related:
1 2 3 Page 2
Page 2 of 3