* gitk changing line color for no reason after merge
From: Pavel Roskin @ 2006-02-02 17:21 UTC (permalink / raw)
To: Paul Mackerras, git
Hello, Paul!
I have noticed that gitk changes the line color at a commit following a
merge (i.e. a commit with many parents). I made this screenshot to
demonstrate the problem:
http://red-bean.com/proski/gitk/gitk.png
If you follow the leftmost line, you'll see how green becomes red, gray
becomes brown and red becomes blue.
I think it would be much better if line colors only change at
non-trivial nodes, i.e. those with more than one child or parent.
The fix is trivial:
diff --git a/gitk b/gitk
index f12b3ce..14ff570 100755
--- a/gitk
+++ b/gitk
@@ -770,7 +770,7 @@ proc assigncolor {id} {
if [info exists colormap($id)] return
set ncolors [llength $colors]
- if {$nparents($id) <= 1 && $nchildren($id) == 1} {
+ if {$nchildren($id) == 1} {
set child [lindex $children($id) 0]
if {[info exists colormap($child)]
&& $nparents($child) == 1} {
I checked the history of gitk and could trace this code back to the
first version of gitk in the git repository. Maybe it was intended this
way, but I think it would be better to fix it.
--
Regards,
Pavel Roskin
^ permalink raw reply related
* [PATCH 1/2] Provide a more meaningful initial "From " line when using --compose in git-send-email.
From: Ryan Anderson @ 2006-02-02 16:56 UTC (permalink / raw)
To: git; +Cc: Ryan Anderson
In-Reply-To: <11388993661745-git-send-email-ryan@michonline.com>
git-send-email, when used with --compose, provided the user with a mbox-format
file to edit. Some users, however, were confused by the leading, blank, "From
" line, so this change puts the value that will appear on the From: line of the
actual email on this line, along with a note that the line is ignored.
Signed-off-by: Ryan Anderson <ryan@michonline.com>
---
git-send-email.perl | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
c6b0c22e482aa6fe314e4be077d705c98fee7bf2
diff --git a/git-send-email.perl b/git-send-email.perl
index ec1428d..51b7513 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -125,7 +125,7 @@ if ($compose) {
# effort to have it be unique
open(C,">",$compose_filename)
or die "Failed to open for writing $compose_filename: $!";
- print C "From \n";
+ print C "From $from # This line is ignored.\n";
printf C "Subject: %s\n\n", $initial_subject;
printf C <<EOT;
GIT: Please enter your email below.
--
1.1.4.g3dcbd
^ permalink raw reply related
* [PATCH 0/2] Small updates to git-send-email
From: Ryan Anderson @ 2006-02-02 16:56 UTC (permalink / raw)
To: git
These updates fix some usability issues raised by Octavian in #git.
Thanks for the feedback!
--
Ryan Anderson
sometimes Pug Majere
^ permalink raw reply
* [PATCH 2/2] git-send-email: Add --quiet to reduce some of the chatter when sending emails.
From: Ryan Anderson @ 2006-02-02 16:56 UTC (permalink / raw)
To: git; +Cc: Ryan Anderson
In-Reply-To: <11388993663675-git-send-email-ryan@michonline.com>
Signed-off-by: Ryan Anderson <ryan@michonline.com>
---
git-send-email.perl | 9 ++++++---
1 files changed, 6 insertions(+), 3 deletions(-)
3dcbd6298dc6fb4a903404cb9c47e3690bf2e01a
diff --git a/git-send-email.perl b/git-send-email.perl
index 51b7513..ca1fa37 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -34,7 +34,7 @@ my $compose_filename = ".msg.$$";
my (@to,@cc,$initial_reply_to,$initial_subject,@files,$from,$compose);
# Behavior modification variables
-my ($chain_reply_to, $smtp_server) = (1, "localhost");
+my ($chain_reply_to, $smtp_server, $quiet) = (1, "localhost", 0);
# Example reply to:
#$initial_reply_to = ''; #<20050203173208.GA23964@foobar.com>';
@@ -51,6 +51,7 @@ my $rc = GetOptions("from=s" => \$from,
"chain-reply-to!" => \$chain_reply_to,
"smtp-server=s" => \$smtp_server,
"compose" => \$compose,
+ "quiet" => \$quiet,
);
# Now, let's fill any that aren't set in with defaults:
@@ -267,8 +268,10 @@ sub send_message
sendmail(%mail) or die $Mail::Sendmail::error;
- print "OK. Log says:\n", $Mail::Sendmail::log;
- print "\n\n"
+ unless ($quiet) {
+ print "OK. Log says:\n", $Mail::Sendmail::log;
+ print "\n\n"
+ }
}
--
1.1.4.g3dcbd
^ permalink raw reply related
* Re: Two ideas for improving git's user interface
From: Carl Baldwin @ 2006-02-02 16:30 UTC (permalink / raw)
To: Carl Worth; +Cc: Linus Torvalds, Junio C Hamano, Nicolas Pitre, git
In-Reply-To: <87lkwupsbr.wl%cworth@cworth.org>
On Wed, Feb 01, 2006 at 03:33:44PM -0800, Carl Worth wrote:
> Is it ever useful (reasonable, desirable) to commit file
> contents that differ from the contents of the working
> directory?
What _is_ useful about the status quo is the ability to make some minor
change, update that change to the index when I've decided that it is a
good change and then use git diff to see what I've incrementally changed
in the same file since that update. That way new incremental changes
can be viewed independantly of the change I've already decided was good.
> What I would love to have is the ability to pass the same arguments to
> git diff to get a preview of what any get commit would do. For
> example, something like:
>
> git diff # would be a preview of:
> git commit
'git diff --cached' does this.
> git diff -a # would be a preview of:
> git commit -a
'git diff HEAD' does this.
> git diff fileA fileB # would be a preview of:
> git commit fileA fileB
Paths can be specified in conjunction with the above commands.
Yes, these are idioms specific to git and are not immediately intuitive
to the new user. However, if the user has access to a good tutorial
that walks through these scenerios its not so bad.
Carl
--
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Carl Baldwin RADCAD (R&D CAD)
Hewlett Packard Company
MS 88 work: 970 898-1523
3404 E. Harmony Rd. work: Carl.N.Baldwin@hp.com
Fort Collins, CO 80525 home: Carl@ecBaldwin.net
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
^ permalink raw reply
* Re: gitview 0.3
From: Aneesh Kumar @ 2006-02-02 16:03 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vzmlauw35.fsf@assigned-by-dhcp.cox.net>
[-- Attachment #1: Type: text/plain, Size: 2780 bytes --]
On 2/2/06, Junio C Hamano <junkio@cox.net> wrote:
> Nice work for 0.low-number version.
>
> On my notebook, I felt really miserable to see that the middle
> band taking so much space to show rev committer timestamp and
> parents. The bottom window starts with the same information
> repeated (worse, with unreadable timestamp format) and I had to
> scroll all the way down to view the rest of the commit message.
I have rearranged the default with respect these frames. Attaching the
code below. Let me know if it is ok.
>
> If you absolutely want the middle band, maybe instead of showing
> object names in "Parents" "Children" part, you can show the
> one-line commit logs from them there, and pop-up the object
> names along with the rest of commit log message as mouse hovers
> over.
>
> I missed "this commit is branch head of X" and "this commit is
> tagged with T" markers gitk has.
>
I am planning to add this. I am yet to learn fully how to use the
cairo API. gitview was partly my attempt to learn pygtk.
> Needs a bit more compact layout to be useful for me. In short,
> gitk's display does everything I want it to show in a compact
> enough way and I think there is no reason not to imitate it.
>
One thing i didn't like with gitk was the looks. And the diff window
was so shaded i had to put real effort to read the contents. May be i
didn't had necessary fonts. I don't know
> Do colors of nodes have any significance? I couldn't tell from
> the UI (and I tried to figure it out without reading code --
> otherwise I cannot tell if the choice of colors is intuitive).
>
One parent of the child follows the same colour. It in a way let one
figure out at what point branch happened and at what point they merged
back.
> It might match more people's expectation if --with-diff were the
> default.
>
This is done. I am attaching the full code below. Can you get the
gitview added git repository so that next time onwards i need to send
only the diff.
> This patch might make merges easier to read.
>
> -- >8 --
> [PATCH] Use "diff-tree -c" to display merges a bit more readably.
>
> --- a/gitview 2006-02-01 21:16:43.000000000 -0800
> +++ b/gitview 2006-02-01 21:46:24.000000000 -0800
> @@ -305,7 +305,7 @@
> return message
>
> def diff_tree(self):
> - fp = os.popen("git diff-tree --pretty -m -v -p " + " " + self.commit_sha1)
> + fp = os.popen("git diff-tree --pretty -c -v -p " + " " + self.commit_sha1)
> diff = fp.read()
> fp.close()
>
>
>
>
I am using the --cc flag and if i don't have any message i get the
commit message only using git cat-file. I guess that is ok
-aneesh
[-- Attachment #2: gitview --]
[-- Type: application/octet-stream, Size: 24940 bytes --]
#! /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 <scott@ubuntu.com>
"""
__author__ = "Aneesh Kumar K.V <aneesh.kumar@gmail.com>"
import sys
import os
import gtk
import pygtk
import pango
import re
import time
import gobject
import cairo
import math
import string
try:
import gtksourceview
have_gtksourceview = True
except ImportError:
have_gtksourceview = False
print "Running without gtksourceview module"
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
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) 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 = max(cols, start, end)
width = box_size * (cols + 1)
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) = 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()
class Commit:
""" This represent a commit object obtained after parsing the git-rev-list
output """
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.match("author", line)
if (m != None ):
patch_author = re.split(" ", line)
self.author = list_to_string(patch_author[1:-2], 0)
self.date = time.strftime("%Y-%m-%d %H:%M:%S",
time.gmtime(float(patch_author[-2])))
continue
m = re.match("committer", line)
if (m != None ):
patch_committer = re.split(" ", line)
self.committer = list_to_string(patch_committer[1:-2], 0)
self.commit_date = time.strftime("%Y-%m-%d %H:%M:%S",
time.gmtime(float(patch_committer[-2])))
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 " + " " + self.commit_sha1)
diff = fp.read()
fp.close()
if (diff == ""):
# After optimization in case of merge commits if don't
# have any diffs. Just show the commit message
diff = self.get_message(0)
return diff
class DiffWindow:
"""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."""
hbox = gtk.HBox(spacing=6)
hbox.set_border_width(12)
self.window.add(hbox)
hbox.show()
scrollwin = gtk.ScrolledWindow()
scrollwin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
scrollwin.set_shadow_type(gtk.SHADOW_IN)
hbox.pack_start(scrollwin, expand=True, fill=True)
scrollwin.show()
if have_gtksourceview:
self.buffer = gtksourceview.SourceBuffer()
slm = gtksourceview.SourceLanguagesManager()
gsl = slm.get_language_from_mime_type("text/x-patch")
self.buffer.set_highlight(True)
self.buffer.set_language(gsl)
sourceview = gtksourceview.SourceView(self.buffer)
else:
self.buffer = gtk.TextBuffer()
sourceview = gtk.TextView(self.buffer)
sourceview.set_editable(False)
sourceview.modify_font(pango.FontDescription("Monospace"))
scrollwin.add(sourceview)
sourceview.show()
def set_diff(self, commit_sha1, parent_sha1):
"""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(fp.read())
fp.close()
self.window.show()
class GitView:
""" This is the main class
"""
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")
# 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.construct()
def construct(self):
"""Construct the window contents."""
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()
scrollwin = gtk.ScrolledWindow()
scrollwin.set_policy(gtk.POLICY_NEVER, 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(False)
column.pack_start(cell, expand=False)
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 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()
if have_gtksourceview:
self.message_buffer = gtksourceview.SourceBuffer()
slm = gtksourceview.SourceLanguagesManager()
gsl = slm.get_language_from_mime_type("text/x-patch")
self.message_buffer.set_highlight(True)
self.message_buffer.set_language(gsl)
sourceview = gtksourceview.SourceView(self.message_buffer)
else:
self.message_buffer = gtk.TextBuffer()
sourceview = gtk.TextView(self.message_buffer)
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(message)
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)
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)
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 = {}
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 ):
(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
# Skip the '\0
commit_lines = []
commit_lines.append(input_line[1:])
input_line = fp.readline()
fp.close()
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 = 0
# 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
try:
node_pos = self.nodepos[commit.commit_sha1]
except KeyError:
last_nodepos +=1
self.nodepos[commit.commit_sha1] = last_nodepos
node_pos = last_nodepos
#The first parent always continue on the same line
try:
# check we alreay 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
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)
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)
node = (node_pos, colour)
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, index):
try:
self.incomplete_line[sha1].append(self.nodepos[sha1])
except KeyError:
self.incomplete_line[sha1] = [self.nodepos[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
# revid == 0 is the parent of the first commit
if (revid != 0 ):
print "Try running gitview without any options"
self.treeview.grab_focus()
def _show_clicked_cb(self, widget, commit_sha1, parent_sha1):
"""Callback for when the show button for a parent is clicked."""
window = DiffWindow()
window.set_diff(commit_sha1, parent_sha1)
self.treeview.grab_focus()
if __name__ == "__main__":
without_diff = 0
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:])
^ permalink raw reply
* Re: [PATCH] git-svnimport.perl: fix for 'arg list too long...'
From: Sasha Khapyorsky @ 2006-02-02 14:26 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, Matthias Urlichs
In-Reply-To: <7v3bj27kxe.fsf@assigned-by-dhcp.cox.net>
On 14:50 Wed 01 Feb , Junio C Hamano wrote:
>
> *1* I do not think this makes much of a difference but here is what
> I mean.
>
> diff --git a/git-svnimport.perl b/git-svnimport.perl
Tested. Works good. I think your version is cleaner. Cosmetic comment btw:
> + open my $F, "|-",
> + qw(git-update-index --force-remove -z --stdin)
> + or die $!;
> + print $F "$_\0" for @u;
> + close $F or die $!;
It is not critical, but this block may be under if(@u) {..} to prevent
"empty" git-update-index invocations.
Sasha.
^ permalink raw reply
* Re: Two ideas for improving git's user interface
From: Florian Weimer @ 2006-02-02 12:31 UTC (permalink / raw)
To: git
In-Reply-To: <87lkwupsbr.wl%cworth@cworth.org>
* Carl Worth:
> Here's a fundamental question I have, (and thanks to Keith Packard for
> helping me to phrase it):
>
> Is it ever useful (reasonable, desirable) to commit file
> contents that differ from the contents of the working
> directory?
You mean like "darcs record"? 8-)
I think this is very useful functionality. Granted, it interferes
with a rigorous developer-side regression test policy ("all changes
must have been built and passed the test suite"). But it encourages
things like fixing typos in comments you spot while editing a file for
other reasons. And you can keep some ugly debugging code while
working on a series of changes.
^ permalink raw reply
* [PATCH] Fix date display
From: Jonas Fonseca @ 2006-02-02 12:21 UTC (permalink / raw)
To: Aneesh Kumar; +Cc: git, junkio
In-Reply-To: <cc723f590602012033w41b49b2ao4423707702086739@mail.gmail.com>
Hello,
Here is a patch that uses the tz info for setting commit dates.
--- a/gitview 2006-02-02 12:29:05.000000000 +0100
+++ b/gitview 2006-02-02 12:28:24.000000000 +0100
@@ -31,6 +31,7 @@
have_gtksourceview = False
print "Running without 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)
@@ -43,6 +44,16 @@
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))
+
class CellRendererGraph(gtk.GenericCellRenderer):
"""Cell renderer for directed graph.
@@ -277,22 +288,15 @@
if (m != None):
continue
-
- m = re.match("author", line)
- if (m != None ):
- patch_author = re.split(" ", line)
- self.author = list_to_string(patch_author[1:-2], 0)
- self.date = time.strftime("%Y-%m-%d %H:%M:%S",
- time.gmtime(float(patch_author[-2])))
- continue
-
- m = re.match("committer", line)
- if (m != None ):
- patch_committer = re.split(" ", line)
- self.committer = list_to_string(patch_committer[1:-2], 0)
- self.commit_date = time.strftime("%Y-%m-%d %H:%M:%S",
- time.gmtime(float(patch_committer[-2])))
- continue
+ m = re_ident.match(line)
+ if (m != None):
+ date = show_date(m.group('epoch'), m.group('tz'))
+ if m.group(1)[0] == 'a':
+ self.author = m.group('ident')
+ self.date = date
+ else:
+ self.committer = m.group('ident')
+ self.commit_date = date
def get_message(self, with_diff=0):
if (with_diff == 1):
--
Jonas Fonseca
^ permalink raw reply
* [PATCH 2/2] merge-recursive: Speed up commit graph construction
From: Fredrik Kuivinen @ 2006-02-02 11:43 UTC (permalink / raw)
To: git; +Cc: junkio
In-Reply-To: <20060202113848.GA8103@c165.ib.student.liu.se>
Use __slots__ to speed up construction and decrease memory consumption
of the Commit objects.
Signed-off-by: Fredrik Kuivinen <freku045@student.liu.se>
---
gitMergeCommon.py | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
23aa79d4e86761e049bc44b5106cd45355045174
diff --git a/gitMergeCommon.py b/gitMergeCommon.py
index ff6f58a..fdbf9e4 100644
--- a/gitMergeCommon.py
+++ b/gitMergeCommon.py
@@ -107,7 +107,10 @@ def isSha(obj):
return (type(obj) is str and bool(shaRE.match(obj))) or \
(type(obj) is int and obj >= 1)
-class Commit:
+class Commit(object):
+ __slots__ = ['parents', 'firstLineMsg', 'children', '_tree', 'sha',
+ 'virtual']
+
def __init__(self, sha, parents, tree=None):
self.parents = parents
self.firstLineMsg = None
--
1.1.6.gc78e-dirty
^ permalink raw reply related
* [PATCH 1/2] merge-recursive: Make use of provided bases
From: Fredrik Kuivinen @ 2006-02-02 11:43 UTC (permalink / raw)
To: git; +Cc: junkio
In-Reply-To: <20060202113848.GA8103@c165.ib.student.liu.se>
This makes some cases faster as we don't have to build the commit graph.
Signed-off-by: Fredrik Kuivinen <freku045@student.liu.se>
---
git-merge-recursive.py | 31 +++++++++++++++++++++----------
1 files changed, 21 insertions(+), 10 deletions(-)
c78eacd112489b264df5d176df287f7ff5696948
diff --git a/git-merge-recursive.py b/git-merge-recursive.py
index b17c8e5..ce8a31f 100755
--- a/git-merge-recursive.py
+++ b/git-merge-recursive.py
@@ -45,11 +45,10 @@ cacheOnly = False
# The entry point to the merge code
# ---------------------------------
-def merge(h1, h2, branch1Name, branch2Name, graph, callDepth=0):
+def merge(h1, h2, branch1Name, branch2Name, graph, callDepth=0, ancestor=None):
'''Merge the commits h1 and h2, return the resulting virtual
commit object and a flag indicating the cleaness of the merge.'''
assert(isinstance(h1, Commit) and isinstance(h2, Commit))
- assert(isinstance(graph, Graph))
global outputIndent
@@ -58,7 +57,11 @@ def merge(h1, h2, branch1Name, branch2Na
output(h2)
sys.stdout.flush()
- ca = getCommonAncestors(graph, h1, h2)
+ if ancestor:
+ ca = [ancestor]
+ else:
+ assert(isinstance(graph, Graph))
+ ca = getCommonAncestors(graph, h1, h2)
output('found', len(ca), 'common ancestor(s):')
for x in ca:
output(x)
@@ -86,7 +89,7 @@ def merge(h1, h2, branch1Name, branch2Na
[shaRes, clean] = mergeTrees(h1.tree(), h2.tree(), mergedCA.tree(),
branch1Name, branch2Name)
- if clean or cacheOnly:
+ if graph and (clean or cacheOnly):
res = Commit(None, [h1, h2], tree=shaRes)
graph.addNode(res)
else:
@@ -891,12 +894,11 @@ def usage():
# main entry point as merge strategy module
# The first parameters up to -- are merge bases, and the rest are heads.
-# This strategy module figures out merge bases itself, so we only
-# get heads.
if len(sys.argv) < 4:
usage()
+bases = []
for nextArg in xrange(1, len(sys.argv)):
if sys.argv[nextArg] == '--':
if len(sys.argv) != nextArg + 3:
@@ -907,6 +909,8 @@ for nextArg in xrange(1, len(sys.argv)):
except IndexError:
usage()
break
+ else:
+ bases.append(sys.argv[nextArg])
print 'Merging', h1, 'with', h2
@@ -914,10 +918,17 @@ try:
h1 = runProgram(['git-rev-parse', '--verify', h1 + '^0']).rstrip()
h2 = runProgram(['git-rev-parse', '--verify', h2 + '^0']).rstrip()
- graph = buildGraph([h1, h2])
-
- [dummy, clean] = merge(graph.shaMap[h1], graph.shaMap[h2],
- firstBranch, secondBranch, graph)
+ if len(bases) == 1:
+ base = runProgram(['git-rev-parse', '--verify',
+ bases[0] + '^0']).rstrip()
+ ancestor = Commit(base, None)
+ [dummy, clean] = merge(Commit(h1, None), Commit(h2, None),
+ firstBranch, secondBranch, None, 0,
+ ancestor)
+ else:
+ graph = buildGraph([h1, h2])
+ [dummy, clean] = merge(graph.shaMap[h1], graph.shaMap[h2],
+ firstBranch, secondBranch, graph)
print ''
except:
--
1.1.6.gc78e-dirty
^ permalink raw reply related
* [PATCH 0/2] Make merge recursive faster in some cases
From: Fredrik Kuivinen @ 2006-02-02 11:38 UTC (permalink / raw)
To: git; +Cc: junkio
The first patch teaches git-merge-recursive how to use the bases that
are supplied by the merge driver program in some cases. To be more
precise: if git-merge-recursive is supplied with a single base then
that one will be used, otherwise git-merge-recursive will compute the
bases on its own.
The second patch makes the commit graph construction more efficient.
- Fredrik
^ permalink raw reply
* Re: The merge from hell...
From: Junio C Hamano @ 2006-02-02 10:41 UTC (permalink / raw)
To: Linus Torvalds
Cc: Marco Costalba, Junio C Hamano, Git Mailing List, Paul Mackerras,
Marco Costalba
In-Reply-To: <Pine.LNX.4.64.0602020027400.21884@g5.osdl.org>
Linus Torvalds <torvalds@osdl.org> writes:
> On Thu, 2 Feb 2006, Aneesh Kumar wrote:
>>
>> Ok i tried using --cc. But then as per the man page if the
>> optimization makes the all the hunks disapper then commit log is not
>> show unless -m is used.
>
> Ahh. You're mis-using git-diff-tree.
>
> git-diff-tree will _never_ show the commit log if the diff ends up being
> empty.
True, I should fix the documentation.
It _might_ make sense for certain users like gitk and gitview if
we had a single tool that gives --pretty and its diff even if
the diff is empty. Having said that, the flag --cc -m is too
specific. If some uses want to see the commit log even for an
empty diff, that flag should not be something only --cc honors.
^ permalink raw reply
* [PATCH] combine-diff: add safety check to --cc.
From: Junio C Hamano @ 2006-02-02 9:34 UTC (permalink / raw)
To: Linus Torvalds
Cc: Git Mailing List, Paul Mackerras, Marco Costalba, Aneesh Kumar,
Len Brown
In-Reply-To: <7voe1qtbr5.fsf_-_@assigned-by-dhcp.cox.net>
The earlier change implemented "only two version" check but
without checking if the change rewrites from all the parents.
This implements a check to make sure that a change introduced
by the merge from all the parents is caught to be interesting.
Signed-off-by: Junio C Hamano <junkio@cox.net>
---
Junio C Hamano <junkio@cox.net> writes:
> Linus Torvalds <torvalds@osdl.org> writes:
>
> > On Wed, 1 Feb 2006, Linus Torvalds wrote:
> >
> > Actually, I take that back.
>
> I do not do that "result to match the final" check in this
> version yet. I'll need to revisit it before placing this in
> the master, but I am going to bed.
Well, I didn't ;-).
combine-diff.c | 20 ++++++++++++++++++--
1 files changed, 18 insertions(+), 2 deletions(-)
43fef6678c8e925307197fb705e499a023bba838
diff --git a/combine-diff.c b/combine-diff.c
index 45f1822..69e19ed 100644
--- a/combine-diff.c
+++ b/combine-diff.c
@@ -397,7 +397,23 @@ static int make_hunks(struct sline *slin
hunk_end = j;
/* [i..hunk_end) are interesting. Now is it really
- * interesting?
+ * interesting? We check if there are only two versions
+ * and the result matches one of them. That is, we look
+ * at:
+ * (+) line, which records lines added to which parents;
+ * this line appears in the result.
+ * (-) line, which records from what parents the line
+ * was removed; this line does not appear in the result.
+ * then check the set of parents the result has difference
+ * from, from all lines. If there are lines that has
+ * different set of parents that the result has differences
+ * from, that means we have more than two versions.
+ *
+ * Even when we have only two versions, if the result does
+ * not match any of the parents, the it should be considered
+ * interesting. In such a case, we would have all '+' line.
+ * After passing the above "two versions" test, that would
+ * appear as "the same set of parents" to be "all parents".
*/
same_diff = 0;
has_interesting = 0;
@@ -429,7 +445,7 @@ static int make_hunks(struct sline *slin
}
}
- if (!has_interesting) {
+ if (!has_interesting && same_diff != all_mask) {
/* This hunk is not that interesting after all */
for (j = hunk_begin; j < hunk_end; j++)
sline[j].flag &= ~mark;
--
1.1.6.g2672
^ permalink raw reply related
* Re: [Census] So who uses git?
From: Alex Riesen @ 2006-02-02 9:12 UTC (permalink / raw)
To: Linus Torvalds
Cc: Martin Langhoff, Ray Lehtiniemi, Radoslaw Szkodzinski,
Keith Packard, Junio C Hamano, cworth, Git Mailing List
In-Reply-To: <Pine.LNX.4.64.0602010815480.21884@g5.osdl.org>
On 2/1/06, Linus Torvalds <torvalds@osdl.org> wrote:
> > $ time git update-index --refresh
> >
> > real 0m21.500s
> > user 0m0.358s
> > sys 0m1.406s
> >
> > WinNT, NTFS, 13k files, hot cache.
>
> That's 25% less files than the Linux kernel, and I can do that operation
> in 0m0.062s (0.012s user, 0.048s system).
correction. It's 18k files, which is almost the same as 2.6.13-rc6. But these
files got *very* long names (the project poisoned by classical C++ education
and breaks windows' 255 chars limit on filename length from time to time).
Refresh index in 2.6.13 is actualy consistantly faster:
$ cd src/linux-2.6.13-rc6
$ time git update-index --refresh
real 0m1.344s
user 0m0.358s
sys 0m0.984s
> So WinNT/cygwin is about 2.5 _orders_of_maginitude_ slower here, or 340
> times slower.
>
> Now, I'm tempted to say that NT is a piece of sh*t, but the fact is, your
> CPU-times seem to indicate that most of it is IO (and the "real" cost is
> just 1.7 seconds, much of which is system time, which in turn itself is
> probably due to the IO costs too - so even that isn't comparable with
> the ).
>
> Which may mean that you simply don't have enough memory to cache the whole
> thing. Which may be NT sucking, of course ("we don't like to use more than
> 10% of memory for caches"), but it might also be a tunable (which is sucky
> in itself, of course), but finally, it might just be that you just don't
> have a ton of memory. I've got 2GB in my machines, although 1GB is plenty
> to cache the kernel.
I have 2Gb, the "System Cache" is around 1.5Gb, and this is PIV 3.2GHz.
There seem to be no tunables for any kind of system stuff
(savin' on support costs, do they?).
You'd be very hardpressed not to say that windows is a piece of sh*t.
The "benchmark: several times in a row:
$ time git update-index --refresh
real 0m1.766s
user 0m0.498s
sys 0m1.203s
$ time git update-index --refresh
real 0m1.766s
user 0m0.358s
sys 0m1.390s
$ time git update-index --refresh
real 0m1.781s
user 0m0.420s
sys 0m1.311s
$ time git update-index --refresh
real 0m1.875s
user 0m0.374s
sys 0m1.343s
$ time git update-index --refresh
real 0m1.766s
user 0m0.326s
sys 0m1.375s
It is always almost the same time. I don't think it's IO, looks more like
cache accesses. It is just that bad in this cygwin+win2k combination.
Besides, I don't trust "time <command>" on windows much: it returned
sys time 0 for git-update-index in a directory which was read before.
Yes, there was disk activity, I can hear it real good with that barrakuda.
^ permalink raw reply
* Re: The merge from hell...
From: Linus Torvalds @ 2006-02-02 8:44 UTC (permalink / raw)
To: Aneesh Kumar
Cc: Marco Costalba, Junio C Hamano, Git Mailing List, Paul Mackerras,
Marco Costalba
In-Reply-To: <cc723f590602020007s43f89d10i4529d118ade7c764@mail.gmail.com>
On Thu, 2 Feb 2006, Aneesh Kumar wrote:
>
> Ok i tried using --cc. But then as per the man page if the
> optimization makes the all the hunks disapper then commit log is not
> show unless -m is used.
Ahh. You're mis-using git-diff-tree.
git-diff-tree will _never_ show the commit log if the diff ends up being
empty. That can actually happen even for a regular commit, because we had
some early bugs that allowed them.
See commit 69d37960b578be0a69383bd71d06c1fcfb86e8b9, for example. Notice
how
git-diff-tree --pretty 69d37960
is entirely silent, even though
git log 69d37960
clearly shows that the commit exists. I screwed up a commit, and
effectively applied an empty patch (this was before git-apply would
notice, and consider it an error - something I fixed very soon
afterwards ;^).
> Is there a way to get the commit log printed.
Yes. What you should do is to do
git-rev-list --parents --pretty
which gives the revision _log_ in pretty format.
The difference between "git-rev-list --pretty" and "git-diff-tree
--pretty" is really exactly that "git-rev-list" lists every revision,
while git-diff-tree only lists revisions that _differ_ in the trees.
This, btw, is also really the main difference between doing a "git log"
and doing a "git whatchanged". A "git log" shows all revisions (and uses
"git-rev-list --pretty"). While "git whatchanged" shows what _changed_
(and uses "git-diff-tree --pretty").
For a revision tool like gitview, you want to use "git-rev-list --pretty".
[ SIDE NOTE! Actually, there's another format that you may find easier to
parse automatically: "git-rev-list --header". It uses the raw format,
and adds a NUL character between each rev. That makes things like the
date etc trivial to parse, and it's also slightly easier to see the end
of a commit message vs just a normal end-of-line.
So "gitk", for example, really parses the output of
git-rev-list --header --topo-order --parents
to generate the revision list. The "--topo-order" part guarantees that
all children will always be shown before any parents. ]
Hope that clarifies the issue.
Linus
^ permalink raw reply
* Re: The merge from hell...
From: Junio C Hamano @ 2006-02-02 8:27 UTC (permalink / raw)
To: Aneesh Kumar; +Cc: git
In-Reply-To: <cc723f590602020007s43f89d10i4529d118ade7c764@mail.gmail.com>
Aneesh Kumar <aneesh.kumar@gmail.com> writes:
> Ok i tried using --cc. But then as per the man page if the
> optimization makes the all the hunks disapper then commit log is not
> show unless -m is used. Is there a way to get the commit log printed.
Yes, there is a way. I need to fix a bug ;-).
This patch was done on top of the other two patches I sent
earlier tonight, but should apply on top of master even if you
have not applied the other two.
--
diff --git a/combine-diff.c b/combine-diff.c
index 44931b2..45f1822 100644
--- a/combine-diff.c
+++ b/combine-diff.c
@@ -675,6 +675,8 @@ int diff_tree_combined_merge(const unsig
show_empty_merge))
header = NULL;
}
+ if (header)
+ puts(header);
}
/* Clean things up */
^ permalink raw reply related
* [PATCH] combine-diff: update --cc "uninteresting hunks" logic.
From: Junio C Hamano @ 2006-02-02 8:18 UTC (permalink / raw)
To: Linus Torvalds
Cc: Git Mailing List, Paul Mackerras, Marco Costalba, Aneesh Kumar,
Len Brown
In-Reply-To: <Pine.LNX.4.64.0602020002110.21884@g5.osdl.org>
Earlier logic was discarding hunks that has difference from only
one parent or the same difference from all but one parent. This
changes it to check if the differences on all lines are from the
same sets of parents. This discards more uninteresting hunks
and seems to match expectations more naturally.
Signed-off-by: Junio C Hamano <junkio@cox.net>
---
Linus Torvalds <torvalds@osdl.org> writes:
> On Wed, 1 Feb 2006, Linus Torvalds wrote:
>>
>> I _think_ your version of the rule ("pluses and minuses in all the same
>> columns") ends up being exactly the same as my rule ("only two different
>> versions").
>
> Actually, I take that back.
I do not do that "result to match the final" check in this
version yet. I'll need to revisit it before placing this in
the master, but I am going to bed.
combine-diff.c | 102 ++++++++++++++++++--------------------------------------
1 files changed, 33 insertions(+), 69 deletions(-)
bcb331e2e87c2d7221751994b5ead4a79dd2a17b
diff --git a/combine-diff.c b/combine-diff.c
index 0cc18fe..44931b2 100644
--- a/combine-diff.c
+++ b/combine-diff.c
@@ -262,58 +262,6 @@ static int interesting(struct sline *sli
return ((sline->flag & all_mask) != all_mask || sline->lost_head);
}
-static unsigned long line_common_diff(struct sline *sline, unsigned long all_mask)
-{
- /*
- * Look at the line and see from which parents we have the
- * same difference.
- */
-
- /* Lower bits of sline->flag records if the parent had this
- * line, so XOR with all_mask gives us on-bits for parents we
- * have differences with.
- */
- unsigned long common_adds = (sline->flag ^ all_mask) & all_mask;
- unsigned long common_removes = all_mask;
-
- /* If all the parents have this line, that also counts as
- * having the same difference.
- */
- if (!common_adds)
- common_adds = all_mask;
-
- if (sline->lost_head) {
- /* Lost head list records the lines removed from
- * the parents, and parent_map records from which
- * parent the line was removed.
- */
- struct lline *ll;
- for (ll = sline->lost_head; ll; ll = ll->next) {
- common_removes &= ll->parent_map;
- }
- }
- return common_adds & common_removes;
-}
-
-static unsigned long line_all_diff(struct sline *sline, unsigned long all_mask)
-{
- /*
- * Look at the line and see from which parents we have some difference.
- */
- unsigned long different = (sline->flag ^ all_mask) & all_mask;
- if (sline->lost_head) {
- /* Lost head list records the lines removed from
- * the parents, and parent_map records from which
- * parent the line was removed.
- */
- struct lline *ll;
- for (ll = sline->lost_head; ll; ll = ll->next) {
- different |= ll->parent_map;
- }
- }
- return different;
-}
-
static unsigned long adjust_hunk_tail(struct sline *sline,
unsigned long all_mask,
unsigned long hunk_begin,
@@ -417,8 +365,7 @@ static int make_hunks(struct sline *slin
i = 0;
while (i < cnt) {
unsigned long j, hunk_begin, hunk_end;
- int same, diff;
- unsigned long same_diff, all_diff;
+ unsigned long same_diff;
while (i < cnt && !(sline[i].flag & mark))
i++;
if (cnt <= i)
@@ -449,23 +396,40 @@ static int make_hunks(struct sline *slin
}
hunk_end = j;
- /* [i..hunk_end) are interesting. Now does it have
- * the same change with all but one parent?
+ /* [i..hunk_end) are interesting. Now is it really
+ * interesting?
*/
- same_diff = all_mask;
- all_diff = 0;
- for (j = i; j < hunk_end; j++) {
- same_diff &= line_common_diff(sline + j, all_mask);
- all_diff |= line_all_diff(sline + j, all_mask);
- }
- diff = same = 0;
- for (j = 0; j < num_parent; j++) {
- if (same_diff & (1UL<<j))
- same++;
- if (all_diff & (1UL<<j))
- diff++;
+ same_diff = 0;
+ has_interesting = 0;
+ for (j = i; j < hunk_end && !has_interesting; j++) {
+ unsigned long this_diff = ~sline[j].flag & all_mask;
+ struct lline *ll = sline[j].lost_head;
+ if (this_diff) {
+ /* This has some changes. Is it the
+ * same as others?
+ */
+ if (!same_diff)
+ same_diff = this_diff;
+ else if (same_diff != this_diff) {
+ has_interesting = 1;
+ break;
+ }
+ }
+ while (ll && !has_interesting) {
+ /* Lost this line from these parents;
+ * who are they? Are they the same?
+ */
+ this_diff = ll->parent_map;
+ if (!same_diff)
+ same_diff = this_diff;
+ else if (same_diff != this_diff) {
+ has_interesting = 1;
+ }
+ ll = ll->next;
+ }
}
- if ((num_parent - 1 <= same) || (diff == 1)) {
+
+ if (!has_interesting) {
/* This hunk is not that interesting after all */
for (j = hunk_begin; j < hunk_end; j++)
sline[j].flag &= ~mark;
--
1.1.6.g2672
^ permalink raw reply related
* Re: The merge from hell...
From: Linus Torvalds @ 2006-02-02 8:08 UTC (permalink / raw)
To: Junio C Hamano
Cc: Git Mailing List, Paul Mackerras, Marco Costalba, Aneesh Kumar,
Len Brown
In-Reply-To: <Pine.LNX.4.64.0602012353130.21884@g5.osdl.org>
On Wed, 1 Feb 2006, Linus Torvalds wrote:
>
> I _think_ your version of the rule ("pluses and minuses in all the same
> columns") ends up being exactly the same as my rule ("only two different
> versions").
Actually, I take that back.
My version of the rule was not just that there were only two versions: the
merge _result_ had to match one of the versions in one of the branches
too.
That's important. It's important because you _can_ actually have a merge
where both branches have the exact same content, but some evil merger
ended up editing just the merge result.
So there are literally just two versions, but one of the versions _only_
exists in the merge result. Such a thing must always be considered a
conflict, since basically the merge result is obviously "interesting".
That requirement can still be rewritten as a slight variation of your
version, I think: "the pluses and minuses are all in the same columns, and
the final column has to match one other column"
Maybe I'm not thinking clearly. Somebody else should double-check my
thinking. My brain is tired, and I'm going to bed.
Linus
^ permalink raw reply
* Re: The merge from hell...
From: Aneesh Kumar @ 2006-02-02 8:07 UTC (permalink / raw)
To: Linus Torvalds
Cc: Marco Costalba, Junio C Hamano, Git Mailing List, Paul Mackerras,
Marco Costalba
In-Reply-To: <Pine.LNX.4.64.0602012356131.21884@g5.osdl.org>
On 2/2/06, Linus Torvalds <torvalds@osdl.org> wrote:
>
>
> On Thu, 2 Feb 2006, Marco Costalba wrote:
> >
> > Currently the public git repo version of qgit uses "git-diff-tree -c"
> > for merges, It's not a problem to change qgit to use --cc option
> > instead. But I would like to use just one kind of option to filter
> > merges files.
>
> I think using "-c" rather than "--cc" is fine, and if it makes parsing
> easier..
>
> The "--cc" option should show less "noise", an dI'm actually arguing that
> it should show even less than it does now (for when the branches agreed
> with each other, and there was no actual conflict, which is what I think
> is more useful), but I don't think "-c" is _wrong_ either.
>
> Using "-c" is a strange kind of "show all differences in a file that had
> file-level merges" while at least to me "--cc" is meant to be more of a
> "show all actual file-level CONFLICTS where the merge actually did
> something different"
Ok i tried using --cc. But then as per the man page if the
optimization makes the all the hunks disapper then commit log is not
show unless -m is used. Is there a way to get the commit log printed.
BTW using -m didn't show any difference even though man page said
about some difference
-aneesh
^ permalink raw reply
* Re: The merge from hell...
From: Linus Torvalds @ 2006-02-02 8:02 UTC (permalink / raw)
To: Marco Costalba
Cc: Junio C Hamano, Git Mailing List, Paul Mackerras, Marco Costalba,
Aneesh Kumar
In-Reply-To: <e5bfff550602012325s7d0a799ct5bfabbce2c579449@mail.gmail.com>
On Thu, 2 Feb 2006, Marco Costalba wrote:
>
> Currently the public git repo version of qgit uses "git-diff-tree -c"
> for merges, It's not a problem to change qgit to use --cc option
> instead. But I would like to use just one kind of option to filter
> merges files.
I think using "-c" rather than "--cc" is fine, and if it makes parsing
easier..
The "--cc" option should show less "noise", an dI'm actually arguing that
it should show even less than it does now (for when the branches agreed
with each other, and there was no actual conflict, which is what I think
is more useful), but I don't think "-c" is _wrong_ either.
Using "-c" is a strange kind of "show all differences in a file that had
file-level merges" while at least to me "--cc" is meant to be more of a
"show all actual file-level CONFLICTS where the merge actually did
something different"
Linus
^ permalink raw reply
* Re: The merge from hell...
From: Linus Torvalds @ 2006-02-02 7:55 UTC (permalink / raw)
To: Junio C Hamano
Cc: Git Mailing List, Paul Mackerras, Marco Costalba, Aneesh Kumar,
Len Brown
In-Reply-To: <Pine.LNX.4.64.0602012334360.21884@g5.osdl.org>
On Wed, 1 Feb 2006, Linus Torvalds wrote:
>
> Not under my suggested "two version" rule.
That "Not" is just me being stupid. I'm agreeing with you, not
disagreeing, I just misread your mail.
I _think_ your version of the rule ("pluses and minuses in all the same
columns") ends up being exactly the same as my rule ("only two different
versions").
Linus
^ permalink raw reply
* Re: The merge from hell...
From: Linus Torvalds @ 2006-02-02 7:51 UTC (permalink / raw)
To: Junio C Hamano
Cc: Git Mailing List, Paul Mackerras, Marco Costalba, Aneesh Kumar,
Len Brown
In-Reply-To: <7v8xsuuto5.fsf@assigned-by-dhcp.cox.net>
On Wed, 1 Feb 2006, Junio C Hamano wrote:
>
> > It's commit 9fdb62af92c741addbea15545f214a6e89460865, and passing it to
> > git-diff-tree with the "--cc" option seems to do the largely the right
> > thing (although arguably, since one of the parents always matches the end
> > result in all the files, it shouldn't have shown anything at all, so I
> > think it could do with some tweaking).
>
> Hmph. Do you mean a hunk like this?
>
> diff --cc kernel/sys.c
> @@@@@@@@@@@@@ +33,7 @@@@@@@@@@@@@
>
> #include <linux/compat.h>
> #include <linux/syscalls.h>
> + +++ #include <linux/kprobes.h>
>
> #include <asm/uaccess.h>
> #include <asm/io.h>
Yes.
> Currently I cull hunks that have changes from only one parent,
> or when the changes are the same from all but one parent. This
> hunk does not match either criteria.
Correct. I think "git-diff-tree --cc" actually works as you advertized,
but that we should change the rules. More akin to
- if there are only two versions of a hunk, and one of those versions
ended up in the result, the hunk is considered successfully merged
and should be ignored under "--cc"
Under that rule, the kernel/sys.c hunk you specify is indeed
uninteresting, because there are only two versions: the version that
didn't have the addition, and the version that did.
> or "plus and minus in the same set of columns" hunks. If I did
> so, this would become uninteresting:
>
> diff --cc arch/ia64/pci/pci.c
> @@@@@@@@@@@@@ +709,7 @@@@@@@@@@@@@
> */
> int ia64_pci_legacy_write(struct pci_dev *bus, u16...
> {
> ------ - int ret = 0;
> ++++++ + int ret = size;
>
> switch (size) {
> case 1:
Yes. Again, only two versions. Either it was "ret = 0" or it was "ret =
size". No other version existed in any branch or in the end result, so
there really were only two versions, and one of them ended up being the
end result.
> But this is still interesting:
>
> @@@@@@@@@@@@@ +308,35 @@@@@@@@@@@@@
> goto end;
> }
> }
> -- cx->usage++;
> --
>
> +++ #ifdef CONFIG_HOTPLUG_CPU
> +++ /*
Not under my suggested "two version" rule.
The above has _three_ versions: the one with no changes, the one with
"cx->usage++" removed and the one with "#ifdef CONFIG_HOTPLUG_CPU" added.
So under the two-version rule, the last one would still be interesting.
> > git-diff-tree takes almost three seconds to get its result, though.
>
> One trivial thing I should be able to do to speed things up is
> to reuse previous diff with other parents.
Yes. In this example, it would apparently cut down the work by a third for
that file, although it migt make it harder to calculate the proper "-/+"
patterns..
> I did not expect anybody to be _that_ sick (eh, pardon my
> language) to do a 12-way octpus, so I did not consider this
> optimization possibility, but I should be doing only 4 diffs to
> format -c for this commit. Currently I do 12.
I agree, I wouldn't have considered that 12-way merge sane either, but
hey, it worked, and our octopus merge rules are simple enough that I guess
there's not really any downside to it.
And I was actually happy to have "git-diff-tree --cc" to look at it, and
that "gitk" eventually gave results that looked decent. I didn't go
through it all that closely, but the ones I _looked_ at looked fine, and
it was mighty pleasant to have the tools to look more closely.
So thanks for "--cc" yet again.
> > So think of it as a correctness/scalability test.
>
> Heh. I like this one as a practice. Thanks!
Thank Len. He may have done it as a way to avoid having extra merges,
since I complained about those last time ;)
Linus
^ permalink raw reply
* [PATCH] combine-diff: reuse diff from the same blob.
From: Junio C Hamano @ 2006-02-02 7:40 UTC (permalink / raw)
To: Git Mailing List
Cc: Linus Torvalds, Paul Mackerras, Marco Costalba, Aneesh Kumar
In-Reply-To: <7v8xsuuto5.fsf@assigned-by-dhcp.cox.net>
When dealing with an insanely large Octopus, it is possible to
optimize by noticing that more than one parents have the same
blob and avoid running diff between a parent and the merge
result by reusing an earlier result.
Signed-off-by: Junio C Hamano <junkio@cox.net>
---
Junio C Hamano <junkio@cox.net> writes:
> One trivial thing I should be able to do to speed things up is
> to reuse previous diff with other parents. For example, that
> commit does this to kernel/sys.c from its 12 parents.
>
> :100644 100644 d09cac2... 0929c69... M kernel/sys.c
> :100644 100644 eecf845... 0929c69... M kernel/sys.c
> :100644 100644 c3b1874... 0929c69... M kernel/sys.c
> :100644 100644 bce933e... 0929c69... M kernel/sys.c
> :100644 100644 eecf845... 0929c69... M kernel/sys.c
> :100644 100644 bce933e... 0929c69... M kernel/sys.c
> :100644 100644 bce933e... 0929c69... M kernel/sys.c
> :100644 100644 bce933e... 0929c69... M kernel/sys.c
> :100644 100644 eecf845... 0929c69... M kernel/sys.c
> :100644 100644 eecf845... 0929c69... M kernel/sys.c
> :100644 100644 eecf845... 0929c69... M kernel/sys.c
> :100644 100644 eecf845... 0929c69... M kernel/sys.c
>
> Running "sort -u" on these would leave only 4 lines.
>
> I did not expect anybody to be _that_ sick (eh, pardon my
> language) to do a 12-way octpus, so I did not consider this
> optimization possibility, but I should be doing only 4 diffs to
> format -c for this commit. Currently I do 12.
On my Duron 750 w/ 770MB RAM here is the results.
Without this optimization:
real 0m11.117s user 0m9.230s sys 0m1.860s
With this optimization:
real 0m7.339s user 0m6.730s sys 0m0.610s
combine-diff.c | 39 +++++++++++++++++++++++++++++++++++++--
1 files changed, 37 insertions(+), 2 deletions(-)
7bf761b73cfb74917454e179d95f0dab1cab8f0b
diff --git a/combine-diff.c b/combine-diff.c
index 243f967..0cc18fe 100644
--- a/combine-diff.c
+++ b/combine-diff.c
@@ -523,6 +523,30 @@ static void dump_sline(struct sline *sli
}
}
+static void reuse_combine_diff(struct sline *sline, unsigned long cnt,
+ int i, int j)
+{
+ /* We have already examined parent j and we know parent i
+ * and parent j are the same, so reuse the combined result
+ * of parent j for parent i.
+ */
+ unsigned long lno, imask, jmask;
+ imask = (1UL<<i);
+ jmask = (1UL<<j);
+
+ for (lno = 0; lno < cnt; lno++) {
+ struct lline *ll = sline->lost_head;
+ while (ll) {
+ if (ll->parent_map & jmask)
+ ll->parent_map |= imask;
+ ll = ll->next;
+ }
+ if (!(sline->flag & jmask))
+ sline->flag &= ~imask;
+ sline++;
+ }
+}
+
int show_combined_diff(struct combine_diff_path *elem, int num_parent,
int dense, const char *header, int show_empty)
{
@@ -596,8 +620,19 @@ int show_combined_diff(struct combine_di
sline[cnt-1].flag = (1UL<<num_parent) - 1;
}
- for (i = 0; i < num_parent; i++)
- combine_diff(elem->parent_sha1[i], ourtmp, sline, cnt, i);
+ for (i = 0; i < num_parent; i++) {
+ int j;
+ for (j = 0; j < i; j++) {
+ if (!memcmp(elem->parent_sha1[i],
+ elem->parent_sha1[j], 20)) {
+ reuse_combine_diff(sline, cnt, i, j);
+ break;
+ }
+ }
+ if (i <= j)
+ combine_diff(elem->parent_sha1[i], ourtmp, sline,
+ cnt, i);
+ }
show_hunks = make_hunks(sline, cnt, num_parent, dense);
--
1.1.6.g2672
^ permalink raw reply related
* Re: The merge from hell...
From: Marco Costalba @ 2006-02-02 7:25 UTC (permalink / raw)
To: Linus Torvalds
Cc: Junio C Hamano, Git Mailing List, Paul Mackerras, Marco Costalba,
Aneesh Kumar
In-Reply-To: <Pine.LNX.4.64.0602012212200.21884@g5.osdl.org>
On 2/2/06, Linus Torvalds <torvalds@osdl.org> wrote:
>
> Btw, I think you're better off parsing the "git-diff-tree --cc" output
> than doing it yourself like gitk does, now that core git has support for
> things like that.
>
Currently the public git repo version of qgit uses "git-diff-tree -c"
for merges, It's not a problem to change qgit to use --cc option
instead. But I would like to use just one kind of option to filter
merges files.
So I would like to hear some feedback on using --cc vs -c.
Marco
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox