Skip to content

Commit

Permalink
big cleanup, refactor, fill some missing functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
Joe Mou committed Apr 21, 2019
1 parent 079f767 commit d5d472d
Show file tree
Hide file tree
Showing 13 changed files with 90 additions and 110 deletions.
54 changes: 20 additions & 34 deletions add
Original file line number Diff line number Diff line change
@@ -1,43 +1,29 @@
#!/usr/bin/python

# update-index.c:add_file_to_cache
import struct
import os
import subprocess
import sys

# TODO write in C? do all macs have gcc?
# TODO if cache doesn't exist?
index = open('.zit/index').read()
assert index[0:4] == 'DIRC'
assert struct.unpack('>I', index[4:8]) == (2,)
num_entries, = struct.unpack('>I', index[8:12])
entries = []
i = 12
for _ in range(num_entries):
# ignore inode heuristics, file/symlink bit, permissions
i += 40
sha1 = index[i:i+20].encode('hex')
# just use NUL-terminated?
name_length = struct.unpack('>H', index[i+20:i+22])[0] & 0xfff
name = index[i+22:i+22+name_length]
i += (22 + name_length + 8) / 8 * 8
entries.append((name, sha1))
import index

_, filename = sys.argv
# TODO handle deleted files?
sha1 = subprocess.check_output(['hash-object', 'blob', filename]).strip()
# TODO canonicalize filename?
entries.append((filename, sha1))
filenames = subprocess.check_output(['find'] + sys.argv[1:] + ['!', '-type', 'd']).splitlines()
entries = index.read_index()
for filename in filenames:
entries = [e for e in entries if e[0] != filename]
if os.path.exists(filename):
if os.path.islink(filename):
mode = 0120000
with open('.zit/blob.tmp', 'w') as f:
f.write(os.readlink(filename))
sha1 = subprocess.check_output(['hash-object', 'blob', '.zit/blob.tmp']).strip()
else:
if os.access(filename, os.X_OK):
mode = 0100755
else:
mode = 0100644
sha1 = subprocess.check_output(['hash-object', 'blob', filename]).strip()
entries.append((filename, mode, bytearray.fromhex(sha1)))
entries.sort()

