def __init__(self): pubsub = PubSub() events_dispatcher = EventsDispatcher(pubsub) display = self.display_surface() repo = Repository(config["repo_path"]) branches = repo.listall_branches() drawer = Drawer(repo, branches, display, pubsub) pubsub.sub("on_program_exit", self.exit_program) self.main_loop = MainLoop(display, drawer, events_dispatcher) self.init_screen()
def _list_remote_branches( repo: pygit2.Repository, remote: str = 'origin', exclude_remote_of_head: bool = True) -> Iterator[pygit2.Branch]: remote_prefix = remote + '/' remote_head = remote + '/HEAD' remote_of_local_head = remote + '/' + repo.head.shorthand for branch_name in repo.listall_branches(pygit2.GIT_BRANCH_REMOTE): if not branch_name.startswith(remote_prefix): continue if branch_name == remote_head: continue if exclude_remote_of_head and branch_name == remote_of_local_head: continue yield repo.lookup_branch(branch_name, pygit2.GIT_BRANCH_REMOTE)
def test_install(repo: Repository, template_repo: Repository): battenberg = Battenberg(repo) battenberg.install(template_repo.workdir, no_input=True) assert battenberg.is_installed() # Ensure we have the appropriate branches we expect. assert not {'master', 'template'} - set(repo.listall_branches()) # Ensure we have a valid structure for the template branch. template_oids = { ref.oid_new for ref in repo.references['refs/heads/template'].log() } template_commits = [repo[oid].message for oid in template_oids] assert template_commits == ['Prepared template installation'] # Ensure we have valid merge commit from the template branch -> master. template_install_message = f'commit (merge): Installed template \'{template_repo.workdir}\'' master_merge_ref = find_ref_from_message(repo, template_install_message) assert master_merge_ref # Ensure the merge commit was derived from the template branch. assert not template_oids - set(repo[master_merge_ref.oid_new].parent_ids)
class GitStorage(BaseStorage): _backend = None def __init__(self, context, repo_path=None): self.context = context rp = IStorageInfo(context).path try: self.repo = Repository(discover_repository(rp)) except KeyError: # discover_repository may have failed. raise PathNotFoundError('repository does not exist at path') self.checkout() # defaults to HEAD. @property def empty_root(self): return {'': '_empty_root'} def _get_empty_root(self): return self.empty_root def _get_obj(self, path, cls=None): if path == '' and self._commit is None: # special case return self._get_empty_root() if self._commit is None: raise PathNotFoundError('repository is empty') root = self._commit.tree try: breadcrumbs = [] fragments = list(reversed(path.split('/'))) node = root oid = None while fragments: fragment = fragments.pop() if not fragment == '': # no empty string entries, also skips over '//' and # leaves the final node (if directory) as the tree. oid = node[fragment].oid node = self.repo.get(oid) breadcrumbs.append(fragment) if node is None: # strange. Looks like it's either submodules only # have entry nodes or pygit2 doesn't fully support # this. Try to manually resolve the .gitmodules # file. if cls is None: # Only return this if a specific type was not # expected. submods = parse_gitmodules(self.repo.get( root[GIT_MODULE_FILE].oid).data) submod = submods.get('/'.join(breadcrumbs)) if submod: fragments.reverse() return { '': '_subrepo', 'location': submod, 'path': '/'.join(fragments), 'rev': oid.hex, } if node and (cls is None or isinstance(node, cls)): return node except KeyError: # can't find what is needed in repo, raised by pygit2 raise PathNotFoundError('path not found') # not what we were looking for. if cls == Tree: raise PathNotDirError('path not dir') elif cls == Blob: raise PathNotFileError('path not file') raise PathNotFoundError('path not found') @property def _commit(self): return self.__commit @property def rev(self): if self.__commit: return self.__commit.hex return None @property def shortrev(self): # TODO this is an interim solution. if self.rev: return self.rev[:12] def basename(self, name): return name.split('/')[-1] def checkout(self, rev=None): # None maps to the default revision. if rev is None: rev = 'HEAD' try: self.__commit = self.repo.revparse_single(rev) except KeyError: if rev == 'HEAD': # probably a new repo. self.__commit = None return raise RevisionNotFoundError('revision %s not found' % rev) # otherwise a RevisionNotFoundError should be raised. def files(self): def _files(tree, current_path=None): results = [] for node in tree: if current_path: name = '/'.join([current_path, node.name]) else: name = node.name obj = self.repo.get(node.oid) if isinstance(obj, Blob): results.append(name) elif isinstance(obj, Tree): results.extend(_files(obj, name)) return results if not self._commit: return [] results = _files(self._commit.tree) return results def file(self, path): return self._get_obj(path, Blob).data def listdir(self, path): if path: tree = self._get_obj(path, Tree) else: if self._commit is None: return [] tree = self._commit.tree return [entry.name for entry in tree] def format(self, **kw): # XXX backwards compatibility?? return kw def log(self, start, count, branch=None, shortlog=False): """ start and branch are literally the same thing. """ def _log(iterator): for pos, commit in iterator: if pos == count: raise StopIteration yield { 'author': commit.committer.name, 'email': self._commit.committer.email, 'date': self.strftime(committer_dt(commit.committer)), 'node': commit.hex, 'rev': commit.hex, 'desc': commit.message } if start is None: # assumption. start = 'HEAD' try: self.repo.revparse_single(start) except KeyError: return [] try: rev = self.repo.revparse_single(start).hex except KeyError: raise RevisionNotFoundError('revision %s not found' % start) iterator = enumerate(self.repo.walk(rev, GIT_SORT_TIME)) return list(_log(iterator)) def pathinfo(self, path): obj = self._get_obj(path) if isinstance(obj, Blob): return self.format(**{ 'type': 'file', 'basename': self.basename(path), 'size': obj.size, 'date': self.strftime(committer_dt(self._commit.committer)), }) elif isinstance(obj, dict): # special cases are represented as dict. if obj[''] == '_subrepo': return self.format(**{ 'type': 'subrepo', 'date': '', 'size': 0, 'basename': self.basename(path), # extra field. 'obj': obj, }) elif obj[''] == '_empty_root': return self.format(**{ 'type': 'folder', 'date': '', 'size': 0, 'basename': self.basename(path), }) # Assume this is a Tree. return self.format(**{ 'basename': self.basename(path), 'size': 0, 'type': 'folder', 'date': '', }) def branches(self): return tuple( (b, self.repo.lookup_branch(b).target.hex) for b in self.repo.listall_branches() ) def tags(self): return tuple( (b[10:], self.repo.lookup_reference(b).target.hex) for b in self.repo.listall_references() if b.startswith('refs/tags') )
c.execute(sql, {"repo_name": repo_name}) result = c.fetchall() if len(result) > 0: # The unique id # for the repo in the database repo_id = result[0][0] else: # The repo isn't in the database yet, so we add it sql = 'INSERT INTO repo (repo_id, name) VALUES (NULL, :repo_name)' c.execute(sql, {"repo_name": repo_name}) conn.commit() # Retrieve the repo_id value generated by the database for the above insert repo_id = c.lastrowid # Loop around for each branch, adding their commits to the database for branch_name in repo.listall_branches(GIT_BRANCH_REMOTE): # Starting with the oldest commit in the branch, add its commits to the database branch = repo.lookup_reference('refs/remotes/' + branch_name) for commit in repo.walk(branch.target, GIT_SORT_TIME | GIT_SORT_REVERSE): # If requested, display the commit info for debugging purposes if debug == 1: print "commit {0}".format(commit.hex) print "Author: {0} <{1}>".format(unicode(commit.author.name).encode("utf-8"), commit.author.email) print datetime.utcfromtimestamp(commit.commit_time).strftime('Date: %a %b %d %H:%M:%S %Y +0000\n') print " {0}".format(unicode(commit.message).encode("utf-8")) # Check if the commit already exists in the database. Don't add it if its already there sql = 'SELECT commit_id, hash FROM commits WHERE repo = :repo AND hash = :hash' c.execute(sql, {"repo": repo_id, "hash": commit.hex})
def show_status(srcdir, packages, projects, other_git, ws_state, show_up_to_date=True, cache=None): def create_upstream_status(repo, head_branch, master_branch, master_remote_branch, tracking_branch): status = [] if not repo.head_is_detached and not has_pending_merge(repo): if tracking_branch is not None: if master_remote_branch is not None: if tracking_branch.remote_name != master_remote_branch.remote_name: status.append("@!@{rf}remote '%s'" % tracking_branch.remote_name) if need_push(repo, head_branch): status.append("@!@{yf}needs push") elif need_pull(repo, head_branch): status.append("@!@{cf}needs pull") elif not is_up_to_date(repo, head_branch): status.append("@!@{yf}needs pull -M") else: if head_branch: status.append("@!on branch '%s'" % repo.head.shorthand) else: status.append("empty branch") if master_remote_branch is None: status.append("@!@{rf}no remote") elif master_branch is None: status.append("@!@{rf}untracked remote") if is_up_to_date(repo, master_branch) or need_push( repo, master_branch): if need_pull(repo, head_branch, master_branch): status.append("@!@{cf}needs pull -L") else: if not is_ancestor(repo, master_branch, head_branch): status.append("@!@{yf}needs merge --from-master") if not is_up_to_date(repo, head_branch, master_branch): status.append("@!@{yf}needs merge --to-master") if master_branch is not None and master_remote_branch is not None and ( tracking_branch is None or tracking_branch.name != master_remote_branch.name): if need_push(repo, master_branch): status.append("@!@{yf}%s needs push" % master_branch.shorthand) elif need_pull(repo, master_branch): status.append("@!@{cf}%s needs pull" % master_branch.shorthand) elif not is_up_to_date(repo, master_branch): status.append("@!@{yf}%s needs merge" % master_branch.shorthand) return status def create_local_status(repo, upstream_status, is_dirty): status = [] if repo.head_is_detached: status.append("@!@{rf}detached HEAD") return status if has_pending_merge(repo): if repo.index.conflicts: status.append("@!@{rf}merge conflicts") else: status.append("@!@{yf}merged, needs commit") return status if is_dirty: status.append("@!@{yf}needs commit") status += upstream_status if not status: if not show_up_to_date: return None status.append("@!@{gf}up-to-date") return status table = TableView("Package", "Path", "Status") found_packages = set() for project in projects: repo = Repository(os.path.join(srcdir, project.workspace_path, ".git")) dirty_files = [ a for a, b in iteritems(repo.status()) if b != GIT_STATUS_IGNORED and b != GIT_STATUS_CURRENT ] head_branch = get_head_branch(repo) tracking_branch = head_branch.upstream if head_branch else None master_remote = get_origin(repo, project) if master_remote is not None: master_remote_branch = repo.lookup_branch( "%s/%s" % (master_remote.name, project.master_branch), GIT_BRANCH_REMOTE) master_branch = None if master_remote_branch is not None: for name in repo.listall_branches(GIT_BRANCH_LOCAL): b = repo.lookup_branch(name, GIT_BRANCH_LOCAL) if b.upstream and b.upstream.branch_name == master_remote_branch.branch_name: master_branch = b break else: master_remote_branch = None master_branch = None ws_packages = find_catkin_packages(srcdir, project.workspace_path, cache=cache) found_packages |= set(ws_packages.keys()) upstream_status = create_upstream_status(repo, head_branch, master_branch, master_remote_branch, tracking_branch) for name, pkg_list in iteritems(ws_packages): if name not in packages: continue for pkg in pkg_list: is_dirty = False local_path = os.path.relpath(pkg.workspace_path, project.workspace_path) if dirty_files and local_path == ".": is_dirty = True else: for fpath in dirty_files: if path_has_prefix(fpath, local_path): is_dirty = True break status = create_local_status(repo, upstream_status, is_dirty) if status is not None: head, tail = os.path.split(pkg.workspace_path) pkg_path = escape(head + "/" if tail == name else pkg.workspace_path) table.add_row(escape(name), pkg_path, status) for path in other_git: repo = Repository(os.path.join(srcdir, path, ".git")) dirty_files = [ a for a, b in iteritems(repo.status()) if b != GIT_STATUS_IGNORED and b != GIT_STATUS_CURRENT ] head_branch = get_head_branch(repo) tracking_branch = head_branch.upstream if head_branch else None ws_packages = find_catkin_packages(srcdir, path, cache=cache) found_packages |= set(ws_packages.keys()) upstream_status = create_upstream_status(repo, head_branch, None, None, tracking_branch) for name, pkg_list in iteritems(ws_packages): if name not in packages: continue for pkg in pkg_list: is_dirty = False local_path = os.path.relpath(pkg.workspace_path, path) if dirty_files and local_path == ".": is_dirty = True else: for fpath in dirty_files: if path_has_prefix(fpath, local_path): is_dirty = True break status = create_local_status(repo, upstream_status, is_dirty) if status is not None: head, tail = os.path.split(pkg.workspace_path) pkg_path = escape(head + "/" if tail == name else pkg.workspace_path) table.add_row(escape(name), pkg_path, status) missing = set(packages) - found_packages for name in missing: path_list = [] status = "no git" if name in ws_state.ws_packages: for pkg in ws_state.ws_packages[name]: if not os.path.isdir(os.path.join(srcdir, pkg.workspace_path)): status = "@{rf}deleted" head, tail = os.path.split(pkg.workspace_path) path_list.append( escape(head + "/" if tail == name else pkg.workspace_path)) table.add_row(escape(name), path_list, status) if table.empty(): if found_packages: msg("Everything is @!@{gf}up-to-date@|.\n") else: warning("no Git repositories\n") else: table.sort(0) table.write(sys.stdout)
def show_status(srcdir, packages, projects, other_git, ws_state, show_up_to_date=True, cache=None): def create_upstream_status(repo, head_branch, master_branch, master_remote_branch, tracking_branch): status = [] if not repo.head_is_detached and not has_pending_merge(repo): if tracking_branch is not None: if master_remote_branch is not None: if tracking_branch.remote_name != master_remote_branch.remote_name: status.append("@!@{rf}remote '%s'" % tracking_branch.remote_name) if need_push(repo, head_branch): status.append("@!@{yf}needs push") elif need_pull(repo, head_branch): status.append("@!@{cf}needs pull") elif not is_up_to_date(repo, head_branch): status.append("@!@{yf}needs pull -M") else: if head_branch: status.append("@!on branch '%s'" % repo.head.shorthand) else: status.append("empty branch") if master_remote_branch is None: status.append("@!@{rf}no remote") elif master_branch is None: status.append("@!@{rf}untracked remote") if is_up_to_date(repo, master_branch) or need_push(repo, master_branch): if need_pull(repo, head_branch, master_branch): status.append("@!@{cf}needs pull -L") else: if not is_ancestor(repo, master_branch, head_branch): status.append("@!@{yf}needs merge --from-master") if not is_up_to_date(repo, head_branch, master_branch): status.append("@!@{yf}needs merge --to-master") if master_branch is not None and master_remote_branch is not None and (tracking_branch is None or tracking_branch.name != master_remote_branch.name): if need_push(repo, master_branch): status.append("@!@{yf}%s needs push" % master_branch.shorthand) elif need_pull(repo, master_branch): status.append("@!@{cf}%s needs pull" % master_branch.shorthand) elif not is_up_to_date(repo, master_branch): status.append("@!@{yf}%s needs merge" % master_branch.shorthand) return status def create_local_status(repo, upstream_status, is_dirty): status = [] if repo.head_is_detached: status.append("@!@{rf}detached HEAD") return status if has_pending_merge(repo): if repo.index.conflicts: status.append("@!@{rf}merge conflicts") else: status.append("@!@{yf}merged, needs commit") return status if is_dirty: status.append("@!@{yf}needs commit") status += upstream_status if not status: if not show_up_to_date: return None status.append("@!@{gf}up-to-date") return status table = TableView("Package", "Path", "Status") found_packages = set() for project in projects: repo = Repository(os.path.join(srcdir, project.workspace_path, ".git")) dirty_files = [a for a, b in iteritems(repo.status()) if b != GIT_STATUS_IGNORED and b != GIT_STATUS_CURRENT] head_branch = get_head_branch(repo) tracking_branch = head_branch.upstream if head_branch else None master_remote = get_origin(repo, project) if master_remote is not None: master_remote_branch = repo.lookup_branch("%s/%s" % (master_remote.name, project.master_branch), GIT_BRANCH_REMOTE) master_branch = None if master_remote_branch is not None: for name in repo.listall_branches(GIT_BRANCH_LOCAL): b = repo.lookup_branch(name, GIT_BRANCH_LOCAL) if b.upstream and b.upstream.branch_name == master_remote_branch.branch_name: master_branch = b break else: master_remote_branch = None master_branch = None ws_packages = find_catkin_packages(srcdir, project.workspace_path, cache=cache) found_packages |= set(ws_packages.keys()) upstream_status = create_upstream_status(repo, head_branch, master_branch, master_remote_branch, tracking_branch) for name, pkg_list in iteritems(ws_packages): if name not in packages: continue for pkg in pkg_list: is_dirty = False local_path = os.path.relpath(pkg.workspace_path, project.workspace_path) if dirty_files and local_path == ".": is_dirty = True else: for fpath in dirty_files: if path_has_prefix(fpath, local_path): is_dirty = True break status = create_local_status(repo, upstream_status, is_dirty) if status is not None: head, tail = os.path.split(pkg.workspace_path) pkg_path = escape(head + "/" if tail == name else pkg.workspace_path) table.add_row(escape(name), pkg_path, status) for path in other_git: repo = Repository(os.path.join(srcdir, path, ".git")) dirty_files = [a for a, b in iteritems(repo.status()) if b != GIT_STATUS_IGNORED and b != GIT_STATUS_CURRENT] head_branch = get_head_branch(repo) tracking_branch = head_branch.upstream if head_branch else None ws_packages = find_catkin_packages(srcdir, path, cache=cache) found_packages |= set(ws_packages.keys()) upstream_status = create_upstream_status(repo, head_branch, None, None, tracking_branch) for name, pkg_list in iteritems(ws_packages): if name not in packages: continue for pkg in pkg_list: is_dirty = False local_path = os.path.relpath(pkg.workspace_path, path) if dirty_files and local_path == ".": is_dirty = True else: for fpath in dirty_files: if path_has_prefix(fpath, local_path): is_dirty = True break status = create_local_status(repo, upstream_status, is_dirty) if status is not None: head, tail = os.path.split(pkg.workspace_path) pkg_path = escape(head + "/" if tail == name else pkg.workspace_path) table.add_row(escape(name), pkg_path, status) missing = set(packages) - found_packages for name in missing: path_list = [] status = "no git" if name in ws_state.ws_packages: for pkg in ws_state.ws_packages[name]: if not os.path.isdir(os.path.join(srcdir, pkg.workspace_path)): status = "@{rf}deleted" head, tail = os.path.split(pkg.workspace_path) path_list.append(escape(head + "/" if tail == name else pkg.workspace_path)) table.add_row(escape(name), path_list, status) if table.empty(): if found_packages: msg("Everything is @!@{gf}up-to-date@|.\n") else: warning("no Git repositories\n") else: table.sort(0) table.write(sys.stdout)
class GitRepo(object): ''' git repo class ''' def __init__(self, path): try: self.__repo = Repository(path) except Exception as e: self.__repo = None print(e) def get_info(self): if not self.__repo: return None signature = self.__repo.default_signature result = { 'path': self.__repo.path, 'workdir': self.__repo.workdir, 'bare': self.__repo.is_bare, 'empty': self.__repo.is_empty, 'name': signature.name, 'email': signature.email, 'time': signature.time, 'offset': signature.offset, } return result def get_all_references(self): return self.__repo.listall_references() def get_reference(self, name): if not self.__repo: return None ref = None try: ref = self.__repo.lookup_reference(name) except Exception as e: print(e) return ref def get_all_branches(self, branch_type=None): if not self.__repo: return None if branch_type: return self.__repo.listall_branches(branch_type) r = self.__repo.listall_branches(GIT_BRANCH_LOCAL | GIT_BRANCH_REMOTE) return r def get_branch(self, name, branch_type=GIT_BRANCH_LOCAL): if not self.__repo: return None return self.__repo.lookup_branch(name, branch_type) def check_branch(self, name, branch_type=None): if not branch_type: if '/' in name: branch_type = GIT_BRANCH_REMOTE else: branch_type = GIT_BRANCH_LOCAL try: result = self.get_branch(name, branch_type) return result except Exception as e: print(e) return False def get_current_commit(self): if not self.__repo: return None commit = self.__repo.revparse_single('HEAD') return self.get_commit(commit) def get_commit_by_branch(self, branch): if not self.__repo: return None query = 'refs/' if hasattr(branch, 'remote_name'): query += 'remotes/' else: query += 'heads/' query += branch.branch_name try: ref = self.get_reference(query) commit = ref.target return self.get_commit(commit) except Exception as e: print(e) return None def get_commit_by_tag(self, tag): if self.__repo is None: return None if tag: commit = tag.get_object() return self.get_commit(commit) return None def get_commit(self, oid_or_commit): ''' return a commit w/ json ''' if not self.__repo or not oid_or_commit: return None try: commit = oid_or_commit if not isinstance(oid_or_commit, Commit): commit = self.__repo.get(oid_or_commit) if commit and commit.type == GIT_OBJ_COMMIT: # t1 = self.__repo.revparse_single('HEAD^') # t2 = self.__repo.revparse_single('HEAD^^') # patches = self.__repo.diff(t1, t2) # for p in patches: # print(p.new_file_path) result = { 'id': str(commit.id), 'author': commit.author.name, 'commiter': commit.committer.name, 'message': commit.message, 'message_encoding': commit.message_encoding, 'tree': str(commit.tree_id), 'parent': [str(pid) for pid in commit.parent_ids], 'time': str(commit.commit_time), 'time_offset': str(commit.commit_time_offset), } return result except Exception as e: print(e) return None def get_commits(self, depth=10, oid_or_commit=None): result = [] if depth == 0: return result if oid_or_commit: commit = self.get_commit(oid_or_commit) else: commit = self.get_current_commit() if not commit: return result # TODO: starting from a commit or its parent # TODO: author result.append(commit) depth -= 1 if commit and commit['parent']: for parent in commit['parent']: result.extend(self.get_commits(depth, parent)) return result def get_commits_by_branch(self, name, path=None): if not self.__repo: return None if self.check_branch(name): ref = self.get_reference('refs/heads/' + name) if ref: commit = ref.target commits = self.get_commits(commit) result = {} for key, val in commits.items(): if self.check_commit_by_path(val, path): result[key] = val return result return None def check_tag(self, name): try: ref = self.get_reference('refs/tags/' + name) return ref except Exception: return False def get_commits_by_tag(self, tag, path=None): if not self.__repo: return None if tag: commit = tag.target commits = self.get_commits(commit) result = {} for key, val in commits.items(): if self.check_commit_by_path(val, path): result[key] = val return result return None def check_commit_by_path(self, commit, path): if not commit: return False if path is None or len(path) == 0: return True result = self.get_tree(commit['tree']) if not isinstance(path, list): path = path.strip().split('/') for name in path: name = name.strip() if name in result: oid = result[name] result = self.get_tree(oid) if not result: result = self.get_blob(oid) return result is not None def get_tree(self, oid, ppath=None): if not self.__repo: return None try: tree = self.__repo.get(oid) if tree and tree.type == GIT_OBJ_TREE: result = {} for entry in tree: item = { 'id': str(entry.id) } obj = self.__repo.get(entry.id) if obj.type == GIT_OBJ_BLOB: item['type'] = 'blob' elif obj.type == GIT_OBJ_TREE: item['type'] = 'tree' item['ppath'] = ppath result[entry.name] = item return result except Exception as e: print(e) return None def get_tree_by_commit(self, commit, path=None): if not commit: return None result = self.get_tree(commit['tree']) if not path: return result # if not isinstance(path, list): # path = path.strip().split('/') try: for name in path: oid = result[name]['id'] p = result[name]['ppath'] p = name if not p else p + '/' + name result = self.get_tree(oid, p) if not result: break except Exception as e: print(e) result = None return result def get_current_root(self): tree = self.get_current_commit() if tree: return self.get_tree(tree['tree']) return None def get_whole_tree(self, oid): ''' tree w/ json ''' if not self.__repo: return None result = tree_walker(self.__repo, oid) return result def get_blob(self, oid): ''' blob w/ json ''' if not self.__repo or not oid: return None try: blob = self.__repo.get(oid) if blob and blob.type == GIT_OBJ_BLOB: content = blob.is_binary and None or blob.data.decode( 'utf8', 'ignore') result = { 'id': str(blob.id), 'content': content, 'size': blob.size, } return result except Exception as e: print(e) return None def get_blob_by_commit(self, commit, path=None): try: tree = self.get_tree_by_commit(commit, path[:-1]) oid = tree[path[-1]]['id'] result = self.get_blob(oid) return result except Exception as e: print(e) return None def get_tag(self, oid): ''' blob w/ json ''' if not self.__repo or not oid: return None try: tag = self.__repo.get(oid) if tag and tag.type == GIT_OBJ_TAG: result = { 'id': str(oid), 'name': tag.name, 'target': str(tag.target.id), 'tagger': tag.tagger, 'message': tag.message, } return result except Exception as e: print(e) return None def get_patches(self, a=None, b=None): try: if not a: a = 'HEAD' if not b: b = a + '^' t1 = self.__repo.revparse_single(a) t2 = self.__repo.revparse_single(b) patches = self.__repo.diff(t1, t2) result = [] for patch in patches: p = { 'old_file_path': patch.old_file_path, 'new_file_path': patch.new_file_path, 'old_oid': str(patch.old_oid), 'new_oid': str(patch.new_oid), 'status': patch.status, 'similarity': patch.similarity, 'additions': patch.additions, 'deletions': patch.deletions, 'binary': patch.is_binary, 'hunks': [], } for hunk in patch.hunks: h = { 'old_start': hunk.old_start, 'old_lines': hunk.old_lines, 'new_start': hunk.new_start, 'new_lines': hunk.new_lines, 'lines': hunk.lines, } p['hunks'].append(h) result.append(p) return result except Exception as e: print(e) return None