def diff(repository, ref, from_ref=None, **kwargs): """git diff command, pygit2 wrapper :param ref: :param from_ref: :param flags: :param context_lines: :param paths: """ _diff = {} ref = ref.strip() sha = resolve_version(repository, ref) if not sha: raise JagareError("%s...%s" % (from_ref, ref)) commit = get_commit_by_sha(repository, sha) from_commit = None if from_ref: from_ref = from_ref.strip() from_sha = resolve_version(repository, from_ref) if not from_sha: raise JagareError("%s...%s" % (from_ref, ref)) from_commit = get_commit_by_sha(repository, from_sha) # get pygit2 diff if from_commit: diff, _diff['old_sha'] = diff_commits(repository, commit, from_commit, **kwargs) else: diff, _diff['old_sha'] = diff_commit(repository, commit, **kwargs) _diff['new_sha'] = commit.hex _diff['diff'] = diff return _diff
def get_commit_by_sha(repository, sha): try: commit = repository[sha] except (ValueError, KeyError, TypeError): raise JagareError("Commit '%s' is invalid." % sha) if commit and commit.type == GIT_OBJ_COMMIT: return commit
def update_ref(repository, ref, newvalue): """git update-ref/symbolic-ref command, pygit2 wrapper. :param ref: the full name of the reference/symbolic ref. :param newvalue: the sha-1 value of the commit or the full name of the target reference.""" # TODO: support for no-deref option # git update-ref if repository.is_empty: raise JagareError("repository is empty") try: commit = repository.revparse_single(newvalue) except KeyError: raise JagareError("newvalue is invalid.") except Exception: raise JagareError("refs not found.") try: repo_ref = repository.lookup_reference(ref) except KeyError: repository.create_reference(ref, commit.hex) return if repo_ref.type == GIT_REF_OID: try: repo_ref.target = commit.hex except OSError: raise JagareError("OSError occurred because of concurrency," " try again later") # TODO: change acting when the reference is symbolic elif repo_ref.type == GIT_REF_SYMBOLIC: # WARNING: this else is acting like `git symbolic-ref` try: repo_new = repository.lookup_reference(newvalue) except Exception: raise JagareError("refs not found.", 400) repo_ref.target = repo_new.name
def create_commit(repository, branch, parent, author_name, author_email, message, reflog, data): """git commit command, pygit2 wrapper. :param parent: parent ref :param data: list of tuple(filepath, content, action), action is insert/remove""" if repository.is_empty: if branch != "master" or parent != "master": raise JagareError("only commit to master when repo is empty") parents_sha = [] parent_commit = None if not repository.is_empty: parent_commit = repository.revparse_single(parent) parents_sha.append(str(parent_commit.id)) ret = [] flag = False root = init_root() for filepath, content, action in data: content = unicode_to_utf8(content) content = content.replace("\r\n", "\n") if action == "insert": root.add_file(filepath, content) elif action == "remove": root.del_file(filepath) else: root.add_file(filepath, content) #filepath = unicode_to_utf8(filepath) #mode = _get_pygit2_mode(mode) flag = True # FIXME: remove this after refactor gist #if not flag: # root.add_file('empty', '') # flag = True if flag: for entry in root.walk(): entry.write(repository, parent_commit if parent_commit else None) tree_oid = root.id signature = Signature(author_name, author_email) commit_oid = repository.create_commit("refs/heads/%s" % branch, signature, signature, message, tree_oid, parents_sha) master = repository.lookup_reference("refs/heads/%s" % branch) master.target = str(commit_oid) master.log_append(str(commit_oid), signature, reflog) return ret return []
def ls_tree(repository, ref, recursive=None, size=None, name_only=None, req_path=None, with_commit=False): """git ls-tree command, pygit2 wrapper. List the contents of a tree object. """ if req_path: req_path = _remove_slash(req_path) try: obj = repository.revparse_single(ref) except (ValueError, KeyError): raise JagareError("Reference not found.") commit_obj = None if obj.type == GIT_OBJ_TREE: tree_obj = obj elif obj.type == GIT_OBJ_TAG: commit_obj = repository.revparse_single(obj.target.hex) tree_obj = commit_obj.tree elif obj.type == GIT_OBJ_BLOB: raise JagareError("Object is blob, doesn't contain any tree") elif obj.type == GIT_OBJ_COMMIT: commit_obj = obj tree_obj = obj.tree if req_path: tree_entry = tree_obj[req_path] tree_obj = repository[tree_entry.id] walker = _walk_tree(tree_obj, req_path) else: walker = _walk_tree(tree_obj) ret_tree = {} submodule_obj = None submodule = None try: submodule_obj = repository.revparse_single("%s:.gitmodules" % ref) submodule = _parse_submodule(repository, submodule_obj) except (ValueError, KeyError): # FIXME: return error pass #raise JagareError("Reference not found.") for index, (entry, path) in enumerate(walker): mode = '%06o' % entry.filemode if mode == '160000': objtype = 'submodule' # For git submodules elif mode == '040000': objtype = 'tree' else: objtype = 'blob' path = "%s/%s" % (path, entry.name) if path else entry.name if recursive and entry.type == GIT_OBJ_TREE: _tree = repository[entry.id] _tree_list = _walk_tree(_tree, path) for _index, _entry in enumerate(_tree_list): walker.insert(index + _index + 1, _entry) continue if name_only: ret_tree[path] = path continue item = { "id": entry.hex, # FIXME: remove this "mode": mode, "type": objtype, "sha": entry.hex, "path": path, "name": entry.name } if entry.type == GIT_OBJ_COMMIT: item['submodule'] = _format_submodule(submodule, path) if size: if objtype == 'blob': blob = repository[entry.id] item['size'] = blob.size else: item['size'] = '-' ret_tree[path] = item if name_only: return ret_tree.values() if with_commit and commit_obj: _format_with_last_commit(repository, ret_tree, commit_obj) tree_list = ret_tree.values() tree_list.sort(key=lambda i: (TREE_ORDER[i['type']], i['name'])) return tree_list
def repository(path): try: repo = Repository(path) except KeyError: raise JagareError('repo %s not exists' % path) return repo