def test_show_blob(self): repo = Jagare(self.path) ls = repo.ls_tree('master') blobs = [item['sha'] for item in ls if item['type'] == 'blob'] for sha in blobs: ret = repo.show(sha) assert ret['type'] == 'blob'
def test_blame(self): repo = Jagare(self.path) tree = repo.ls_tree('master') blobs = [item['path'] for item in tree if item['type'] == 'blob'] for node in blobs: blame_ret = repo.blame('master', path=node) if node == 'new.txt': for hunk in blame_ret['hunks']: self.assertEquals( '4bc90207e76d68d5cda435e67c5f85a0ce710f44', hunk['final_commit_id']) self.assertEquals(hunk['final_committer']['email'], '*****@*****.**') self.assertEquals(hunk['orig_committer']['email'], '*****@*****.**') if node == 'README.md': for hunk in blame_ret['hunks']: self.assertEquals( 'e9f35005ca7d004d87732598f761b1be3b9d1c61', hunk['final_commit_id']) self.assertEquals(hunk['final_committer']['email'], '*****@*****.**') self.assertEquals(hunk['orig_committer']['email'], '*****@*****.**')
def ls_tree(self, path, ref, req_path, recursive, with_size, with_commit, name_only): try: repo = Jagare(path) ret = repo.ls_tree(ref, path=req_path, recursive=recursive, size=with_size, with_commit=with_commit, name_only=name_only) return json.dumps(ret) except Exception as e: raise ServiceUnavailable(repr(e))
def test_blame(self): repo = Jagare(self.path) tree = repo.ls_tree('master') blobs = [item['path'] for item in tree if item['type'] == 'blob'] for node in blobs: blame_ret = repo.blame('master', path=node) if node == 'new.txt': for hunk in blame_ret['hunks']: self.assertEquals('4bc90207e76d68d5cda435e67c5f85a0ce710f44', hunk['final_commit_id']) self.assertEquals(hunk['final_committer']['email'], '*****@*****.**') if node == 'README.md': for hunk in blame_ret['hunks']: self.assertEquals('e9f35005ca7d004d87732598f761b1be3b9d1c61', hunk['final_commit_id']) self.assertEquals(hunk['final_committer']['email'], '*****@*****.**')
class GistRepo(Repo): provided_features = [] # TODO: move to utils PREFIX = 'gistfile' def __init__(self, gist): self.type = "gist" self.gist = gist self.name = gist.name self.path = gist.repo_path self.repo = Jagare(gist.repo_path) @classmethod def init(cls, gist): Jagare.init(gist.repo_path, bare=True) def clone(self, gist): super(GistRepo, self).clone(gist.repo_path, bare=True) def get_files(self): files = [] if self.empty: return files tree = self.repo.ls_tree('HEAD') for f in tree: files.append([f['sha'], f['name']]) return files # TODO: move to utils def check_filename(self, fn): for c in (' ', '<', '>', '|', ';', ':', '&', '`', "'"): fn = fn.replace(c, '\%s' % c) fn = fn.replace('/', '') return fn def commit_all_files(self, names, contents, oids, author): data = [] for i, (name, content, oid) in enumerate(zip(names, contents, oids), start=1): if not name and not content: continue if not name: name = self.PREFIX + str(i) name = self.check_filename(name) data.append([name, content, 'insert']) files = self.get_files() for sha, name in files: if name in names: continue data.append([name, '', 'remove']) self.repo.commit_file(branch='master', parent='master', author_name=author.name, author_email=author.email, message=' ', reflog=' ', data=data) def is_commit(self, ref): commit = self.repo.show(ref) if commit: return True
class ProjectRepo(Repo): provided_features = [ 'project', 'fulltext', 'moreline', 'side_by_side', 'patch_actions' ] def __init__(self, project, pull=None): self.type = "project" self.pull = pull self.project = project self.project_name = project.name self.name = project.name self.path = project.repo_path self.repo = Jagare(self.path) # TODO: url @property def api_url(self): return '' @property def context_url(self): return 'moreline' @property def fulltext_url(self): return 'fulltext' @property def branches(self): return self.repo.branches @property def tags(self): return self.repo.tags def get_tree(self, ref, path=None, recursive=False): tree = self.repo.ls_tree(ref, path=path, recursive=recursive) if not tree: return None return Tree(self, tree) def get_file_by_ref(self, ref): blob = self.repo.show(ref) if not blob: return None return blob['data'] def get_contexts(self, ref, path, line_start, line_end): def fix_line_index(index, max_i, min_i=0): i = index - 1 i = max(i, min_i) i = min(i, max_i) return i lines = self.get_file_by_lines(ref, path) if not lines: return None n = len(lines) start = fix_line_index(line_start, n) end = fix_line_index(line_end, n) return lines[start:end] def blame_file(self, *w, **kw): blame = self.repo.blame(*w, **kw) return blame def get_renamed_files(self, ref, path=None): return self.repo.detect_renamed(ref) def commit_file(self, *w, **kw): return self.repo.commit_file(*w, **kw) def get_temp_branch(self): commit = self.get_commit('HEAD') return 'patch_tmp' + time.strftime('%Y%m%d%H%M%S-') + commit.sha[10] def get_patch_file(self, ref, from_ref=None): return self.repo.format_patch(ref, from_ref) def get_diff_file(self, ref, from_ref=None): _raw_diff = self.get_raw_diff(ref, from_ref) if not _raw_diff: return '' return _raw_diff['diff'].patch def get_last_update_timestamp(self): commit = self.get_last_commit('HEAD') if not commit: return 0 return int(commit.author_timestamp) @classmethod def init(cls, path, work_path=None, bare=True): return Jagare.init(path, work_path=work_path, bare=bare) @classmethod def mirror(cls, url, path, env=None): Jagare.mirror(url, path, env=env) def add_remote(self, name, url): return self.repo.add_remote(name, url) def add_remote_hub(self, name, url): self.add_remote('hub/%s' % name, url) def update_ref(self, ref, value): return self.repo.update_ref(ref, value) def sha(self, rev='HEAD'): return self.repo.sha(rev) def merge_base(self, to_sha, from_sha): return self.repo.merge_base(to_sha, from_sha) def remotes(self): return self.repo.remotes() def fetch_all(self): self.repo.fetch_all() def fetch(self, name): self.repo.fetch(name) def archive(self): super(ProjectRepo, self).archive(self.project.name) def get_latest_update_branches(self): refs = self.repo.listall_references() refs = filter(lambda r: r.startswith('refs/heads'), refs) current_time = time.time() latest_branches = [] for ref in refs: commit_time = self.repo.lookup_reference( ref).get_object().commit_time delta = current_time - commit_time if delta < LATEST_UPDATE_REF_THRESHOLD: latest_branches.append((commit_time, ref.split('/')[-1])) return sorted(latest_branches, key=lambda r: r[0], reverse=True) def get_all_src_objects(self): refs = self.repo.listall_references() refs = filter(lambda r: r.startswith('refs/heads'), refs) commits_dict = {} for ref in refs: commits = self.repo.rev_list(ref) commits = {c['sha']: c for c in commits} commits_dict.update(commits) commits = sorted(commits_dict.values(), key=lambda x: x['time'], reverse=True) pruned_set = set() objects_dict = {} treenode_list = [(commit['sha'], commit['tree'], '') for commit in commits] while treenode_list: commit_id, tree_id, path = treenode_list.pop() if tree_id in pruned_set: continue pruned_set.add(tree_id) objects = self.repo.ls_tree(tree_id, size=True) for obj in objects: obj_id = obj['id'] obj_path = '%s/%s' % (path, obj['name']) if obj['type'] == 'tree': treenode_list.append((commit_id, obj_id, obj_path)) elif obj['type'] == 'blob': if obj_id not in objects_dict: commit = commits_dict[commit_id] objects_dict[obj_id] = dict( path=obj_path[1:], commit=commit_id, size=obj['size'], commit_time=commit['time'], committer=commit['committer']['name']) return objects_dict
class ProjectRepo(Repo): provided_features = ['project', 'fulltext', 'moreline', 'side_by_side', 'patch_actions'] def __init__(self, project, pull=None): self.type = "project" self.pull = pull self.project = project self.project_name = project.name self.name = project.name self.path = project.repo_path self.repo = Jagare(self.path) # TODO: url @property def api_url(self): return '' @property def context_url(self): return 'moreline' @property def fulltext_url(self): return 'fulltext' @property def branches(self): return self.repo.branches @property def tags(self): return self.repo.tags def get_tree(self, ref, path=None, recursive=False): tree = self.repo.ls_tree(ref, path=path, recursive=recursive) if not tree: return None return Tree(self, tree) def get_file_by_ref(self, ref): blob = self.repo.show(ref) if not blob: return None return blob['data'] def get_contexts(self, ref, path, line_start, line_end): def fix_line_index(index, max_i, min_i=0): i = index - 1 i = max(i, min_i) i = min(i, max_i) return i lines = self.get_file_by_lines(ref, path) if not lines: return None n = len(lines) start = fix_line_index(line_start, n) end = fix_line_index(line_end, n) return lines[start:end] def blame_file(self, *w, **kw): blame = self.repo.blame(*w, **kw) return blame def get_renamed_files(self, ref, path=None): return self.repo.detect_renamed(ref) def commit_file(self, *w, **kw): return self.repo.commit_file(*w, **kw) def get_temp_branch(self): commit = self.get_commit('HEAD') return 'patch_tmp' + time.strftime('%Y%m%d%H%M%S-') + commit.sha[10] def get_patch_file(self, ref, from_ref=None): return self.repo.format_patch(ref, from_ref) def get_diff_file(self, ref, from_ref=None): _raw_diff = self.get_raw_diff(ref, from_ref) if not _raw_diff: return '' return _raw_diff['diff'].patch def get_last_update_timestamp(self): commit = self.get_last_commit('HEAD') if not commit: return 0 return int(commit.author_timestamp) @classmethod def init(cls, path, work_path=None, bare=True): return Jagare.init(path, work_path=work_path, bare=bare) @classmethod def mirror(cls, url, path, env=None): Jagare.mirror(url, path, env=env) def add_remote(self, name, url): return self.repo.add_remote(name, url) def add_remote_hub(self, name, url): self.add_remote('hub/%s' % name, url) def update_ref(self, ref, value): return self.repo.update_ref(ref, value) def sha(self, rev='HEAD'): return self.repo.sha(rev) def merge_base(self, to_sha, from_sha): return self.repo.merge_base(to_sha, from_sha) def remotes(self): return self.repo.remotes() def fetch_all(self): self.repo.fetch_all() def fetch(self, name): self.repo.fetch(name) def archive(self): super(ProjectRepo, self).archive(self.project.name) def get_latest_update_branches(self): refs = self.repo.listall_references() refs = filter(lambda r:r.startswith('refs/heads'), refs) current_time = time.time() latest_branches = [] for ref in refs: commit_time = self.repo.lookup_reference(ref).get_object().commit_time delta = current_time - commit_time if delta < LATEST_UPDATE_REF_THRESHOLD: latest_branches.append((commit_time, ref.split('/')[-1])) return sorted(latest_branches, key=lambda r:r[0], reverse=True) def get_all_src_objects(self): refs = self.repo.listall_references() refs = filter(lambda r: r.startswith('refs/heads'), refs) commits_dict = {} for ref in refs: commits = self.repo.rev_list(ref) commits = {c['sha']: c for c in commits} commits_dict.update(commits) commits = sorted(commits_dict.values(), key=lambda x: x['time'], reverse=True) pruned_set = set() objects_dict = {} treenode_list = [(commit['sha'], commit['tree'], '') for commit in commits] while treenode_list: commit_id, tree_id, path = treenode_list.pop() if tree_id in pruned_set: continue pruned_set.add(tree_id) objects = self.repo.ls_tree(tree_id, size=True) for obj in objects: obj_id = obj['id'] obj_path = '%s/%s' % (path, obj['name']) if obj['type'] == 'tree': treenode_list.append((commit_id, obj_id, obj_path)) elif obj['type'] == 'blob': if obj_id not in objects_dict: commit = commits_dict[commit_id] objects_dict[obj_id] = dict(path=obj_path[1:], commit=commit_id, size=obj['size'], commit_time=commit['time'], committer=commit['committer']['name'] ) return objects_dict
class GistRepo(Repo): provided_features = [] # TODO: move to utils PREFIX = "gistfile" def __init__(self, gist): self.type = "gist" self.gist = gist self.name = gist.name self.path = gist.repo_path self.repo = Jagare(gist.repo_path) @classmethod def init(cls, gist): Jagare.init(gist.repo_path, bare=True) def clone(self, gist): super(GistRepo, self).clone(gist.repo_path, bare=True) def get_files(self): files = [] if self.empty: return files tree = self.repo.ls_tree("HEAD") for f in tree: files.append([f["sha"], f["name"]]) return files # TODO: move to utils def check_filename(self, fn): for c in (" ", "<", ">", "|", ";", ":", "&", "`", "'"): fn = fn.replace(c, "\%s" % c) fn = fn.replace("/", "") return fn def commit_all_files(self, names, contents, oids, author): data = [] for i, (name, content, oid) in enumerate(zip(names, contents, oids), start=1): if not name and not content: continue if not name: name = self.PREFIX + str(i) name = self.check_filename(name) data.append([name, content, "insert"]) files = self.get_files() for sha, name in files: if name in names: continue data.append([name, "", "remove"]) self.repo.commit_file( branch="master", parent="master", author_name=author.name, author_email=author.email, message=" ", reflog=" ", data=data, ) def is_commit(self, ref): commit = self.repo.show(ref) if commit: return True
class ProjectRepo(Repo): provided_features = ["project", "fulltext", "moreline", "side_by_side", "patch_actions"] def __init__(self, project, pull=None): self.type = "project" self.pull = pull self.project = project self.project_name = project.name self.name = project.name self.path = project.repo_path self.repo = Jagare(self.path) # TODO: url @property def api_url(self): return "" @property def context_url(self): return "moreline" @property def fulltext_url(self): return "fulltext" @property def branches(self): return self.repo.branches @property def tags(self): return self.repo.tags def get_tree(self, ref, path=None, recursive=False, with_commit=False, recursive_with_tree_node=False): tree = self.repo.ls_tree(ref, path=path, recursive=recursive, with_commit=with_commit) # recursive_with_tree_node=recursive_with_tree_node) if not tree: return None return Tree(self, tree) def get_file_by_ref(self, ref): blob = self.repo.show(ref) if not blob: return None return blob["data"] def get_contexts(self, ref, path, line_start, line_end): def fix_line_index(index, max_i, min_i=0): i = index - 1 i = max(i, min_i) i = min(i, max_i) return i lines = self.get_file_by_lines(ref, path) if not lines: return None n = len(lines) start = fix_line_index(line_start, n) end = fix_line_index(line_end, n) return lines[start:end] def blame_file(self, *w, **kw): blame = self.repo.blame(*w, **kw) if not blame: return None return Blame(self, blame) def get_renamed_files(self, ref, path=None): return self.repo.detect_renamed(ref) def commit_file(self, *w, **kw): return self.repo.commit_file(*w, **kw) def get_temp_branch(self): commit = self.get_commit("HEAD") return "patch_tmp" + time.strftime("%Y%m%d%H%M%S-") + commit.sha[10] def get_patch_file(self, ref, from_ref=None): return self.repo.format_patch(ref, from_ref) def get_diff_file(self, ref, from_ref=None): _raw_diff = self.get_raw_diff(ref, from_ref) if not _raw_diff: return "" patch = _raw_diff["diff"].patch if not patch: return "" return patch @classmethod def init(cls, path, work_path=None, bare=True): return Jagare.init(path, work_path=work_path, bare=bare) @classmethod def mirror(cls, url, path, env=None): Jagare.mirror(url, path, env=env) def add_remote(self, name, url): return self.repo.add_remote(name, url) def add_remote_hub(self, name, url): self.add_remote("hub/%s" % name, url) def update_ref(self, ref, value): result = None try: result = self.repo.update_ref(ref, value) except JagareError: # FIXME: logging # FIXME: more meaningful error (JagareError) pass return result def sha(self, rev="HEAD"): return self.repo.sha(rev) def merge_base(self, to_sha, from_sha): return self.repo.merge_base(to_sha, from_sha) @property def remotes(self): return self.repo.remotes def fetch_all(self): self.repo.fetch_all() def fetch(self, name): self.repo.fetch(name) def fetch_(self, *w, **kw): return self.repo.fetch_(*w, **kw) def get_latest_update_branches(self): refs = self.repo.listall_references() refs = filter(lambda r: r.startswith("refs/heads"), refs) current_time = time.time() latest_branches = [] for ref in refs: commit_time = self.repo.lookup_reference(ref).get_object().commit_time # noqa delta = current_time - commit_time if delta < LATEST_UPDATE_REF_THRESHOLD: latest_branches.append((commit_time, ref.split("/")[-1])) return sorted(latest_branches, key=lambda r: r[0], reverse=True) def get_all_src_objects(self): refs = self.repo.listall_references() refs = filter(lambda r: r.startswith("refs/heads"), refs) commits_dict = {} for ref in refs: commits = self.repo.rev_list(ref) commits = {c["sha"]: c for c in commits} commits_dict.update(commits) commits = sorted(commits_dict.values(), key=lambda x: x["committer"]["time"], reverse=True) pruned_set = set() objects_dict = {} treenode_list = [(commit["sha"], commit["tree"], "") for commit in commits] while treenode_list: commit_id, tree_id, path = treenode_list.pop() if tree_id in pruned_set: continue pruned_set.add(tree_id) objects = self.repo.ls_tree(tree_id, size=True) for obj in objects: obj_id = obj["id"] obj_path = "%s/%s" % (path, obj["name"]) if obj["type"] == "tree": treenode_list.append((commit_id, obj_id, obj_path)) elif obj["type"] == "blob": if obj_id not in objects_dict: commit = commits_dict[commit_id] objects_dict[obj_id] = dict( path=obj_path[1:], commit=commit_id, size=obj["size"], commit_time=datetime.fromtimestamp(commit["committer"]["time"]), committer=commit["committer"]["name"], ) return objects_dict