Skip to content

Commit

Permalink
support detached head, symlinks, executable bit; annotate optional code
Browse files Browse the repository at this point in the history
  • Loading branch information
Joe Mou committed Apr 21, 2019
1 parent 55e2c63 commit b77784b
Show file tree
Hide file tree
Showing 9 changed files with 75 additions and 46 deletions.
6 changes: 3 additions & 3 deletions add
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,18 @@ import sys

import index

filenames = subprocess.check_output(['find'] + sys.argv[1:] + ['!', '-type', 'd']).splitlines()
filenames = subprocess.check_output(['find'] + sys.argv[1:] + ['!', '-type', 'd']).splitlines() # for directories
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):
if os.path.islink(filename): # for symlinks
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):
if os.access(filename, os.X_OK): # for executable files
mode = 0100755
else:
mode = 0100644
Expand Down
2 changes: 1 addition & 1 deletion branch
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/bin/bash -e

if [[ $# -eq 0 ]]; then
headref=$(symbolic-ref HEAD | sed -e 's|^refs/heads/||')
headref=$(symbolic-ref HEAD | sed -e 's|^refs/heads/||') # for current branch
echo "*$headref"
cd .zit/refs/heads
ls | grep -vxF $headref
Expand Down
2 changes: 2 additions & 0 deletions checkout
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,7 @@ checkout-index
if [[ -f .zit/refs/heads/$revision ]]; then
symbolic-ref HEAD refs/heads/$revision
else
rev-parse $revision > .zit/HEAD.tmp
mv .zit/HEAD.tmp .zit/HEAD
echo "You are in 'detached HEAD' state." >&2
fi
6 changes: 4 additions & 2 deletions checkout-index
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ for filename, mode, sha1 in entries:
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.encode('hex')], stdout=open(filename, 'w'))
if mode == 0100755:
if mode == 0100755: # for executable files
os.chmod(filename, 0755)
elif mode == 0120000:
elif mode == 0120000: # for symlinks
target = open(filename).read()
if os.path.exists(filename):
os.unlink(filename)
os.symlink(target, filename)
2 changes: 1 addition & 1 deletion commit
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash -e

if [[ -f .zit/$(symbolic-ref HEAD) ]]; then
if [[ -f .zit/$(symbolic-ref HEAD) ]]; then # for non-initial commit
parents='-p HEAD'
fi
echo '# write a commit message' > .zit/COMMIT_EDITMSG
Expand Down
3 changes: 2 additions & 1 deletion commit-tree
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
#!/bin/bash -e

# for non-hardcoded commit
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
while [[ $1 == -p ]]; do # for non-initial commit
parent=$(rev-parse $2)
echo parent $parent >> .zit/commit.tmp
shift; shift
Expand Down
1 change: 1 addition & 0 deletions init
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
mkdir -p "$1/.zit/objects"
echo 'ref: refs/heads/master' > "$1/.zit/HEAD"

# for git compatibility
ln -s .zit "$1/.git"
mkdir "$1/.git/info"
echo .zit > "$1/.git/info/exclude"
6 changes: 3 additions & 3 deletions rev-parse
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ import sys

# sha1_name.c:get_sha1
def get_sha1(name):
if name[-2] == '~':
if name[-2] == '~': # for ~
name = name[:-2] + '^' * int(name[-1])
if name[-1] == '^':
if name[-1] == '^': # for ^
sha1 = get_sha1(name[:-1])
contents = subprocess.check_output(['cat-file', 'commit', sha1])
parent = next(line for line in contents.splitlines()
if line.startswith('parent '))
return parent.split(' ')[1]
if '^{' in name:
if '^{' in name: # for ^{type}
name, requested_type = name.rsplit('^{', 1)
assert requested_type[-1] == '}'
requested_type = requested_type[:-1]
Expand Down
93 changes: 58 additions & 35 deletions test
Original file line number Diff line number Diff line change
Expand Up @@ -13,101 +13,124 @@ get_md5() {
}

header 'Initializing repo... [zit, init]'
[[ $1 == --keep ]] && { keep=1; shift; }
ZIT="${1-zit}"
trap 'echo -e "\e[31mFAIL\e[0m"' ERR
repo="$PWD/test.tmp"
rm -rf "$repo"
zit init "$repo"
[[ $1 != --keep ]] && trap 'rm -rf "$repo"' EXIT
$ZIT init "$repo"
[[ -n $keep ]] || trap 'rm -rf "$repo"' EXIT
cd "$repo"
[[ $(<.zit/HEAD) == 'ref: refs/heads/master' ]]
[[ ${ZIT::1} == / ]] || ZIT="../$ZIT"

