def get(self, arg): if arg == 'HEAD': self.response.out.write('ref: refs/heads/master\n') elif arg == 'info/refs': service = self.request.get('service') if service in ('git-upload-pack', 'git-receive-pack'): return self.smart_upload_pack(service) inforefs = self.store.getinforefs() infostr = ''.join(['%s\t%s\n' % (sha, ref) for ref, sha in inforefs.iteritems()]) self.response.out.write(infostr) elif arg.startswith('objects/') and arg[10] == '/': sha = arg[8:10] + arg[11:49] compressed = self.store.getobjz(sha) self.response.headers['Content-Type'] = 'application/octet-stream' self.response.out.write(compressed) elif arg.startswith('edit/'): if not self.has_write_perm: return app.common.error_403(self) editurl = arg[5:] obj = self.repo.traverse(editurl) if obj is None: self.response.out.write('404 not found') elif babygit.obj_type(obj) == 'blob': contents = babygit.obj_contents(obj) self.response.out.write('<html><title>Editing: ' + cgi.escape(editurl) + '</title>\n') self.response.out.write('<body>\n') self.response.out.write('<h1>Editing ' + cgi.escape(editurl) + '</h1>\n') self.response.out.write('<form method="post" action="/git/save/' + urllib.quote(editurl) + '">\n') self.response.out.write('<textarea cols="80" rows="24" name="content">\n') for line in contents.split('\n'): self.response.out.write(cgi.escape(line) + '\n') self.response.out.write('</textarea>') self.response.out.write('<br />\n') self.response.out.write('<input type="submit" value="Save">\n') elif arg.startswith('gc/'): # TODO: should be POST, this should just serve the form return self.serve_gc() else: # try to serve a raw blob obj = self.repo.traverse(arg) if obj is None: self.response.out.write('404 not found') elif babygit.obj_type(obj) == 'blob': self.response.headers['Content-Type'] = 'text/plain; charset=UTF-8'; contents = babygit.obj_contents(obj) self.response.out.write(contents) else: if len(arg) and not arg.endswith('/'): url = self.request.url + '/' self.redirect(url) return ptree = self.repo.parse_tree(obj) html = ['<html><ul>'] for mode, name, sha in ptree: fn = name if mode == '40000': fn += '/' html.append('<li><a href="' + fn + '">' + fn + '</a></li>\n') self.response.out.write(''.join(html))
def get(self, arg): if arg == "HEAD": self.response.out.write("ref: refs/heads/master\n") elif arg == "info/refs": service = self.request.get("service") if service in ("git-upload-pack", "git-receive-pack"): return self.smart_upload_pack(service) inforefs = self.store.getinforefs() infostr = "".join(["%s\t%s\n" % (sha, ref) for ref, sha in inforefs.iteritems()]) self.response.out.write(infostr) elif arg.startswith("objects/") and arg[10] == "/": sha = arg[8:10] + arg[11:49] compressed = self.store.getobjz(sha) self.response.headers["Content-Type"] = "application/octet-stream" self.response.out.write(compressed) elif arg.startswith("edit/"): if not self.has_write_perm: return app.common.error_403(self) editurl = arg[5:] obj = self.repo.traverse(editurl) if obj is None: self.response.out.write("404 not found") elif babygit.obj_type(obj) == "blob": contents = babygit.obj_contents(obj) self.response.out.write("<html><title>Editing: " + cgi.escape(editurl) + "</title>\n") self.response.out.write("<body>\n") self.response.out.write("<h1>Editing " + cgi.escape(editurl) + "</h1>\n") self.response.out.write('<form method="post" action="/git/save/' + urllib.quote(editurl) + '">\n') self.response.out.write('<textarea cols="80" rows="24" name="content">\n') for line in contents.split("\n"): self.response.out.write(cgi.escape(line) + "\n") self.response.out.write("</textarea>") self.response.out.write("<br />\n") self.response.out.write('<input type="submit" value="Save">\n') elif arg.startswith("gc/"): # TODO: should be POST, this should just serve the form return self.serve_gc() else: # try to serve a raw blob obj = self.repo.traverse(arg) if obj is None: self.response.out.write("404 not found") elif babygit.obj_type(obj) == "blob": self.response.headers["Content-Type"] = "text/plain; charset=UTF-8" contents = babygit.obj_contents(obj) self.response.out.write(contents) else: if len(arg) and not arg.endswith("/"): url = self.request.url + "/" self.redirect(url) return ptree = self.repo.parse_tree(obj) html = ["<html><ul>"] for mode, name, sha in ptree: fn = name if mode == "40000": fn += "/" html.append('<li><a href="' + fn + '">' + fn + "</a></li>\n") self.response.out.write("".join(html))
def traverse(self, path, root=None): if root is None: root = self.getroot() splitpath = path.split('/') if splitpath[-1] == '': splitpath.pop() sha = root obj = self.store.getobj(sha) for i in range(len(splitpath)): if babygit.obj_type(obj) != 'tree': raise ValueError('expected tree') ptree = self.parse_tree(obj) mode_sha = self.find_in_tree(ptree, splitpath[i]) if mode_sha is None: return None obj = self.store.getobj(mode_sha[1]) t = babygit.obj_type(obj) return obj
def gc_action(sha, obj): idx[sha] = off[0] t = babygit.obj_type(obj) s = babygit.obj_size(obj) enc_t_s = self.encode_type_and_size(t, s) pack.write(enc_t_s) off[0] += len(enc_t_s) compressed = zlib.compress(babygit.obj_contents(obj)) pack.write(compressed) off[0] += len(compressed)
def getroot(self, commitsha=None): if commitsha is None: commitsha = self.gethead() obj = self.store.getobj(commitsha) if babygit.obj_type(obj) != 'commit': raise ValueError('expected commit obj type') commitlines = obj[obj.find('\x00') + 1:].split('\n') for l in commitlines: if l.startswith('tree'): return l.split(' ')[1]
def ls(store, sha, prefix = ''): r = repo.Repo(store) blob = store.getobj(sha) if blob is None: return t = babygit.obj_type(blob) if t == 'tree': for mode, name, child_sha in r.parse_tree(blob): print mode, prefix + '/' + name ls(store, child_sha, prefix + '/' + name)
def parse_tree(self, obj): if babygit.obj_type(obj) != 'tree': raise ValueError('wrong obj type') ix = obj.find('\x00') + 1 if ix == 0: raise ValueError('missing nul') result = [] while ix < len(obj): nul_ix = obj.find('\x00', ix) mode_and_name = obj[ix:nul_ix] mode, name = mode_and_name.split(' ', 1) sha = binascii.hexlify(obj[nul_ix + 1:nul_ix + 21]) result.append((mode, name, sha)) ix = nul_ix + 21 return result
def send_packfile(self, objs, out): m = hashlib.sha1() header = 'PACK' + struct.pack('>II', 2, len(objs)) out.write(header) m.update(header) for ref, obj in objs: t = babygit.obj_type(obj) s = babygit.obj_size(obj) #if s != len(babygit.obj_contents(obj)): # logging.debug('size mismatch') enc_t_s = self.encode_type_and_size(t, s) out.write(enc_t_s) m.update(enc_t_s) compressed = zlib.compress(babygit.obj_contents(obj)) out.write(compressed) m.update(compressed) out.write(m.digest())
def parse_commit(self, obj): result = {} result['parents'] = [] if babygit.obj_type(obj) != 'commit': raise ValueError('wrong obj type') lines = babygit.obj_contents(obj).split('\n') for i, l in enumerate(lines): if l.startswith('tree '): result['tree'] = l.split(' ')[1] elif l.startswith('parent '): result['parents'].append(l.split(' ')[1]) elif l.startswith('author '): result['author'] = l.split(' ', 1)[1] elif l.startswith('committer '): result['committer'] = l.split(' ', 1)[1] elif l == '': result['msg'] = '\n'.join(lines[i + 1:]) break return result
def walk_action(self, wants, haves, action): done = set() queue = set(wants) while queue: sha = queue.pop() if sha in done or sha in haves: continue obj = self.store.getobj(sha) if obj is None: logging.debug('walk, can\'t find ' + ` sha `) break action(sha, obj) done.add(sha) t = babygit.obj_type(obj) if t == 'commit': for l in babygit.obj_contents(obj).split('\n'): if l == '': break elif l.startswith('tree ') or l.startswith('parent '): queue.add(l.rstrip('\n').split(' ')[1]) elif t == 'tree': for mode, name, sha in self.parse_tree(obj): queue.add(sha)