summaryrefslogtreecommitdiffstats
path: root/fit.py
diff options
context:
space:
mode:
Diffstat (limited to 'fit.py')
-rw-r--r--fit.py162
1 files changed, 162 insertions, 0 deletions
diff --git a/fit.py b/fit.py
new file mode 100644
index 0000000..529b787
--- /dev/null
+++ b/fit.py
@@ -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))