header 'Writing a blob object... [hash-object]'
echo "I'm a little teapot" > lullaby
[[ $(zit hash-object blob lullaby) == 3eb7f9afc452afe452b99d478d89264380622248 ]]
[[ $($ZIT hash-object blob lullaby) == 3eb7f9afc452afe452b99d478d89264380622248 ]]

header 'Reading an object... [cat-file]'
[[ $(zit cat-file -t 3eb7f9afc452afe452b99d478d89264380622248 ) == blob ]]
[[ $(zit cat-file blob 3eb7f9afc452afe452b99d478d89264380622248 ) == "I'm a little teapot" ]]
[[ $($ZIT cat-file -t 3eb7f9afc452afe452b99d478d89264380622248 ) == blob ]]
[[ $($ZIT cat-file blob 3eb7f9afc452afe452b99d478d89264380622248 ) == "I'm a little teapot" ]]

header 'Writing to the index... [index.py]'
PYTHONPATH=.. /usr/bin/python -c 'import index; index.write_index([("lullaby", 0100644, "\x3e\xb7\xf9\xaf\xc4\x52\xaf\xe4\x52\xb9\x9d\x47\x8d\x89\x26\x43\x80\x62\x22\x48")])'
PYTHONPATH=$(dirname "$ZIT") /usr/bin/python -c 'import index; index.write_index([("lullaby", 0100644, "\x3e\xb7\xf9\xaf\xc4\x52\xaf\xe4\x52\xb9\x9d\x47\x8d\x89\x26\x43\x80\x62\x22\x48")])'
[[ $(get_md5 .zit/index) == 06432001fc95f78cd6353321f7c95009 ]]

header 'Adding a file to the index... [add]'
echo here > handle
zit add handle
[[ $(zit cat-file blob 012ea92e81171f5ef7486696878656c5263cf722 ) == here ]]
$ZIT add handle
[[ $($ZIT cat-file blob 012ea92e81171f5ef7486696878656c5263cf722 ) == here ]]
[[ $(get_md5 .zit/index) == 61728e18ee75d24576d9ea2b626fb1ff ]]

header 'Reading the index... [index.py]'
[[ $(PYTHONPATH=.. /usr/bin/python -c 'import index; print index.read_index()') == "[('handle', 33188, '\x01.\xa9.\x81\x17\x1f^\xf7Hf\x96\x87\x86V\xc5&<\xf7\"'), ('lullaby', 33188, '>\xb7\xf9\xaf\xc4R\xaf\xe4R\xb9\x9dG\x8d\x89&C\x80b\"H')]" ]]
[[ $(PYTHONPATH=$(dirname "$ZIT") /usr/bin/python -c 'import index; print index.read_index()') == "[('handle', 33188, '\x01.\xa9.\x81\x17\x1f^\xf7Hf\x96\x87\x86V\xc5&<\xf7\"'), ('lullaby', 33188, '>\xb7\xf9\xaf\xc4R\xaf\xe4R\xb9\x9dG\x8d\x89&C\x80b\"H')]" ]]

header 'Writing the index to a tree object... [write-tree]'
initial_tree=$(zit write-tree)
initial_tree=$($ZIT write-tree)
[[ $initial_tree == f65ccd4f10cb3416c7be6601bafd2371a784054f ]]

