diff options
Diffstat (limited to 'fit.py')
-rw-r--r-- | fit.py | 162 |
1 files changed, 162 insertions, 0 deletions
@@ -0,0 +1,162 @@ +import os, time + +from pygit2 import Repository, Signature +from binascii import b2a_hex + + +class Fit: + def __init__(self, path): + self.repo = Repository(path) + + def _insert_node(self, node_oid, path, root_oid): + filename = os.path.basename(path) + + if root_oid: + root = self.repo.TreeBuilder(root_oid) + current_node = self.repo[root_oid] + else: + root = self.repo.TreeBuilder() + current_node = root.write() + + entries = path.split('/')[:-1] + entries.reverse() + + # search for existing nodes in path + tree_path = [('/', root)] + while len(entries) > 0: + if entries[-1] not in current_node: + break + + entry = entries.pop() + current_node = self.repo[current_node[entry].oid] + tree_path.append(( + entry, self.repo.TreeBuilder(current_node.oid) + )) + + # create node + if len(entries) > 0: + tmp = self.repo.TreeBuilder() + elif len(tree_path) > 0: + tmp = tree_path[-1][1] + else: + tmp = root + + tmp.insert(filename, node_oid, 0100644) + current = tmp.write() + + # create new nodes bottom-up for our node + size = len(entries) + for i, entry in enumerate(entries): + if i < (size - 1): + tmp = self.repo.TreeBuilder() + tmp.insert(entry, current, 040000) + current = tmp.write() + else: + tree_path.append((entry, None)) + + # connect existing nodes with created nodes + pre = tree_path.pop()[0] + tree_path.reverse() + for name, builder in tree_path: + builder.insert(pre, current, 040000) + current = builder.write() + pre = name + + return current + + + def _get_last_commit(self): + head = self.repo.lookup_reference('HEAD').resolve() + return self.repo[head.oid] + + + def add_file(self, data, git_path, tags): + try: + commit = self._get_last_commit() + parents = [commit.oid] + root = commit.tree.oid + + except: + parents = [] + root = None + + + blob_oid = self.repo.create_blob(data) + root = self._insert_node(blob_oid, git_path, root) + filename = os.path.basename(git_path) + for tag in tags: + name = 'tags/%s/%s' % (tag, filename) + root = self._insert_node(blob_oid, name, root) + + author = committer = Signature('Fit', 'Fit@fit.de', int(time.time()), 120) + + commit = self.repo.create_commit( + 'HEAD', + author, + committer, + 'added %s' % git_path, + root, + parents + ) + + return b2a_hex(commit).decode('ascii') + + + def get_all_files(self): + try: + commit = self._get_last_commit() + files = commit.tree['files'].to_object() + return ((x.name, x.hex) for x in files) + except: + return [] + + + def get_file(self, oid): + return self.repo[oid].data + + + def get_all_tags(self): + try: + commit = self._get_last_commit() + tags = commit.tree['tags'].to_object() + return ((x.name, x.hex) for x in tags) + except: + return [] + + + def get_files_for_tags(self, tags): + try: + commit = self._get_last_commit() + tree = commit.tree['tags'].to_object() + entries = [ tree[x.encode('ascii')].to_object() for x in tags] + add = lambda x,y: x+y + return reduce(add, + map(lambda entry: [ (x.name, x.hex) for x in entry ],entries) + ) + except: + return [] + + + def get_file_with_tags(self, oid): + tags = [] + for name, tag_oid in fit.get_all_tags(): + for entry in self.repo[tag_oid]: + if entry.oid == oid: + tags.append((name, tag_oid)) + + return tags + + +#fit = Fit('tmp/fit') +#fit.add_file('main.c', 'files/main.c', ['alp2', '2007']) +# +#print("All files") +#for name, oid in fit.get_all_files(): +# tags = ','.join(map(lambda x: x[0], fit.get_file_with_tags(oid))) +# print("* %s (%s)" % (name, tags)) +# #print(fit.get_file(oid) + "\n") +# +#print("\nAll tags") +#for name, oid in fit.get_all_tags(): +# files = ','.join(map(lambda x: x[0], fit.get_files_for_tags([name]))) +# print("* %s (%s)" % (name, files)) |