Dear Stefan,

Thank you for commenting on my report and getting the ball rolling on this. 
This response sounds good to me.

Regards,
Javantea

On Wed, 28 Dec 2016 09:28:37 -0800, Stefan Beller <[email protected]> wrote:
>gitview did not have meaningful contributions since 2007, which gives the
>impression it is either a mature or dead project.
>
>In both cases we should not carry it in git.git as the README for contrib
>states we only want to carry experimental things to give early exposure.
>
>Recently a security vulnerability was reported by Javantea, so the decision
>to either fix the issue or remove the code in question becomes a bit
>more urgent.
>
>Reported-by: Javantea <[email protected]>
>Signed-off-by: Stefan Beller <[email protected]>
>---
> contrib/gitview/gitview     | 1305 -------------------------------------------
> contrib/gitview/gitview.txt |   57 --
> 2 files changed, 1362 deletions(-)
> delete mode 100755 contrib/gitview/gitview
> delete mode 100644 contrib/gitview/gitview.txt
>
>diff --git a/contrib/gitview/gitview b/contrib/gitview/gitview
>deleted file mode 100755
>index 4e23c650fe..0000000000
>--- a/contrib/gitview/gitview
>+++ /dev/null
>@@ -1,1305 +0,0 @@
>-#! /usr/bin/env python
>-
>-# This program is free software; you can redistribute it and/or modify
>-# it under the terms of the GNU General Public License as published by
>-# the Free Software Foundation; either version 2 of the License, or
>-# (at your option) any later version.
>-
>-""" gitview
>-GUI browser for git repository
>-This program is based on bzrk by Scott James Remnant <[email protected]>
>-"""
>-__copyright__ = "Copyright (C) 2006 Hewlett-Packard Development Company, L.P."
>-__copyright__ = "Copyright (C) 2007 Aneesh Kumar K.V <[email protected]"
>-__author__    = "Aneesh Kumar K.V <[email protected]>"
>-
>-
>-import sys
>-import os
>-import gtk
>-import pygtk
>-import pango
>-import re
>-import time
>-import gobject
>-import cairo
>-import math
>-import string
>-import fcntl
>-
>-have_gtksourceview2 = False
>-have_gtksourceview = False
>-try:
>-    import gtksourceview2
>-    have_gtksourceview2 = True
>-except ImportError:
>-    try:
>-        import gtksourceview
>-        have_gtksourceview = True
>-    except ImportError:
>-        print "Running without gtksourceview2 or gtksourceview module"
>-
>-re_ident = re.compile('(author|committer) (?P<ident>.*) (?P<epoch>\d+) 
>(?P<tz>[+-]\d{4})')
>-
>-def list_to_string(args, skip):
>-      count = len(args)
>-      i = skip
>-      str_arg=" "
>-      while (i < count ):
>-              str_arg = str_arg + args[i]
>-              str_arg = str_arg + " "
>-              i = i+1
>-
>-      return str_arg
>-
>-def show_date(epoch, tz):
>-      secs = float(epoch)
>-      tzsecs = float(tz[1:3]) * 3600
>-      tzsecs += float(tz[3:5]) * 60
>-      if (tz[0] == "+"):
>-              secs += tzsecs
>-      else:
>-              secs -= tzsecs
>-
>-      return time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(secs))
>-
>-def get_source_buffer_and_view():
>-      if have_gtksourceview2:
>-              buffer = gtksourceview2.Buffer()
>-              slm = gtksourceview2.LanguageManager()
>-              gsl = slm.get_language("diff")
>-              buffer.set_highlight_syntax(True)
>-              buffer.set_language(gsl)
>-              view = gtksourceview2.View(buffer)
>-      elif have_gtksourceview:
>-              buffer = gtksourceview.SourceBuffer()
>-              slm = gtksourceview.SourceLanguagesManager()
>-              gsl = slm.get_language_from_mime_type("text/x-patch")
>-              buffer.set_highlight(True)
>-              buffer.set_language(gsl)
>-              view = gtksourceview.SourceView(buffer)
>-      else:
>-              buffer = gtk.TextBuffer()
>-              view = gtk.TextView(buffer)
>-      return (buffer, view)
>-
>-
>-class CellRendererGraph(gtk.GenericCellRenderer):
>-      """Cell renderer for directed graph.
>-
>-      This module contains the implementation of a custom GtkCellRenderer that
>-      draws part of the directed graph based on the lines suggested by the 
>code
>-      in graph.py.
>-
>-      Because we're shiny, we use Cairo to do this, and because we're naughty
>-      we cheat and draw over the bits of the TreeViewColumn that are supposed 
>to
>-      just be for the background.
>-
>-      Properties:
>-      node              (column, colour, [ names ]) tuple to draw revision 
>node,
>-      in_lines          (start, end, colour) tuple list to draw inward lines,
>-      out_lines         (start, end, colour) tuple list to draw outward lines.
>-      """
>-
>-      __gproperties__ = {
>-      "node":         ( gobject.TYPE_PYOBJECT, "node",
>-                        "revision node instruction",
>-                        gobject.PARAM_WRITABLE
>-                      ),
>-      "in-lines":     ( gobject.TYPE_PYOBJECT, "in-lines",
>-                        "instructions to draw lines into the cell",
>-                        gobject.PARAM_WRITABLE
>-                      ),
>-      "out-lines":    ( gobject.TYPE_PYOBJECT, "out-lines",
>-                        "instructions to draw lines out of the cell",
>-                        gobject.PARAM_WRITABLE
>-                      ),
>-      }
>-
>-      def do_set_property(self, property, value):
>-              """Set properties from GObject properties."""
>-              if property.name == "node":
>-                      self.node = value
>-              elif property.name == "in-lines":
>-                      self.in_lines = value
>-              elif property.name == "out-lines":
>-                      self.out_lines = value
>-              else:
>-                      raise AttributeError, "no such property: '%s'" % 
>property.name
>-
>-      def box_size(self, widget):
>-              """Calculate box size based on widget's font.
>-
>-              Cache this as it's probably expensive to get.  It ensures that 
>we
>-              draw the graph at least as large as the text.
>-              """
>-              try:
>-                      return self._box_size
>-              except AttributeError:
>-                      pango_ctx = widget.get_pango_context()
>-                      font_desc = widget.get_style().font_desc
>-                      metrics = pango_ctx.get_metrics(font_desc)
>-
>-                      ascent = pango.PIXELS(metrics.get_ascent())
>-                      descent = pango.PIXELS(metrics.get_descent())
>-
>-                      self._box_size = ascent + descent + 6
>-                      return self._box_size
>-
>-      def set_colour(self, ctx, colour, bg, fg):
>-              """Set the context source colour.
>-
>-              Picks a distinct colour based on an internal wheel; the bg
>-              parameter provides the value that should be assigned to the 
>'zero'
>-              colours and the fg parameter provides the multiplier that 
>should be
>-              applied to the foreground colours.
>-              """
>-              colours = [
>-                  ( 1.0, 0.0, 0.0 ),
>-                  ( 1.0, 1.0, 0.0 ),
>-                  ( 0.0, 1.0, 0.0 ),
>-                  ( 0.0, 1.0, 1.0 ),
>-                  ( 0.0, 0.0, 1.0 ),
>-                  ( 1.0, 0.0, 1.0 ),
>-                  ]
>-
>-              colour %= len(colours)
>-              red   = (colours[colour][0] * fg) or bg
>-              green = (colours[colour][1] * fg) or bg
>-              blue  = (colours[colour][2] * fg) or bg
>-
>-              ctx.set_source_rgb(red, green, blue)
>-
>-      def on_get_size(self, widget, cell_area):
>-              """Return the size we need for this cell.
>-
>-              Each cell is drawn individually and is only as wide as it needs
>-              to be, we let the TreeViewColumn take care of making them all
>-              line up.
>-              """
>-              box_size = self.box_size(widget)
>-
>-              cols = self.node[0]
>-              for start, end, colour in self.in_lines + self.out_lines:
>-                      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)
>-
>-              width = box_size * (cols + 1 ) + names_len
>-              height = box_size
>-
>-              # FIXME I have no idea how to use cell_area properly
>-              return (0, 0, width, height)
>-
>-      def on_render(self, window, widget, bg_area, cell_area, exp_area, 
>flags):
>-              """Render an individual cell.
>-
>-              Draws the cell contents using cairo, taking care to clip what we
>-              do to within the background area so we don't draw over other 
>cells.
>-              Note that we're a bit naughty there and should really be drawing
>-              in the cell_area (or even the exposed area), but we explicitly 
>don't
>-              want any gutter.
>-
>-              We try and be a little clever, if the line we need to draw is 
>going
>-              to cross other columns we actually draw it as in the .---' style
>-              instead of a pure diagonal ... this reduces confusion by an
>-              incredible amount.
>-              """
>-              ctx = window.cairo_create()
>-              ctx.rectangle(bg_area.x, bg_area.y, bg_area.width, 
>bg_area.height)
>-              ctx.clip()
>-
>-              box_size = self.box_size(widget)
>-
>-              ctx.set_line_width(box_size / 8)
>-              ctx.set_line_cap(cairo.LINE_CAP_SQUARE)
>-
>-              # Draw lines into the cell
>-              for start, end, colour in self.in_lines:
>-                      ctx.move_to(cell_area.x + box_size * start + box_size / 
>2,
>-                                      bg_area.y - bg_area.height / 2)
>-
>-                      if start - end > 1:
>-                              ctx.line_to(cell_area.x + box_size * start, 
>bg_area.y)
>-                              ctx.line_to(cell_area.x + box_size * end + 
>box_size, bg_area.y)
>-                      elif start - end < -1:
>-                              ctx.line_to(cell_area.x + box_size * start + 
>box_size,
>-                                              bg_area.y)
>-                              ctx.line_to(cell_area.x + box_size * end, 
>bg_area.y)
>-
>-                      ctx.line_to(cell_area.x + box_size * end + box_size / 2,
>-                                      bg_area.y + bg_area.height / 2)
>-
>-                      self.set_colour(ctx, colour, 0.0, 0.65)
>-                      ctx.stroke()
>-
>-              # Draw lines out of the cell
>-              for start, end, colour in self.out_lines:
>-                      ctx.move_to(cell_area.x + box_size * start + box_size / 
>2,
>-                                      bg_area.y + bg_area.height / 2)
>-
>-                      if start - end > 1:
>-                              ctx.line_to(cell_area.x + box_size * start,
>-                                              bg_area.y + bg_area.height)
>-                              ctx.line_to(cell_area.x + box_size * end + 
>box_size,
>-                                              bg_area.y + bg_area.height)
>-                      elif start - end < -1:
>-                              ctx.line_to(cell_area.x + box_size * start + 
>box_size,
>-                                              bg_area.y + bg_area.height)
>-                              ctx.line_to(cell_area.x + box_size * end,
>-                                              bg_area.y + bg_area.height)
>-
>-                      ctx.line_to(cell_area.x + box_size * end + box_size / 2,
>-                                      bg_area.y + bg_area.height / 2 + 
>bg_area.height)
>-
>-                      self.set_colour(ctx, colour, 0.0, 0.65)
>-                      ctx.stroke()
>-
>-              # Draw the revision node in the right column
>-              (column, colour, names) = self.node
>-              ctx.arc(cell_area.x + box_size * column + box_size / 2,
>-                              cell_area.y + cell_area.height / 2,
>-                              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.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(object):
>-      """ This represent a commit object obtained after parsing the 
>git-rev-list
>-      output """
>-
>-      __slots__ = ['children_sha1', 'message', 'author', 'date', 'committer',
>-                               'commit_date', 'commit_sha1', 'parent_sha1']
>-
>-      children_sha1 = {}
>-
>-      def __init__(self, commit_lines):
>-              self.message            = ""
>-              self.author             = ""
>-              self.date               = ""
>-              self.committer          = ""
>-              self.commit_date        = ""
>-              self.commit_sha1        = ""
>-              self.parent_sha1        = [ ]
>-              self.parse_commit(commit_lines)
>-
>-
>-      def parse_commit(self, commit_lines):
>-
>-              # First line is the sha1 lines
>-              line = string.strip(commit_lines[0])
>-              sha1 = re.split(" ", line)
>-              self.commit_sha1 = sha1[0]
>-              self.parent_sha1 = sha1[1:]
>-
>-              #build the child list
>-              for parent_id in self.parent_sha1:
>-                      try:
>-                              
>Commit.children_sha1[parent_id].append(self.commit_sha1)
>-                      except KeyError:
>-                              Commit.children_sha1[parent_id] = 
>[self.commit_sha1]
>-
>-              # IF we don't have parent
>-              if (len(self.parent_sha1) == 0):
>-                      self.parent_sha1 = [0]
>-
>-              for line in commit_lines[1:]:
>-                      m = re.match("^ ", line)
>-                      if (m != None):
>-                              # First line of the commit message used for 
>short log
>-                              if self.message == "":
>-                                      self.message = string.strip(line)
>-                              continue
>-
>-                      m = re.match("tree", line)
>-                      if (m != None):
>-                              continue
>-
>-                      m = re.match("parent", line)
>-                      if (m != None):
>-                              continue
>-
>-                      m = re_ident.match(line)
>-                      if (m != None):
>-                              date = show_date(m.group('epoch'), 
>m.group('tz'))
>-                              if m.group(1) == "author":
>-                                      self.author = m.group('ident')
>-                                      self.date = date
>-                              elif m.group(1) == "committer":
>-                                      self.committer = m.group('ident')
>-                                      self.commit_date = date
>-
>-                              continue
>-
>-      def get_message(self, with_diff=0):
>-              if (with_diff == 1):
>-                      message = self.diff_tree()
>-              else:
>-                      fp = os.popen("git cat-file commit " + self.commit_sha1)
>-                      message = fp.read()
>-                      fp.close()
>-
>-              return message
>-
>-      def diff_tree(self):
>-              fp = os.popen("git diff-tree --pretty --cc  -v -p --always " +  
>self.commit_sha1)
>-              diff = fp.read()
>-              fp.close()
>-              return diff
>-
>-class AnnotateWindow(object):
>-      """Annotate window.
>-      This object represents and manages a single window containing the
>-      annotate information of the file
>-      """
>-
>-      def __init__(self):
>-              self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
>-              self.window.set_border_width(0)
>-              self.window.set_title("Git repository browser annotation 
>window")
>-              self.prev_read = ""
>-
>-              # Use two thirds of the screen by default
>-              screen = self.window.get_screen()
>-              monitor = screen.get_monitor_geometry(0)
>-              width = int(monitor.width * 0.66)
>-              height = int(monitor.height * 0.66)
>-              self.window.set_default_size(width, height)
>-
>-      def add_file_data(self, filename, commit_sha1, line_num):
>-              fp = os.popen("git cat-file blob " + commit_sha1 +":"+filename)
>-              i = 1;
>-              for line in fp.readlines():
>-                      line = string.rstrip(line)
>-                      self.model.append(None, ["HEAD", filename, line, i])
>-                      i = i+1
>-              fp.close()
>-
>-              # now set the cursor position
>-              self.treeview.set_cursor(line_num-1)
>-              self.treeview.grab_focus()
>-
>-      def _treeview_cursor_cb(self, *args):
>-              """Callback for when the treeview cursor changes."""
>-              (path, col) = self.treeview.get_cursor()
>-              commit_sha1 = self.model[path][0]
>-              commit_msg = ""
>-              fp = os.popen("git cat-file commit " + commit_sha1)
>-              for line in fp.readlines():
>-                      commit_msg =  commit_msg + line
>-              fp.close()
>-
>-              self.commit_buffer.set_text(commit_msg)
>-
>-      def _treeview_row_activated(self, *args):
>-              """Callback for when the treeview row gets selected."""
>-              (path, col) = self.treeview.get_cursor()
>-              commit_sha1 = self.model[path][0]
>-              filename    = self.model[path][1]
>-              line_num    = self.model[path][3]
>-
>-              window = AnnotateWindow();
>-              fp = os.popen("git rev-parse "+ commit_sha1 + "~1")
>-              commit_sha1 = string.strip(fp.readline())
>-              fp.close()
>-              window.annotate(filename, commit_sha1, line_num)
>-
>-      def data_ready(self, source, condition):
>-              while (1):
>-                      try :
>-                              # A simple readline doesn't work
>-                              # a readline bug ??
>-                              buffer = source.read(100)
>-
>-                      except:
>-                              # resource temporary not available
>-                              return True
>-
>-                      if (len(buffer) == 0):
>-                              gobject.source_remove(self.io_watch_tag)
>-                              source.close()
>-                              return False
>-
>-                      if (self.prev_read != ""):
>-                              buffer = self.prev_read + buffer
>-                              self.prev_read = ""
>-
>-                      if (buffer[len(buffer) -1] != '\n'):
>-                              try:
>-                                      newline_index = buffer.rindex("\n")
>-                              except ValueError:
>-                                      newline_index = 0
>-
>-                              self.prev_read = 
>buffer[newline_index:(len(buffer))]
>-                              buffer = buffer[0:newline_index]
>-
>-                      for buff in buffer.split("\n"):
>-                              annotate_line = re.compile('^([0-9a-f]{40}) 
>(.+) (.+) (.+)$')
>-                              m = annotate_line.match(buff)
>-                              if not m:
>-                                      annotate_line = re.compile('^(filename) 
>(.+)$')
>-                                      m = annotate_line.match(buff)
>-                                      if not m:
>-                                              continue
>-                                      filename = m.group(2)
>-                              else:
>-                                      self.commit_sha1 = m.group(1)
>-                                      self.source_line = int(m.group(2))
>-                                      self.result_line = int(m.group(3))
>-                                      self.count          = int(m.group(4))
>-                                      #set the details only when we have the 
>file name
>-                                      continue
>-
>-                              while (self.count > 0):
>-                                      # set at result_line + count-1 the sha1 
>as commit_sha1
>-                                      self.count = self.count - 1
>-                                      iter = self.model.iter_nth_child(None, 
>self.result_line + self.count-1)
>-                                      self.model.set(iter, 0, 
>self.commit_sha1, 1, filename, 3, self.source_line)
>-
>-
>-      def annotate(self, filename, commit_sha1, line_num):
>-              # verify the commit_sha1 specified has this filename
>-
>-              fp = os.popen("git ls-tree "+ commit_sha1 + " -- " + filename)
>-              line = string.strip(fp.readline())
>-              if line == '':
>-                      # pop up the message the file is not there as a part of 
>the commit
>-                      fp.close()
>-                      dialog = gtk.MessageDialog(parent=None, flags=0,
>-                                      type=gtk.MESSAGE_WARNING, 
>buttons=gtk.BUTTONS_CLOSE,
>-                                      message_format=None)
>-                      dialog.set_markup("The file %s is not present in the 
>parent commit %s" % (filename, commit_sha1))
>-                      dialog.run()
>-                      dialog.destroy()
>-                      return
>-
>-              fp.close()
>-
>-              vpan = gtk.VPaned();
>-              self.window.add(vpan);
>-              vpan.show()
>-
>-              scrollwin = gtk.ScrolledWindow()
>-              scrollwin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
>-              scrollwin.set_shadow_type(gtk.SHADOW_IN)
>-              vpan.pack1(scrollwin, True, True);
>-              scrollwin.show()
>-
>-              self.model = gtk.TreeStore(str, str, str, int)
>-              self.treeview = gtk.TreeView(self.model)
>-              self.treeview.set_rules_hint(True)
>-              self.treeview.set_search_column(0)
>-              self.treeview.connect("cursor-changed", 
>self._treeview_cursor_cb)
>-              self.treeview.connect("row-activated", 
>self._treeview_row_activated)
>-              scrollwin.add(self.treeview)
>-              self.treeview.show()
>-
>-              cell = gtk.CellRendererText()
>-              cell.set_property("width-chars", 10)
>-              cell.set_property("ellipsize", pango.ELLIPSIZE_END)
>-              column = gtk.TreeViewColumn("Commit")
>-              column.set_resizable(True)
>-              column.pack_start(cell, expand=True)
>-              column.add_attribute(cell, "text", 0)
>-              self.treeview.append_column(column)
>-
>-              cell = gtk.CellRendererText()
>-              cell.set_property("width-chars", 20)
>-              cell.set_property("ellipsize", pango.ELLIPSIZE_END)
>-              column = gtk.TreeViewColumn("File Name")
>-              column.set_resizable(True)
>-              column.pack_start(cell, expand=True)
>-              column.add_attribute(cell, "text", 1)
>-              self.treeview.append_column(column)
>-
>-              cell = gtk.CellRendererText()
>-              cell.set_property("width-chars", 20)
>-              cell.set_property("ellipsize", pango.ELLIPSIZE_END)
>-              column = gtk.TreeViewColumn("Data")
>-              column.set_resizable(True)
>-              column.pack_start(cell, expand=True)
>-              column.add_attribute(cell, "text", 2)
>-              self.treeview.append_column(column)
>-
>-              # The commit message window
>-              scrollwin = gtk.ScrolledWindow()
>-              scrollwin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
>-              scrollwin.set_shadow_type(gtk.SHADOW_IN)
>-              vpan.pack2(scrollwin, True, True);
>-              scrollwin.show()
>-
>-              commit_text = gtk.TextView()
>-              self.commit_buffer = gtk.TextBuffer()
>-              commit_text.set_buffer(self.commit_buffer)
>-              scrollwin.add(commit_text)
>-              commit_text.show()
>-
>-              self.window.show()
>-
>-              self.add_file_data(filename, commit_sha1, line_num)
>-
>-              fp = os.popen("git blame --incremental -C -C -- " + filename + 
>" " + commit_sha1)
>-              flags = fcntl.fcntl(fp.fileno(), fcntl.F_GETFL)
>-              fcntl.fcntl(fp.fileno(), fcntl.F_SETFL, flags | os.O_NONBLOCK)
>-              self.io_watch_tag = gobject.io_add_watch(fp, gobject.IO_IN, 
>self.data_ready)
>-
>-
>-class DiffWindow(object):
>-      """Diff window.
>-      This object represents and manages a single window containing the
>-      differences between two revisions on a branch.
>-      """
>-
>-      def __init__(self):
>-              self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
>-              self.window.set_border_width(0)
>-              self.window.set_title("Git repository browser diff window")
>-
>-              # Use two thirds of the screen by default
>-              screen = self.window.get_screen()
>-              monitor = screen.get_monitor_geometry(0)
>-              width = int(monitor.width * 0.66)
>-              height = int(monitor.height * 0.66)
>-              self.window.set_default_size(width, height)
>-
>-
>-              self.construct()
>-
>-      def construct(self):
>-              """Construct the window contents."""
>-              vbox = gtk.VBox()
>-              self.window.add(vbox)
>-              vbox.show()
>-
>-              menu_bar = gtk.MenuBar()
>-              save_menu = gtk.ImageMenuItem(gtk.STOCK_SAVE)
>-              save_menu.connect("activate", self.save_menu_response, "save")
>-              save_menu.show()
>-              menu_bar.append(save_menu)
>-              vbox.pack_start(menu_bar, expand=False, fill=True)
>-              menu_bar.show()
>-
>-              hpan = gtk.HPaned()
>-
>-              scrollwin = gtk.ScrolledWindow()
>-              scrollwin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
>-              scrollwin.set_shadow_type(gtk.SHADOW_IN)
>-              hpan.pack1(scrollwin, True, True)
>-              scrollwin.show()
>-
>-              (self.buffer, sourceview) = get_source_buffer_and_view()
>-
>-              sourceview.set_editable(False)
>-              sourceview.modify_font(pango.FontDescription("Monospace"))
>-              scrollwin.add(sourceview)
>-              sourceview.show()
>-
>-              # The file hierarchy: a scrollable treeview
>-              scrollwin = gtk.ScrolledWindow()
>-              scrollwin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
>-              scrollwin.set_shadow_type(gtk.SHADOW_IN)
>-              scrollwin.set_size_request(20, -1)
>-              hpan.pack2(scrollwin, True, True)
>-              scrollwin.show()
>-
>-              self.model = gtk.TreeStore(str, str, str)
>-              self.treeview = gtk.TreeView(self.model)
>-              self.treeview.set_search_column(1)
>-              self.treeview.connect("cursor-changed", self._treeview_clicked)
>-              scrollwin.add(self.treeview)
>-              self.treeview.show()
>-
>-              cell = gtk.CellRendererText()
>-              cell.set_property("width-chars", 20)
>-              column = gtk.TreeViewColumn("Select to annotate")
>-              column.pack_start(cell, expand=True)
>-              column.add_attribute(cell, "text", 0)
>-              self.treeview.append_column(column)
>-
>-              vbox.pack_start(hpan, expand=True, fill=True)
>-              hpan.show()
>-
>-      def _treeview_clicked(self, *args):
>-              """Callback for when the treeview cursor changes."""
>-              (path, col) = self.treeview.get_cursor()
>-              specific_file = self.model[path][1]
>-              commit_sha1 =  self.model[path][2]
>-              if specific_file ==  None :
>-                      return
>-              elif specific_file ==  "" :
>-                      specific_file =  None
>-
>-              window = AnnotateWindow();
>-              window.annotate(specific_file, commit_sha1, 1)
>-
>-
>-      def commit_files(self, commit_sha1, parent_sha1):
>-              self.model.clear()
>-              add  = self.model.append(None, [ "Added", None, None])
>-              dele = self.model.append(None, [ "Deleted", None, None])
>-              mod  = self.model.append(None, [ "Modified", None, None])
>-              diff_tree = re.compile('^(:.{6}) (.{6}) (.{40}) (.{40}) 
>(A|D|M)\s(.+)$')
>-              fp = os.popen("git diff-tree -r --no-commit-id " + parent_sha1 
>+ " " + commit_sha1)
>-              while 1:
>-                      line = string.strip(fp.readline())
>-                      if line == '':
>-                              break
>-                      m = diff_tree.match(line)
>-                      if not m:
>-                              continue
>-
>-                      attr = m.group(5)
>-                      filename = m.group(6)
>-                      if attr == "A":
>-                              self.model.append(add,  [filename, filename, 
>commit_sha1])
>-                      elif attr == "D":
>-                              self.model.append(dele, [filename, filename, 
>commit_sha1])
>-                      elif attr == "M":
>-                              self.model.append(mod,  [filename, filename, 
>commit_sha1])
>-              fp.close()
>-
>-              self.treeview.expand_all()
>-
>-      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.
>-              """
>-              # Diff with the first commit or the last commit shows nothing
>-              if (commit_sha1 == 0 or parent_sha1 == 0 ):
>-                      return
>-
>-              fp = os.popen("git diff-tree -p " + parent_sha1 + " " + 
>commit_sha1)
>-              self.buffer.set_text(unicode(fp.read(), 
>encoding).encode('utf-8'))
>-              fp.close()
>-              self.commit_files(commit_sha1, parent_sha1)
>-              self.window.show()
>-
>-      def save_menu_response(self, widget, string):
>-              dialog = gtk.FileChooserDialog("Save..", None, 
>gtk.FILE_CHOOSER_ACTION_SAVE,
>-                              (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
>-                                      gtk.STOCK_SAVE, gtk.RESPONSE_OK))
>-              dialog.set_default_response(gtk.RESPONSE_OK)
>-              response = dialog.run()
>-              if response == gtk.RESPONSE_OK:
>-                      patch_buffer = 
>self.buffer.get_text(self.buffer.get_start_iter(),
>-                                      self.buffer.get_end_iter())
>-                      fp = open(dialog.get_filename(), "w")
>-                      fp.write(patch_buffer)
>-                      fp.close()
>-              dialog.destroy()
>-
>-class GitView(object):
>-      """ This is the main class
>-      """
>-      version = "0.9"
>-
>-      def __init__(self, with_diff=0):
>-              self.with_diff = with_diff
>-              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
>-              screen = self.window.get_screen()
>-              monitor = screen.get_monitor_geometry(0)
>-              width = int(monitor.width * 0.75)
>-              height = int(monitor.height * 0.75)
>-              self.window.set_default_size(width, height)
>-
>-              # FIXME AndyFitz!
>-              icon = self.window.render_icon(gtk.STOCK_INDEX, 
>gtk.ICON_SIZE_BUTTON)
>-              self.window.set_icon(icon)
>-
>-              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.accel_group.connect_group(0xffc1, 0, gtk.ACCEL_LOCKED, 
>self.maximize);
>-              self.accel_group.connect_group(0xffc8, 0, gtk.ACCEL_LOCKED, 
>self.fullscreen);
>-              self.accel_group.connect_group(0xffc9, 0, gtk.ACCEL_LOCKED, 
>self.unfullscreen);
>-
>-              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 maximize(self, widget, event=None, *arguments, **keywords):
>-              self.window.maximize()
>-              return True
>-
>-      def fullscreen(self, widget, event=None, *arguments, **keywords):
>-              self.window.fullscreen()
>-              return True
>-
>-      def unfullscreen(self, widget, event=None, *arguments, **keywords):
>-              self.window.unfullscreen()
>-              return True
>-
>-      def get_bt_sha1(self):
>-              """ Update the bt_sha1 dictionary with the
>-              respective sha1 details """
>-
>-              self.bt_sha1 = { }
>-              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()
>-
>-      def get_encoding(self):
>-              fp = os.popen("git 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)
>-              menu_bar = gtk.MenuBar()
>-              menu_bar.set_pack_direction(gtk.PACK_DIRECTION_RTL)
>-              help_menu = gtk.MenuItem("Help")
>-              menu = gtk.Menu()
>-              about_menu = gtk.MenuItem("About")
>-              menu.append(about_menu)
>-              about_menu.connect("activate", self.about_menu_response, 
>"about")
>-              about_menu.show()
>-              help_menu.set_submenu(menu)
>-              help_menu.show()
>-              menu_bar.append(help_menu)
>-              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_AUTOMATIC, gtk.POLICY_AUTOMATIC)
>-              scrollwin.set_shadow_type(gtk.SHADOW_IN)
>-              vbox.pack_start(scrollwin, expand=True, fill=True)
>-              scrollwin.show()
>-
>-              self.treeview = gtk.TreeView()
>-              self.treeview.set_rules_hint(True)
>-              self.treeview.set_search_column(4)
>-              self.treeview.connect("cursor-changed", 
>self._treeview_cursor_cb)
>-              scrollwin.add(self.treeview)
>-              self.treeview.show()
>-
>-              cell = CellRendererGraph()
>-              column = gtk.TreeViewColumn()
>-              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)
>-              self.treeview.append_column(column)
>-
>-              cell = gtk.CellRendererText()
>-              cell.set_property("width-chars", 65)
>-              cell.set_property("ellipsize", pango.ELLIPSIZE_END)
>-              column = gtk.TreeViewColumn("Message")
>-              column.set_resizable(True)
>-              column.pack_start(cell, expand=True)
>-              column.add_attribute(cell, "text", 4)
>-              self.treeview.append_column(column)
>-
>-              cell = gtk.CellRendererText()
>-              cell.set_property("width-chars", 40)
>-              cell.set_property("ellipsize", pango.ELLIPSIZE_END)
>-              column = gtk.TreeViewColumn("Author")
>-              column.set_resizable(True)
>-              column.pack_start(cell, expand=True)
>-              column.add_attribute(cell, "text", 5)
>-              self.treeview.append_column(column)
>-
>-              cell = gtk.CellRendererText()
>-              cell.set_property("ellipsize", pango.ELLIPSIZE_END)
>-              column = gtk.TreeViewColumn("Date")
>-              column.set_resizable(True)
>-              column.pack_start(cell, expand=True)
>-              column.add_attribute(cell, "text", 6)
>-              self.treeview.append_column(column)
>-
>-              return vbox
>-
>-      def about_menu_response(self, widget, string):
>-              dialog = gtk.AboutDialog()
>-              dialog.set_name("Gitview")
>-              dialog.set_version(GitView.version)
>-              dialog.set_authors(["Aneesh Kumar K.V 
><[email protected]>"])
>-              
>dialog.set_website("http://www.kernel.org/pub/software/scm/git/";)
>-              dialog.set_copyright("Use and distribute under the terms of the 
>GNU General Public License")
>-              dialog.set_wrap_license(True)
>-              dialog.run()
>-              dialog.destroy()
>-
>-
>-      def construct_bottom(self):
>-              """Construct the bottom half of the window."""
>-              vbox = gtk.VBox(False, spacing=6)
>-              vbox.set_border_width(12)
>-              (width, height) = self.window.get_size()
>-              vbox.set_size_request(width, int(height / 2.5))
>-              vbox.show()
>-
>-              self.table = gtk.Table(rows=4, columns=4)
>-              self.table.set_row_spacings(6)
>-              self.table.set_col_spacings(6)
>-              vbox.pack_start(self.table, expand=False, fill=True)
>-              self.table.show()
>-
>-              align = gtk.Alignment(0.0, 0.5)
>-              label = gtk.Label()
>-              label.set_markup("<b>Revision:</b>")
>-              align.add(label)
>-              self.table.attach(align, 0, 1, 0, 1, gtk.FILL, gtk.FILL)
>-              label.show()
>-              align.show()
>-
>-              align = gtk.Alignment(0.0, 0.5)
>-              self.revid_label = gtk.Label()
>-              self.revid_label.set_selectable(True)
>-              align.add(self.revid_label)
>-              self.table.attach(align, 1, 2, 0, 1, gtk.EXPAND | gtk.FILL, 
>gtk.FILL)
>-              self.revid_label.show()
>-              align.show()
>-
>-              align = gtk.Alignment(0.0, 0.5)
>-              label = gtk.Label()
>-              label.set_markup("<b>Committer:</b>")
>-              align.add(label)
>-              self.table.attach(align, 0, 1, 1, 2, gtk.FILL, gtk.FILL)
>-              label.show()
>-              align.show()
>-
>-              align = gtk.Alignment(0.0, 0.5)
>-              self.committer_label = gtk.Label()
>-              self.committer_label.set_selectable(True)
>-              align.add(self.committer_label)
>-              self.table.attach(align, 1, 2, 1, 2, gtk.EXPAND | gtk.FILL, 
>gtk.FILL)
>-              self.committer_label.show()
>-              align.show()
>-
>-              align = gtk.Alignment(0.0, 0.5)
>-              label = gtk.Label()
>-              label.set_markup("<b>Timestamp:</b>")
>-              align.add(label)
>-              self.table.attach(align, 0, 1, 2, 3, gtk.FILL, gtk.FILL)
>-              label.show()
>-              align.show()
>-
>-              align = gtk.Alignment(0.0, 0.5)
>-              self.timestamp_label = gtk.Label()
>-              self.timestamp_label.set_selectable(True)
>-              align.add(self.timestamp_label)
>-              self.table.attach(align, 1, 2, 2, 3, gtk.EXPAND | gtk.FILL, 
>gtk.FILL)
>-              self.timestamp_label.show()
>-              align.show()
>-
>-              align = gtk.Alignment(0.0, 0.5)
>-              label = gtk.Label()
>-              label.set_markup("<b>Parents:</b>")
>-              align.add(label)
>-              self.table.attach(align, 0, 1, 3, 4, gtk.FILL, gtk.FILL)
>-              label.show()
>-              align.show()
>-              self.parents_widgets = []
>-
>-              align = gtk.Alignment(0.0, 0.5)
>-              label = gtk.Label()
>-              label.set_markup("<b>Children:</b>")
>-              align.add(label)
>-              self.table.attach(align, 2, 3, 3, 4, gtk.FILL, gtk.FILL)
>-              label.show()
>-              align.show()
>-              self.children_widgets = []
>-
>-              scrollwin = gtk.ScrolledWindow()
>-              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()
>-
>-              (self.message_buffer, sourceview) = get_source_buffer_and_view()
>-
>-              sourceview.set_editable(False)
>-              sourceview.modify_font(pango.FontDescription("Monospace"))
>-              scrollwin.add(sourceview)
>-              sourceview.show()
>-
>-              return vbox
>-
>-      def _treeview_cursor_cb(self, *args):
>-              """Callback for when the treeview cursor changes."""
>-              (path, col) = self.treeview.get_cursor()
>-              commit = self.model[path][0]
>-
>-              if commit.committer is not None:
>-                      committer = commit.committer
>-                      timestamp = commit.commit_date
>-                      message   =  commit.get_message(self.with_diff)
>-                      revid_label = commit.commit_sha1
>-              else:
>-                      committer = ""
>-                      timestamp = ""
>-                      message = ""
>-                      revid_label = ""
>-
>-              self.revid_label.set_text(revid_label)
>-              self.committer_label.set_text(committer)
>-              self.timestamp_label.set_text(timestamp)
>-              self.message_buffer.set_text(unicode(message, 
>self.encoding).encode('utf-8'))
>-
>-              for widget in self.parents_widgets:
>-                      self.table.remove(widget)
>-
>-              self.parents_widgets = []
>-              self.table.resize(4 + len(commit.parent_sha1) - 1, 4)
>-              for idx, parent_id in enumerate(commit.parent_sha1):
>-                      self.table.set_row_spacing(idx + 3, 0)
>-
>-                      align = gtk.Alignment(0.0, 0.0)
>-                      self.parents_widgets.append(align)
>-                      self.table.attach(align, 1, 2, idx + 3, idx + 4,
>-                                      gtk.EXPAND | gtk.FILL, gtk.FILL)
>-                      align.show()
>-
>-                      hbox = gtk.HBox(False, 0)
>-                      align.add(hbox)
>-                      hbox.show()
>-
>-                      label = gtk.Label(parent_id)
>-                      label.set_selectable(True)
>-                      hbox.pack_start(label, expand=False, fill=True)
>-                      label.show()
>-
>-                      image = gtk.Image()
>-                      image.set_from_stock(gtk.STOCK_JUMP_TO, 
>gtk.ICON_SIZE_MENU)
>-                      image.show()
>-
>-                      button = gtk.Button()
>-                      button.add(image)
>-                      button.set_relief(gtk.RELIEF_NONE)
>-                      button.connect("clicked", self._go_clicked_cb, 
>parent_id)
>-                      hbox.pack_start(button, expand=False, fill=True)
>-                      button.show()
>-
>-                      image = gtk.Image()
>-                      image.set_from_stock(gtk.STOCK_FIND, gtk.ICON_SIZE_MENU)
>-                      image.show()
>-
>-                      button = gtk.Button()
>-                      button.add(image)
>-                      button.set_relief(gtk.RELIEF_NONE)
>-                      button.set_sensitive(True)
>-                      button.connect("clicked", self._show_clicked_cb,
>-                                      commit.commit_sha1, parent_id, 
>self.encoding)
>-                      hbox.pack_start(button, expand=False, fill=True)
>-                      button.show()
>-
>-              # Populate with child details
>-              for widget in self.children_widgets:
>-                      self.table.remove(widget)
>-
>-              self.children_widgets = []
>-              try:
>-                      child_sha1 = Commit.children_sha1[commit.commit_sha1]
>-              except KeyError:
>-                      # We don't have child
>-                      child_sha1 = [ 0 ]
>-
>-              if ( len(child_sha1) > len(commit.parent_sha1)):
>-                      self.table.resize(4 + len(child_sha1) - 1, 4)
>-
>-              for idx, child_id in enumerate(child_sha1):
>-                      self.table.set_row_spacing(idx + 3, 0)
>-
>-                      align = gtk.Alignment(0.0, 0.0)
>-                      self.children_widgets.append(align)
>-                      self.table.attach(align, 3, 4, idx + 3, idx + 4,
>-                                      gtk.EXPAND | gtk.FILL, gtk.FILL)
>-                      align.show()
>-
>-                      hbox = gtk.HBox(False, 0)
>-                      align.add(hbox)
>-                      hbox.show()
>-
>-                      label = gtk.Label(child_id)
>-                      label.set_selectable(True)
>-                      hbox.pack_start(label, expand=False, fill=True)
>-                      label.show()
>-
>-                      image = gtk.Image()
>-                      image.set_from_stock(gtk.STOCK_JUMP_TO, 
>gtk.ICON_SIZE_MENU)
>-                      image.show()
>-
>-                      button = gtk.Button()
>-                      button.add(image)
>-                      button.set_relief(gtk.RELIEF_NONE)
>-                      button.connect("clicked", self._go_clicked_cb, child_id)
>-                      hbox.pack_start(button, expand=False, fill=True)
>-                      button.show()
>-
>-                      image = gtk.Image()
>-                      image.set_from_stock(gtk.STOCK_FIND, gtk.ICON_SIZE_MENU)
>-                      image.show()
>-
>-                      button = gtk.Button()
>-                      button.add(image)
>-                      button.set_relief(gtk.RELIEF_NONE)
>-                      button.set_sensitive(True)
>-                      button.connect("clicked", self._show_clicked_cb,
>-                                      child_id, commit.commit_sha1, 
>self.encoding)
>-                      hbox.pack_start(button, expand=False, fill=True)
>-                      button.show()
>-
>-      def _destroy_cb(self, widget):
>-              """Callback for when a window we manage is destroyed."""
>-              self.quit()
>-
>-
>-      def quit(self):
>-              """Stop the GTK+ main loop."""
>-              gtk.main_quit()
>-
>-      def run(self, args):
>-              self.set_branch(args)
>-              self.window.connect("destroy", self._destroy_cb)
>-              self.window.show()
>-              gtk.main()
>-
>-      def set_branch(self, args):
>-              """Fill in different windows with info from the reposiroty"""
>-              fp = os.popen("git rev-parse --sq --default HEAD " + 
>list_to_string(args, 1))
>-              git_rev_list_cmd = fp.read()
>-              fp.close()
>-              fp = os.popen("git rev-list  --header --topo-order --parents " 
>+ git_rev_list_cmd)
>-              self.update_window(fp)
>-
>-      def update_window(self, fp):
>-              commit_lines = []
>-
>-              self.model = gtk.ListStore(gobject.TYPE_PYOBJECT, 
>gobject.TYPE_PYOBJECT,
>-                              gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT, 
>str, str, str)
>-
>-              # used for cursor positioning
>-              self.index = {}
>-
>-              self.colours = {}
>-              self.nodepos = {}
>-              self.incomplete_line = {}
>-              self.commits = []
>-
>-              index = 0
>-              last_colour = 0
>-              last_nodepos = -1
>-              out_line = []
>-              input_line = fp.readline()
>-              while (input_line != ""):
>-                      # The commit header ends with '\0'
>-                      # This NULL is immediately followed by the sha1 of the
>-                      # next commit
>-                      if (input_line[0] != '\0'):
>-                              commit_lines.append(input_line)
>-                              input_line = fp.readline()
>-                              continue;
>-
>-                      commit = Commit(commit_lines)
>-                      if (commit != None ):
>-                              self.commits.append(commit)
>-
>-                      # Skip the '\0
>-                      commit_lines = []
>-                      commit_lines.append(input_line[1:])
>-                      input_line = fp.readline()
>-
>-              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()
>-
>-      def draw_graph(self, commit, index, out_line, last_colour, 
>last_nodepos):
>-              in_line=[]
>-
>-              #   |   -> outline
>-              #   X
>-              #   |\  <- inline
>-
>-              # Reset nodepostion
>-              if (last_nodepos > 5):
>-                      last_nodepos = -1
>-
>-              # Add the incomplete lines of the last cell in this
>-              try:
>-                      colour = self.colours[commit.commit_sha1]
>-              except KeyError:
>-                      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:
>-                      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:
>-                      # check we already have the value
>-                      tmp_node_pos = self.nodepos[commit.parent_sha1[0]]
>-              except KeyError:
>-                      self.colours[commit.parent_sha1[0]] = colour
>-                      self.nodepos[commit.parent_sha1[0]] = node_pos
>-
>-              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]
>-
>-
>-              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]
>-              except KeyError:
>-                      branch_tag = [ ]
>-
>-
>-              node = (node_pos, colour, branch_tag)
>-
>-              self.model.append([commit, node, out_line, in_line,
>-                              commit.message, commit.author, commit.date])
>-
>-              return (in_line, last_colour, last_nodepos)
>-
>-      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:
>-                      dialog = gtk.MessageDialog(parent=None, flags=0,
>-                                      type=gtk.MESSAGE_WARNING, 
>buttons=gtk.BUTTONS_CLOSE,
>-                                      message_format=None)
>-                      dialog.set_markup("Revision <b>%s</b> not present in 
>the list" % revid)
>-                      # revid == 0 is the parent of the first commit
>-                      if (revid != 0 ):
>-                              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, encoding):
>-              """Callback for when the show button for a parent is clicked."""
>-              window = DiffWindow()
>-              window.set_diff(commit_sha1, parent_sha1, encoding)
>-              self.treeview.grab_focus()
>-
>-without_diff = 0
>-if __name__ == "__main__":
>-
>-      if (len(sys.argv) > 1 ):
>-              if (sys.argv[1] == "--without-diff"):
>-                      without_diff = 1
>-
>-      view = GitView( without_diff != 1)
>-      view.run(sys.argv[without_diff:])
>diff --git a/contrib/gitview/gitview.txt b/contrib/gitview/gitview.txt
>deleted file mode 100644
>index 7b5f9002b9..0000000000
>--- a/contrib/gitview/gitview.txt
>+++ /dev/null
>@@ -1,57 +0,0 @@
>-gitview(1)
>-==========
>-
>-NAME
>-----
>-gitview - A GTK based repository browser for git
>-
>-SYNOPSIS
>---------
>-[verse]
>-'gitview' [options] [args]
>-
>-DESCRIPTION
>----------
>-
>-Dependencies:
>-
>-* Python 2.4
>-* PyGTK 2.8 or later
>-* PyCairo 1.0 or later
>-
>-OPTIONS
>--------
>---without-diff::
>-
>-      If the user doesn't want to list the commit diffs in the main window.
>-      This may speed up the repository browsing.
>-
>-<args>::
>-
>-      All the valid option for linkgit:git-rev-list[1].
>-
>-Key Bindings
>-------------
>-F4::
>-      To maximize the window
>-
>-F5::
>-      To reread references.
>-
>-F11::
>-      Full screen
>-
>-F12::
>-      Leave full screen
>-
>-EXAMPLES
>---------
>-
>-gitview v2.6.12.. include/scsi drivers/scsi::
>-
>-      Show as the changes since version v2.6.12 that changed any file in the
>-      include/scsi or drivers/scsi subdirectories
>-
>-gitview --since=2.weeks.ago::
>-
>-      Show the changes during the last two weeks
>-- 
>2.11.0.259.ga95e92af08
>
>
>

Reply via email to