Git development
 help / color / mirror / Atom feed
* [PATCH 7/7] gitk: Explicitly position popup windows.
From: Alexander Gavrilov @ 2008-10-08  7:05 UTC (permalink / raw)
  To: git; +Cc: Paul Mackerras
In-Reply-To: <1223449540-20457-7-git-send-email-angavrilov@gmail.com>

For some reason, on Windows all transient windows are placed
in the upper left corner of the screen. Thus, it is necessary
to explicitly position the windows using the tk::PlaceWindow
function.

Reference list and the Edit View dialog are positioned under
the mouse cursor, thus allowing the user to create them in a
convenient place using keyboard shortcuts, and providing a
sane position when opened through the menu.

Other popups are centered on the main window.

Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com>
---
 gitk |   19 +++++++++++++++++--
 1 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/gitk b/gitk
index c7dd487..9e580a6 100755
--- a/gitk
+++ b/gitk
@@ -1703,7 +1703,7 @@ proc removehead {id name} {
     unset headids($name)
 }
 
-proc show_error {w top msg} {
+proc show_error {w top msg {owner {}}} {
     message $w.m -text $msg -justify center -aspect 400
     pack $w.m -side top -fill x -padx 20 -pady 20
     button $w.ok -text [mc OK] -command "destroy $top"
@@ -1712,6 +1712,9 @@ proc show_error {w top msg} {
     bind $top <Key-Return> "destroy $top"
     bind $top <Key-space>  "destroy $top"
     bind $top <Key-Escape> "destroy $top"
+    if {$owner ne {}} {
+	tk::PlaceWindow $top widget $owner
+    }
     tkwait window $top
 }
 
@@ -1719,7 +1722,7 @@ proc error_popup {msg {owner .}} {
     set w .error
     toplevel $w
     wm transient $w $owner
-    show_error $w $w $msg
+    show_error $w $w $msg $owner
 }
 
 proc confirm_popup {msg {owner .}} {
@@ -1738,6 +1741,7 @@ proc confirm_popup {msg {owner .}} {
     bind $w <Key-Return> "set confirm_ok 1; destroy $w"
     bind $w <Key-space>  "set confirm_ok 1; destroy $w"
     bind $w <Key-Escape> "destroy $w"
+    tk::PlaceWindow $w widget $owner
     tkwait window $w
     return $confirm_ok
 }
@@ -2493,6 +2497,7 @@ Use and redistribute under the terms of the GNU General Public License"] \
     bind $w <Visibility> "focus $w.ok"
     bind $w <Key-Escape> "destroy $w"
     bind $w <Key-Return> "destroy $w"
+    tk::PlaceWindow $w widget .
 }
 
 proc keys {} {
@@ -2554,6 +2559,7 @@ proc keys {} {
     bind $w <Visibility> "focus $w.ok"
     bind $w <Key-Escape> "destroy $w"
     bind $w <Key-Return> "destroy $w"
+    tk::PlaceWindow $w widget .
 }
 
 # Procedures for manipulating the file list window at the
@@ -3497,6 +3503,7 @@ proc vieweditor {top n title} {
     grid columnconfigure $top.buts 1 -weight 1 -uniform a
     grid columnconfigure $top.buts 2 -weight 1 -uniform a
     pack $top.buts -in $top -side top -fill x
+    tk::PlaceWindow $top pointer .
     focus $top.t
 }
 
@@ -7684,6 +7691,7 @@ proc mkpatch {} {
     grid columnconfigure $top.buts 1 -weight 1 -uniform a
     grid $top.buts - -pady 10 -sticky ew
     focus $top.fname
+    tk::PlaceWindow $top widget .
 }
 
 proc mkpatchrev {} {
@@ -7758,6 +7766,7 @@ proc mktag {} {
     grid columnconfigure $top.buts 1 -weight 1 -uniform a
     grid $top.buts - -pady 10 -sticky ew
     focus $top.tag
+    tk::PlaceWindow $top widget .
 }
 
 proc domktag {} {
@@ -7865,6 +7874,7 @@ proc writecommit {} {
     grid columnconfigure $top.buts 1 -weight 1 -uniform a
     grid $top.buts - -pady 10 -sticky ew
     focus $top.fname
+    tk::PlaceWindow $top widget .
 }
 
 proc wrcomgo {} {
@@ -7914,6 +7924,7 @@ proc mkbranch {} {
     grid columnconfigure $top.buts 1 -weight 1 -uniform a
     grid $top.buts - -pady 10 -sticky ew
     focus $top.name
+    tk::PlaceWindow $top widget .
 }
 
 proc mkbrgo {top} {
@@ -8093,6 +8104,7 @@ proc resethead {} {
     bind $w <Key-Escape> [list destroy $w]
     pack $w.cancel -side right -fill x -padx 20 -pady 20
     bind $w <Visibility> "grab $w; focus $w"
+    tk::PlaceWindow $w widget .
     tkwait window $w
     if {!$confirm_ok} return
     if {[catch {set fd [open \
@@ -8278,6 +8290,7 @@ proc showrefs {} {
     bind $top.list <ButtonRelease-1> {sel_reflist %W %x %y; break}
     set reflist {}
     refill_reflist
+    tk::PlaceWindow $top pointer .
 }
 
 proc sel_reflist {w x y} {
@@ -9630,6 +9643,7 @@ proc choosefont {font which} {
 	grid columnconfigure $top.buts 1 -weight 1 -uniform a
 	pack $top.buts -side bottom -fill x
 	trace add variable fontparam write chg_fontparam
+	tk::PlaceWindow $top widget $prefstop
     } else {
 	raise $top
 	$top.c itemconf text -text $which
@@ -9801,6 +9815,7 @@ proc doprefs {} {
     grid columnconfigure $top.buts 1 -weight 1 -uniform a
     grid $top.buts - - -pady 10 -sticky ew
     bind $top <Visibility> "focus $top.buts.ok"
+    tk::PlaceWindow $top widget .
 }
 
 proc choose_extdiff {} {
-- 
1.6.0.20.g6148bc

^ permalink raw reply related

* [PATCH 6/7] gitk: Implement a user-friendly Edit View dialog.
From: Alexander Gavrilov @ 2008-10-08  7:05 UTC (permalink / raw)
  To: git; +Cc: Paul Mackerras
In-Reply-To: <1223449540-20457-6-git-send-email-angavrilov@gmail.com>

Originally gitk required the user to specify all limiting
options manually in the same field with the list of commits.
It is extremely unfriendly for new users, who may not know
which options can be used, or, indeed, that it is possible
to specify them at all.

This patch modifies the dialog to present the most useful
options as individual fields. Note that options that may
be useful to an extent, but produce broken view, are
deliberately not included.

It is still possible to specify options in the commit list
field, but when the dialog is reopened, they will be extracted
into their own separate fields.

Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com>
---
 gitk |  207 ++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
 1 files changed, 163 insertions(+), 44 deletions(-)

diff --git a/gitk b/gitk
index e84e109..c7dd487 100755
--- a/gitk
+++ b/gitk
@@ -3289,8 +3289,8 @@ proc shellsplit {str} {
 # Code to implement multiple views
 
 proc newview {ishighlight} {
-    global nextviewnum newviewname newviewperm newishighlight
-    global newviewargs revtreeargs viewargscmd newviewargscmd curview
+    global nextviewnum newviewname newishighlight
+    global revtreeargs viewargscmd newviewopts curview
 
     set newishighlight $ishighlight
     set top .gitkview
@@ -3299,9 +3299,9 @@ proc newview {ishighlight} {
 	return
     }
     set newviewname($nextviewnum) "[mc "View"] $nextviewnum"
-    set newviewperm($nextviewnum) 0
-    set newviewargs($nextviewnum) [shellarglist $revtreeargs]
-    set newviewargscmd($nextviewnum) $viewargscmd($curview)
+    set newviewopts($nextviewnum,perm) 0
+    set newviewopts($nextviewnum,cmd)  $viewargscmd($curview)
+    decode_view_opts $nextviewnum $revtreeargs
     vieweditor $top $nextviewnum [mc "Gitk view definition"]
 }
 
@@ -3315,53 +3315,167 @@ proc edit_or_newview {} {
     }
 }
 
+set known_view_options {
+    {perm    b    . {}               {mc "Remember this view"}}
+    {args    t50= + {}               {mc "Commits to include (arguments to git log):"}}
+    {all     b    * "--all"          {mc "Use all refs"}}
+    {dorder  b    . {"--date-order" "-d"}      {mc "Strictly sort by date"}}
+    {lright  b    . "--left-right"   {mc "Mark branch sides"}}
+    {since   t15  + {"--since=*" "--after=*"}  {mc "Since date:"}}
+    {until   t15  . {"--until=*" "--before=*"} {mc "Until date:"}}
+    {limit   t10  + "--max-count=*"  {mc "Max count:"}}
+    {skip    t10  . "--skip=*"       {mc "Skip:"}}
+    {first   b    . "--first-parent" {mc "Limit to first parent"}}
+    {cmd     t50= + {}               {mc "Command to generate more commits to include:"}}
+    }
+
+proc encode_view_opts {n} {
+    global known_view_options newviewopts
+
+    set rargs [list]
+    foreach opt $known_view_options {
+	set patterns [lindex $opt 3]
+	if {$patterns eq {}} continue
+	set pattern [lindex $patterns 0]
+
+	set val $newviewopts($n,[lindex $opt 0])
+	
+	if {[lindex $opt 1] eq "b"} {
+	    if {$val} {
+		lappend rargs $pattern
+	    }
+	} else {
+	    set val [string trim $val]
+	    if {$val ne {}} {
+		set pfix [string range $pattern 0 end-1]
+		lappend rargs $pfix$val
+	    }
+	}
+    }
+    return [concat $rargs [shellsplit $newviewopts($n,args)]]
+}
+
+proc decode_view_opts {n view_args} {
+    global known_view_options newviewopts
+
+    foreach opt $known_view_options {
+	if {[lindex $opt 1] eq "b"} {
+	    set val 0
+	} else {
+	    set val {}
+	}
+	set newviewopts($n,[lindex $opt 0]) $val
+    }
+    set oargs [list]
+    foreach arg $view_args {
+	if {[regexp -- {^-([0-9]+)$} $arg arg cnt]
+	    && ![info exists found(limit)]} {
+	    set newviewopts($n,limit) $cnt
+	    set found(limit) 1
+	    continue
+	}
+	catch { unset val }
+	foreach opt $known_view_options {
+	    set id [lindex $opt 0]
+	    if {[info exists found($id)]} continue
+	    foreach pattern [lindex $opt 3] {
+		if {![string match $pattern $arg]} continue
+		if {[lindex $opt 1] ne "b"} {
+		    set size [string length $pattern]
+		    set val [string range $arg [expr {$size-1}] end]
+		} else {
+		    set val 1
+		}
+		set newviewopts($n,$id) $val
+		set found($id) 1
+		break
+	    }
+	    if {[info exists val]} break
+	}
+	if {[info exists val]} continue
+	lappend oargs $arg
+    }
+    set newviewopts($n,args) [shellarglist $oargs]
+}
+
 proc editview {} {
     global curview
-    global viewname viewperm newviewname newviewperm
-    global viewargs newviewargs viewargscmd newviewargscmd
+    global viewname viewperm newviewname newviewopts
+    global viewargs viewargscmd
 
     set top .gitkvedit-$curview
     if {[winfo exists $top]} {
 	raise $top
 	return
     }
-    set newviewname($curview) $viewname($curview)
-    set newviewperm($curview) $viewperm($curview)
-    set newviewargs($curview) [shellarglist $viewargs($curview)]
-    set newviewargscmd($curview) $viewargscmd($curview)
+    set newviewname($curview)      $viewname($curview)
+    set newviewopts($curview,perm) $viewperm($curview)
+    set newviewopts($curview,cmd)  $viewargscmd($curview)
+    decode_view_opts $curview $viewargs($curview)
     vieweditor $top $curview "Gitk: edit view $viewname($curview)"
 }
 
 proc vieweditor {top n title} {
-    global newviewname newviewperm viewfiles bgcolor
+    global newviewname newviewopts viewfiles bgcolor
+    global known_view_options
 
     toplevel $top
     wm title $top $title
     wm transient $top .
+
+    # View name
+    frame $top.nfr
     label $top.nl -text [mc "Name"]
     entry $top.name -width 20 -textvariable newviewname($n)
-    grid $top.nl $top.name -sticky w -pady 5
-    checkbutton $top.perm -text [mc "Remember this view"] \
-	-variable newviewperm($n)
-    grid $top.perm - -pady 5 -sticky w
-    message $top.al -aspect 1000 \
-	-text [mc "Commits to include (arguments to git log):"]
-    grid $top.al - -sticky w -pady 5
-    entry $top.args -width 50 -textvariable newviewargs($n) \
-	-background $bgcolor
-    grid $top.args - -sticky ew -padx 5
-
-    message $top.ac -aspect 1000 \
-	-text [mc "Command to generate more commits to include:"]
-    grid $top.ac - -sticky w -pady 5
-    entry $top.argscmd -width 50 -textvariable newviewargscmd($n) \
-	-background white
-    grid $top.argscmd - -sticky ew -padx 5
-
-    message $top.l -aspect 1000 \
+    pack $top.nfr -in $top -fill x -pady 5 -padx 3
+    pack $top.nl -in $top.nfr -side left -padx {0 30}
+    pack $top.name -in $top.nfr -side left
+
+    # View options
+    set cframe $top.nfr
+    set cexpand 0
+    set cnt 0
+    foreach opt $known_view_options {
+	set id [lindex $opt 0]
+	set type [lindex $opt 1]
+	set flags [lindex $opt 2]
+	set title [eval [lindex $opt 4]]
+	set lxpad 0
+
+	if {$flags eq "+" || $flags eq "*"} {
+	    set cframe $top.fr$cnt
+	    incr cnt
+	    frame $cframe
+	    pack $cframe -in $top -fill x -pady 3 -padx 3
+	    set cexpand [expr {$flags eq "*"}]
+	} else {
+	    set lxpad 5
+	}
+
+	if {$type eq "b"} {
+	    checkbutton $cframe.c_$id -text $title -variable newviewopts($n,$id)
+	    pack $cframe.c_$id -in $cframe -side left \
+		-padx [list $lxpad 0] -expand $cexpand -anchor w
+	} elseif {[regexp {^t(\d+)$} $type type sz]} {
+	    message $cframe.l_$id -aspect 1500 -text $title
+	    entry $cframe.e_$id -width $sz -background $bgcolor \
+		-textvariable newviewopts($n,$id)
+	    pack $cframe.l_$id -in $cframe -side left -padx [list $lxpad 0]
+	    pack $cframe.e_$id -in $cframe -side left -expand 1 -fill x
+	} elseif {[regexp {^t(\d+)=$} $type type sz]} {
+	    message $cframe.l_$id -aspect 1500 -text $title
+	    entry $cframe.e_$id -width $sz -background $bgcolor \
+		-textvariable newviewopts($n,$id)
+	    pack $cframe.l_$id -in $cframe -side top -pady [list 3 0] -anchor w
+	    pack $cframe.e_$id -in $cframe -side top -fill x
+	}
+    }
+
+    # Path list
+    message $top.l -aspect 1500 \
 	-text [mc "Enter files and directories to include, one per line:"]
-    grid $top.l - -sticky w
-    text $top.t -width 40 -height 10 -background $bgcolor -font uifont
+    pack $top.l -in $top -side top -pady [list 7 0] -anchor w -padx 3
+    text $top.t -width 40 -height 5 -background $bgcolor -font uifont
     if {[info exists viewfiles($n)]} {
 	foreach f $viewfiles($n) {
 	    $top.t insert end $f
@@ -3370,15 +3484,19 @@ proc vieweditor {top n title} {
 	$top.t delete {end - 1c} end
 	$top.t mark set insert 0.0
     }
-    grid $top.t - -sticky ew -padx 5
+    pack $top.t -in $top -side top -pady [list 0 5] -fill both -expand 1 -padx 3
     frame $top.buts
     button $top.buts.ok -text [mc "OK"] -command [list newviewok $top $n]
+    button $top.buts.apply -text [mc "Apply (F5)"] -command [list newviewok $top $n 1]
     button $top.buts.can -text [mc "Cancel"] -command [list destroy $top]
+    bind $top <Control-Return> [list newviewok $top $n]
+    bind $top <F5> [list newviewok $top $n 1]
     bind $top <Escape> [list destroy $top]
-    grid $top.buts.ok $top.buts.can
+    grid $top.buts.ok $top.buts.apply $top.buts.can
     grid columnconfigure $top.buts 0 -weight 1 -uniform a
     grid columnconfigure $top.buts 1 -weight 1 -uniform a
-    grid $top.buts - -pady 10 -sticky ew
+    grid columnconfigure $top.buts 2 -weight 1 -uniform a
+    pack $top.buts -in $top -side top -fill x
     focus $top.t
 }
 
@@ -3399,13 +3517,13 @@ proc allviewmenus {n op args} {
     # doviewmenu $viewhlmenu 1 [list addvhighlight $n] $op $args
 }
 
-proc newviewok {top n} {
+proc newviewok {top n {apply 0}} {
     global nextviewnum newviewperm newviewname newishighlight
     global viewname viewfiles viewperm selectedview curview
-    global viewargs newviewargs viewargscmd newviewargscmd viewhlmenu
+    global viewargs viewargscmd newviewopts viewhlmenu
 
     if {[catch {
-	set newargs [shellsplit $newviewargs($n)]
+	set newargs [encode_view_opts $n]
     } err]} {
 	error_popup "[mc "Error in commit selection arguments:"] $err" $top
 	return
@@ -3421,10 +3539,10 @@ proc newviewok {top n} {
 	# creating a new view
 	incr nextviewnum
 	set viewname($n) $newviewname($n)
-	set viewperm($n) $newviewperm($n)
+	set viewperm($n) $newviewopts($n,perm)
 	set viewfiles($n) $files
 	set viewargs($n) $newargs
-	set viewargscmd($n) $newviewargscmd($n)
+	set viewargscmd($n) $newviewopts($n,cmd)
 	addviewmenu $n
 	if {!$newishighlight} {
 	    run showview $n
@@ -3433,7 +3551,7 @@ proc newviewok {top n} {
 	}
     } else {
 	# editing an existing view
-	set viewperm($n) $newviewperm($n)
+	set viewperm($n) $newviewopts($n,perm)
 	if {$newviewname($n) ne $viewname($n)} {
 	    set viewname($n) $newviewname($n)
 	    doviewmenu .bar.view 5 [list showview $n] \
@@ -3442,15 +3560,16 @@ proc newviewok {top n} {
 		# entryconf [list -label $viewname($n) -value $viewname($n)]
 	}
 	if {$files ne $viewfiles($n) || $newargs ne $viewargs($n) || \
-		$newviewargscmd($n) ne $viewargscmd($n)} {
+		$newviewopts($n,cmd) ne $viewargscmd($n)} {
 	    set viewfiles($n) $files
 	    set viewargs($n) $newargs
-	    set viewargscmd($n) $newviewargscmd($n)
+	    set viewargscmd($n) $newviewopts($n,cmd)
 	    if {$curview == $n} {
 		run reloadcommits
 	    }
 	}
     }
+    if {$apply} return
     catch {destroy $top}
 }
 
-- 
1.6.0.20.g6148bc

^ permalink raw reply related

* [PATCH 4/7] gitk: Fix file list context menu for merge commits.
From: Alexander Gavrilov @ 2008-10-08  7:05 UTC (permalink / raw)
  To: git; +Cc: Paul Mackerras
In-Reply-To: <1223449540-20457-4-git-send-email-angavrilov@gmail.com>

Currently it displays an ugly error box, because the
treediffs array is not filled for such commits. This
is clearly unacceptable.

Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com>
---
 gitk |    6 ++++--
 1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/gitk b/gitk
index 3c77909..cfaf7a1 100755
--- a/gitk
+++ b/gitk
@@ -6479,7 +6479,7 @@ proc getblobline {bf id} {
 
 proc mergediff {id} {
     global diffmergeid mdifffd
-    global diffids
+    global diffids treediffs
     global parents
     global diffcontext
     global diffencoding
@@ -6487,6 +6487,7 @@ proc mergediff {id} {
 
     set diffmergeid $id
     set diffids $id
+    set treediffs($id) [list ]
     # this doesn't seem to actually affect anything...
     set cmd [concat | git diff-tree --no-commit-id --cc -U$diffcontext $id]
     if {$limitdiffs && $vfilelimit($curview) ne {}} {
@@ -6506,7 +6507,7 @@ proc mergediff {id} {
 
 proc getmergediffline {mdf id np} {
     global diffmergeid ctext cflist mergemax
-    global difffilestart mdifffd
+    global difffilestart mdifffd treediffs
     global ctext_file_names ctext_file_lines
     global diffencoding
 
@@ -6524,6 +6525,7 @@ proc getmergediffline {mdf id np} {
 	    $ctext insert end "\n"
 	    set here [$ctext index "end - 1c"]
 	    lappend difffilestart $here
+	    lappend treediffs($id) $fname
 	    add_flist [list $fname]
 	    lappend ctext_file_names $fname
 	    lappend ctext_file_lines [lindex [split $here "."] 0]
-- 
1.6.0.20.g6148bc

^ permalink raw reply related

* [PATCH 3/7] gitk: Allow starting gui blame for a specific line.
From: Alexander Gavrilov @ 2008-10-08  7:05 UTC (permalink / raw)
  To: git; +Cc: Paul Mackerras
In-Reply-To: <1223449540-20457-3-git-send-email-angavrilov@gmail.com>

Adds a context menu item to the diff viewer pane that
calls blame, focusing it on the clicked line. In case
of combined diffs, it also automatically deduces which
parent is to be blamed.

The context menu itself is added by this patch. It is
possible to populate it with commands from the flist
menu.

Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com>
---
 gitk |  135 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 133 insertions(+), 2 deletions(-)

diff --git a/gitk b/gitk
index 96ca965..3c77909 100755
--- a/gitk
+++ b/gitk
@@ -2184,6 +2184,7 @@ proc makewindow {} {
     bind $cflist <ButtonRelease-1> {treeclick %W %x %y}
     global ctxbut
     bind $cflist $ctxbut {pop_flist_menu %W %X %Y %x %y}
+    bind $ctext $ctxbut {pop_diff_menu %W %X %Y %x %y}
 
     set maincursor [. cget -cursor]
     set textcursor [$ctext cget -cursor]
@@ -2233,6 +2234,12 @@ proc makewindow {} {
         -command {external_diff}
     $flist_menu add command -label [mc "Blame parent commit"] \
         -command {external_blame 1}
+
+    global diff_menu
+    set diff_menu .diffctxmenu
+    menu $diff_menu -tearoff 0
+    $diff_menu add command -label [mc "Blame parent commit"] \
+        -command {external_blame_diff}
 }
 
 # Windows sends all mouse wheel events to the current focused window, not
@@ -2935,6 +2942,34 @@ proc pop_flist_menu {w X Y x y} {
     tk_popup $flist_menu $X $Y
 }
 
+proc find_ctext_fileinfo {line} {
+    global ctext_file_names ctext_file_lines
+
+    set ok [bsearch $ctext_file_lines $line]
+    set tline [lindex $ctext_file_lines $ok]
+
+    if {$ok >= [llength $ctext_file_lines] || $line < $tline} {
+        return {}
+    } else {
+        return [list [lindex $ctext_file_names $ok] $tline]
+    }
+}
+
+proc pop_diff_menu {w X Y x y} {
+    global ctext diff_menu flist_menu_file
+    global diff_menu_txtpos diff_menu_line
+    global diff_menu_filebase
+
+    stopfinding
+    set diff_menu_txtpos [split [$w index "@$x,$y"] "."]
+    set diff_menu_line [lindex $diff_menu_txtpos 0]
+    set f [find_ctext_fileinfo $diff_menu_line]
+    if {$f eq {}} return
+    set flist_menu_file [lindex $f 0]
+    set diff_menu_filebase [lindex $f 1]
+    tk_popup $diff_menu $X $Y
+}
+
 proc flist_hl {only} {
     global flist_menu_file findstring gdttype
 
@@ -3041,7 +3076,84 @@ proc external_diff {} {
     }
 }
 
-proc external_blame {parent_idx} {
+proc find_hunk_blamespec {base line} {
+    global ctext
+
+    # Find and parse the hunk header
+    set s_lix [$ctext search -backwards -regexp ^@@ "$line.0 lineend" $base.0]
+    if {$s_lix eq {}} return
+
+    set s_line [$ctext get $s_lix "$s_lix + 1 lines"]
+    if {![regexp {^@@@?(( -\d+(,\d+)?)+) \+(\d+)(,\d+)? @@} $s_line \
+	    s_line old_specs osz osz1 new_line nsz]} {
+	return
+    }
+
+    # base lines for the parents
+    set old_lines [list]
+    foreach old_spec [lrange [split $old_specs " "] 1 end] {
+	if {![regexp -- {-(\d+)(,\d+)?} $old_spec \
+	        old_spec old_line osz]} {
+	    return
+	}
+	lappend old_lines $old_line
+    }
+
+    # Now scan the lines to determine offset within the hunk
+    set parent {}
+    set dline 0
+    set s_lno [lindex [split $s_lix "."] 0]
+
+    for {set i $line} {$i > $s_lno} {incr i -1} {
+	set c_line [$ctext get $i.0 "$i.0 + 1 lines"]
+	if {$parent eq {}} {
+	    # find first preceeding line that belongs to some parent
+	    for {set j 0} {$j < [llength $old_lines]} {incr j} {
+		set code [string index $c_line $j]
+		if {$code ne {-} && $code ne { }} continue
+		if {$code eq { } && $parent ne {}} continue
+		set parent $j
+		if {$code eq {-}} break
+	    }
+	}
+	if {$parent ne {}} {
+	    # then count other lines that belong to it
+	    set code [string index $c_line $parent]
+	    if {$code ne {+}} {
+		incr dline
+	    }
+	}
+    }
+
+    if {$parent eq {}} { set parent 0 }
+    incr dline [lindex $old_lines $parent]
+    incr parent
+    return [list $parent $dline]
+}
+
+proc external_blame_diff {} {
+    global currentid diffmergeid cmitmode
+    global diff_menu_txtpos diff_menu_line
+    global diff_menu_filebase flist_menu_file
+
+    if {$cmitmode eq "tree"} {
+	set parent_idx 1
+	set line [expr {$diff_menu_line - $diff_menu_filebase - 1}]
+    } else {
+	set hinfo [find_hunk_blamespec $diff_menu_filebase $diff_menu_line]
+	if {$hinfo ne {}} {
+	    set parent_idx [lindex $hinfo 0]
+	    set line [lindex $hinfo 1]
+	} else {
+	    set parent_idx 1
+	    set line 0
+	}
+    }
+
+    external_blame $parent_idx $line
+}
+
+proc external_blame {parent_idx {line {}}} {
     global flist_menu_file
     global nullid nullid2
     global parentlist selectedline currentid
@@ -3057,7 +3169,12 @@ proc external_blame {parent_idx} {
 	return
     }
 
-    if {[catch {exec git gui blame $base_commit $flist_menu_file &} err]} {
+    set cmdline [list git gui blame]
+    if {$line ne {} && $line > 1} {
+	lappend cmdline "--line=$line"
+    }
+    lappend cmdline $base_commit $flist_menu_file
+    if {[catch {eval exec $cmdline &} err]} {
 	error_popup "[mc "git gui blame: command failed:"] $err"
     }
 }
@@ -6305,6 +6422,7 @@ proc gettreeline {gtf id} {
 
 proc showfile {f} {
     global treefilelist treeidlist diffids nullid nullid2
+    global ctext_file_names ctext_file_lines
     global ctext commentend
 
     set i [lsearch -exact $treefilelist($diffids) $f]
@@ -6328,6 +6446,8 @@ proc showfile {f} {
     filerun $bf [list getblobline $bf $diffids]
     $ctext config -state normal
     clear_ctext $commentend
+    lappend ctext_file_names $f
+    lappend ctext_file_lines [lindex [split $commentend "."] 0]
     $ctext insert end "\n"
     $ctext insert end "$f\n" filesep
     $ctext config -state disabled
@@ -6387,6 +6507,7 @@ proc mergediff {id} {
 proc getmergediffline {mdf id np} {
     global diffmergeid ctext cflist mergemax
     global difffilestart mdifffd
+    global ctext_file_names ctext_file_lines
     global diffencoding
 
     $ctext conf -state normal
@@ -6404,6 +6525,8 @@ proc getmergediffline {mdf id np} {
 	    set here [$ctext index "end - 1c"]
 	    lappend difffilestart $here
 	    add_flist [list $fname]
+	    lappend ctext_file_names $fname
+	    lappend ctext_file_lines [lindex [split $here "."] 0]
 	    set diffencoding [get_cached_encoding $fname]
 	    set l [expr {(78 - [string length $fname]) / 2}]
 	    set pad [string range "----------------------------------------" 1 $l]
@@ -6661,11 +6784,13 @@ proc setinlist {var i val} {
 
 proc makediffhdr {fname ids} {
     global ctext curdiffstart treediffs
+    global ctext_file_names
 
     set i [lsearch -exact $treediffs($ids) $fname]
     if {$i >= 0} {
 	setinlist difffilestart $i $curdiffstart
     }
+    set ctext_file_names [lreplace $ctext_file_names end end $fname]
     set l [expr {(78 - [string length $fname]) / 2}]
     set pad [string range "----------------------------------------" 1 $l]
     $ctext insert $curdiffstart "$pad $fname $pad" filesep
@@ -6674,6 +6799,7 @@ proc makediffhdr {fname ids} {
 proc getblobdiffline {bdf ids} {
     global diffids blobdifffd ctext curdiffstart
     global diffnexthead diffnextnote difffilestart
+    global ctext_file_names ctext_file_lines
     global diffinhdr treediffs
     global diffencoding
 
@@ -6691,6 +6817,8 @@ proc getblobdiffline {bdf ids} {
 	    # start of a new file
 	    $ctext insert end "\n"
 	    set curdiffstart [$ctext index "end - 1c"]
+	    lappend ctext_file_names ""
+	    lappend ctext_file_lines [lindex [split $curdiffstart "."] 0]
 	    $ctext insert end "\n" filesep
 	    # If the name hasn't changed the length will be odd,
 	    # the middle char will be a space, and the two bits either
@@ -6827,6 +6955,7 @@ proc nextfile {} {
 
 proc clear_ctext {{first 1.0}} {
     global ctext smarktop smarkbot
+    global ctext_file_names ctext_file_lines
     global pendinglinks
 
     set l [lindex [split $first .] 0]
@@ -6840,6 +6969,8 @@ proc clear_ctext {{first 1.0}} {
     if {$first eq "1.0"} {
 	catch {unset pendinglinks}
     }
+    set ctext_file_names {}
+    set ctext_file_lines {}
 }
 
 proc settabs {{firstab {}}} {
-- 
1.6.0.20.g6148bc

^ permalink raw reply related

* [PATCH 5/7] gitk: Make cherry-pick call git-citool on conflicts.
From: Alexander Gavrilov @ 2008-10-08  7:05 UTC (permalink / raw)
  To: git; +Cc: Paul Mackerras
In-Reply-To: <1223449540-20457-5-git-send-email-angavrilov@gmail.com>

Now that git-gui has facilities to help users resolve
conflicts, it makes sense to launch it from other gui
tools when they happen.

Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com>
---
 gitk |   59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 58 insertions(+), 1 deletions(-)

diff --git a/gitk b/gitk
index cfaf7a1..e84e109 100755
--- a/gitk
+++ b/gitk
@@ -7843,6 +7843,53 @@ proc mkbrgo {top} {
     }
 }
 
+proc exec_citool {args {baseid {}}} {
+    global commitinfo env
+
+    if {[info exists env(GIT_AUTHOR_NAME)]} {
+	set old_name $env(GIT_AUTHOR_NAME)
+    }
+    if {[info exists env(GIT_AUTHOR_EMAIL)]} {
+	set old_email $env(GIT_AUTHOR_EMAIL)
+    }
+    if {[info exists env(GIT_AUTHOR_DATE)]} {
+	set old_date $env(GIT_AUTHOR_DATE)
+    }
+
+    if {$baseid ne {}} {
+	if {![info exists commitinfo($baseid)]} {
+	    getcommit $baseid
+	}
+	set author [lindex $commitinfo($baseid) 1]
+	set date [lindex $commitinfo($baseid) 2]
+	if {[regexp {^\s*(\S.*\S|\S)\s*<(.*)>\s*$} \
+	            $author author name email]
+	    && $date ne {}} {
+	    set env(GIT_AUTHOR_NAME) $name
+	    set env(GIT_AUTHOR_EMAIL) $email
+	    set env(GIT_AUTHOR_DATE) $date
+	}
+    }
+
+    eval exec git citool $args &
+
+    if {[info exists old_name]} {
+	set env(GIT_AUTHOR_NAME) $old_name
+    } else {
+	unset env(GIT_AUTHOR_NAME)
+    }
+    if {[info exists old_email]} {
+	set env(GIT_AUTHOR_EMAIL) $old_email
+    } else {
+	unset env(GIT_AUTHOR_EMAIL)
+    }
+    if {[info exists old_date]} {
+	set env(GIT_AUTHOR_DATE) $old_date
+    } else {
+	unset env(GIT_AUTHOR_DATE)
+    }
+}
+
 proc cherrypick {} {
     global rowmenuid curview
     global mainhead mainheadid
@@ -7861,7 +7908,17 @@ proc cherrypick {} {
     # no error occurs, and exec takes that as an indication of error...
     if {[catch {exec sh -c "git cherry-pick -r $rowmenuid 2>&1"} err]} {
 	notbusy cherrypick
-	error_popup $err
+	if {[regexp -line \
+	    {Entry '(.*)' would be overwritten by merge} $err msg fname]} {
+	    error_popup [mc "Cherry-pick failed: file '%s' had local modifications.
+Your working directory is in an inconsistent state." $fname]
+	} elseif {[regexp -line {^CONFLICT \(.*\):} $err msg]} {
+	    # Force citool to read MERGE_MSG
+	    file delete [file join [gitdir] "GITGUI_MSG"]
+	    exec_citool [list] $rowmenuid
+	} else {
+	    error_popup $err
+	}
 	return
     }
     set newhead [exec git rev-parse HEAD]
-- 
1.6.0.20.g6148bc

^ permalink raw reply related

* [PATCH 1/7] gitk: Enhance UI popup and accelerator handling.
From: Alexander Gavrilov @ 2008-10-08  7:05 UTC (permalink / raw)
  To: git; +Cc: Paul Mackerras
In-Reply-To: <1223449540-20457-1-git-send-email-angavrilov@gmail.com>

- Popups are supposed to be marked transient, otherwise
  the WM creates them in strange places. Besides, at
  least under kwin, transients are automatically kept
  above their parent.
- Accelerators for menu items should be listed directly
  on the items, to make them more discoverable.
- Some more accelerators are added, e.g. F4 for Edit View.
- Finally, dialogs can now be accepted or dismissed using
  the Return and Escape keys.

Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com>
---
 gitk |   96 ++++++++++++++++++++++++++++++++++++++++++++++++++----------------
 1 files changed, 73 insertions(+), 23 deletions(-)

diff --git a/gitk b/gitk
index e6c2a17..a4ef736 100755
--- a/gitk
+++ b/gitk
@@ -1710,22 +1710,24 @@ proc show_error {w top msg} {
     pack $w.ok -side bottom -fill x
     bind $top <Visibility> "grab $top; focus $top"
     bind $top <Key-Return> "destroy $top"
+    bind $top <Key-space>  "destroy $top"
+    bind $top <Key-Escape> "destroy $top"
     tkwait window $top
 }
 
-proc error_popup msg {
+proc error_popup {msg {owner .}} {
     set w .error
     toplevel $w
-    wm transient $w .
+    wm transient $w $owner
     show_error $w $w $msg
 }
 
-proc confirm_popup msg {
+proc confirm_popup {msg {owner .}} {
     global confirm_ok
     set confirm_ok 0
     set w .confirm
     toplevel $w
-    wm transient $w .
+    wm transient $w $owner
     message $w.m -text $msg -justify center -aspect 400
     pack $w.m -side top -fill x -padx 20 -pady 20
     button $w.ok -text [mc OK] -command "set confirm_ok 1; destroy $w"
@@ -1733,6 +1735,9 @@ proc confirm_popup msg {
     button $w.cancel -text [mc Cancel] -command "destroy $w"
     pack $w.cancel -side right -fill x
     bind $w <Visibility> "grab $w; focus $w"
+    bind $w <Key-Return> "set confirm_ok 1; destroy $w"
+    bind $w <Key-space>  "set confirm_ok 1; destroy $w"
+    bind $w <Key-Escape> "destroy $w"
     tkwait window $w
     return $confirm_ok
 }
@@ -1767,22 +1772,28 @@ proc makewindow {} {
     global rprogitem rprogcoord rownumsel numcommits
     global have_tk85
 
+    if {[tk windowingsystem] eq {aqua}} {
+	set M1T Cmd
+    } else {
+	set M1T Ctrl
+    }
+
     menu .bar
     .bar add cascade -label [mc "File"] -menu .bar.file
     menu .bar.file
-    .bar.file add command -label [mc "Update"] -command updatecommits
-    .bar.file add command -label [mc "Reload"] -command reloadcommits
+    .bar.file add command -label [mc "Update"] -accelerator F5 -command updatecommits
+    .bar.file add command -label [mc "Reload"] -accelerator $M1T-F5 -command reloadcommits
     .bar.file add command -label [mc "Reread references"] -command rereadrefs
-    .bar.file add command -label [mc "List references"] -command showrefs
-    .bar.file add command -label [mc "Quit"] -command doquit
+    .bar.file add command -label [mc "List references"] -accelerator F2 -command showrefs
+    .bar.file add command -label [mc "Quit"] -accelerator $M1T-Q -command doquit
     menu .bar.edit
     .bar add cascade -label [mc "Edit"] -menu .bar.edit
     .bar.edit add command -label [mc "Preferences"] -command doprefs
 
     menu .bar.view
     .bar add cascade -label [mc "View"] -menu .bar.view
-    .bar.view add command -label [mc "New view..."] -command {newview 0}
-    .bar.view add command -label [mc "Edit view..."] -command editview \
+    .bar.view add command -label [mc "New view..."] -accelerator Shift-F4 -command {newview 0}
+    .bar.view add command -label [mc "Edit view..."] -accelerator F4 -command editview \
 	-state disabled
     .bar.view add command -label [mc "Delete view"] -command delview -state disabled
     .bar.view add separator
@@ -2146,7 +2157,12 @@ proc makewindow {} {
     bindkey <Key-Return> {dofind 1 1}
     bindkey ? {dofind -1 1}
     bindkey f nextfile
-    bindkey <F5> updatecommits
+    bind . <F5> updatecommits
+    bind . <$M1B-F5> reloadcommits
+    bind . <F2> showrefs
+    bind . <Shift-F4> {newview 0}
+    catch { bind . <Shift-Key-XF86_Switch_VT_4> {newview 0} }
+    bind . <F4> edit_or_newview
     bind . <$M1B-q> doquit
     bind . <$M1B-f> {dofind 1 1}
     bind . <$M1B-g> {dofind 1 0}
@@ -2456,6 +2472,7 @@ proc about {} {
     }
     toplevel $w
     wm title $w [mc "About gitk"]
+    wm transient $w .
     message $w.m -text [mc "
 Gitk - a commit viewer for git
 
@@ -2484,10 +2501,10 @@ proc keys {} {
     }
     toplevel $w
     wm title $w [mc "Gitk key bindings"]
+    wm transient $w .
     message $w.m -text "
 [mc "Gitk key bindings:"]
 
-[mc "<%s-Q>		Quit" $M1T]
 [mc "<Home>		Move to first commit"]
 [mc "<End>		Move to last commit"]
 [mc "<Up>, p, i	Move up one commit"]
@@ -2521,11 +2538,11 @@ proc keys {} {
 [mc "<%s-plus>	Increase font size" $M1T]
 [mc "<%s-KP->	Decrease font size" $M1T]
 [mc "<%s-minus>	Decrease font size" $M1T]
-[mc "<F5>		Update"]
 " \
 	    -justify left -bg white -border 2 -relief groove
     pack $w.m -side top -fill both -padx 2 -pady 2
     button $w.ok -text [mc "Close"] -command "destroy $w" -default active
+    bind $w <Key-Escape> [list destroy $w]
     pack $w.ok -side bottom
     bind $w <Visibility> "focus $w.ok"
     bind $w <Key-Escape> "destroy $w"
@@ -3171,6 +3188,16 @@ proc newview {ishighlight} {
     vieweditor $top $nextviewnum [mc "Gitk view definition"]
 }
 
+proc edit_or_newview {} {
+    global curview
+
+    if {$curview > 0} {
+	editview
+    } else {
+	newview 0
+    }
+}
+
 proc editview {} {
     global curview
     global viewname viewperm newviewname newviewperm
@@ -3193,6 +3220,7 @@ proc vieweditor {top n title} {
 
     toplevel $top
     wm title $top $title
+    wm transient $top .
     label $top.nl -text [mc "Name"]
     entry $top.name -width 20 -textvariable newviewname($n)
     grid $top.nl $top.name -sticky w -pady 5
@@ -3229,6 +3257,7 @@ proc vieweditor {top n title} {
     frame $top.buts
     button $top.buts.ok -text [mc "OK"] -command [list newviewok $top $n]
     button $top.buts.can -text [mc "Cancel"] -command [list destroy $top]
+    bind $top <Escape> [list destroy $top]
     grid $top.buts.ok $top.buts.can
     grid columnconfigure $top.buts 0 -weight 1 -uniform a
     grid columnconfigure $top.buts 1 -weight 1 -uniform a
@@ -3261,9 +3290,7 @@ proc newviewok {top n} {
     if {[catch {
 	set newargs [shellsplit $newviewargs($n)]
     } err]} {
-	error_popup "[mc "Error in commit selection arguments:"] $err"
-	wm raise $top
-	focus $top
+	error_popup "[mc "Error in commit selection arguments:"] $err" $top
 	return
     }
     set files {}
@@ -7367,6 +7394,7 @@ proc mkpatch {} {
     set patchtop $top
     catch {destroy $top}
     toplevel $top
+    wm transient $top .
     label $top.title -text [mc "Generate patch"]
     grid $top.title - -pady 10
     label $top.from -text [mc "From:"]
@@ -7397,6 +7425,8 @@ proc mkpatch {} {
     frame $top.buts
     button $top.buts.gen -text [mc "Generate"] -command mkpatchgo
     button $top.buts.can -text [mc "Cancel"] -command mkpatchcan
+    bind $top <Key-Return> mkpatchgo
+    bind $top <Key-Escape> mkpatchcan
     grid $top.buts.gen $top.buts.can
     grid columnconfigure $top.buts 0 -weight 1 -uniform a
     grid columnconfigure $top.buts 1 -weight 1 -uniform a
@@ -7431,7 +7461,7 @@ proc mkpatchgo {} {
     set cmd [lrange $cmd 1 end]
     lappend cmd >$fname &
     if {[catch {eval exec $cmd} err]} {
-	error_popup "[mc "Error creating patch:"] $err"
+	error_popup "[mc "Error creating patch:"] $err" $patchtop
     }
     catch {destroy $patchtop}
     unset patchtop
@@ -7451,6 +7481,7 @@ proc mktag {} {
     set mktagtop $top
     catch {destroy $top}
     toplevel $top
+    wm transient $top .
     label $top.title -text [mc "Create tag"]
     grid $top.title - -pady 10
     label $top.id -text [mc "ID:"]
@@ -7468,6 +7499,8 @@ proc mktag {} {
     frame $top.buts
     button $top.buts.gen -text [mc "Create"] -command mktaggo
     button $top.buts.can -text [mc "Cancel"] -command mktagcan
+    bind $top <Key-Return> mktaggo
+    bind $top <Key-Escape> mktagcan
     grid $top.buts.gen $top.buts.can
     grid columnconfigure $top.buts 0 -weight 1 -uniform a
     grid columnconfigure $top.buts 1 -weight 1 -uniform a
@@ -7481,17 +7514,17 @@ proc domktag {} {
     set id [$mktagtop.sha1 get]
     set tag [$mktagtop.tag get]
     if {$tag == {}} {
-	error_popup [mc "No tag name specified"]
+	error_popup [mc "No tag name specified"] $mktagtop
 	return
     }
     if {[info exists tagids($tag)]} {
-	error_popup [mc "Tag \"%s\" already exists" $tag]
+	error_popup [mc "Tag \"%s\" already exists" $tag] $mktagtop
 	return
     }
     if {[catch {
 	exec git tag $tag $id
     } err]} {
-	error_popup "[mc "Error creating tag:"] $err"
+	error_popup "[mc "Error creating tag:"] $err" $mktagtop
 	return
     }
 
@@ -7501,6 +7534,7 @@ proc domktag {} {
     addedtag $id
     dispneartags 0
     run refill_reflist
+    return 1
 }
 
 proc redrawtags {id} {
@@ -7539,7 +7573,7 @@ proc mktagcan {} {
 }
 
 proc mktaggo {} {
-    domktag
+    if {![domktag]} return
     mktagcan
 }
 
@@ -7550,6 +7584,7 @@ proc writecommit {} {
     set wrcomtop $top
     catch {destroy $top}
     toplevel $top
+    wm transient $top .
     label $top.title -text [mc "Write commit to file"]
     grid $top.title - -pady 10
     label $top.id -text [mc "ID:"]
@@ -7571,6 +7606,8 @@ proc writecommit {} {
     frame $top.buts
     button $top.buts.gen -text [mc "Write"] -command wrcomgo
     button $top.buts.can -text [mc "Cancel"] -command wrcomcan
+    bind $top <Key-Return> wrcomgo
+    bind $top <Key-Escape> wrcomcan
     grid $top.buts.gen $top.buts.can
     grid columnconfigure $top.buts 0 -weight 1 -uniform a
     grid columnconfigure $top.buts 1 -weight 1 -uniform a
@@ -7585,7 +7622,7 @@ proc wrcomgo {} {
     set cmd "echo $id | [$wrcomtop.cmd get]"
     set fname [$wrcomtop.fname get]
     if {[catch {exec sh -c $cmd >$fname &} err]} {
-	error_popup "[mc "Error writing commit:"] $err"
+	error_popup "[mc "Error writing commit:"] $err" $wrcomtop
     }
     catch {destroy $wrcomtop}
     unset wrcomtop
@@ -7604,6 +7641,7 @@ proc mkbranch {} {
     set top .makebranch
     catch {destroy $top}
     toplevel $top
+    wm transient $top .
     label $top.title -text [mc "Create new branch"]
     grid $top.title - -pady 10
     label $top.id -text [mc "ID:"]
@@ -7617,6 +7655,8 @@ proc mkbranch {} {
     frame $top.buts
     button $top.buts.go -text [mc "Create"] -command [list mkbrgo $top]
     button $top.buts.can -text [mc "Cancel"] -command "catch {destroy $top}"
+    bind $top <Key-Return> [list mkbrgo $top]
+    bind $top <Key-Escape> "catch {destroy $top}"
     grid $top.buts.go $top.buts.can
     grid columnconfigure $top.buts 0 -weight 1 -uniform a
     grid columnconfigure $top.buts 1 -weight 1 -uniform a
@@ -7630,7 +7670,7 @@ proc mkbrgo {top} {
     set name [$top.name get]
     set id [$top.sha1 get]
     if {$name eq {}} {
-	error_popup [mc "Please specify a name for the new branch"]
+	error_popup [mc "Please specify a name for the new branch"] $top
 	return
     }
     catch {destroy $top}
@@ -7723,6 +7763,7 @@ proc resethead {} {
     button $w.ok -text [mc OK] -command "set confirm_ok 1; destroy $w"
     pack $w.ok -side left -fill x -padx 20 -pady 20
     button $w.cancel -text [mc Cancel] -command "destroy $w"
+    bind $w <Key-Escape> [list destroy $w]
     pack $w.cancel -side right -fill x -padx 20 -pady 20
     bind $w <Visibility> "grab $w; focus $w"
     tkwait window $w
@@ -7879,6 +7920,7 @@ proc showrefs {} {
     }
     toplevel $top
     wm title $top [mc "Tags and heads: %s" [file tail [pwd]]]
+    wm transient $top .
     text $top.list -background $bgcolor -foreground $fgcolor \
 	-selectbackground $selectbgcolor -font mainfont \
 	-xscrollcommand "$top.xsb set" -yscrollcommand "$top.ysb set" \
@@ -7900,6 +7942,7 @@ proc showrefs {} {
     pack $top.f.l -side left
     grid $top.f - -sticky ew -pady 2
     button $top.close -command [list destroy $top] -text [mc "Close"]
+    bind $top <Key-Escape> [list destroy $top]
     grid $top.close -
     grid columnconfigure $top 0 -weight 1
     grid rowconfigure $top 0 -weight 1
@@ -9205,6 +9248,7 @@ proc mkfontdisp {font top which} {
 
 proc choosefont {font which} {
     global fontparam fontlist fonttop fontattr
+    global prefstop
 
     set fontparam(which) $which
     set fontparam(font) $font
@@ -9218,6 +9262,7 @@ proc choosefont {font which} {
 	font create sample
 	eval font config sample [font actual $font]
 	toplevel $top
+	wm transient $top $prefstop
 	wm title $top [mc "Gitk font chooser"]
 	label $top.l -textvariable fontparam(which)
 	pack $top.l -side top
@@ -9251,6 +9296,8 @@ proc choosefont {font which} {
 	frame $top.buts
 	button $top.buts.ok -text [mc "OK"] -command fontok -default active
 	button $top.buts.can -text [mc "Cancel"] -command fontcan -default normal
+	bind $top <Key-Return> fontok
+	bind $top <Key-Escape> fontcan
 	grid $top.buts.ok $top.buts.can
 	grid columnconfigure $top.buts 0 -weight 1 -uniform a
 	grid columnconfigure $top.buts 1 -weight 1 -uniform a
@@ -9332,6 +9379,7 @@ proc doprefs {} {
     }
     toplevel $top
     wm title $top [mc "Gitk preferences"]
+    wm transient $top .
     label $top.ldisp -text [mc "Commit list display options"]
     grid $top.ldisp - -sticky w -pady 10
     label $top.spacer -text " "
@@ -9419,6 +9467,8 @@ proc doprefs {} {
     frame $top.buts
     button $top.buts.ok -text [mc "OK"] -command prefsok -default active
     button $top.buts.can -text [mc "Cancel"] -command prefscan -default normal
+    bind $top <Key-Return> prefsok
+    bind $top <Key-Escape> prefscan
     grid $top.buts.ok $top.buts.can
     grid columnconfigure $top.buts 0 -weight 1 -uniform a
     grid columnconfigure $top.buts 1 -weight 1 -uniform a
-- 
1.6.0.20.g6148bc

^ permalink raw reply related

* [PATCH 2/7] gitk: Allow forcing branch creation if it already exists.
From: Alexander Gavrilov @ 2008-10-08  7:05 UTC (permalink / raw)
  To: git; +Cc: Paul Mackerras
In-Reply-To: <1223449540-20457-2-git-send-email-angavrilov@gmail.com>

If gitk knows that the branch the user tries to create exists,
it should ask whether it should overwrite it. This way the user
can either decide to choose a new name, or move the head while
preserving the reflog.

Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com>
---
 gitk |   28 +++++++++++++++++++++++-----
 1 files changed, 23 insertions(+), 5 deletions(-)

diff --git a/gitk b/gitk
index a4ef736..96ca965 100755
--- a/gitk
+++ b/gitk
@@ -7669,24 +7669,42 @@ proc mkbrgo {top} {
 
     set name [$top.name get]
     set id [$top.sha1 get]
+    set cmdargs [list]
+    set old_id {}
     if {$name eq {}} {
 	error_popup [mc "Please specify a name for the new branch"] $top
 	return
     }
+    if {[info exists headids($name)]} {
+	if {![confirm_popup [mc \
+		"Branch '%s' already exists. Overwrite?" $name] $top]} {
+	    return
+	}
+	set old_id $headids($name)
+	lappend cmdargs -f
+    }
     catch {destroy $top}
+    lappend cmdargs $name $id
     nowbusy newbranch
     update
     if {[catch {
-	exec git branch $name $id
+	eval exec git branch $cmdargs
     } err]} {
 	notbusy newbranch
 	error_popup $err
     } else {
-	set headids($name) $id
-	lappend idheads($id) $name
-	addedhead $id $name
 	notbusy newbranch
-	redrawtags $id
+	if {$old_id ne {}} {
+	    movehead $id $name
+	    movedhead $id $name
+	    redrawtags $old_id
+	    redrawtags $id
+	} else {
+	    set headids($name) $id
+	    lappend idheads($id) $name
+	    addedhead $id $name
+	    redrawtags $id
+	}
 	dispneartags 0
 	run refill_reflist
     }
-- 
1.6.0.20.g6148bc

^ permalink raw reply related

* [PATCH 0/7] gitk: UI enhancements
From: Alexander Gavrilov @ 2008-10-08  7:05 UTC (permalink / raw)
  To: git; +Cc: Paul Mackerras

This is a set of patches that enhance the UI in various ways.
They should be applied in order, and after the previous 4 patches
that deal with encodings. The previous set of patches is
apparently not applied yet, but I feel that I should not hold
these back any longer.

If Robin Rosenberg's series gets accepted first, I'll rebase
and resend the patches.


Alexander Gavrilov (7):
      gitk: Enhance UI popup and accelerator handling.
      gitk: Allow forcing branch creation if it already exists.
      gitk: Allow starting gui blame for a specific line.
      gitk: Fix file list context menu for merge commits.
      gitk: Make cherry-pick call git-citool on conflicts.
      gitk: Implement a user-friendly Edit View dialog.
      gitk: Explicitly position popup windows.

 gitk |  550 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 471 insertions(+), 79 deletions(-)

^ permalink raw reply

* [PATCH v2 RFC] rebase-i-p: do not include non-first-parent commits touching UPSTREAM
From: Stephen Haberman @ 2008-10-08  6:41 UTC (permalink / raw)
  To: git; +Cc: spearce, Stephen Haberman
In-Reply-To: <cover.1223445353.git.stephen@exigencecorp.com>

This covers an odd boundary case found by Avi Kivity's script where a branch
coming off of UPSTREAM is merged into HEAD. Initially it show up in
UPSTREAM..HEAD, but technically UPSTREAM is not moving, the rest of head is, so
we should not need to rewrite the merge.

This adds a check saying we can keep `preserve=t` if `p=UPSTREAM`...unless this
is the first first-parent commit in our UPSTREAM..HEAD rev-list, which could
very well point to UPSTREAM, but we still need to consider it as rewritten so we
start pulling in the rest of the UPSTREAM..HEAD commits that point to it.

Signed-off-by: Stephen Haberman <stephen@exigencecorp.com>
---
 git-rebase--interactive.sh |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 7003ac0..2e9270a 100755
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -553,6 +553,7 @@ first and then run 'git rebase --continue' again."
 					die "Could not init rewritten commits"
 			done
 			MERGES_OPTION=
+			first_after_upstream="$(git rev-list --reverse --first-parent $UPSTREAM..$HEAD | head -n 1)"
 		else
 			MERGES_OPTION=--no-merges
 		fi
@@ -573,7 +574,7 @@ first and then run 'git rebase --continue' again."
 				preserve=t
 				for p in $(git rev-list --parents -1 $sha1 | cut -d' ' -f2-)
 				do
-					if test -f "$REWRITTEN"/$p
+					if test -f "$REWRITTEN"/$p -a \( $p != $UPSTREAM -o $sha1 = $first_after_upstream \)
 					then
 						preserve=f
 					fi
-- 
1.6.0.2

^ permalink raw reply related

* [PATCH v2 RFC] rebase-i-p: if todo was reordered use HEAD as the rewritten parent
From: Stephen Haberman @ 2008-10-08  6:41 UTC (permalink / raw)
  To: git; +Cc: spearce, Stephen Haberman
In-Reply-To: <cover.1223445353.git.stephen@exigencecorp.com>

This seems like the best guess we can make until git sequencer marks are
available. That being said, within the context of re-ordering a commit before
its parent in todo, I think applying it on top of the current commit seems like
a reasonable assumption of what the user intended.

Signed-off-by: Stephen Haberman <stephen@exigencecorp.com>
---
 git-rebase--interactive.sh |    9 +++++++++
 1 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 2e9270a..8a22d78 100755
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -179,6 +179,15 @@ pick_one_preserving_merges () {
 		if test -f "$REWRITTEN"/$p
 		then
 			new_p=$(cat "$REWRITTEN"/$p)
+
+			# If the todo reordered commits, and our parent is marked for
+			# rewriting, but hasn't been gotten to yet, assume the user meant to
+			# drop it on top of the current HEAD
+			if test -z "$new_p"
+			then
+				new_p=$(git rev-parse HEAD)
+			fi
+
 			test $p != $new_p && fast_forward=f
 			case "$new_parents" in
 			*$new_p*)
-- 
1.6.0.2

^ permalink raw reply related

* [PATCH v2 RFC] rebase-i-p: fix 'no squashing merges' tripping up non-merges
From: Stephen Haberman @ 2008-10-08  6:41 UTC (permalink / raw)
  To: git; +Cc: spearce, Stephen Haberman
In-Reply-To: <cover.1223445353.git.stephen@exigencecorp.com>

Also only check out the first parent if this commit if not a squash--if it is a
squash, we want to explicitly ignore the parent and leave the wc as is, as
cherry-pick will apply the squash on top of it.

Signed-off-by: Stephen Haberman <stephen@exigencecorp.com>
---
 git-rebase--interactive.sh |   14 +++++++++-----
 1 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 8af425d..0464bfb 100755
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -198,15 +198,19 @@ pick_one_preserving_merges () {
 			die "Cannot fast forward to $sha1"
 		;;
 	f)
-		test "a$1" = a-n && die "Refusing to squash a merge: $sha1"
-
 		first_parent=$(expr "$new_parents" : ' \([^ ]*\)')
-		# detach HEAD to current parent
-		output git checkout $first_parent 2> /dev/null ||
-			die "Cannot move HEAD to $first_parent"
+
+		if [ "$1" != "-n" ]
+		then
+			# detach HEAD to current parent
+			output git checkout $first_parent 2> /dev/null ||
+				die "Cannot move HEAD to $first_parent"
+		fi
 
 		case "$new_parents" in
 		' '*' '*)
+			test "a$1" = a-n && die "Refusing to squash a merge: $sha1"
+
 			# redo merge
 			author_script=$(get_author_ident_from_commit $sha1)
 			eval "$author_script"
-- 
1.6.0.2

^ permalink raw reply related

* [PATCH v2 RFC] rebase-i-p: only list commits that require rewriting in todo
From: Stephen Haberman @ 2008-10-08  6:41 UTC (permalink / raw)
  To: git; +Cc: spearce, Stephen Haberman
In-Reply-To: <cover.1223445353.git.stephen@exigencecorp.com>

This is heavily based on Stephan Beyer's git sequencer rewrite of rebase-i-p.

Each commit is still found by rev-list UPSTREAM..HEAD, but a commit is only
included in todo if at least one its parents has been marked for rewriting.

Signed-off-by: Stephen Haberman <stephen@exigencecorp.com>
---
 git-rebase--interactive.sh |   26 ++++++++++++++++++++++++--
 1 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 0464bfb..7003ac0 100755
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -561,9 +561,31 @@ first and then run 'git rebase --continue' again."
 		SHORTHEAD=$(git rev-parse --short $HEAD)
 		SHORTONTO=$(git rev-parse --short $ONTO)
 		git rev-list $MERGES_OPTION --pretty=oneline --abbrev-commit \
-			--abbrev=7 --reverse --left-right --cherry-pick \
+			--abbrev=7 --reverse --left-right --cherry-pick --topo-order \
 			$UPSTREAM...$HEAD | \
-			sed -n "s/^>/pick /p" > "$TODO"
+			sed -n "s/^>//p" | while read shortsha1 rest
+		do
+			if test t != "$PRESERVE_MERGES"
+			then
+				echo "pick $shortsha1 $rest" >> "$TODO"
+			else
+				sha1=$(git rev-parse $shortsha1)
+				preserve=t
+				for p in $(git rev-list --parents -1 $sha1 | cut -d' ' -f2-)
+				do
+					if test -f "$REWRITTEN"/$p
+					then
+						preserve=f
+					fi
+				done
+				if test f = "$preserve"
+				then
+					touch "$REWRITTEN/$sha1"
+					echo "pick $shortsha1 $rest" >> "$TODO"
+				fi
+			fi
+		done
+
 		cat >> "$TODO" << EOF
 
 # Rebase $SHORTUPSTREAM..$SHORTHEAD onto $SHORTONTO
-- 
1.6.0.2

^ permalink raw reply related

* [PATCH v2 RFC] rebase-i-p: delay saving current-commit to REWRITTEN if squashing
From: Stephen Haberman @ 2008-10-08  6:41 UTC (permalink / raw)
  To: git; +Cc: spearce, Stephen Haberman
In-Reply-To: <cover.1223445353.git.stephen@exigencecorp.com>

If the current-commit was dumped to REWRITTEN, but then we squash the next
commit in to it, we have invalidated the HEAD was just written to REWRITTEN.
Instead, append the squash hash to current-commit and save both of them the next
time around.

Signed-off-by: Stephen Haberman <stephen@exigencecorp.com>
---
 git-rebase--interactive.sh |   15 ++++++++++-----
 1 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index b7eda66..8af425d 100755
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -159,13 +159,18 @@ pick_one_preserving_merges () {
 
 	if test -f "$DOTEST"/current-commit
 	then
-		current_commit=$(cat "$DOTEST"/current-commit) &&
-		git rev-parse HEAD > "$REWRITTEN"/$current_commit &&
-		rm "$DOTEST"/current-commit ||
-		die "Cannot write current commit's replacement sha1"
+		if [ "$fast_forward" == "t" ]
+		then
+			cat "$DOTEST"/current-commit | while read current_commit
+			do
+				git rev-parse HEAD > "$REWRITTEN"/$current_commit
+			done
+			rm "$DOTEST"/current-commit ||
+			die "Cannot write current commit's replacement sha1"
+		fi
 	fi
 
-	echo $sha1 > "$DOTEST"/current-commit
+	echo $sha1 >> "$DOTEST"/current-commit
 
 	# rewrite parents; if none were rewritten, we can fast-forward.
 	new_parents=
-- 
1.6.0.2

^ permalink raw reply related

* [PATCH v2 RFC] rebase-i-p: test to exclude commits from todo based on its parents
From: Stephen Haberman @ 2008-10-08  6:41 UTC (permalink / raw)
  To: git; +Cc: spearce, Stephen Haberman
In-Reply-To: <cover.1223445353.git.stephen@exigencecorp.com>

The first case was based off a script from Avi Kivity <avi@redhat.com>.

The second case includes a merge-of-a-merge to ensure both are included in todo.

Signed-off-by: Stephen Haberman <stephen@exigencecorp.com>
---
 t/t3411-rebase-preserve-around-merges.sh |  136 ++++++++++++++++++++++++++++++
 1 files changed, 136 insertions(+), 0 deletions(-)
 create mode 100644 t/t3411-rebase-preserve-around-merges.sh

diff --git a/t/t3411-rebase-preserve-around-merges.sh b/t/t3411-rebase-preserve-around-merges.sh
new file mode 100644
index 0000000..18202fb
--- /dev/null
+++ b/t/t3411-rebase-preserve-around-merges.sh
@@ -0,0 +1,136 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Stephen Haberman
+#
+
+test_description='git rebase preserve merges
+
+This test runs git rebase with and tries to squash a commit from after a merge
+to before the merge.
+'
+. ./test-lib.sh
+
+# Copy/paste from t3404-rebase-interactive.sh
+echo "#!$SHELL_PATH" >fake-editor.sh
+cat >> fake-editor.sh <<\EOF
+case "$1" in
+*/COMMIT_EDITMSG)
+	test -z "$FAKE_COMMIT_MESSAGE" || echo "$FAKE_COMMIT_MESSAGE" > "$1"
+	test -z "$FAKE_COMMIT_AMEND" || echo "$FAKE_COMMIT_AMEND" >> "$1"
+	exit
+	;;
+esac
+test -z "$EXPECT_COUNT" ||
+	test "$EXPECT_COUNT" = $(sed -e '/^#/d' -e '/^$/d' < "$1" | wc -l) ||
+	exit
+test -z "$FAKE_LINES" && exit
+grep -v '^#' < "$1" > "$1".tmp
+rm -f "$1"
+cat "$1".tmp
+action=pick
+for line in $FAKE_LINES; do
+	case $line in
+	squash|edit)
+		action="$line";;
+	*)
+		echo sed -n "${line}s/^pick/$action/p"
+		sed -n "${line}p" < "$1".tmp
+		sed -n "${line}s/^pick/$action/p" < "$1".tmp >> "$1"
+		action=pick;;
+	esac
+done
+EOF
+
+test_set_editor "$(pwd)/fake-editor.sh"
+chmod a+x fake-editor.sh
+
+# set up two branches like this:
+#
+# A1 - B1 - D1 - E1 - F1
+#       \        /
+#        -- C1 --
+
+test_expect_success 'setup' '
+	touch a &&
+	touch b &&
+	git add a &&
+	git commit -m A1 &&
+	git tag A1
+	git add b &&
+	git commit -m B1 &&
+	git tag B1 &&
+	git checkout -b branch &&
+	touch c &&
+	git add c &&
+	git commit -m C1 &&
+	git checkout master &&
+	touch d &&
+	git add d &&
+	git commit -m D1 &&
+	git merge branch &&
+	touch f &&
+	git add f &&
+	git commit -m F1 &&
+	git tag F1
+'
+
+# Should result in:
+#
+# A1 - B1 - D2 - E2
+#       \        /
+#        -- C1 --
+#
+test_expect_success 'squash F1 into D1' '
+	FAKE_LINES="1 squash 3 2" git rebase -i -p B1 &&
+	test "$(git rev-parse HEAD^2)" = "$(git rev-parse branch)" &&
+	test "$(git rev-parse HEAD~2)" = "$(git rev-parse B1)" &&
+	git tag E2
+'
+
+# Start with:
+#
+# A1 - B1 - D2 - E2
+#  \
+#   G1 ---- L1 ---- M1
+#    \             /
+#     H1 -- J1 -- K1
+#      \         /
+#        -- I1 --
+#
+# And rebase G1..M1 onto E3
+
+test_expect_success 'rebase two levels of merge' '
+	git checkout -b branch2 A1 &&
+	touch g &&
+	git add g &&
+	git commit -m G1 &&
+	git checkout -b branch3 &&
+	touch h
+	git add h &&
+	git commit -m H1 &&
+	git checkout -b branch4 &&
+	touch i &&
+	git add i &&
+	git commit -m I1 &&
+	git tag I1 &&
+	git checkout branch3 &&
+	touch j &&
+	git add j &&
+	git commit -m J1 &&
+	git merge I1 --no-commit &&
+	git commit -m K1 &&
+	git tag K1 &&
+	git checkout branch2 &&
+	touch l &&
+	git add l &&
+	git commit -m L1 &&
+	git merge K1 --no-commit &&
+	git commit -m M1 &&
+	GIT_EDITOR=: git rebase -i -p E2 &&
+	test "$(git rev-parse HEAD~3)" = "$(git rev-parse E2)" &&
+	test "$(git rev-parse HEAD~2)" = "$(git rev-parse HEAD^2^2~2)" &&
+	test "$(git rev-parse HEAD^2^1^1)" = "$(git rev-parse HEAD^2^2^1)"
+'
+
+test_done
+
-- 
1.6.0.2

^ permalink raw reply related

* [PATCH v2 RFC] rebase-i-p: use HEAD for updating the ref instead of mapping OLDHEAD
From: Stephen Haberman @ 2008-10-08  6:41 UTC (permalink / raw)
  To: git; +Cc: spearce, Stephen Haberman
In-Reply-To: <cover.1223445353.git.stephen@exigencecorp.com>

If OLDHEAD was reordered in the todo, and its mapped NEWHEAD was used to set the
ref, commits reordered after OLDHEAD in the todo would should up as un-committed
changes.

Signed-off-by: Stephen Haberman <stephen@exigencecorp.com>
---
 git-rebase--interactive.sh |   15 +--------------
 1 files changed, 1 insertions(+), 14 deletions(-)

diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index edb6ec6..b7eda66 100755
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -350,20 +350,7 @@ do_next () {
 	HEADNAME=$(cat "$DOTEST"/head-name) &&
 	OLDHEAD=$(cat "$DOTEST"/head) &&
 	SHORTONTO=$(git rev-parse --short $(cat "$DOTEST"/onto)) &&
-	if test -d "$REWRITTEN"
-	then
-		test -f "$DOTEST"/current-commit &&
-			current_commit=$(cat "$DOTEST"/current-commit) &&
-			git rev-parse HEAD > "$REWRITTEN"/$current_commit
-		if test -f "$REWRITTEN"/$OLDHEAD
-		then
-			NEWHEAD=$(cat "$REWRITTEN"/$OLDHEAD)
-		else
-			NEWHEAD=$OLDHEAD
-		fi
-	else
-		NEWHEAD=$(git rev-parse HEAD)
-	fi &&
+	NEWHEAD=$(git rev-parse HEAD) &&
 	case $HEADNAME in
 	refs/*)
 		message="$GIT_REFLOG_ACTION: $HEADNAME onto $SHORTONTO)" &&
-- 
1.6.0.2

^ permalink raw reply related

* [PATCH v2 RFC] rebase-i-p: squashing and limiting todo
From: Stephen Haberman @ 2008-10-08  6:41 UTC (permalink / raw)
  To: git; +Cc: spearce, Stephen Haberman

This is v2 of my attempt at keeping commits with no-parents-being-rewritten off
the rebase-i-p todo list. This was prompted by Avi Kivity's request to squash
commits on either side of a merge, but is something I had wanted as well without
fully realizing it.

Stephan Beyer pointed out his git sequencer branch already does this, contrary
to my incorrect reading of it. His rewrite of rebase-i-p changed how todo was
generated to follow these semantics, and nicely, too, so I replaced my initial
hacky algorithm for "only include commits with rewritten parents" with his.

The better implementation aside, I found Stephan's matching semantics
encouraging as if Avi, myself, and Stephan (plus others/the list involved in
past git sequencer discussions) all expect rebase-i-p to drop non-rewritten
commits, then the semantics should be intuitive and what most users expect.

Also, even though git sequencer has these semantics (and more), I'd like to see
this patch reviewed and applied anyway as I think it is a nice solution to the
current rebase-i-p shortcomings. And, assuming its approved, it can be applied
now instead of waiting for git sequencer to be finished, reviewed, and applied.

This is also my first patch series. I started a new thread--I'm not sure if I
was supposed to use Avi's original message id or not. Also, I cheated and put
the tests in the first commit instead of starting them as test_expect_failure
and gradually changing them to test_expect_success.

Stephen Haberman (7):
  rebase-i-p: test to exclude commits from todo based on its parents
  rebase-i-p: use HEAD for updating the ref instead of mapping OLDHEAD
  rebase-i-p: delay saving current-commit to REWRITTEN if squashing
  rebase-i-p: fix 'no squashing merges' tripping up non-merges
  rebase-i-p: only list commits that require rewriting in todo
  rebase-i-p: do not include non-first-parent commits touching UPSTREAM
  rebase-i-p: if todo was reordered use HEAD as the rewritten parent

 git-rebase--interactive.sh               |   80 ++++++++++++------
 t/t3411-rebase-preserve-around-merges.sh |  136 ++++++++++++++++++++++++++++++
 2 files changed, 190 insertions(+), 26 deletions(-)
 create mode 100644 t/t3411-rebase-preserve-around-merges.sh

^ permalink raw reply

* Re: Different svn-id URLs in history
From: Knut Eldhuset @ 2008-10-08  6:34 UTC (permalink / raw)
  To: git
In-Reply-To: <48EB79D8.6090908@drmicha.warpmail.net>

Michael J Gruber wrote:
> Knut Eldhuset venit, vidit, dixit 07.10.2008 12:58:
>> Hi,
>>
>> After cloning my svn repository, I notice that the svn-id URL is 
>> different when going back in history:
>>
>> git-svn-id: https://server/trunk@300
>>
>> vs
>>
>> git-svn-id: https://server/trunk/some_folder/project/src@250
>>
> 
> I take this is as an invitation for guesswork (given the amount of
> details)...

Sorry about that... I'm confused.
> 
> You probably have commits which don't follow your usual svn repo layout
> (trunk/some_folder/project/src) but commit to trunk/ directly. The output of
> 
> svn log -v -r300 https://server/trunk@300
> svn log -v -r250 https://server/trunk/some_folder/project/src@250
> 
> should give some clues.
> 

Svn log shows that the same path has been modified in both cases. I see 
something strange in git, though. Our svn repository has about 6500 
commits, but git shows over 10.000. Further investigation shows that a 
lot of svn commits have two entries in git. Some branches off of trunk 
do not start at r1, but off of a duplicate rNNNN. Could this be due to 
our unhealthy practice of creating branches off of subtrees in svn? By 
this I mean create a branch off of 
https://server/trunk/some_folder/project/src instead of 
https://server/trunk. If so, what can be done to fix this?

As a sidenote, during git svn clone, I noticed that each time a new 
branch or tag was discovered, the "scanning" started back at r1. Is this 
normal? I would think the history before the branch was already 
imported. Of course, this could maybe be due to the bad branching 
practice described above.

Regards,
Knut

^ permalink raw reply

* Re: [RFC] git rev-contains [Was: merge -s ffonly]
From: Andreas Ericsson @ 2008-10-08  6:18 UTC (permalink / raw)
  To: Uwe Kleine-König; +Cc: Shawn O. Pearce, git, Randal L. Schwartz
In-Reply-To: <20081007185815.GA10744@strlen.de>

Uwe Kleine-König wrote:
> Hello,
> 
>> +	if test -n "$(git rev-list $1..HEAD)"
> I already wrote similar tests and I wonder if this couldn't be done in a
> new builtin command more effectively.  Something like
> 
> 	git rev-contains HEAD "$1"
> 
> .  I expect it to be faster and maybe it prevents a command line
> overflow?!  (I remember something like 32000 chars max in a command, but
> I could not trigger that with bash.)
> 

On Linux (well, on my system anyways), it's 128K for arguments and
environment combined.

-- 
Andreas Ericsson                   andreas.ericsson@op5.se
OP5 AB                             www.op5.se
Tel: +46 8-230225                  Fax: +46 8-230231

^ permalink raw reply

* Re: files missing after converting a cvs repository to git
From: Andreas Ericsson @ 2008-10-08  6:16 UTC (permalink / raw)
  To: Adam Mercer; +Cc: GIT
In-Reply-To: <799406d60810070855y53cf5191m111ce8f5380f96c6@mail.gmail.com>

Adam Mercer wrote:
> On Tue, Oct 7, 2008 at 01:08, Andreas Ericsson <ae@op5.se> wrote:
> 
>> Has the CVS repo been tampered with in the past? If so, it's entirely
>> possible that checking out and working with CVS works just fine, but
>> getting history into coherent changesets is impossible.
> 
> Unfortunately yes. Thats what I thought, and was afraid, was going on.
> I've managed to get things working by restoring some of the missing
> files ,v files from a backup and regenerating the tracking
> repositories. Then I had to remove the files in question from cvs and
> readd them, git cvsimport then saw these files.
> 

Ouch. In that case, all bets are off when it comes to correctly cloning
the history, I'm afraid. On the up-side, if you get a oneshot conversion
done properly you can easily convert it to something else later in case
git doesn't meet your needs, and it might even be easier to add commit
support to "git cvsserver" than it is to fix your broken repository
(it might be in there already; I don't use it so I don't know), in
which case you can use CVS with a git object store.

-- 
Andreas Ericsson                   andreas.ericsson@op5.se
OP5 AB                             www.op5.se
Tel: +46 8-230225                  Fax: +46 8-230231

^ permalink raw reply

* Re: git-who
From: Johannes Sixt @ 2008-10-08  6:13 UTC (permalink / raw)
  To: Rhodes, Kate; +Cc: git
In-Reply-To: <DE2CF127-A7FD-4765-A8E4-5235C5F1B9A9@gmail.com>

Rhodes, Kate schrieb:
> Once upon a someone asked about seeing who had touched some files. Petr
> Baudis responded with a quickie script that did the job.

Wouldn't

   git shortlog -s -- path/to/file

solve your problem?

-- Hannes

^ permalink raw reply

* Re: Git and tagging hook
From: Andreas Ericsson @ 2008-10-08  6:12 UTC (permalink / raw)
  To: Kristis Makris; +Cc: git
In-Reply-To: <1223400602.20250.2.camel@localhost>

Kristis Makris wrote:
> On Mon, 2008-10-06 at 09:20 +0200, Andreas Ericsson wrote:
>> Next time, don't include a members-only list in the CC, please. The
>> usual action when replying to an email on git@vger is to "Reply All",
>> which doesn't play nicely with such lists and will render one list
>> archive incomplete (since people will inevitably cull that other
>> list from their CC's after having sent to it once).
> 
> Why would they cull that other list, if the usual action is to "Reply
> All" ?

Because it's a members-only list. Like me, I'm sure many will get
annoyed enough to remember to remove it for further postings on the
subject. Those nonsensical "awaiting moderator approval" emails are
irritating noise, and since they're "To: me" and get a low spamrank
they go straight to the high-priority folder. Many others on this
list use similar filters as it's a neat way of dealing with several
high-volume mailing lists sanely.

-- 
Andreas Ericsson                   andreas.ericsson@op5.se
OP5 AB                             www.op5.se
Tel: +46 8-230225                  Fax: +46 8-230231

^ permalink raw reply

* Re: [PATCH] Implement git clone -v
From: Shawn O. Pearce @ 2008-10-08  6:02 UTC (permalink / raw)
  To: Miklos Vajna; +Cc: Alex Riesen, Constantine Plotnikov, git
In-Reply-To: <20081007193956.GB536@genesis.frugalware.org>

Miklos Vajna <vmiklos@frugalware.org> wrote:
> On Tue, Oct 07, 2008 at 08:21:28AM +0200, Alex Riesen <raa.lkml@gmail.com> wrote:
> > Yes. Does it work? :)
> 
> Yes, it does. I'm not sure how to test it from the testsuite, maybe
> redirect the output to a file and grep in it? It's ugly, that's why I
> did not do so, but if you think a testcase is a musthave for this
> feature then that's the way to go, I guess.

Actually its not a bad way to test the feature.  Normally we disable
progress if stdout is not a tty.  If you redirect to a file then
-v should be needed to get anything at all on stderr.

You may be able to just test the size of the file:

	git fetch -v ... >out 2>err &&
	test -s err

-- 
Shawn.

^ permalink raw reply

* Re: git-who
From: Rhodes, Kate @ 2008-10-08  4:59 UTC (permalink / raw)
  To: Jeff King; +Cc: git
In-Reply-To: <20081008022505.GB29313@coredump.intra.peff.net>


On Oct 7, 2008, at 10:25 PM, Jeff King wrote:

> On Tue, Oct 07, 2008 at 05:02:46PM -0400, Kate Rhodes wrote:
>
>> As is it's probably not worth including in git, but I'm thinking that
>> someone else can probably come up with some improvements, such as  
>> dates in
>> the verbose mode, support for a treeish instead of a single file  
>> path, and
>> / or rewriting it in C so that it can work on Windows.
>
> Scripts like this often find a good home in git's contrib/ directory.
> Consider submitting a patch which adds it there.
>
>> git://github.com/masukomi/git_accessories.git
>
> I took a look. My biggest complaint is that for many files, it  
> produces
> too many names.

Yeah, I agree, I just haven't come up with a better idea that  
addresses the question of "who touched this". Maybe some sort of  
recency toggle.

> It would be nice to at least sort the names by number
> of commits. But even more accurate might be the number of added lines.
> Somebody who creates a 200-line file should surely come before  
> somebody
> who made a 1-line tweak, right?

Yeah, I've considered maybe adding a -n (number) like that and  
ordering people by number of commits. I'm not convinced that, in most  
cases, size of changes is as important as number.  I think it depends  
on the file. In some cases a person who's constantly mucking about  
with the file is a better go-to person when you have questions /  
issues, than someone who happened to make a few large commits a while  
ago. But then again....


>
> But perhaps even more accurate would be to rely on blame output, since
> it attributes not just added lines, but lines which have actually
> survived into the current product.

mmm good idea.


> And fortunately that is relatively
> easy to do (only lightly tested):

excellent! Thank you. I'll poke at this tomorrow. :)

-masukomi

>
>
> -- >8 --
> #!/usr/bin/perl
> #
> # Invoke as 'git who -M -C file.c' (or whichever blame options
> # you prefer). You can even check a particular set of lines
> # with "git who -M -C -L 40,60 file.c".
>
> use strict;
>
> open(my $in, '-|', qw(git blame -p), @ARGV);
>
> my %count;
> my %author;
> my $current_sha1;
> while(<$in>) {
>  if (!$current_sha1) {
>    /^[0-9a-f]{40}/ or die "expected sha1, got $_";
>    $current_sha1 = $&;
>    $count{$current_sha1}++;
>  }
>  elsif (/^author (.*)/) {
>    $author{$current_sha1} = $1;
>  }
>  elsif (/^\t/) {
>    $current_sha1 = undef;
>  }
> }
>
> my %acount;
> while(my ($h, $c) = each %count) {
>  $acount{$author{$h}} += $c;
> }
>
> foreach (sort { $acount{$b} <=> $acount{$a} } keys %acount) {
>  print "$_ ($acount{$_})\n";
> }

^ permalink raw reply

* Re: git-who
From: Jeff King @ 2008-10-08  2:25 UTC (permalink / raw)
  To: Rhodes, Kate; +Cc: git
In-Reply-To: <DE2CF127-A7FD-4765-A8E4-5235C5F1B9A9@gmail.com>

On Tue, Oct 07, 2008 at 05:02:46PM -0400, Kate Rhodes wrote:

> As is it's probably not worth including in git, but I'm thinking that  
> someone else can probably come up with some improvements, such as dates in 
> the verbose mode, support for a treeish instead of a single file path, and 
> / or rewriting it in C so that it can work on Windows.

Scripts like this often find a good home in git's contrib/ directory.
Consider submitting a patch which adds it there.

> git://github.com/masukomi/git_accessories.git

I took a look. My biggest complaint is that for many files, it produces
too many names. It would be nice to at least sort the names by number
of commits. But even more accurate might be the number of added lines.
Somebody who creates a 200-line file should surely come before somebody
who made a 1-line tweak, right?

But perhaps even more accurate would be to rely on blame output, since
it attributes not just added lines, but lines which have actually
survived into the current product. And fortunately that is relatively
easy to do (only lightly tested):

-- >8 --
#!/usr/bin/perl
#
# Invoke as 'git who -M -C file.c' (or whichever blame options
# you prefer). You can even check a particular set of lines
# with "git who -M -C -L 40,60 file.c".

use strict;

open(my $in, '-|', qw(git blame -p), @ARGV);

my %count;
my %author;
my $current_sha1;
while(<$in>) {
  if (!$current_sha1) {
    /^[0-9a-f]{40}/ or die "expected sha1, got $_";
    $current_sha1 = $&;
    $count{$current_sha1}++;
  }
  elsif (/^author (.*)/) {
    $author{$current_sha1} = $1;
  }
  elsif (/^\t/) {
    $current_sha1 = undef;
  }
}

my %acount;
while(my ($h, $c) = each %count) {
  $acount{$author{$h}} += $c;
}

foreach (sort { $acount{$b} <=> $acount{$a} } keys %acount) {
  print "$_ ($acount{$_})\n";
}

^ permalink raw reply

* [PATCH] guilt: add git commit level versioning
From: Paul Gortmaker @ 2008-10-08  2:08 UTC (permalink / raw)
  To: jeffpc; +Cc: git

Shamelessly steal the dynamic versioning goodies from git
itself.  Now when you do "guilt --version" you can expect to
see things like:

	Guilt version 0.31.2.14.gece1.dirty

assuming you've 14 commits since 0.31.2 and also some changes
that you've not committed yet.

Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
---
 .gitignore             |    2 ++
 Documentation/Makefile |    4 ++--
 GUILT-VERSION-GEN      |   42 ++++++++++++++++++++++++++++++++++++++++++
 Makefile               |   21 ++++++++++++++++-----
 guilt                  |    4 +++-
 5 files changed, 65 insertions(+), 8 deletions(-)
 create mode 100755 GUILT-VERSION-GEN

diff --git a/.gitignore b/.gitignore
index c81112b..61161ef 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,3 +7,5 @@
 #
 *~
 *.swp
+guilt.bin
+GUILT-VERSION-FILE
diff --git a/Documentation/Makefile b/Documentation/Makefile
index 9fc1165..4b7d037 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -7,7 +7,7 @@ DOC_MAN1=$(patsubst %.txt,%.1,$(MAN1_TXT))
 DOC_MAN7=$(patsubst %.txt,%.7,$(MAN7_TXT))
 
 USAGE=$(patsubst %.txt,usage-%.txt,$(MAN1_TXT))
-VERSION=$(shell git describe 2> /dev/null || sed -n -e '/^GUILT_VERSION=/ { s/^GUILT_VERSION="/v/; s/"//; p; q; }' ../guilt)
+include ../GUILT-VERSION-FILE
 
 prefix?=$(PREFIX)
 bindir?=$(prefix)/bin
@@ -51,7 +51,7 @@ doc.dep : $(wildcard *.txt) build-docdep.perl
 -include doc.dep
 
 version.txt:
-	echo "(Generated for Guilt $(VERSION))" > version.txt
+	echo "(Generated for Guilt $(GUILT_VERSION))" > version.txt
 
 cmds.txt: cmd-list.sh $(MAN1_TXT)
 	sh ./cmd-list.sh
diff --git a/GUILT-VERSION-GEN b/GUILT-VERSION-GEN
new file mode 100755
index 0000000..66b40e2
--- /dev/null
+++ b/GUILT-VERSION-GEN
@@ -0,0 +1,42 @@
+#!/bin/sh
+
+GVF=GUILT-VERSION-FILE
+DEF_VER=v0.31.2
+
+LF='
+'
+
+# First see if there is a version file (included in release tarballs),
+# then try git-describe, then default.
+if test -f version
+then
+	VN=$(cat version) || VN="$DEF_VER"
+elif test -d .git -o -f .git &&
+	VN=$(git describe --abbrev=4 HEAD 2>/dev/null) &&
+	case "$VN" in
+	*$LF*) (exit 1) ;;
+	v[0-9]*)
+		git update-index -q --refresh
+		test -z "$(git diff-index --name-only HEAD --)" ||
+		VN="$VN-dirty" ;;
+	esac
+then
+	VN=$(echo "$VN" | sed -e 's/-/./g');
+else
+	VN="$DEF_VER"
+fi
+
+VN=$(expr "$VN" : v*'\(.*\)')
+
+if test -r $GVF
+then
+	VC=$(sed -e 's/^GUILT_VERSION = //' <$GVF)
+else
+	VC=unset
+fi
+test "$VN" = "$VC" || {
+	echo >&2 "GUILT_VERSION=$VN"
+	echo "GUILT_VERSION=$VN" >$GVF
+}
+
+
diff --git a/Makefile b/Makefile
index af53fb5..f3cf0b3 100644
--- a/Makefile
+++ b/Makefile
@@ -1,25 +1,35 @@
 PREFIX=/usr/local
 DESTDIR=
 
-SCRIPTS = guilt \
-	  $(filter-out $(wildcard *~),$(wildcard guilt-*))
+SCRIPTS = $(filter-out $(wildcard *~),$(wildcard guilt-*))
 
-.PHONY: all 
-all: doc
+all::
+
+.PHONY: .FORCE-GUILT-VERSION-FILE
+GUILT-VERSION-FILE: .FORCE-GUILT-VERSION-FILE
+	@$(SHELL_PATH) ./GUILT-VERSION-GEN
+-include GUILT-VERSION-FILE
+
+.PHONY: all
+all:: doc guilt.bin
 	@echo "Nothing to build, it is all bash :)"
 	@echo "Try make install"
 
+guilt.bin: GUILT-VERSION-FILE
+	@sed 's/^GUILT_VERSION=$$/GUILT_VERSION="$(GUILT_VERSION)"/' < guilt > guilt.bin
+
 .PHONY: install
 install:
 	install -d $(DESTDIR)$(PREFIX)/bin/
 	install -m 755 $(SCRIPTS) $(DESTDIR)$(PREFIX)/bin/
+	install -m 755 guilt.bin $(DESTDIR)$(PREFIX)/bin/guilt
 
 .PHONY: uninstall
 uninstall:
 	./uninstall $(DESTDIR)$(PREFIX)/bin/ $(SCRIPTS)
 
 .PHONY: doc
-doc:
+doc: GUILT-VERSION-FILE
 	$(MAKE) -C Documentation all
 
 .PHONY: install-doc
@@ -33,3 +43,4 @@ test:
 .PHONY: clean
 clean: 
 	$(MAKE) -C Documentation clean 
+	$(RM) GUILT-VERSION-FILE guilt.bin
diff --git a/guilt b/guilt
index fabee17..7cfa23b 100755
--- a/guilt
+++ b/guilt
@@ -3,7 +3,9 @@
 # Copyright (c) Josef "Jeff" Sipek, 2006-2008
 #
 
-GUILT_VERSION="0.31.2"
+# Version replaced at build time. Could have in separate file, but why
+# do a "source version_file" on every guilt operation?
+GUILT_VERSION=
 GUILT_NAME="Ciuleandra"
 
 # If the first argument is one of the below, display the man page instead of
-- 
1.6.0

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox