from django.db import models from settings import * from django.conf import settings try: ADMIN_URL = settings.ADMIN_URL except AttributeError: ADMIN_URL='/admin' if ADMIN_URL[-1] == '/': ADMIN_URL=ADMIN_URL[:-1] class Tree(models.Model): mode = models.CharField("file mode/permissions", blank=False,maxlength=4) path = models.CharField("relative path from repo base", maxlength=512) id = models.CharField("hash", maxlength=40,blank=False,primary_key=True) name = models.CharField("name of dir", maxlength=128,blank=False) type = 'tree' def slug(self): #TODO: secure this return ''.join(self.path.replace('"','').replace("'","").strip().lower().split()) class Admin: list_display = ['name', 'id', 'mode'] ordering = ['path','name'] def __str__(self): return self.name def get_absolute_url(self): return "/k/%s/" % self.slug() def get_admin_url(self): return "%s/k/%s/" % (ADMIN_URL, self.id) def update(self): import commands if (not self.id): return self.id = self.id.strip() tree_ls = commands.getoutput(GITPREFIX + ' ls-tree --full-name ' \ + self.id) tree_objs = list() blob_objs = list() for line in tree_ls.splitlines(): l = line.split() if len(l) < 4: continue if l[1] == 'tree': t = Tree(id=l[2]) t.path = ' '.join(l[3:]) if self.path and self.path != '/': t.path = self.path + '/' + t.path t.name = t.path tree_objs.append(t) if l[1] == 'blob': i = Item(id=l[2]) i.path = ' '.join(l[3:]) if self.path and self.path != '/': i.path = self.path + '/' + i.path i.name=i.path blob_objs.append(i) self.tree_objs = tree_objs self.blob_objs = blob_objs self.all_objs = tree_objs + blob_objs self.save() class Item(models.Model): mode = models.CharField("file mode/permissions", blank=False,maxlength=4) path = models.CharField("relative path from repo base", maxlength=512) id = models.CharField("hash", maxlength=40,blank=False,primary_key=True) name = models.CharField("name of dir", maxlength=128,blank=False) size = models.IntegerField("filesize in byte", maxlength=128,blank=False) contents = models.TextField("ASCII contents of the file") type='blob' def slug(self): #TODO: secure this return ''.join(self.name.replace('"','').replace("'","").strip().lower().split()) class Admin: list_display = ['name', 'id', 'size'] search_fields = ['contents'] ordering = ['name'] def __str__(self): return self.name def get_absolute_url(self): return "/k/%s/" % self.slug() def get_admin_url(self): return "%s/k/%s/" % (ADMIN_URL, self.id) def isfig(self): if self.name.find('.') != -1: return True else: return False def update(self): import commands if (not self.id): return self.id = self.id.strip() self.contents = commands.getoutput(GITPREFIX + ' cat-file -p ' \ + self.id) self.size = commands.getoutput(GITPREFIX + ' cat-file -s ' + self.id) if not self.isfig(): self.save() def getfile(self): import commands if (not self.id): return return open(str(GITWIKI_DIR + '/objects/' + self.id[:2] + '/' + self.id[2:]),'r') class Commit(models.Model): id = models.CharField("hash", maxlength=40,blank=False,primary_key=True) rawdiff = models.TextField("ASCII contents of full commit diff") commit_date = models.DateField("Date of commit to repository") author_date = models.DateField("Date commit was writen/created") author = models.CharField("Name of commit author", maxlength=96) author_email = models.CharField("Email address of commit author",\ maxlength=196) committer = models.CharField("Name of committer", maxlength=96) committer_email = models.CharField("Email address of committer", \ maxlength=196) comment = models.TextField("Notes on the commit") parenthash = models.CharField("parent's hash", maxlength=40) #TODO: parent = models.ForeignKey() treehash = models.CharField("tree object's hash", maxlength=40) tree = models.ForeignKey(Tree) type='commit' class Admin: ordering = ['commit_date','author_date','author'] list_display = ['id', 'commit_date', 'author'] def __str__(self): return self.id def get_absolute_url(self): return "/k/commit/%s/" % (self.id) def get_admin_url(self): return "%s/k/commit/%s/" % (ADMIN_URL, self.id) def update(self): import commands,time if (not self.id): return self.id = self.id.strip() raw = commands.getoutput(GITPREFIX + ' cat-file -p ' + self.id) self.rawdiff = commands.getoutput(GITPREFIX + ' diff ' + self.id \ +' | cat') raw = raw.splitlines() if len(raw) < 3: return self.treehash = raw[0].split()[-1].strip() if raw[1].startswith('parent'): self.parenthash = raw[1][6:].strip() raw.pop(1) # Sometimes there are multiple parents; this ignores all but the # first while raw[1].startswith('parent'): raw.pop(1) self.author = raw[1].split()[1] self.author_date = time.ctime(int(raw[1].split()[-2])) self.committer = raw[2].split()[1] self.committer_date = time.ctime(int(raw[2].split()[-2])) self.rawdiff = commands.getoutput(GITPREFIX + ' diff ' \ + self.parenthash + ' ' + self.id + ' | cat') if len(raw) > 3: for l in raw[3:]: self.comment += str(l) + '\n' else: self.comment = '(none)' def fromslug(reqslug): import commands if reqslug == '' or reqslug == '/': f = open(GITWIKI_DIR + '/HEAD','r') head = f.readline().strip().split()[1] f.close() f = open(GITWIKI_DIR + '/'+head,'r') hash = f.readline().strip() f.close() ret = Tree(id=hash) ret.path='/' ret.name='/' ret.reqslug = '/' return ret reqslug = ''.join(reqslug.replace('"','').replace("'","").strip().lower().split()) if reqslug[-1] == '/': reqslug=reqslug[:-1] itemtxt = commands.getoutput(GITPREFIX \ + ' ls-tree -t -r HEAD') if not itemtxt: return None hash, path, type = None, None, None for l in itemtxt.splitlines(): words = l.split() if len(words) < 4: continue ftype = words[1] fhash = words[2] fpath = ' '.join(words[3:]) if fpath[-1] == '/': fpath=fpath[:-1] if ''.join(fpath.replace('"','').replace("'","").strip().lower().split()) == reqslug: hash = fhash path = fpath type = ftype break; if (not hash) or (not type) or (not path): return None if type == 'blob': ret = Item(id=hash) elif type == 'tree': ret = Tree(id=hash) ret.path=path ret.name=path ret.reqslug = reqslug return ret def reposcan(): import os heads = dict() for h in os.listdir(GITWIKI_DIR + '/refs/heads/'): f = open(GITWIKI_DIR + '/refs/heads/' + h,'r') heads[h.strip()] = f.readline().strip() f.close() tags = dict() for t in os.listdir(GITWIKI_DIR + '/refs/tags/'): f = open(GITWIKI_DIR + '/refs/tags/' + t,'r') tags[t.strip()] = f.readline().strip() f.close() return (heads, tags) def newest_items(): num = Item.objects.count() min = num-6 if min < 0: min = 0 return Item.objects.all()[min:num] def shortlog(hash=None,tree=None): import commands if tree: hash=tree.id logtxt = commands.getoutput(GITPREFIX \ + ' log --relative-date --max-count=6 | cat') log_items = logtxt.split('\ncommit ') if (log_items[0] == ''): log_items.pop(0) if (log_items[0].startswith('commit ')): log_items[0] = log_items[0][7:] shortlog = list() for li in log_items: logobj = dict() lines = li.splitlines() if len(lines) < 3: continue logobj['hash'] = lines[0].strip() logobj['shorthash'] = lines[0].strip()[:5] logobj['author'] = lines[1][8:] logobj['date'] = lines[2][8:] if len(lines) > 4: logobj['description'] = lines[4][4:] else: logobj['description'] = '(none)' # here we truncate commit comments for shortlogs logobj['shortdescription'] = logobj['description'][:128] shortlog.append(logobj) return shortlog