First version which handles git directories, files and directories
This commit is contained in:
parent
3beabe653d
commit
ea2dde6c57
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/test/
|
|
@ -12,26 +12,30 @@ def hash1(bytes):
|
|||
#print("hash1 " + bytes)
|
||||
return subprocess.check_output(['sha256sum', '--binary', '--zero'], input=bytes)[0:64]
|
||||
|
||||
def hashN(bytesList):
|
||||
#print("hashN ")
|
||||
#print(b''.join(bytesList))
|
||||
return subprocess.check_output(['sha256sum', '--binary', '--zero'], input = b''.join(bytesList))[0:64]
|
||||
|
||||
#
|
||||
# TODO: use this to get the hashes and names for all roots of the DAG (commits that are reachable only through one (or several) direct branch names, but not transitively as ancestors of other commits)
|
||||
#
|
||||
git_command='''
|
||||
(
|
||||
(
|
||||
git log --format=%P --all HEAD FETCH_HEAD | tr ' ' \\n | grep -v '^$' | sort -u | sed -e 'p;p';
|
||||
git rev-parse HEAD FETCH_HEAD --all | sort -u
|
||||
git log --format=%P --all {HEAD} {FETCH_HEAD} | tr ' ' \\n | grep -v '^$' | sort -u | sed -e 'p;p';
|
||||
git rev-parse {HEAD} {FETCH_HEAD} --all | sort -u
|
||||
) | sort | uniq -u;
|
||||
for ref in HEAD FETCH_HEAD; do echo "$(git rev-parse $ref) $ref"; done; git for-each-ref --format='%(objectname) %(refname)'
|
||||
) | sort | awk 'BEGIN { h="" } { if (length($0) == 40) { h=$0 } else { if (substr($0,1,40) == h) print $0 } }' | sort -k 2
|
||||
for ref in {HEAD} {FETCH_HEAD}; do echo "$(git rev-parse $ref) $ref"; done; git for-each-ref --format='%(objectname) %(refname)'
|
||||
) | sort | awk 'BEGIN {{ h="" }} {{ if (length($0) == 40) {{ h=$0 }} else {{ if (substr($0,1,40) == h) print $0 }} }}' | sort -k 2
|
||||
'''
|
||||
|
||||
def ref_exists(path, ref):
|
||||
try:
|
||||
subprocess.check_output("git rev-parse --verify "+ref+" 2>/dev/null", cwd=path, shell=True)
|
||||
return True
|
||||
except subprocess.CalledProcessError:
|
||||
return False
|
||||
|
||||
def hashGit(path):
|
||||
return subprocess.check_output(['sh', '-c', git_command])
|
||||
FETCH_HEAD = "FETCH_HEAD" if ref_exists(path, "FETCH_HEAD") else ''
|
||||
HEAD = "HEAD" if ref_exists(path, "HEAD") else ''
|
||||
return subprocess.check_output(['sh', '-c', git_command.format(HEAD=HEAD, FETCH_HEAD=FETCH_HEAD)], cwd=path)
|
||||
|
||||
sqlite3_command='''
|
||||
(
|
||||
|
@ -42,22 +46,34 @@ sqlite3_command='''
|
|||
def hashSqlite3(path):
|
||||
pass # TODO…
|
||||
|
||||
def ignore_exitcode(cmd, **kwargs):
|
||||
try:
|
||||
return subprocess.check_output(cmd, **kwargs)
|
||||
except subprocess.CalledProcessError:
|
||||
return ''
|
||||
|
||||
def is_git(x):
|
||||
return os.path.isdir(x) \
|
||||
and (ignore_exitcode("git rev-parse --is-inside-git-dir 2>/dev/null", cwd=x, shell=True).strip() == b'true' or
|
||||
ignore_exitcode("git rev-parse --is-inside-work-tree 2>/dev/null", cwd=x, shell=True).strip() == b'true')
|
||||
# TODO: if a file which is inside a larger git dir is passed on the CLI, this still returns True :-(
|
||||
|
||||
def recur(x):
|
||||
#print(x)
|
||||
# initial list of paths
|
||||
if isinstance(x, list):
|
||||
return hashN([b'root\0'] + [recur(os.path.abspath(path)) + b' ' + path.encode('utf-8') + b'\0' for path in sorted(x)])
|
||||
return b'root\0' + b''.join(recur(os.path.abspath(path)) + b' ' + path.encode('utf-8') + b'\0' for path in sorted(x))
|
||||
# GIT repo
|
||||
elif os.path.isdir(x) and os.path.exists(os.path.join(x, '.git')):
|
||||
print("GIT DIR")
|
||||
return hashN([b'git-versioned folder\0', hashGit(x)])
|
||||
elif is_git(x):
|
||||
#print("GIT DIR " + x, file=sys.stderr)
|
||||
return hash1(b'git-versioned folder\0' + hashGit(x))
|
||||
# directory
|
||||
elif os.path.isdir(x):
|
||||
return hashN([b'directory\0'] + [recur(entry) + b' ' + entry.encode('utf-8') + b'\0' for entry in os.listdir(x)])
|
||||
return hash1(b'directory\0' + b''.join(recur(os.path.join(x, entry)) + b' ' + entry.encode('utf-8') + b'\0' for entry in os.listdir(x)))
|
||||
# Just a file
|
||||
elif os.path.isfile(x):
|
||||
return hashFile(x)
|
||||
else:
|
||||
sys.exit("unknown file type for %s" % f)
|
||||
sys.exit("unknown file type for %s" % os.path.abspath(x))
|
||||
|
||||
print(recur(sys.argv[1:]).decode('utf-8'))
|
||||
print(hash1(recur(sys.argv[1:])).decode('utf-8'))
|
||||
|
|
28
test.py
Executable file
28
test.py
Executable file
|
@ -0,0 +1,28 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import os, subprocess, tempfile
|
||||
|
||||
with tempfile.TemporaryDirectory(prefix="test", dir="/tmp") as tempdir:
|
||||
os.mkdir(tempdir+'/test')
|
||||
os.mkdir(tempdir+'/test/foo')
|
||||
os.mkdir(tempdir+'/test/foo/bar')
|
||||
os.mkdir(tempdir+'/test/foo/baz')
|
||||
os.mkdir(tempdir+'/test/foo/baz/quux')
|
||||
os.system('git init '+tempdir+'/test/foo/baz/git_workdir -b branchname')
|
||||
os.system('git init '+tempdir+'/test/foo/baz/git_workdir_empty -b branchname')
|
||||
os.system('git init --bare '+tempdir+'/test/foo/baz/git_bare -b branchname')
|
||||
os.system('git init --bare '+tempdir+'/test/foo/baz/git_bare_empty -b branchname')
|
||||
os.system('cd '+tempdir+'/test/foo/baz/git_workdir && echo a > toto')
|
||||
os.system('cd '+tempdir+'/test/foo/baz/git_workdir && git add toto')
|
||||
os.system('cd '+tempdir+'/test/foo/baz/git_workdir&& GIT_COMMITTER_DATE="Sun Feb 21 18:00 2020 +0000" GIT_AUTHOR_NAME="Suzanne Soy" GIT_AUTHOR_EMAIL="example@suzanne.soy" GIT_COMMITTER_NAME="Suzanne Soy" GIT_COMMITTER_EMAIL="example@suzanne.soy" git commit -m "example commit for tests" --date="Sun Feb 21 18:00 2020 +0000"')
|
||||
os.system('cd '+tempdir+'/test/foo/baz/git_workdir && git push ../git_bare branchname')
|
||||
#os.system('sqlite3 '+tempdir+'/test/foo/baz/db "create table tbl(x)"')
|
||||
os.system('echo a > '+tempdir+'/test/foo/baz/titi')
|
||||
os.system('cp -ai '+tempdir+' /tmp/xxx')
|
||||
print('')
|
||||
h = subprocess.check_output([os.path.abspath('./hash-files.py'), 'test/foo'], cwd=tempdir).strip()
|
||||
if h == b'8a84206ece36f07d2c408e565ec506bab407d6e1c645eb4a5c7d057049956110':
|
||||
print("test passed")
|
||||
else:
|
||||
print("TEST FAILED: got hash " + repr(h))
|
||||
exit(1)
|
Loading…
Reference in New Issue
Block a user