def commit(repo, commit_msg): if not commit_msg: commit_msg = 'dulwich_' + U.stime() if not py.isbytes(commit_msg): commit_msg = commit_msg.encode('utf-8') index = repo.open_index() new_tree = index.commit(repo.object_store) if new_tree != repo[repo.head()].tree: bhash = repo.do_commit(commit_msg, tree=new_tree) return bhash, commit_msg else: return b'', py.No("Empty commit!")
def get_git_patch(repo, unstaged=True): final_changes = {} store = OverrideObjectStore(repo.object_store) try: head = repo.head() except KeyError: return None tree_id = repo[head].tree tree = repo[tree_id] index = repo.open_index() normalizer = repo.get_blob_normalizer() filter_callback = normalizer.checkin_normalize object_store = repo.object_store blob_from_path_and_stat = dulwich.index.blob_from_path_and_stat cleanup_mode = dulwich.index.cleanup_mode lookup_path = tree.lookup_path repo_path = repo.path.encode(sys.getfilesystemencoding()) def lookup_entry(path): absolute_path = os.path.join(repo_path, path) if os.path.isfile(absolute_path): st = os.lstat(absolute_path) # TODO: Building the blob means that we need to load the whole # file content in memory. We should be able to compute the sha # without needed to load the whole blob in memory. blob = blob_from_path_and_stat(absolute_path, st) blob = filter_callback(blob, path) blob_id = blob.id mode = cleanup_mode(st.st_mode) # Check if on-disk blob differs from the one in tree try: tree_blob = lookup_path(object_store.__getitem__, path) except KeyError: # Lookup path will fails for added files store[blob_id] = blob else: # If the blob for path in index differs from the one on disk, # store the on-disk one if tree_blob[1] != blob_id: store[blob_id] = blob return blob_id, mode elif os.path.isdir(absolute_path): try: tree_blob = lookup_path(object_store.__getitem__, path) except KeyError: # If the submodule is not in the store, it must be in index # and should be added index_entry = index[path] return index_entry.sha, index_entry.mode tree_mode = tree_blob[0] if dulwich.objects.S_ISGITLINK(tree_mode): return tree_blob[1], tree_mode else: # We shouldn't be here? raise KeyError(path) else: # Indicate that the files has been removed raise KeyError(path) # Merges names from the index and from the store as some files can be only # on index or only on the store names = set() for (name, _, _) in object_store.iter_tree_contents(tree_id): names.add(name) names.update(index._byname.keys()) final_changes = dulwich.index.changes_from_tree(names, lookup_entry, repo.object_store, tree_id, want_unchanged=False) # Generate the diff diff = BytesIO() def key(x): # Generate a comparable sorting key paths = tuple(p for p in x[0] if p) return paths for (oldpath, newpath), (oldmode, newmode), (oldsha, newsha) in sorted(final_changes, key=key): dulwich.patch.write_object_diff(diff, store, (oldpath, oldmode, oldsha), (newpath, newmode, newsha)) diff.seek(0) diff_result = diff.getvalue() # Detect empty diff if not diff_result: return None return diff_result
#! /bin/python #import git #repo = git.Repo( '.' ) #print repo.git.status() #import sh #git = sh.git.bake(_cwd='.') #print git.status() #import pygit2 #repo = pygit2.Repository('.') #print repo.path #print repo.status() import dulwich.repo repo = dulwich.repo.Repo('.') print repo index = repo.open_index() print index print list(index)
def emit_repo_as_xdot(repo, options): '''Emits xdot for the given repo on stdout.''' global graph # TODO: globals are bad mmmmkay global vertices vertices = {} graph = pydot.Graph(verbose=True) graph.set_bgcolor('#00000000') # transparent background objstore = repo.object_store seen = set() # walk everything in the object store. (this means orphaned nodes will show.) for sha in objstore: if not options.blobs and objstore[sha].type_name in ('blob', 'tree'): continue walk_node(objstore, seen, sha, options) for ref in repo.refs.keys(): if ref == 'HEAD': continue # TODO: let this loop handle symbolic refs too branch_node = add_branch_node(ref) graph.add_edge( pydot.Edge(branch_node, repo.refs[ref], **edge_opts(style='dotted'))) # do HEAD as a special case ref = 'HEAD' nopts = node_opts(label=ref, shape='diamond', style='filled', fillcolor='#ff3333', fontcolor='white', tooltip='Symbolic Ref: HEAD') head_node = pydot.Node(ref, **nopts) graph.add_node(head_node) symref = repo.refs.read_ref(ref) if symref.startswith('ref: '): symref = symref[5:] points_to = add_branch_node(symref) graph.add_node(points_to) graph.add_edge( pydot.Edge(head_node, add_branch_node(symref), **edge_opts(style='dotted'))) # index if options.index: try: head_tree = repo['HEAD'].tree except KeyError: head_tree = None index = repo.open_index() try: changes = list(index.changes_from_tree(objstore, head_tree)) except TypeError: # the official dulwich repo throws a TypeError changes_from_tree is # called against an empty tree (None) if head_tree is not None: raise changes = [] if changes: index_node = pydot.Node('index', shape='invtriangle', style='filled', fillcolor='#33ff33', fontname=DEFAULT_FONTNAME, fontsize=DEFAULT_FONTSIZE) graph.add_node(index_node) for (oldpath, newpath), (oldmode, newmode), (oldsha, newsha) in changes: graph.add_edge( pydot.Edge(index_node, vert_for_sha(objstore, newsha), label=q(' ' + newpath), fontname=DEFAULT_FONTNAME, fontsize=DEFAULT_FONTSIZE)) # invoke dot -Txdot to turn out DOT file into an xdot file, which canviz is expecting subprocess.Popen(['dot', '-Txdot'], stdin=subprocess.PIPE).communicate(graph.to_string())
def emit_repo_as_xdot(repo, options): """Emits xdot for the given repo on stdout.""" global graph # TODO: globals are bad mmmmkay global vertices vertices = {} graph = pydot.Graph(verbose=True) graph.set_bgcolor("#00000000") # transparent background objstore = repo.object_store seen = set() # walk everything in the object store. (this means orphaned nodes will show.) for sha in objstore: if not options.blobs and objstore[sha].type_name in ("blob", "tree"): continue walk_node(objstore, seen, sha, options) for ref in repo.refs.keys(): if ref == "HEAD": continue # TODO: let this loop handle symbolic refs too branch_node = add_branch_node(ref) graph.add_edge(pydot.Edge(branch_node, repo.refs[ref], **edge_opts(style="dotted"))) # do HEAD as a special case ref = "HEAD" nopts = node_opts( label=ref, shape="diamond", style="filled", fillcolor="#ff3333", fontcolor="white", tooltip="Symbolic Ref: HEAD" ) head_node = pydot.Node(ref, **nopts) graph.add_node(head_node) symref = repo.refs.read_ref(ref) if symref.startswith("ref: "): symref = symref[5:] points_to = add_branch_node(symref) graph.add_node(points_to) graph.add_edge(pydot.Edge(head_node, add_branch_node(symref), **edge_opts(style="dotted"))) # index if options.index: try: head_tree = repo["HEAD"].tree except KeyError: head_tree = None index = repo.open_index() try: changes = list(index.changes_from_tree(objstore, head_tree)) except TypeError: # the official dulwich repo throws a TypeError changes_from_tree is # called against an empty tree (None) if head_tree is not None: raise changes = [] if changes: index_node = pydot.Node( "index", shape="invtriangle", style="filled", fillcolor="#33ff33", fontname=DEFAULT_FONTNAME, fontsize=DEFAULT_FONTSIZE, ) graph.add_node(index_node) for (oldpath, newpath), (oldmode, newmode), (oldsha, newsha) in changes: graph.add_edge( pydot.Edge( index_node, vert_for_sha(objstore, newsha), label=q(" " + newpath), fontname=DEFAULT_FONTNAME, fontsize=DEFAULT_FONTSIZE, ) ) # invoke dot -Txdot to turn out DOT file into an xdot file, which canviz is expecting subprocess.Popen(["dot", "-Txdot"], stdin=subprocess.PIPE).communicate(graph.to_string())