f = open('.zit/index', 'w')
f.write('DIRC')
f.write(struct.pack('>II', 2, len(entries)))
for filename, sha1 in entries:
f.write('\0' * 24)
f.write(struct.pack('>I', 0b1000000110100100)) # file 644
f.write('\0' * 12)
f.write(bytearray.fromhex(sha1))
f.write(struct.pack('>H', len(filename)))
f.write(filename)
f.write('\0' * (8 - (len(filename) + 6) % 8))
index.write_index(entries)
5 changes: 1 addition & 4 deletions branch
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,5 @@ if [[ $# -eq 0 ]]; then
elif [[ $1 == -d ]]; then
rm -f .zit/refs/heads/$2
else
branchname=$1
startpoint=${2-HEAD}
rev=$(rev-parse $startpoint)
update-ref refs/heads/$branchname $rev
update-ref refs/heads/$1 ${2-HEAD}
fi
1 change: 0 additions & 1 deletion cat-file
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#!/usr/bin/python

# git1.0 cat-file.c sha1_file.c:read_object_with_reference
# TODO follow commit->tree and tag->object
import sys
import zlib

Expand Down
31 changes: 9 additions & 22 deletions checkout-index
Original file line number Diff line number Diff line change
@@ -1,33 +1,20 @@
#!/usr/bin/python

import os
import struct
import subprocess

# TODO dedup w/ write-tree
index = open('.zit/index').read()
assert index[0:4] == 'DIRC'
assert struct.unpack('>I', index[4:8]) == (2,)
num_entries, = struct.unpack('>I', index[8:12])
entries = []
i = 12
for _ in range(num_entries):
# ignore inode heuristics, file/symlink bit, permissions
i += 40
sha1 = index[i:i+20].encode('hex')
# just use NUL-terminated?
name_length = struct.unpack('>H', index[i+20:i+22])[0] & 0xfff
name = index[i+22:i+22+name_length]
i += (22 + name_length + 8) / 8 * 8
entries.append((name, sha1))
import index

entries = index.read_index()
# entry.c:checkout_entry
for filename, sha1 in entries:
for filename, mode, sha1 in entries:
assert not filename.startswith('/')
assert '..' not in filename
# TODO unlink directories?
if os.path.exists(filename):
os.unlink(filename)
subprocess.check_call(['mkdir', '-p', './' + os.path.dirname(filename)])
# TODO git 1.0 doesn't seem to unlink deleted files
subprocess.check_call(['cat-file', 'blob', sha1], stdout=open(filename, 'w'))
subprocess.check_call(['cat-file', 'blob', sha1.encode('hex')], stdout=open(filename, 'w'))
if mode == 0100755:
os.chmod(filename, 0755)
elif mode == 0120000:
target = open(filename).read()
os.symlink(target, filename)
5 changes: 3 additions & 2 deletions commit
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
#!/bin/bash -e

# TODO unless this is the initial commit
parents='-p HEAD'
if [[ -f .zit/$(symbolic-ref HEAD) ]]; then
parents='-p HEAD'
fi
echo '# write a commit message' > .zit/COMMIT_EDITMSG
vi .zit/COMMIT_EDITMSG
tree=$(write-tree)
Expand Down
9 changes: 7 additions & 2 deletions commit-tree
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
#!/bin/bash -e

export ZIT_AUTHOR_NAME="${ZIT_AUTHOR_NAME-Frank N. Stein}"
export ZIT_AUTHOR_EMAIL="${ZIT_AUTHOR_EMAIL-eat@brains.com}"
export ZIT_COMMITTER_NAME="${ZIT_COMMITTER_NAME-$ZIT_AUTHOR_NAME}"
export ZIT_COMMITTER_EMAIL="${ZIT_COMMITTER_EMAIL-$ZIT_AUTHOR_EMAIL}"

echo tree $1 > .zit/commit.tmp
shift
while [[ $1 == -p ]]; do
parent=$(rev-parse $2)
echo parent $parent >> .zit/commit.tmp
shift; shift
done
echo author "Joe Mou <[email protected]> $(date +'%s %z')" >> .zit/commit.tmp
echo committer "Joe Mou <[email protected]> $(date +'%s %z')" >> .zit/commit.tmp
echo author "$ZIT_AUTHOR_NAME <$ZIT_AUTHOR_EMAIL> $(date +'%s %z')" >> .zit/commit.tmp
echo committer "$ZIT_COMMITTER_NAME <$ZIT_COMMITTER_EMAIL> $(date +'%s %z')" >> .zit/commit.tmp
echo >> .zit/commit.tmp
cat >> .zit/commit.tmp

Expand Down
5 changes: 1 addition & 4 deletions get-sha1-basic
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,5 @@
if [[ ${#1} -eq 40 ]]; then
echo $1
else
cat .zit/$(symbolic-ref $1) 2> /dev/null || \
cat .zit/$(symbolic-ref refs/$1) 2> /dev/null || \
cat .zit/$(symbolic-ref refs/tags/$1) 2> /dev/null || \
cat .zit/$(symbolic-ref refs/heads/$1)
cat .zit/$(symbolic-ref $1) 2> /dev/null || cat .zit/$(symbolic-ref refs/heads/$1)
fi
36 changes: 36 additions & 0 deletions index.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import os
import struct

def write_index(entries):
f = open('.zit/index', 'w')
f.write('DIRC')
f.write(struct.pack('>II', 2, len(entries)))
for filename, mode, rawsha1 in entries:
f.write('\0' * 24)
f.write(struct.pack('>I', mode))
f.write('\0' * 12)
f.write(rawsha1)
f.write(struct.pack('>H', len(filename)))
f.write(filename)
f.write('\0' * (8 - (len(filename) + 6) % 8))

def read_index():
if not os.path.exists('.zit/index'):
return []
index = open('.zit/index').read()
assert index[0:4] == 'DIRC'
assert struct.unpack('>I', index[4:8]) == (2,)
num_entries, = struct.unpack('>I', index[8:12])
i = 12
entries = []
for _ in range(num_entries):
# ignore inode heuristics
mode, = struct.unpack('>I', index[i+24:i+28])
i += 40
rawsha1 = index[i:i+20]
# just use NUL-terminated?
filename_length = struct.unpack('>H', index[i+20:i+22])[0] & 0xfff
filename = index[i+22:i+22+filename_length]
i += (22 + filename_length + 8) / 8 * 8
entries.append((filename, mode, rawsha1))
return entries
21 changes: 6 additions & 15 deletions read-tree
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,18 @@ import struct
import subprocess
import sys

import index

_, tree_sha1 = sys.argv
tree = subprocess.check_output(['cat-file', 'tree', tree_sha1])
entries = []
while tree:
header, rest = tree.split('\0', 1)
flags, filename = header.split(' ', 1)
mode, filename = header.split(' ', 1)
rawsha1 = rest[:20]
tree = rest[20:]
# TODO handle directories
if flags != '040000':
entries.append((flags, filename, rawsha1))
if mode != '040000':
entries.append((filename, int(mode, 8), rawsha1))

# TODO dedup with add. this handles flags
f = open('.zit/index', 'w')
f.write('DIRC')
f.write(struct.pack('>II', 2, len(entries)))
for flags, filename, rawsha1 in entries:
f.write('\0' * 24)
f.write(struct.pack('>I', int(flags, 8)))
f.write('\0' * 12)
f.write(rawsha1)
f.write(struct.pack('>H', len(filename)))
f.write(filename)
f.write('\0' * (8 - (len(filename) + 6) % 8))
index.write_index(entries)
2 changes: 1 addition & 1 deletion rev-parse
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def get_sha1(name):
return sha1
elif actual_type == 'commit':
assert int(length) == len(contents)
tree = next(line for line in contents.split('\n')
tree = next(line for line in contents.splitlines()
if line.startswith('tree '))
name = tree.split(' ')[1]
# TODO deref tags?
Expand Down
1 change: 0 additions & 1 deletion update-ref
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,5 @@

path=.zit/$(symbolic-ref $1)
sha1=$(rev-parse $2)
# TODO initialize directory structure instead?
mkdir -p $(dirname $path)
echo $sha1 > $path
28 changes: 5 additions & 23 deletions write-tree
Original file line number Diff line number Diff line change
@@ -1,36 +1,18 @@
#!/usr/bin/python

# write-tree.c
import struct
import subprocess
import sys

# TODO write in C? do all macs have gcc?
# TODO if cache doesn't exist?
index = open('.zit/index').read()
assert index[0:4] == 'DIRC'
assert struct.unpack('>I', index[4:8]) == (2,)
num_entries, = struct.unpack('>I', index[8:12])
entries = []
i = 12
for _ in range(num_entries):
# ignore inode heuristics, file/symlink bit, permissions
i += 40
sha1 = index[i:i+20].encode('hex')
# just use NUL-terminated?
name_length = struct.unpack('>H', index[i+20:i+22])[0] & 0xfff
name = index[i+22:i+22+name_length]
i += (22 + name_length + 8) / 8 * 8
entries.append((name, sha1))
import index

entries = index.read_index()
# TODO write directories recursively? groupby?
f = open('.zit/tree.tmp', 'w')
for filename, sha1 in entries:
# TODO directories and file 755
f.write('100644 ') # file 644
for filename, mode, rawsha1 in entries:
f.write('{:o} '.format(mode))
f.write(filename)
f.write('\0')
f.write(bytearray.fromhex(sha1))
f.write(rawsha1)
f.close()

subprocess.check_call(['hash-object', 'tree', '.zit/tree.tmp'])
2 changes: 1 addition & 1 deletion zit
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/bash -e

export PATH="${BASH_SOURCE%/*}:$PATH"
export PATH="$(cd "${BASH_SOURCE%/*}"; echo "$PWD"):$PATH"
exec "$@"

0 comments on commit d5d472d

Please sign in to comment.