summaryrefslogtreecommitdiffstats
path: root/fit.py
blob: 529b7875fef06721da785fbc038fe6bf52e9b34f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
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))