header 'Writing an initial commit object... [commit-tree]'
export ZIT_AUTHOR_NAME='Miss Teapot' [email protected]
initial_commit=$(echo initial commit | zit commit-tree $initial_tree)
[[ $(zit cat-file commit $initial_commit ) =~ ^"tree $initial_tree
author Miss Teapot <[email protected]> "[0-9]*\ [+-][0-9]{4}"
committer Miss Teapot <[email protected]> "[0-9]*\ [+-][0-9]{4}"
initial_commit=$(echo initial commit | $ZIT commit-tree $initial_tree)
[[ $($ZIT cat-file commit $initial_commit ) =~ ^"tree $initial_tree
author "[^\<]*" <"[^\>]*"> "[0-9]*\ [+-][0-9]{4}"
committer "[^\<]*" <"[^\>]*"> "[0-9]*\ [+-][0-9]{4}"
initial commit"$ ]]

header 'Create a branch ref [update-ref]'
zit update-ref refs/heads/initial $initial_commit
$ZIT update-ref refs/heads/initial $initial_commit
[[ $(<.zit/refs/heads/initial) == $initial_commit ]]

header 'Read HEAD symbolic ref [symbolic-ref]'
[[ $(zit symbolic-ref HEAD) == refs/heads/master ]]
[[ $($ZIT symbolic-ref HEAD) == refs/heads/master ]]

header 'Birth master branch [update-ref, get-sha1-basic, rev-parse]'
zit update-ref HEAD $initial_commit
[[ $(zit rev-parse HEAD) == $initial_commit ]]
$ZIT update-ref HEAD $initial_commit
[[ $($ZIT rev-parse HEAD) == $initial_commit ]]

header 'Delete and create a branch [branch]'
zit branch -d initial
$ZIT branch -d initial
[[ ! -f .zit/refs/heads/initial ]]
zit branch initial
$ZIT branch initial
[[ $(<.zit/refs/heads/initial) == $initial_commit ]]

header 'Writing another commit object... [commit, commit-tree]'
echo 'short and stout' > lullaby
zit add lullaby
echo 'second verse' | EDITOR=tee zit commit > /dev/null
$ZIT add lullaby
EDITOR=tee $ZIT commit <<< 'second verse' > /dev/null
second_tree=3c1bea2d45d260a3836794e04a4bbef34e3c2459
[[ $(zit cat-file commit $(zit rev-parse HEAD) ) =~ ^"tree $second_tree
second_commit=$($ZIT rev-parse HEAD)
[[ $($ZIT cat-file commit $second_commit ) =~ ^"tree $second_tree
parent $initial_commit
author Miss Teapot <[email protected]> "[0-9]*\ [+-][0-9]{4}"
committer Miss Teapot <[email protected]> "[0-9]*\ [+-][0-9]{4}"
author "[^\<]*" <"[^\>]*"> "[0-9]*\ [+-][0-9]{4}"
committer "[^\<]*" <"[^\>]*"> "[0-9]*\ [+-][0-9]{4}"
second verse"$ ]]

header 'Parse ^ and ~ revisions [rev-parse]'
[[ $(zit rev-parse HEAD^) == $initial_commit ]]
[[ $(zit rev-parse HEAD~1) == $initial_commit ]]
[[ $(zit rev-parse initial~0) == $initial_commit ]]
[[ $($ZIT rev-parse HEAD^) == $initial_commit ]]
[[ $($ZIT rev-parse HEAD~1) == $initial_commit ]]
[[ $($ZIT rev-parse initial~0) == $initial_commit ]]

header 'Parse ^{type} revisions [rev-parse]'
[[ $(zit rev-parse HEAD^{tree}) == $second_tree ]]
[[ $(zit rev-parse HEAD^^{tree}) == $initial_tree ]]
[[ $($ZIT rev-parse HEAD^{tree}) == $second_tree ]]
[[ $($ZIT rev-parse HEAD^^{tree}) == $initial_tree ]]

header 'Reading tree object into the index... [read-tree]'
zit read-tree $initial_tree
$ZIT read-tree $initial_tree
[[ $(get_md5 .zit/index) == 61728e18ee75d24576d9ea2b626fb1ff ]]

header 'Checkout from the index [checkout-index]'
zit checkout-index
$ZIT checkout-index
[[ $(<lullaby) == "I'm a little teapot" ]]

header 'Update HEAD symbolic ref [symbolic-ref]'
zit symbolic-ref HEAD refs/heads/initial
$ZIT symbolic-ref HEAD refs/heads/initial
[[ $(<.zit/HEAD) == 'ref: refs/heads/initial' ]]

header 'Checkout master branch [checkout]'
zit checkout master
$ZIT checkout master
[[ $(<lullaby) == 'short and stout' ]]
[[ $(<.zit/HEAD) == 'ref: refs/heads/master' ]]

header 'Checkout detached HEAD [checkout]'
$ZIT checkout HEAD
[[ $(<.zit/HEAD) == $second_commit ]]

header 'Commit executable file, symlink, and directory [add]'
chmod +x handle
mkdir and
ln -s ../handle and/spout
git add handle and/spout
EDITOR=tee $ZIT commit <<< 'first stanza' > /dev/null
[[ $($ZIT rev-parse HEAD^{tree}) == 6a8ad12fa34d4f1ea64abb28c8ae143b1e8fde40 ]]

header 'Checkout a new branch [checkout, checkout-index]'
rm -rf handle and
$ZIT checkout -b stanza
[[ $(<.zit/HEAD) == 'ref: refs/heads/stanza' ]]
[[ -x handle ]]
[[ $(python -c 'import os; print os.readlink("and/spout")') == ../handle ]]

[[ -n $keep ]] || { rm -rf "$repo"; trap '' EXIT; }
header PASS

0 comments on commit b77784b

Please sign in to comment.