X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=contrib%2Fgitview%2Fgitview;h=b836047cf34715909470049a24febdd8f966eaab;hb=756944350d675bd3c08130df337b776f189ed752;hp=5862fcca4123fc35859013b2d265a184fea96c9c;hpb=290252e06341c05fcebb65784ad05c37656ae36d;p=git.git diff --git a/contrib/gitview/gitview b/contrib/gitview/gitview index 5862fcca..b836047c 100755 --- a/contrib/gitview/gitview +++ b/contrib/gitview/gitview @@ -56,20 +56,6 @@ def show_date(epoch, tz): return time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(secs)) -def get_sha1_from_tags(line): - fp = os.popen("git cat-file -t " + line) - entry = string.strip(fp.readline()) - fp.close() - if (entry == "commit"): - return line - elif (entry == "tag"): - fp = os.popen("git cat-file tag "+ line) - entry = string.strip(fp.readline()) - fp.close() - obj = re.split(" ", entry) - if (obj[0] == "object"): - return obj[1] - return None class CellRendererGraph(gtk.GenericCellRenderer): """Cell renderer for directed graph. @@ -168,15 +154,15 @@ class CellRendererGraph(gtk.GenericCellRenderer): cols = self.node[0] for start, end, colour in self.in_lines + self.out_lines: - cols = max(cols, start, end) + cols = int(max(cols, start, end)) (column, colour, names) = self.node names_len = 0 if (len(names) != 0): for item in names: - names_len += len(item)/3 + names_len += len(item) - width = box_size * (cols + 1 + names_len ) + width = box_size * (cols + 1 ) + names_len height = box_size # FIXME I have no idea how to use cell_area properly @@ -253,18 +239,23 @@ class CellRendererGraph(gtk.GenericCellRenderer): box_size / 4, 0, 2 * math.pi) + self.set_colour(ctx, colour, 0.0, 0.5) + ctx.stroke_preserve() + + self.set_colour(ctx, colour, 0.5, 1.0) + ctx.fill_preserve() + if (len(names) != 0): name = " " for item in names: name = name + item + " " - ctx.text_path(name) - - self.set_colour(ctx, colour, 0.0, 0.5) - ctx.stroke_preserve() - - self.set_colour(ctx, colour, 0.5, 1.0) - ctx.fill() + ctx.set_font_size(13) + if (flags & 1): + self.set_colour(ctx, colour, 0.5, 1.0) + else: + self.set_colour(ctx, colour, 0.0, 0.5) + ctx.show_text(name) class Commit: """ This represent a commit object obtained after parsing the git-rev-list @@ -273,11 +264,11 @@ class Commit: children_sha1 = {} def __init__(self, commit_lines): - self.message = "" + self.message = "" self.author = "" - self.date = "" - self.committer = "" - self.commit_date = "" + self.date = "" + self.committer = "" + self.commit_date = "" self.commit_sha1 = "" self.parent_sha1 = [ ] self.parse_commit(commit_lines) @@ -377,7 +368,7 @@ class DiffWindow: save_menu.connect("activate", self.save_menu_response, "save") save_menu.show() menu_bar.append(save_menu) - vbox.pack_start(menu_bar, False, False, 2) + vbox.pack_start(menu_bar, expand=False, fill=True) menu_bar.show() scrollwin = gtk.ScrolledWindow() @@ -403,7 +394,7 @@ class DiffWindow: sourceview.show() - def set_diff(self, commit_sha1, parent_sha1): + def set_diff(self, commit_sha1, parent_sha1, encoding): """Set the differences showed by this window. Compares the two trees and populates the window with the differences. @@ -413,7 +404,7 @@ class DiffWindow: return fp = os.popen("git diff-tree -p " + parent_sha1 + " " + commit_sha1) - self.buffer.set_text(fp.read()) + self.buffer.set_text(unicode(fp.read(), encoding).encode('utf-8')) fp.close() self.window.show() @@ -434,14 +425,15 @@ class DiffWindow: class GitView: """ This is the main class """ - version = "0.6" + version = "0.8" def __init__(self, with_diff=0): self.with_diff = with_diff - self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) + self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) self.window.set_border_width(0) self.window.set_title("Git repository browser") + self.get_encoding() self.get_bt_sha1() # Use three-quarters of the screen by default @@ -457,57 +449,52 @@ class GitView: self.accel_group = gtk.AccelGroup() self.window.add_accel_group(self.accel_group) + self.accel_group.connect_group(0xffc2, 0, gtk.ACCEL_LOCKED, self.refresh); - self.construct() + self.window.add(self.construct()) + + def refresh(self, widget, event=None, *arguments, **keywords): + self.get_encoding() + self.get_bt_sha1() + Commit.children_sha1 = {} + self.set_branch(sys.argv[without_diff:]) + self.window.show() + return True def get_bt_sha1(self): """ Update the bt_sha1 dictionary with the respective sha1 details """ self.bt_sha1 = { } - git_dir = os.getenv("GIT_DIR") - if (git_dir == None): - git_dir = ".git" - - #FIXME the path seperator - ref_files = os.listdir(git_dir + "/refs/tags") - for file in ref_files: - fp = open(git_dir + "/refs/tags/"+file) - sha1 = get_sha1_from_tags(string.strip(fp.readline())) - try: - self.bt_sha1[sha1].append(file) - except KeyError: - self.bt_sha1[sha1] = [file] - fp.close() - + ls_remote = re.compile('^(.{40})\trefs/([^^]+)(?:\\^(..))?$'); + fp = os.popen('git ls-remote "${GIT_DIR-.git}"') + while 1: + line = string.strip(fp.readline()) + if line == '': + break + m = ls_remote.match(line) + if not m: + continue + (sha1, name) = (m.group(1), m.group(2)) + if not self.bt_sha1.has_key(sha1): + self.bt_sha1[sha1] = [] + self.bt_sha1[sha1].append(name) + fp.close() - #FIXME the path seperator - ref_files = os.listdir(git_dir + "/refs/heads") - for file in ref_files: - fp = open(git_dir + "/refs/heads/" + file) - sha1 = get_sha1_from_tags(string.strip(fp.readline())) - try: - self.bt_sha1[sha1].append(file) - except KeyError: - self.bt_sha1[sha1] = [file] - fp.close() + def get_encoding(self): + fp = os.popen("git repo-config --get i18n.commitencoding") + self.encoding=string.strip(fp.readline()) + fp.close() + if (self.encoding == ""): + self.encoding = "utf-8" def construct(self): """Construct the window contents.""" + vbox = gtk.VBox() paned = gtk.VPaned() paned.pack1(self.construct_top(), resize=False, shrink=True) paned.pack2(self.construct_bottom(), resize=False, shrink=True) - self.window.add(paned) - paned.show() - - - def construct_top(self): - """Construct the top-half of the window.""" - vbox = gtk.VBox(spacing=6) - vbox.set_border_width(12) - vbox.show() - menu_bar = gtk.MenuBar() menu_bar.set_pack_direction(gtk.PACK_DIRECTION_RTL) help_menu = gtk.MenuItem("Help") @@ -519,11 +506,23 @@ class GitView: help_menu.set_submenu(menu) help_menu.show() menu_bar.append(help_menu) - vbox.pack_start(menu_bar, False, False, 2) menu_bar.show() + vbox.pack_start(menu_bar, expand=False, fill=True) + vbox.pack_start(paned, expand=True, fill=True) + paned.show() + vbox.show() + return vbox + + + def construct_top(self): + """Construct the top-half of the window.""" + vbox = gtk.VBox(spacing=6) + vbox.set_border_width(12) + vbox.show() + scrollwin = gtk.ScrolledWindow() - scrollwin.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) + scrollwin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) scrollwin.set_shadow_type(gtk.SHADOW_IN) vbox.pack_start(scrollwin, expand=True, fill=True) scrollwin.show() @@ -537,8 +536,8 @@ class GitView: cell = CellRendererGraph() column = gtk.TreeViewColumn() - column.set_resizable(False) - column.pack_start(cell, expand=False) + column.set_resizable(True) + column.pack_start(cell, expand=True) column.add_attribute(cell, "node", 1) column.add_attribute(cell, "in-lines", 2) column.add_attribute(cell, "out-lines", 3) @@ -707,7 +706,7 @@ class GitView: self.revid_label.set_text(revid_label) self.committer_label.set_text(committer) self.timestamp_label.set_text(timestamp) - self.message_buffer.set_text(message) + self.message_buffer.set_text(unicode(message, self.encoding).encode('utf-8')) for widget in self.parents_widgets: self.table.remove(widget) @@ -752,7 +751,7 @@ class GitView: button.set_relief(gtk.RELIEF_NONE) button.set_sensitive(True) button.connect("clicked", self._show_clicked_cb, - commit.commit_sha1, parent_id) + commit.commit_sha1, parent_id, self.encoding) hbox.pack_start(button, expand=False, fill=True) button.show() @@ -808,7 +807,7 @@ class GitView: button.set_relief(gtk.RELIEF_NONE) button.set_sensitive(True) button.connect("clicked", self._show_clicked_cb, - child_id, commit.commit_sha1) + child_id, commit.commit_sha1, self.encoding) hbox.pack_start(button, expand=False, fill=True) button.show() @@ -847,6 +846,7 @@ class GitView: self.colours = {} self.nodepos = {} self.incomplete_line = {} + self.commits = [] index = 0 last_colour = 0 @@ -864,12 +864,7 @@ class GitView: commit = Commit(commit_lines) if (commit != None ): - (out_line, last_colour, last_nodepos) = self.draw_graph(commit, - index, out_line, - last_colour, - last_nodepos) - self.index[commit.commit_sha1] = index - index += 1 + self.commits.append(commit) # Skip the '\0 commit_lines = [] @@ -878,6 +873,14 @@ class GitView: fp.close() + for commit in self.commits: + (out_line, last_colour, last_nodepos) = self.draw_graph(commit, + index, out_line, + last_colour, + last_nodepos) + self.index[commit.commit_sha1] = index + index += 1 + self.treeview.set_model(self.model) self.treeview.show() @@ -890,28 +893,22 @@ class GitView: # Reset nodepostion if (last_nodepos > 5): - last_nodepos = 0 + last_nodepos = -1 # Add the incomplete lines of the last cell in this - for sha1 in self.incomplete_line.keys(): - if ( sha1 != commit.commit_sha1): - for pos in self.incomplete_line[sha1]: - in_line.append((pos, pos, self.colours[sha1])) - else: - del self.incomplete_line[sha1] - try: colour = self.colours[commit.commit_sha1] except KeyError: - last_colour +=1 - self.colours[commit.commit_sha1] = last_colour - colour = last_colour + self.colours[commit.commit_sha1] = last_colour+1 + last_colour = self.colours[commit.commit_sha1] + colour = self.colours[commit.commit_sha1] + try: node_pos = self.nodepos[commit.commit_sha1] except KeyError: - last_nodepos +=1 - self.nodepos[commit.commit_sha1] = last_nodepos - node_pos = last_nodepos + self.nodepos[commit.commit_sha1] = last_nodepos+1 + last_nodepos = self.nodepos[commit.commit_sha1] + node_pos = self.nodepos[commit.commit_sha1] #The first parent always continue on the same line try: @@ -921,25 +918,26 @@ class GitView: self.colours[commit.parent_sha1[0]] = colour self.nodepos[commit.parent_sha1[0]] = node_pos - in_line.append((node_pos, self.nodepos[commit.parent_sha1[0]], - self.colours[commit.parent_sha1[0]])) - - self.add_incomplete_line(commit.parent_sha1[0], index+1) + for sha1 in self.incomplete_line.keys(): + if (sha1 != commit.commit_sha1): + self.draw_incomplete_line(sha1, node_pos, + out_line, in_line, index) + else: + del self.incomplete_line[sha1] - if (len(commit.parent_sha1) > 1): - for parent_id in commit.parent_sha1[1:]: - try: - tmp_node_pos = self.nodepos[parent_id] - except KeyError: - last_colour += 1; - self.colours[parent_id] = last_colour - last_nodepos +=1 - self.nodepos[parent_id] = last_nodepos - in_line.append((node_pos, self.nodepos[parent_id], - self.colours[parent_id])) - self.add_incomplete_line(parent_id, index+1) + for parent_id in commit.parent_sha1: + try: + tmp_node_pos = self.nodepos[parent_id] + except KeyError: + self.colours[parent_id] = last_colour+1 + last_colour = self.colours[parent_id] + self.nodepos[parent_id] = last_nodepos+1 + last_nodepos = self.nodepos[parent_id] + in_line.append((node_pos, self.nodepos[parent_id], + self.colours[parent_id])) + self.add_incomplete_line(parent_id) try: branch_tag = self.bt_sha1[commit.commit_sha1] @@ -954,33 +952,57 @@ class GitView: return (in_line, last_colour, last_nodepos) - def add_incomplete_line(self, sha1, index): + def add_incomplete_line(self, sha1): try: self.incomplete_line[sha1].append(self.nodepos[sha1]) except KeyError: self.incomplete_line[sha1] = [self.nodepos[sha1]] + def draw_incomplete_line(self, sha1, node_pos, out_line, in_line, index): + for idx, pos in enumerate(self.incomplete_line[sha1]): + if(pos == node_pos): + #remove the straight line and add a slash + if ((pos, pos, self.colours[sha1]) in out_line): + out_line.remove((pos, pos, self.colours[sha1])) + out_line.append((pos, pos+0.5, self.colours[sha1])) + self.incomplete_line[sha1][idx] = pos = pos+0.5 + try: + next_commit = self.commits[index+1] + if (next_commit.commit_sha1 == sha1 and pos != int(pos)): + # join the line back to the node point + # This need to be done only if we modified it + in_line.append((pos, pos-0.5, self.colours[sha1])) + continue; + except IndexError: + pass + in_line.append((pos, pos, self.colours[sha1])) + def _go_clicked_cb(self, widget, revid): """Callback for when the go button for a parent is clicked.""" try: self.treeview.set_cursor(self.index[revid]) except KeyError: - print "Revision %s not present in the list" % revid + dialog = gtk.MessageDialog(parent=None, flags=0, + type=gtk.MESSAGE_WARNING, buttons=gtk.BUTTONS_CLOSE, + message_format=None) + dialog.set_markup("Revision %s not present in the list" % revid) # revid == 0 is the parent of the first commit if (revid != 0 ): - print "Try running gitview without any options" + dialog.format_secondary_text("Try running gitview without any options") + dialog.run() + dialog.destroy() self.treeview.grab_focus() - def _show_clicked_cb(self, widget, commit_sha1, parent_sha1): + def _show_clicked_cb(self, widget, commit_sha1, parent_sha1, encoding): """Callback for when the show button for a parent is clicked.""" window = DiffWindow() - window.set_diff(commit_sha1, parent_sha1) + window.set_diff(commit_sha1, parent_sha1, encoding) self.treeview.grab_focus() +without_diff = 0 if __name__ == "__main__": - without_diff = 0 if (len(sys.argv) > 1 ): if (sys.argv[1] == "--without-diff"):