From 6e8c87070306a757c4d7fd2c55cca3a90fe140c7 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Tue, 31 Jul 2007 21:03:06 +1000 Subject: [PATCH 0001/1490] gitk: Establish and use global left-to-right ordering for commits This creates an "ordering token" for each commit which establishes a total ordering for commits and is used to order the commits from left to right on a row. The ordering token is assigned when a commit is first encountered or when it is first listed as a parent of some other commit, whichever comes first. The ordering token is a string of variable length. Parents that don't already have an ordering token are assigned one by appending to the child's token; the first parent gets a "0" on the end, the second "1" and so on. As an optimization, the "0" isn't appended if the child only has one parent. When inserting a new commit into an element of rowidlist, it is inserted in the position which makes the ordering tokens increase from left to right. This also simplifies the layout code by getting rid of the rowoffsets variable, and terminates lines with an arrow after 5 rows if the line would be longer than about 110 rows (rather than letting them go on and terminating them later with an arrow if the graph gets too wide). The effect of having the total ordering, and terminating the lines early, is that it will be possible to lay out only a part of the graph rather than having to do the whole thing top to bottom. Signed-off-by: Paul Mackerras --- gitk | 351 +++++++++++++++++++++++++---------------------------------- 1 file changed, 148 insertions(+), 203 deletions(-) diff --git a/gitk b/gitk index 6c2be3b727..40e5d31749 100755 --- a/gitk +++ b/gitk @@ -82,11 +82,12 @@ proc dorunq {} { proc start_rev_list {view} { global startmsecs global commfd leftover tclencoding datemode - global viewargs viewfiles commitidx + global viewargs viewfiles commitidx vnextroot global lookingforhead showlocalchanges set startmsecs [clock clicks -milliseconds] set commitidx($view) 0 + set vnextroot($view) 0 set order "--topo-order" if {$datemode} { set order "--date-order" @@ -131,12 +132,26 @@ proc getcommits {} { show_status "Reading commits..." } +# This makes a string representation of a positive integer which +# sorts as a string in numerical order +proc strrep {n} { + if {$n < 16} { + return [format "%x" $n] + } elseif {$n < 256} { + return [format "x%.2x" $n] + } elseif {$n < 65536} { + return [format "y%.4x" $n] + } + return [format "z%.8x" $n] +} + proc getcommitlines {fd view} { global commitlisted global leftover commfd global displayorder commitidx commitrow commitdata global parentlist children curview hlview global vparentlist vdisporder vcmitlisted + global ordertok vnextroot set stuff [read $fd 500000] # git log doesn't terminate the last commit with a null... @@ -221,14 +236,32 @@ proc getcommitlines {fd view} { exit 1 } set id [lindex $ids 0] + if {![info exists ordertok($view,$id)]} { + set otok "o[strrep $vnextroot($view)]" + incr vnextroot($view) + set ordertok($view,$id) $otok + } else { + set otok $ordertok($view,$id) + } if {$listed} { set olds [lrange $ids 1 end] - set i 0 - foreach p $olds { - if {$i == 0 || [lsearch -exact $olds $p] >= $i} { - lappend children($view,$p) $id + if {[llength $olds] == 1} { + set p [lindex $olds 0] + lappend children($view,$p) $id + if {![info exists ordertok($view,$p)]} { + set ordertok($view,$p) $ordertok($view,$id) + } + } else { + set i 0 + foreach p $olds { + if {$i == 0 || [lsearch -exact $olds $p] >= $i} { + lappend children($view,$p) $id + } + if {![info exists ordertok($view,$p)]} { + set ordertok($view,$p) "$otok[strrep $i]]" + } + incr i } - incr i } } else { set olds {} @@ -1821,7 +1854,7 @@ proc unflatten {var l} { proc showview {n} { global curview viewdata viewfiles - global displayorder parentlist rowidlist rowoffsets + global displayorder parentlist rowidlist global colormap rowtextx commitrow nextcolor canvxmax global numcommits rowrangelist commitlisted idrowranges rowchk global selectedline currentid canv canvy0 @@ -1859,13 +1892,13 @@ proc showview {n} { set vcmitlisted($curview) $commitlisted if {$phase ne {}} { set viewdata($curview) \ - [list $phase $rowidlist $rowoffsets $rowrangelist \ + [list $phase $rowidlist {} $rowrangelist \ [flatten idrowranges] [flatten idinlist] \ $rowlaidout $rowoptim $numcommits] } elseif {![info exists viewdata($curview)] || [lindex $viewdata($curview) 0] ne {}} { set viewdata($curview) \ - [list {} $rowidlist $rowoffsets $rowrangelist] + [list {} $rowidlist {} $rowrangelist] } } catch {unset treediffs} @@ -1894,7 +1927,6 @@ proc showview {n} { set parentlist $vparentlist($n) set commitlisted $vcmitlisted($n) set rowidlist [lindex $v 1] - set rowoffsets [lindex $v 2] set rowrangelist [lindex $v 3] if {$phase eq {}} { set numcommits [llength $displayorder] @@ -2542,67 +2574,43 @@ proc usedinrange {id l1 l2} { return 0 } -proc sanity {row {full 0}} { - global rowidlist rowoffsets +# Work out where id should go in idlist so that order-token +# values increase from left to right +proc idcol {idlist id {i 0}} { + global ordertok curview - set col -1 - set ids [lindex $rowidlist $row] - foreach id $ids { - incr col - if {$id eq {}} continue - if {$col < [llength $ids] - 1 && - [lsearch -exact -start [expr {$col+1}] $ids $id] >= 0} { - puts "oops: [shortids $id] repeated in row $row col $col: {[shortids [lindex $rowidlist $row]]}" + set t $ordertok($curview,$id) + if {$i >= [llength $idlist] || + $t < $ordertok($curview,[lindex $idlist $i])} { + if {$i > [llength $idlist]} { + set i [llength $idlist] } - set o [lindex $rowoffsets $row $col] - set y $row - set x $col - while {$o ne {}} { - incr y -1 - incr x $o - if {[lindex $rowidlist $y $x] != $id} { - puts "oops: rowoffsets wrong at row [expr {$y+1}] col [expr {$x-$o}]" - puts " id=[shortids $id] check started at row $row" - for {set i $row} {$i >= $y} {incr i -1} { - puts " row $i ids={[shortids [lindex $rowidlist $i]]} offs={[lindex $rowoffsets $i]}" - } - break - } - if {!$full} break - set o [lindex $rowoffsets $y $x] + while {[incr i -1] >= 0 && + $t < $ordertok($curview,[lindex $idlist $i])} {} + incr i + } else { + if {$t > $ordertok($curview,[lindex $idlist $i])} { + while {[incr i] < [llength $idlist] && + $t >= $ordertok($curview,[lindex $idlist $i])} {} } } + return $i } -proc makeuparrow {oid x y z} { - global rowidlist rowoffsets uparrowlen idrowranges displayorder +proc makeuparrow {oid y x} { + global rowidlist uparrowlen idrowranges displayorder for {set i 1} {$i < $uparrowlen && $y > 1} {incr i} { incr y -1 - incr x $z - set off0 [lindex $rowoffsets $y] - for {set x0 $x} {1} {incr x0} { - if {$x0 >= [llength $off0]} { - set x0 [llength [lindex $rowoffsets [expr {$y-1}]]] - break - } - set z [lindex $off0 $x0] - if {$z ne {}} { - incr x0 $z - break - } - } - set z [expr {$x0 - $x}] - lset rowidlist $y [linsert [lindex $rowidlist $y] $x $oid] - lset rowoffsets $y [linsert [lindex $rowoffsets $y] $x $z] + set idl [lindex $rowidlist $y] + set x [idcol $idl $oid $x] + lset rowidlist $y [linsert $idl $x $oid] } - set tmp [lreplace [lindex $rowoffsets $y] $x $x {}] - lset rowoffsets $y [incrange $tmp [expr {$x+1}] -1] lappend idrowranges($oid) [lindex $displayorder $y] } proc initlayout {} { - global rowidlist rowoffsets displayorder commitlisted + global rowidlist displayorder commitlisted global rowlaidout rowoptim global idinlist rowchk rowrangelist idrowranges global numcommits canvxmax canv @@ -2618,7 +2626,6 @@ proc initlayout {} { set rowrangelist {} set nextcolor 0 set rowidlist {{}} - set rowoffsets {{}} catch {unset idinlist} catch {unset rowchk} set rowlaidout 0 @@ -2679,8 +2686,8 @@ proc layoutmore {tmax allread} { set nr [expr {$commitidx($curview) - $rowlaidout}] # may need to increase this threshold if uparrowlen or # mingaplen are increased... - if {$nr > 150} { - set nr 150 + if {$nr > 200} { + set nr 200 } set row $rowlaidout set rowlaidout [layoutrows $row [expr {$row + $nr}] $allread] @@ -2861,7 +2868,7 @@ proc readdifffiles {fd serial} { } proc layoutrows {row endrow last} { - global rowidlist rowoffsets displayorder + global rowidlist displayorder global uparrowlen downarrowlen maxwidth mingaplen global children parentlist global idrowranges @@ -2869,12 +2876,12 @@ proc layoutrows {row endrow last} { global idinlist rowchk rowrangelist set idlist [lindex $rowidlist $row] - set offs [lindex $rowoffsets $row] while {$row < $endrow} { set id [lindex $displayorder $row] set oldolds {} set newolds {} - foreach p [lindex $parentlist $row] { + set olds [lindex $parentlist $row] + foreach p $olds { if {![info exists idinlist($p)]} { lappend newolds $p } elseif {!$idinlist($p)} { @@ -2883,7 +2890,7 @@ proc layoutrows {row endrow last} { } set nev [expr {[llength $idlist] + [llength $newolds] + [llength $oldolds] - $maxwidth + 1}] - if {$nev > 0} { + if {1 || $nev > 0} { if {!$last && $row + $uparrowlen + $mingaplen >= $commitidx($curview)} break for {set x [llength $idlist]} {[incr x -1] >= 0} {} { @@ -2893,34 +2900,25 @@ proc layoutrows {row endrow last} { [expr {$row + $uparrowlen + $mingaplen}]] if {$r == 0} { set idlist [lreplace $idlist $x $x] - set offs [lreplace $offs $x $x] - set offs [incrange $offs $x 1] set idinlist($i) 0 set rm1 [expr {$row - 1}] lappend idrowranges($i) [lindex $displayorder $rm1] - if {[incr nev -1] <= 0} break + #if {[incr nev -1] <= 0} break continue } set rowchk($id) [expr {$row + $r}] } } lset rowidlist $row $idlist - lset rowoffsets $row $offs } set col [lsearch -exact $idlist $id] if {$col < 0} { - set col [llength $idlist] - lappend idlist $id + set col [idcol $idlist $id] + set idlist [linsert $idlist $col $id] lset rowidlist $row $idlist - set z {} if {$children($curview,$id) ne {}} { - set z [expr {[llength [lindex $rowidlist [expr {$row-1}]]] - $col}] unset idinlist($id) - } - lappend offs $z - lset rowoffsets $row $offs - if {$z ne {}} { - makeuparrow $id $col $row $z + makeuparrow $id $row $col } } else { unset idinlist($id) @@ -2933,38 +2931,21 @@ proc layoutrows {row endrow last} { } lappend rowrangelist $ranges incr row - set offs [ntimes [llength $idlist] 0] - set l [llength $newolds] - set idlist [eval lreplace \$idlist $col $col $newolds] - set o 0 - if {$l != 1} { - set offs [lrange $offs 0 [expr {$col - 1}]] - foreach x $newolds { - lappend offs {} - incr o -1 - } - incr o - set tmp [expr {[llength $idlist] - [llength $offs]}] - if {$tmp > 0} { - set offs [concat $offs [ntimes $tmp $o]] - } - } else { - lset offs $col {} - } + set idlist [lreplace $idlist $col $col] + set x $col foreach i $newolds { + set x [idcol $idlist $i $x] + set idlist [linsert $idlist $x $i] set idinlist($i) 1 set idrowranges($i) $id } - incr col $l foreach oid $oldolds { set idinlist($oid) 1 - set idlist [linsert $idlist $col $oid] - set offs [linsert $offs $col $o] - makeuparrow $oid $col $row $o - incr col + set x [idcol $idlist $oid $x] + set idlist [linsert $idlist $x $oid] + makeuparrow $oid $row $x } lappend rowidlist $idlist - lappend rowoffsets $offs } return $row } @@ -2989,7 +2970,7 @@ proc addextraid {id row} { } proc layouttail {} { - global rowidlist rowoffsets idinlist commitidx curview + global rowidlist idinlist commitidx curview global idrowranges rowrangelist set row $commitidx($curview) @@ -3003,56 +2984,70 @@ proc layouttail {} { lappend rowrangelist $idrowranges($id) unset idrowranges($id) incr row - set offs [ntimes $col 0] set idlist [lreplace $idlist $col $col] lappend rowidlist $idlist - lappend rowoffsets $offs } foreach id [array names idinlist] { unset idinlist($id) addextraid $id $row lset rowidlist $row [list $id] - lset rowoffsets $row 0 - makeuparrow $id 0 $row 0 + makeuparrow $id $row 0 lappend idrowranges($id) $id lappend rowrangelist $idrowranges($id) unset idrowranges($id) incr row lappend rowidlist {} - lappend rowoffsets {} } } proc insert_pad {row col npad} { - global rowidlist rowoffsets + global rowidlist set pad [ntimes $npad {}] lset rowidlist $row [eval linsert [list [lindex $rowidlist $row]] $col $pad] - set tmp [eval linsert [list [lindex $rowoffsets $row]] $col $pad] - lset rowoffsets $row [incrange $tmp [expr {$col + $npad}] [expr {-$npad}]] } proc optimize_rows {row col endrow} { - global rowidlist rowoffsets displayorder + global rowidlist displayorder + if {$row < 1} { + set row 1 + } + set idlist [lindex $rowidlist [expr {$row - 1}]] + if {$row >= 2} { + set previdlist [lindex $rowidlist [expr {$row - 2}]] + } else { + set previdlist {} + } for {} {$row < $endrow} {incr row} { + set pprevidlist $previdlist + set previdlist $idlist set idlist [lindex $rowidlist $row] - set offs [lindex $rowoffsets $row] set haspad 0 - for {} {$col < [llength $offs]} {incr col} { - if {[lindex $idlist $col] eq {}} { + set y0 [expr {$row - 1}] + set ym [expr {$row - 2}] + set x0 -1 + set xm -1 + for {} {$col < [llength $idlist]} {incr col} { + set id [lindex $idlist $col] + if {[lindex $previdlist $col] eq $id} continue + if {$id eq {}} { set haspad 1 continue } - set z [lindex $offs $col] - if {$z eq {}} continue + set x0 [lsearch -exact $previdlist $id] + if {$x0 < 0} continue + set z [expr {$x0 - $col}] set isarrow 0 - set x0 [expr {$col + $z}] - set y0 [expr {$row - 1}] - set z0 [lindex $rowoffsets $y0 $x0] + set z0 {} + if {$ym >= 0} { + set xm [lsearch -exact $pprevidlist $id] + if {$xm >= 0} { + set z0 [expr {$xm - $x0}] + } + } if {$z0 eq {}} { - set id [lindex $idlist $col] set ranges [rowranges $id] if {$ranges ne {} && $y0 > [lindex $ranges 0]} { set isarrow 1 @@ -3066,43 +3061,32 @@ proc optimize_rows {row col endrow} { # Line currently goes left too much; # insert pads in the previous row, then optimize it set npad [expr {-1 - $z + $isarrow}] - set offs [incrange $offs $col $npad] insert_pad $y0 $x0 $npad if {$y0 > 0} { optimize_rows $y0 $x0 $row } - set z [lindex $offs $col] - set x0 [expr {$col + $z}] - set z0 [lindex $rowoffsets $y0 $x0] + set previdlist [lindex $rowidlist $y0] + set x0 [lsearch -exact $previdlist $id] + set z [expr {$x0 - $col}] + if {$z0 ne {}} { + set pprevidlist [lindex $rowidlist $ym] + set xm [lsearch -exact $pprevidlist $id] + set z0 [expr {$xm - $x0}] + } } elseif {$z > 1 || ($z > 0 && $isarrow)} { # Line currently goes right too much; - # insert pads in this line and adjust the next's rowoffsets + # insert pads in this line set npad [expr {$z - 1 + $isarrow}] - set y1 [expr {$row + 1}] - set offs2 [lindex $rowoffsets $y1] - set x1 -1 - foreach z $offs2 { - incr x1 - if {$z eq {} || $x1 + $z < $col} continue - if {$x1 + $z > $col} { - incr npad - } - lset rowoffsets $y1 [incrange $offs2 $x1 $npad] - break - } set pad [ntimes $npad {}] set idlist [eval linsert \$idlist $col $pad] - set tmp [eval linsert \$offs $col $pad] incr col $npad - set offs [incrange $tmp $col [expr {-$npad}]] - set z [lindex $offs $col] + set z [expr {$x0 - $col}] set haspad 1 } - if {$z0 eq {} && !$isarrow} { + if {$z0 eq {} && !$isarrow && $ym >= 0} { # this line links to its first child on row $row-2 - set rm2 [expr {$row - 2}] - set id [lindex $displayorder $rm2] - set xc [lsearch -exact [lindex $rowidlist $rm2] $id] + set id [lindex $displayorder $ym] + set xc [lsearch -exact $pprevidlist $id] if {$xc >= 0} { set z0 [expr {$xc - $x0}] } @@ -3110,51 +3094,36 @@ proc optimize_rows {row col endrow} { # avoid lines jigging left then immediately right if {$z0 ne {} && $z < 0 && $z0 > 0} { insert_pad $y0 $x0 1 - set offs [incrange $offs $col 1] - optimize_rows $y0 [expr {$x0 + 1}] $row + incr x0 + optimize_rows $y0 $x0 $row + set previdlist [lindex $rowidlist $y0] + set pprevidlist [lindex $rowidlist $ym] } } if {!$haspad} { - set o {} # Find the first column that doesn't have a line going right for {set col [llength $idlist]} {[incr col -1] >= 0} {} { - set o [lindex $offs $col] - if {$o eq {}} { + set id [lindex $idlist $col] + if {$id eq {}} break + set x0 [lsearch -exact $previdlist $id] + if {$x0 < 0} { # check if this is the link to the first child - set id [lindex $idlist $col] set ranges [rowranges $id] if {$ranges ne {} && $row == [lindex $ranges 0]} { # it is, work out offset to child - set y0 [expr {$row - 1}] set id [lindex $displayorder $y0] - set x0 [lsearch -exact [lindex $rowidlist $y0] $id] - if {$x0 >= 0} { - set o [expr {$x0 - $col}] - } + set x0 [lsearch -exact $previdlist $id] } } - if {$o eq {} || $o <= 0} break + if {$x0 <= $col} break } # Insert a pad at that column as long as it has a line and - # isn't the last column, and adjust the next row' offsets - if {$o ne {} && [incr col] < [llength $idlist]} { - set y1 [expr {$row + 1}] - set offs2 [lindex $rowoffsets $y1] - set x1 -1 - foreach z $offs2 { - incr x1 - if {$z eq {} || $x1 + $z < $col} continue - lset rowoffsets $y1 [incrange $offs2 $x1 1] - break - } + # isn't the last column + if {$x0 >= 0 && [incr col] < [llength $idlist]} { set idlist [linsert $idlist $col {}] - set tmp [linsert $offs $col {}] - incr col - set offs [incrange $tmp $col -1] } } lset rowidlist $row $idlist - lset rowoffsets $row $offs set col 0 } } @@ -3669,7 +3638,7 @@ proc clear_display {} { } proc findcrossings {id} { - global rowidlist parentlist numcommits rowoffsets displayorder + global rowidlist parentlist numcommits displayorder set cross {} set ccross {} @@ -3678,12 +3647,9 @@ proc findcrossings {id} { set e [expr {$numcommits - 1}] } if {$e <= $s} continue - set x [lsearch -exact [lindex $rowidlist $e] $id] - if {$x < 0} { - puts "findcrossings: oops, no [shortids $id] in row $e" - continue - } for {set row $e} {[incr row -1] >= $s} {} { + set x [lsearch -exact [lindex $rowidlist $row] $id] + if {$x < 0} break set olds [lindex $parentlist $row] set kid [lindex $displayorder $row] set kidx [lsearch -exact [lindex $rowidlist $row] $kid] @@ -3701,9 +3667,6 @@ proc findcrossings {id} { } } } - set inc [lindex $rowoffsets $row $x] - if {$inc eq {}} break - incr x $inc } } return [concat $ccross {{}} $cross] @@ -3893,7 +3856,7 @@ proc show_status {msg} { # on that row and below will move down one row. proc insertrow {row newcmit} { global displayorder parentlist commitlisted children - global commitrow curview rowidlist rowoffsets numcommits + global commitrow curview rowidlist numcommits global rowrangelist rowlaidout rowoptim numcommits global selectedline rowchk commitidx @@ -3917,26 +3880,14 @@ proc insertrow {row newcmit} { incr commitidx($curview) set idlist [lindex $rowidlist $row] - set offs [lindex $rowoffsets $row] - set newoffs {} - foreach x $idlist { - if {$x eq {} || ($x eq $p && [llength $kids] == 1)} { - lappend newoffs {} - } else { - lappend newoffs 0 - } - } if {[llength $kids] == 1} { set col [lsearch -exact $idlist $p] lset idlist $col $newcmit } else { set col [llength $idlist] lappend idlist $newcmit - lappend offs {} - lset rowoffsets $row $offs } set rowidlist [linsert $rowidlist $row $idlist] - set rowoffsets [linsert $rowoffsets [expr {$row+1}] $newoffs] set rowrangelist [linsert $rowrangelist $row {}] if {[llength $kids] > 1} { @@ -3965,7 +3916,7 @@ proc insertrow {row newcmit} { # Remove a commit that was inserted with insertrow on row $row. proc removerow {row} { global displayorder parentlist commitlisted children - global commitrow curview rowidlist rowoffsets numcommits + global commitrow curview rowidlist numcommits global rowrangelist idrowranges rowlaidout rowoptim numcommits global linesegends selectedline rowchk commitidx @@ -3993,12 +3944,6 @@ proc removerow {row} { incr commitidx($curview) -1 set rowidlist [lreplace $rowidlist $row $row] - set rowoffsets [lreplace $rowoffsets $rp1 $rp1] - if {$kids ne {}} { - set offs [lindex $rowoffsets $row] - set offs [lreplace $offs end end] - lset rowoffsets $row $offs - } set rowrangelist [lreplace $rowrangelist $row $row] if {[llength $kids] > 0} { @@ -7590,9 +7535,9 @@ set maxgraphpct 50 set maxwidth 16 set revlistorder 0 set fastdate 0 -set uparrowlen 7 -set downarrowlen 7 -set mingaplen 30 +set uparrowlen 5 +set downarrowlen 5 +set mingaplen 100 set cmitmode "patch" set wrapcomment "none" set showneartags 1 From 513a54dc212044596d932dcc9468e0774c1ee2c1 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Wed, 1 Aug 2007 22:27:57 +1000 Subject: [PATCH 0002/1490] gitk: Improve the drawing of links to parent lines The way gitk used to draw the lines joining a commit to the lines representing its parents was sometimes visually ambiguous, especially when the line to the parent had a corner that coincided with a corner on another line. This improves things by using a smaller slanting section on the line joining a commit to a parent line if the parent line is vertical where it joins on. It also optimizes the drawing a little in the case where the parent line slants towards this commit already. Signed-off-by: Paul Mackerras --- gitk | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/gitk b/gitk index 40e5d31749..bc3022e69f 100755 --- a/gitk +++ b/gitk @@ -3363,7 +3363,7 @@ proc drawlineseg {id row endrow arrowlow} { proc drawparentlinks {id row} { global rowidlist canv colormap curview parentlist - global idpos + global idpos linespc set rowids [lindex $rowidlist $row] set col [lsearch -exact $rowids $id] @@ -3373,6 +3373,8 @@ proc drawparentlinks {id row} { set x [xc $row $col] set y [yc $row] set y2 [yc $row2] + set d [expr {int(0.4 * $linespc)}] + set ymid [expr {$y + $d}] set ids [lindex $rowidlist $row2] # rmx = right-most X coord used set rmx 0 @@ -3386,19 +3388,37 @@ proc drawparentlinks {id row} { if {$x2 > $rmx} { set rmx $x2 } - if {[lsearch -exact $rowids $p] < 0} { + set j [lsearch -exact $rowids $p] + if {$j < 0} { # drawlineseg will do this one for us continue } assigncolor $p # should handle duplicated parents here... set coords [list $x $y] - if {$i < $col - 1} { - lappend coords [xc $row [expr {$i + 1}]] $y - } elseif {$i > $col + 1} { - lappend coords [xc $row [expr {$i - 1}]] $y + if {$i != $col} { + # if attaching to a vertical segment, draw a smaller + # slant for visual distinctness + if {$i == $j} { + if {$i < $col} { + lappend coords [expr {$x2 + $d}] $y $x2 $ymid + } else { + lappend coords [expr {$x2 - $d}] $y $x2 $ymid + } + } elseif {$i < $col && $i < $j} { + # segment slants towards us already + lappend coords [xc $row $j] $y + } else { + if {$i < $col - 1} { + lappend coords [expr {$x2 + $linespc}] $y + } elseif {$i > $col + 1} { + lappend coords [expr {$x2 - $linespc}] $y + } + lappend coords $x2 $y2 + } + } else { + lappend coords $x2 $y2 } - lappend coords $x2 $y2 set t [$canv create line $coords -width [linewidth $p] \ -fill $colormap($p) -tags lines.$p] $canv lower $t From e341c06d8140b689001ddc183ec3476c1ede264a Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sun, 12 Aug 2007 12:42:57 +1000 Subject: [PATCH 0003/1490] gitk: Eliminate diagonal arrows This changes the optimizer to insert pads to straighten downward pointing arrows so they point straight down. When drawing the parent link to the first child in drawlineseg, this draws it with 3 segments like other parent links if it is only one row high with an arrow. These two things mean we can dispense with the workarounds for arrows on diagonal segments. This also fixes a couple of other minor bugs. Signed-off-by: Paul Mackerras --- gitk | 87 +++++++++++++++++++++++++----------------------------------- 1 file changed, 36 insertions(+), 51 deletions(-) diff --git a/gitk b/gitk index bc3022e69f..7b62e98ec1 100755 --- a/gitk +++ b/gitk @@ -2600,7 +2600,7 @@ proc idcol {idlist id {i 0}} { proc makeuparrow {oid y x} { global rowidlist uparrowlen idrowranges displayorder - for {set i 1} {$i < $uparrowlen && $y > 1} {incr i} { + for {set i 0} {$i < $uparrowlen && $y > 1} {incr i} { incr y -1 set idl [lindex $rowidlist $y] set x [idcol $idl $oid $x] @@ -3005,7 +3005,14 @@ proc insert_pad {row col npad} { global rowidlist set pad [ntimes $npad {}] - lset rowidlist $row [eval linsert [list [lindex $rowidlist $row]] $col $pad] + set idlist [lindex $rowidlist $row] + set bef [lrange $idlist 0 [expr {$col - 1}]] + set aft [lrange $idlist $col end] + set i [lsearch -exact $aft {}] + if {$i > 0} { + set aft [lreplace $aft $i $i] + } + lset rowidlist $row [concat $bef $pad $aft] } proc optimize_rows {row col endrow} { @@ -3053,6 +3060,10 @@ proc optimize_rows {row col endrow} { set isarrow 1 } } + if {!$isarrow && $id ne [lindex $displayorder $row] && + [lsearch -exact [lindex $rowidlist [expr {$row+1}]] $id] < 0} { + set isarrow 1 + } # Looking at lines from this row to the previous row, # make them go straight up if they end in an arrow on # the previous row; otherwise make them go straight up @@ -3077,8 +3088,8 @@ proc optimize_rows {row col endrow} { # Line currently goes right too much; # insert pads in this line set npad [expr {$z - 1 + $isarrow}] - set pad [ntimes $npad {}] - set idlist [eval linsert \$idlist $col $pad] + insert_pad $row $col $npad + set idlist [lindex $rowidlist $row] incr col $npad set z [expr {$x0 - $col}] set haspad 1 @@ -3169,31 +3180,9 @@ proc rowranges {id} { return $linenos } -# work around tk8.4 refusal to draw arrows on diagonal segments -proc adjarrowhigh {coords} { - global linespc - - set x0 [lindex $coords 0] - set x1 [lindex $coords 2] - if {$x0 != $x1} { - set y0 [lindex $coords 1] - set y1 [lindex $coords 3] - if {$y0 - $y1 <= 2 * $linespc && $x1 == [lindex $coords 4]} { - # we have a nearby vertical segment, just trim off the diag bit - set coords [lrange $coords 2 end] - } else { - set slope [expr {($x0 - $x1) / ($y0 - $y1)}] - set xi [expr {$x0 - $slope * $linespc / 2}] - set yi [expr {$y0 - $linespc / 2}] - set coords [lreplace $coords 0 1 $xi $y0 $xi $yi] - } - } - return $coords -} - proc drawlineseg {id row endrow arrowlow} { global rowidlist displayorder iddrawn linesegs - global canv colormap linespc curview maxlinelen + global canv colormap linespc curview maxlinelen parentlist set cols [list [lsearch -exact [lindex $rowidlist $row] $id]] set le [expr {$row + 1}] @@ -3268,9 +3257,11 @@ proc drawlineseg {id row endrow arrowlow} { set itl [lindex $lines [expr {$i-1}] 2] set al [$canv itemcget $itl -arrow] set arrowlow [expr {$al eq "last" || $al eq "both"}] - } elseif {$arrowlow && - [lsearch -exact [lindex $rowidlist [expr {$row-1}]] $id] >= 0} { - set arrowlow 0 + } elseif {$arrowlow} { + if {[lsearch -exact [lindex $rowidlist [expr {$row-1}]] $id] >= 0 || + [lsearch -exact [lindex $parentlist [expr {$row-1}]] $id] >= 0} { + set arrowlow 0 + } } set arrow [lindex {none first last both} [expr {$arrowhigh + 2*$arrowlow}]] for {set y $le} {[incr y -1] > $row} {} { @@ -3289,8 +3280,19 @@ proc drawlineseg {id row endrow arrowlow} { set xc [lsearch -exact [lindex $rowidlist $row] $ch] if {$xc < 0} { puts "oops: drawlineseg: child $ch not on row $row" - } else { - if {$xc < $x - 1} { + } elseif {$xc != $x} { + if {($arrowhigh && $le == $row + 1) || $dir == 0} { + set d [expr {int(0.5 * $linespc)}] + set x1 [xc $row $x] + if {$xc < $x} { + set x2 [expr {$x1 - $d}] + } else { + set x2 [expr {$x1 + $d}] + } + set y2 [yc $row] + set y1 [expr {$y2 + $d}] + lappend coords $x1 $y1 $x2 $y2 + } elseif {$xc < $x - 1} { lappend coords [xc $row [expr {$x-1}]] [yc $row] } elseif {$xc > $x + 1} { lappend coords [xc $row [expr {$x+1}]] [yc $row] @@ -3301,23 +3303,9 @@ proc drawlineseg {id row endrow arrowlow} { } else { set xn [xc $row $xp] set yn [yc $row] - # work around tk8.4 refusal to draw arrows on diagonal segments - if {$arrowlow && $xn != [lindex $coords end-1]} { - if {[llength $coords] < 4 || - [lindex $coords end-3] != [lindex $coords end-1] || - [lindex $coords end] - $yn > 2 * $linespc} { - set xn [xc $row [expr {$xp - 0.5 * $dir}]] - set yo [yc [expr {$row + 0.5}]] - lappend coords $xn $yo $xn $yn - } - } else { - lappend coords $xn $yn - } + lappend coords $xn $yn } if {!$joinhigh} { - if {$arrowhigh} { - set coords [adjarrowhigh $coords] - } assigncolor $id set t [$canv create line $coords -width [linewidth $id] \ -fill $colormap($id) -tags lines.$id -arrow $arrow] @@ -3341,9 +3329,6 @@ proc drawlineseg {id row endrow arrowlow} { set coords [concat $coords $clow] if {!$joinhigh} { lset lines [expr {$i-1}] 1 $le - if {$arrowhigh} { - set coords [adjarrowhigh $coords] - } } else { # coalesce two pieces $canv delete $ith @@ -3373,7 +3358,7 @@ proc drawparentlinks {id row} { set x [xc $row $col] set y [yc $row] set y2 [yc $row2] - set d [expr {int(0.4 * $linespc)}] + set d [expr {int(0.5 * $linespc)}] set ymid [expr {$y + $d}] set ids [lindex $rowidlist $row2] # rmx = right-most X coord used From 92ed666fa761554c67c8f883863517870a65376d Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Wed, 22 Aug 2007 22:35:28 +1000 Subject: [PATCH 0004/1490] gitk: Get rid of idrowranges and rowrangelist Instead make the rowranges procedure compute its result by looking in the rowidlist entries for the rows around the children of the id and the id itself. This turns out not to take too long, and not having to maintain idrowranges and rowrangelist speeds up the layout. This also makes optimize_rows not use rowranges, since all it really needed was a way to work out if one id is the first child of another, so it can just look at the children list. Signed-off-by: Paul Mackerras --- gitk | 142 +++++++++++++++++++++++++++-------------------------------- 1 file changed, 66 insertions(+), 76 deletions(-) diff --git a/gitk b/gitk index d2f5eeeaaf..a29c793830 100755 --- a/gitk +++ b/gitk @@ -1927,7 +1927,7 @@ proc showview {n} { global curview viewdata viewfiles global displayorder parentlist rowidlist global colormap rowtextx commitrow nextcolor canvxmax - global numcommits rowrangelist commitlisted idrowranges rowchk + global numcommits commitlisted rowchk global selectedline currentid canv canvy0 global treediffs global pending_select phase @@ -1963,13 +1963,13 @@ proc showview {n} { set vcmitlisted($curview) $commitlisted if {$phase ne {}} { set viewdata($curview) \ - [list $phase $rowidlist {} $rowrangelist \ - [flatten idrowranges] [flatten idinlist] \ + [list $phase $rowidlist {} {} \ + {} [flatten idinlist] \ $rowlaidout $rowoptim $numcommits] } elseif {![info exists viewdata($curview)] || [lindex $viewdata($curview) 0] ne {}} { set viewdata($curview) \ - [list {} $rowidlist {} $rowrangelist] + [list {} $rowidlist {} {}] } } catch {unset treediffs} @@ -1998,12 +1998,9 @@ proc showview {n} { set parentlist $vparentlist($n) set commitlisted $vcmitlisted($n) set rowidlist [lindex $v 1] - set rowrangelist [lindex $v 3] if {$phase eq {}} { set numcommits [llength $displayorder] - catch {unset idrowranges} } else { - unflatten idrowranges [lindex $v 4] unflatten idinlist [lindex $v 5] set rowlaidout [lindex $v 6] set rowoptim [lindex $v 7] @@ -2670,7 +2667,7 @@ proc idcol {idlist id {i 0}} { } proc makeuparrow {oid y x} { - global rowidlist uparrowlen idrowranges displayorder + global rowidlist uparrowlen displayorder for {set i 0} {$i < $uparrowlen && $y > 1} {incr i} { incr y -1 @@ -2678,13 +2675,12 @@ proc makeuparrow {oid y x} { set x [idcol $idl $oid $x] lset rowidlist $y [linsert $idl $x $oid] } - lappend idrowranges($oid) [lindex $displayorder $y] } proc initlayout {} { global rowidlist displayorder commitlisted global rowlaidout rowoptim - global idinlist rowchk rowrangelist idrowranges + global idinlist rowchk global numcommits canvxmax canv global nextcolor global parentlist @@ -2695,7 +2691,6 @@ proc initlayout {} { set displayorder {} set commitlisted {} set parentlist {} - set rowrangelist {} set nextcolor 0 set rowidlist {{}} catch {unset idinlist} @@ -2705,7 +2700,6 @@ proc initlayout {} { set canvxmax [$canv cget -width] catch {unset colormap} catch {unset rowtextx} - catch {unset idrowranges} set selectfirst 1 } @@ -2952,9 +2946,8 @@ proc layoutrows {row endrow last} { global rowidlist displayorder global uparrowlen downarrowlen maxwidth mingaplen global children parentlist - global idrowranges global commitidx curview - global idinlist rowchk rowrangelist + global idinlist rowchk set idlist [lindex $rowidlist $row] while {$row < $endrow} { @@ -2970,8 +2963,6 @@ proc layoutrows {row endrow last} { if {$r == 0} { set idlist [lreplace $idlist $x $x] set idinlist($i) 0 - set rm1 [expr {$row - 1}] - lappend idrowranges($i) [lindex $displayorder $rm1] continue } set rowchk($i) [expr {$row + $r}] @@ -3001,20 +2992,12 @@ proc layoutrows {row endrow last} { } else { unset idinlist($id) } - set ranges {} - if {[info exists idrowranges($id)]} { - set ranges $idrowranges($id) - lappend ranges $id - unset idrowranges($id) - } - lappend rowrangelist $ranges incr row set idlist [lreplace $idlist $col $col] set x $col foreach i $newolds { set x [idcol $idlist $i $x] set idlist [linsert $idlist $x $i] - set idrowranges($i) $id } foreach oid $oldolds { set x [idcol $idlist $oid $x] @@ -3047,7 +3030,6 @@ proc addextraid {id row} { proc layouttail {} { global rowidlist idinlist commitidx curview - global idrowranges rowrangelist set row $commitidx($curview) set idlist [lindex $rowidlist $row] @@ -3056,9 +3038,6 @@ proc layouttail {} { set id [lindex $idlist $col] addextraid $id $row catch {unset idinlist($id)} - lappend idrowranges($id) $id - lappend rowrangelist $idrowranges($id) - unset idrowranges($id) incr row set idlist [lreplace $idlist $col $col] lappend rowidlist $idlist @@ -3069,9 +3048,6 @@ proc layouttail {} { addextraid $id $row lset rowidlist $row [list $id] makeuparrow $id $row 0 - lappend idrowranges($id) $id - lappend rowrangelist $idrowranges($id) - unset idrowranges($id) incr row lappend rowidlist {} } @@ -3092,7 +3068,7 @@ proc insert_pad {row col npad} { } proc optimize_rows {row col endrow} { - global rowidlist displayorder + global rowidlist displayorder curview children if {$row < 1} { set row 1 @@ -3131,8 +3107,9 @@ proc optimize_rows {row col endrow} { } } if {$z0 eq {}} { - set ranges [rowranges $id] - if {$ranges ne {} && $y0 > [lindex $ranges 0]} { + # if row y0 is the first child of $id then it's not an arrow + if {[lindex $children($curview,$id) 0] ne + [lindex $displayorder $y0]} { set isarrow 1 } } @@ -3195,11 +3172,10 @@ proc optimize_rows {row col endrow} { set x0 [lsearch -exact $previdlist $id] if {$x0 < 0} { # check if this is the link to the first child - set ranges [rowranges $id] - if {$ranges ne {} && $row == [lindex $ranges 0]} { + set kid [lindex $displayorder $y0] + if {[lindex $children($curview,$id) 0] eq $kid} { # it is, work out offset to child - set id [lindex $displayorder $y0] - set x0 [lsearch -exact $previdlist $id] + set x0 [lsearch -exact $previdlist $kid] } } if {$x0 <= $col} break @@ -3236,24 +3212,59 @@ proc linewidth {id} { } proc rowranges {id} { - global phase idrowranges commitrow rowlaidout rowrangelist curview + global commitrow curview children uparrowlen downarrowlen + global rowidlist - set ranges {} - if {$phase eq {} || - ([info exists commitrow($curview,$id)] - && $commitrow($curview,$id) < $rowlaidout)} { - set ranges [lindex $rowrangelist $commitrow($curview,$id)] - } elseif {[info exists idrowranges($id)]} { - set ranges $idrowranges($id) + set kids $children($curview,$id) + if {$kids eq {}} { + return {} } - set linenos {} - foreach rid $ranges { - lappend linenos $commitrow($curview,$rid) + set ret {} + lappend kids $id + foreach child $kids { + if {![info exists commitrow($curview,$child)]} break + set row $commitrow($curview,$child) + if {![info exists prev]} { + lappend ret [expr {$row + 1}] + } else { + if {$row <= $prevrow} { + puts "oops children out of order [shortids $id] $row < [shortids $prev] $prevrow" + } + # see if the line extends the whole way from prevrow to row + if {$row > $prevrow + $uparrowlen + $downarrowlen && + [lsearch -exact [lindex $rowidlist \ + [expr {int(($row + $prevrow) / 2)}]] $id] < 0} { + # it doesn't, see where it ends + set r [expr {$prevrow + $downarrowlen}] + if {[lsearch -exact [lindex $rowidlist $r] $id] < 0} { + while {[incr r -1] > $prevrow && + [lsearch -exact [lindex $rowidlist $r] $id] < 0} {} + } else { + while {[incr r] <= $row && + [lsearch -exact [lindex $rowidlist $r] $id] >= 0} {} + incr r -1 + } + lappend ret $r + # see where it starts up again + set r [expr {$row - $uparrowlen}] + if {[lsearch -exact [lindex $rowidlist $r] $id] < 0} { + while {[incr r] < $row && + [lsearch -exact [lindex $rowidlist $r] $id] < 0} {} + } else { + while {[incr r -1] >= $prevrow && + [lsearch -exact [lindex $rowidlist $r] $id] >= 0} {} + incr r + } + lappend ret $r + } + } + if {$child eq $id} { + lappend ret $row + } + set prev $id + set prevrow $row } - if {$linenos ne {}} { - lset linenos 0 [expr {[lindex $linenos 0] + 1}] - } - return $linenos + return $ret } proc drawlineseg {id row endrow arrowlow} { @@ -3938,7 +3949,7 @@ proc show_status {msg} { proc insertrow {row newcmit} { global displayorder parentlist commitlisted children global commitrow curview rowidlist numcommits - global rowrangelist rowlaidout rowoptim numcommits + global rowlaidout rowoptim numcommits global selectedline rowchk commitidx if {$row >= $numcommits} { @@ -3970,18 +3981,6 @@ proc insertrow {row newcmit} { } set rowidlist [linsert $rowidlist $row $idlist] - set rowrangelist [linsert $rowrangelist $row {}] - if {[llength $kids] > 1} { - set rp1 [expr {$row + 1}] - set ranges [lindex $rowrangelist $rp1] - if {$ranges eq {}} { - set ranges [list $newcmit $p] - } elseif {[lindex $ranges end-1] eq $p} { - lset ranges end-1 $newcmit - } - lset rowrangelist $rp1 $ranges - } - catch {unset rowchk} incr rowlaidout @@ -3998,7 +3997,7 @@ proc insertrow {row newcmit} { proc removerow {row} { global displayorder parentlist commitlisted children global commitrow curview rowidlist numcommits - global rowrangelist idrowranges rowlaidout rowoptim numcommits + global rowlaidout rowoptim numcommits global linesegends selectedline rowchk commitidx if {$row >= $numcommits} { @@ -4026,15 +4025,6 @@ proc removerow {row} { set rowidlist [lreplace $rowidlist $row $row] - set rowrangelist [lreplace $rowrangelist $row $row] - if {[llength $kids] > 0} { - set ranges [lindex $rowrangelist $row] - if {[lindex $ranges end-1] eq $id} { - set ranges [lreplace $ranges end-1 end] - lset rowrangelist $row $ranges - } - } - catch {unset rowchk} incr rowlaidout -1 From b0cdca996a3717552ee30e8cc2bd157bb32fd213 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Thu, 23 Aug 2007 19:35:51 +1000 Subject: [PATCH 0005/1490] gitk: Get rid of idinlist array This changes layoutrows to use information from rowidlist and children to work out which parent ids are appearing for the first time or need an up arrow, instead of using idinlist. To detect the situation where git log doesn't give us all the commits it references, this adds an idpending array that is updated and used by getcommitlines. This also fixes a bug where we weren't resetting the ordertok array when updating the list of commits; this fixes that too, and a bug where we could try to access an undefined element of commitrow if the user did an update before gitk had finished reading in the graph. Signed-off-by: Paul Mackerras --- gitk | 84 +++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 46 insertions(+), 38 deletions(-) diff --git a/gitk b/gitk index a29c793830..7b0b4cfade 100755 --- a/gitk +++ b/gitk @@ -151,7 +151,7 @@ proc getcommitlines {fd view} { global displayorder commitidx commitrow commitdata global parentlist children curview hlview global vparentlist vdisporder vcmitlisted - global ordertok vnextroot + global ordertok vnextroot idpending set stuff [read $fd 500000] # git log doesn't terminate the last commit with a null... @@ -162,6 +162,23 @@ proc getcommitlines {fd view} { if {![eof $fd]} { return 1 } + # Check if we have seen any ids listed as parents that haven't + # appeared in the list + foreach vid [array names idpending "$view,*"] { + # should only get here if git log is buggy + set id [lindex [split $vid ","] 1] + set commitrow($vid) $commitidx($view) + incr commitidx($view) + if {$view == $curview} { + lappend parentlist {} + lappend displayorder $id + lappend commitlisted 0 + } else { + lappend vparentlist($view) {} + lappend vdisporder($view) $id + lappend vcmitlisted($view) 0 + } + } global viewname unset commfd($view) notbusy $view @@ -242,6 +259,7 @@ proc getcommitlines {fd view} { set ordertok($view,$id) $otok } else { set otok $ordertok($view,$id) + unset idpending($view,$id) } if {$listed} { set olds [lrange $ids 1 end] @@ -250,6 +268,7 @@ proc getcommitlines {fd view} { lappend children($view,$p) $id if {![info exists ordertok($view,$p)]} { set ordertok($view,$p) $ordertok($view,$id) + set idpending($view,$p) 1 } } else { set i 0 @@ -259,6 +278,7 @@ proc getcommitlines {fd view} { } if {![info exists ordertok($view,$p)]} { set ordertok($view,$p) "$otok[strrep $i]]" + set idpending($view,$p) 1 } incr i } @@ -328,7 +348,7 @@ proc readcommit {id} { } proc updatecommits {} { - global viewdata curview phase displayorder + global viewdata curview phase displayorder ordertok idpending global children commitrow selectedline thickerline showneartags if {$phase ne {}} { @@ -339,6 +359,10 @@ proc updatecommits {} { foreach id $displayorder { catch {unset children($n,$id)} catch {unset commitrow($n,$id)} + catch {unset ordertok($n,$id)} + } + foreach vid [array names idpending "$n,*"] { + unset idpending($vid) } set curview -1 catch {unset selectedline} @@ -1963,13 +1987,11 @@ proc showview {n} { set vcmitlisted($curview) $commitlisted if {$phase ne {}} { set viewdata($curview) \ - [list $phase $rowidlist {} {} \ - {} [flatten idinlist] \ - $rowlaidout $rowoptim $numcommits] + [list $phase $rowidlist $rowlaidout $rowoptim $numcommits] } elseif {![info exists viewdata($curview)] || [lindex $viewdata($curview) 0] ne {}} { set viewdata($curview) \ - [list {} $rowidlist {} {}] + [list {} $rowidlist] } } catch {unset treediffs} @@ -2001,10 +2023,9 @@ proc showview {n} { if {$phase eq {}} { set numcommits [llength $displayorder] } else { - unflatten idinlist [lindex $v 5] - set rowlaidout [lindex $v 6] - set rowoptim [lindex $v 7] - set numcommits [lindex $v 8] + set rowlaidout [lindex $v 2] + set rowoptim [lindex $v 3] + set numcommits [lindex $v 4] catch {unset rowchk} } @@ -2123,7 +2144,7 @@ proc addvhighlight {n} { } set hlview $n if {$n != $curview && ![info exists viewdata($n)]} { - set viewdata($n) [list getcommits {{}} {{}} {} {} {} 0 0 0 {}] + set viewdata($n) [list getcommits {{}} 0 0 0] set vparentlist($n) {} set vdisporder($n) {} set vcmitlisted($n) {} @@ -2635,9 +2656,11 @@ proc usedinrange {id l1 l2} { } set kids $children($curview,$id) foreach c $kids { - set r $commitrow($curview,$c) - if {$l1 <= $r && $r <= $l2} { - return [expr {$r - $l1 + 1}] + if {[info exists commitrow($curview,$c)]} { + set r $commitrow($curview,$c) + if {$l1 <= $r && $r <= $l2} { + return [expr {$r - $l1 + 1}] + } } } return 0 @@ -2680,7 +2703,7 @@ proc makeuparrow {oid y x} { proc initlayout {} { global rowidlist displayorder commitlisted global rowlaidout rowoptim - global idinlist rowchk + global rowchk global numcommits canvxmax canv global nextcolor global parentlist @@ -2693,7 +2716,6 @@ proc initlayout {} { set parentlist {} set nextcolor 0 set rowidlist {{}} - catch {unset idinlist} catch {unset rowchk} set rowlaidout 0 set rowoptim 0 @@ -2733,7 +2755,7 @@ proc visiblerows {} { proc layoutmore {tmax allread} { global rowlaidout rowoptim commitidx numcommits optim_delay - global uparrowlen curview rowidlist idinlist + global uparrowlen curview rowidlist set showlast 0 set showdelay $optim_delay @@ -2763,8 +2785,7 @@ proc layoutmore {tmax allread} { } elseif {$allread} { set optdelay 0 set nrows $commitidx($curview) - if {[lindex $rowidlist $nrows] ne {} || - [array names idinlist] ne {}} { + if {[lindex $rowidlist $nrows] ne {}} { layouttail set rowlaidout $commitidx($curview) } elseif {$rowoptim == $nrows} { @@ -2947,7 +2968,7 @@ proc layoutrows {row endrow last} { global uparrowlen downarrowlen maxwidth mingaplen global children parentlist global commitidx curview - global idinlist rowchk + global rowchk set idlist [lindex $rowidlist $row] while {$row < $endrow} { @@ -2962,7 +2983,6 @@ proc layoutrows {row endrow last} { [expr {$row + $uparrowlen + $mingaplen}]] if {$r == 0} { set idlist [lreplace $idlist $x $x] - set idinlist($i) 0 continue } set rowchk($i) [expr {$row + $r}] @@ -2973,12 +2993,12 @@ proc layoutrows {row endrow last} { set oldolds {} set newolds {} foreach p [lindex $parentlist $row] { - if {![info exists idinlist($p)]} { + # is id the first child of this parent? + if {$id eq [lindex $children($curview,$p) 0]} { lappend newolds $p - } elseif {!$idinlist($p)} { + } elseif {[lsearch -exact $idlist $p] < 0} { lappend oldolds $p } - set idinlist($p) 1 } set col [lsearch -exact $idlist $id] if {$col < 0} { @@ -2986,11 +3006,8 @@ proc layoutrows {row endrow last} { set idlist [linsert $idlist $col $id] lset rowidlist $row $idlist if {$children($curview,$id) ne {}} { - unset idinlist($id) makeuparrow $id $row $col } - } else { - unset idinlist($id) } incr row set idlist [lreplace $idlist $col $col] @@ -3029,7 +3046,7 @@ proc addextraid {id row} { } proc layouttail {} { - global rowidlist idinlist commitidx curview + global rowidlist commitidx curview set row $commitidx($curview) set idlist [lindex $rowidlist $row] @@ -3037,20 +3054,10 @@ proc layouttail {} { set col [expr {[llength $idlist] - 1}] set id [lindex $idlist $col] addextraid $id $row - catch {unset idinlist($id)} incr row set idlist [lreplace $idlist $col $col] lappend rowidlist $idlist } - - foreach id [array names idinlist] { - unset idinlist($id) - addextraid $id $row - lset rowidlist $row [list $id] - makeuparrow $id $row 0 - incr row - lappend rowidlist {} - } } proc insert_pad {row col npad} { @@ -4205,6 +4212,7 @@ proc findmorerev {} { set last 0 for {} {$l > $lim} {incr l -1} { set id [lindex $displayorder $l] + if {![info exists commitdata($id)]} continue if {![doesmatch $commitdata($id)]} continue if {![info exists commitinfo($id)]} { getcommit $id From 97645683bff498e369c1c24ce10e78b51cdaf468 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Thu, 23 Aug 2007 22:24:38 +1000 Subject: [PATCH 0006/1490] gitk: Fix some problems with the display of ids as links First, this fixes the problem where a SHA1 id wouldn't be displayed as a link if it wasn't in the part of the graph that had been laid out at the time the details pane was filled in, even if that commit later became part of the graph. This arranges for us to turn the SHA1 id into a link when we get to that id in laying out the graph. Secondly, there was a problem where the cursor wouldn't always turn to a hand when over a link, because the areas for two links could overlap slightly. This fixes that by using a counter rather than always reverting to a counter when we leave the region of a link (which can happen just after we've entered a different link). Signed-off-by: Paul Mackerras --- gitk | 87 ++++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 55 insertions(+), 32 deletions(-) diff --git a/gitk b/gitk index 7b0b4cfade..c795e9838e 100755 --- a/gitk +++ b/gitk @@ -1959,7 +1959,7 @@ proc showview {n} { global commfd global selectedview selectfirst global vparentlist vdisporder vcmitlisted - global hlview selectedhlview + global hlview selectedhlview commitinterest if {$n == $curview} return set selid {} @@ -2000,6 +2000,7 @@ proc showview {n} { unset hlview set selectedhlview None } + catch {unset commitinterest} set curview $n set selectedview $n @@ -4322,7 +4323,7 @@ proc commit_descriptor {p} { # append some text to the ctext widget, and make any SHA1 ID # that we know about be a clickable link. proc appendwithlinks {text tags} { - global ctext commitrow linknum curview + global ctext commitrow linknum curview pendinglinks set start [$ctext index "end - 1c"] $ctext insert end $text $tags @@ -4331,17 +4332,48 @@ proc appendwithlinks {text tags} { set s [lindex $l 0] set e [lindex $l 1] set linkid [string range $text $s $e] - if {![info exists commitrow($curview,$linkid)]} continue incr e - $ctext tag add link "$start + $s c" "$start + $e c" $ctext tag add link$linknum "$start + $s c" "$start + $e c" - $ctext tag bind link$linknum <1> \ - [list selectline $commitrow($curview,$linkid) 1] + setlink $linkid link$linknum incr linknum } - $ctext tag conf link -foreground blue -underline 1 - $ctext tag bind link { %W configure -cursor hand2 } - $ctext tag bind link { %W configure -cursor $curtextcursor } +} + +proc setlink {id lk} { + global curview commitrow ctext pendinglinks commitinterest + + if {[info exists commitrow($curview,$id)]} { + $ctext tag conf $lk -foreground blue -underline 1 + $ctext tag bind $lk <1> [list selectline $commitrow($curview,$id) 1] + $ctext tag bind $lk {linkcursor %W 1} + $ctext tag bind $lk {linkcursor %W -1} + } else { + lappend pendinglinks($id) $lk + lappend commitinterest($id) {makelink %I} + } +} + +proc makelink {id} { + global pendinglinks + + if {![info exists pendinglinks($id)]} return + foreach lk $pendinglinks($id) { + setlink $id $lk + } + unset pendinglinks($id) +} + +proc linkcursor {w inc} { + global linkentercount curtextcursor + + if {[incr linkentercount $inc] > 0} { + $w configure -cursor hand2 + } else { + $w configure -cursor $curtextcursor + if {$linkentercount < 0} { + set linkentercount 0 + } + } } proc viewnextline {dir} { @@ -4388,15 +4420,7 @@ proc appendrefs {pos ids var} { $ctext tag delete $lk $ctext insert $pos $sep $ctext insert $pos [lindex $ti 0] $lk - if {[info exists commitrow($curview,$id)]} { - $ctext tag conf $lk -foreground blue - $ctext tag bind $lk <1> \ - [list selectline $commitrow($curview,$id) 1] - $ctext tag conf $lk -underline 1 - $ctext tag bind $lk { %W configure -cursor hand2 } - $ctext tag bind $lk \ - { %W configure -cursor $curtextcursor } - } + setlink $id $lk set sep ", " } } @@ -5237,6 +5261,7 @@ proc nextfile {} { proc clear_ctext {{first 1.0}} { global ctext smarktop smarkbot + global pendinglinks set l [lindex [split $first .] 0] if {![info exists smarktop] || [$ctext compare $first < $smarktop.0]} { @@ -5246,6 +5271,9 @@ proc clear_ctext {{first 1.0}} { set smarkbot $l } $ctext delete $first end + if {$first eq "1.0"} { + catch {unset pendinglinks} + } } proc incrsearch {name ix op} { @@ -5609,12 +5637,9 @@ proc lineclick {x y id isnew} { # fill the details pane with info about this line $ctext conf -state normal clear_ctext - $ctext tag conf link -foreground blue -underline 1 - $ctext tag bind link { %W configure -cursor hand2 } - $ctext tag bind link { %W configure -cursor $curtextcursor } $ctext insert end "Parent:\t" - $ctext insert end $id [list link link0] - $ctext tag bind link0 <1> [list selbyid $id] + $ctext insert end $id link0 + setlink $id link0 set info $commitinfo($id) $ctext insert end "\n\t[lindex $info 0]\n" $ctext insert end "\tAuthor:\t[lindex $info 1]\n" @@ -5629,8 +5654,8 @@ proc lineclick {x y id isnew} { if {![info exists commitinfo($child)] && ![getcommit $child]} continue set info $commitinfo($child) $ctext insert end "\n\t" - $ctext insert end $child [list link link$i] - $ctext tag bind link$i <1> [list selbyid $child] + $ctext insert end $child link$i + setlink $child link$i $ctext insert end "\n\t[lindex $info 0]" $ctext insert end "\n\tAuthor:\t[lindex $info 1]" set date [formatdate [lindex $info 2]] @@ -5711,16 +5736,13 @@ proc doseldiff {oldid newid} { clear_ctext init_flist "Top" $ctext insert end "From " - $ctext tag conf link -foreground blue -underline 1 - $ctext tag bind link { %W configure -cursor hand2 } - $ctext tag bind link { %W configure -cursor $curtextcursor } - $ctext tag bind link0 <1> [list selbyid $oldid] - $ctext insert end $oldid [list link link0] + $ctext insert end $oldid link0 + setlink $oldid link0 $ctext insert end "\n " $ctext insert end [lindex $commitinfo($oldid) 0] $ctext insert end "\n\nTo " - $ctext tag bind link1 <1> [list selbyid $newid] - $ctext insert end $newid [list link link1] + $ctext insert end $newid link1 + setlink $newid link1 $ctext insert end "\n " $ctext insert end [lindex $commitinfo($newid) 0] $ctext insert end "\n" @@ -7892,6 +7914,7 @@ set boldrows {} set boldnamerows {} set diffelide {0 0} set markingmatches 0 +set linkentercount 0 set optim_delay 16 From 8f0bc7e95e41673a853a53e17708c6f4f46e6420 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Fri, 24 Aug 2007 22:16:42 +1000 Subject: [PATCH 0007/1490] gitk: Get rid of the rowchk array Instead, when looking for lines that should be terminated with a down arrow, we look at the parents of the commit $downarrowlen + 1 rows before. This gets rid of one more place where we are assuming that all the rows are laid out in order from top to bottom. Signed-off-by: Paul Mackerras --- gitk | 55 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/gitk b/gitk index c795e9838e..7726c311c5 100755 --- a/gitk +++ b/gitk @@ -1951,7 +1951,7 @@ proc showview {n} { global curview viewdata viewfiles global displayorder parentlist rowidlist global colormap rowtextx commitrow nextcolor canvxmax - global numcommits commitlisted rowchk + global numcommits commitlisted global selectedline currentid canv canvy0 global treediffs global pending_select phase @@ -2027,7 +2027,6 @@ proc showview {n} { set rowlaidout [lindex $v 2] set rowoptim [lindex $v 3] set numcommits [lindex $v 4] - catch {unset rowchk} } catch {unset colormap} @@ -2704,7 +2703,6 @@ proc makeuparrow {oid y x} { proc initlayout {} { global rowidlist displayorder commitlisted global rowlaidout rowoptim - global rowchk global numcommits canvxmax canv global nextcolor global parentlist @@ -2717,7 +2715,6 @@ proc initlayout {} { set parentlist {} set nextcolor 0 set rowidlist {{}} - catch {unset rowchk} set rowlaidout 0 set rowoptim 0 set canvxmax [$canv cget -width] @@ -2964,29 +2961,43 @@ proc readdifffiles {fd serial} { return 0 } +proc nextuse {id row} { + global commitrow curview children + + if {[info exists children($curview,$id)]} { + foreach kid $children($curview,$id) { + if {[info exists commitrow($curview,$kid)] && + $commitrow($curview,$kid) > $row} { + return $commitrow($curview,$kid) + } + } + } + if {[info exists commitrow($curview,$id)]} { + return $commitrow($curview,$id) + } + return -1 +} + proc layoutrows {row endrow last} { global rowidlist displayorder global uparrowlen downarrowlen maxwidth mingaplen global children parentlist global commitidx curview - global rowchk set idlist [lindex $rowidlist $row] + if {!$last && $endrow + $uparrowlen + $mingaplen > $commitidx($curview)} { + set endrow [expr {$commitidx($curview) - $uparrowlen - $mingaplen}] + } while {$row < $endrow} { set id [lindex $displayorder $row] - if {1} { - if {!$last && - $row + $uparrowlen + $mingaplen >= $commitidx($curview)} break - for {set x [llength $idlist]} {[incr x -1] >= 0} {} { - set i [lindex $idlist $x] - if {![info exists rowchk($i)] || $row >= $rowchk($i)} { - set r [usedinrange $i [expr {$row - $downarrowlen}] \ - [expr {$row + $uparrowlen + $mingaplen}]] - if {$r == 0} { - set idlist [lreplace $idlist $x $x] - continue - } - set rowchk($i) [expr {$row + $r}] + if {$row > $downarrowlen} { + set termrow [expr {$row - $downarrowlen - 1}] + foreach p [lindex $parentlist $termrow] { + set i [lsearch -exact $idlist $p] + if {$i < 0} continue + set nr [nextuse $p $termrow] + if {$nr < 0 || $nr >= $row + $mingaplen + $uparrowlen} { + set idlist [lreplace $idlist $i $i] } } lset rowidlist $row $idlist @@ -3958,7 +3969,7 @@ proc insertrow {row newcmit} { global displayorder parentlist commitlisted children global commitrow curview rowidlist numcommits global rowlaidout rowoptim numcommits - global selectedline rowchk commitidx + global selectedline commitidx if {$row >= $numcommits} { puts "oops, inserting new row $row but only have $numcommits rows" @@ -3989,8 +4000,6 @@ proc insertrow {row newcmit} { } set rowidlist [linsert $rowidlist $row $idlist] - catch {unset rowchk} - incr rowlaidout incr rowoptim incr numcommits @@ -4006,7 +4015,7 @@ proc removerow {row} { global displayorder parentlist commitlisted children global commitrow curview rowidlist numcommits global rowlaidout rowoptim numcommits - global linesegends selectedline rowchk commitidx + global linesegends selectedline commitidx if {$row >= $numcommits} { puts "oops, removing row $row but only have $numcommits rows" @@ -4033,8 +4042,6 @@ proc removerow {row} { set rowidlist [lreplace $rowidlist $row $row] - catch {unset rowchk} - incr rowlaidout -1 incr rowoptim -1 incr numcommits -1 From 0380081c65c3e8a46caad9aebe8e97ff65510453 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Wed, 29 Aug 2007 21:45:21 +1000 Subject: [PATCH 0008/1490] gitk: Do only the parts of the layout that are needed This changes layoutrows and optimize_rows to make it possible to lay out only a little bit more of the graph than is visible, rather than having to lay out the whole graph from top to bottom. To lay out some of the graph without starting at the top, we use the new make_idlist procedure for the first row, then lay it out proceeding downwards as before. Empty list elements in rowidlist are used to denote rows that haven't been laid out yet. Optimizing happens much as before except that we don't try to optimize unless we have three consecutive rows laid out (or the top 2 rows). We have a new list, rowisopt, to record which rows have been optimized. If we change a row that has already been drawn, we set a flag which causes drawcommits to throw away everything drawn on the canvas and redraw the visible rows. Signed-off-by: Paul Mackerras --- gitk | 492 ++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 265 insertions(+), 227 deletions(-) diff --git a/gitk b/gitk index 7726c311c5..060c4c0cb2 100755 --- a/gitk +++ b/gitk @@ -1949,13 +1949,13 @@ proc unflatten {var l} { proc showview {n} { global curview viewdata viewfiles - global displayorder parentlist rowidlist + global displayorder parentlist rowidlist rowisopt global colormap rowtextx commitrow nextcolor canvxmax global numcommits commitlisted global selectedline currentid canv canvy0 global treediffs global pending_select phase - global commitidx rowlaidout rowoptim + global commitidx global commfd global selectedview selectfirst global vparentlist vdisporder vcmitlisted @@ -1987,11 +1987,11 @@ proc showview {n} { set vcmitlisted($curview) $commitlisted if {$phase ne {}} { set viewdata($curview) \ - [list $phase $rowidlist $rowlaidout $rowoptim $numcommits] + [list $phase $rowidlist $rowisopt $numcommits] } elseif {![info exists viewdata($curview)] || [lindex $viewdata($curview) 0] ne {}} { set viewdata($curview) \ - [list {} $rowidlist] + [list {} $rowidlist $rowisopt] } } catch {unset treediffs} @@ -2021,12 +2021,11 @@ proc showview {n} { set parentlist $vparentlist($n) set commitlisted $vcmitlisted($n) set rowidlist [lindex $v 1] + set rowisopt [lindex $v 2] if {$phase eq {}} { set numcommits [llength $displayorder] } else { - set rowlaidout [lindex $v 2] - set rowoptim [lindex $v 3] - set numcommits [lindex $v 4] + set numcommits [lindex $v 3] } catch {unset colormap} @@ -2625,47 +2624,18 @@ proc shortids {ids} { return $res } -proc incrange {l x o} { - set n [llength $l] - while {$x < $n} { - set e [lindex $l $x] - if {$e ne {}} { - lset l $x [expr {$e + $o}] - } - incr x - } - return $l -} - proc ntimes {n o} { set ret {} - for {} {$n > 0} {incr n -1} { - lappend ret $o + set o [list $o] + for {set mask 1} {$mask <= $n} {incr mask $mask} { + if {($n & $mask) != 0} { + set ret [concat $ret $o] + } + set o [concat $o $o] } return $ret } -proc usedinrange {id l1 l2} { - global children commitrow curview - - if {[info exists commitrow($curview,$id)]} { - set r $commitrow($curview,$id) - if {$l1 <= $r && $r <= $l2} { - return [expr {$r - $l1 + 1}] - } - } - set kids $children($curview,$id) - foreach c $kids { - if {[info exists commitrow($curview,$c)]} { - set r $commitrow($curview,$c) - if {$l1 <= $r && $r <= $l2} { - return [expr {$r - $l1 + 1}] - } - } - } - return 0 -} - # Work out where id should go in idlist so that order-token # values increase from left to right proc idcol {idlist id {i 0}} { @@ -2689,20 +2659,8 @@ proc idcol {idlist id {i 0}} { return $i } -proc makeuparrow {oid y x} { - global rowidlist uparrowlen displayorder - - for {set i 0} {$i < $uparrowlen && $y > 1} {incr i} { - incr y -1 - set idl [lindex $rowidlist $y] - set x [idcol $idl $oid $x] - lset rowidlist $y [linsert $idl $x $oid] - } -} - proc initlayout {} { - global rowidlist displayorder commitlisted - global rowlaidout rowoptim + global rowidlist rowisopt displayorder commitlisted global numcommits canvxmax canv global nextcolor global parentlist @@ -2714,9 +2672,8 @@ proc initlayout {} { set commitlisted {} set parentlist {} set nextcolor 0 - set rowidlist {{}} - set rowlaidout 0 - set rowoptim 0 + set rowidlist {} + set rowisopt {} set canvxmax [$canv cget -width] catch {unset colormap} catch {unset rowtextx} @@ -2752,54 +2709,18 @@ proc visiblerows {} { } proc layoutmore {tmax allread} { - global rowlaidout rowoptim commitidx numcommits optim_delay - global uparrowlen curview rowidlist + global commitidx numcommits + global uparrowlen downarrowlen mingaplen curview - set showlast 0 - set showdelay $optim_delay - set optdelay [expr {$uparrowlen + 1}] - while {1} { - if {$rowoptim - $showdelay > $numcommits} { - showstuff [expr {$rowoptim - $showdelay}] $showlast - } elseif {$rowlaidout - $optdelay > $rowoptim} { - set nr [expr {$rowlaidout - $optdelay - $rowoptim}] - if {$nr > 100} { - set nr 100 - } - optimize_rows $rowoptim 0 [expr {$rowoptim + $nr}] - incr rowoptim $nr - } elseif {$commitidx($curview) > $rowlaidout} { - set nr [expr {$commitidx($curview) - $rowlaidout}] - # may need to increase this threshold if uparrowlen or - # mingaplen are increased... - if {$nr > 200} { - set nr 200 - } - set row $rowlaidout - set rowlaidout [layoutrows $row [expr {$row + $nr}] $allread] - if {$rowlaidout == $row} { - return 0 - } - } elseif {$allread} { - set optdelay 0 - set nrows $commitidx($curview) - if {[lindex $rowidlist $nrows] ne {}} { - layouttail - set rowlaidout $commitidx($curview) - } elseif {$rowoptim == $nrows} { - set showdelay 0 - set showlast 1 - if {$numcommits == $nrows} { - return 0 - } - } - } else { - return 0 - } - if {$tmax ne {} && [clock clicks -milliseconds] >= $tmax} { - return 1 - } + set show $commitidx($curview) + if {!$allread} { + set delay [expr {$uparrowlen + $mingaplen + $downarrowlen + 3}] + set show [expr {$show - $delay}] } + if {$show > $numcommits} { + showstuff $show $allread + } + return 0 } proc showstuff {canshow last} { @@ -2966,8 +2887,10 @@ proc nextuse {id row} { if {[info exists children($curview,$id)]} { foreach kid $children($curview,$id) { - if {[info exists commitrow($curview,$kid)] && - $commitrow($curview,$kid) > $row} { + if {![info exists commitrow($curview,$kid)]} { + return -1 + } + if {$commitrow($curview,$kid) > $row} { return $commitrow($curview,$kid) } } @@ -2978,97 +2901,171 @@ proc nextuse {id row} { return -1 } -proc layoutrows {row endrow last} { - global rowidlist displayorder +proc make_idlist {row} { + global displayorder parentlist uparrowlen downarrowlen mingaplen + global commitidx curview ordertok children commitrow + + set r [expr {$row - $mingaplen - $downarrowlen - 1}] + if {$r < 0} { + set r 0 + } + set ra [expr {$row - $downarrowlen}] + if {$ra < 0} { + set ra 0 + } + set rb [expr {$row + $uparrowlen}] + if {$rb > $commitidx($curview)} { + set rb $commitidx($curview) + } + set ids {} + for {} {$r < $ra} {incr r} { + set nextid [lindex $displayorder [expr {$r + 1}]] + foreach p [lindex $parentlist $r] { + if {$p eq $nextid} continue + set rn [nextuse $p $r] + if {$rn >= $row && + $rn <= $r + $downarrowlen + $mingaplen + $uparrowlen} { + lappend ids [list $ordertok($curview,$p) $p] + } + } + } + for {} {$r < $row} {incr r} { + set nextid [lindex $displayorder [expr {$r + 1}]] + foreach p [lindex $parentlist $r] { + if {$p eq $nextid} continue + set rn [nextuse $p $r] + if {$rn < 0 || $rn >= $row} { + lappend ids [list $ordertok($curview,$p) $p] + } + } + } + set id [lindex $displayorder $row] + lappend ids [list $ordertok($curview,$id) $id] + while {$r < $rb} { + foreach p [lindex $parentlist $r] { + set firstkid [lindex $children($curview,$p) 0] + if {$commitrow($curview,$firstkid) < $row} { + lappend ids [list $ordertok($curview,$p) $p] + } + } + incr r + set id [lindex $displayorder $r] + if {$id ne {}} { + set firstkid [lindex $children($curview,$id) 0] + if {$firstkid ne {} && $commitrow($curview,$firstkid) < $row} { + lappend ids [list $ordertok($curview,$id) $id] + } + } + } + set idlist {} + foreach idx [lsort -unique $ids] { + lappend idlist [lindex $idx 1] + } + return $idlist +} + +proc layoutrows {row endrow} { + global rowidlist rowisopt displayorder global uparrowlen downarrowlen maxwidth mingaplen global children parentlist - global commitidx curview + global commitidx curview commitrow - set idlist [lindex $rowidlist $row] - if {!$last && $endrow + $uparrowlen + $mingaplen > $commitidx($curview)} { - set endrow [expr {$commitidx($curview) - $uparrowlen - $mingaplen}] + set idlist {} + if {$row > 0} { + foreach id [lindex $rowidlist [expr {$row - 1}]] { + if {$id ne {}} { + lappend idlist $id + } + } } - while {$row < $endrow} { - set id [lindex $displayorder $row] - if {$row > $downarrowlen} { - set termrow [expr {$row - $downarrowlen - 1}] - foreach p [lindex $parentlist $termrow] { - set i [lsearch -exact $idlist $p] - if {$i < 0} continue - set nr [nextuse $p $termrow] - if {$nr < 0 || $nr >= $row + $mingaplen + $uparrowlen} { - set idlist [lreplace $idlist $i $i] + for {} {$row < $endrow} {incr row} { + set rm1 [expr {$row - 1}] + if {$rm1 < 0 || [lindex $rowidlist $rm1] eq {}} { + set idlist [make_idlist $row] + } else { + set id [lindex $displayorder $rm1] + set col [lsearch -exact $idlist $id] + set idlist [lreplace $idlist $col $col] + foreach p [lindex $parentlist $rm1] { + if {[lsearch -exact $idlist $p] < 0} { + set col [idcol $idlist $p $col] + set idlist [linsert $idlist $col $p] } } - lset rowidlist $row $idlist - } - set oldolds {} - set newolds {} - foreach p [lindex $parentlist $row] { - # is id the first child of this parent? - if {$id eq [lindex $children($curview,$p) 0]} { - lappend newolds $p - } elseif {[lsearch -exact $idlist $p] < 0} { - lappend oldolds $p + set id [lindex $displayorder $row] + if {$row > $downarrowlen} { + set termrow [expr {$row - $downarrowlen - 1}] + foreach p [lindex $parentlist $termrow] { + set i [lsearch -exact $idlist $p] + if {$i < 0} continue + set nr [nextuse $p $termrow] + if {$nr < 0 || $nr >= $row + $mingaplen + $uparrowlen} { + set idlist [lreplace $idlist $i $i] + } + } + } + set col [lsearch -exact $idlist $id] + if {$col < 0} { + set col [idcol $idlist $id] + set idlist [linsert $idlist $col $id] + } + set r [expr {$row + $uparrowlen - 1}] + if {$r < $commitidx($curview)} { + set x $col + foreach p [lindex $parentlist $r] { + if {[lsearch -exact $idlist $p] >= 0} continue + set fk [lindex $children($curview,$p) 0] + if {$commitrow($curview,$fk) < $row} { + set x [idcol $idlist $p $x] + set idlist [linsert $idlist $x $p] + } + } + if {[incr r] < $commitidx($curview)} { + set p [lindex $displayorder $r] + if {[lsearch -exact $idlist $p] < 0} { + set fk [lindex $children($curview,$p) 0] + if {$fk ne {} && $commitrow($curview,$fk) < $row} { + set x [idcol $idlist $p $x] + set idlist [linsert $idlist $x $p] + } + } + } } } - set col [lsearch -exact $idlist $id] - if {$col < 0} { - set col [idcol $idlist $id] - set idlist [linsert $idlist $col $id] - lset rowidlist $row $idlist - if {$children($curview,$id) ne {}} { - makeuparrow $id $row $col + set l [llength $rowidlist] + if {$row == $l} { + lappend rowidlist $idlist + lappend rowisopt 0 + } elseif {$row < $l} { + if {$idlist ne [lindex $rowidlist $row]} { + lset rowidlist $row $idlist + changedrow $row } + } else { + set rowidlist [concat $rowidlist [ntimes [expr {$row - $l}] {}]] + lappend rowidlist $idlist + set rowisopt [concat $rowisopt [ntimes [expr {$row - $l + 1}] 0]] } - incr row - set idlist [lreplace $idlist $col $col] - set x $col - foreach i $newolds { - set x [idcol $idlist $i $x] - set idlist [linsert $idlist $x $i] - } - foreach oid $oldolds { - set x [idcol $idlist $oid $x] - set idlist [linsert $idlist $x $oid] - makeuparrow $oid $row $x - } - lappend rowidlist $idlist } return $row } -proc addextraid {id row} { - global displayorder commitrow commitinfo - global commitidx commitlisted - global parentlist children curview +proc changedrow {row} { + global displayorder iddrawn rowisopt need_redisplay - incr commitidx($curview) - lappend displayorder $id - lappend commitlisted 0 - lappend parentlist {} - set commitrow($curview,$id) $row - readcommit $id - if {![info exists commitinfo($id)]} { - set commitinfo($id) {"No commit information available"} + set l [llength $rowisopt] + if {$row < $l} { + lset rowisopt $row 0 + if {$row + 1 < $l} { + lset rowisopt [expr {$row + 1}] 0 + if {$row + 2 < $l} { + lset rowisopt [expr {$row + 2}] 0 + } + } } - if {![info exists children($curview,$id)]} { - set children($curview,$id) {} - } -} - -proc layouttail {} { - global rowidlist commitidx curview - - set row $commitidx($curview) - set idlist [lindex $rowidlist $row] - while {$idlist ne {}} { - set col [expr {[llength $idlist] - 1}] - set id [lindex $idlist $col] - addextraid $id $row - incr row - set idlist [lreplace $idlist $col $col] - lappend rowidlist $idlist + set id [lindex $displayorder $row] + if {[info exists iddrawn($id)]} { + set need_redisplay 1 } } @@ -3084,27 +3081,29 @@ proc insert_pad {row col npad} { set aft [lreplace $aft $i $i] } lset rowidlist $row [concat $bef $pad $aft] + changedrow $row } proc optimize_rows {row col endrow} { - global rowidlist displayorder curview children + global rowidlist rowisopt displayorder curview children if {$row < 1} { set row 1 } - set idlist [lindex $rowidlist [expr {$row - 1}]] - if {$row >= 2} { - set previdlist [lindex $rowidlist [expr {$row - 2}]] - } else { - set previdlist {} - } - for {} {$row < $endrow} {incr row} { - set pprevidlist $previdlist - set previdlist $idlist - set idlist [lindex $rowidlist $row] + for {} {$row < $endrow} {incr row; set col 0} { + if {[lindex $rowisopt $row]} continue set haspad 0 set y0 [expr {$row - 1}] set ym [expr {$row - 2}] + set idlist [lindex $rowidlist $row] + set previdlist [lindex $rowidlist $y0] + if {$idlist eq {} || $previdlist eq {}} continue + if {$ym >= 0} { + set pprevidlist [lindex $rowidlist $ym] + if {$pprevidlist eq {}} continue + } else { + set pprevidlist {} + } set x0 -1 set xm -1 for {} {$col < [llength $idlist]} {incr col} { @@ -3180,7 +3179,6 @@ proc optimize_rows {row col endrow} { incr x0 optimize_rows $y0 $x0 $row set previdlist [lindex $rowidlist $y0] - set pprevidlist [lindex $rowidlist $ym] } } if {!$haspad} { @@ -3203,10 +3201,10 @@ proc optimize_rows {row col endrow} { # isn't the last column if {$x0 >= 0 && [incr col] < [llength $idlist]} { set idlist [linsert $idlist $col {}] + lset rowidlist $row $idlist + changedrow $row } } - lset rowidlist $row $idlist - set col 0 } } @@ -3531,7 +3529,7 @@ proc drawcmittext {id row col} { global linespc canv canv2 canv3 canvy0 fgcolor curview global commitlisted commitinfo rowidlist parentlist global rowtextx idpos idtags idheads idotherrefs - global linehtag linentag linedtag + global linehtag linentag linedtag selectedline global mainfont canvxmax boldrows boldnamerows fgcolor nullid nullid2 # listed is 0 for boundary, 1 for normal, 2 for left, 3 for right @@ -3607,6 +3605,9 @@ proc drawcmittext {id row col} { -text $name -font $nfont -tags text] set linedtag($row) [$canv3 create text 3 $y -anchor w -fill $fgcolor \ -text $date -font $mainfont -tags text] + if {[info exists selectedline] && $selectedline == $row} { + make_secsel $row + } set xr [expr {$xt + [font measure $mainfont $headline]}] if {$xr > $canvxmax} { set canvxmax $xr @@ -3615,7 +3616,7 @@ proc drawcmittext {id row col} { } proc drawcmitrow {row} { - global displayorder rowidlist + global displayorder rowidlist nrows_drawn global iddrawn markingmatches global commitinfo parentlist numcommits global filehighlight fhighlights findstring nhighlights @@ -3649,6 +3650,7 @@ proc drawcmitrow {row} { assigncolor $id drawcmittext $id $row $col set iddrawn($id) 1 + incr nrows_drawn } if {$markingmatches} { markrowmatches $row $id @@ -3656,8 +3658,8 @@ proc drawcmitrow {row} { } proc drawcommits {row {endrow {}}} { - global numcommits iddrawn displayorder curview - global parentlist rowidlist + global numcommits iddrawn displayorder curview need_redisplay + global parentlist rowidlist uparrowlen downarrowlen nrows_drawn if {$row < 0} { set row 0 @@ -3669,6 +3671,35 @@ proc drawcommits {row {endrow {}}} { set endrow [expr {$numcommits - 1}] } + set rl1 [expr {$row - $downarrowlen - 3}] + if {$rl1 < 0} { + set rl1 0 + } + set ro1 [expr {$row - 3}] + if {$ro1 < 0} { + set ro1 0 + } + set r2 [expr {$endrow + $uparrowlen + 3}] + if {$r2 > $numcommits} { + set r2 $numcommits + } + for {set r $rl1} {$r < $r2} {incr r} { + if {[lindex $rowidlist $r] ne {}} { + if {$rl1 < $r} { + layoutrows $rl1 $r + } + set rl1 [expr {$r + 1}] + } + } + if {$rl1 < $r} { + layoutrows $rl1 $r + } + optimize_rows $ro1 0 $r2 + if {$need_redisplay || $nrows_drawn > 2000} { + clear_display + drawvisible + } + # make the lines join to already-drawn rows either side set r [expr {$row - 1}] if {$r < 0 || ![info exists iddrawn([lindex $displayorder $r])]} { @@ -3736,7 +3767,7 @@ proc drawvisible {} { } proc clear_display {} { - global iddrawn linesegs + global iddrawn linesegs need_redisplay nrows_drawn global vhighlights fhighlights nhighlights rhighlights allcanvs delete all @@ -3746,6 +3777,8 @@ proc clear_display {} { catch {unset fhighlights} catch {unset nhighlights} catch {unset rhighlights} + set need_redisplay 0 + set nrows_drawn 0 } proc findcrossings {id} { @@ -3967,9 +4000,9 @@ proc show_status {msg} { # on that row and below will move down one row. proc insertrow {row newcmit} { global displayorder parentlist commitlisted children - global commitrow curview rowidlist numcommits - global rowlaidout rowoptim numcommits - global selectedline commitidx + global commitrow curview rowidlist rowisopt numcommits + global numcommits + global selectedline commitidx ordertok if {$row >= $numcommits} { puts "oops, inserting new row $row but only have $numcommits rows" @@ -3989,6 +4022,7 @@ proc insertrow {row newcmit} { set commitrow($curview,$id) $r } incr commitidx($curview) + set ordertok($curview,$newcmit) $ordertok($curview,$p) set idlist [lindex $rowidlist $row] if {[llength $kids] == 1} { @@ -3999,9 +4033,8 @@ proc insertrow {row newcmit} { lappend idlist $newcmit } set rowidlist [linsert $rowidlist $row $idlist] + set rowisopt [linsert $rowisopt $row 0] - incr rowlaidout - incr rowoptim incr numcommits if {[info exists selectedline] && $selectedline >= $row} { @@ -4013,8 +4046,8 @@ proc insertrow {row newcmit} { # Remove a commit that was inserted with insertrow on row $row. proc removerow {row} { global displayorder parentlist commitlisted children - global commitrow curview rowidlist numcommits - global rowlaidout rowoptim numcommits + global commitrow curview rowidlist rowisopt numcommits + global numcommits global linesegends selectedline commitidx if {$row >= $numcommits} { @@ -4041,9 +4074,8 @@ proc removerow {row} { incr commitidx($curview) -1 set rowidlist [lreplace $rowidlist $row $row] + set rowisopt [lreplace $rowisopt $row $row] - incr rowlaidout -1 - incr rowoptim -1 incr numcommits -1 if {[info exists selectedline] && $selectedline > $row} { @@ -4485,9 +4517,27 @@ proc dispnexttag {} { } } +proc make_secsel {l} { + global linehtag linentag linedtag canv canv2 canv3 + + if {![info exists linehtag($l)]} return + $canv delete secsel + set t [eval $canv create rect [$canv bbox $linehtag($l)] -outline {{}} \ + -tags secsel -fill [$canv cget -selectbackground]] + $canv lower $t + $canv2 delete secsel + set t [eval $canv2 create rect [$canv2 bbox $linentag($l)] -outline {{}} \ + -tags secsel -fill [$canv2 cget -selectbackground]] + $canv2 lower $t + $canv3 delete secsel + set t [eval $canv3 create rect [$canv3 bbox $linedtag($l)] -outline {{}} \ + -tags secsel -fill [$canv3 cget -selectbackground]] + $canv3 lower $t +} + proc selectline {l isnew} { - global canv canv2 canv3 ctext commitinfo selectedline - global displayorder linehtag linentag linedtag + global canv ctext commitinfo selectedline + global displayorder global canvy0 linespc parentlist children curview global currentid sha1entry global commentend idtags linknum @@ -4536,19 +4586,7 @@ proc selectline {l isnew} { drawvisible } - if {![info exists linehtag($l)]} return - $canv delete secsel - set t [eval $canv create rect [$canv bbox $linehtag($l)] -outline {{}} \ - -tags secsel -fill [$canv cget -selectbackground]] - $canv lower $t - $canv2 delete secsel - set t [eval $canv2 create rect [$canv2 bbox $linentag($l)] -outline {{}} \ - -tags secsel -fill [$canv2 cget -selectbackground]] - $canv2 lower $t - $canv3 delete secsel - set t [eval $canv3 create rect [$canv3 bbox $linedtag($l)] -outline {{}} \ - -tags secsel -fill [$canv3 cget -selectbackground]] - $canv3 lower $t + make_secsel $l if {$isnew} { addtohistory [list selectline $l 0] @@ -5616,7 +5654,7 @@ proc arrowjump {id n y} { } proc lineclick {x y id isnew} { - global ctext commitinfo children canv thickerline curview + global ctext commitinfo children canv thickerline curview commitrow if {![info exists commitinfo($id)] && ![getcommit $id]} return unmarkmatches @@ -7922,8 +7960,8 @@ set boldnamerows {} set diffelide {0 0} set markingmatches 0 set linkentercount 0 - -set optim_delay 16 +set need_redisplay 0 +set nrows_drawn 0 set nextviewnum 1 set curview 0 From df904497ecc15382199045bb257250c857f04eca Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Wed, 29 Aug 2007 22:03:07 +1000 Subject: [PATCH 0009/1490] gitk: Fix bug causing incorrect ref list contents when switching view If the view we're switching to hadn't been read in, we hit an early return in showview which meant we didn't update the ref list window. Signed-off-by: Paul Mackerras --- gitk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gitk b/gitk index 060c4c0cb2..0125f17fcd 100755 --- a/gitk +++ b/gitk @@ -2007,6 +2007,7 @@ proc showview {n} { .bar.view entryconf Edit* -state [expr {$n == 0? "disabled": "normal"}] .bar.view entryconf Delete* -state [expr {$n == 0? "disabled": "normal"}] + run refill_reflist if {![info exists viewdata($n)]} { if {$selid ne {}} { set pending_select $selid @@ -2070,7 +2071,6 @@ proc showview {n} { } elseif {$numcommits == 0} { show_status "No commits selected" } - run refill_reflist } # Stuff relating to the highlighting facility From 6eaaccd12846c5957c3433c773ad60b8a4196045 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Wed, 29 Aug 2007 22:41:34 +1000 Subject: [PATCH 0010/1490] gitk: Fix bug causing undefined variable error when cherry-picking When "Show nearby tags" is turned off and the user did a cherry-pick, we were trying to access variables relating to the descendent/ancestor tag & head computations in addnewchild though they hadn't been set. This makes sure we don't do that. Reported by Johannes Sixt. Signed-off-by: Paul Mackerras --- gitk | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gitk b/gitk index 0125f17fcd..22a6318421 100755 --- a/gitk +++ b/gitk @@ -6648,8 +6648,9 @@ proc splitarc {p} { proc addnewchild {id p} { global allids allparents allchildren idtags nextarc nbmp global arcnos arcids arctags arcout arcend arcstart archeads growing - global seeds + global seeds allcommits + if {![info exists allcommits]} return lappend allids $id set allparents($id) [list $p] set allchildren($id) {} From 5cd15b6b7f87dc61f729ad31a682ffc394560273 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Thu, 30 Aug 2007 21:54:17 +1000 Subject: [PATCH 0011/1490] gitk: Add a cache for the topology info This adds code to write out the topology information used to determine precedes/follows and branch information into a cache file (~3.5MB for the kernel tree). At startup we read the cache file and then do a git rev-list to update it, which is fast because we exclude all commits in the cache that have no children and commits reachable from them (which amounts to everything in the cache). If one of those commits without children no longer exists, then git rev-list will give an error, whereupon we throw away the cache and read in the whole tree again. This gives a significant speedup in the startup time for gitk. Signed-off-by: Paul Mackerras --- gitk | 259 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 237 insertions(+), 22 deletions(-) diff --git a/gitk b/gitk index 22a6318421..251e9242b3 100755 --- a/gitk +++ b/gitk @@ -6445,25 +6445,59 @@ proc refill_reflist {} { # Stuff for finding nearby tags proc getallcommits {} { - global allcommits allids nbmp nextarc seeds + global allcommits nextarc seeds allccache allcwait cachedarcs allcupdate + global idheads idtags idotherrefs allparents tagobjid if {![info exists allcommits]} { - set allids {} - set nbmp 0 set nextarc 0 set allcommits 0 set seeds {} + set allcwait 0 + set cachedarcs 0 + set allccache [file join [gitdir] "gitk.cache"] + if {![catch { + set f [open $allccache r] + set allcwait 1 + getcache $f + }]} return } - set cmd [concat | git rev-list --all --parents] - foreach id $seeds { - lappend cmd "^$id" + if {$allcwait} { + return + } + set cmd [list | git rev-list --parents] + set allcupdate [expr {$seeds ne {}}] + if {!$allcupdate} { + set ids "--all" + } else { + set refs [concat [array names idheads] [array names idtags] \ + [array names idotherrefs]] + set ids {} + set tagobjs {} + foreach name [array names tagobjid] { + lappend tagobjs $tagobjid($name) + } + foreach id [lsort -unique $refs] { + if {![info exists allparents($id)] && + [lsearch -exact $tagobjs $id] < 0} { + lappend ids $id + } + } + if {$ids ne {}} { + foreach id $seeds { + lappend ids "^$id" + } + } + } + if {$ids ne {}} { + set fd [open [concat $cmd $ids] r] + fconfigure $fd -blocking 0 + incr allcommits + nowbusy allcommits + filerun $fd [list getallclines $fd] + } else { + dispneartags 0 } - set fd [open $cmd r] - fconfigure $fd -blocking 0 - incr allcommits - nowbusy allcommits - filerun $fd [list getallclines $fd] } # Since most commits have 1 parent and 1 child, we group strings of @@ -6482,10 +6516,10 @@ proc getallcommits {} { # coming from descendents, and "outgoing" means going towards ancestors. proc getallclines {fd} { - global allids allparents allchildren idtags idheads nextarc nbmp + global allparents allchildren idtags idheads nextarc global arcnos arcids arctags arcout arcend arcstart archeads growing - global seeds allcommits - + global seeds allcommits cachedarcs allcupdate + set nid 0 while {[incr nid] <= 1000 && [gets $fd line] >= 0} { set id [lindex $line 0] @@ -6493,7 +6527,7 @@ proc getallclines {fd} { # seen it already continue } - lappend allids $id + set cachedarcs 0 set olds [lrange $line 1 end] set allparents($id) $olds if {![info exists allchildren($id)]} { @@ -6524,7 +6558,6 @@ proc getallclines {fd} { continue } } - incr nbmp foreach a $arcnos($id) { lappend arcids($a) $id set arcend($a) $id @@ -6564,9 +6597,28 @@ proc getallclines {fd} { if {![eof $fd]} { return [expr {$nid >= 1000? 2: 1}] } - close $fd + set cacheok 1 + if {[catch { + fconfigure $fd -blocking 1 + close $fd + } err]} { + # got an error reading the list of commits + # if we were updating, try rereading the whole thing again + if {$allcupdate} { + incr allcommits -1 + dropcache $err + return + } + error_popup "Error reading commit topology information;\ + branch and preceding/following tag information\ + will be incomplete.\n($err)" + set cacheok 0 + } if {[incr allcommits -1] == 0} { notbusy allcommits + if {$cacheok} { + run savecache + } } dispneartags 0 return 0 @@ -6590,7 +6642,7 @@ proc recalcarc {a} { } proc splitarc {p} { - global arcnos arcids nextarc nbmp arctags archeads idtags idheads + global arcnos arcids nextarc arctags archeads idtags idheads global arcstart arcend arcout allparents growing set a $arcnos($p) @@ -6622,7 +6674,6 @@ proc splitarc {p} { set growing($na) 1 unset growing($a) } - incr nbmp foreach id $tail { if {[llength $arcnos($id)] == 1} { @@ -6646,17 +6697,15 @@ proc splitarc {p} { # Update things for a new commit added that is a child of one # existing commit. Used when cherry-picking. proc addnewchild {id p} { - global allids allparents allchildren idtags nextarc nbmp + global allparents allchildren idtags nextarc global arcnos arcids arctags arcout arcend arcstart archeads growing global seeds allcommits if {![info exists allcommits]} return - lappend allids $id set allparents($id) [list $p] set allchildren($id) {} set arcnos($id) {} lappend seeds $id - incr nbmp lappend allchildren($p) $id set a [incr nextarc] set arcstart($a) $id @@ -6671,6 +6720,172 @@ proc addnewchild {id p} { set arcout($id) [list $a] } +# This implements a cache for the topology information. +# The cache saves, for each arc, the start and end of the arc, +# the ids on the arc, and the outgoing arcs from the end. +proc readcache {f} { + global arcnos arcids arcout arcstart arcend arctags archeads nextarc + global idtags idheads allparents cachedarcs possible_seeds seeds growing + global allcwait + + set a $nextarc + set lim $cachedarcs + if {$lim - $a > 500} { + set lim [expr {$a + 500}] + } + if {[catch { + if {$a == $lim} { + # finish reading the cache and setting up arctags, etc. + set line [gets $f] + if {$line ne "1"} {error "bad final version"} + close $f + foreach id [array names idtags] { + if {[info exists arcnos($id)] && [llength $arcnos($id)] == 1 && + [llength $allparents($id)] == 1} { + set a [lindex $arcnos($id) 0] + if {$arctags($a) eq {}} { + recalcarc $a + } + } + } + foreach id [array names idheads] { + if {[info exists arcnos($id)] && [llength $arcnos($id)] == 1 && + [llength $allparents($id)] == 1} { + set a [lindex $arcnos($id) 0] + if {$archeads($a) eq {}} { + recalcarc $a + } + } + } + foreach id [lsort -unique $possible_seeds] { + if {$arcnos($id) eq {}} { + lappend seeds $id + } + } + set allcwait 0 + } else { + while {[incr a] <= $lim} { + set line [gets $f] + if {[llength $line] != 3} {error "bad line"} + set s [lindex $line 0] + set arcstart($a) $s + lappend arcout($s) $a + if {![info exists arcnos($s)]} { + lappend possible_seeds $s + set arcnos($s) {} + } + set e [lindex $line 1] + if {$e eq {}} { + set growing($a) 1 + } else { + set arcend($a) $e + if {![info exists arcout($e)]} { + set arcout($e) {} + } + } + set arcids($a) [lindex $line 2] + foreach id $arcids($a) { + lappend allparents($s) $id + set s $id + lappend arcnos($id) $a + } + if {![info exists allparents($s)]} { + set allparents($s) {} + } + set arctags($a) {} + set archeads($a) {} + } + set nextarc [expr {$a - 1}] + } + } err]} { + dropcache $err + return 0 + } + if {!$allcwait} { + getallcommits + } + return $allcwait +} + +proc getcache {f} { + global nextarc cachedarcs possible_seeds + + if {[catch { + set line [gets $f] + if {[llength $line] != 2 || [lindex $line 0] ne "1"} {error "bad version"} + # make sure it's an integer + set cachedarcs [expr {int([lindex $line 1])}] + if {$cachedarcs < 0} {error "bad number of arcs"} + set nextarc 0 + set possible_seeds {} + run readcache $f + } err]} { + dropcache $err + } + return 0 +} + +proc dropcache {err} { + global allcwait nextarc cachedarcs seeds + + #puts "dropping cache ($err)" + foreach v {arcnos arcout arcids arcstart arcend growing \ + arctags archeads allparents allchildren} { + global $v + catch {unset $v} + } + set allcwait 0 + set nextarc 0 + set cachedarcs 0 + set seeds {} + getallcommits +} + +proc writecache {f} { + global cachearc cachedarcs allccache + global arcstart arcend arcnos arcids arcout + + set a $cachearc + set lim $cachedarcs + if {$lim - $a > 1000} { + set lim [expr {$a + 1000}] + } + if {[catch { + while {[incr a] <= $lim} { + if {[info exists arcend($a)]} { + puts $f [list $arcstart($a) $arcend($a) $arcids($a)] + } else { + puts $f [list $arcstart($a) {} $arcids($a)] + } + } + } err]} { + catch {close $f} + catch {file delete $allccache} + #puts "writing cache failed ($err)" + return 0 + } + set cachearc [expr {$a - 1}] + if {$a > $cachedarcs} { + puts $f "1" + close $f + return 0 + } + return 1 +} + +proc savecache {} { + global nextarc cachedarcs cachearc allccache + + if {$nextarc == $cachedarcs} return + set cachearc 0 + set cachedarcs $nextarc + catch { + set f [open $allccache w] + puts $f [list 1 $cachedarcs] + run writecache $f + } +} + # Returns 1 if a is an ancestor of b, -1 if b is an ancestor of a, # or 0 if neither is true. proc anc_or_desc {a b} { From fc703c209d415fe20ad5551465b5b68b8ab8b046 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Sat, 1 Sep 2007 21:58:29 -0400 Subject: [PATCH 0012/1490] git-gui: Locate the library directory early during startup To support a localized version of git-gui we need to locate the library directory early so we can initialize Tcl's msgcat package to load translated messages from. This needs to occur before we declare our git-version proc so that errors related to locating git or assessing its version can be reported to the end-user in their preferred language. However we have to keep the library loading until after git-version has been declared, otherwise we will fail to start git-gui if we are using a fake tclIndex that was generated by our Makefile. Signed-off-by: Shawn O. Pearce --- git-gui.sh | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/git-gui.sh b/git-gui.sh index fa30ccc5d6..4ea6e91b01 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -42,6 +42,20 @@ if {[catch {package require Tcl 8.4} err] exit 1 } +###################################################################### +## +## locate our library + +set oguilib {@@GITGUI_LIBDIR@@} +set oguirel {@@GITGUI_RELATIVE@@} +if {$oguirel eq {1}} { + set oguilib [file dirname [file dirname [file normalize $argv0]]] + set oguilib [file join $oguilib share git-gui lib] +} elseif {[string match @@* $oguirel]} { + set oguilib [file join [file dirname [file normalize $argv0]] lib] +} +unset oguirel + ###################################################################### ## ## enable verbose loading? @@ -595,15 +609,6 @@ You are using [git-version]: ## ## configure our library -set oguilib {@@GITGUI_LIBDIR@@} -set oguirel {@@GITGUI_RELATIVE@@} -if {$oguirel eq {1}} { - set oguilib [file dirname [file dirname [file normalize $argv0]]] - set oguilib [file join $oguilib share git-gui lib] -} elseif {[string match @@* $oguirel]} { - set oguilib [file join [file dirname [file normalize $argv0]] lib] -} - set idx [file join $oguilib tclIndex] if {[catch {set fd [open $idx r]} err]} { catch {wm withdraw .} @@ -637,7 +642,7 @@ if {$idx ne {}} { } else { set auto_path [concat [list $oguilib] $auto_path] } -unset -nocomplain oguirel idx fd +unset -nocomplain idx fd ###################################################################### ## From d4b0ccd931cc29f35e8f8493445af27ea72ed03e Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Sat, 1 Sep 2007 22:22:42 -0400 Subject: [PATCH 0013/1490] git-gui: Initialize Tcl's msgcat library for internationalization Tcl's msgcat library and corresponding mc procedure can locate a translated string for any user message, provided that it is first given a directory where the *.msg files are located containing the translations. During installation we will place the translations in lib/msgs/, so we need to inform msgcat of this location once we determine it during startup. Our source code tree however will store all of the translations within the po/ directory, so we need to special case this variant. Signed-off-by: Shawn O. Pearce --- git-gui.sh | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/git-gui.sh b/git-gui.sh index 4ea6e91b01..486d36ee19 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -51,8 +51,12 @@ set oguirel {@@GITGUI_RELATIVE@@} if {$oguirel eq {1}} { set oguilib [file dirname [file dirname [file normalize $argv0]]] set oguilib [file join $oguilib share git-gui lib] + set oguimsg [file join $oguilib msgs] } elseif {[string match @@* $oguirel]} { set oguilib [file join [file dirname [file normalize $argv0]] lib] + set oguimsg [file join [file dirname [file normalize $argv0]] po] +} else { + set oguimsg [file join $oguilib msgs] } unset oguirel @@ -74,6 +78,16 @@ if {![catch {set _verbose $env(GITGUI_VERBOSE)}]} { } } +###################################################################### +## +## Internationalization (i18n) through msgcat and gettext. See +## http://www.gnu.org/software/gettext/manual/html_node/Tcl.html + +package require msgcat +namespace import ::msgcat::mc +::msgcat::mcload $oguimsg +unset oguimsg + ###################################################################### ## ## read only globals From 1ac17950e93a956d01b042db3de70010195eddcc Mon Sep 17 00:00:00 2001 From: Christian Stimming Date: Sat, 21 Jul 2007 14:21:34 +0200 Subject: [PATCH 0014/1490] Mark strings for translation. The procedure [mc ...] will translate the strings through msgcat. Strings must be enclosed in quotes, not in braces, because otherwise xgettext cannot extract them properly, although on the Tcl side both delimiters would work fine. [jes: I merged the later patches to that end.] Signed-off-by: Christian Stimming Signed-off-by: Johannes Schindelin --- git-gui.sh | 257 ++++++++++++++++++----------------- lib/blame.tcl | 10 +- lib/branch_checkout.tcl | 16 +-- lib/branch_create.tcl | 38 +++--- lib/branch_delete.tcl | 22 ++- lib/branch_rename.tcl | 22 +-- lib/browser.tcl | 22 +-- lib/checkout_op.tcl | 48 +++---- lib/choose_rev.tcl | 16 +-- lib/commit.tcl | 52 +++---- lib/console.tcl | 14 +- lib/database.tcl | 28 ++-- lib/diff.tcl | 16 +-- lib/error.tcl | 8 +- lib/index.tcl | 23 +++- lib/merge.tcl | 60 ++++---- lib/option.tcl | 45 +++--- lib/remote.tcl | 6 +- lib/remote_branch_delete.tcl | 42 +++--- lib/shortcut.tcl | 12 +- lib/status_bar.tcl | 2 +- lib/transport.tcl | 30 ++-- 22 files changed, 397 insertions(+), 392 deletions(-) diff --git a/git-gui.sh b/git-gui.sh index 486d36ee19..913ba68101 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -502,7 +502,7 @@ proc tk_optionMenu {w varName args} { set _git [_which git] if {$_git eq {}} { catch {wm withdraw .} - error_popup "Cannot find git in PATH." + error_popup [mc "Cannot find git in PATH."] exit 1 } @@ -529,7 +529,7 @@ if {![regsub {^git version } $_git_version {} _git_version]} { -icon error \ -type ok \ -title "git-gui: fatal error" \ - -message "Cannot parse Git version string:\n\n$_git_version" + -message [append [mc "Cannot parse Git version string:"] "\n\n$_git_version"] exit 1 } @@ -546,14 +546,14 @@ if {![regexp {^[1-9]+(\.[0-9]+)+$} $_git_version]} { -type yesno \ -default no \ -title "[appname]: warning" \ - -message "Git version cannot be determined. + -message [mc "Git version cannot be determined. -$_git claims it is version '$_real_git_version'. +%s claims it is version '%s'. -[appname] requires at least Git 1.5.0 or later. +%s requires at least Git 1.5.0 or later. -Assume '$_real_git_version' is version 1.5.0? -"] eq {yes}} { +Assume '%s' is version 1.5.0? +" $_git $_real_git_version [appname] $_real_git_version]] eq {yes}} { set _git_version 1.5.0 } else { exit 1 @@ -711,7 +711,7 @@ if {[catch { set _prefix [git rev-parse --show-prefix] } err]} { catch {wm withdraw .} - error_popup "Cannot find the git directory:\n\n$err" + error_popup [append [mc "Cannot find the git directory:"] "\n\n$err"] exit 1 } if {![file isdirectory $_gitdir] && [is_Cygwin]} { @@ -719,7 +719,7 @@ if {![file isdirectory $_gitdir] && [is_Cygwin]} { } if {![file isdirectory $_gitdir]} { catch {wm withdraw .} - error_popup "Git directory not found:\n\n$_gitdir" + error_popup [append [mc "Git directory not found:"] "\n\n$_gitdir"] exit 1 } if {$_prefix ne {}} { @@ -733,12 +733,12 @@ if {$_prefix ne {}} { } elseif {![is_enabled bare]} { if {[lindex [file split $_gitdir] end] ne {.git}} { catch {wm withdraw .} - error_popup "Cannot use funny .git directory:\n\n$_gitdir" + error_popup [append [mc "Cannot use funny .git directory:"] "\n\n$_gitdir"] exit 1 } if {[catch {cd [file dirname $_gitdir]} err]} { catch {wm withdraw .} - error_popup "No working directory [file dirname $_gitdir]:\n\n$err" + error_popup [append [mc "No working directory"] " [file dirname $_gitdir]:\n\n$err"] exit 1 } } @@ -885,7 +885,7 @@ proc rescan {after {honor_trustmtime 1}} { rescan_stage2 {} $after } else { set rescan_active 1 - ui_status {Refreshing file status...} + ui_status [mc "Refreshing file status..."] set fd_rf [git_read update-index \ -q \ --unmerged \ @@ -922,7 +922,7 @@ proc rescan_stage2 {fd after} { set buf_rlo {} set rescan_active 3 - ui_status {Scanning for modified files ...} + ui_status [mc "Scanning for modified files ..."] set fd_di [git_read diff-index --cached -z [PARENT]] set fd_df [git_read diff-files -z] set fd_lo [eval git_read ls-files --others -z $ls_others] @@ -1088,7 +1088,7 @@ proc ui_status {msg} { } proc ui_ready {{test {}}} { - $::main_status show {Ready.} $test + $::main_status show [mc "Ready."] $test } proc escape_path {path} { @@ -1353,31 +1353,32 @@ set all_icons(O$ui_workdir) file_plain set max_status_desc 0 foreach i { - {__ "Unmodified"} + {__ {mc "Unmodified"}} - {_M "Modified, not staged"} - {M_ "Staged for commit"} - {MM "Portions staged for commit"} - {MD "Staged for commit, missing"} + {_M {mc "Modified, not staged"}} + {M_ {mc "Staged for commit"}} + {MM {mc "Portions staged for commit"}} + {MD {mc "Staged for commit, missing"}} - {_O "Untracked, not staged"} - {A_ "Staged for commit"} - {AM "Portions staged for commit"} - {AD "Staged for commit, missing"} + {_O {mc "Untracked, not staged"}} + {A_ {mc "Staged for commit"}} + {AM {mc "Portions staged for commit"}} + {AD {mc "Staged for commit, missing"}} - {_D "Missing"} - {D_ "Staged for removal"} - {DO "Staged for removal, still present"} + {_D {mc "Missing"}} + {D_ {mc "Staged for removal"}} + {DO {mc "Staged for removal, still present"}} - {U_ "Requires merge resolution"} - {UU "Requires merge resolution"} - {UM "Requires merge resolution"} - {UD "Requires merge resolution"} + {U_ {mc "Requires merge resolution"}} + {UU {mc "Requires merge resolution"}} + {UM {mc "Requires merge resolution"}} + {UD {mc "Requires merge resolution"}} } { - if {$max_status_desc < [string length [lindex $i 1]]} { - set max_status_desc [string length [lindex $i 1]] + set text [eval [lindex $i 1]] + if {$max_status_desc < [string length $text]} { + set max_status_desc [string length $text] } - set all_descs([lindex $i 0]) [lindex $i 1] + set all_descs([lindex $i 0]) $text } unset i @@ -1416,7 +1417,7 @@ proc incr_font_size {font {amt 1}} { ## ## ui commands -set starting_gitk_msg {Starting gitk... please wait...} +set starting_gitk_msg [mc "Starting gitk... please wait..."] proc do_gitk {revs} { # -- Always start gitk through whatever we were loaded with. This @@ -1425,7 +1426,7 @@ proc do_gitk {revs} { set exe [file join [file dirname $::_git] gitk] set cmd [list [info nameofexecutable] $exe] if {! [file exists $exe]} { - error_popup "Unable to start gitk:\n\n$exe does not exist" + error_popup [mc "Unable to start gitk:\n\n%s does not exist" $exe] } else { eval exec $cmd $revs & ui_status $::starting_gitk_msg @@ -1642,7 +1643,7 @@ proc apply_config {} { font configure $font $cn $cv } } err]} { - error_popup "Invalid font specified in gui.$name:\n\n$err" + error_popup [append [mc "Invalid font specified in gui.%s:" $name] "\n\n$err"] } foreach {cn cv} [font configure $font] { font configure ${font}bold $cn $cv @@ -1667,8 +1668,8 @@ set default_config(gui.newbranchtemplate) {} set default_config(gui.fontui) [font configure font_ui] set default_config(gui.fontdiff) [font configure font_diff] set font_descs { - {fontui font_ui {Main Font}} - {fontdiff font_diff {Diff/Console Font}} + {fontui font_ui {mc "Main Font"}} + {fontdiff font_diff {mc "Diff/Console Font"}} } load_config 0 apply_config @@ -1682,18 +1683,18 @@ set ui_comm {} # -- Menu Bar # menu .mbar -tearoff 0 -.mbar add cascade -label Repository -menu .mbar.repository -.mbar add cascade -label Edit -menu .mbar.edit +.mbar add cascade -label [mc Repository] -menu .mbar.repository +.mbar add cascade -label [mc Edit] -menu .mbar.edit if {[is_enabled branch]} { - .mbar add cascade -label Branch -menu .mbar.branch + .mbar add cascade -label [mc Branch] -menu .mbar.branch } if {[is_enabled multicommit] || [is_enabled singlecommit]} { - .mbar add cascade -label Commit -menu .mbar.commit + .mbar add cascade -label [mc Commit] -menu .mbar.commit } if {[is_enabled transport]} { - .mbar add cascade -label Merge -menu .mbar.merge - .mbar add cascade -label Fetch -menu .mbar.fetch - .mbar add cascade -label Push -menu .mbar.push + .mbar add cascade -label [mc Merge] -menu .mbar.merge + .mbar add cascade -label [mc Fetch] -menu .mbar.fetch + .mbar add cascade -label [mc Push] -menu .mbar.push } . configure -menu .mbar @@ -1702,87 +1703,87 @@ if {[is_enabled transport]} { menu .mbar.repository .mbar.repository add command \ - -label {Browse Current Branch's Files} \ + -label [mc "Browse Current Branch's Files"] \ -command {browser::new $current_branch} set ui_browse_current [.mbar.repository index last] .mbar.repository add command \ - -label {Browse Branch Files...} \ + -label [mc "Browse Branch Files..."] \ -command browser_open::dialog .mbar.repository add separator .mbar.repository add command \ - -label {Visualize Current Branch's History} \ + -label [mc "Visualize Current Branch's History"] \ -command {do_gitk $current_branch} set ui_visualize_current [.mbar.repository index last] .mbar.repository add command \ - -label {Visualize All Branch History} \ + -label [mc "Visualize All Branch History"] \ -command {do_gitk --all} .mbar.repository add separator proc current_branch_write {args} { global current_branch .mbar.repository entryconf $::ui_browse_current \ - -label "Browse $current_branch's Files" + -label [mc "Browse %s's Files" $current_branch] .mbar.repository entryconf $::ui_visualize_current \ - -label "Visualize $current_branch's History" + -label [mc "Visualize %s's History" $current_branch] } trace add variable current_branch write current_branch_write if {[is_enabled multicommit]} { - .mbar.repository add command -label {Database Statistics} \ + .mbar.repository add command -label [mc "Database Statistics"] \ -command do_stats - .mbar.repository add command -label {Compress Database} \ + .mbar.repository add command -label [mc "Compress Database"] \ -command do_gc - .mbar.repository add command -label {Verify Database} \ + .mbar.repository add command -label [mc "Verify Database"] \ -command do_fsck_objects .mbar.repository add separator if {[is_Cygwin]} { .mbar.repository add command \ - -label {Create Desktop Icon} \ + -label [mc "Create Desktop Icon"] \ -command do_cygwin_shortcut } elseif {[is_Windows]} { .mbar.repository add command \ - -label {Create Desktop Icon} \ + -label [mc "Create Desktop Icon"] \ -command do_windows_shortcut } elseif {[is_MacOSX]} { .mbar.repository add command \ - -label {Create Desktop Icon} \ + -label [mc "Create Desktop Icon"] \ -command do_macosx_app } } -.mbar.repository add command -label Quit \ +.mbar.repository add command -label [mc Quit] \ -command do_quit \ -accelerator $M1T-Q # -- Edit Menu # menu .mbar.edit -.mbar.edit add command -label Undo \ +.mbar.edit add command -label [mc Undo] \ -command {catch {[focus] edit undo}} \ -accelerator $M1T-Z -.mbar.edit add command -label Redo \ +.mbar.edit add command -label [mc Redo] \ -command {catch {[focus] edit redo}} \ -accelerator $M1T-Y .mbar.edit add separator -.mbar.edit add command -label Cut \ +.mbar.edit add command -label [mc Cut] \ -command {catch {tk_textCut [focus]}} \ -accelerator $M1T-X -.mbar.edit add command -label Copy \ +.mbar.edit add command -label [mc Copy] \ -command {catch {tk_textCopy [focus]}} \ -accelerator $M1T-C -.mbar.edit add command -label Paste \ +.mbar.edit add command -label [mc Paste] \ -command {catch {tk_textPaste [focus]; [focus] see insert}} \ -accelerator $M1T-V -.mbar.edit add command -label Delete \ +.mbar.edit add command -label [mc Delete] \ -command {catch {[focus] delete sel.first sel.last}} \ -accelerator Del .mbar.edit add separator -.mbar.edit add command -label {Select All} \ +.mbar.edit add command -label [mc "Select All"] \ -command {catch {[focus] tag add sel 0.0 end}} \ -accelerator $M1T-A @@ -1791,29 +1792,29 @@ menu .mbar.edit if {[is_enabled branch]} { menu .mbar.branch - .mbar.branch add command -label {Create...} \ + .mbar.branch add command -label [mc "Create..."] \ -command branch_create::dialog \ -accelerator $M1T-N lappend disable_on_lock [list .mbar.branch entryconf \ [.mbar.branch index last] -state] - .mbar.branch add command -label {Checkout...} \ + .mbar.branch add command -label [mc "Checkout..."] \ -command branch_checkout::dialog \ -accelerator $M1T-O lappend disable_on_lock [list .mbar.branch entryconf \ [.mbar.branch index last] -state] - .mbar.branch add command -label {Rename...} \ + .mbar.branch add command -label [mc "Rename..."] \ -command branch_rename::dialog lappend disable_on_lock [list .mbar.branch entryconf \ [.mbar.branch index last] -state] - .mbar.branch add command -label {Delete...} \ + .mbar.branch add command -label [mc "Delete..."] \ -command branch_delete::dialog lappend disable_on_lock [list .mbar.branch entryconf \ [.mbar.branch index last] -state] - .mbar.branch add command -label {Reset...} \ + .mbar.branch add command -label [mc "Reset..."] \ -command merge::reset_hard lappend disable_on_lock [list .mbar.branch entryconf \ [.mbar.branch index last] -state] @@ -1825,7 +1826,7 @@ if {[is_enabled multicommit] || [is_enabled singlecommit]} { menu .mbar.commit .mbar.commit add radiobutton \ - -label {New Commit} \ + -label [mc "New Commit"] \ -command do_select_commit_type \ -variable selected_commit_type \ -value new @@ -1833,7 +1834,7 @@ if {[is_enabled multicommit] || [is_enabled singlecommit]} { [list .mbar.commit entryconf [.mbar.commit index last] -state] .mbar.commit add radiobutton \ - -label {Amend Last Commit} \ + -label [mc "Amend Last Commit"] \ -command do_select_commit_type \ -variable selected_commit_type \ -value amend @@ -1842,40 +1843,40 @@ if {[is_enabled multicommit] || [is_enabled singlecommit]} { .mbar.commit add separator - .mbar.commit add command -label Rescan \ + .mbar.commit add command -label [mc Rescan] \ -command do_rescan \ -accelerator F5 lappend disable_on_lock \ [list .mbar.commit entryconf [.mbar.commit index last] -state] - .mbar.commit add command -label {Stage To Commit} \ + .mbar.commit add command -label [mc "Stage To Commit"] \ -command do_add_selection lappend disable_on_lock \ [list .mbar.commit entryconf [.mbar.commit index last] -state] - .mbar.commit add command -label {Stage Changed Files To Commit} \ + .mbar.commit add command -label [mc "Stage Changed Files To Commit"] \ -command do_add_all \ -accelerator $M1T-I lappend disable_on_lock \ [list .mbar.commit entryconf [.mbar.commit index last] -state] - .mbar.commit add command -label {Unstage From Commit} \ + .mbar.commit add command -label [mc "Unstage From Commit"] \ -command do_unstage_selection lappend disable_on_lock \ [list .mbar.commit entryconf [.mbar.commit index last] -state] - .mbar.commit add command -label {Revert Changes} \ + .mbar.commit add command -label [mc "Revert Changes"] \ -command do_revert_selection lappend disable_on_lock \ [list .mbar.commit entryconf [.mbar.commit index last] -state] .mbar.commit add separator - .mbar.commit add command -label {Sign Off} \ + .mbar.commit add command -label [mc "Sign Off"] \ -command do_signoff \ -accelerator $M1T-S - .mbar.commit add command -label Commit \ + .mbar.commit add command -label [mc Commit] \ -command do_commit \ -accelerator $M1T-Return lappend disable_on_lock \ @@ -1886,12 +1887,12 @@ if {[is_enabled multicommit] || [is_enabled singlecommit]} { # if {[is_enabled branch]} { menu .mbar.merge - .mbar.merge add command -label {Local Merge...} \ + .mbar.merge add command -label [mc "Local Merge..."] \ -command merge::dialog \ -accelerator $M1T-M lappend disable_on_lock \ [list .mbar.merge entryconf [.mbar.merge index last] -state] - .mbar.merge add command -label {Abort Merge...} \ + .mbar.merge add command -label [mc "Abort Merge..."] \ -command merge::reset_hard lappend disable_on_lock \ [list .mbar.merge entryconf [.mbar.merge index last] -state] @@ -1903,38 +1904,38 @@ if {[is_enabled transport]} { menu .mbar.fetch menu .mbar.push - .mbar.push add command -label {Push...} \ + .mbar.push add command -label [mc "Push..."] \ -command do_push_anywhere \ -accelerator $M1T-P - .mbar.push add command -label {Delete...} \ + .mbar.push add command -label [mc "Delete..."] \ -command remote_branch_delete::dialog } if {[is_MacOSX]} { # -- Apple Menu (Mac OS X only) # - .mbar add cascade -label Apple -menu .mbar.apple + .mbar add cascade -label [mc Apple] -menu .mbar.apple menu .mbar.apple - .mbar.apple add command -label "About [appname]" \ + .mbar.apple add command -label [mc "About %s" [appname]] \ -command do_about - .mbar.apple add command -label "Options..." \ + .mbar.apple add command -label [mc "Options..."] \ -command do_options } else { # -- Edit Menu # .mbar.edit add separator - .mbar.edit add command -label {Options...} \ + .mbar.edit add command -label [mc "Options..."] \ -command do_options } # -- Help Menu # -.mbar add cascade -label Help -menu .mbar.help +.mbar add cascade -label [mc Help] -menu .mbar.help menu .mbar.help if {![is_MacOSX]} { - .mbar.help add command -label "About [appname]" \ + .mbar.help add command -label [mc "About %s" [appname]] \ -command do_about } @@ -1971,7 +1972,7 @@ if {[file isfile $doc_path]} { } if {$browser ne {}} { - .mbar.help add command -label {Online Documentation} \ + .mbar.help add command -label [mc "Online Documentation"] \ -command [list exec $browser $doc_url &] } unset browser doc_path doc_url @@ -2093,7 +2094,7 @@ frame .branch \ -borderwidth 1 \ -relief sunken label .branch.l1 \ - -text {Current Branch:} \ + -text [mc "Current Branch:"] \ -anchor w \ -justify left label .branch.cb \ @@ -2114,7 +2115,7 @@ pack .vpane -anchor n -side top -fill both -expand 1 # -- Index File List # frame .vpane.files.index -height 100 -width 200 -label .vpane.files.index.title -text {Staged Changes (Will Be Committed)} \ +label .vpane.files.index.title -text [mc "Staged Changes (Will Be Committed)"] \ -background lightgreen text $ui_index -background white -borderwidth 0 \ -width 20 -height 10 \ @@ -2134,7 +2135,7 @@ pack $ui_index -side left -fill both -expand 1 # -- Working Directory File List # frame .vpane.files.workdir -height 100 -width 200 -label .vpane.files.workdir.title -text {Unstaged Changes (Will Not Be Committed)} \ +label .vpane.files.workdir.title -text [mc "Unstaged Changes (Will Not Be Committed)"] \ -background lightsalmon text $ui_workdir -background white -borderwidth 0 \ -width 20 -height 10 \ @@ -2175,29 +2176,29 @@ label .vpane.lower.commarea.buttons.l -text {} \ pack .vpane.lower.commarea.buttons.l -side top -fill x pack .vpane.lower.commarea.buttons -side left -fill y -button .vpane.lower.commarea.buttons.rescan -text {Rescan} \ +button .vpane.lower.commarea.buttons.rescan -text [mc Rescan] \ -command do_rescan pack .vpane.lower.commarea.buttons.rescan -side top -fill x lappend disable_on_lock \ {.vpane.lower.commarea.buttons.rescan conf -state} -button .vpane.lower.commarea.buttons.incall -text {Stage Changed} \ +button .vpane.lower.commarea.buttons.incall -text [mc "Stage Changed"] \ -command do_add_all pack .vpane.lower.commarea.buttons.incall -side top -fill x lappend disable_on_lock \ {.vpane.lower.commarea.buttons.incall conf -state} -button .vpane.lower.commarea.buttons.signoff -text {Sign Off} \ +button .vpane.lower.commarea.buttons.signoff -text [mc "Sign Off"] \ -command do_signoff pack .vpane.lower.commarea.buttons.signoff -side top -fill x -button .vpane.lower.commarea.buttons.commit -text {Commit} \ +button .vpane.lower.commarea.buttons.commit -text [mc Commit] \ -command do_commit pack .vpane.lower.commarea.buttons.commit -side top -fill x lappend disable_on_lock \ {.vpane.lower.commarea.buttons.commit conf -state} -button .vpane.lower.commarea.buttons.push -text {Push} \ +button .vpane.lower.commarea.buttons.push -text [mc Push] \ -command do_push_anywhere pack .vpane.lower.commarea.buttons.push -side top -fill x @@ -2208,14 +2209,14 @@ frame .vpane.lower.commarea.buffer.header set ui_comm .vpane.lower.commarea.buffer.t set ui_coml .vpane.lower.commarea.buffer.header.l radiobutton .vpane.lower.commarea.buffer.header.new \ - -text {New Commit} \ + -text [mc "New Commit"] \ -command do_select_commit_type \ -variable selected_commit_type \ -value new lappend disable_on_lock \ [list .vpane.lower.commarea.buffer.header.new conf -state] radiobutton .vpane.lower.commarea.buffer.header.amend \ - -text {Amend Last Commit} \ + -text [mc "Amend Last Commit"] \ -command do_select_commit_type \ -variable selected_commit_type \ -value amend @@ -2227,12 +2228,12 @@ label $ui_coml \ proc trace_commit_type {varname args} { global ui_coml commit_type switch -glob -- $commit_type { - initial {set txt {Initial Commit Message:}} - amend {set txt {Amended Commit Message:}} - amend-initial {set txt {Amended Initial Commit Message:}} - amend-merge {set txt {Amended Merge Commit Message:}} - merge {set txt {Merge Commit Message:}} - * {set txt {Commit Message:}} + initial {set txt [mc "Initial Commit Message:"]} + amend {set txt [mc "Amended Commit Message:"]} + amend-initial {set txt [mc "Amended Initial Commit Message:"]} + amend-merge {set txt [mc "Amended Merge Commit Message:"]} + merge {set txt [mc "Merge Commit Message:"]} + * {set txt [mc "Commit Message:"]} } $ui_coml conf -text $txt } @@ -2261,23 +2262,23 @@ pack .vpane.lower.commarea.buffer -side left -fill y set ctxm .vpane.lower.commarea.buffer.ctxm menu $ctxm -tearoff 0 $ctxm add command \ - -label {Cut} \ + -label [mc Cut] \ -command {tk_textCut $ui_comm} $ctxm add command \ - -label {Copy} \ + -label [mc Copy] \ -command {tk_textCopy $ui_comm} $ctxm add command \ - -label {Paste} \ + -label [mc Paste] \ -command {tk_textPaste $ui_comm} $ctxm add command \ - -label {Delete} \ + -label [mc Delete] \ -command {$ui_comm delete sel.first sel.last} $ctxm add separator $ctxm add command \ - -label {Select All} \ + -label [mc "Select All"] \ -command {focus $ui_comm;$ui_comm tag add sel 0.0 end} $ctxm add command \ - -label {Copy All} \ + -label [mc "Copy All"] \ -command { $ui_comm tag add sel 0.0 end tk_textCopy $ui_comm @@ -2285,7 +2286,7 @@ $ctxm add command \ } $ctxm add separator $ctxm add command \ - -label {Sign Off} \ + -label [mc "Sign Off"] \ -command do_signoff bind_button3 $ui_comm "tk_popup $ctxm %X %Y" @@ -2301,7 +2302,7 @@ proc trace_current_diff_path {varname args} { } else { set p $current_diff_path set s [mapdesc [lindex $file_states($p) 0] $p] - set f {File:} + set f [mc "File:"] set p [escape_path $p] set o normal } @@ -2335,7 +2336,7 @@ pack .vpane.lower.diff.header.path -fill x set ctxm .vpane.lower.diff.header.ctxm menu $ctxm -tearoff 0 $ctxm add command \ - -label {Copy} \ + -label [mc Copy] \ -command { clipboard clear clipboard append \ @@ -2403,19 +2404,19 @@ $ui_diff tag raise sel set ctxm .vpane.lower.diff.body.ctxm menu $ctxm -tearoff 0 $ctxm add command \ - -label {Refresh} \ + -label [mc Refresh] \ -command reshow_diff lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state] $ctxm add command \ - -label {Copy} \ + -label [mc Copy] \ -command {tk_textCopy $ui_diff} lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state] $ctxm add command \ - -label {Select All} \ + -label [mc "Select All"] \ -command {focus $ui_diff;$ui_diff tag add sel 0.0 end} lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state] $ctxm add command \ - -label {Copy All} \ + -label [mc "Copy All"] \ -command { $ui_diff tag add sel 0.0 end tk_textCopy $ui_diff @@ -2424,36 +2425,36 @@ $ctxm add command \ lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state] $ctxm add separator $ctxm add command \ - -label {Apply/Reverse Hunk} \ + -label [mc "Apply/Reverse Hunk"] \ -command {apply_hunk $cursorX $cursorY} set ui_diff_applyhunk [$ctxm index last] lappend diff_actions [list $ctxm entryconf $ui_diff_applyhunk -state] $ctxm add separator $ctxm add command \ - -label {Decrease Font Size} \ + -label [mc "Decrease Font Size"] \ -command {incr_font_size font_diff -1} lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state] $ctxm add command \ - -label {Increase Font Size} \ + -label [mc "Increase Font Size"] \ -command {incr_font_size font_diff 1} lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state] $ctxm add separator $ctxm add command \ - -label {Show Less Context} \ + -label [mc "Show Less Context"] \ -command {if {$repo_config(gui.diffcontext) >= 1} { incr repo_config(gui.diffcontext) -1 reshow_diff }} lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state] $ctxm add command \ - -label {Show More Context} \ + -label [mc "Show More Context"] \ -command {if {$repo_config(gui.diffcontext) < 99} { incr repo_config(gui.diffcontext) reshow_diff }} lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state] $ctxm add separator -$ctxm add command -label {Options...} \ +$ctxm add command -label [mc "Options..."] \ -command do_options proc popup_diff_menu {ctxm x y X Y} { global current_diff_path file_states @@ -2461,7 +2462,7 @@ proc popup_diff_menu {ctxm x y X Y} { set ::cursorY $y if {$::ui_index eq $::current_diff_side} { set s normal - set l "Unstage Hunk From Commit" + set l [mc "Unstage Hunk From Commit"] } else { if {$current_diff_path eq {} || ![info exists file_states($current_diff_path)] @@ -2470,7 +2471,7 @@ proc popup_diff_menu {ctxm x y X Y} { } else { set s normal } - set l "Stage Hunk For Commit" + set l [mc "Stage Hunk For Commit"] } if {$::is_3way_diff} { set s disabled @@ -2484,7 +2485,7 @@ bind_button3 $ui_diff [list popup_diff_menu $ctxm %x %y %X %Y] # set main_status [::status_bar::new .status] pack .status -anchor w -side bottom -fill x -$main_status show {Initializing...} +$main_status show [mc "Initializing..."] # -- Load geometry # diff --git a/lib/blame.tcl b/lib/blame.tcl index 96072847a2..b5fdad5643 100644 --- a/lib/blame.tcl +++ b/lib/blame.tcl @@ -74,11 +74,11 @@ constructor new {i_commit i_path} { set path $i_path make_toplevel top w - wm title $top "[appname] ([reponame]): File Viewer" + wm title $top [append "[appname] ([reponame]): " [mc "File Viewer"]] frame $w.header -background gold label $w.header.commit_l \ - -text {Commit:} \ + -text [mc "Commit:"] \ -background gold \ -anchor w \ -justify left @@ -101,7 +101,7 @@ constructor new {i_commit i_path} { -anchor w \ -justify left label $w.header.path_l \ - -text {File:} \ + -text [mc "File:"] \ -background gold \ -anchor w \ -justify left @@ -246,7 +246,7 @@ constructor new {i_commit i_path} { menu $w.ctxm -tearoff 0 $w.ctxm add command \ - -label "Copy Commit" \ + -label [mc "Copy Commit"] \ -command [cb _copycommit] foreach i $w_columns { @@ -366,7 +366,7 @@ method _load {jump} { set amov_data [list [list]] set asim_data [list [list]] - $status show "Reading $commit:[escape_path $path]..." + $status show [mc "Reading %s..." "$commit:[escape_path $path]"] $w_path conf -text [escape_path $path] if {$commit eq {}} { set fd [open $path r] diff --git a/lib/branch_checkout.tcl b/lib/branch_checkout.tcl index 72c45b4554..6603703ea1 100644 --- a/lib/branch_checkout.tcl +++ b/lib/branch_checkout.tcl @@ -11,37 +11,37 @@ field opt_detach 0; # force a detached head case? constructor dialog {} { make_toplevel top w - wm title $top "[appname] ([reponame]): Checkout Branch" + wm title $top [append "[appname] ([reponame]): " [mc "Checkout Branch"]] if {$top ne {.}} { wm geometry $top "+[winfo rootx .]+[winfo rooty .]" } - label $w.header -text {Checkout Branch} -font font_uibold + label $w.header -text [mc "Checkout Branch"] -font font_uibold pack $w.header -side top -fill x frame $w.buttons - button $w.buttons.create -text Checkout \ + button $w.buttons.create -text [mc Checkout] \ -default active \ -command [cb _checkout] pack $w.buttons.create -side right - button $w.buttons.cancel -text {Cancel} \ + button $w.buttons.cancel -text [mc Cancel] \ -command [list destroy $w] pack $w.buttons.cancel -side right -padx 5 pack $w.buttons -side bottom -fill x -pady 10 -padx 10 - set w_rev [::choose_rev::new $w.rev {Revision}] + set w_rev [::choose_rev::new $w.rev [mc Revision]] $w_rev bind_listbox [cb _checkout] pack $w.rev -anchor nw -fill both -expand 1 -pady 5 -padx 5 - labelframe $w.options -text {Options} + labelframe $w.options -text [mc Options] checkbutton $w.options.fetch \ - -text {Fetch Tracking Branch} \ + -text [mc "Fetch Tracking Branch"] \ -variable @opt_fetch pack $w.options.fetch -anchor nw checkbutton $w.options.detach \ - -text {Detach From Local Branch} \ + -text [mc "Detach From Local Branch"] \ -variable @opt_detach pack $w.options.detach -anchor nw diff --git a/lib/branch_create.tcl b/lib/branch_create.tcl index def615d19d..53dfb4ce6b 100644 --- a/lib/branch_create.tcl +++ b/lib/branch_create.tcl @@ -19,28 +19,28 @@ constructor dialog {} { global repo_config make_toplevel top w - wm title $top "[appname] ([reponame]): Create Branch" + wm title $top [append "[appname] ([reponame]): " [mc "Create Branch"]] if {$top ne {.}} { wm geometry $top "+[winfo rootx .]+[winfo rooty .]" } - label $w.header -text {Create New Branch} -font font_uibold + label $w.header -text [mc "Create New Branch"] -font font_uibold pack $w.header -side top -fill x frame $w.buttons - button $w.buttons.create -text Create \ + button $w.buttons.create -text [mc Create] \ -default active \ -command [cb _create] pack $w.buttons.create -side right - button $w.buttons.cancel -text {Cancel} \ + button $w.buttons.cancel -text [mc Cancel] \ -command [list destroy $w] pack $w.buttons.cancel -side right -padx 5 pack $w.buttons -side bottom -fill x -pady 10 -padx 10 - labelframe $w.desc -text {Branch Name} + labelframe $w.desc -text [mc "Branch Name"] radiobutton $w.desc.name_r \ -anchor w \ - -text {Name:} \ + -text [mc "Name:"] \ -value user \ -variable @name_type set w_name $w.desc.name_t @@ -55,7 +55,7 @@ constructor dialog {} { radiobutton $w.desc.match_r \ -anchor w \ - -text {Match Tracking Branch Name} \ + -text [mc "Match Tracking Branch Name"] \ -value match \ -variable @name_type grid $w.desc.match_r -sticky we -padx {0 5} -columnspan 2 @@ -63,38 +63,38 @@ constructor dialog {} { grid columnconfigure $w.desc 1 -weight 1 pack $w.desc -anchor nw -fill x -pady 5 -padx 5 - set w_rev [::choose_rev::new $w.rev {Starting Revision}] + set w_rev [::choose_rev::new $w.rev [mc "Starting Revision"]] pack $w.rev -anchor nw -fill both -expand 1 -pady 5 -padx 5 - labelframe $w.options -text {Options} + labelframe $w.options -text [mc Options] frame $w.options.merge - label $w.options.merge.l -text {Update Existing Branch:} + label $w.options.merge.l -text [mc "Update Existing Branch:"] pack $w.options.merge.l -side left radiobutton $w.options.merge.no \ - -text No \ + -text [mc No] \ -value none \ -variable @opt_merge pack $w.options.merge.no -side left radiobutton $w.options.merge.ff \ - -text {Fast Forward Only} \ + -text [mc "Fast Forward Only"] \ -value ff \ -variable @opt_merge pack $w.options.merge.ff -side left radiobutton $w.options.merge.reset \ - -text {Reset} \ + -text [mc Reset] \ -value reset \ -variable @opt_merge pack $w.options.merge.reset -side left pack $w.options.merge -anchor nw checkbutton $w.options.fetch \ - -text {Fetch Tracking Branch} \ + -text [mc "Fetch Tracking Branch"] \ -variable @opt_fetch pack $w.options.fetch -anchor nw checkbutton $w.options.checkout \ - -text {Checkout After Creation} \ + -text [mc "Checkout After Creation"] \ -variable @opt_checkout pack $w.options.checkout -anchor nw pack $w.options -anchor nw -fill x -pady 5 -padx 5 @@ -128,7 +128,7 @@ method _create {} { -type ok \ -title [wm title $w] \ -parent $w \ - -message "Please select a tracking branch." + -message [mc "Please select a tracking branch."] return } if {![regsub ^refs/heads/ [lindex $spec 2] {} newbranch]} { @@ -137,7 +137,7 @@ method _create {} { -type ok \ -title [wm title $w] \ -parent $w \ - -message "Tracking branch [$w get] is not a branch in the remote repository." + -message [mc "Tracking branch %s is not a branch in the remote repository." [$w get]] return } } @@ -150,7 +150,7 @@ method _create {} { -type ok \ -title [wm title $w] \ -parent $w \ - -message "Please supply a branch name." + -message [mc "Please supply a branch name."] focus $w_name return } @@ -161,7 +161,7 @@ method _create {} { -type ok \ -title [wm title $w] \ -parent $w \ - -message "'$newbranch' is not an acceptable branch name." + -message [mc "'%s' is not an acceptable branch name." $newbranch] focus $w_name return } diff --git a/lib/branch_delete.tcl b/lib/branch_delete.tcl index c7573c6c72..86c4f73370 100644 --- a/lib/branch_delete.tcl +++ b/lib/branch_delete.tcl @@ -12,29 +12,29 @@ constructor dialog {} { global current_branch make_toplevel top w - wm title $top "[appname] ([reponame]): Delete Branch" + wm title $top [append "[appname] ([reponame]): " [mc "Delete Branch"]] if {$top ne {.}} { wm geometry $top "+[winfo rootx .]+[winfo rooty .]" } - label $w.header -text {Delete Local Branch} -font font_uibold + label $w.header -text [mc "Delete Local Branch"] -font font_uibold pack $w.header -side top -fill x frame $w.buttons set w_delete $w.buttons.delete button $w_delete \ - -text Delete \ + -text [mc Delete] \ -default active \ -state disabled \ -command [cb _delete] pack $w_delete -side right button $w.buttons.cancel \ - -text {Cancel} \ + -text [mc Cancel] \ -command [list destroy $w] pack $w.buttons.cancel -side right -padx 5 pack $w.buttons -side bottom -fill x -pady 10 -padx 10 - labelframe $w.list -text {Local Branches} + labelframe $w.list -text [mc "Local Branches"] set w_heads $w.list.l listbox $w_heads \ -height 10 \ @@ -49,9 +49,9 @@ constructor dialog {} { set w_check [choose_rev::new \ $w.check \ - {Delete Only If Merged Into} \ + [mc "Delete Only If Merged Into"] \ ] - $w_check none {Always (Do not perform merge test.)} + $w_check none [mc "Always (Do not perform merge test.)"] pack $w.check -anchor nw -fill x -pady 5 -padx 5 foreach h [load_all_heads] { @@ -100,7 +100,7 @@ method _delete {} { lappend to_delete [list $b $o] } if {$not_merged ne {}} { - set msg "The following branches are not completely merged into [$w_check get]: + set msg "[mc "The following branches are not completely merged into %s:" [$w_check get]] - [join $not_merged "\n - "]" tk_messageBox \ @@ -112,9 +112,7 @@ method _delete {} { } if {$to_delete eq {}} return if {$check_cmt eq {}} { - set msg {Recovering deleted branches is difficult. - -Delete the selected branches?} + set msg [mc "Recovering deleted branches is difficult. \n\n Delete the selected branches?"] if {[tk_messageBox \ -icon warning \ -type yesno \ @@ -140,7 +138,7 @@ Delete the selected branches?} -type ok \ -title [wm title $w] \ -parent $w \ - -message "Failed to delete branches:\n$failed" + -message [mc "Failed to delete branches:\n%s" $failed] } destroy $w diff --git a/lib/branch_rename.tcl b/lib/branch_rename.tcl index 1cadc31d20..d6f040e7a2 100644 --- a/lib/branch_rename.tcl +++ b/lib/branch_rename.tcl @@ -11,7 +11,7 @@ constructor dialog {} { global current_branch make_toplevel top w - wm title $top "[appname] ([reponame]): Rename Branch" + wm title $top [append "[appname] ([reponame]): " [mc "Rename Branch"]] if {$top ne {.}} { wm geometry $top "+[winfo rootx .]+[winfo rooty .]" } @@ -19,24 +19,24 @@ constructor dialog {} { set oldname $current_branch set newname [get_config gui.newbranchtemplate] - label $w.header -text {Rename Branch} -font font_uibold + label $w.header -text [mc "Rename Branch"] -font font_uibold pack $w.header -side top -fill x frame $w.buttons - button $w.buttons.rename -text Rename \ + button $w.buttons.rename -text [mc Rename] \ -default active \ -command [cb _rename] pack $w.buttons.rename -side right - button $w.buttons.cancel -text {Cancel} \ + button $w.buttons.cancel -text [mc Cancel] \ -command [list destroy $w] pack $w.buttons.cancel -side right -padx 5 pack $w.buttons -side bottom -fill x -pady 10 -padx 10 frame $w.rename - label $w.rename.oldname_l -text {Branch:} + label $w.rename.oldname_l -text [mc "Branch:"] eval tk_optionMenu $w.rename.oldname_m @oldname [load_all_heads] - label $w.rename.newname_l -text {New Name:} + label $w.rename.newname_l -text [mc "New Name:"] entry $w.rename.newname_t \ -borderwidth 1 \ -relief sunken \ @@ -72,7 +72,7 @@ method _rename {} { -type ok \ -title [wm title $w] \ -parent $w \ - -message "Please select a branch to rename." + -message [mc "Please select a branch to rename."] focus $w.rename.oldname_m return } @@ -83,7 +83,7 @@ method _rename {} { -type ok \ -title [wm title $w] \ -parent $w \ - -message "Please supply a branch name." + -message [mc "Please supply a branch name."] focus $w.rename.newname_t return } @@ -93,7 +93,7 @@ method _rename {} { -type ok \ -title [wm title $w] \ -parent $w \ - -message "Branch '$newname' already exists." + -message [mc "Branch '%s' already exists." $newname] focus $w.rename.newname_t return } @@ -103,7 +103,7 @@ method _rename {} { -type ok \ -title [wm title $w] \ -parent $w \ - -message "We do not like '$newname' as a branch name." + -message [mc "'%s' is not an acceptable branch name." $newname] focus $w.rename.newname_t return } @@ -114,7 +114,7 @@ method _rename {} { -type ok \ -title [wm title $w] \ -parent $w \ - -message "Failed to rename '$oldname'.\n\n$err" + -message [append [mc "Failed to rename '%s'." $oldname] "\n\n$err"] return } diff --git a/lib/browser.tcl b/lib/browser.tcl index 888db3c889..987622933c 100644 --- a/lib/browser.tcl +++ b/lib/browser.tcl @@ -14,7 +14,7 @@ field w field browser_commit field browser_path field browser_files {} -field browser_status {Starting...} +field browser_status [mc "Starting..."] field browser_stack {} field browser_busy 1 @@ -23,7 +23,7 @@ field ls_buf {}; # Buffered record output from ls-tree constructor new {commit {path {}}} { global cursor_ptr M1B make_toplevel top w - wm title $top "[appname] ([reponame]): File Browser" + wm title $top [append "[appname] ([reponame]): " [mc "File Browser"]] set browser_commit $commit set browser_path $browser_commit:$path @@ -124,7 +124,7 @@ method _parent {} { } else { regsub {/[^/]+$} $browser_path {} browser_path } - set browser_status "Loading $browser_path..." + set browser_status [mc "Loading %s..." $browser_path] _ls $this [lindex $parent 0] [lindex $parent 1] } } @@ -141,7 +141,7 @@ method _enter {} { tree { set name [lindex $info 2] set escn [escape_path $name] - set browser_status "Loading $escn..." + set browser_status [mc "Loading %s..." $escn] append browser_path $escn _ls $this [lindex $info 1] $name } @@ -185,7 +185,7 @@ method _ls {tree_id {name {}}} { -align center -padx 5 -pady 1 \ -name icon0 \ -image ::browser::img_parent - $w insert end {[Up To Parent]} + $w insert end [mc "\[Up To Parent\]"] lappend browser_files parent } lappend browser_stack [list $tree_id $name] @@ -244,7 +244,7 @@ method _read {fd} { if {[eof $fd]} { close $fd - set browser_status Ready. + set browser_status [mc "Ready."] set browser_busy 0 set ls_buf {} if {$n > 0} { @@ -265,27 +265,27 @@ field w_rev ; # mega-widget to pick the initial revision constructor dialog {} { make_toplevel top w - wm title $top "[appname] ([reponame]): Browse Branch Files" + wm title $top [append "[appname] ([reponame]): " [mc "Browse Branch Files"]] if {$top ne {.}} { wm geometry $top "+[winfo rootx .]+[winfo rooty .]" } label $w.header \ - -text {Browse Branch Files} \ + -text [mc "Browse Branch Files"] \ -font font_uibold pack $w.header -side top -fill x frame $w.buttons - button $w.buttons.browse -text Browse \ + button $w.buttons.browse -text [mc Browse] \ -default active \ -command [cb _open] pack $w.buttons.browse -side right - button $w.buttons.cancel -text {Cancel} \ + button $w.buttons.cancel -text [mc Cancel] \ -command [list destroy $w] pack $w.buttons.cancel -side right -padx 5 pack $w.buttons -side bottom -fill x -pady 10 -padx 10 - set w_rev [::choose_rev::new $w.rev {Revision}] + set w_rev [::choose_rev::new $w.rev [mc Revision]] $w_rev bind_listbox [cb _open] pack $w.rev -anchor nw -fill both -expand 1 -pady 5 -padx 5 diff --git a/lib/checkout_op.tcl b/lib/checkout_op.tcl index 170f737f61..b98c9cbcd8 100644 --- a/lib/checkout_op.tcl +++ b/lib/checkout_op.tcl @@ -76,7 +76,7 @@ method run {} { _toplevel $this {Refreshing Tracking Branch} set w_cons [::console::embed \ $w.console \ - "Fetching $r_name from $remote"] + [mc "Fetching %s from %s" $r_name $remote]] pack $w.console -fill both -expand 1 $w_cons exec $cmd [cb _finish_fetch] @@ -137,7 +137,7 @@ method _finish_fetch {ok} { destroy $w set w {} } else { - button $w.close -text Close -command [list destroy $w] + button $w.close -text [mc Close] -command [list destroy $w] pack $w.close -side bottom -anchor e -padx 10 -pady 10 } @@ -166,7 +166,7 @@ method _update_ref {} { # Assume it does not exist, and that is what the error was. # if {!$create} { - _error $this "Branch '$newbranch' does not exist." + _error $this [mc "Branch '%s' does not exist." $newbranch] return 0 } @@ -176,7 +176,7 @@ method _update_ref {} { # We were told to create it, but not do a merge. # Bad. Name shouldn't have existed. # - _error $this "Branch '$newbranch' already exists." + _error $this [mc "Branch '%s' already exists." $newbranch] return 0 } elseif {!$create && $merge_type eq {none}} { # We aren't creating, it exists and we don't merge. @@ -203,7 +203,7 @@ method _update_ref {} { set new $cur set new_hash $cur } else { - _error $this "Branch '$newbranch' already exists.\n\nIt cannot fast-forward to $new_expr.\nA merge is required." + _error $this [mc "Branch '%s' already exists.\n\nIt cannot fast-forward to %s.\nA merge is required." $newbranch $new_expr] return 0 } } @@ -217,7 +217,7 @@ method _update_ref {} { } } default { - _error $this "Merge strategy '$merge_type' not supported." + _error $this [mc "Merge strategy '%s' not supported." $merge_type] return 0 } } @@ -236,7 +236,7 @@ method _update_ref {} { if {[catch { git update-ref -m $reflog_msg $ref $new $cur } err]} { - _error $this "Failed to update '$newbranch'.\n\n$err" + _error $this [append [mc "Failed to update '%s'." $newbranch] "\n\n$err"] return 0 } } @@ -248,7 +248,7 @@ method _checkout {} { if {[lock_index checkout_op]} { after idle [cb _start_checkout] } else { - _error $this "Staging area (index) is already locked." + _error $this [mc "Staging area (index) is already locked."] delete_this } } @@ -263,12 +263,12 @@ method _start_checkout {} { && $curType eq {normal} && $curHEAD eq $HEAD} { } elseif {$commit_type ne $curType || $HEAD ne $curHEAD} { - info_popup {Last scanned state does not match repository state. + info_popup [mc "Last scanned state does not match repository state. Another Git program has modified this repository since the last scan. A rescan must be performed before the current branch can be changed. The rescan will be automatically started now. -} +"] unlock_index rescan ui_ready delete_this @@ -350,12 +350,12 @@ method _readtree_wait {fd} { if {[catch {close $fd}]} { set err $readtree_d regsub {^fatal: } $err {} err - $::main_status stop "Aborted checkout of '[_name $this]' (file level merging is required)." - warn_popup "File level merge required. + $::main_status stop [mc "Aborted checkout of '%s' (file level merging is required)." [_name $this]] + warn_popup [append [mc "File level merge required."] " $err -Staying on branch '$current_branch'." +" [mc "Staying on branch '%s'." $current_branch]] unlock_index delete_this return @@ -426,9 +426,9 @@ method _after_readtree {} { } if {$is_detached} { - info_popup "You are no longer on a local branch. + info_popup [mc "You are no longer on a local branch. -If you wanted to be on a branch, create one now starting from 'This Detached Checkout'." +If you wanted to be on a branch, create one now starting from 'This Detached Checkout'."] } # -- Update our repository state. If we were previously in @@ -475,7 +475,7 @@ method _confirm_reset {cur} { pack [label $w.msg1 \ -anchor w \ -justify left \ - -text "Resetting '$name' to $new_expr will lose the following commits:" \ + -text [mc "Resetting '%s' to '%s' will lose the following commits:" $name $new_expr]\ ] -anchor w set list $w.list.l @@ -497,21 +497,21 @@ method _confirm_reset {cur} { pack [label $w.msg2 \ -anchor w \ -justify left \ - -text {Recovering lost commits may not be easy.} \ + -text [mc "Recovering lost commits may not be easy."] \ ] pack [label $w.msg3 \ -anchor w \ -justify left \ - -text "Reset '$name'?" \ + -text [mc "Reset '%s'?" $name] \ ] frame $w.buttons button $w.buttons.visualize \ - -text Visualize \ + -text [mc Visualize] \ -command $gitk pack $w.buttons.visualize -side left button $w.buttons.reset \ - -text Reset \ + -text [mc Reset] \ -command " set @reset_ok 1 destroy $w @@ -519,7 +519,7 @@ method _confirm_reset {cur} { pack $w.buttons.reset -side right button $w.buttons.cancel \ -default active \ - -text Cancel \ + -text [mc Cancel] \ -command [list destroy $w] pack $w.buttons.cancel -side right -padx 5 pack $w.buttons -side bottom -fill x -pady 10 -padx 10 @@ -575,13 +575,13 @@ method _toplevel {title} { } method _fatal {err} { - error_popup "Failed to set current branch. + error_popup [append [mc "Failed to set current branch. This working directory is only partially switched. We successfully updated your files, but failed to update an internal Git file. -This should not have occurred. [appname] will now close and give up. +This should not have occurred. %s will now close and give up." [appname]] " -$err" +$err"] exit 1 } diff --git a/lib/choose_rev.tcl b/lib/choose_rev.tcl index ec064b3e13..a58b752cdd 100644 --- a/lib/choose_rev.tcl +++ b/lib/choose_rev.tcl @@ -50,14 +50,14 @@ constructor _new {path unmerged_only title} { if {$is_detached} { radiobutton $w.detachedhead_r \ -anchor w \ - -text {This Detached Checkout} \ + -text [mc "This Detached Checkout"] \ -value HEAD \ -variable @revtype grid $w.detachedhead_r -sticky we -padx {0 5} -columnspan 2 } radiobutton $w.expr_r \ - -text {Revision Expression:} \ + -text [mc "Revision Expression:"] \ -value expr \ -variable @revtype entry $w.expr_t \ @@ -71,17 +71,17 @@ constructor _new {path unmerged_only title} { frame $w.types radiobutton $w.types.head_r \ - -text {Local Branch} \ + -text [mc "Local Branch"] \ -value head \ -variable @revtype pack $w.types.head_r -side left radiobutton $w.types.trck_r \ - -text {Tracking Branch} \ + -text [mc "Tracking Branch"] \ -value trck \ -variable @revtype pack $w.types.trck_r -side left radiobutton $w.types.tag_r \ - -text {Tag} \ + -text [mc "Tag"] \ -value tag \ -variable @revtype pack $w.types.tag_r -side left @@ -314,7 +314,7 @@ method commit_or_die {} { } set top [winfo toplevel $w] - set msg "Invalid revision: [get $this]\n\n$err" + set msg [append [mc "Invalid revision: %s" [get $this]] "\n\n$err"] tk_messageBox \ -icon error \ -type ok \ @@ -335,7 +335,7 @@ method _expr {} { if {$i ne {}} { return [lindex $cur_specs $i 1] } else { - error "No revision selected." + error [mc "No revision selected."] } } @@ -343,7 +343,7 @@ method _expr {} { if {$c_expr ne {}} { return $c_expr } else { - error "Revision expression is empty." + error [mc "Revision expression is empty."] } } HEAD { return HEAD } diff --git a/lib/commit.tcl b/lib/commit.tcl index f857a2ff5b..15489c616b 100644 --- a/lib/commit.tcl +++ b/lib/commit.tcl @@ -6,19 +6,19 @@ proc load_last_commit {} { global repo_config if {[llength $PARENT] == 0} { - error_popup {There is nothing to amend. + error_popup [mc "There is nothing to amend. You are about to create the initial commit. There is no commit before this to amend. -} +"] return } repository_state curType curHEAD curMERGE_HEAD if {$curType eq {merge}} { - error_popup {Cannot amend while merging. + error_popup [mc "Cannot amend while merging. You are currently in the middle of a merge that has not been fully completed. You cannot amend the prior commit unless you first abort the current merge activity. -} +"] return } @@ -46,7 +46,7 @@ You are currently in the middle of a merge that has not been fully completed. Y } set msg [string trim $msg] } err]} { - error_popup "Error loading commit data for amend:\n\n$err" + error_popup [append [mc "Error loading commit data for amend:"] "\n\n$err"] return } @@ -73,12 +73,12 @@ proc committer_ident {} { if {$GIT_COMMITTER_IDENT eq {}} { if {[catch {set me [git var GIT_COMMITTER_IDENT]} err]} { - error_popup "Unable to obtain your identity:\n\n$err" + error_popup [append [mc "Unable to obtain your identity:"] "\n\n$err"] return {} } if {![regexp {^(.*) [0-9]+ [-+0-9]+$} \ $me me GIT_COMMITTER_IDENT]} { - error_popup "Invalid GIT_COMMITTER_IDENT:\n\n$me" + error_popup [append [mc "Invalid GIT_COMMITTER_IDENT:"] "\n\n$me"] return {} } } @@ -130,12 +130,12 @@ proc commit_tree {} { && $curType eq {normal} && $curHEAD eq $HEAD} { } elseif {$commit_type ne $curType || $HEAD ne $curHEAD} { - info_popup {Last scanned state does not match repository state. + info_popup [mc "Last scanned state does not match repository state. Another Git program has modified this repository since the last scan. A rescan must be performed before another commit can be created. The rescan will be automatically started now. -} +"] unlock_index rescan ui_ready return @@ -151,26 +151,26 @@ The rescan will be automatically started now. D? - M? {set files_ready 1} U? { - error_popup "Unmerged files cannot be committed. + error_popup [mc "Unmerged files cannot be committed. -File [short_path $path] has merge conflicts. You must resolve them and stage the file before committing. -" +File %s has merge conflicts. You must resolve them and stage the file before committing. +" [short_path $path]] unlock_index return } default { - error_popup "Unknown file state [lindex $s 0] detected. + error_popup [mc "Unknown file state %s detected. -File [short_path $path] cannot be committed by this program. -" +File %s cannot be committed by this program. +" [lindex $s 0] [short_path $path]] } } } if {!$files_ready && ![string match *merge $curType]} { - info_popup {No changes to commit. + info_popup [mc "No changes to commit. You must stage at least 1 file before you can commit. -} +"] unlock_index return } @@ -180,14 +180,14 @@ You must stage at least 1 file before you can commit. set msg [string trim [$ui_comm get 1.0 end]] regsub -all -line {[ \t\r]+$} $msg {} msg if {$msg eq {}} { - error_popup {Please supply a commit message. + error_popup [mc "Please supply a commit message. A good commit message has the following format: - First line: Describe in one sentance what you did. - Second line: Blank - Remaining lines: Describe why this change is good. -} +"] unlock_index return } @@ -254,7 +254,7 @@ proc commit_committree {fd_wt curHEAD msg} { gets $fd_wt tree_id if {$tree_id eq {} || [catch {close $fd_wt} err]} { - error_popup "write-tree failed:\n\n$err" + error_popup [append [mc "write-tree failed:"] "\n\n$err"] ui_status {Commit failed.} unlock_index return @@ -276,14 +276,14 @@ proc commit_committree {fd_wt curHEAD msg} { } if {$tree_id eq $old_tree} { - info_popup {No changes to commit. + info_popup [mc "No changes to commit. No files were modified by this commit and it was not a merge commit. A rescan will be automatically started now. -} +"] unlock_index - rescan {ui_status {No changes to commit.}} + rescan {ui_status [mc "No changes to commit."]} return } } @@ -314,7 +314,7 @@ A rescan will be automatically started now. } lappend cmd <$msg_p if {[catch {set cmt_id [eval git $cmd]} err]} { - error_popup "commit-tree failed:\n\n$err" + error_popup [append [mc "commit-tree failed:"] "\n\n$err"] ui_status {Commit failed.} unlock_index return @@ -336,7 +336,7 @@ A rescan will be automatically started now. if {[catch { git update-ref -m $reflogm HEAD $cmt_id $curHEAD } err]} { - error_popup "update-ref failed:\n\n$err" + error_popup [append [mc "update-ref failed:"] "\n\n$err"] ui_status {Commit failed.} unlock_index return @@ -427,5 +427,5 @@ A rescan will be automatically started now. display_all_files unlock_index reshow_diff - ui_status "Created commit [string range $cmt_id 0 7]: $subject" + ui_status [mc "Created commit %s: %s" [string range $cmt_id 0 7] $subject] } diff --git a/lib/console.tcl b/lib/console.tcl index 6f718fbac3..e5f9ba429b 100644 --- a/lib/console.tcl +++ b/lib/console.tcl @@ -52,7 +52,7 @@ method _init {} { -state disabled \ -xscrollcommand [list $w.m.sbx set] \ -yscrollcommand [list $w.m.sby set] - label $w.m.s -text {Working... please wait...} \ + label $w.m.s -text [mc "Working... please wait..."] \ -anchor w \ -justify left \ -font font_uibold @@ -66,11 +66,11 @@ method _init {} { pack $w.m -side top -fill both -expand 1 -padx 5 -pady 10 menu $w.ctxm -tearoff 0 - $w.ctxm add command -label "Copy" \ + $w.ctxm add command -label [mc "Copy"] \ -command "tk_textCopy $w.m.t" - $w.ctxm add command -label "Select All" \ + $w.ctxm add command -label [mc "Select All"] \ -command "focus $w.m.t;$w.m.t tag add sel 0.0 end" - $w.ctxm add command -label "Copy All" \ + $w.ctxm add command -label [mc "Copy All"] \ -command " $w.m.t tag add sel 0.0 end tk_textCopy $w.m.t @@ -78,7 +78,7 @@ method _init {} { " if {$is_toplevel} { - button $w.ok -text {Close} \ + button $w.ok -text [mc "Close"] \ -state disabled \ -command [list destroy $w] pack $w.ok -side bottom -anchor e -pady 10 -padx 10 @@ -181,7 +181,7 @@ method insert {txt} { method done {ok} { if {$ok} { if {[winfo exists $w.m.s]} { - $w.m.s conf -background green -text {Success} + $w.m.s conf -background green -text [mc "Success"] if {$is_toplevel} { $w.ok conf -state normal focus $w.ok @@ -191,7 +191,7 @@ method done {ok} { if {![winfo exists $w.m.s]} { _init $this } - $w.m.s conf -background red -text {Error: Command Failed} + $w.m.s conf -background red -text [mc "Error: Command Failed"] if {$is_toplevel} { $w.ok conf -state normal focus $w.ok diff --git a/lib/database.tcl b/lib/database.tcl index 0657cc2245..118b1b29ab 100644 --- a/lib/database.tcl +++ b/lib/database.tcl @@ -24,14 +24,14 @@ proc do_stats {} { toplevel $w wm geometry $w "+[winfo rootx .]+[winfo rooty .]" - label $w.header -text {Database Statistics} + label $w.header -text [mc "Database Statistics"] pack $w.header -side top -fill x frame $w.buttons -border 1 - button $w.buttons.close -text Close \ + button $w.buttons.close -text [mc Close] \ -default active \ -command [list destroy $w] - button $w.buttons.gc -text {Compress Database} \ + button $w.buttons.gc -text [mc "Compress Database"] \ -default normal \ -command "destroy $w;do_gc" pack $w.buttons.close -side right @@ -40,16 +40,16 @@ proc do_stats {} { frame $w.stat -borderwidth 1 -relief solid foreach s { - {count {Number of loose objects}} - {size {Disk space used by loose objects} { KiB}} - {in-pack {Number of packed objects}} - {packs {Number of packs}} - {size-pack {Disk space used by packed objects} { KiB}} - {prune-packable {Packed objects waiting for pruning}} - {garbage {Garbage files}} + {count {mc "Number of loose objects"}} + {size {mc "Disk space used by loose objects"} { KiB}} + {in-pack {mc "Number of packed objects"}} + {packs {mc "Number of packs"}} + {size-pack {mc "Disk space used by packed objects"} { KiB}} + {prune-packable {mc "Packed objects waiting for pruning"}} + {garbage {mc "Garbage files"}} } { set name [lindex $s 0] - set label [lindex $s 1] + set label [eval [lindex $s 1]] if {[catch {set value $stats($name)}]} continue if {[llength $s] > 2} { set value "$value[lindex $s 2]" @@ -64,12 +64,12 @@ proc do_stats {} { bind $w "grab $w; focus $w.buttons.close" bind $w [list destroy $w] bind $w [list destroy $w] - wm title $w "[appname] ([reponame]): Database Statistics" + wm title $w [append "[appname] ([reponame]): " [mc "Database Statistics"]] tkwait window $w } proc do_gc {} { - set w [console::new {gc} {Compressing the object database}] + set w [console::new {gc} [mc "Compressing the object database"]] console::chain $w { {exec git pack-refs --prune} {exec git reflog expire --all} @@ -80,7 +80,7 @@ proc do_gc {} { proc do_fsck_objects {} { set w [console::new {fsck-objects} \ - {Verifying the object database with fsck-objects}] + [mc "Verifying the object database with fsck-objects"]] set cmd [list git fsck-objects] lappend cmd --full lappend cmd --cache diff --git a/lib/diff.tcl b/lib/diff.tcl index e09e1257e1..b1129d551b 100644 --- a/lib/diff.tcl +++ b/lib/diff.tcl @@ -39,13 +39,13 @@ proc handle_empty_diff {} { set s $file_states($path) if {[lindex $s 0] ne {_M}} return - info_popup "No differences detected. + info_popup [mc "No differences detected. -[short_path $path] has no changes. +%s has no changes. The modification date of this file was updated by another application, but the content within the file was not changed. -A rescan will be automatically started to find other files which may have the same state." +A rescan will be automatically started to find other files which may have the same state." [short_path $path]] clear_diff display_file $path __ @@ -94,7 +94,7 @@ proc show_diff {path w {lno {}}} { set diff_active 0 unlock_index ui_status "Unable to display [escape_path $path]" - error_popup "Error loading file:\n\n$err" + error_popup [append [mc "Error loading file:"] "\n\n$err"] return } $ui_diff conf -state normal @@ -159,7 +159,7 @@ proc show_diff {path w {lno {}}} { set diff_active 0 unlock_index ui_status "Unable to display [escape_path $path]" - error_popup "Error loading diff:\n\n$err" + error_popup [append [mc "Error loading diff:"] "\n\n$err"] return } @@ -275,14 +275,14 @@ proc apply_hunk {x y} { set apply_cmd {apply --cached --whitespace=nowarn} set mi [lindex $file_states($current_diff_path) 0] if {$current_diff_side eq $ui_index} { - set mode unstage + set failed_msg [mc "Failed to unstage selected hunk."] lappend apply_cmd --reverse if {[string index $mi 0] ne {M}} { unlock_index return } } else { - set mode stage + set failed_msg [mc "Failed to stage selected hunk."] if {[string index $mi 1] ne {M}} { unlock_index return @@ -307,7 +307,7 @@ proc apply_hunk {x y} { puts -nonewline $p $current_diff_header puts -nonewline $p [$ui_diff get $s_lno $e_lno] close $p} err]} { - error_popup "Failed to $mode selected hunk.\n\n$err" + error_popup [append $failed_msg "\n\n$err"] unlock_index return } diff --git a/lib/error.tcl b/lib/error.tcl index 16a22187b2..13565b7ab0 100644 --- a/lib/error.tcl +++ b/lib/error.tcl @@ -9,7 +9,7 @@ proc error_popup {msg} { set cmd [list tk_messageBox \ -icon error \ -type ok \ - -title "$title: error" \ + -title [append "$title: " [mc "error"]] \ -message $msg] if {[winfo ismapped .]} { lappend cmd -parent . @@ -25,7 +25,7 @@ proc warn_popup {msg} { set cmd [list tk_messageBox \ -icon warning \ -type ok \ - -title "$title: warning" \ + -title [append "$title: " [mc "warning"]] \ -message $msg] if {[winfo ismapped .]} { lappend cmd -parent . @@ -78,7 +78,7 @@ proc hook_failed_popup {hook msg} { -font font_diff \ -yscrollcommand [list $w.m.sby set] label $w.m.l2 \ - -text {You must correct the above errors before committing.} \ + -text [mc "You must correct the above errors before committing."] \ -anchor w \ -justify left \ -font font_uibold @@ -99,6 +99,6 @@ proc hook_failed_popup {hook msg} { bind $w "grab $w; focus $w" bind $w "destroy $w" - wm title $w "[appname] ([reponame]): error" + wm title $w [append "[appname] ([reponame]): " [mc "error"]] tkwait window $w } diff --git a/lib/index.tcl b/lib/index.tcl index f47f9290c8..b3f5e17d1f 100644 --- a/lib/index.tcl +++ b/lib/index.tcl @@ -345,26 +345,35 @@ proc revert_helper {txt paths} { } } + + # Split question between singular and plural cases, because + # such distinction is needed in some languages. Previously, the + # code used "Revert changes in" for both, but that can't work + # in languages where 'in' must be combined with word from + # rest of string (in diffrent way for both cases of course). + # + # FIXME: Unfortunately, even that isn't enough in some languages + # as they have quite complex plural-form rules. Unfortunately, + # msgcat doesn't seem to support that kind of string translation. + # set n [llength $pathList] if {$n == 0} { unlock_index return } elseif {$n == 1} { - set s "[short_path [lindex $pathList]]" + set query [mc "Revert changes in file %s?" [short_path [lindex $pathList]]] } else { - set s "these $n files" + set query [mc "Revert changes in these %i files?" $n] } set reply [tk_dialog \ .confirm_revert \ "[appname] ([reponame])" \ - "Revert changes in $s? - -Any unstaged changes will be permanently lost by the revert." \ + [mc "Any unstaged changes will be permanently lost by the revert."] \ question \ 1 \ - {Do Nothing} \ - {Revert Changes} \ + [mc "Do Nothing"] \ + [mc "Revert Changes"] \ ] if {$reply == 1} { checkout_index \ diff --git a/lib/merge.tcl b/lib/merge.tcl index 0e50919d4c..63e14279c1 100644 --- a/lib/merge.tcl +++ b/lib/merge.tcl @@ -10,10 +10,10 @@ method _can_merge {} { global HEAD commit_type file_states if {[string match amend* $commit_type]} { - info_popup {Cannot merge while amending. + info_popup [mc "Cannot merge while amending. You must finish amending this commit before starting any type of merge. -} +"] return 0 } @@ -24,12 +24,12 @@ You must finish amending this commit before starting any type of merge. # repository_state curType curHEAD curMERGE_HEAD if {$commit_type ne $curType || $HEAD ne $curHEAD} { - info_popup {Last scanned state does not match repository state. + info_popup [mc "Last scanned state does not match repository state. Another Git program has modified this repository since the last scan. A rescan must be performed before a merge can be performed. The rescan will be automatically started now. -} +"] unlock_index rescan ui_ready return 0 @@ -41,22 +41,22 @@ The rescan will be automatically started now. continue; # and pray it works! } U? { - error_popup "You are in the middle of a conflicted merge. + error_popup [mc "You are in the middle of a conflicted merge. -File [short_path $path] has merge conflicts. +File %s has merge conflicts. You must resolve them, stage the file, and commit to complete the current merge. Only then can you begin another merge. -" +" [short_path $path]] unlock_index return 0 } ?? { - error_popup "You are in the middle of a change. + error_popup [mc "You are in the middle of a change. -File [short_path $path] is modified. +File %s is modified. You should complete the current commit before starting a merge. Doing so will help you abort a failed merge, should the need arise. -" +" [short_path $path]] unlock_index return 0 } @@ -103,7 +103,7 @@ method _start {} { regsub {^[^:@]*@} $remote {} remote } set branch [lindex $spec 2] - set stitle "$branch of $remote" + set stitle [mc "%s of %s" $branch $remote] } regsub ^refs/heads/ $branch {} branch puts $fh "$cmit\t\tbranch '$branch' of $remote" @@ -116,9 +116,9 @@ method _start {} { lappend cmd HEAD lappend cmd $name - set msg "Merging $current_branch and $stitle" + set msg [mc "Merging %s and %s" $current_branch $stitle] ui_status "$msg..." - set cons [console::new "Merge" "merge $stitle"] + set cons [console::new [mc "Merge"] "merge $stitle"] console::exec $cons $cmd [cb _finish $cons] wm protocol $w WM_DELETE_WINDOW {} @@ -128,9 +128,9 @@ method _start {} { method _finish {cons ok} { console::done $cons $ok if {$ok} { - set msg {Merge completed successfully.} + set msg [mc "Merge completed successfully."] } else { - set msg {Merge failed. Conflict resolution is required.} + set msg [mc "Merge failed. Conflict resolution is required."] } unlock_index rescan [list ui_status $msg] @@ -147,7 +147,7 @@ constructor dialog {} { } make_toplevel top w - wm title $top "[appname] ([reponame]): Merge" + wm title $top [append "[appname] ([reponame]): " [mc "Merge"]] if {$top ne {.}} { wm geometry $top "+[winfo rootx .]+[winfo rooty .]" } @@ -155,26 +155,26 @@ constructor dialog {} { set _start [cb _start] label $w.header \ - -text "Merge Into $current_branch" \ + -text [mc "Merge Into %s" $current_branch] \ -font font_uibold pack $w.header -side top -fill x frame $w.buttons button $w.buttons.visualize \ - -text Visualize \ + -text [mc Visualize] \ -command [cb _visualize] pack $w.buttons.visualize -side left button $w.buttons.merge \ - -text Merge \ + -text [mc Merge] \ -command $_start pack $w.buttons.merge -side right button $w.buttons.cancel \ - -text {Cancel} \ + -text [mc "Cancel"] \ -command [cb _cancel] pack $w.buttons.cancel -side right -padx 5 pack $w.buttons -side bottom -fill x -pady 10 -padx 10 - set w_rev [::choose_rev::new_unmerged $w.rev {Revision To Merge}] + set w_rev [::choose_rev::new_unmerged $w.rev [mc "Revision To Merge"]] pack $w.rev -anchor nw -fill both -expand 1 -pady 5 -padx 5 bind $w <$M1B-Key-Return> $_start @@ -209,34 +209,34 @@ proc reset_hard {} { global HEAD commit_type file_states if {[string match amend* $commit_type]} { - info_popup {Cannot abort while amending. + info_popup [mc "Cannot abort while amending. You must finish amending this commit. -} +"] return } if {![lock_index abort]} return if {[string match *merge* $commit_type]} { - set op_question "Abort merge? + set op_question [mc "Abort merge? Aborting the current merge will cause *ALL* uncommitted changes to be lost. -Continue with aborting the current merge?" +Continue with aborting the current merge?"] } else { - set op_question "Reset changes? + set op_question [mc "Reset changes? Resetting the changes will cause *ALL* uncommitted changes to be lost. -Continue with resetting the current changes?" +Continue with resetting the current changes?"] } if {[ask_popup $op_question] eq {yes}} { set fd [git_read --stderr read-tree --reset -u -v HEAD] fconfigure $fd -blocking 0 -translation binary fileevent $fd readable [namespace code [list _reset_wait $fd]] - $::main_status start {Aborting} {files reset} + $::main_status start [mc "Aborting"] {files reset} } else { unlock_index } @@ -263,9 +263,9 @@ proc _reset_wait {fd} { catch {file delete [gitdir GITGUI_MSG]} if {$fail} { - warn_popup "Abort failed.\n\n$err" + warn_popup "[mc "Abort failed."]\n\n$err" } - rescan {ui_status {Abort completed. Ready.}} + rescan {ui_status [mc "Abort completed. Ready."]} } else { fconfigure $fd -blocking 0 } diff --git a/lib/option.tcl b/lib/option.tcl index aa9f783afd..31c7d47f35 100644 --- a/lib/option.tcl +++ b/lib/option.tcl @@ -62,7 +62,7 @@ proc do_about {} { toplevel $w wm geometry $w "+[winfo rootx .]+[winfo rooty .]" - label $w.header -text "About [appname]" \ + label $w.header -text [mc "About %s" [appname]] \ -font font_uibold pack $w.header -side top -fill x @@ -74,8 +74,7 @@ proc do_about {} { pack $w.buttons -side bottom -fill x -pady 10 -padx 10 label $w.desc \ - -text "git-gui - a graphical user interface for Git. -$copyright" \ + -text "[mc "git-gui - a graphical user interface for Git."]\n$copyright" \ -padx 5 -pady 5 \ -justify left \ -anchor w \ @@ -157,48 +156,48 @@ proc do_options {} { toplevel $w wm geometry $w "+[winfo rootx .]+[winfo rooty .]" - label $w.header -text "Options" \ + label $w.header -text [mc "Options"] \ -font font_uibold pack $w.header -side top -fill x frame $w.buttons - button $w.buttons.restore -text {Restore Defaults} \ + button $w.buttons.restore -text [mc "Restore Defaults"] \ -default normal \ -command do_restore_defaults pack $w.buttons.restore -side left - button $w.buttons.save -text Save \ + button $w.buttons.save -text [mc Save] \ -default active \ -command [list do_save_config $w] pack $w.buttons.save -side right - button $w.buttons.cancel -text {Cancel} \ + button $w.buttons.cancel -text [mc "Cancel"] \ -default normal \ -command [list destroy $w] pack $w.buttons.cancel -side right -padx 5 pack $w.buttons -side bottom -fill x -pady 10 -padx 10 - labelframe $w.repo -text "[reponame] Repository" - labelframe $w.global -text {Global (All Repositories)} + labelframe $w.repo -text [mc "%s Repository" [reponame]] + labelframe $w.global -text [mc "Global (All Repositories)"] pack $w.repo -side left -fill both -expand 1 -pady 5 -padx 5 pack $w.global -side right -fill both -expand 1 -pady 5 -padx 5 set optid 0 foreach option { - {t user.name {User Name}} - {t user.email {Email Address}} + {t user.name {mc "User Name"}} + {t user.email {mc "Email Address"}} - {b merge.summary {Summarize Merge Commits}} - {i-1..5 merge.verbosity {Merge Verbosity}} - {b merge.diffstat {Show Diffstat After Merge}} + {b merge.summary {mc "Summarize Merge Commits"}} + {i-1..5 merge.verbosity {mc "Merge Verbosity"}} + {b merge.diffstat {mc "Show Diffstat After Merge"}} - {b gui.trustmtime {Trust File Modification Timestamps}} - {b gui.pruneduringfetch {Prune Tracking Branches During Fetch}} - {b gui.matchtrackingbranch {Match Tracking Branches}} - {i-0..99 gui.diffcontext {Number of Diff Context Lines}} - {t gui.newbranchtemplate {New Branch Name Template}} + {b gui.trustmtime {mc "Trust File Modification Timestamps"}} + {b gui.pruneduringfetch {mc "Prune Tracking Branches During Fetch"}} + {b gui.matchtrackingbranch {mc "Match Tracking Branches"}} + {i-0..99 gui.diffcontext {mc "Number of Diff Context Lines"}} + {t gui.newbranchtemplate {mc "New Branch Name Template"}} } { set type [lindex $option 0] set name [lindex $option 1] - set text [lindex $option 2] + set text [eval [lindex $option 2]] incr optid foreach f {repo global} { switch -glob -- $type { @@ -246,7 +245,7 @@ proc do_options {} { foreach option $font_descs { set name [lindex $option 0] set font [lindex $option 1] - set text [lindex $option 2] + set text [eval [lindex $option 2]] set global_config_new(gui.$font^^family) \ [font configure $font -family] @@ -272,7 +271,7 @@ proc do_options {} { bind $w "grab $w; focus $w.buttons.save" bind $w "destroy $w" bind $w [list do_save_config $w] - wm title $w "[appname] ([reponame]): Options" + wm title $w [append "[appname] ([reponame]): " [mc "Options"]] tkwait window $w } @@ -303,7 +302,7 @@ proc do_restore_defaults {} { proc do_save_config {w} { if {[catch {save_config} err]} { - error_popup "Failed to completely save options:\n\n$err" + error_popup [append [mc "Failed to completely save options:"] "\n\n$err"] } reshow_diff destroy $w diff --git a/lib/remote.tcl b/lib/remote.tcl index cf9b9d5829..62bfe8f741 100644 --- a/lib/remote.tcl +++ b/lib/remote.tcl @@ -159,7 +159,7 @@ proc populate_fetch_menu {} { if {$enable} { lappend prune_list $r $m add command \ - -label "Fetch from $r..." \ + -label [mc "Fetch from %s..." $r] \ -command [list fetch_from $r] } } @@ -169,7 +169,7 @@ proc populate_fetch_menu {} { } foreach r $prune_list { $m add command \ - -label "Prune from $r..." \ + -label [mc "Prune from %s..." $r] \ -command [list prune_from $r] } } @@ -203,7 +203,7 @@ proc populate_push_menu {} { $m add separator } $m add command \ - -label "Push to $r..." \ + -label [mc "Push to %s..." $r] \ -command [list push_to $r] incr fast_count } diff --git a/lib/remote_branch_delete.tcl b/lib/remote_branch_delete.tcl index c88a360db5..06b5eabf91 100644 --- a/lib/remote_branch_delete.tcl +++ b/lib/remote_branch_delete.tcl @@ -26,28 +26,28 @@ constructor dialog {} { global all_remotes M1B make_toplevel top w - wm title $top "[appname] ([reponame]): Delete Remote Branch" + wm title $top [append "[appname] ([reponame]): " [mc "Delete Remote Branch"]] if {$top ne {.}} { wm geometry $top "+[winfo rootx .]+[winfo rooty .]" } - label $w.header -text {Delete Remote Branch} -font font_uibold + label $w.header -text [mc "Delete Remote Branch"] -font font_uibold pack $w.header -side top -fill x frame $w.buttons - button $w.buttons.delete -text Delete \ + button $w.buttons.delete -text [mc Delete] \ -default active \ -command [cb _delete] pack $w.buttons.delete -side right - button $w.buttons.cancel -text {Cancel} \ + button $w.buttons.cancel -text [mc "Cancel"] \ -command [list destroy $w] pack $w.buttons.cancel -side right -padx 5 pack $w.buttons -side bottom -fill x -pady 10 -padx 10 - labelframe $w.dest -text {From Repository} + labelframe $w.dest -text [mc "From Repository"] if {$all_remotes ne {}} { radiobutton $w.dest.remote_r \ - -text {Remote:} \ + -text [mc "Remote:"] \ -value remote \ -variable @urltype eval tk_optionMenu $w.dest.remote_m @remote $all_remotes @@ -63,7 +63,7 @@ constructor dialog {} { set urltype url } radiobutton $w.dest.url_r \ - -text {Arbitrary URL:} \ + -text [mc "Arbitrary URL:"] \ -value url \ -variable @urltype entry $w.dest.url_t \ @@ -81,7 +81,7 @@ constructor dialog {} { grid columnconfigure $w.dest 1 -weight 1 pack $w.dest -anchor nw -fill x -pady 5 -padx 5 - labelframe $w.heads -text {Branches} + labelframe $w.heads -text [mc "Branches"] listbox $w.heads.l \ -height 10 \ -width 70 \ @@ -96,7 +96,7 @@ constructor dialog {} { -anchor w \ -justify left button $w.heads.footer.rescan \ - -text {Rescan} \ + -text [mc "Rescan"] \ -command [cb _rescan] pack $w.heads.footer.status -side left -fill x pack $w.heads.footer.rescan -side right @@ -106,9 +106,9 @@ constructor dialog {} { pack $w.heads.l -side left -fill both -expand 1 pack $w.heads -fill both -expand 1 -pady 5 -padx 5 - labelframe $w.validate -text {Delete Only If} + labelframe $w.validate -text [mc "Delete Only If"] radiobutton $w.validate.head_r \ - -text {Merged Into:} \ + -text [mc "Merged Into:"] \ -value head \ -variable @checktype set head_m [tk_optionMenu $w.validate.head_m @check_head {}] @@ -116,7 +116,7 @@ constructor dialog {} { trace add variable @check_head write [cb _write_check_head] grid $w.validate.head_r $w.validate.head_m -sticky w radiobutton $w.validate.always_r \ - -text {Always (Do not perform merge checks)} \ + -text [mc "Always (Do not perform merge checks)"] \ -value always \ -variable @checktype grid $w.validate.always_r -columnspan 2 -sticky w @@ -149,7 +149,7 @@ method _delete {} { -type ok \ -title [wm title $w] \ -parent $w \ - -message "A branch is required for 'Merged Into'." + -message [mc "A branch is required for 'Merged Into'."] return } set crev $full_cache("$cache\nrefs/heads/$check_head") @@ -186,9 +186,7 @@ method _delete {} { - [join $not_merged "\n - "]" if {$need_fetch} { - append msg " - -One or more of the merge tests failed because you have not fetched the necessary commits. Try fetching from $uri first." + append msg "\n\n" [mc "One or more of the merge tests failed because you have not fetched the necessary commits. Try fetching from %s first." $uri] } tk_messageBox \ @@ -206,7 +204,7 @@ One or more of the merge tests failed because you have not fetched the necessary -type ok \ -title [wm title $w] \ -parent $w \ - -message "Please select one or more branches to delete." + -message [mc "Please select one or more branches to delete."] return } @@ -215,9 +213,9 @@ One or more of the merge tests failed because you have not fetched the necessary -type yesno \ -title [wm title $w] \ -parent $w \ - -message {Recovering deleted branches is difficult. + -message [mc "Recovering deleted branches is difficult. -Delete the selected branches?}] ne yes} { +Delete the selected branches?"]] ne yes} { return } @@ -225,7 +223,7 @@ Delete the selected branches?}] ne yes} { set cons [console::new \ "push $uri" \ - "Deleting branches from $uri"] + [mc "Deleting branches from %s" $uri]] console::exec $cons $push_cmd } @@ -285,12 +283,12 @@ method _load {cache uri} { $w.heads.l conf -state disabled set head_list [list] set full_list [list] - set status {No repository selected.} + set status [mc "No repository selected."] return } if {[catch {set x $cached($cache)}]} { - set status "Scanning $uri..." + set status [mc "Scanning %s..." $uri] $w.heads.l conf -state disabled set head_list [list] set full_list [list] diff --git a/lib/shortcut.tcl b/lib/shortcut.tcl index c36be2f3cd..d0e63a3d0e 100644 --- a/lib/shortcut.tcl +++ b/lib/shortcut.tcl @@ -6,7 +6,7 @@ proc do_windows_shortcut {} { set fn [tk_getSaveFile \ -parent . \ - -title "[appname] ([reponame]): Create Desktop Icon" \ + -title [append "[appname] ([reponame]): " [mc "Create Desktop Icon"]] \ -initialfile "Git [reponame].bat"] if {$fn != {}} { if {[file extension $fn] ne {.bat}} { @@ -23,7 +23,7 @@ proc do_windows_shortcut {} { puts $fd " \"[file normalize $argv0]\"" close $fd } err]} { - error_popup "Cannot write script:\n\n$err" + error_popup [append [mc "Cannot write script:"] "\n\n$err"] } } } @@ -42,7 +42,7 @@ proc do_cygwin_shortcut {} { } set fn [tk_getSaveFile \ -parent . \ - -title "[appname] ([reponame]): Create Desktop Icon" \ + -title [append "[appname] ([reponame]): " [mc "Create Desktop Icon"]] \ -initialdir $desktop \ -initialfile "Git [reponame].bat"] if {$fn != {}} { @@ -71,7 +71,7 @@ proc do_cygwin_shortcut {} { puts $fd " &\"" close $fd } err]} { - error_popup "Cannot write script:\n\n$err" + error_popup [append [mc "Cannot write script:"] "\n\n$err"] } } } @@ -81,7 +81,7 @@ proc do_macosx_app {} { set fn [tk_getSaveFile \ -parent . \ - -title "[appname] ([reponame]): Create Desktop Icon" \ + -title [append "[appname] ([reponame]): " [mc "Create Desktop Icon"]] \ -initialdir [file join $env(HOME) Desktop] \ -initialfile "Git [reponame].app"] if {$fn != {}} { @@ -146,7 +146,7 @@ proc do_macosx_app {} { file attributes $exe -permissions u+x,g+x,o+x } err]} { - error_popup "Cannot write icon:\n\n$err" + error_popup [append [mc "Cannot write icon:"] "\n\n$err"] } } } diff --git a/lib/status_bar.tcl b/lib/status_bar.tcl index 72a8fe1fd3..769ef81c4b 100644 --- a/lib/status_bar.tcl +++ b/lib/status_bar.tcl @@ -55,7 +55,7 @@ method update {have total} { set pdone [expr {100 * $have / $total}] } - set status [format "%s ... %i of %i %s (%2i%%)" \ + set status [mc "%s ... %i of %i %s (%2i%%)" \ $prefix $have $total $units $pdone] $w_c coords bar 0 0 $pdone 20 } diff --git a/lib/transport.tcl b/lib/transport.tcl index 3a22bd40d4..1c7baef173 100644 --- a/lib/transport.tcl +++ b/lib/transport.tcl @@ -4,7 +4,7 @@ proc fetch_from {remote} { set w [console::new \ "fetch $remote" \ - "Fetching new changes from $remote"] + [mc "Fetching new changes from %s" $remote]] set cmds [list] lappend cmds [list exec git fetch $remote] if {[is_config_true gui.pruneduringfetch]} { @@ -16,14 +16,14 @@ proc fetch_from {remote} { proc prune_from {remote} { set w [console::new \ "remote prune $remote" \ - "Pruning tracking branches deleted from $remote"] + [mc "Pruning tracking branches deleted from %s" $remote]] console::exec $w [list git remote prune $remote] } proc push_to {remote} { set w [console::new \ "push $remote" \ - "Pushing changes to $remote"] + [mc "Pushing changes to %s" $remote]] set cmd [list git push] lappend cmd -v lappend cmd $remote @@ -65,7 +65,7 @@ proc start_push_anywhere_action {w} { set cons [console::new \ "push $r_url" \ - "Pushing $cnt $unit to $r_url"] + [mc "Pushing %s %s to %s" $cnt $unit $r_url]] console::exec $cons $cmd destroy $w } @@ -81,21 +81,21 @@ proc do_push_anywhere {} { toplevel $w wm geometry $w "+[winfo rootx .]+[winfo rooty .]" - label $w.header -text {Push Branches} -font font_uibold + label $w.header -text [mc "Push Branches"] -font font_uibold pack $w.header -side top -fill x frame $w.buttons - button $w.buttons.create -text Push \ + button $w.buttons.create -text [mc Push] \ -default active \ -command [list start_push_anywhere_action $w] pack $w.buttons.create -side right - button $w.buttons.cancel -text {Cancel} \ + button $w.buttons.cancel -text [mc "Cancel"] \ -default normal \ -command [list destroy $w] pack $w.buttons.cancel -side right -padx 5 pack $w.buttons -side bottom -fill x -pady 10 -padx 10 - labelframe $w.source -text {Source Branches} + labelframe $w.source -text [mc "Source Branches"] listbox $w.source.l \ -height 10 \ -width 70 \ @@ -112,10 +112,10 @@ proc do_push_anywhere {} { pack $w.source.l -side left -fill both -expand 1 pack $w.source -fill both -expand 1 -pady 5 -padx 5 - labelframe $w.dest -text {Destination Repository} + labelframe $w.dest -text [mc "Destination Repository"] if {$all_remotes ne {}} { radiobutton $w.dest.remote_r \ - -text {Remote:} \ + -text [mc "Remote:"] \ -value remote \ -variable push_urltype eval tk_optionMenu $w.dest.remote_m push_remote $all_remotes @@ -130,7 +130,7 @@ proc do_push_anywhere {} { set push_urltype url } radiobutton $w.dest.url_r \ - -text {Arbitrary URL:} \ + -text [mc "Arbitrary URL:"] \ -value url \ -variable push_urltype entry $w.dest.url_t \ @@ -150,13 +150,13 @@ proc do_push_anywhere {} { grid columnconfigure $w.dest 1 -weight 1 pack $w.dest -anchor nw -fill x -pady 5 -padx 5 - labelframe $w.options -text {Transfer Options} + labelframe $w.options -text [mc "Transfer Options"] checkbutton $w.options.thin \ - -text {Use thin pack (for slow network connections)} \ + -text [mc "Use thin pack (for slow network connections)"] \ -variable push_thin grid $w.options.thin -columnspan 2 -sticky w checkbutton $w.options.tags \ - -text {Include tags} \ + -text [mc "Include tags"] \ -variable push_tags grid $w.options.tags -columnspan 2 -sticky w grid columnconfigure $w.options 1 -weight 1 @@ -169,6 +169,6 @@ proc do_push_anywhere {} { bind $w "grab $w; focus $w.buttons.create" bind $w "destroy $w" bind $w [list start_push_anywhere_action $w] - wm title $w "[appname] ([reponame]): Push" + wm title $w [append "[appname] ([reponame]): " [mc "Push"]] tkwait window $w } From 3845048064352f4e213363239298f4fa3190ddb9 Mon Sep 17 00:00:00 2001 From: Christian Stimming Date: Sat, 21 Jul 2007 14:17:07 +0200 Subject: [PATCH 0015/1490] Makefile rules for translation catalog generation and installation. [jes: with fixes by the i18n team.] Signed-off-by: Christian Stimming Signed-off-by: Johannes Schindelin --- Makefile | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 1bac6fed46..559e65ecd6 100644 --- a/Makefile +++ b/Makefile @@ -103,6 +103,21 @@ $(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh $(GITGUI_BUILT_INS): git-gui $(QUIET_BUILT_IN)rm -f $@ && ln git-gui $@ +XGETTEXT ?= xgettext +msgsdir ?= $(libdir)/msgs +msgsdir_SQ = $(subst ','\'',$(msgsdir)) +PO_TEMPLATE = po/git-gui.pot +ALL_POFILES = $(wildcard po/*.po) +ALL_MSGFILES = $(subst .po,.msg,$(ALL_POFILES)) + +$(PO_TEMPLATE): $(SCRIPT_SH) $(ALL_LIBFILES) + $(XGETTEXT) -kmc -LTcl -o $@ $(SCRIPT_SH) $(ALL_LIBFILES) +update-po:: $(PO_TEMPLATE) + $(foreach p, $(ALL_POFILES), echo Updating $p ; msgmerge -U $p $(PO_TEMPLATE) ; ) +$(ALL_MSGFILES): %.msg : %.po + @echo Generating catalog $@ + msgfmt --statistics --tcl $< -l $(basename $(notdir $<)) -d $(dir $@) + lib/tclIndex: $(ALL_LIBFILES) $(QUIET_INDEX)if echo \ $(foreach p,$(PRELOAD_FILES),source $p\;) \ @@ -136,7 +151,7 @@ GIT-GUI-VARS: .FORCE-GIT-GUI-VARS echo 1>$@ "$$VARS"; \ fi -all:: $(ALL_PROGRAMS) lib/tclIndex +all:: $(ALL_PROGRAMS) lib/tclIndex $(ALL_MSGFILES) install: all $(QUIET)$(INSTALL_D0)'$(DESTDIR_SQ)$(gitexecdir_SQ)' $(INSTALL_D1) @@ -145,13 +160,15 @@ install: all $(QUIET)$(INSTALL_D0)'$(DESTDIR_SQ)$(libdir_SQ)' $(INSTALL_D1) $(QUIET)$(INSTALL_R0)lib/tclIndex $(INSTALL_R1) '$(DESTDIR_SQ)$(libdir_SQ)' $(QUIET)$(foreach p,$(ALL_LIBFILES), $(INSTALL_R0)$p $(INSTALL_R1) '$(DESTDIR_SQ)$(libdir_SQ)' &&) true + $(QUIET)$(INSTALL_D0)'$(DESTDIR_SQ)$(msgsdir_SQ)' $(INSTALL_D1) + $(QUIET)$(foreach p,$(ALL_MSGFILES), $(INSTALL_R0)$p $(INSTALL_R1) '$(DESTDIR_SQ)$(msgsdir_SQ)' &&) true dist-version: @mkdir -p $(TARDIR) @echo $(GITGUI_VERSION) > $(TARDIR)/version clean:: - rm -f $(ALL_PROGRAMS) lib/tclIndex + rm -f $(ALL_PROGRAMS) lib/tclIndex po/*.msg rm -f GIT-VERSION-FILE GIT-GUI-VARS .PHONY: all install dist-version clean From 2631a81b901fc7baa274f98530a0d9cc05cecd17 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 27 Jul 2007 16:05:16 -0700 Subject: [PATCH 0016/1490] git-gui po/README: Guide to translators This short note is to help a translation contributor to help us localizing git-gui message files by covering the basics. Signed-off-by: Junio C Hamano --- po/README | 205 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 po/README diff --git a/po/README b/po/README new file mode 100644 index 0000000000..af5dfad8c7 --- /dev/null +++ b/po/README @@ -0,0 +1,205 @@ +Localizing git-gui for your language +==================================== + +This short note is to help you, who reads and writes English and your +own language, help us getting git-gui localized for more languages. It +does not try to be a comprehensive manual of GNU gettext, which is the +i18n framework we use, but tries to help you get started by covering the +basics and how it is used in this project. + +1. Getting started. + +You would first need to have a working "git". Your distribution may +have it as "git-core" package (do not get "GNU Interactive Tools" -- +that is a different "git"). You would also need GNU gettext toolchain +to test the resulting translation out. Although you can work on message +translation files with a regular text editor, it is a good idea to have +specialized so-called "po file editors" (e.g. emacs po-mode, KBabel, +poedit, GTranslator --- any of them would work well). Please install +them. + +You would then need to clone the git-gui internationalization project +repository, so that you can work on it: + + $ git clone mob@repo.or.cz:/srv/git/git-gui/git-gui-i18n.git/ + $ cd git-gui-i18n + $ git checkout --track -b mob origin/mob + $ git config remote.origin.push mob + +The "git checkout" command creates a 'mob' branch from upstream's +corresponding branch and makes it your current branch. You will be +working on this branch. + +The "git config" command records in your repository configuration file +that you would push "mob" branch to the upstream when you say "git +push". + + +2. Starting a new language. + +In the git-gui-i18n directory is a po/ subdirectory. It has a +handful files whose names end with ".po". Is there a file that has +messages in your language? + +If you do not know what your language should be named, you need to find +it. This currently follows ISO 639-1 two letter codes: + + http://www.loc.gov/standards/iso639-2/php/code_list.php + +For example, if you are preparing a translation for Afrikaans, the +language code is "af". If there already is a translation for your +language, you do not have to perform any step in this section, but keep +reading, because we are covering the basics. + +If you did not find your language, you would need to start one yourself. +Copy po/git-gui.pot file to po/af.po (replace "af" with the code for +your language). Edit the first several lines to match existing *.po +files to make it clear this is a translation table for git-gui project, +and you are the primary translator. The result of your editing would +look something like this: + + # Translation of git-gui to Afrikaans + # Copyright (C) 2007 Shawn Pearce + # This file is distributed under the same license as the git-gui package. + # YOUR NAME , 2007. + # + #, fuzzy + msgid "" + msgstr "" + "Project-Id-Version: git-gui\n" + "Report-Msgid-Bugs-To: \n" + "POT-Creation-Date: 2007-07-24 22:19+0300\n" + "PO-Revision-Date: 2007-07-25 18:00+0900\n" + "Last-Translator: YOUR NAME \n" + "Language-Team: Afrikaans\n" + "MIME-Version: 1.0\n" + "Content-Type: text/plain; charset=UTF-8\n" + "Content-Transfer-Encoding: 8bit\n" + +You will find many pairs of a "msgid" line followed by a "msgstr" line. +These pairs define how messages in git-gui application are translated to +your language. Your primarily job is to fill in the empty double quote +pairs on msgstr lines with the translation of the strings on their +matching msgid lines. A few tips: + + - Control characters, such as newlines, are written in backslash + sequence similar to string literals in the C programming language. + When the string given on a msgid line has such a backslash sequence, + you would typically want to have corresponding ones in the string on + your msgstr line. + + - Often the messages being translated are format strings given to + "printf()"-like functions. Make sure "%s", "%d", and "%%" in your + translated messages match the original. + + When you have to change the order of words, you can add "\$" + between '%' and the conversion ('s', 'd', etc.) to say "-th + parameter to the format string is used at this point". For example, + if the original message is like this: + + "Length is %d, Weight is %d" + + and if for whatever reason your translation needs to say weight first + and then length, you can say something like: + + "WEIGHT IS %2\$d, LENGTH IS %1\$d" + + The reason you need a backslash before dollar sign is because + this is a double quoted string in Tcl language, and without + it the letter introduces a variable interpolation, which you + do not want here. + + - A long message can be split across multiple lines by ending the + string with a double quote, and starting another string on the next + line with another double quote. They will be concatenated in the + result. For example: + + #: lib/remote_branch_delete.tcl:189 + #, tcl-format + msgid "" + "One or more of the merge tests failed because you have not fetched the " + "necessary commits. Try fetching from %s first." + msgstr "" + "HERE YOU WILL WRITE YOUR TRANSLATION OF THE ABOVE LONG " + "MESSAGE IN YOUR LANGUAGE." + +You can test your translation by running "make install", which would +create po/af.msg file and installs the result, and then running the +resulting git-gui under your locale: + + $ make install + $ LANG=af git-gui + +There is a trick to test your translation without first installing, if +you prefer. First, create this symbolic link in the source tree: + + $ ln -s ../po lib/msgs + +After setting up such a symbolic link, you can: + + $ make + $ LANG=af ./git-gui.sh + +When you are satisfied with your translation, commit your changes, and +push it back to the 'mob' branch: + + $ edit po/af.po + ... be sure to update Last-Translator: and + ... PO-Revision-Date: lines. + $ git add po/af.po + $ git commit -m 'Started Afrikaans translation.' + $ git push + + +3. Updating your translation. + +There may already be a translation for your language, and you may want +to contribute an update. This may be because you would want to improve +the translation of existing messages, or because the git-gui software +itself was updated and there are new messages that need translation. + +In any case, make sure you are up-to-date before starting your work: + + $ git pull + +In the former case, you will edit po/af.po (again, replace "af" with +your language code), and after testing and updating the Last-Translator: +and PO-Revision-Date: lines, "add/commit/push" as in the previous +section. + +By comparing "POT-Creation-Date:" line in po/git-gui.pot file and +po/af.po file, you can tell if there are new messages that need to be +translated. You would need the GNU gettext package to perform this +step. + + $ msgmerge -U po/af.po po/git-gui.pot + +[NEEDSWORK: who is responsible for updating po/git-gui.pot file by +running xgettext? IIRC, Christian recommended against running it +nilly-willy because it can become a source of unnecessary merge +conflicts. Perhaps we should mention something like " + +The po/git-gui.pot file is updated by the internationalization +coordinator from time to time. You _could_ update it yourself, but +translators are discouraged from doing so because we would want all +language teams to be working off of the same version of git-gui.pot. + +" here?] + +This updates po/af.po (again, replace "af" with your language +code) so that it contains msgid lines (i.e. the original) that +your translation did not have before. There are a few things to +watch out for: + + - The original text in English of an older message you already + translated might have been changed. You will notice a comment line + that begins with "#, fuzzy" in front of such a message. msgmerge + tool made its best effort to match your old translation with the + message from the updated software, but you may find cases that it + matched your old translated message to a new msgid and the pairing + does not make any sense -- you would need to fix them, and then + remove the "#, fuzzy" line from the message (your fixed translation + of the message will not be used before you remove the marker). + + - New messages added to the software will have msgstr lines with empty + strings. You would need to translate them. From e79bbfea9be31957e0532db67b264d7d8581af30 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sun, 22 Jul 2007 02:12:18 +0100 Subject: [PATCH 0017/1490] Add po/git-gui.pot Usually, generated files are not part of the tracked content in a project. However, translators may lack the tools to generate git-gui.pot. Besides, it is possible that a contributor does not even check out the repository, but gets this file via gitweb. Pointed out by Junio. Signed-off-by: Johannes Schindelin --- po/git-gui.pot | 1264 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1264 insertions(+) create mode 100644 po/git-gui.pot diff --git a/po/git-gui.pot b/po/git-gui.pot new file mode 100644 index 0000000000..991efea5f3 --- /dev/null +++ b/po/git-gui.pot @@ -0,0 +1,1264 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2007-08-11 17:28+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: git-gui.sh:531 +msgid "Cannot find git in PATH." +msgstr "" + +#: git-gui.sh:550 +msgid "Cannot parse Git version string:" +msgstr "" + +#: git-gui.sh:567 +#, tcl-format +msgid "" +"Git version cannot be determined.\n" +"\n" +"%s claims it is version '%s'.\n" +"\n" +"%s requires at least Git 1.5.0 or later.\n" +"\n" +"Assume '%s' is version 1.5.0?\n" +msgstr "" + +#: git-gui.sh:689 +msgid "Cannot find the git directory:" +msgstr "" + +#: git-gui.sh:697 +msgid "Git directory not found:" +msgstr "" + +#: git-gui.sh:703 +msgid "Cannot use funny .git directory:" +msgstr "" + +#: git-gui.sh:708 +msgid "No working directory" +msgstr "" + +#: git-gui.sh:854 +msgid "Refreshing file status..." +msgstr "" + +#: git-gui.sh:891 +msgid "Scanning for modified files ..." +msgstr "" + +#: git-gui.sh:1057 lib/browser.tcl:247 +msgid "Ready." +msgstr "" + +#: git-gui.sh:1322 +msgid "Unmodified" +msgstr "" + +#: git-gui.sh:1324 +msgid "Modified, not staged" +msgstr "" + +#: git-gui.sh:1325 git-gui.sh:1330 +msgid "Staged for commit" +msgstr "" + +#: git-gui.sh:1326 git-gui.sh:1331 +msgid "Portions staged for commit" +msgstr "" + +#: git-gui.sh:1327 git-gui.sh:1332 +msgid "Staged for commit, missing" +msgstr "" + +#: git-gui.sh:1329 +msgid "Untracked, not staged" +msgstr "" + +#: git-gui.sh:1334 +msgid "Missing" +msgstr "" + +#: git-gui.sh:1335 +msgid "Staged for removal" +msgstr "" + +#: git-gui.sh:1336 +msgid "Staged for removal, still present" +msgstr "" + +#: git-gui.sh:1338 git-gui.sh:1339 git-gui.sh:1340 git-gui.sh:1341 +msgid "Requires merge resolution" +msgstr "" + +#: git-gui.sh:1383 +msgid "Starting gitk... please wait..." +msgstr "" + +#: git-gui.sh:1392 +#, tcl-format +msgid "" +"Unable to start gitk:\n" +"\n" +"%s does not exist" +msgstr "" + +#: git-gui.sh:1609 +#, tcl-format +msgid "Invalid font specified in gui.%s:" +msgstr "" + +#: git-gui.sh:1634 +msgid "Main Font" +msgstr "" + +#: git-gui.sh:1635 +msgid "Diff/Console Font" +msgstr "" + +#: git-gui.sh:1649 +msgid "Repository" +msgstr "" + +#: git-gui.sh:1650 +msgid "Edit" +msgstr "" + +#: git-gui.sh:1652 +msgid "Branch" +msgstr "" + +#: git-gui.sh:1655 git-gui.sh:1842 git-gui.sh:2152 +msgid "Commit" +msgstr "" + +#: git-gui.sh:1658 lib/merge.tcl:121 lib/merge.tcl:150 lib/merge.tcl:168 +msgid "Merge" +msgstr "" + +#: git-gui.sh:1659 +msgid "Fetch" +msgstr "" + +#: git-gui.sh:1660 git-gui.sh:2158 lib/transport.tcl:88 lib/transport.tcl:172 +msgid "Push" +msgstr "" + +#: git-gui.sh:1669 +msgid "Browse Current Branch's Files" +msgstr "" + +#: git-gui.sh:1673 +msgid "Browse Branch Files..." +msgstr "" + +#: git-gui.sh:1678 +msgid "Visualize Current Branch's History" +msgstr "" + +#: git-gui.sh:1682 +msgid "Visualize All Branch History" +msgstr "" + +#: git-gui.sh:1689 +#, tcl-format +msgid "Browse %s's Files" +msgstr "" + +#: git-gui.sh:1691 +#, tcl-format +msgid "Visualize %s's History" +msgstr "" + +#: git-gui.sh:1696 lib/database.tcl:27 lib/database.tcl:67 +msgid "Database Statistics" +msgstr "" + +#: git-gui.sh:1699 lib/database.tcl:34 +msgid "Compress Database" +msgstr "" + +#: git-gui.sh:1702 +msgid "Verify Database" +msgstr "" + +#: git-gui.sh:1709 git-gui.sh:1713 git-gui.sh:1717 lib/shortcut.tcl:9 +#: lib/shortcut.tcl:45 lib/shortcut.tcl:84 +msgid "Create Desktop Icon" +msgstr "" + +#: git-gui.sh:1722 +msgid "Quit" +msgstr "" + +#: git-gui.sh:1729 +msgid "Undo" +msgstr "" + +#: git-gui.sh:1732 +msgid "Redo" +msgstr "" + +#: git-gui.sh:1736 git-gui.sh:2222 +msgid "Cut" +msgstr "" + +#: git-gui.sh:1739 git-gui.sh:2225 git-gui.sh:2296 git-gui.sh:2368 +#: lib/console.tcl:69 +msgid "Copy" +msgstr "" + +#: git-gui.sh:1742 git-gui.sh:2228 +msgid "Paste" +msgstr "" + +#: git-gui.sh:1745 git-gui.sh:2231 lib/branch_delete.tcl:26 +#: lib/remote_branch_delete.tcl:38 +msgid "Delete" +msgstr "" + +#: git-gui.sh:1749 git-gui.sh:2235 git-gui.sh:2372 lib/console.tcl:71 +msgid "Select All" +msgstr "" + +#: git-gui.sh:1758 +msgid "Create..." +msgstr "" + +#: git-gui.sh:1764 +msgid "Checkout..." +msgstr "" + +#: git-gui.sh:1770 +msgid "Rename..." +msgstr "" + +#: git-gui.sh:1775 git-gui.sh:1873 +msgid "Delete..." +msgstr "" + +#: git-gui.sh:1780 +msgid "Reset..." +msgstr "" + +#: git-gui.sh:1792 git-gui.sh:2169 +msgid "New Commit" +msgstr "" + +#: git-gui.sh:1800 git-gui.sh:2176 +msgid "Amend Last Commit" +msgstr "" + +#: git-gui.sh:1809 git-gui.sh:2136 lib/remote_branch_delete.tcl:99 +msgid "Rescan" +msgstr "" + +#: git-gui.sh:1815 +msgid "Stage To Commit" +msgstr "" + +#: git-gui.sh:1820 +msgid "Stage Changed Files To Commit" +msgstr "" + +#: git-gui.sh:1826 +msgid "Unstage From Commit" +msgstr "" + +#: git-gui.sh:1831 lib/index.tcl:376 +msgid "Revert Changes" +msgstr "" + +#: git-gui.sh:1838 git-gui.sh:2148 git-gui.sh:2246 +msgid "Sign Off" +msgstr "" + +#: git-gui.sh:1853 +msgid "Local Merge..." +msgstr "" + +#: git-gui.sh:1858 +msgid "Abort Merge..." +msgstr "" + +#: git-gui.sh:1870 +msgid "Push..." +msgstr "" + +#: git-gui.sh:1880 +msgid "Apple" +msgstr "" + +#: git-gui.sh:1883 git-gui.sh:1901 lib/option.tcl:65 +#, tcl-format +msgid "About %s" +msgstr "" + +#: git-gui.sh:1885 git-gui.sh:1891 git-gui.sh:2414 +msgid "Options..." +msgstr "" + +#: git-gui.sh:1897 +msgid "Help" +msgstr "" + +#: git-gui.sh:1938 +msgid "Online Documentation" +msgstr "" + +#: git-gui.sh:2054 +msgid "Current Branch:" +msgstr "" + +#: git-gui.sh:2075 +msgid "Staged Changes (Will Be Committed)" +msgstr "" + +#: git-gui.sh:2095 +msgid "Unstaged Changes (Will Not Be Committed)" +msgstr "" + +#: git-gui.sh:2142 +msgid "Stage Changed" +msgstr "" + +#: git-gui.sh:2188 +msgid "Initial Commit Message:" +msgstr "" + +#: git-gui.sh:2189 +msgid "Amended Commit Message:" +msgstr "" + +#: git-gui.sh:2190 +msgid "Amended Initial Commit Message:" +msgstr "" + +#: git-gui.sh:2191 +msgid "Amended Merge Commit Message:" +msgstr "" + +#: git-gui.sh:2192 +msgid "Merge Commit Message:" +msgstr "" + +#: git-gui.sh:2193 +msgid "Commit Message:" +msgstr "" + +#: git-gui.sh:2238 git-gui.sh:2376 lib/console.tcl:73 +msgid "Copy All" +msgstr "" + +#: git-gui.sh:2262 lib/blame.tcl:104 +msgid "File:" +msgstr "" + +#: git-gui.sh:2364 +msgid "Refresh" +msgstr "" + +#: git-gui.sh:2385 +msgid "Apply/Reverse Hunk" +msgstr "" + +#: git-gui.sh:2391 +msgid "Decrease Font Size" +msgstr "" + +#: git-gui.sh:2395 +msgid "Increase Font Size" +msgstr "" + +#: git-gui.sh:2400 +msgid "Show Less Context" +msgstr "" + +#: git-gui.sh:2407 +msgid "Show More Context" +msgstr "" + +#: git-gui.sh:2422 +msgid "Unstage Hunk From Commit" +msgstr "" + +#: git-gui.sh:2426 git-gui.sh:2430 +msgid "Stage Hunk For Commit" +msgstr "" + +#: git-gui.sh:2440 +msgid "Initializing..." +msgstr "" + +#: lib/blame.tcl:77 +msgid "File Viewer" +msgstr "" + +#: lib/blame.tcl:81 +msgid "Commit:" +msgstr "" + +#: lib/blame.tcl:249 +msgid "Copy Commit" +msgstr "" + +#: lib/blame.tcl:369 +#, tcl-format +msgid "Reading %s..." +msgstr "" + +#: lib/branch_checkout.tcl:14 lib/branch_checkout.tcl:19 +msgid "Checkout Branch" +msgstr "" + +#: lib/branch_checkout.tcl:23 +msgid "Checkout" +msgstr "" + +#: lib/branch_checkout.tcl:27 lib/branch_create.tcl:35 +#: lib/branch_delete.tcl:32 lib/branch_rename.tcl:30 lib/browser.tcl:283 +#: lib/checkout_op.tcl:522 lib/merge.tcl:172 lib/option.tcl:172 +#: lib/remote_branch_delete.tcl:42 lib/transport.tcl:92 +msgid "Cancel" +msgstr "" + +#: lib/branch_checkout.tcl:32 lib/browser.tcl:288 +msgid "Revision" +msgstr "" + +#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:159 +#: lib/option.tcl:274 +msgid "Options" +msgstr "" + +#: lib/branch_checkout.tcl:39 lib/branch_create.tcl:92 +msgid "Fetch Tracking Branch" +msgstr "" + +#: lib/branch_checkout.tcl:44 +msgid "Detach From Local Branch" +msgstr "" + +#: lib/branch_create.tcl:22 +msgid "Create Branch" +msgstr "" + +#: lib/branch_create.tcl:27 +msgid "Create New Branch" +msgstr "" + +#: lib/branch_create.tcl:31 +msgid "Create" +msgstr "" + +#: lib/branch_create.tcl:40 +msgid "Branch Name" +msgstr "" + +#: lib/branch_create.tcl:43 +msgid "Name:" +msgstr "" + +#: lib/branch_create.tcl:58 +msgid "Match Tracking Branch Name" +msgstr "" + +#: lib/branch_create.tcl:66 +msgid "Starting Revision" +msgstr "" + +#: lib/branch_create.tcl:72 +msgid "Update Existing Branch:" +msgstr "" + +#: lib/branch_create.tcl:75 +msgid "No" +msgstr "" + +#: lib/branch_create.tcl:80 +msgid "Fast Forward Only" +msgstr "" + +#: lib/branch_create.tcl:85 lib/checkout_op.tcl:514 +msgid "Reset" +msgstr "" + +#: lib/branch_create.tcl:97 +msgid "Checkout After Creation" +msgstr "" + +#: lib/branch_create.tcl:131 +msgid "Please select a tracking branch." +msgstr "" + +#: lib/branch_create.tcl:140 +#, tcl-format +msgid "Tracking branch %s is not a branch in the remote repository." +msgstr "" + +#: lib/branch_create.tcl:153 lib/branch_rename.tcl:86 +msgid "Please supply a branch name." +msgstr "" + +#: lib/branch_create.tcl:164 lib/branch_rename.tcl:106 +#, tcl-format +msgid "'%s' is not an acceptable branch name." +msgstr "" + +#: lib/branch_delete.tcl:15 +msgid "Delete Branch" +msgstr "" + +#: lib/branch_delete.tcl:20 +msgid "Delete Local Branch" +msgstr "" + +#: lib/branch_delete.tcl:37 +msgid "Local Branches" +msgstr "" + +#: lib/branch_delete.tcl:52 +msgid "Delete Only If Merged Into" +msgstr "" + +#: lib/branch_delete.tcl:54 +msgid "Always (Do not perform merge test.)" +msgstr "" + +#: lib/branch_delete.tcl:103 +#, tcl-format +msgid "The following branches are not completely merged into %s:" +msgstr "" + +#: lib/branch_delete.tcl:115 +msgid "" +"Recovering deleted branches is difficult. \n" +"\n" +" Delete the selected branches?" +msgstr "" + +#: lib/branch_delete.tcl:141 +#, tcl-format +msgid "" +"Failed to delete branches:\n" +"%s" +msgstr "" + +#: lib/branch_rename.tcl:14 lib/branch_rename.tcl:22 +msgid "Rename Branch" +msgstr "" + +#: lib/branch_rename.tcl:26 +msgid "Rename" +msgstr "" + +#: lib/branch_rename.tcl:36 +msgid "Branch:" +msgstr "" + +#: lib/branch_rename.tcl:39 +msgid "New Name:" +msgstr "" + +#: lib/branch_rename.tcl:75 +msgid "Please select a branch to rename." +msgstr "" + +#: lib/branch_rename.tcl:96 lib/checkout_op.tcl:179 +#, tcl-format +msgid "Branch '%s' already exists." +msgstr "" + +#: lib/branch_rename.tcl:117 +#, tcl-format +msgid "Failed to rename '%s'." +msgstr "" + +#: lib/browser.tcl:17 +msgid "Starting..." +msgstr "" + +#: lib/browser.tcl:26 +msgid "File Browser" +msgstr "" + +#: lib/browser.tcl:127 lib/browser.tcl:144 +#, tcl-format +msgid "Loading %s..." +msgstr "" + +#: lib/browser.tcl:188 +msgid "[Up To Parent]" +msgstr "" + +#: lib/browser.tcl:268 lib/browser.tcl:274 +msgid "Browse Branch Files" +msgstr "" + +#: lib/browser.tcl:279 +msgid "Browse" +msgstr "" + +#: lib/checkout_op.tcl:79 +#, tcl-format +msgid "Fetching %s from %s" +msgstr "" + +#: lib/checkout_op.tcl:140 lib/console.tcl:81 lib/database.tcl:31 +msgid "Close" +msgstr "" + +#: lib/checkout_op.tcl:169 +#, tcl-format +msgid "Branch '%s' does not exist." +msgstr "" + +#: lib/checkout_op.tcl:206 +#, tcl-format +msgid "" +"Branch '%s' already exists.\n" +"\n" +"It cannot fast-forward to %s.\n" +"A merge is required." +msgstr "" + +#: lib/checkout_op.tcl:220 +#, tcl-format +msgid "Merge strategy '%s' not supported." +msgstr "" + +#: lib/checkout_op.tcl:239 +#, tcl-format +msgid "Failed to update '%s'." +msgstr "" + +#: lib/checkout_op.tcl:251 +msgid "Staging area (index) is already locked." +msgstr "" + +#: lib/checkout_op.tcl:266 +msgid "" +"Last scanned state does not match repository state.\n" +"\n" +"Another Git program has modified this repository since the last scan. A " +"rescan must be performed before the current branch can be changed.\n" +"\n" +"The rescan will be automatically started now.\n" +msgstr "" + +#: lib/checkout_op.tcl:353 +#, tcl-format +msgid "Aborted checkout of '%s' (file level merging is required)." +msgstr "" + +#: lib/checkout_op.tcl:354 +msgid "File level merge required." +msgstr "" + +#: lib/checkout_op.tcl:358 +#, tcl-format +msgid "Staying on branch '%s'." +msgstr "" + +#: lib/checkout_op.tcl:429 +msgid "" +"You are no longer on a local branch.\n" +"\n" +"If you wanted to be on a branch, create one now starting from 'This Detached " +"Checkout'." +msgstr "" + +#: lib/checkout_op.tcl:478 +#, tcl-format +msgid "Resetting '%s' to '%s' will lose the following commits:" +msgstr "" + +#: lib/checkout_op.tcl:500 +msgid "Recovering lost commits may not be easy." +msgstr "" + +#: lib/checkout_op.tcl:505 +#, tcl-format +msgid "Reset '%s'?" +msgstr "" + +#: lib/checkout_op.tcl:510 lib/merge.tcl:164 +msgid "Visualize" +msgstr "" + +#: lib/checkout_op.tcl:578 +#, tcl-format +msgid "" +"Failed to set current branch.\n" +"\n" +"This working directory is only partially switched. We successfully updated " +"your files, but failed to update an internal Git file.\n" +"\n" +"This should not have occurred. %s will now close and give up." +msgstr "" + +#: lib/choose_rev.tcl:53 +msgid "This Detached Checkout" +msgstr "" + +#: lib/choose_rev.tcl:60 +msgid "Revision Expression:" +msgstr "" + +#: lib/choose_rev.tcl:74 +msgid "Local Branch" +msgstr "" + +#: lib/choose_rev.tcl:79 +msgid "Tracking Branch" +msgstr "" + +#: lib/choose_rev.tcl:84 +msgid "Tag" +msgstr "" + +#: lib/choose_rev.tcl:317 +#, tcl-format +msgid "Invalid revision: %s" +msgstr "" + +#: lib/choose_rev.tcl:338 +msgid "No revision selected." +msgstr "" + +#: lib/choose_rev.tcl:346 +msgid "Revision expression is empty." +msgstr "" + +#: lib/commit.tcl:9 +msgid "" +"There is nothing to amend.\n" +"\n" +"You are about to create the initial commit. There is no commit before this " +"to amend.\n" +msgstr "" + +#: lib/commit.tcl:18 +msgid "" +"Cannot amend while merging.\n" +"\n" +"You are currently in the middle of a merge that has not been fully " +"completed. You cannot amend the prior commit unless you first abort the " +"current merge activity.\n" +msgstr "" + +#: lib/commit.tcl:49 +msgid "Error loading commit data for amend:" +msgstr "" + +#: lib/commit.tcl:76 +msgid "Unable to obtain your identity:" +msgstr "" + +#: lib/commit.tcl:81 +msgid "Invalid GIT_COMMITTER_IDENT:" +msgstr "" + +#: lib/commit.tcl:133 +msgid "" +"Last scanned state does not match repository state.\n" +"\n" +"Another Git program has modified this repository since the last scan. A " +"rescan must be performed before another commit can be created.\n" +"\n" +"The rescan will be automatically started now.\n" +msgstr "" + +#: lib/commit.tcl:154 +#, tcl-format +msgid "" +"Unmerged files cannot be committed.\n" +"\n" +"File %s has merge conflicts. You must resolve them and stage the file " +"before committing.\n" +msgstr "" + +#: lib/commit.tcl:162 +#, tcl-format +msgid "" +"Unknown file state %s detected.\n" +"\n" +"File %s cannot be committed by this program.\n" +msgstr "" + +#: lib/commit.tcl:170 +msgid "" +"No changes to commit.\n" +"\n" +"You must stage at least 1 file before you can commit.\n" +msgstr "" + +#: lib/commit.tcl:183 +msgid "" +"Please supply a commit message.\n" +"\n" +"A good commit message has the following format:\n" +"\n" +"- First line: Describe in one sentance what you did.\n" +"- Second line: Blank\n" +"- Remaining lines: Describe why this change is good.\n" +msgstr "" + +#: lib/commit.tcl:257 +msgid "write-tree failed:" +msgstr "" + +#: lib/commit.tcl:279 +msgid "" +"No changes to commit.\n" +"\n" +"No files were modified by this commit and it was not a merge commit.\n" +"\n" +"A rescan will be automatically started now.\n" +msgstr "" + +#: lib/commit.tcl:286 +msgid "No changes to commit." +msgstr "" + +#: lib/commit.tcl:317 +msgid "commit-tree failed:" +msgstr "" + +#: lib/commit.tcl:339 +msgid "update-ref failed:" +msgstr "" + +#: lib/commit.tcl:430 +#, tcl-format +msgid "Created commit %s: %s" +msgstr "" + +#: lib/console.tcl:55 +msgid "Working... please wait..." +msgstr "" + +#: lib/console.tcl:184 +msgid "Success" +msgstr "" + +#: lib/console.tcl:194 +msgid "Error: Command Failed" +msgstr "" + +#: lib/database.tcl:43 +msgid "Number of loose objects" +msgstr "" + +#: lib/database.tcl:44 +msgid "Disk space used by loose objects" +msgstr "" + +#: lib/database.tcl:45 +msgid "Number of packed objects" +msgstr "" + +#: lib/database.tcl:46 +msgid "Number of packs" +msgstr "" + +#: lib/database.tcl:47 +msgid "Disk space used by packed objects" +msgstr "" + +#: lib/database.tcl:48 +msgid "Packed objects waiting for pruning" +msgstr "" + +#: lib/database.tcl:49 +msgid "Garbage files" +msgstr "" + +#: lib/database.tcl:72 +msgid "Compressing the object database" +msgstr "" + +#: lib/database.tcl:83 +msgid "Verifying the object database with fsck-objects" +msgstr "" + +#: lib/diff.tcl:42 +#, tcl-format +msgid "" +"No differences detected.\n" +"\n" +"%s has no changes.\n" +"\n" +"The modification date of this file was updated by another application, but " +"the content within the file was not changed.\n" +"\n" +"A rescan will be automatically started to find other files which may have " +"the same state." +msgstr "" + +#: lib/diff.tcl:97 +msgid "Error loading file:" +msgstr "" + +#: lib/diff.tcl:162 +msgid "Error loading diff:" +msgstr "" + +#: lib/diff.tcl:278 +msgid "Failed to unstage selected hunk." +msgstr "" + +#: lib/diff.tcl:285 +msgid "Failed to stage selected hunk." +msgstr "" + +#: lib/error.tcl:12 lib/error.tcl:102 +msgid "error" +msgstr "" + +#: lib/error.tcl:28 +msgid "warning" +msgstr "" + +#: lib/error.tcl:81 +msgid "You must correct the above errors before committing." +msgstr "" + +#: lib/index.tcl:364 +#, tcl-format +msgid "Revert changes in file %s?" +msgstr "" + +#: lib/index.tcl:366 +#, tcl-format +msgid "Revert changes in these %i files?" +msgstr "" + +#: lib/index.tcl:372 +msgid "Any unstaged changes will be permanently lost by the revert." +msgstr "" + +#: lib/index.tcl:375 +msgid "Do Nothing" +msgstr "" + +#: lib/merge.tcl:13 +msgid "" +"Cannot merge while amending.\n" +"\n" +"You must finish amending this commit before starting any type of merge.\n" +msgstr "" + +#: lib/merge.tcl:27 +msgid "" +"Last scanned state does not match repository state.\n" +"\n" +"Another Git program has modified this repository since the last scan. A " +"rescan must be performed before a merge can be performed.\n" +"\n" +"The rescan will be automatically started now.\n" +msgstr "" + +#: lib/merge.tcl:44 +#, tcl-format +msgid "" +"You are in the middle of a conflicted merge.\n" +"\n" +"File %s has merge conflicts.\n" +"\n" +"You must resolve them, stage the file, and commit to complete the current " +"merge. Only then can you begin another merge.\n" +msgstr "" + +#: lib/merge.tcl:54 +#, tcl-format +msgid "" +"You are in the middle of a change.\n" +"\n" +"File %s is modified.\n" +"\n" +"You should complete the current commit before starting a merge. Doing so " +"will help you abort a failed merge, should the need arise.\n" +msgstr "" + +#: lib/merge.tcl:106 +#, tcl-format +msgid "%s of %s" +msgstr "" + +#: lib/merge.tcl:119 +#, tcl-format +msgid "Merging %s and %s" +msgstr "" + +#: lib/merge.tcl:131 +msgid "Merge completed successfully." +msgstr "" + +#: lib/merge.tcl:133 +msgid "Merge failed. Conflict resolution is required." +msgstr "" + +#: lib/merge.tcl:158 +#, tcl-format +msgid "Merge Into %s" +msgstr "" + +#: lib/merge.tcl:177 +msgid "Revision To Merge" +msgstr "" + +#: lib/merge.tcl:212 +msgid "" +"Cannot abort while amending.\n" +"\n" +"You must finish amending this commit.\n" +msgstr "" + +#: lib/merge.tcl:222 +msgid "" +"Abort merge?\n" +"\n" +"Aborting the current merge will cause *ALL* uncommitted changes to be lost.\n" +"\n" +"Continue with aborting the current merge?" +msgstr "" + +#: lib/merge.tcl:228 +msgid "" +"Reset changes?\n" +"\n" +"Resetting the changes will cause *ALL* uncommitted changes to be lost.\n" +"\n" +"Continue with resetting the current changes?" +msgstr "" + +#: lib/merge.tcl:239 +msgid "Aborting" +msgstr "" + +#: lib/merge.tcl:266 +msgid "Abort failed." +msgstr "" + +#: lib/merge.tcl:268 +msgid "Abort completed. Ready." +msgstr "" + +#: lib/option.tcl:77 +msgid "git-gui - a graphical user interface for Git." +msgstr "" + +#: lib/option.tcl:164 +msgid "Restore Defaults" +msgstr "" + +#: lib/option.tcl:168 +msgid "Save" +msgstr "" + +#: lib/option.tcl:178 +#, tcl-format +msgid "%s Repository" +msgstr "" + +#: lib/option.tcl:179 +msgid "Global (All Repositories)" +msgstr "" + +#: lib/option.tcl:185 +msgid "User Name" +msgstr "" + +#: lib/option.tcl:186 +msgid "Email Address" +msgstr "" + +#: lib/option.tcl:188 +msgid "Summarize Merge Commits" +msgstr "" + +#: lib/option.tcl:189 +msgid "Merge Verbosity" +msgstr "" + +#: lib/option.tcl:190 +msgid "Show Diffstat After Merge" +msgstr "" + +#: lib/option.tcl:192 +msgid "Trust File Modification Timestamps" +msgstr "" + +#: lib/option.tcl:193 +msgid "Prune Tracking Branches During Fetch" +msgstr "" + +#: lib/option.tcl:194 +msgid "Match Tracking Branches" +msgstr "" + +#: lib/option.tcl:195 +msgid "Number of Diff Context Lines" +msgstr "" + +#: lib/option.tcl:196 +msgid "New Branch Name Template" +msgstr "" + +#: lib/option.tcl:305 +msgid "Failed to completely save options:" +msgstr "" + +#: lib/remote_branch_delete.tcl:29 lib/remote_branch_delete.tcl:34 +msgid "Delete Remote Branch" +msgstr "" + +#: lib/remote_branch_delete.tcl:47 +msgid "From Repository" +msgstr "" + +#: lib/remote_branch_delete.tcl:50 lib/transport.tcl:118 +msgid "Remote:" +msgstr "" + +#: lib/remote_branch_delete.tcl:66 lib/transport.tcl:133 +msgid "Arbitrary URL:" +msgstr "" + +#: lib/remote_branch_delete.tcl:84 +msgid "Branches" +msgstr "" + +#: lib/remote_branch_delete.tcl:109 +msgid "Delete Only If" +msgstr "" + +#: lib/remote_branch_delete.tcl:111 +msgid "Merged Into:" +msgstr "" + +#: lib/remote_branch_delete.tcl:119 +msgid "Always (Do not perform merge checks)" +msgstr "" + +#: lib/remote_branch_delete.tcl:152 +msgid "A branch is required for 'Merged Into'." +msgstr "" + +#: lib/remote_branch_delete.tcl:189 +#, tcl-format +msgid "" +"One or more of the merge tests failed because you have not fetched the " +"necessary commits. Try fetching from %s first." +msgstr "" + +#: lib/remote_branch_delete.tcl:207 +msgid "Please select one or more branches to delete." +msgstr "" + +#: lib/remote_branch_delete.tcl:216 +msgid "" +"Recovering deleted branches is difficult.\n" +"\n" +"Delete the selected branches?" +msgstr "" + +#: lib/remote_branch_delete.tcl:226 +#, tcl-format +msgid "Deleting branches from %s" +msgstr "" + +#: lib/remote_branch_delete.tcl:286 +msgid "No repository selected." +msgstr "" + +#: lib/remote_branch_delete.tcl:291 +#, tcl-format +msgid "Scanning %s..." +msgstr "" + +#: lib/remote.tcl:162 +#, tcl-format +msgid "Fetch from %s..." +msgstr "" + +#: lib/remote.tcl:172 +#, tcl-format +msgid "Prune from %s..." +msgstr "" + +#: lib/remote.tcl:206 +#, tcl-format +msgid "Push to %s..." +msgstr "" + +#: lib/shortcut.tcl:26 lib/shortcut.tcl:74 +msgid "Cannot write script:" +msgstr "" + +#: lib/shortcut.tcl:149 +msgid "Cannot write icon:" +msgstr "" + +#: lib/status_bar.tcl:58 +#, tcl-format +msgid "%s ... %i of %i %s (%2i%%)" +msgstr "" + +#: lib/transport.tcl:7 +#, tcl-format +msgid "Fetching new changes from %s" +msgstr "" + +#: lib/transport.tcl:19 +#, tcl-format +msgid "Pruning tracking branches deleted from %s" +msgstr "" + +#: lib/transport.tcl:26 +#, tcl-format +msgid "Pushing changes to %s" +msgstr "" + +#: lib/transport.tcl:68 +#, tcl-format +msgid "Pushing %s %s to %s" +msgstr "" + +#: lib/transport.tcl:84 +msgid "Push Branches" +msgstr "" + +#: lib/transport.tcl:98 +msgid "Source Branches" +msgstr "" + +#: lib/transport.tcl:115 +msgid "Destination Repository" +msgstr "" + +#: lib/transport.tcl:153 +msgid "Transfer Options" +msgstr "" + +#: lib/transport.tcl:155 +msgid "Use thin pack (for slow network connections)" +msgstr "" + +#: lib/transport.tcl:159 +msgid "Include tags" +msgstr "" From 9f1a80877a59aeae1626296fac25360d9a81954e Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sun, 22 Jul 2007 12:31:45 +0100 Subject: [PATCH 0018/1490] Ignore po/*.msg Signed-off-by: Johannes Schindelin --- po/.gitignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 po/.gitignore diff --git a/po/.gitignore b/po/.gitignore new file mode 100644 index 0000000000..a89cf44969 --- /dev/null +++ b/po/.gitignore @@ -0,0 +1,2 @@ +*.msg +*~ From 660a68cf1816075b935c67aa780fd1b2484c0f2f Mon Sep 17 00:00:00 2001 From: Christian Stimming Date: Mon, 23 Jul 2007 22:11:12 +0200 Subject: [PATCH 0019/1490] Add glossary that can be converted into a po file for each language. Signed-off-by: Johannes Schindelin --- po/glossary/Makefile | 9 ++++++ po/glossary/git-gui-glossary.txt | 34 ++++++++++++++++++++++ po/glossary/txt-to-pot.sh | 48 ++++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+) create mode 100644 po/glossary/Makefile create mode 100644 po/glossary/git-gui-glossary.txt create mode 100755 po/glossary/txt-to-pot.sh diff --git a/po/glossary/Makefile b/po/glossary/Makefile new file mode 100644 index 0000000000..749aa2e7ec --- /dev/null +++ b/po/glossary/Makefile @@ -0,0 +1,9 @@ +PO_TEMPLATE = git-gui-glossary.pot + +ALL_POFILES = $(wildcard *.po) + +$(PO_TEMPLATE): $(subst .pot,.txt,$(PO_TEMPLATE)) + ./txt-to-pot.sh $< > $@ + +update-po:: git-gui-glossary.pot + $(foreach p, $(ALL_POFILES), echo Updating $p ; msgmerge -U $p $(PO_TEMPLATE) ; ) diff --git a/po/glossary/git-gui-glossary.txt b/po/glossary/git-gui-glossary.txt new file mode 100644 index 0000000000..bb55aa827d --- /dev/null +++ b/po/glossary/git-gui-glossary.txt @@ -0,0 +1,34 @@ +"English Term (Dear translator: This file will never be visible to the user!)" "English Definition (Dear translator: This file will never be visible to the user! It should only serve as a tool for you, the translator. Nothing more.)" +"amend" "" +"annotate" "" +"branch [noun]" "A 'branch' is an active line of development." +"branch [verb]" "" +"checkout [noun]" "" +"checkout [verb]" "The action of updating the working tree to a revision which was stored in the object database." +"commit [noun]" "A single point in the git history." +"commit [verb]" "The action of storing a new snapshot of the project's state in the git history." +"diff [noun]" "" +"diff [verb]" "" +"fast forward merge" "A fast-forward is a special type of merge where you have a revision and you are merging another branch's changes that happen to be a descendant of what you have." +"fetch" "Fetching a branch means to get the branch's head from a remote repository, to find out which objects are missing from the local object database, and to get them, too." +"index (in git-gui: staging area)" "A collection of files. The index is a stored version of your working tree." +"merge [noun]" "A successful merge results in the creation of a new commit representing the result of the merge." +"merge [verb]" "To bring the contents of another branch into the current branch." +"message" "" +"pull" "Pulling a branch means to fetch it and merge it." +"push" "Pushing a branch means to get the branch's head ref from a remote repository, and ... (well, can someone please explain it for mere mortals?)" +"redo" "" +"repository" "A collection of refs (?) together with an object database containing all objects which are reachable from the refs... (oops, you've lost me here. Again, please an explanation for mere mortals?)" +"reset" "" +"revert" "" +"revision" "A particular state of files and directories which was stored in the object database." +"sign off" "" +"staging area" "" +"status" "" +"tag [noun]" "A ref pointing to a tag or commit object" +"tag [verb]" "" +"tracking branch" "A regular git branch that is used to follow changes from another repository." +"undo" "" +"update" "" +"verify" "" +"working copy, working tree" "The tree of actual checked out files." diff --git a/po/glossary/txt-to-pot.sh b/po/glossary/txt-to-pot.sh new file mode 100755 index 0000000000..49bf7c5365 --- /dev/null +++ b/po/glossary/txt-to-pot.sh @@ -0,0 +1,48 @@ +#!/bin/sh +# This is a very, _very_, simple script to convert a tab-separated +# .txt file into a .pot/.po. +# Its not clever but it took me 2 minutes to write :) +# Michael Twomey +# 23 March 2001 +# with slight GnuCash modifications by Christian Stimming +# 19 Aug 2001, 23 Jul 2007 + +#check args +if [ $# -eq 0 ] +then + cat < git-gui-glossary.pot +! + exit 1; +fi + +GLOSSARY_CSV="$1"; + +if [ ! -f "$GLOSSARY_CSV" ] +then + echo "Can't find $GLOSSARY_CSV."; + exit 1; +fi + +cat <, YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: `date +'%Y-%m-%d %H:%M%z'`\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: ENCODING\n" + +! + +#Yes this is the most simple awk script you've ever seen :) +awk -F'\t' '{if ($2 != "") print "#. "$2; print "msgid "$1; print "msgstr \"\"\n"}' \ +$GLOSSARY_CSV From 3b703b2a380c276da946338ad16801a12962b000 Mon Sep 17 00:00:00 2001 From: Christian Stimming Date: Fri, 27 Jul 2007 19:24:45 +0200 Subject: [PATCH 0020/1490] Add glossary translation template into git. This way, it should be easier for new translators to actually find out about the glossary. Signed-off-by: Johannes Schindelin --- po/glossary/git-gui-glossary.pot | 152 +++++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 po/glossary/git-gui-glossary.pot diff --git a/po/glossary/git-gui-glossary.pot b/po/glossary/git-gui-glossary.pot new file mode 100644 index 0000000000..c955b46744 --- /dev/null +++ b/po/glossary/git-gui-glossary.pot @@ -0,0 +1,152 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Free Software Foundation, Inc. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2007-07-27 19:21+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: ENCODING\n" + +#. "English Definition (Dear translator: This file will never be visible to the user! It should only serve as a tool for you, the translator. Nothing more.)" +msgid "English Term (Dear translator: This file will never be visible to the user!)" +msgstr "" + +#. "" +msgid "amend" +msgstr "" + +#. "" +msgid "annotate" +msgstr "" + +#. "A 'branch' is an active line of development." +msgid "branch [noun]" +msgstr "" + +#. "" +msgid "branch [verb]" +msgstr "" + +#. "" +msgid "checkout [noun]" +msgstr "" + +#. "The action of updating the working tree to a revision which was stored in the object database." +msgid "checkout [verb]" +msgstr "" + +#. "A single point in the git history." +msgid "commit [noun]" +msgstr "" + +#. "The action of storing a new snapshot of the project's state in the git history." +msgid "commit [verb]" +msgstr "" + +#. "" +msgid "diff [noun]" +msgstr "" + +#. "" +msgid "diff [verb]" +msgstr "" + +#. "A fast-forward is a special type of merge where you have a revision and you are merging another branch's changes that happen to be a descendant of what you have." +msgid "fast forward merge" +msgstr "" + +#. "Fetching a branch means to get the branch's head from a remote repository, to find out which objects are missing from the local object database, and to get them, too." +msgid "fetch" +msgstr "" + +#. "A collection of files. The index is a stored version of your working tree." +msgid "index (in git-gui: staging area)" +msgstr "" + +#. "A successful merge results in the creation of a new commit representing the result of the merge." +msgid "merge [noun]" +msgstr "" + +#. "To bring the contents of another branch into the current branch." +msgid "merge [verb]" +msgstr "" + +#. "" +msgid "message" +msgstr "" + +#. "Pulling a branch means to fetch it and merge it." +msgid "pull" +msgstr "" + +#. "Pushing a branch means to get the branch's head ref from a remote repository, and ... (well, can someone please explain it for mere mortals?)" +msgid "push" +msgstr "" + +#. "" +msgid "redo" +msgstr "" + +#. "A collection of refs (?) together with an object database containing all objects which are reachable from the refs... (oops, you've lost me here. Again, please an explanation for mere mortals?)" +msgid "repository" +msgstr "" + +#. "" +msgid "reset" +msgstr "" + +#. "" +msgid "revert" +msgstr "" + +#. "A particular state of files and directories which was stored in the object database." +msgid "revision" +msgstr "" + +#. "" +msgid "sign off" +msgstr "" + +#. "" +msgid "staging area" +msgstr "" + +#. "" +msgid "status" +msgstr "" + +#. "A ref pointing to a tag or commit object" +msgid "tag [noun]" +msgstr "" + +#. "" +msgid "tag [verb]" +msgstr "" + +#. "A regular git branch that is used to follow changes from another repository." +msgid "tracking branch" +msgstr "" + +#. "" +msgid "undo" +msgstr "" + +#. "" +msgid "update" +msgstr "" + +#. "" +msgid "verify" +msgstr "" + +#. "The tree of actual checked out files." +msgid "working copy, working tree" +msgstr "" + From 90a7149ff15ea0ee0e2ad04ea72ac64e29a1cb52 Mon Sep 17 00:00:00 2001 From: Christian Stimming Date: Sat, 21 Jul 2007 14:18:14 +0200 Subject: [PATCH 0021/1490] German translation for git-gui Signed-off-by: Christian Stimming Signed-off-by: Johannes Schindelin --- po/de.po | 1398 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1398 insertions(+) create mode 100644 po/de.po diff --git a/po/de.po b/po/de.po new file mode 100644 index 0000000000..7d57dd15f9 --- /dev/null +++ b/po/de.po @@ -0,0 +1,1398 @@ +# Translation of git-gui to German. +# Copyright (C) 2007 Shawn Pearce, et al. +# This file is distributed under the same license as the git package. +# Christian Stimming , 2007 +# +msgid "" +msgstr "" +"Project-Id-Version: git-gui\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2007-08-11 17:28+0200\n" +"PO-Revision-Date: 2007-08-11 17:37+0200\n" +"Last-Translator: Christian Stimming \n" +"Language-Team: German\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: git-gui.sh:531 +msgid "Cannot find git in PATH." +msgstr "Git kann im PATH nicht gefunden werden." + +#: git-gui.sh:550 +msgid "Cannot parse Git version string:" +msgstr "Git Versionsangabe kann nicht erkannt werden:" + +#: git-gui.sh:567 +#, tcl-format +msgid "" +"Git version cannot be determined.\n" +"\n" +"%s claims it is version '%s'.\n" +"\n" +"%s requires at least Git 1.5.0 or later.\n" +"\n" +"Assume '%s' is version 1.5.0?\n" +msgstr "" +"Die Version von Git kann nicht bestimmt werden.\n" +"\n" +"»%s« behauptet, es sei Version »%s«.\n" +"\n" +"%s benötigt mindestens Git 1.5.0 oder höher.\n" +"\n" +"Soll angenommen werden, »%s« sei Version 1.5.0?\n" + +#: git-gui.sh:689 +msgid "Cannot find the git directory:" +msgstr "Git-Verzeichnis kann nicht gefunden werden:" + +#: git-gui.sh:697 +msgid "Git directory not found:" +msgstr "Git-Verzeichnis nicht gefunden:" + +#: git-gui.sh:703 +msgid "Cannot use funny .git directory:" +msgstr "Unerwartete Struktur des .git Verzeichnis:" + +#: git-gui.sh:708 +msgid "No working directory" +msgstr "Kein Arbeitsverzeichnis" + +#: git-gui.sh:854 +msgid "Refreshing file status..." +msgstr "Dateistatus aktualisieren..." + +#: git-gui.sh:891 +msgid "Scanning for modified files ..." +msgstr "Nach geänderten Dateien suchen..." + +#: git-gui.sh:1057 lib/browser.tcl:247 +msgid "Ready." +msgstr "Bereit." + +#: git-gui.sh:1322 +msgid "Unmodified" +msgstr "Unverändert" + +#: git-gui.sh:1324 +msgid "Modified, not staged" +msgstr "Verändert, nicht bereitgestellt" + +#: git-gui.sh:1325 git-gui.sh:1330 +msgid "Staged for commit" +msgstr "Bereitgestellt zur Übertragung" + +#: git-gui.sh:1326 git-gui.sh:1331 +msgid "Portions staged for commit" +msgstr "Teilweise bereitgestellt zur Übertragung" + +#: git-gui.sh:1327 git-gui.sh:1332 +msgid "Staged for commit, missing" +msgstr "Bereitgestellt zur Übertragung, fehlend" + +#: git-gui.sh:1329 +msgid "Untracked, not staged" +msgstr "Nicht unter Versionskontrolle, nicht bereitgestellt" + +#: git-gui.sh:1334 +msgid "Missing" +msgstr "Fehlend" + +#: git-gui.sh:1335 +msgid "Staged for removal" +msgstr "Bereitgestellt zum Löschen" + +#: git-gui.sh:1336 +msgid "Staged for removal, still present" +msgstr "Bereitgestellt zum Löschen, trotzdem vorhanden" + +#: git-gui.sh:1338 git-gui.sh:1339 git-gui.sh:1340 git-gui.sh:1341 +msgid "Requires merge resolution" +msgstr "Konfliktauflösung nötig" + +#: git-gui.sh:1383 +msgid "Starting gitk... please wait..." +msgstr "Gitk wird gestartet... bitte warten." + +#: git-gui.sh:1392 +#, tcl-format +msgid "" +"Unable to start gitk:\n" +"\n" +"%s does not exist" +msgstr "" +"Gitk kann nicht gestartet werden:\n" +"\n" +"%s existiert nicht" + +#: git-gui.sh:1609 +#, tcl-format +msgid "Invalid font specified in gui.%s:" +msgstr "Ungültige Zeichensatz-Angabe in gui.%s:" + +#: git-gui.sh:1634 +msgid "Main Font" +msgstr "Programmschriftart" + +#: git-gui.sh:1635 +msgid "Diff/Console Font" +msgstr "Vergleich-Schriftart" + +#: git-gui.sh:1649 +msgid "Repository" +msgstr "Projektarchiv" + +#: git-gui.sh:1650 +msgid "Edit" +msgstr "Bearbeiten" + +#: git-gui.sh:1652 +msgid "Branch" +msgstr "Zweig" + +#: git-gui.sh:1655 git-gui.sh:1842 git-gui.sh:2152 +msgid "Commit" +msgstr "Übertragen" + +#: git-gui.sh:1658 lib/merge.tcl:121 lib/merge.tcl:150 lib/merge.tcl:168 +msgid "Merge" +msgstr "Zusammenführen" + +#: git-gui.sh:1659 +msgid "Fetch" +msgstr "Anfordern" + +#: git-gui.sh:1660 git-gui.sh:2158 lib/transport.tcl:88 lib/transport.tcl:172 +msgid "Push" +msgstr "Ausliefern" + +#: git-gui.sh:1669 +msgid "Browse Current Branch's Files" +msgstr "Aktuellen Zweig durchblättern" + +#: git-gui.sh:1673 +msgid "Browse Branch Files..." +msgstr "Einen Zweig durchblättern..." + +#: git-gui.sh:1678 +msgid "Visualize Current Branch's History" +msgstr "Aktuellen Zweig darstellen" + +#: git-gui.sh:1682 +msgid "Visualize All Branch History" +msgstr "Alle Zweige darstellen" + +#: git-gui.sh:1689 +#, tcl-format +msgid "Browse %s's Files" +msgstr "Zweig »%s« durchblättern" + +#: git-gui.sh:1691 +#, tcl-format +msgid "Visualize %s's History" +msgstr "Historie von »%s« darstellen" + +#: git-gui.sh:1696 lib/database.tcl:27 lib/database.tcl:67 +msgid "Database Statistics" +msgstr "Datenbankstatistik" + +#: git-gui.sh:1699 lib/database.tcl:34 +msgid "Compress Database" +msgstr "Datenbank komprimieren" + +#: git-gui.sh:1702 +msgid "Verify Database" +msgstr "Datenbank überprüfen" + +#: git-gui.sh:1709 git-gui.sh:1713 git-gui.sh:1717 lib/shortcut.tcl:9 +#: lib/shortcut.tcl:45 lib/shortcut.tcl:84 +msgid "Create Desktop Icon" +msgstr "Desktop-Icon erstellen" + +#: git-gui.sh:1722 +msgid "Quit" +msgstr "Beenden" + +#: git-gui.sh:1729 +msgid "Undo" +msgstr "Rückgängig" + +#: git-gui.sh:1732 +msgid "Redo" +msgstr "Wiederholen" + +#: git-gui.sh:1736 git-gui.sh:2222 +msgid "Cut" +msgstr "Ausschneiden" + +#: git-gui.sh:1739 git-gui.sh:2225 git-gui.sh:2296 git-gui.sh:2368 +#: lib/console.tcl:69 +msgid "Copy" +msgstr "Kopieren" + +#: git-gui.sh:1742 git-gui.sh:2228 +msgid "Paste" +msgstr "Einfügen" + +#: git-gui.sh:1745 git-gui.sh:2231 lib/branch_delete.tcl:26 +#: lib/remote_branch_delete.tcl:38 +msgid "Delete" +msgstr "Löschen" + +#: git-gui.sh:1749 git-gui.sh:2235 git-gui.sh:2372 lib/console.tcl:71 +msgid "Select All" +msgstr "Alle auswählen" + +#: git-gui.sh:1758 +msgid "Create..." +msgstr "Erstellen..." + +#: git-gui.sh:1764 +msgid "Checkout..." +msgstr "Auschecken..." + +#: git-gui.sh:1770 +msgid "Rename..." +msgstr "Umbenennen..." + +#: git-gui.sh:1775 git-gui.sh:1873 +msgid "Delete..." +msgstr "Löschen..." + +#: git-gui.sh:1780 +msgid "Reset..." +msgstr "Zurücksetzen..." + +#: git-gui.sh:1792 git-gui.sh:2169 +msgid "New Commit" +msgstr "Neu übertragen" + +#: git-gui.sh:1800 git-gui.sh:2176 +msgid "Amend Last Commit" +msgstr "Letzte Übertragung nachbessern" + +#: git-gui.sh:1809 git-gui.sh:2136 lib/remote_branch_delete.tcl:99 +msgid "Rescan" +msgstr "Neu laden" + +#: git-gui.sh:1815 +msgid "Stage To Commit" +msgstr "Zur Übertragung bereitstellen" + +#: git-gui.sh:1820 +msgid "Stage Changed Files To Commit" +msgstr "Geänderte Dateien zur Übertragung bereitstellen" + +#: git-gui.sh:1826 +msgid "Unstage From Commit" +msgstr "Aus der Bereitstellung herausnehmen" + +#: git-gui.sh:1831 lib/index.tcl:376 +msgid "Revert Changes" +msgstr "Änderungen revidieren" + +#: git-gui.sh:1838 git-gui.sh:2148 git-gui.sh:2246 +msgid "Sign Off" +msgstr "Abzeichnen" + +#: git-gui.sh:1853 +msgid "Local Merge..." +msgstr "Lokales Zusammenführen..." + +#: git-gui.sh:1858 +msgid "Abort Merge..." +msgstr "Zusammenführen abbrechen..." + +#: git-gui.sh:1870 +msgid "Push..." +msgstr "Ausliefern..." + +#: git-gui.sh:1880 +msgid "Apple" +msgstr "Apple" + +#: git-gui.sh:1883 git-gui.sh:1901 lib/option.tcl:65 +#, tcl-format +msgid "About %s" +msgstr "Über %s" + +#: git-gui.sh:1885 git-gui.sh:1891 git-gui.sh:2414 +msgid "Options..." +msgstr "Optionen..." + +#: git-gui.sh:1897 +msgid "Help" +msgstr "Hilfe" + +#: git-gui.sh:1938 +msgid "Online Documentation" +msgstr "Online-Dokumentation" + +#: git-gui.sh:2054 +msgid "Current Branch:" +msgstr "Aktueller Zweig:" + +#: git-gui.sh:2075 +msgid "Staged Changes (Will Be Committed)" +msgstr "Bereitgestellte Änderungen (werden übertragen)" + +#: git-gui.sh:2095 +msgid "Unstaged Changes (Will Not Be Committed)" +msgstr "Nicht bereitgestellte Änderungen (werden nicht übertragen)" + +#: git-gui.sh:2142 +msgid "Stage Changed" +msgstr "Geänderte bereitstellen" + +#: git-gui.sh:2188 +msgid "Initial Commit Message:" +msgstr "Erstmalige Übertragungsmeldung" + +#: git-gui.sh:2189 +msgid "Amended Commit Message:" +msgstr "Übertragungsmeldung mit Nachbesserung:" + +#: git-gui.sh:2190 +msgid "Amended Initial Commit Message:" +msgstr "Erstmalige Übertragungsmeldung mit Nachbesserung:" + +#: git-gui.sh:2191 +msgid "Amended Merge Commit Message:" +msgstr "Zusammenführungs-Übertragungsmeldung mit Nachbesserung" + +#: git-gui.sh:2192 +msgid "Merge Commit Message:" +msgstr "Übertragungsmeldung Zusammenführung:" + +#: git-gui.sh:2193 +msgid "Commit Message:" +msgstr "Übertragungsmeldung:" + +#: git-gui.sh:2238 git-gui.sh:2376 lib/console.tcl:73 +msgid "Copy All" +msgstr "Alle kopieren" + +#: git-gui.sh:2262 lib/blame.tcl:104 +msgid "File:" +msgstr "Datei:" + +#: git-gui.sh:2364 +msgid "Refresh" +msgstr "Aktualisieren" + +#: git-gui.sh:2385 +msgid "Apply/Reverse Hunk" +msgstr "Änderung anwenden/umkehren" + +#: git-gui.sh:2391 +msgid "Decrease Font Size" +msgstr "Schriftgröße verkleinern" + +#: git-gui.sh:2395 +msgid "Increase Font Size" +msgstr "Schriftgröße vergrößern" + +#: git-gui.sh:2400 +msgid "Show Less Context" +msgstr "Weniger Kontext anzeigen" + +#: git-gui.sh:2407 +msgid "Show More Context" +msgstr "Mehr Kontext anzeigen" + +#: git-gui.sh:2422 +msgid "Unstage Hunk From Commit" +msgstr "Aus der Bereitstellung herausnehmen" + +#: git-gui.sh:2426 git-gui.sh:2430 +msgid "Stage Hunk For Commit" +msgstr "In die Bereitstellung hinzufügen" + +#: git-gui.sh:2440 +msgid "Initializing..." +msgstr "Initialisieren..." + +#: lib/blame.tcl:77 +msgid "File Viewer" +msgstr "Datei-Browser" + +#: lib/blame.tcl:81 +msgid "Commit:" +msgstr "Übertragung:" + +#: lib/blame.tcl:249 +msgid "Copy Commit" +msgstr "Übertragung kopieren" + +#: lib/blame.tcl:369 +#, tcl-format +msgid "Reading %s..." +msgstr "%s lesen..." + +#: lib/branch_checkout.tcl:14 lib/branch_checkout.tcl:19 +msgid "Checkout Branch" +msgstr "Zweig auschecken" + +#: lib/branch_checkout.tcl:23 +msgid "Checkout" +msgstr "Auschecken" + +#: lib/branch_checkout.tcl:27 lib/branch_create.tcl:35 +#: lib/branch_delete.tcl:32 lib/branch_rename.tcl:30 lib/browser.tcl:283 +#: lib/checkout_op.tcl:522 lib/merge.tcl:172 lib/option.tcl:172 +#: lib/remote_branch_delete.tcl:42 lib/transport.tcl:92 +msgid "Cancel" +msgstr "Abbrechen" + +#: lib/branch_checkout.tcl:32 lib/browser.tcl:288 +msgid "Revision" +msgstr "Version" + +#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:159 +#: lib/option.tcl:274 +msgid "Options" +msgstr "Optionen" + +#: lib/branch_checkout.tcl:39 lib/branch_create.tcl:92 +msgid "Fetch Tracking Branch" +msgstr "Übernahmezweig anfordern" + +#: lib/branch_checkout.tcl:44 +msgid "Detach From Local Branch" +msgstr "Verbindung zu lokalem Zweig lösen" + +#: lib/branch_create.tcl:22 +msgid "Create Branch" +msgstr "Zweig erstellen" + +#: lib/branch_create.tcl:27 +msgid "Create New Branch" +msgstr "Neuen Zweig erstellen" + +#: lib/branch_create.tcl:31 +msgid "Create" +msgstr "Erstellen" + +#: lib/branch_create.tcl:40 +msgid "Branch Name" +msgstr "Zweigname" + +#: lib/branch_create.tcl:43 +msgid "Name:" +msgstr "Name:" + +#: lib/branch_create.tcl:58 +msgid "Match Tracking Branch Name" +msgstr "Passend zu Übernahmezweig-Name" + +#: lib/branch_create.tcl:66 +msgid "Starting Revision" +msgstr "Anfangsversion" + +#: lib/branch_create.tcl:72 +msgid "Update Existing Branch:" +msgstr "Existierenden Zweig aktualisieren:" + +#: lib/branch_create.tcl:75 +msgid "No" +msgstr "Nein" + +#: lib/branch_create.tcl:80 +msgid "Fast Forward Only" +msgstr "Nur Schnellzusammenführung" + +#: lib/branch_create.tcl:85 lib/checkout_op.tcl:514 +msgid "Reset" +msgstr "Zurücksetzen" + +#: lib/branch_create.tcl:97 +msgid "Checkout After Creation" +msgstr "Auschecken nach Erstellen" + +#: lib/branch_create.tcl:131 +msgid "Please select a tracking branch." +msgstr "Bitte wählen Sie einen Übernahmezweig." + +#: lib/branch_create.tcl:140 +#, tcl-format +msgid "Tracking branch %s is not a branch in the remote repository." +msgstr "Übernahmezweig »%s« ist kein Zweig im Projektarchiv der Gegenseite." + +#: lib/branch_create.tcl:153 lib/branch_rename.tcl:86 +msgid "Please supply a branch name." +msgstr "Bitte geben Sie einen Zweignamen an." + +#: lib/branch_create.tcl:164 lib/branch_rename.tcl:106 +#, tcl-format +msgid "'%s' is not an acceptable branch name." +msgstr "»%s« ist kein zulässiger Zweigname." + +#: lib/branch_delete.tcl:15 +msgid "Delete Branch" +msgstr "Zweig löschen" + +#: lib/branch_delete.tcl:20 +msgid "Delete Local Branch" +msgstr "Lokalen Zweig löschen" + +#: lib/branch_delete.tcl:37 +msgid "Local Branches" +msgstr "Lokale Zweige" + +#: lib/branch_delete.tcl:52 +msgid "Delete Only If Merged Into" +msgstr "Nur löschen, wenn darin zusammengeführt" + +#: lib/branch_delete.tcl:54 +msgid "Always (Do not perform merge test.)" +msgstr "Immer (ohne Zusammenführungstest)" + +#: lib/branch_delete.tcl:103 +#, tcl-format +msgid "The following branches are not completely merged into %s:" +msgstr "Folgende Zweige sind noch nicht mit »%s« zusammengeführt:" + +#: lib/branch_delete.tcl:115 +msgid "" +"Recovering deleted branches is difficult. \n" +"\n" +" Delete the selected branches?" +msgstr "" +"Gelöschte Zweige können nur mit größerem Aufwand wiederhergestellt werden.\n" +"\n" +"Gewählte Zweige jetzt löschen?" + +#: lib/branch_delete.tcl:141 +#, tcl-format +msgid "" +"Failed to delete branches:\n" +"%s" +msgstr "" +"Fehler beim Löschen der Zweige:\n" +"%s" + +#: lib/branch_rename.tcl:14 lib/branch_rename.tcl:22 +msgid "Rename Branch" +msgstr "Zweig umbenennen" + +#: lib/branch_rename.tcl:26 +msgid "Rename" +msgstr "Umbenennen" + +#: lib/branch_rename.tcl:36 +msgid "Branch:" +msgstr "Zweig:" + +#: lib/branch_rename.tcl:39 +msgid "New Name:" +msgstr "Neuer Name:" + +#: lib/branch_rename.tcl:75 +msgid "Please select a branch to rename." +msgstr "Bitte wählen Sie einen Zweig zum umbenennen." + +#: lib/branch_rename.tcl:96 lib/checkout_op.tcl:179 +#, tcl-format +msgid "Branch '%s' already exists." +msgstr "Zweig »%s« existiert bereits." + +#: lib/branch_rename.tcl:117 +#, tcl-format +msgid "Failed to rename '%s'." +msgstr "Fehler beim Umbenennen von »%s«." + +#: lib/browser.tcl:17 +msgid "Starting..." +msgstr "Starten..." + +#: lib/browser.tcl:26 +msgid "File Browser" +msgstr "Datei-Browser" + +#: lib/browser.tcl:127 lib/browser.tcl:144 +#, tcl-format +msgid "Loading %s..." +msgstr "%s laden..." + +#: lib/browser.tcl:188 +msgid "[Up To Parent]" +msgstr "[Nach oben]" + +#: lib/browser.tcl:268 lib/browser.tcl:274 +msgid "Browse Branch Files" +msgstr "Dateien des Zweigs durchblättern" + +#: lib/browser.tcl:279 +msgid "Browse" +msgstr "Blättern" + +#: lib/checkout_op.tcl:79 +#, tcl-format +msgid "Fetching %s from %s" +msgstr "Änderungen »%s« von »%s« anfordern" + +#: lib/checkout_op.tcl:140 lib/console.tcl:81 lib/database.tcl:31 +msgid "Close" +msgstr "Schließen" + +#: lib/checkout_op.tcl:169 +#, tcl-format +msgid "Branch '%s' does not exist." +msgstr "Zweig »%s« existiert nicht." + +#: lib/checkout_op.tcl:206 +#, tcl-format +msgid "" +"Branch '%s' already exists.\n" +"\n" +"It cannot fast-forward to %s.\n" +"A merge is required." +msgstr "" +"Zweig »%s« existiert bereits.\n" +"\n" +"Zweig kann nicht mit »%s« schnellzusammengeführt werden. Reguläres " +"Zusammenführen ist notwendig." + +#: lib/checkout_op.tcl:220 +#, tcl-format +msgid "Merge strategy '%s' not supported." +msgstr "Zusammenführungsmethode »%s« nicht unterstützt." + +#: lib/checkout_op.tcl:239 +#, tcl-format +msgid "Failed to update '%s'." +msgstr "Aktualisieren von »%s« fehlgeschlagen." + +#: lib/checkout_op.tcl:251 +msgid "Staging area (index) is already locked." +msgstr "Bereitstellung (»index«) ist zur Bearbeitung gesperrt (»locked«)." + +#: lib/checkout_op.tcl:266 +msgid "" +"Last scanned state does not match repository state.\n" +"\n" +"Another Git program has modified this repository since the last scan. A " +"rescan must be performed before the current branch can be changed.\n" +"\n" +"The rescan will be automatically started now.\n" +msgstr "" +"Der letzte geladene Status stimmt nicht mehr mit dem Projektarchiv überein.\n" +"\n" +"Ein anderes Git-Programm hat das Projektarchiv seit dem letzten Laden " +"geändert. Vor dem Wechseln des lokalen Zweigs muss neu geladen werden.\n" +"\n" +"Es wird gleich neu geladen.\n" + +#: lib/checkout_op.tcl:353 +#, tcl-format +msgid "Aborted checkout of '%s' (file level merging is required)." +msgstr "" +"Auschecken von »%s« abgebrochen (Zusammenführen der Dateien ist notwendig)." + +#: lib/checkout_op.tcl:354 +msgid "File level merge required." +msgstr "Zusammenführen der Dateien ist notwendig." + +#: lib/checkout_op.tcl:358 +#, tcl-format +msgid "Staying on branch '%s'." +msgstr "Es wird auf Zweig »%s« verblieben." + +#: lib/checkout_op.tcl:429 +msgid "" +"You are no longer on a local branch.\n" +"\n" +"If you wanted to be on a branch, create one now starting from 'This Detached " +"Checkout'." +msgstr "" +"Die Arbeitskopie ist nicht auf einem lokalen Zweig.\n" +"\n" +"Wenn Sie auf einem Zwei arbeiten möchten, erstellen Sie bitte jetzt einen " +"Zweig mit der Auswahl »Abgetrennte Auscheck-Version«." + +#: lib/checkout_op.tcl:478 +#, tcl-format +msgid "Resetting '%s' to '%s' will lose the following commits:" +msgstr "Zurücksetzen von »%s« nach »%s« wird folgende Versionen verwerfen:" + +#: lib/checkout_op.tcl:500 +msgid "Recovering lost commits may not be easy." +msgstr "" +"Verworfene Versionen können nur mit größerem Aufwand wiederhergestellt " +"werden." + +#: lib/checkout_op.tcl:505 +#, tcl-format +msgid "Reset '%s'?" +msgstr "»%s« zurücksetzen?" + +#: lib/checkout_op.tcl:510 lib/merge.tcl:164 +msgid "Visualize" +msgstr "Darstellen" + +#: lib/checkout_op.tcl:578 +#, tcl-format +msgid "" +"Failed to set current branch.\n" +"\n" +"This working directory is only partially switched. We successfully updated " +"your files, but failed to update an internal Git file.\n" +"\n" +"This should not have occurred. %s will now close and give up." +msgstr "" +"Lokaler Zweig kann nicht gesetzt werden.\n" +"\n" +"Diese Arbeitskopie ist nur teilweise umgestellt. Die Dateien sind korrekt " +"aktualisiert, aber einige interne Git-Dateien konnten nicht geändert " +"werden.\n" +"\n" +"Dies ist ein interner Programmfehler von %s. Programm wird jetzt abgebrochen." + +#: lib/choose_rev.tcl:53 +msgid "This Detached Checkout" +msgstr "Abgetrennte Auscheck-Version" + +#: lib/choose_rev.tcl:60 +msgid "Revision Expression:" +msgstr "Version Regexp-Ausdruck:" + +#: lib/choose_rev.tcl:74 +msgid "Local Branch" +msgstr "Lokaler Zweig" + +#: lib/choose_rev.tcl:79 +msgid "Tracking Branch" +msgstr "Übernahmezweig" + +#: lib/choose_rev.tcl:84 +msgid "Tag" +msgstr "Markierung" + +#: lib/choose_rev.tcl:317 +#, tcl-format +msgid "Invalid revision: %s" +msgstr "Ungültige Version: %s" + +#: lib/choose_rev.tcl:338 +msgid "No revision selected." +msgstr "Keine Version ausgewählt." + +#: lib/choose_rev.tcl:346 +msgid "Revision expression is empty." +msgstr "Versions-Ausdruck ist leer." + +#: lib/commit.tcl:9 +msgid "" +"There is nothing to amend.\n" +"\n" +"You are about to create the initial commit. There is no commit before this " +"to amend.\n" +msgstr "" +"Keine Version zur Nachbesserung vorhanden.\n" +"\n" +"Sie sind dabei, die erste Version zu übertragen. Es gibt keine existierende " +"Version, die Sie nachbessern könnten.\n" + +#: lib/commit.tcl:18 +msgid "" +"Cannot amend while merging.\n" +"\n" +"You are currently in the middle of a merge that has not been fully " +"completed. You cannot amend the prior commit unless you first abort the " +"current merge activity.\n" +msgstr "" +"Nachbesserung währen Zusammenführung nicht möglich.\n" +"\n" +"Sie haben das Zusammenführen von Versionen angefangen, aber noch nicht " +"beendet. Sie können keine vorige Übertragung nachbessern, solange eine " +"unfertige Zusammenführung existiert. Dazu müssen Sie die Zusammenführung " +"beenden oder abbrechen.\n" + +#: lib/commit.tcl:49 +msgid "Error loading commit data for amend:" +msgstr "Fehler beim Laden der Versionsdaten für Nachbessern:" + +#: lib/commit.tcl:76 +msgid "Unable to obtain your identity:" +msgstr "Benutzername konnte nicht bestimmt werden:" + +#: lib/commit.tcl:81 +msgid "Invalid GIT_COMMITTER_IDENT:" +msgstr "Ungültiger Wert von GIT_COMMITTER_INDENT:" + +#: lib/commit.tcl:133 +msgid "" +"Last scanned state does not match repository state.\n" +"\n" +"Another Git program has modified this repository since the last scan. A " +"rescan must be performed before another commit can be created.\n" +"\n" +"The rescan will be automatically started now.\n" +msgstr "" +"Der letzte geladene Status stimmt nicht mehr mit dem Projektarchiv überein.\n" +"\n" +"Ein anderes Git-Programm hat das Projektarchiv seit dem letzten Laden " +"geändert. Vor einer neuen Übertragung muss neu geladen werden.\n" +"\n" +"Es wird gleich neu geladen.\n" + +#: lib/commit.tcl:154 +#, tcl-format +msgid "" +"Unmerged files cannot be committed.\n" +"\n" +"File %s has merge conflicts. You must resolve them and stage the file " +"before committing.\n" +msgstr "" +"Nicht zusammengeführte Dateien können nicht übertragen werden.\n" +"\n" +"Die Datei %s hat noch nicht aufgelöste Zusammenführungs-Konflikte. Sie " +"müssen diese Konflikte auflösen, bevor Sie übertragen können.\n" + +#: lib/commit.tcl:162 +#, tcl-format +msgid "" +"Unknown file state %s detected.\n" +"\n" +"File %s cannot be committed by this program.\n" +msgstr "" +"Unbekannter Dateizustand »%s«.\n" +"\n" +"Datei »%s« kann nicht übertragen werden.\n" + +#: lib/commit.tcl:170 +msgid "" +"No changes to commit.\n" +"\n" +"You must stage at least 1 file before you can commit.\n" +msgstr "" +"Keine Änderungen vorhanden, die übertragen werden könnten.\n" +"\n" +"Sie müssen mindestens eine Datei bereitstellen, bevor Sie übertragen " +"können.\n" + +#: lib/commit.tcl:183 +msgid "" +"Please supply a commit message.\n" +"\n" +"A good commit message has the following format:\n" +"\n" +"- First line: Describe in one sentance what you did.\n" +"- Second line: Blank\n" +"- Remaining lines: Describe why this change is good.\n" +msgstr "" +"Bitte geben Sie eine Übertragungsmeldung ein.\n" +"\n" +"Eine gute Übertragungsmeldung enthält folgende Abschnitte:\n" +"\n" +"- Erste Zeile: Eine Zusammenfassung, was man gemacht hat.\n" +"\n" +"- Zweite Zeile: Leerzeile\n" +"\n" +"- Rest der Meldung: Eine ausführliche Beschreibung, warum diese Änderung " +"hilfreich ist.\n" + +#: lib/commit.tcl:257 +msgid "write-tree failed:" +msgstr "write-tree fehlgeschlagen:" + +#: lib/commit.tcl:279 +msgid "" +"No changes to commit.\n" +"\n" +"No files were modified by this commit and it was not a merge commit.\n" +"\n" +"A rescan will be automatically started now.\n" +msgstr "" +"Keine Änderungen zu übertragen.\n" +"\n" +"Es gibt keine geänderte Datei bei dieser Übertragung und es wurde auch " +"nichts zusammengeführt.\n" +"\n" +"Das Arbeitsverzeichnis wird daher jetzt neu geladen.\n" + +#: lib/commit.tcl:286 +msgid "No changes to commit." +msgstr "Keine Änderungen, die übertragen werden können." + +#: lib/commit.tcl:317 +msgid "commit-tree failed:" +msgstr "commit-tree fehlgeschlagen:" + +#: lib/commit.tcl:339 +msgid "update-ref failed:" +msgstr "update-ref fehlgeschlagen:" + +#: lib/commit.tcl:430 +#, tcl-format +msgid "Created commit %s: %s" +msgstr "Version %s übertragen: %s" + +#: lib/console.tcl:55 +msgid "Working... please wait..." +msgstr "Verarbeitung. Bitte warten..." + +#: lib/console.tcl:184 +msgid "Success" +msgstr "Erfolgreich" + +#: lib/console.tcl:194 +msgid "Error: Command Failed" +msgstr "Fehler: Kommando fehlgeschlagen" + +#: lib/database.tcl:43 +msgid "Number of loose objects" +msgstr "Anzahl unverknüpfter Objekte" + +#: lib/database.tcl:44 +msgid "Disk space used by loose objects" +msgstr "Festplattenplatz von unverknüpften Objekten" + +#: lib/database.tcl:45 +msgid "Number of packed objects" +msgstr "Anzahl komprimierter Objekte" + +#: lib/database.tcl:46 +msgid "Number of packs" +msgstr "Anzahl Komprimierungseinheiten" + +#: lib/database.tcl:47 +msgid "Disk space used by packed objects" +msgstr "Festplattenplatz von komprimierten Objekten" + +#: lib/database.tcl:48 +msgid "Packed objects waiting for pruning" +msgstr "Komprimierte Objekte, die zum Löschen vorgesehen sind" + +#: lib/database.tcl:49 +msgid "Garbage files" +msgstr "Dateien im Mülleimer" + +#: lib/database.tcl:72 +msgid "Compressing the object database" +msgstr "Objektdatenbank komprimieren" + +#: lib/database.tcl:83 +msgid "Verifying the object database with fsck-objects" +msgstr "Die Objektdatenbank durch »fsck-objects« überprüfen lassen" + +#: lib/diff.tcl:42 +#, tcl-format +msgid "" +"No differences detected.\n" +"\n" +"%s has no changes.\n" +"\n" +"The modification date of this file was updated by another application, but " +"the content within the file was not changed.\n" +"\n" +"A rescan will be automatically started to find other files which may have " +"the same state." +msgstr "" +"Keine Änderungen feststellbar.\n" +"\n" +"»%s« enthält keine Änderungen. Zwar wurde das Änderungsdatum dieser Datei " +"von einem anderen Programm modifiziert, aber der Inhalt der Datei ist " +"unverändert.\n" +"\n" +"Das Arbeitsverzeichnis wird jetzt neu geladen, um diese Änderung bei allen " +"Dateien zu prüfen." + +#: lib/diff.tcl:97 +msgid "Error loading file:" +msgstr "Fehler beim Laden der Datei:" + +#: lib/diff.tcl:162 +msgid "Error loading diff:" +msgstr "Fehler beim Laden des Vergleichs:" + +#: lib/diff.tcl:278 +msgid "Failed to unstage selected hunk." +msgstr "Fehler beim Herausnehmen der gewählten Dateien aus der Bereitstellung." + +#: lib/diff.tcl:285 +msgid "Failed to stage selected hunk." +msgstr "Fehler beim Bereitstellen der gewählten Dateien." + +#: lib/error.tcl:12 lib/error.tcl:102 +msgid "error" +msgstr "Fehler" + +#: lib/error.tcl:28 +msgid "warning" +msgstr "Warnung" + +#: lib/error.tcl:81 +msgid "You must correct the above errors before committing." +msgstr "" +"Sie müssen die obigen Fehler zuerst beheben, bevor Sie übertragen können." + +#: lib/index.tcl:364 +#, tcl-format +msgid "Revert changes in file %s?" +msgstr "Änderungen in Datei »%s« revidieren?" + +#: lib/index.tcl:366 +#, tcl-format +msgid "Revert changes in these %i files?" +msgstr "Änderungen in den gewählten %i Dateien revidieren?" + +#: lib/index.tcl:372 +msgid "Any unstaged changes will be permanently lost by the revert." +msgstr "" +"Alle nicht bereitgestellten Änderungen werden beim Revidieren verloren gehen." + +#: lib/index.tcl:375 +msgid "Do Nothing" +msgstr "Nichts tun" + +#: lib/merge.tcl:13 +msgid "" +"Cannot merge while amending.\n" +"\n" +"You must finish amending this commit before starting any type of merge.\n" +msgstr "" +"Zusammenführen kann nicht gleichzeitig mit Nachbessern durchgeführt werden.\n" +"\n" +"Sie müssen zuerst die Nachbesserungs-Übertragung abschließen, bevor Sie " +"zusammenführen können.\n" + +#: lib/merge.tcl:27 +msgid "" +"Last scanned state does not match repository state.\n" +"\n" +"Another Git program has modified this repository since the last scan. A " +"rescan must be performed before a merge can be performed.\n" +"\n" +"The rescan will be automatically started now.\n" +msgstr "" +"Der letzte geladene Status stimmt nicht mehr mit dem Projektarchiv überein.\n" +"\n" +"Ein anderes Git-Programm hat das Projektarchiv seit dem letzten Laden " +"geändert. Vor einem Zusammenführen muss neu geladen werden.\n" +"\n" +"Es wird gleich neu geladen.\n" + +#: lib/merge.tcl:44 +#, tcl-format +msgid "" +"You are in the middle of a conflicted merge.\n" +"\n" +"File %s has merge conflicts.\n" +"\n" +"You must resolve them, stage the file, and commit to complete the current " +"merge. Only then can you begin another merge.\n" +msgstr "" +"Zusammenführung mit Konflikten.\n" +"\n" +"Die Datei »%s« enthält Konflikte beim Zusammenführen. Sie müssen diese " +"Konflikte per Hand auflösen. Anschließend müssen Sie die Datei wieder " +"bereitstellen und übertragen, um die Zusammenführung abzuschließen. Erst " +"danach kann eine neue Zusammenführung begonnen werden.\n" + +#: lib/merge.tcl:54 +#, tcl-format +msgid "" +"You are in the middle of a change.\n" +"\n" +"File %s is modified.\n" +"\n" +"You should complete the current commit before starting a merge. Doing so " +"will help you abort a failed merge, should the need arise.\n" +msgstr "" +"Es liegen Änderungen vor.\n" +"\n" +"Die Datei »%s« wurde geändert. Sie sollten zuerst die bereitgestellte " +"Übertragung abschließen, bevor Sie eine Zusammenführung beginnen. Mit " +"dieser Reihenfolge können Sie mögliche Konflikte beim Zusammenführen " +"wesentlich einfacher beheben oder abbrechen.\n" + +#: lib/merge.tcl:106 +#, tcl-format +msgid "%s of %s" +msgstr "%s von %s" + +#: lib/merge.tcl:119 +#, tcl-format +msgid "Merging %s and %s" +msgstr "Zusammenführen von %s und %s" + +#: lib/merge.tcl:131 +msgid "Merge completed successfully." +msgstr "Zusammenführen erfolgreich abgeschlossen." + +#: lib/merge.tcl:133 +msgid "Merge failed. Conflict resolution is required." +msgstr "Zusammenführen fehlgeschlagen. Konfliktauflösung ist notwendig." + +#: lib/merge.tcl:158 +#, tcl-format +msgid "Merge Into %s" +msgstr "Zusammenführen in %s" + +#: lib/merge.tcl:177 +msgid "Revision To Merge" +msgstr "Zusammenzuführende Version" + +#: lib/merge.tcl:212 +msgid "" +"Cannot abort while amending.\n" +"\n" +"You must finish amending this commit.\n" +msgstr "" +"Abbruch der Nachbesserung ist nicht möglich.\n" +"\n" +"Sie müssen die Nachbesserung der Übertragung abschließen.\n" + +#: lib/merge.tcl:222 +msgid "" +"Abort merge?\n" +"\n" +"Aborting the current merge will cause *ALL* uncommitted changes to be lost.\n" +"\n" +"Continue with aborting the current merge?" +msgstr "" +"Zusammenführen abbrechen?\n" +"\n" +"Wenn Sie abbrechen, gehen alle noch nicht übertragenen Änderungen verloren.\n" +"\n" +"Zusammenführen jetzt abbrechen?" + +#: lib/merge.tcl:228 +msgid "" +"Reset changes?\n" +"\n" +"Resetting the changes will cause *ALL* uncommitted changes to be lost.\n" +"\n" +"Continue with resetting the current changes?" +msgstr "" +"Änderungen zurücksetzen?\n" +"\n" +"Wenn Sie zurücksetzen, gehen alle noch nicht übertragenen Änderungen " +"verloren.\n" +"\n" +"Änderungen jetzt zurücksetzen?" + +#: lib/merge.tcl:239 +msgid "Aborting" +msgstr "Abbruch" + +#: lib/merge.tcl:266 +msgid "Abort failed." +msgstr "Abbruch fehlgeschlagen." + +#: lib/merge.tcl:268 +msgid "Abort completed. Ready." +msgstr "Abbruch durchgeführt. Bereit." + +#: lib/option.tcl:77 +msgid "git-gui - a graphical user interface for Git." +msgstr "git-gui - eine grafische Oberfläche für Git." + +#: lib/option.tcl:164 +msgid "Restore Defaults" +msgstr "Voreinstellungen wiederherstellen" + +#: lib/option.tcl:168 +msgid "Save" +msgstr "Speichern" + +#: lib/option.tcl:178 +#, tcl-format +msgid "%s Repository" +msgstr "Projektarchiv %s" + +#: lib/option.tcl:179 +msgid "Global (All Repositories)" +msgstr "Global (Alle Projektarchive)" + +#: lib/option.tcl:185 +msgid "User Name" +msgstr "Benutzername" + +#: lib/option.tcl:186 +msgid "Email Address" +msgstr "E-Mail-Adresse" + +#: lib/option.tcl:188 +msgid "Summarize Merge Commits" +msgstr "Zusammenführungs-Übertragungen zusammenfassen" + +#: lib/option.tcl:189 +msgid "Merge Verbosity" +msgstr "Ausführlichkeit der Zusammenführen-Meldungen" + +#: lib/option.tcl:190 +msgid "Show Diffstat After Merge" +msgstr "Vergleichsstatistik nach Zusammenführen anzeigen" + +#: lib/option.tcl:192 +msgid "Trust File Modification Timestamps" +msgstr "Auf Dateiänderungsdatum verlassen" + +#: lib/option.tcl:193 +msgid "Prune Tracking Branches During Fetch" +msgstr "Übernahmezweige löschen während Anforderung" + +#: lib/option.tcl:194 +msgid "Match Tracking Branches" +msgstr "Passend zu Übernahmezweig" + +#: lib/option.tcl:195 +msgid "Number of Diff Context Lines" +msgstr "Anzahl der Kontextzeilen beim Vergleich" + +#: lib/option.tcl:196 +msgid "New Branch Name Template" +msgstr "Namensvorschlag für neue Zweige" + +#: lib/option.tcl:305 +msgid "Failed to completely save options:" +msgstr "Optionen konnten nicht gespeichert werden:" + +#: lib/remote_branch_delete.tcl:29 lib/remote_branch_delete.tcl:34 +msgid "Delete Remote Branch" +msgstr "Zweig im Projektarchiv der Gegenseite löschen" + +#: lib/remote_branch_delete.tcl:47 +msgid "From Repository" +msgstr "Von Projektarchiv" + +#: lib/remote_branch_delete.tcl:50 lib/transport.tcl:118 +msgid "Remote:" +msgstr "Gegenseite:" + +#: lib/remote_branch_delete.tcl:66 lib/transport.tcl:133 +msgid "Arbitrary URL:" +msgstr "Kommunikation mit URL:" + +#: lib/remote_branch_delete.tcl:84 +msgid "Branches" +msgstr "Zweige" + +#: lib/remote_branch_delete.tcl:109 +msgid "Delete Only If" +msgstr "Löschen, falls" + +#: lib/remote_branch_delete.tcl:111 +msgid "Merged Into:" +msgstr "Zusammenführen mit:" + +#: lib/remote_branch_delete.tcl:119 +msgid "Always (Do not perform merge checks)" +msgstr "Immer (Keine Zusammenführungsprüfung)" + +#: lib/remote_branch_delete.tcl:152 +msgid "A branch is required for 'Merged Into'." +msgstr "Für »Zusammenführen mit« muss ein Zweig angegeben werden." + +#: lib/remote_branch_delete.tcl:189 +#, tcl-format +msgid "" +"One or more of the merge tests failed because you have not fetched the " +"necessary commits. Try fetching from %s first." +msgstr "" +"Ein oder mehrere Zusammenführungen sind fehlgeschlagen, da Sie nicht die " +"notwendigen Versionen vorher angefordert haben. Sie sollten versuchen, " +"zuerst von »%s« anzufordern." + +#: lib/remote_branch_delete.tcl:207 +msgid "Please select one or more branches to delete." +msgstr "Bitte wählen Sie mindestens einen Zweig, der gelöscht werden soll." + +#: lib/remote_branch_delete.tcl:216 +msgid "" +"Recovering deleted branches is difficult.\n" +"\n" +"Delete the selected branches?" +msgstr "" +"Das Wiederherstellen von gelöschten Zweigen ist nur mit größerem Aufwand " +"möglich.\n" +"\n" +"Sollen die ausgewählten Zweige gelöscht werden?" + +#: lib/remote_branch_delete.tcl:226 +#, tcl-format +msgid "Deleting branches from %s" +msgstr "Zweige auf »%s« werden gelöscht" + +#: lib/remote_branch_delete.tcl:286 +msgid "No repository selected." +msgstr "Kein Projektarchiv ausgewählt." + +#: lib/remote_branch_delete.tcl:291 +#, tcl-format +msgid "Scanning %s..." +msgstr "%s laden..." + +#: lib/remote.tcl:162 +#, tcl-format +msgid "Fetch from %s..." +msgstr "Von »%s« anfordern..." + +#: lib/remote.tcl:172 +#, tcl-format +msgid "Prune from %s..." +msgstr "Löschen von »%s«..." + +#: lib/remote.tcl:206 +#, tcl-format +msgid "Push to %s..." +msgstr "Nach %s ausliefern..." + +#: lib/shortcut.tcl:26 lib/shortcut.tcl:74 +msgid "Cannot write script:" +msgstr "Fehler beim Schreiben des Scripts:" + +#: lib/shortcut.tcl:149 +msgid "Cannot write icon:" +msgstr "Fehler beim Erstellen des Icons:" + +#: lib/status_bar.tcl:58 +#, tcl-format +msgid "%s ... %i of %i %s (%2i%%)" +msgstr "%s ... %i von %i %s (%2i%%)" + +#: lib/transport.tcl:7 +#, tcl-format +msgid "Fetching new changes from %s" +msgstr "Neue Änderungen von »%s« holen" + +#: lib/transport.tcl:19 +#, tcl-format +msgid "Pruning tracking branches deleted from %s" +msgstr "Übernahmezweige löschen, die in »%s« gelöscht wurden" + +#: lib/transport.tcl:26 +#, tcl-format +msgid "Pushing changes to %s" +msgstr "Änderungen nach %s ausliefern" + +#: lib/transport.tcl:68 +#, tcl-format +msgid "Pushing %s %s to %s" +msgstr "%s %s nach %s ausliefern" + +#: lib/transport.tcl:84 +msgid "Push Branches" +msgstr "Zweige ausliefern" + +#: lib/transport.tcl:98 +msgid "Source Branches" +msgstr "Herkunftszweige" + +#: lib/transport.tcl:115 +msgid "Destination Repository" +msgstr "Ziel-Projektarchiv" + +#: lib/transport.tcl:153 +msgid "Transfer Options" +msgstr "Netzwerk-Einstellungen" + +#: lib/transport.tcl:155 +msgid "Use thin pack (for slow network connections)" +msgstr "Kompaktes Datenformat benutzen (für langsame Netzverbindungen)" + +#: lib/transport.tcl:159 +msgid "Include tags" +msgstr "Mit Markierungen übertragen" From 377eaa03961985b5fa379244ed89de51fbf08045 Mon Sep 17 00:00:00 2001 From: Xudong Guan Date: Sun, 22 Jul 2007 01:08:56 +0100 Subject: [PATCH 0022/1490] Initial Chinese translation for git-gui Simplified Chinese, in UTF-8 encoding. Signed-off-by: Xudong Guan Signed-off-by: Johannes Schindelin --- po/zh_cn.po | 1284 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1284 insertions(+) create mode 100644 po/zh_cn.po diff --git a/po/zh_cn.po b/po/zh_cn.po new file mode 100644 index 0000000000..45eb5b5f98 --- /dev/null +++ b/po/zh_cn.po @@ -0,0 +1,1284 @@ +# Translation of git-gui to Chinese +# Copyright (C) 2007 Shawn Pearce +# This file is distributed under the same license as the git-gui package. +# Xudong Guan , 2007. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: git-gui\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2007-07-27 19:33+0200\n" +"PO-Revision-Date: 2007-07-21 01:23-0700\n" +"Last-Translator: Xudong Guan \n" +"Language-Team: Chinese\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: git-gui.sh:531 +msgid "Cannot find git in PATH." +msgstr "" + +#: git-gui.sh:550 +msgid "Cannot parse Git version string:" +msgstr "" + +#: git-gui.sh:567 +#, tcl-format +msgid "" +"Git version cannot be determined.\n" +"\n" +"%s claims it is version '%s'.\n" +"\n" +"%s requires at least Git 1.5.0 or later.\n" +"\n" +"Assume '%s' is version 1.5.0?\n" +msgstr "" + +#: git-gui.sh:689 +msgid "Cannot find the git directory:" +msgstr "" + +#: git-gui.sh:697 +msgid "Git directory not found:" +msgstr "" + +#: git-gui.sh:703 +msgid "Cannot use funny .git directory:" +msgstr "" + +#: git-gui.sh:708 +msgid "No working directory" +msgstr "" + +#: git-gui.sh:853 +msgid "Refreshing file status..." +msgstr "" + +#: git-gui.sh:886 +msgid "Scanning for modified files ..." +msgstr "" + +#: git-gui.sh:1052 lib/browser.tcl:233 +#, fuzzy +msgid "Ready." +msgstr "重做" + +#: git-gui.sh:1343 +msgid "Unmodified" +msgstr "" + +#: git-gui.sh:1345 +msgid "Modified, not staged" +msgstr "" + +#: git-gui.sh:1346 git-gui.sh:1351 +#, fuzzy +msgid "Staged for commit" +msgstr "从本次提交移除" + +#: git-gui.sh:1347 git-gui.sh:1352 +#, fuzzy +msgid "Portions staged for commit" +msgstr "从本次提交移除" + +#: git-gui.sh:1348 git-gui.sh:1353 +msgid "Staged for commit, missing" +msgstr "" + +#: git-gui.sh:1350 +msgid "Untracked, not staged" +msgstr "" + +#: git-gui.sh:1355 +msgid "Missing" +msgstr "" + +#: git-gui.sh:1356 +msgid "Staged for removal" +msgstr "" + +#: git-gui.sh:1357 +msgid "Staged for removal, still present" +msgstr "" + +#: git-gui.sh:1359 git-gui.sh:1360 git-gui.sh:1361 git-gui.sh:1362 +msgid "Requires merge resolution" +msgstr "" + +#: git-gui.sh:1404 +msgid "Starting gitk... please wait..." +msgstr "" + +#: git-gui.sh:1413 +#, tcl-format +msgid "" +"Unable to start gitk:\n" +"\n" +"%s does not exist" +msgstr "" + +#: git-gui.sh:1630 +#, tcl-format +msgid "Invalid font specified in gui.%s:" +msgstr "" + +#: git-gui.sh:1655 +msgid "Main Font" +msgstr "" + +#: git-gui.sh:1656 +msgid "Diff/Console Font" +msgstr "" + +#: git-gui.sh:1670 +msgid "Repository" +msgstr "版本树" + +#: git-gui.sh:1671 +msgid "Edit" +msgstr "编辑" + +#: git-gui.sh:1673 +msgid "Branch" +msgstr "分支" + +#: git-gui.sh:1676 git-gui.sh:1854 git-gui.sh:2193 +msgid "Commit" +msgstr "提交" + +#: git-gui.sh:1679 lib/merge.tcl:96 lib/merge.tcl:157 lib/merge.tcl:173 +msgid "Merge" +msgstr "合并" + +#: git-gui.sh:1680 +msgid "Fetch" +msgstr "导入" + +#: git-gui.sh:1681 git-gui.sh:2199 lib/transport.tcl:88 lib/transport.tcl:172 +msgid "Push" +msgstr "上传" + +#: git-gui.sh:1690 +msgid "Browse Current Branch's Files" +msgstr "浏览当前分支文件" + +#: git-gui.sh:1692 +#, fuzzy, tcl-format +msgid "Browse %s's Files" +msgstr "浏览当前分支文件" + +#: git-gui.sh:1694 +#, fuzzy +msgid "Browse Branch Files..." +msgstr "浏览当前分支文件" + +#: git-gui.sh:1699 +msgid "Visualize Current Branch's History" +msgstr "调用gitk显示当前分支" + +#: git-gui.sh:1701 +#, fuzzy, tcl-format +msgid "Visualize %s's History" +msgstr "调用gitk显示所有分支" + +#: git-gui.sh:1703 +msgid "Visualize All Branch History" +msgstr "调用gitk显示所有分支" + +#: git-gui.sh:1708 lib/database.tcl:27 lib/database.tcl:67 +msgid "Database Statistics" +msgstr "数据库统计数据" + +#: git-gui.sh:1711 lib/database.tcl:34 +msgid "Compress Database" +msgstr "压缩数据库" + +#: git-gui.sh:1714 +msgid "Verify Database" +msgstr "验证数据库" + +#: git-gui.sh:1721 git-gui.sh:1725 git-gui.sh:1729 lib/shortcut.tcl:9 +#: lib/shortcut.tcl:45 lib/shortcut.tcl:84 +msgid "Create Desktop Icon" +msgstr "创建桌面图标" + +#: git-gui.sh:1734 +msgid "Quit" +msgstr "退出" + +#: git-gui.sh:1741 +msgid "Undo" +msgstr "撤销" + +#: git-gui.sh:1744 +msgid "Redo" +msgstr "重做" + +#: git-gui.sh:1748 git-gui.sh:2263 +msgid "Cut" +msgstr "剪切" + +#: git-gui.sh:1751 git-gui.sh:2266 git-gui.sh:2337 git-gui.sh:2409 +#: lib/console.tcl:69 +msgid "Copy" +msgstr "复制" + +#: git-gui.sh:1754 git-gui.sh:2269 +msgid "Paste" +msgstr "粘贴" + +#: git-gui.sh:1757 git-gui.sh:2272 lib/branch_delete.tcl:26 +#: lib/remote_branch_delete.tcl:38 +msgid "Delete" +msgstr "删除" + +#: git-gui.sh:1761 git-gui.sh:2276 git-gui.sh:2413 lib/console.tcl:71 +msgid "Select All" +msgstr "全选" + +#: git-gui.sh:1770 +msgid "Create..." +msgstr "新建..." + +#: git-gui.sh:1776 +msgid "Checkout..." +msgstr "切换..." + +#: git-gui.sh:1782 +msgid "Rename..." +msgstr "改名..." + +#: git-gui.sh:1787 git-gui.sh:1885 +msgid "Delete..." +msgstr "删除..." + +#: git-gui.sh:1792 +msgid "Reset..." +msgstr "重置所有修动..." + +#: git-gui.sh:1804 git-gui.sh:2210 +msgid "New Commit" +msgstr "新提交" + +#: git-gui.sh:1812 git-gui.sh:2217 +msgid "Amend Last Commit" +msgstr "修订上次提交" + +#: git-gui.sh:1821 git-gui.sh:2177 lib/remote_branch_delete.tcl:99 +msgid "Rescan" +msgstr "重新扫描" + +#: git-gui.sh:1827 +msgid "Add To Commit" +msgstr "添加到本次提交" + +#: git-gui.sh:1832 +msgid "Add Existing To Commit" +msgstr "添加默认修改文件" + +#: git-gui.sh:1838 +msgid "Unstage From Commit" +msgstr "从本次提交移除" + +#: git-gui.sh:1843 lib/index.tcl:376 +msgid "Revert Changes" +msgstr "恢复修改" + +#: git-gui.sh:1850 git-gui.sh:2189 git-gui.sh:2287 +msgid "Sign Off" +msgstr "签名" + +#: git-gui.sh:1865 +msgid "Local Merge..." +msgstr "本地合并..." + +#: git-gui.sh:1870 +msgid "Abort Merge..." +msgstr "取消合并..." + +#: git-gui.sh:1882 +msgid "Push..." +msgstr "上传..." + +#: git-gui.sh:1892 +msgid "Apple" +msgstr "苹果" + +#: git-gui.sh:1895 git-gui.sh:1942 lib/option.tcl:65 +#, tcl-format +msgid "About %s" +msgstr "关于%s" + +#: git-gui.sh:1897 git-gui.sh:1903 git-gui.sh:2455 +msgid "Options..." +msgstr "选项..." + +#: git-gui.sh:1917 +msgid "Running miga..." +msgstr "" + +#: git-gui.sh:1938 +msgid "Help" +msgstr "帮助" + +#: git-gui.sh:1979 +msgid "Online Documentation" +msgstr "在线文档" + +#: git-gui.sh:2095 +msgid "Current Branch:" +msgstr "当前分支:" + +#: git-gui.sh:2116 +msgid "Staged Changes (Will Be Committed)" +msgstr "将被提交的修改" + +#: git-gui.sh:2136 +msgid "Unstaged Changes (Will Not Be Committed)" +msgstr "不被提交的修改" + +#: git-gui.sh:2183 +msgid "Add Existing" +msgstr "添加默认修改文件" + +#: git-gui.sh:2229 +msgid "Initial Commit Message:" +msgstr "初始提交描述:" + +#: git-gui.sh:2230 +msgid "Amended Commit Message:" +msgstr "修订提交描述:" + +#: git-gui.sh:2231 +msgid "Amended Initial Commit Message:" +msgstr "修订初始提交描述:" + +#: git-gui.sh:2232 +msgid "Amended Merge Commit Message:" +msgstr "修订合并提交描述:" + +#: git-gui.sh:2233 +msgid "Merge Commit Message:" +msgstr "合并提交描述:" + +#: git-gui.sh:2234 +msgid "Commit Message:" +msgstr "提交描述:" + +#: git-gui.sh:2279 git-gui.sh:2417 lib/console.tcl:73 +msgid "Copy All" +msgstr "全部复制" + +#: git-gui.sh:2303 lib/blame.tcl:104 +msgid "File:" +msgstr "" + +#: git-gui.sh:2405 +msgid "Refresh" +msgstr "刷新" + +#: git-gui.sh:2426 +msgid "Apply/Reverse Hunk" +msgstr "应用/撤消此修改块" + +#: git-gui.sh:2432 +msgid "Decrease Font Size" +msgstr "缩小字体" + +#: git-gui.sh:2436 +msgid "Increase Font Size" +msgstr "放大字体" + +#: git-gui.sh:2441 +msgid "Show Less Context" +msgstr "显示更多diff上下文" + +#: git-gui.sh:2448 +msgid "Show More Context" +msgstr "显示更少diff上下文" + +#: git-gui.sh:2461 +#, fuzzy +msgid "Unstage Hunk From Commit" +msgstr "从本次提交移除" + +#: git-gui.sh:2463 +#, fuzzy +msgid "Stage Hunk For Commit" +msgstr "从本次提交移除" + +#: git-gui.sh:2473 +msgid "Initializing..." +msgstr "" + +#: lib/blame.tcl:77 +msgid "File Viewer" +msgstr "" + +#: lib/blame.tcl:81 +#, fuzzy +msgid "Commit:" +msgstr "提交" + +#: lib/blame.tcl:249 +#, fuzzy +msgid "Copy Commit" +msgstr "提交" + +#: lib/blame.tcl:369 +#, tcl-format +msgid "Reading %s..." +msgstr "" + +#: lib/branch_checkout.tcl:14 lib/branch_checkout.tcl:19 +#, fuzzy +msgid "Checkout Branch" +msgstr "当前分支:" + +#: lib/branch_checkout.tcl:23 +#, fuzzy +msgid "Checkout" +msgstr "切换..." + +#: lib/branch_checkout.tcl:27 lib/branch_create.tcl:35 +#: lib/branch_delete.tcl:32 lib/branch_rename.tcl:30 lib/browser.tcl:269 +#: lib/checkout_op.tcl:519 lib/merge.tcl:176 lib/option.tcl:172 +#: lib/remote_branch_delete.tcl:42 lib/transport.tcl:92 +msgid "Cancel" +msgstr "" + +#: lib/branch_checkout.tcl:32 lib/browser.tcl:274 +msgid "Revision" +msgstr "" + +#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:159 +#: lib/option.tcl:274 +#, fuzzy +msgid "Options" +msgstr "选项..." + +#: lib/branch_checkout.tcl:39 lib/branch_create.tcl:92 +msgid "Fetch Tracking Branch" +msgstr "" + +#: lib/branch_checkout.tcl:44 +msgid "Detach From Local Branch" +msgstr "" + +#: lib/branch_create.tcl:22 +#, fuzzy +msgid "Create Branch" +msgstr "当前分支:" + +#: lib/branch_create.tcl:27 +#, fuzzy +msgid "Create New Branch" +msgstr "当前分支:" + +#: lib/branch_create.tcl:31 +#, fuzzy +msgid "Create" +msgstr "新建..." + +#: lib/branch_create.tcl:40 +#, fuzzy +msgid "Branch Name" +msgstr "分支" + +#: lib/branch_create.tcl:43 +msgid "Name:" +msgstr "" + +#: lib/branch_create.tcl:58 +msgid "Match Tracking Branch Name" +msgstr "" + +#: lib/branch_create.tcl:66 +msgid "Starting Revision" +msgstr "" + +#: lib/branch_create.tcl:72 +msgid "Update Existing Branch:" +msgstr "" + +#: lib/branch_create.tcl:75 +msgid "No" +msgstr "" + +#: lib/branch_create.tcl:80 +msgid "Fast Forward Only" +msgstr "" + +#: lib/branch_create.tcl:85 lib/checkout_op.tcl:511 +#, fuzzy +msgid "Reset" +msgstr "重置所有修动..." + +#: lib/branch_create.tcl:97 +msgid "Checkout After Creation" +msgstr "" + +#: lib/branch_create.tcl:131 +msgid "Please select a tracking branch." +msgstr "" + +#: lib/branch_create.tcl:140 +#, tcl-format +msgid "Tracking branch %s is not a branch in the remote repository." +msgstr "" + +#: lib/branch_create.tcl:153 lib/branch_rename.tcl:86 +msgid "Please supply a branch name." +msgstr "" + +#: lib/branch_create.tcl:164 lib/branch_rename.tcl:106 +#, tcl-format +msgid "'%s' is not an acceptable branch name." +msgstr "" + +#: lib/branch_delete.tcl:15 +#, fuzzy +msgid "Delete Branch" +msgstr "当前分支:" + +#: lib/branch_delete.tcl:20 +msgid "Delete Local Branch" +msgstr "" + +#: lib/branch_delete.tcl:37 +#, fuzzy +msgid "Local Branches" +msgstr "分支" + +#: lib/branch_delete.tcl:52 +msgid "Delete Only If Merged Into" +msgstr "" + +#: lib/branch_delete.tcl:54 +msgid "Always (Do not perform merge test.)" +msgstr "" + +#: lib/branch_delete.tcl:103 +#, tcl-format +msgid "The following branches are not completely merged into %s:" +msgstr "" + +#: lib/branch_delete.tcl:115 +msgid "" +"Recovering deleted branches is difficult. \n" +"\n" +" Delete the selected branches?" +msgstr "" + +#: lib/branch_delete.tcl:141 +#, tcl-format +msgid "" +"Failed to delete branches:\n" +"%s" +msgstr "" + +#: lib/branch_rename.tcl:14 lib/branch_rename.tcl:22 +#, fuzzy +msgid "Rename Branch" +msgstr "当前分支:" + +#: lib/branch_rename.tcl:26 +#, fuzzy +msgid "Rename" +msgstr "改名..." + +#: lib/branch_rename.tcl:36 +#, fuzzy +msgid "Branch:" +msgstr "分支" + +#: lib/branch_rename.tcl:39 +msgid "New Name:" +msgstr "" + +#: lib/branch_rename.tcl:75 +msgid "Please select a branch to rename." +msgstr "" + +#: lib/branch_rename.tcl:96 lib/checkout_op.tcl:179 +#, tcl-format +msgid "Branch '%s' already exists." +msgstr "" + +#: lib/branch_rename.tcl:117 +#, tcl-format +msgid "Failed to rename '%s'." +msgstr "" + +#: lib/browser.tcl:10 +msgid "Starting..." +msgstr "" + +#: lib/browser.tcl:19 +msgid "File Browser" +msgstr "" + +#: lib/browser.tcl:120 lib/browser.tcl:137 +#, tcl-format +msgid "Loading %s..." +msgstr "" + +#: lib/browser.tcl:254 lib/browser.tcl:260 +#, fuzzy +msgid "Browse Branch Files" +msgstr "浏览当前分支文件" + +#: lib/browser.tcl:265 +msgid "Browse" +msgstr "" + +#: lib/checkout_op.tcl:79 +#, tcl-format +msgid "Fetching %s from %s" +msgstr "" + +#: lib/checkout_op.tcl:140 lib/console.tcl:81 lib/database.tcl:31 +msgid "Close" +msgstr "" + +#: lib/checkout_op.tcl:169 +#, tcl-format +msgid "Branch '%s' does not exist." +msgstr "" + +#: lib/checkout_op.tcl:205 +#, tcl-format +msgid "" +"Branch '%s' already exists.\n" +"\n" +"It cannot fast-forward to %s.\n" +"A merge is required." +msgstr "" + +#: lib/checkout_op.tcl:219 +#, tcl-format +msgid "Merge strategy '%s' not supported." +msgstr "" + +#: lib/checkout_op.tcl:238 +#, tcl-format +msgid "Failed to update '%s'." +msgstr "" + +#: lib/checkout_op.tcl:250 +msgid "Index is already locked." +msgstr "" + +#: lib/checkout_op.tcl:265 +msgid "" +"Last scanned state does not match repository state.\n" +"\n" +"Another Git program has modified this repository since the last scan. A " +"rescan must be performed before the current branch can be changed.\n" +"\n" +"The rescan will be automatically started now.\n" +msgstr "" + +#: lib/checkout_op.tcl:352 +#, tcl-format +msgid "Aborted checkout of '%s' (file level merging is required)." +msgstr "" + +#: lib/checkout_op.tcl:353 +msgid "File level merge required." +msgstr "" + +#: lib/checkout_op.tcl:357 +#, tcl-format +msgid "Staying on branch '%s'." +msgstr "" + +#: lib/checkout_op.tcl:426 +msgid "" +"You are no longer on a local branch.\n" +"\n" +"If you wanted to be on a branch, create one now starting from 'This Detached " +"Checkout'." +msgstr "" + +#: lib/checkout_op.tcl:475 +#, tcl-format +msgid "Resetting '%s' to '%s' will lose the following commits:" +msgstr "" + +#: lib/checkout_op.tcl:497 +msgid "Recovering lost commits may not be easy." +msgstr "" + +#: lib/checkout_op.tcl:502 +#, tcl-format +msgid "Reset '%s'?" +msgstr "" + +#: lib/checkout_op.tcl:507 lib/merge.tcl:171 +msgid "Visualize" +msgstr "" + +#: lib/checkout_op.tcl:575 +#, tcl-format +msgid "" +"Failed to set current branch.\n" +"\n" +"This working directory is only partially switched. We successfully updated " +"your files, but failed to update an internal Git file.\n" +"\n" +"This should not have occurred. %s will now close and give up." +msgstr "" + +#: lib/choose_rev.tcl:35 +msgid "This Detached Checkout" +msgstr "" + +#: lib/choose_rev.tcl:42 +msgid "Revision Expression:" +msgstr "" + +#: lib/choose_rev.tcl:56 +#, fuzzy +msgid "Local Branch" +msgstr "分支" + +#: lib/choose_rev.tcl:61 +#, fuzzy +msgid "Tracking Branch" +msgstr "当前分支:" + +#: lib/choose_rev.tcl:66 +msgid "Tag" +msgstr "" + +#: lib/choose_rev.tcl:227 +#, tcl-format +msgid "Invalid revision: %s" +msgstr "" + +#: lib/choose_rev.tcl:248 +msgid "No revision selected." +msgstr "" + +#: lib/choose_rev.tcl:256 +msgid "Revision expression is empty." +msgstr "" + +#: lib/commit.tcl:9 +msgid "" +"There is nothing to amend.\n" +"\n" +"You are about to create the initial commit. There is no commit before this " +"to amend.\n" +msgstr "" + +#: lib/commit.tcl:18 +msgid "" +"Cannot amend while merging.\n" +"\n" +"You are currently in the middle of a merge that has not been fully " +"completed. You cannot amend the prior commit unless you first abort the " +"current merge activity.\n" +msgstr "" + +#: lib/commit.tcl:49 +msgid "Error loading commit data for amend:" +msgstr "" + +#: lib/commit.tcl:76 +msgid "Unable to obtain your identity:" +msgstr "" + +#: lib/commit.tcl:81 +msgid "Invalid GIT_COMMITTER_IDENT:" +msgstr "" + +#: lib/commit.tcl:133 +msgid "" +"Last scanned state does not match repository state.\n" +"\n" +"Another Git program has modified this repository since the last scan. A " +"rescan must be performed before another commit can be created.\n" +"\n" +"The rescan will be automatically started now.\n" +msgstr "" + +#: lib/commit.tcl:154 +#, tcl-format +msgid "" +"Unmerged files cannot be committed.\n" +"\n" +"File %s has merge conflicts. You must resolve them and add the file before " +"committing.\n" +msgstr "" + +#: lib/commit.tcl:162 +#, tcl-format +msgid "" +"Unknown file state %s detected.\n" +"\n" +"File %s cannot be committed by this program.\n" +msgstr "" + +#: lib/commit.tcl:170 +msgid "" +"No changes to commit.\n" +"\n" +"You must add at least 1 file before you can commit.\n" +msgstr "" + +#: lib/commit.tcl:183 +msgid "" +"Please supply a commit message.\n" +"\n" +"A good commit message has the following format:\n" +"\n" +"- First line: Describe in one sentance what you did.\n" +"- Second line: Blank\n" +"- Remaining lines: Describe why this change is good.\n" +msgstr "" + +#: lib/commit.tcl:257 +msgid "write-tree failed:" +msgstr "" + +#: lib/commit.tcl:279 +msgid "" +"No changes to commit.\n" +"\n" +"No files were modified by this commit and it was not a merge commit.\n" +"\n" +"A rescan will be automatically started now.\n" +msgstr "" + +#: lib/commit.tcl:286 +msgid "No changes to commit." +msgstr "" + +#: lib/commit.tcl:317 +msgid "commit-tree failed:" +msgstr "" + +#: lib/commit.tcl:339 +msgid "update-ref failed:" +msgstr "" + +#: lib/commit.tcl:430 +#, tcl-format +msgid "Created commit %s: %s" +msgstr "" + +#: lib/console.tcl:55 +msgid "Working... please wait..." +msgstr "" + +#: lib/console.tcl:184 +msgid "Success" +msgstr "" + +#: lib/console.tcl:194 +msgid "Error: Command Failed" +msgstr "" + +#: lib/database.tcl:43 +msgid "Number of loose objects" +msgstr "" + +#: lib/database.tcl:44 +msgid "Disk space used by loose objects" +msgstr "" + +#: lib/database.tcl:45 +msgid "Number of packed objects" +msgstr "" + +#: lib/database.tcl:46 +msgid "Number of packs" +msgstr "" + +#: lib/database.tcl:47 +msgid "Disk space used by packed objects" +msgstr "" + +#: lib/database.tcl:48 +msgid "Packed objects waiting for pruning" +msgstr "" + +#: lib/database.tcl:49 +msgid "Garbage files" +msgstr "" + +#: lib/database.tcl:72 +#, fuzzy +msgid "Compressing the object database" +msgstr "压缩数据库" + +#: lib/database.tcl:83 +msgid "Verifying the object database with fsck-objects" +msgstr "" + +#: lib/diff.tcl:42 +#, tcl-format +msgid "" +"No differences detected.\n" +"\n" +"%s has no changes.\n" +"\n" +"The modification date of this file was updated by another application, but " +"the content within the file was not changed.\n" +"\n" +"A rescan will be automatically started to find other files which may have " +"the same state." +msgstr "" + +#: lib/diff.tcl:97 +msgid "Error loading file:" +msgstr "" + +#: lib/diff.tcl:162 +msgid "Error loading diff:" +msgstr "" + +#: lib/diff.tcl:278 +msgid "Failed to unstage selected hunk." +msgstr "" + +#: lib/diff.tcl:285 +msgid "Failed to stage selected hunk." +msgstr "" + +#: lib/error.tcl:12 lib/error.tcl:102 +msgid "error" +msgstr "" + +#: lib/error.tcl:28 +msgid "warning" +msgstr "" + +#: lib/error.tcl:81 +msgid "You must correct the above errors before committing." +msgstr "" + +#: lib/index.tcl:364 +#, fuzzy, tcl-format +msgid "Revert changes in file %s?" +msgstr "恢复修改" + +#: lib/index.tcl:366 +#, tcl-format +msgid "Revert changes in these %i files?" +msgstr "" + +#: lib/index.tcl:372 +msgid "Any unadded changes will be permanently lost by the revert." +msgstr "" + +#: lib/index.tcl:375 +msgid "Do Nothing" +msgstr "" + +#: lib/merge.tcl:14 +msgid "" +"Cannot merge while amending.\n" +"\n" +"You must finish amending this commit before starting any type of merge.\n" +msgstr "" + +#: lib/merge.tcl:28 +msgid "" +"Last scanned state does not match repository state.\n" +"\n" +"Another Git program has modified this repository since the last scan. A " +"rescan must be performed before a merge can be performed.\n" +"\n" +"The rescan will be automatically started now.\n" +msgstr "" + +#: lib/merge.tcl:45 +#, tcl-format +msgid "" +"You are in the middle of a conflicted merge.\n" +"\n" +"File %s has merge conflicts.\n" +"\n" +"You must resolve them, add the file, and commit to complete the current " +"merge. Only then can you begin another merge.\n" +msgstr "" + +#: lib/merge.tcl:55 +#, tcl-format +msgid "" +"You are in the middle of a change.\n" +"\n" +"File %s is modified.\n" +"\n" +"You should complete the current commit before starting a merge. Doing so " +"will help you abort a failed merge, should the need arise.\n" +msgstr "" + +#: lib/merge.tcl:94 +#, tcl-format +msgid "Merging %s and %s" +msgstr "" + +#: lib/merge.tcl:106 +msgid "Merge completed successfully." +msgstr "" + +#: lib/merge.tcl:108 +msgid "Merge failed. Conflict resolution is required." +msgstr "" + +#: lib/merge.tcl:166 +#, tcl-format +msgid "Merge Into %s" +msgstr "" + +#: lib/merge.tcl:181 lib/transport.tcl:98 +#, fuzzy +msgid "Source Branches" +msgstr "当前分支:" + +#: lib/merge.tcl:240 +msgid "" +"Cannot abort while amending.\n" +"\n" +"You must finish amending this commit.\n" +msgstr "" + +#: lib/merge.tcl:250 +msgid "" +"Abort merge?\n" +"\n" +"Aborting the current merge will cause *ALL* uncommitted changes to be lost.\n" +"\n" +"Continue with aborting the current merge?" +msgstr "" + +#: lib/merge.tcl:256 +msgid "" +"Abort commit?\n" +"\n" +"Aborting the current commit will cause *ALL* uncommitted changes to be " +"lost.\n" +"\n" +"Continue with aborting the current commit?" +msgstr "" + +#: lib/merge.tcl:267 +msgid "Aborting... please wait..." +msgstr "" + +#: lib/merge.tcl:290 +msgid "Abort completed. Ready." +msgstr "" + +#: lib/option.tcl:77 +msgid "git-gui - a graphical user interface for Git." +msgstr "" + +#: lib/option.tcl:164 +msgid "Restore Defaults" +msgstr "" + +#: lib/option.tcl:168 +msgid "Save" +msgstr "" + +#: lib/option.tcl:178 +#, fuzzy, tcl-format +msgid "%s Repository" +msgstr "版本树" + +#: lib/option.tcl:179 +msgid "Global (All Repositories)" +msgstr "" + +#: lib/option.tcl:185 +msgid "User Name" +msgstr "" + +#: lib/option.tcl:186 +msgid "Email Address" +msgstr "" + +#: lib/option.tcl:188 +#, fuzzy +msgid "Summarize Merge Commits" +msgstr "修订合并提交描述:" + +#: lib/option.tcl:189 +msgid "Merge Verbosity" +msgstr "" + +#: lib/option.tcl:190 +msgid "Show Diffstat After Merge" +msgstr "" + +#: lib/option.tcl:192 +msgid "Trust File Modification Timestamps" +msgstr "" + +#: lib/option.tcl:193 +msgid "Prune Tracking Branches During Fetch" +msgstr "" + +#: lib/option.tcl:194 +msgid "Match Tracking Branches" +msgstr "" + +#: lib/option.tcl:195 +msgid "Number of Diff Context Lines" +msgstr "" + +#: lib/option.tcl:196 +msgid "New Branch Name Template" +msgstr "" + +#: lib/option.tcl:305 +msgid "Failed to completely save options:" +msgstr "" + +#: lib/remote_branch_delete.tcl:29 lib/remote_branch_delete.tcl:34 +msgid "Delete Remote Branch" +msgstr "" + +#: lib/remote_branch_delete.tcl:47 +#, fuzzy +msgid "From Repository" +msgstr "版本树" + +#: lib/remote_branch_delete.tcl:50 lib/transport.tcl:118 +msgid "Remote:" +msgstr "" + +#: lib/remote_branch_delete.tcl:66 lib/transport.tcl:133 +msgid "Arbitrary URL:" +msgstr "" + +#: lib/remote_branch_delete.tcl:84 +#, fuzzy +msgid "Branches" +msgstr "分支" + +#: lib/remote_branch_delete.tcl:109 +#, fuzzy +msgid "Delete Only If" +msgstr "删除" + +#: lib/remote_branch_delete.tcl:111 +msgid "Merged Into:" +msgstr "" + +#: lib/remote_branch_delete.tcl:119 +msgid "Always (Do not perform merge checks)" +msgstr "" + +#: lib/remote_branch_delete.tcl:152 +msgid "A branch is required for 'Merged Into'." +msgstr "" + +#: lib/remote_branch_delete.tcl:189 +#, tcl-format +msgid "" +"One or more of the merge tests failed because you have not fetched the " +"necessary commits. Try fetching from %s first." +msgstr "" + +#: lib/remote_branch_delete.tcl:207 +msgid "Please select one or more branches to delete." +msgstr "" + +#: lib/remote_branch_delete.tcl:216 +msgid "" +"Recovering deleted branches is difficult.\n" +"\n" +"Delete the selected branches?" +msgstr "" + +#: lib/remote_branch_delete.tcl:226 +#, tcl-format +msgid "Deleting branches from %s" +msgstr "" + +#: lib/remote_branch_delete.tcl:286 +msgid "No repository selected." +msgstr "" + +#: lib/remote_branch_delete.tcl:291 +#, tcl-format +msgid "Scanning %s..." +msgstr "" + +#: lib/remote.tcl:156 +#, tcl-format +msgid "Fetch from %s..." +msgstr "" + +#: lib/remote.tcl:166 +#, tcl-format +msgid "Prune from %s..." +msgstr "" + +#: lib/remote.tcl:200 +#, fuzzy, tcl-format +msgid "Push to %s..." +msgstr "上传..." + +#: lib/shortcut.tcl:26 lib/shortcut.tcl:74 +msgid "Cannot write script:" +msgstr "" + +#: lib/shortcut.tcl:149 +msgid "Cannot write icon:" +msgstr "" + +#: lib/status_bar.tcl:58 +#, tcl-format +msgid "%s ... %i of %i %s (%2i%%)" +msgstr "" + +#: lib/transport.tcl:7 +#, tcl-format +msgid "Fetching new changes from %s" +msgstr "" + +#: lib/transport.tcl:19 +#, tcl-format +msgid "Pruning tracking branches deleted from %s" +msgstr "" + +#: lib/transport.tcl:26 +#, tcl-format +msgid "Pushing changes to %s" +msgstr "" + +#: lib/transport.tcl:68 +#, tcl-format +msgid "Pushing %s %s to %s" +msgstr "" + +#: lib/transport.tcl:84 +#, fuzzy +msgid "Push Branches" +msgstr "分支" + +#: lib/transport.tcl:115 +#, fuzzy +msgid "Destination Repository" +msgstr "版本树" + +#: lib/transport.tcl:153 +msgid "Transfer Options" +msgstr "" + +#: lib/transport.tcl:155 +msgid "Use thin pack (for slow network connections)" +msgstr "" + +#: lib/transport.tcl:159 +msgid "Include tags" +msgstr "" From 2340a74e5f64243a10ae2daa9403baa28f3d9d11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=97=E3=82=89=E3=81=84=E3=81=97=E3=81=AA=E3=81=AA?= =?UTF-8?q?=E3=81=93?= Date: Wed, 25 Jul 2007 17:59:58 +0900 Subject: [PATCH 0023/1490] Japanese translation of git-gui MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [jes: Also includes work from Junio Hamano] Signed-off-by: しらいしななこ Signed-off-by: Johannes Schindelin --- po/ja.po | 1381 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1381 insertions(+) create mode 100644 po/ja.po diff --git a/po/ja.po b/po/ja.po new file mode 100644 index 0000000000..17139080ec --- /dev/null +++ b/po/ja.po @@ -0,0 +1,1381 @@ +# Translation of git-gui to Japanese +# Copyright (C) 2007 Shawn Pearce +# This file is distributed under the same license as the git-gui package. +# しらいし ななこ , 2007. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: git-gui\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2007-08-11 17:28+0200\n" +"PO-Revision-Date: 2007-08-14 18:49+0900\n" +"Last-Translator: しらいし ななこ \n" +"Language-Team: Japanese\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: git-gui.sh:531 +msgid "Cannot find git in PATH." +msgstr "PATH 中に git が見つかりません" + +#: git-gui.sh:550 +msgid "Cannot parse Git version string:" +msgstr "Git バージョン名が理解できません:" + +#: git-gui.sh:567 +#, tcl-format +msgid "" +"Git version cannot be determined.\n" +"\n" +"%s claims it is version '%s'.\n" +"\n" +"%s requires at least Git 1.5.0 or later.\n" +"\n" +"Assume '%s' is version 1.5.0?\n" +msgstr "" +"Git のバージョンが確認できません。\n" +"\n" +"%s はバージョン '%s' とのことです。\n" +"\n" +"%s は最低でも 1.5.0 かそれ以降の Git が必要です\n" +"\n" +"'%s' はバージョン 1.5.0 と思って良いですか?\n" + +#: git-gui.sh:689 +msgid "Cannot find the git directory:" +msgstr "git ディレクトリが見つかりません:" + +#: git-gui.sh:697 +msgid "Git directory not found:" +msgstr "Git ディレクトリが見つかりません:" + +#: git-gui.sh:703 +msgid "Cannot use funny .git directory:" +msgstr "変な .git ディレクトリは使えません" + +#: git-gui.sh:708 +msgid "No working directory" +msgstr "作業ディレクトリがありません" + +#: git-gui.sh:854 +msgid "Refreshing file status..." +msgstr "ファイル状態を更新しています…" + +#: git-gui.sh:891 +msgid "Scanning for modified files ..." +msgstr "変更されたファイルをスキャンしています…" + +#: git-gui.sh:1057 lib/browser.tcl:247 +msgid "Ready." +msgstr "準備完了" + +#: git-gui.sh:1322 +msgid "Unmodified" +msgstr "変更無し" + +#: git-gui.sh:1324 +msgid "Modified, not staged" +msgstr "変更あり、コミット未予定" + +#: git-gui.sh:1325 git-gui.sh:1330 +msgid "Staged for commit" +msgstr "コミット予定済" + +#: git-gui.sh:1326 git-gui.sh:1331 +msgid "Portions staged for commit" +msgstr "部分的にコミット予定済" + +#: git-gui.sh:1327 git-gui.sh:1332 +msgid "Staged for commit, missing" +msgstr "コミット予定済、ファイル無し" + +#: git-gui.sh:1329 +msgid "Untracked, not staged" +msgstr "管理外、コミット未予定" + +#: git-gui.sh:1334 +msgid "Missing" +msgstr "ファイル無し" + +#: git-gui.sh:1335 +msgid "Staged for removal" +msgstr "削除予定済" + +#: git-gui.sh:1336 +msgid "Staged for removal, still present" +msgstr "削除予定済、ファイル未削除" + +#: git-gui.sh:1338 git-gui.sh:1339 git-gui.sh:1340 git-gui.sh:1341 +msgid "Requires merge resolution" +msgstr "要マージ解決" + +#: git-gui.sh:1383 +msgid "Starting gitk... please wait..." +msgstr "gitk を起動中…お待ち下さい…" + +#: git-gui.sh:1392 +#, tcl-format +msgid "" +"Unable to start gitk:\n" +"\n" +"%s does not exist" +msgstr "" +"gitk を起動できません:\n" +"\n" +"%s がありません" + +#: git-gui.sh:1609 +#, tcl-format +msgid "Invalid font specified in gui.%s:" +msgstr "gui.%s に無効なフォントが指定されています:" + +#: git-gui.sh:1634 +msgid "Main Font" +msgstr "主フォント" + +#: git-gui.sh:1635 +msgid "Diff/Console Font" +msgstr "diff/コンソール・フォント" + +#: git-gui.sh:1649 +msgid "Repository" +msgstr "リポジトリ" + +#: git-gui.sh:1650 +msgid "Edit" +msgstr "編集" + +#: git-gui.sh:1652 +msgid "Branch" +msgstr "ブランチ" + +#: git-gui.sh:1655 git-gui.sh:1842 git-gui.sh:2152 +msgid "Commit" +msgstr "コミット" + +#: git-gui.sh:1658 lib/merge.tcl:121 lib/merge.tcl:150 lib/merge.tcl:168 +msgid "Merge" +msgstr "マージ" + +#: git-gui.sh:1659 +msgid "Fetch" +msgstr "フェッチ" + +#: git-gui.sh:1660 git-gui.sh:2158 lib/transport.tcl:88 lib/transport.tcl:172 +msgid "Push" +msgstr "プッシュ" + +#: git-gui.sh:1669 +msgid "Browse Current Branch's Files" +msgstr "現在のブランチのファイルを見る" + +#: git-gui.sh:1673 +msgid "Browse Branch Files..." +msgstr "ブランチのファイルを見る…" + +#: git-gui.sh:1678 +msgid "Visualize Current Branch's History" +msgstr "現在のブランチの履歴を見る" + +#: git-gui.sh:1682 +msgid "Visualize All Branch History" +msgstr "全てのブランチの履歴を見る" + +#: git-gui.sh:1689 +#, tcl-format +msgid "Browse %s's Files" +msgstr "ブランチ %s のファイルを見る" + +#: git-gui.sh:1691 +#, tcl-format +msgid "Visualize %s's History" +msgstr "ブランチ %s の履歴を見る" + +#: git-gui.sh:1696 lib/database.tcl:27 lib/database.tcl:67 +msgid "Database Statistics" +msgstr "データベース統計" + +#: git-gui.sh:1699 lib/database.tcl:34 +msgid "Compress Database" +msgstr "データベース圧縮" + +#: git-gui.sh:1702 +msgid "Verify Database" +msgstr "データベース検証" + +#: git-gui.sh:1709 git-gui.sh:1713 git-gui.sh:1717 lib/shortcut.tcl:9 +#: lib/shortcut.tcl:45 lib/shortcut.tcl:84 +msgid "Create Desktop Icon" +msgstr "デスクトップ・アイコンを作る" + +#: git-gui.sh:1722 +msgid "Quit" +msgstr "終了" + +#: git-gui.sh:1729 +msgid "Undo" +msgstr "元に戻す" + +#: git-gui.sh:1732 +msgid "Redo" +msgstr "やり直し" + +#: git-gui.sh:1736 git-gui.sh:2222 +msgid "Cut" +msgstr "切り取り" + +#: git-gui.sh:1739 git-gui.sh:2225 git-gui.sh:2296 git-gui.sh:2368 +#: lib/console.tcl:69 +msgid "Copy" +msgstr "コピー" + +#: git-gui.sh:1742 git-gui.sh:2228 +msgid "Paste" +msgstr "貼り付け" + +#: git-gui.sh:1745 git-gui.sh:2231 lib/branch_delete.tcl:26 +#: lib/remote_branch_delete.tcl:38 +msgid "Delete" +msgstr "削除" + +#: git-gui.sh:1749 git-gui.sh:2235 git-gui.sh:2372 lib/console.tcl:71 +msgid "Select All" +msgstr "全て選択" + +#: git-gui.sh:1758 +msgid "Create..." +msgstr "作成…" + +#: git-gui.sh:1764 +msgid "Checkout..." +msgstr "チェックアウト" + +#: git-gui.sh:1770 +msgid "Rename..." +msgstr "名前変更…" + +#: git-gui.sh:1775 git-gui.sh:1873 +msgid "Delete..." +msgstr "削除…" + +#: git-gui.sh:1780 +msgid "Reset..." +msgstr "リセット…" + +#: git-gui.sh:1792 git-gui.sh:2169 +msgid "New Commit" +msgstr "新規コミット" + +#: git-gui.sh:1800 git-gui.sh:2176 +msgid "Amend Last Commit" +msgstr "最新コミットを訂正" + +#: git-gui.sh:1809 git-gui.sh:2136 lib/remote_branch_delete.tcl:99 +msgid "Rescan" +msgstr "再スキャン" + +#: git-gui.sh:1815 +msgid "Stage To Commit" +msgstr "コミット予定する" + +#: git-gui.sh:1820 +msgid "Stage Changed Files To Commit" +msgstr "変更されたファイルをコミット予定" + +#: git-gui.sh:1826 +msgid "Unstage From Commit" +msgstr "コミットから降ろす" + +#: git-gui.sh:1831 lib/index.tcl:376 +msgid "Revert Changes" +msgstr "変更を元に戻す" + +#: git-gui.sh:1838 git-gui.sh:2148 git-gui.sh:2246 +msgid "Sign Off" +msgstr "署名" + +#: git-gui.sh:1853 +msgid "Local Merge..." +msgstr "ローカル・マージ…" + +#: git-gui.sh:1858 +msgid "Abort Merge..." +msgstr "マージ中止…" + +#: git-gui.sh:1870 +msgid "Push..." +msgstr "プッシュ…" + +#: git-gui.sh:1880 +msgid "Apple" +msgstr "りんご" + +#: git-gui.sh:1883 git-gui.sh:1901 lib/option.tcl:65 +#, tcl-format +msgid "About %s" +msgstr "%s について" + +#: git-gui.sh:1885 git-gui.sh:1891 git-gui.sh:2414 +msgid "Options..." +msgstr "オプション…" + +#: git-gui.sh:1897 +msgid "Help" +msgstr "ヘルプ" + +#: git-gui.sh:1938 +msgid "Online Documentation" +msgstr "オンライン・ドキュメント" + +#: git-gui.sh:2054 +msgid "Current Branch:" +msgstr "現在のブランチ" + +#: git-gui.sh:2075 +msgid "Staged Changes (Will Be Committed)" +msgstr "ステージングされた(コミット予定済の)変更" + +#: git-gui.sh:2095 +msgid "Unstaged Changes (Will Not Be Committed)" +msgstr "ステージングされていない(コミット未予定の)変更" + +#: git-gui.sh:2142 +msgid "Stage Changed" +msgstr "変更をコミット予定に入れる" + +#: git-gui.sh:2188 +msgid "Initial Commit Message:" +msgstr "最初のコミットメッセージ:" + +#: git-gui.sh:2189 +msgid "Amended Commit Message:" +msgstr "訂正したコミットメッセージ:" + +#: git-gui.sh:2190 +msgid "Amended Initial Commit Message:" +msgstr "訂正した最初のコミットメッセージ:" + +#: git-gui.sh:2191 +msgid "Amended Merge Commit Message:" +msgstr "訂正したマージコミットメッセージ:" + +#: git-gui.sh:2192 +msgid "Merge Commit Message:" +msgstr "マージコミットメッセージ:" + +#: git-gui.sh:2193 +msgid "Commit Message:" +msgstr "コミットメッセージ:" + +#: git-gui.sh:2238 git-gui.sh:2376 lib/console.tcl:73 +msgid "Copy All" +msgstr "全てコピー" + +#: git-gui.sh:2262 lib/blame.tcl:104 +msgid "File:" +msgstr "ファイル:" + +#: git-gui.sh:2364 +msgid "Refresh" +msgstr "再読み込み" + +#: git-gui.sh:2385 +msgid "Apply/Reverse Hunk" +msgstr "パッチを適用/取り消す" + +#: git-gui.sh:2391 +msgid "Decrease Font Size" +msgstr "フォントを小さく" + +#: git-gui.sh:2395 +msgid "Increase Font Size" +msgstr "フォントを大きく" + +#: git-gui.sh:2400 +msgid "Show Less Context" +msgstr "文脈を少なく" + +#: git-gui.sh:2407 +msgid "Show More Context" +msgstr "文脈を多く" + +#: git-gui.sh:2422 +msgid "Unstage Hunk From Commit" +msgstr "パッチをコミット予定から外す" + +#: git-gui.sh:2426 git-gui.sh:2430 +msgid "Stage Hunk For Commit" +msgstr "パッチをコミット予定に加える" + +#: git-gui.sh:2440 +msgid "Initializing..." +msgstr "初期化しています…" + +#: lib/blame.tcl:77 +msgid "File Viewer" +msgstr "ファイルピューワ" + +#: lib/blame.tcl:81 +msgid "Commit:" +msgstr "コミット:" + +#: lib/blame.tcl:249 +msgid "Copy Commit" +msgstr "コミットをコピー" + +#: lib/blame.tcl:369 +#, tcl-format +msgid "Reading %s..." +msgstr "%s を読んでいます…" + +#: lib/branch_checkout.tcl:14 lib/branch_checkout.tcl:19 +msgid "Checkout Branch" +msgstr "ブランチをチェックアウト" + +#: lib/branch_checkout.tcl:23 +msgid "Checkout" +msgstr "チェックアウト" + +#: lib/branch_checkout.tcl:27 lib/branch_create.tcl:35 +#: lib/branch_delete.tcl:32 lib/branch_rename.tcl:30 lib/browser.tcl:283 +#: lib/checkout_op.tcl:522 lib/merge.tcl:172 lib/option.tcl:172 +#: lib/remote_branch_delete.tcl:42 lib/transport.tcl:92 +msgid "Cancel" +msgstr "中止" + +#: lib/branch_checkout.tcl:32 lib/browser.tcl:288 +msgid "Revision" +msgstr "リビジョン" + +#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:159 +#: lib/option.tcl:274 +msgid "Options" +msgstr "オプション" + +#: lib/branch_checkout.tcl:39 lib/branch_create.tcl:92 +msgid "Fetch Tracking Branch" +msgstr "トラッキング・ブランチをフェッチ" + +#: lib/branch_checkout.tcl:44 +msgid "Detach From Local Branch" +msgstr "ローカル・ブランチから削除" + +#: lib/branch_create.tcl:22 +msgid "Create Branch" +msgstr "ブランチを作成" + +#: lib/branch_create.tcl:27 +msgid "Create New Branch" +msgstr "ブランチを新規作成" + +#: lib/branch_create.tcl:31 +msgid "Create" +msgstr "作成" + +#: lib/branch_create.tcl:40 +msgid "Branch Name" +msgstr "ブランチ名" + +#: lib/branch_create.tcl:43 +msgid "Name:" +msgstr "名前:" + +#: lib/branch_create.tcl:58 +msgid "Match Tracking Branch Name" +msgstr "トラッキング・ブランチ名を合わせる" + +#: lib/branch_create.tcl:66 +msgid "Starting Revision" +msgstr "初期リビジョン" + +#: lib/branch_create.tcl:72 +msgid "Update Existing Branch:" +msgstr "既存のブランチを更新:" + +#: lib/branch_create.tcl:75 +msgid "No" +msgstr "いいえ" + +#: lib/branch_create.tcl:80 +msgid "Fast Forward Only" +msgstr "早送りのみ" + +#: lib/branch_create.tcl:85 lib/checkout_op.tcl:514 +msgid "Reset" +msgstr "リセット" + +#: lib/branch_create.tcl:97 +msgid "Checkout After Creation" +msgstr "作成してすぐチェックアウト" + +#: lib/branch_create.tcl:131 +msgid "Please select a tracking branch." +msgstr "トラッキング・ブランチを選択して下さい。" + +#: lib/branch_create.tcl:140 +#, tcl-format +msgid "Tracking branch %s is not a branch in the remote repository." +msgstr "トラッキング・ブランチ %s は遠隔リポジトリのブランチではありません。" + +#: lib/branch_create.tcl:153 lib/branch_rename.tcl:86 +msgid "Please supply a branch name." +msgstr "ブランチ名を指定して下さい。" + +#: lib/branch_create.tcl:164 lib/branch_rename.tcl:106 +#, tcl-format +msgid "'%s' is not an acceptable branch name." +msgstr "'%s' はブランチ名に使えません。" + +#: lib/branch_delete.tcl:15 +msgid "Delete Branch" +msgstr "ブランチ削除" + +#: lib/branch_delete.tcl:20 +msgid "Delete Local Branch" +msgstr "ローカル・ブランチを削除" + +#: lib/branch_delete.tcl:37 +msgid "Local Branches" +msgstr "ローカル・ブランチ" + +#: lib/branch_delete.tcl:52 +msgid "Delete Only If Merged Into" +msgstr "マージ済みの時のみ削除" + +#: lib/branch_delete.tcl:54 +msgid "Always (Do not perform merge test.)" +msgstr "無条件(マージテストしない)" + +#: lib/branch_delete.tcl:103 +#, tcl-format +msgid "The following branches are not completely merged into %s:" +msgstr "以下のブランチは %s に完全にマージされていません:" + +#: lib/branch_delete.tcl:115 +msgid "" +"Recovering deleted branches is difficult. \n" +"\n" +" Delete the selected branches?" +msgstr "" +"ブランチを削除すると元に戻すのは困難です。 \n" +"\n" +" 選択したブランチを削除しますか?" + +#: lib/branch_delete.tcl:141 +#, tcl-format +msgid "" +"Failed to delete branches:\n" +"%s" +msgstr "" +"以下のブランチを削除できません:\n" +"%s" + +#: lib/branch_rename.tcl:14 lib/branch_rename.tcl:22 +msgid "Rename Branch" +msgstr "ブランチの名前変更" + +#: lib/branch_rename.tcl:26 +msgid "Rename" +msgstr "名前変更" + +#: lib/branch_rename.tcl:36 +msgid "Branch:" +msgstr "ブランチ:" + +#: lib/branch_rename.tcl:39 +msgid "New Name:" +msgstr "新しい名前:" + +#: lib/branch_rename.tcl:75 +msgid "Please select a branch to rename." +msgstr "名前を変更するブランチを選んで下さい。" + +#: lib/branch_rename.tcl:96 lib/checkout_op.tcl:179 +#, tcl-format +msgid "Branch '%s' already exists." +msgstr "'%s'というブランチは既に存在します。" + +#: lib/branch_rename.tcl:117 +#, tcl-format +msgid "Failed to rename '%s'." +msgstr "'%s'の名前変更に失敗しました。" + +#: lib/browser.tcl:17 +msgid "Starting..." +msgstr "起動中…" + +#: lib/browser.tcl:26 +msgid "File Browser" +msgstr "ファイル・ブラウザ" + +#: lib/browser.tcl:127 lib/browser.tcl:144 +#, tcl-format +msgid "Loading %s..." +msgstr "%s をロード中…" + +#: lib/browser.tcl:188 +msgid "[Up To Parent]" +msgstr "[上位フォルダへ]" + +#: lib/browser.tcl:268 lib/browser.tcl:274 +msgid "Browse Branch Files" +msgstr "現在のブランチのファイルを見る" + +#: lib/browser.tcl:279 +msgid "Browse" +msgstr "ブラウズ" + +#: lib/checkout_op.tcl:79 +#, tcl-format +msgid "Fetching %s from %s" +msgstr "%s から %s をフェッチしています" + +#: lib/checkout_op.tcl:140 lib/console.tcl:81 lib/database.tcl:31 +msgid "Close" +msgstr "閉じる" + +#: lib/checkout_op.tcl:169 +#, tcl-format +msgid "Branch '%s' does not exist." +msgstr "ブランチ'%s'は存在しません。" + +#: lib/checkout_op.tcl:206 +#, tcl-format +msgid "" +"Branch '%s' already exists.\n" +"\n" +"It cannot fast-forward to %s.\n" +"A merge is required." +msgstr "" +"ブランチ '%s' は既に存在します。\n" +"\n" +"%s に早送りできません。\n" +"マージが必要です。" + +#: lib/checkout_op.tcl:220 +#, tcl-format +msgid "Merge strategy '%s' not supported." +msgstr "'%s' マージ戦略はサポートされていません。" + +#: lib/checkout_op.tcl:239 +#, tcl-format +msgid "Failed to update '%s'." +msgstr "'%s' の更新に失敗しました。" + +#: lib/checkout_op.tcl:251 +msgid "Staging area (index) is already locked." +msgstr "インデックスは既にロックされています。" + +#: lib/checkout_op.tcl:266 +msgid "" +"Last scanned state does not match repository state.\n" +"\n" +"Another Git program has modified this repository since the last scan. A " +"rescan must be performed before the current branch can be changed.\n" +"\n" +"The rescan will be automatically started now.\n" +msgstr "" +"最後にスキャンした状態はリポジトリの状態と合致しません。\n" +"\n" +"最後にスキャンして以後、別の Git プログラムがリポジトリを変更しています。現在" +"のブランチを変更する前に、再スキャンが必要です。\n" +"\n" +"自動的に再スキャンを開始します。\n" + +#: lib/checkout_op.tcl:353 +#, tcl-format +msgid "Aborted checkout of '%s' (file level merging is required)." +msgstr "'%s' のチェックアウトを中止しました(ファイル毎のマージが必要です)。" + +#: lib/checkout_op.tcl:354 +msgid "File level merge required." +msgstr "ファイル毎のマージが必要です。" + +#: lib/checkout_op.tcl:358 +#, tcl-format +msgid "Staying on branch '%s'." +msgstr "ブランチ '%s' に滞まります。" + +#: lib/checkout_op.tcl:429 +msgid "" +"You are no longer on a local branch.\n" +"\n" +"If you wanted to be on a branch, create one now starting from 'This Detached " +"Checkout'." +msgstr "" +"ローカル・ブランチから離れます。\n" +"\n" +"ブランチ上に滞まりたいときは、この「分離されたチェックアウト」から新規ブラン" +"チを開始してください。" + +#: lib/checkout_op.tcl:478 +#, tcl-format +msgid "Resetting '%s' to '%s' will lose the following commits:" +msgstr "'%s' を '%s' にリセットすると、以下のコミットが失なわれます:" + +#: lib/checkout_op.tcl:500 +msgid "Recovering lost commits may not be easy." +msgstr "失なわれたコミットを回復するのは簡単ではありません。" + +#: lib/checkout_op.tcl:505 +#, tcl-format +msgid "Reset '%s'?" +msgstr "'%s' をリセットしますか?" + +#: lib/checkout_op.tcl:510 lib/merge.tcl:164 +msgid "Visualize" +msgstr "可視化" + +#: lib/checkout_op.tcl:578 +#, tcl-format +msgid "" +"Failed to set current branch.\n" +"\n" +"This working directory is only partially switched. We successfully updated " +"your files, but failed to update an internal Git file.\n" +"\n" +"This should not have occurred. %s will now close and give up." +msgstr "" +"現在のブランチを設定できません。\n" +"\n" +"作業ディレクトリは部分的にしか切り替わっていません。ファイルの更新には成功し" +"ましたが、 Git の内部データを更新できませんでした。\n" +"起こるはずのないエラーです。あきらめて %s を終了します。" + +#: lib/choose_rev.tcl:53 +msgid "This Detached Checkout" +msgstr "分離されたチェックアウト" + +#: lib/choose_rev.tcl:60 +msgid "Revision Expression:" +msgstr "リビジョン式:" + +#: lib/choose_rev.tcl:74 +msgid "Local Branch" +msgstr "ローカル・ブランチ" + +#: lib/choose_rev.tcl:79 +msgid "Tracking Branch" +msgstr "トラッキング・ブランチ" + +#: lib/choose_rev.tcl:84 +msgid "Tag" +msgstr "タグ" + +#: lib/choose_rev.tcl:317 +#, tcl-format +msgid "Invalid revision: %s" +msgstr "無効なリビジョン: %s" + +#: lib/choose_rev.tcl:338 +msgid "No revision selected." +msgstr "リビジョンが未選択です。" + +#: lib/choose_rev.tcl:346 +msgid "Revision expression is empty." +msgstr "リビジョン式が空です。" + +#: lib/commit.tcl:9 +msgid "" +"There is nothing to amend.\n" +"\n" +"You are about to create the initial commit. There is no commit before this " +"to amend.\n" +msgstr "" +"訂正するコミットがそもそもありません。\n" +"\n" +"これから作るのは最初のコミットです。その前にはまだ訂正するようなコミットはあ" +"りません。\n" + +#: lib/commit.tcl:18 +msgid "" +"Cannot amend while merging.\n" +"\n" +"You are currently in the middle of a merge that has not been fully " +"completed. You cannot amend the prior commit unless you first abort the " +"current merge activity.\n" +msgstr "" +"マージ中にコミットの訂正はできません。\n" +"\n" +"現在はまだマージの途中です。先にこのマージを中止しないと、前のコミットの訂正" +"はできません\n" + +#: lib/commit.tcl:49 +msgid "Error loading commit data for amend:" +msgstr "訂正するコミットのデータを読めません:" + +#: lib/commit.tcl:76 +msgid "Unable to obtain your identity:" +msgstr "ユーザの正体を確認できません:" + +#: lib/commit.tcl:81 +msgid "Invalid GIT_COMMITTER_IDENT:" +msgstr "GIT_COMMITTER_IDENT が無効です:" + +#: lib/commit.tcl:133 +msgid "" +"Last scanned state does not match repository state.\n" +"\n" +"Another Git program has modified this repository since the last scan. A " +"rescan must be performed before another commit can be created.\n" +"\n" +"The rescan will be automatically started now.\n" +msgstr "" +"最後にスキャンした状態はリポジトリの状態と合致しません。\n" +"\n" +"最後にスキャンして以後、別の Git プログラムがリポジトリを変更しています。新し" +"くコミットする前に、再スキャンが必要です。\n" +"\n" +"自動的に再スキャンを開始します。\n" + +#: lib/commit.tcl:154 +#, tcl-format +msgid "" +"Unmerged files cannot be committed.\n" +"\n" +"File %s has merge conflicts. You must resolve them and stage the file " +"before committing.\n" +msgstr "" +"マージしていないファイルはコミットできません。\n" +"\n" +"ファイル %s にはマージ衝突が残っています。まず解決してコミット予定に加える必" +"要があります。\n" + +#: lib/commit.tcl:162 +#, tcl-format +msgid "" +"Unknown file state %s detected.\n" +"\n" +"File %s cannot be committed by this program.\n" +msgstr "" +"不明なファイル状態 %s です。\n" +"\n" +"ファイル %s は本プログラムではコミットできません。\n" + +#: lib/commit.tcl:170 +msgid "" +"No changes to commit.\n" +"\n" +"You must stage at least 1 file before you can commit.\n" +msgstr "" +"コミットする変更がありません。\n" +"\n" +"最低一つの変更をコミット予定に加えてからコミットして下さい。\n" + +#: lib/commit.tcl:183 +msgid "" +"Please supply a commit message.\n" +"\n" +"A good commit message has the following format:\n" +"\n" +"- First line: Describe in one sentance what you did.\n" +"- Second line: Blank\n" +"- Remaining lines: Describe why this change is good.\n" +msgstr "" +"コミット・メッセージを入力して下さい。\n" +"\n" +"正しいコミット・メッセージは:\n" +"\n" +"- 第1行: 何をしたか、を1行で要約。\n" +"- 第2行: 空白\n" +"- 残りの行: なぜ、この変更が良い変更か、の説明。\n" + +#: lib/commit.tcl:257 +msgid "write-tree failed:" +msgstr "write-tree が失敗しました:" + +#: lib/commit.tcl:279 +msgid "" +"No changes to commit.\n" +"\n" +"No files were modified by this commit and it was not a merge commit.\n" +"\n" +"A rescan will be automatically started now.\n" +msgstr "" +"コミットする変更がありません。\n" +"\n" +"マージでなく、また、一つも変更点がありません。\n" +"\n" +"自動的に再スキャンを開始します。\n" + +#: lib/commit.tcl:286 +msgid "No changes to commit." +msgstr "コミットする変更がありません。" + +#: lib/commit.tcl:317 +msgid "commit-tree failed:" +msgstr "commit-tree が失敗しました:" + +#: lib/commit.tcl:339 +msgid "update-ref failed:" +msgstr "update-ref が失敗しました:" + +#: lib/commit.tcl:430 +#, tcl-format +msgid "Created commit %s: %s" +msgstr "コミット %s を作成しました: %s" + +#: lib/console.tcl:55 +msgid "Working... please wait..." +msgstr "実行中…お待ち下さい…" + +#: lib/console.tcl:184 +msgid "Success" +msgstr "成功" + +#: lib/console.tcl:194 +msgid "Error: Command Failed" +msgstr "エラー: コマンドが失敗しました" + +#: lib/database.tcl:43 +msgid "Number of loose objects" +msgstr "ばらばらなオブジェクトの数" + +#: lib/database.tcl:44 +msgid "Disk space used by loose objects" +msgstr "ばらばらなオブジェクトの使用するディスク量" + +#: lib/database.tcl:45 +msgid "Number of packed objects" +msgstr "パックされたオブジェクトの数" + +#: lib/database.tcl:46 +msgid "Number of packs" +msgstr "パックの数" + +#: lib/database.tcl:47 +msgid "Disk space used by packed objects" +msgstr "パックされたオブジェクトの使用するディスク量" + +#: lib/database.tcl:48 +msgid "Packed objects waiting for pruning" +msgstr "パックに存在するので捨てて良いオブジェクトの数" + +#: lib/database.tcl:49 +msgid "Garbage files" +msgstr "ゴミファイル" + +#: lib/database.tcl:72 +msgid "Compressing the object database" +msgstr "データベース圧縮" + +#: lib/database.tcl:83 +msgid "Verifying the object database with fsck-objects" +msgstr "fsck-objects でオブジェクト・データベースを検証しています" + +#: lib/diff.tcl:42 +#, tcl-format +msgid "" +"No differences detected.\n" +"\n" +"%s has no changes.\n" +"\n" +"The modification date of this file was updated by another application, but " +"the content within the file was not changed.\n" +"\n" +"A rescan will be automatically started to find other files which may have " +"the same state." +msgstr "" +"変更がありません。\n" +"\n" +"%s には変更がありません。\n" +"\n" +"このファイルの変更時刻は他のアプリケーションによって更新されていますがファイ" +"ル内容には変更がありません。\n" +"\n" +"同様な状態のファイルを探すために、自動的に再スキャンを開始します。" + +#: lib/diff.tcl:97 +msgid "Error loading file:" +msgstr "ファイルを読む際のエラーです:" + +#: lib/diff.tcl:162 +msgid "Error loading diff:" +msgstr "diff を読む際のエラーです:" + +#: lib/diff.tcl:278 +msgid "Failed to unstage selected hunk." +msgstr "選択されたパッチをコミット予定から外せません。" + +#: lib/diff.tcl:285 +msgid "Failed to stage selected hunk." +msgstr "選択されたパッチをコミット予定に加えられません。" + +#: lib/error.tcl:12 lib/error.tcl:102 +msgid "error" +msgstr "エラー" + +#: lib/error.tcl:28 +msgid "warning" +msgstr "警告" + +#: lib/error.tcl:81 +msgid "You must correct the above errors before committing." +msgstr "コミットする前に、以上のエラーを修正して下さい" + +#: lib/index.tcl:364 +#, tcl-format +msgid "Revert changes in file %s?" +msgstr "ファイル %s にした変更を元に戻しますか?" + +#: lib/index.tcl:366 +#, tcl-format +msgid "Revert changes in these %i files?" +msgstr "これら %i 個のファイルにした変更を元に戻しますか?" + +#: lib/index.tcl:372 +msgid "Any unstaged changes will be permanently lost by the revert." +msgstr "変更を元に戻すとコミット予定していない変更は全て失われます。" + +#: lib/index.tcl:375 +msgid "Do Nothing" +msgstr "何もしない" + +#: lib/merge.tcl:13 +msgid "" +"Cannot merge while amending.\n" +"\n" +"You must finish amending this commit before starting any type of merge.\n" +msgstr "" +"訂正中にはマージできません。\n" +"\n" +"訂正処理を完了するまでは新たにマージを開始できません。\n" + +#: lib/merge.tcl:27 +msgid "" +"Last scanned state does not match repository state.\n" +"\n" +"Another Git program has modified this repository since the last scan. A " +"rescan must be performed before a merge can be performed.\n" +"\n" +"The rescan will be automatically started now.\n" +msgstr "" +"最後にスキャンした状態はリポジトリの状態と合致しません。\n" +"\n" +"最後にスキャンして以後、別の Git プログラムがリポジトリを変更しています。マー" +"ジを開始する前に、再スキャンが必要です。\n" +"\n" +"自動的に再スキャンを開始します。\n" + +#: lib/merge.tcl:44 +#, tcl-format +msgid "" +"You are in the middle of a conflicted merge.\n" +"\n" +"File %s has merge conflicts.\n" +"\n" +"You must resolve them, stage the file, and commit to complete the current " +"merge. Only then can you begin another merge.\n" +msgstr "" +"衝突のあったマージの途中です。\n" +"\n" +"ファイル %s にはマージ中の衝突が残っています。\n" +"\n" +"このファイルの衝突を解決し、コミット予定に加えて、コミットすることでマージを" +"完了します。そうやって始めて、新たなマージを開始できるようになります。\n" + +#: lib/merge.tcl:54 +#, tcl-format +msgid "" +"You are in the middle of a change.\n" +"\n" +"File %s is modified.\n" +"\n" +"You should complete the current commit before starting a merge. Doing so " +"will help you abort a failed merge, should the need arise.\n" +msgstr "" +"変更の途中です。\n" +"\n" +"ファイル %s は変更中です。\n" +"\n" +"現在のコミットを完了してからマージを開始して下さい。そうする方がマージに失敗" +"したときの回復が楽です。\n" + +#: lib/merge.tcl:106 +#, tcl-format +msgid "%s of %s" +msgstr "%s の %s ブランチ" + +#: lib/merge.tcl:119 +#, tcl-format +msgid "Merging %s and %s" +msgstr "%s と %s をマージします" + +#: lib/merge.tcl:131 +msgid "Merge completed successfully." +msgstr "マージが完了しました" + +#: lib/merge.tcl:133 +msgid "Merge failed. Conflict resolution is required." +msgstr "マージが失敗しました。衝突の解決が必要です。" + +#: lib/merge.tcl:158 +#, tcl-format +msgid "Merge Into %s" +msgstr "%s にマージ" + +#: lib/merge.tcl:177 +msgid "Revision To Merge" +msgstr "マージするリビジョン" + +#: lib/merge.tcl:212 +msgid "" +"Cannot abort while amending.\n" +"\n" +"You must finish amending this commit.\n" +msgstr "" +"訂正中には中止できません。\n" +"\n" +"まず今のコミット訂正を完了させて下さい。\n" + +#: lib/merge.tcl:222 +msgid "" +"Abort merge?\n" +"\n" +"Aborting the current merge will cause *ALL* uncommitted changes to be lost.\n" +"\n" +"Continue with aborting the current merge?" +msgstr "" +"マージを中断しますか?\n" +"\n" +"現在のマージを中断すると、コミットしていない全ての変更が失われます。\n" +"\n" +"マージを中断してよろしいですか?" + +#: lib/merge.tcl:228 +msgid "" +"Reset changes?\n" +"\n" +"Resetting the changes will cause *ALL* uncommitted changes to be lost.\n" +"\n" +"Continue with resetting the current changes?" +msgstr "" +"変更点をリセットしますか?\n" +"\n" +"変更点をリセットすると、コミットしていない全ての変更が失われます。\n" +"\n" +"リセットしてよろしいですか?" + +#: lib/merge.tcl:239 +msgid "Aborting" +msgstr "中断しています" + +#: lib/merge.tcl:266 +msgid "Abort failed." +msgstr "中断に失敗しました。" + +#: lib/merge.tcl:268 +msgid "Abort completed. Ready." +msgstr "中断完了。" + +#: lib/option.tcl:77 +msgid "git-gui - a graphical user interface for Git." +msgstr "Git のグラフィカルUI git-gui" + +#: lib/option.tcl:164 +msgid "Restore Defaults" +msgstr "既定値に戻す" + +#: lib/option.tcl:168 +msgid "Save" +msgstr "保存" + +#: lib/option.tcl:178 +#, tcl-format +msgid "%s Repository" +msgstr "%s リポジトリ" + +#: lib/option.tcl:179 +msgid "Global (All Repositories)" +msgstr "大域(全てのリポジトリ)" + +#: lib/option.tcl:185 +msgid "User Name" +msgstr "ユーザ名" + +#: lib/option.tcl:186 +msgid "Email Address" +msgstr "電子メールアドレス" + +#: lib/option.tcl:188 +msgid "Summarize Merge Commits" +msgstr "マージコミットの要約" + +#: lib/option.tcl:189 +msgid "Merge Verbosity" +msgstr "マージの冗長度" + +#: lib/option.tcl:190 +msgid "Show Diffstat After Merge" +msgstr "マージ後に diffstat を表示" + +#: lib/option.tcl:192 +msgid "Trust File Modification Timestamps" +msgstr "ファイル変更時刻を信頼する" + +#: lib/option.tcl:193 +msgid "Prune Tracking Branches During Fetch" +msgstr "フェッチ中にトラッキングブランチを刈る" + +#: lib/option.tcl:194 +msgid "Match Tracking Branches" +msgstr "トラッキングブランチを合わせる" + +#: lib/option.tcl:195 +msgid "Number of Diff Context Lines" +msgstr "diff の文脈行数" + +#: lib/option.tcl:196 +msgid "New Branch Name Template" +msgstr "新しいブランチ名のテンプレート" + +#: lib/option.tcl:305 +msgid "Failed to completely save options:" +msgstr "完全にオプションを保存できません:" + +#: lib/remote_branch_delete.tcl:29 lib/remote_branch_delete.tcl:34 +msgid "Delete Remote Branch" +msgstr "リモート・ブランチを削除" + +#: lib/remote_branch_delete.tcl:47 +msgid "From Repository" +msgstr "元のリポジトリ" + +#: lib/remote_branch_delete.tcl:50 lib/transport.tcl:118 +msgid "Remote:" +msgstr "リモート:" + +#: lib/remote_branch_delete.tcl:66 lib/transport.tcl:133 +msgid "Arbitrary URL:" +msgstr "任意の URL:" + +#: lib/remote_branch_delete.tcl:84 +msgid "Branches" +msgstr "ブランチ" + +#: lib/remote_branch_delete.tcl:109 +msgid "Delete Only If" +msgstr "条件付で削除" + +#: lib/remote_branch_delete.tcl:111 +msgid "Merged Into:" +msgstr "マージ先:" + +#: lib/remote_branch_delete.tcl:119 +msgid "Always (Do not perform merge checks)" +msgstr "無条件(マージ検査をしない)" + +#: lib/remote_branch_delete.tcl:152 +msgid "A branch is required for 'Merged Into'." +msgstr "'マージ先' にはブランチが必要です。" + +#: lib/remote_branch_delete.tcl:189 +#, tcl-format +msgid "" +"One or more of the merge tests failed because you have not fetched the " +"necessary commits. Try fetching from %s first." +msgstr "" +"必要なコミットが不足しているために、マージ検査が失敗しました。まず %s から" +"フェッチして下さい。" + +#: lib/remote_branch_delete.tcl:207 +msgid "Please select one or more branches to delete." +msgstr "削除するブランチを選択して下さい。" + +#: lib/remote_branch_delete.tcl:216 +msgid "" +"Recovering deleted branches is difficult.\n" +"\n" +"Delete the selected branches?" +msgstr "" +"削除したブランチを回復するのは困難です。\n" +"\n" +"選択したブランチを削除して良いですか?" + +#: lib/remote_branch_delete.tcl:226 +#, tcl-format +msgid "Deleting branches from %s" +msgstr "%s からブランチを削除しています。" + +#: lib/remote_branch_delete.tcl:286 +msgid "No repository selected." +msgstr "リポジトリが選択されていません。" + +#: lib/remote_branch_delete.tcl:291 +#, tcl-format +msgid "Scanning %s..." +msgstr "%s をスキャンしています…" + +#: lib/remote.tcl:162 +#, tcl-format +msgid "Fetch from %s..." +msgstr "%s からフェッチ…" + +#: lib/remote.tcl:172 +#, tcl-format +msgid "Prune from %s..." +msgstr "%s から刈る…" + +#: lib/remote.tcl:206 +#, tcl-format +msgid "Push to %s..." +msgstr "%s へプッシュ…" + +#: lib/shortcut.tcl:26 lib/shortcut.tcl:74 +msgid "Cannot write script:" +msgstr "スクリプトが書けません:" + +#: lib/shortcut.tcl:149 +msgid "Cannot write icon:" +msgstr "アイコンが書けません:" + +#: lib/status_bar.tcl:58 +#, tcl-format +msgid "%s ... %i of %i %s (%2i%%)" +msgstr "%1$s ... %3$i %4$s 中の %$2i (%5$2i%%)" + +#: lib/transport.tcl:7 +#, tcl-format +msgid "Fetching new changes from %s" +msgstr "%s から新しい変更をフェッチしています" + +#: lib/transport.tcl:19 +#, tcl-format +msgid "Pruning tracking branches deleted from %s" +msgstr "%s から削除されたトラッキング・ブランチを刈っています" + +#: lib/transport.tcl:26 +#, tcl-format +msgid "Pushing changes to %s" +msgstr "%s へ変更をプッシュしています" + +#: lib/transport.tcl:68 +#, tcl-format +msgid "Pushing %s %s to %s" +msgstr "%3$s へ %1$s %2$s をプッシュしています" + +#: lib/transport.tcl:84 +msgid "Push Branches" +msgstr "ブランチをプッシュ" + +#: lib/transport.tcl:98 +msgid "Source Branches" +msgstr "元のブランチ" + +#: lib/transport.tcl:115 +msgid "Destination Repository" +msgstr "送り先リポジトリ" + +#: lib/transport.tcl:153 +msgid "Transfer Options" +msgstr "通信オプション" + +#: lib/transport.tcl:155 +msgid "Use thin pack (for slow network connections)" +msgstr "Thin Pack を使う(遅いネットワーク接続)" + +#: lib/transport.tcl:159 +msgid "Include tags" +msgstr "タグを含める" From 4fe7626488872e1226490500e70b7e2a4c262906 Mon Sep 17 00:00:00 2001 From: Paolo Ciarrocchi Date: Sun, 22 Jul 2007 12:51:13 +0200 Subject: [PATCH 0024/1490] Italian translation of git-gui [jes: includes patches from Michele Ballabio] Signed-off-by: Paolo Ciarrocchi Signed-off-by: Johannes Schindelin --- po/it.po | 1393 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1393 insertions(+) create mode 100644 po/it.po diff --git a/po/it.po b/po/it.po new file mode 100644 index 0000000000..17a5c21882 --- /dev/null +++ b/po/it.po @@ -0,0 +1,1393 @@ +# Translation of git-gui to Italian +# Copyright (C) 2007 Shawn Pearce +# This file is distributed under the same license as the git-gui package. +# Paolo Ciarrocchi , 2007 +# Michele Ballabio , 2007. +# +# +msgid "" +msgstr "" +"Project-Id-Version: git-gui\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2007-08-11 17:28+0200\n" +"PO-Revision-Date: 2007-08-09 00:27+0200\n" +"Last-Translator: Paolo Ciarrocchi \n" +"Language-Team: Italian \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit" + +#: git-gui.sh:531 +msgid "Cannot find git in PATH." +msgstr "Impossibile trovare git nel PATH" + +#: git-gui.sh:550 +msgid "Cannot parse Git version string:" +msgstr "Impossibile determinare la versione di Git:" + +#: git-gui.sh:567 +#, tcl-format +msgid "" +"Git version cannot be determined.\n" +"\n" +"%s claims it is version '%s'.\n" +"\n" +"%s requires at least Git 1.5.0 or later.\n" +"\n" +"Assume '%s' is version 1.5.0?\n" +msgstr "" +"La versione di GIT non può essere determinata.\n" +"\n" +"%s sostiene che la versione è '%s'.\n" +"\n" +"%s richiede almeno Git 1.5.0 o superiore.\n" +"\n" +"Assumere che '%s' sia alla versione 1.5.0?\n" + +#: git-gui.sh:689 +msgid "Cannot find the git directory:" +msgstr "Non posso trovare la directory di git:" + +#: git-gui.sh:697 +msgid "Git directory not found:" +msgstr "Non trovo la directory di git: " + +#: git-gui.sh:703 +msgid "Cannot use funny .git directory:" +msgstr "Impossibile usare una .git directory strana:" + +#: git-gui.sh:708 +msgid "No working directory" +msgstr "Nessuna directory di lavoro" + +#: git-gui.sh:854 +msgid "Refreshing file status..." +msgstr "Controllo dello stato dei file in corso..." + +#: git-gui.sh:891 +msgid "Scanning for modified files ..." +msgstr "Ricerca di file modificati in corso..." + +#: git-gui.sh:1057 lib/browser.tcl:247 +msgid "Ready." +msgstr "Pronto." + +#: git-gui.sh:1322 +msgid "Unmodified" +msgstr "Non modificato" + +#: git-gui.sh:1324 +msgid "Modified, not staged" +msgstr "Modificato, non pronto per il commit" + +#: git-gui.sh:1325 git-gui.sh:1330 +msgid "Staged for commit" +msgstr "Pronto per il commit" + +#: git-gui.sh:1326 git-gui.sh:1331 +msgid "Portions staged for commit" +msgstr "Parti pronte per il commit" + +#: git-gui.sh:1327 git-gui.sh:1332 +msgid "Staged for commit, missing" +msgstr "Pronto per il commit, mancante" + +#: git-gui.sh:1329 +msgid "Untracked, not staged" +msgstr "Non tracciato, non pronto per il commit" + +#: git-gui.sh:1334 +msgid "Missing" +msgstr "Mancante" + +#: git-gui.sh:1335 +msgid "Staged for removal" +msgstr "Pronto per la rimozione" + +#: git-gui.sh:1336 +msgid "Staged for removal, still present" +msgstr "Pronto alla rimozione, ancora presente" + +#: git-gui.sh:1338 git-gui.sh:1339 git-gui.sh:1340 git-gui.sh:1341 +msgid "Requires merge resolution" +msgstr "Richiede risoluzione dei conflitti" + +#: git-gui.sh:1383 +msgid "Starting gitk... please wait..." +msgstr "Avvio di gitk... attendere..." + +#: git-gui.sh:1392 +#, tcl-format +msgid "" +"Unable to start gitk:\n" +"\n" +"%s does not exist" +msgstr "" +"Impossibile avviare gitk:\n" +"\n" +"%s non esiste" + +#: git-gui.sh:1609 +#, tcl-format +msgid "Invalid font specified in gui.%s:" +msgstr "Caratteri non validi specificati nella gui.%s:" + +#: git-gui.sh:1634 +msgid "Main Font" +msgstr "Caratteri principali" + +#: git-gui.sh:1635 +msgid "Diff/Console Font" +msgstr "Caratteri per confronti e terminale" + +#: git-gui.sh:1649 +msgid "Repository" +msgstr "Archivio" + +#: git-gui.sh:1650 +msgid "Edit" +msgstr "Modifica" + +#: git-gui.sh:1652 +msgid "Branch" +msgstr "Ramo" + +#: git-gui.sh:1655 git-gui.sh:1842 git-gui.sh:2152 +msgid "Commit" +msgstr "Commit" + +#: git-gui.sh:1658 lib/merge.tcl:121 lib/merge.tcl:150 lib/merge.tcl:168 +msgid "Merge" +msgstr "Fusione (Merge)" + +#: git-gui.sh:1659 +msgid "Fetch" +msgstr "Preleva (Fetch)" + +#: git-gui.sh:1660 git-gui.sh:2158 lib/transport.tcl:88 lib/transport.tcl:172 +msgid "Push" +msgstr "Propaga (Push)" + +#: git-gui.sh:1669 +msgid "Browse Current Branch's Files" +msgstr "Esplora i file del ramo corrente" + +#: git-gui.sh:1673 +msgid "Browse Branch Files..." +msgstr "Esplora i file del ramo..." + +#: git-gui.sh:1678 +msgid "Visualize Current Branch's History" +msgstr "Visualizza la cronologia del ramo corrente" + +#: git-gui.sh:1682 +msgid "Visualize All Branch History" +msgstr "Visualizza la cronologia di tutti i rami" + +#: git-gui.sh:1689 +#, tcl-format +msgid "Browse %s's Files" +msgstr "Esplora i file di %s" + +#: git-gui.sh:1691 +#, tcl-format +msgid "Visualize %s's History" +msgstr "Visualizza la cronologia di %s" + +#: git-gui.sh:1696 lib/database.tcl:27 lib/database.tcl:67 +msgid "Database Statistics" +msgstr "Statistiche del database" + +#: git-gui.sh:1699 lib/database.tcl:34 +msgid "Compress Database" +msgstr "Comprimi il database" + +#: git-gui.sh:1702 +msgid "Verify Database" +msgstr "Verifica il database" + +#: git-gui.sh:1709 git-gui.sh:1713 git-gui.sh:1717 lib/shortcut.tcl:9 +#: lib/shortcut.tcl:45 lib/shortcut.tcl:84 +msgid "Create Desktop Icon" +msgstr "Crea icona desktop" + +#: git-gui.sh:1722 +msgid "Quit" +msgstr "Esci" + +#: git-gui.sh:1729 +msgid "Undo" +msgstr "Annulla" + +#: git-gui.sh:1732 +msgid "Redo" +msgstr "Ripeti" + +#: git-gui.sh:1736 git-gui.sh:2222 +msgid "Cut" +msgstr "Taglia" + +#: git-gui.sh:1739 git-gui.sh:2225 git-gui.sh:2296 git-gui.sh:2368 +#: lib/console.tcl:69 +msgid "Copy" +msgstr "Copia" + +#: git-gui.sh:1742 git-gui.sh:2228 +msgid "Paste" +msgstr "Incolla" + +#: git-gui.sh:1745 git-gui.sh:2231 lib/branch_delete.tcl:26 +#: lib/remote_branch_delete.tcl:38 +msgid "Delete" +msgstr "Elimina" + +#: git-gui.sh:1749 git-gui.sh:2235 git-gui.sh:2372 lib/console.tcl:71 +msgid "Select All" +msgstr "Seleziona tutto" + +#: git-gui.sh:1758 +msgid "Create..." +msgstr "Crea..." + +#: git-gui.sh:1764 +msgid "Checkout..." +msgstr "Checkout..." + +#: git-gui.sh:1770 +msgid "Rename..." +msgstr "Rinomina" + +#: git-gui.sh:1775 git-gui.sh:1873 +msgid "Delete..." +msgstr "Elimina..." + +#: git-gui.sh:1780 +msgid "Reset..." +msgstr "Ripristina..." + +#: git-gui.sh:1792 git-gui.sh:2169 +msgid "New Commit" +msgstr "Nuovo commit" + +#: git-gui.sh:1800 git-gui.sh:2176 +msgid "Amend Last Commit" +msgstr "Correggi l'ultimo commit" + +#: git-gui.sh:1809 git-gui.sh:2136 lib/remote_branch_delete.tcl:99 +msgid "Rescan" +msgstr "Analizza nuovamente" + +#: git-gui.sh:1815 +msgid "Stage To Commit" +msgstr "Prepara per il commit" + +#: git-gui.sh:1820 +msgid "Stage Changed Files To Commit" +msgstr "Prepara per il commit i file modificati" + +#: git-gui.sh:1826 +msgid "Unstage From Commit" +msgstr "Non pronto per il commit" + +#: git-gui.sh:1831 lib/index.tcl:376 +msgid "Revert Changes" +msgstr "Annulla modifiche" + +#: git-gui.sh:1838 git-gui.sh:2148 git-gui.sh:2246 +msgid "Sign Off" +msgstr "Sign Off" + +#: git-gui.sh:1853 +msgid "Local Merge..." +msgstr "Fusione locale" + +#: git-gui.sh:1858 +msgid "Abort Merge..." +msgstr "Interrompi fusione" + +#: git-gui.sh:1870 +msgid "Push..." +msgstr "Propaga..." + +#: git-gui.sh:1880 +msgid "Apple" +msgstr "Apple" + +#: git-gui.sh:1883 git-gui.sh:1901 lib/option.tcl:65 +#, tcl-format +msgid "About %s" +msgstr "Informazioni su %s" + +#: git-gui.sh:1885 git-gui.sh:1891 git-gui.sh:2414 +msgid "Options..." +msgstr "Opzioni..." + +#: git-gui.sh:1897 +msgid "Help" +msgstr "Aiuto" + +#: git-gui.sh:1938 +msgid "Online Documentation" +msgstr "Documentazione sul web" + +#: git-gui.sh:2054 +msgid "Current Branch:" +msgstr "Ramo attuale:" + +#: git-gui.sh:2075 +msgid "Staged Changes (Will Be Committed)" +msgstr "Modifiche preparate (ne verrà effettuato il commit)" + +#: git-gui.sh:2095 +msgid "Unstaged Changes (Will Not Be Committed)" +msgstr "Modifiche non preparate (non ne verrà effettuato il commit)" + +#: git-gui.sh:2142 +msgid "Stage Changed" +msgstr "Prepara modificati" + +#: git-gui.sh:2188 +msgid "Initial Commit Message:" +msgstr "Messaggio di commit iniziale:" + +#: git-gui.sh:2189 +msgid "Amended Commit Message:" +msgstr "Messaggio di commit corretto:" + +#: git-gui.sh:2190 +msgid "Amended Initial Commit Message:" +msgstr "Messaggio iniziale di commit corretto:" + +#: git-gui.sh:2191 +msgid "Amended Merge Commit Message:" +msgstr "Messaggio di fusione corretto:" + +#: git-gui.sh:2192 +msgid "Merge Commit Message:" +msgstr "Messaggio di fusione:" + +#: git-gui.sh:2193 +msgid "Commit Message:" +msgstr "Messaggio di commit:" + +#: git-gui.sh:2238 git-gui.sh:2376 lib/console.tcl:73 +msgid "Copy All" +msgstr "Copia tutto" + +#: git-gui.sh:2262 lib/blame.tcl:104 +msgid "File:" +msgstr "File:" + +#: git-gui.sh:2364 +msgid "Refresh" +msgstr "Rinfresca" + +#: git-gui.sh:2385 +msgid "Apply/Reverse Hunk" +msgstr "Applica/Inverti sezione" + +#: git-gui.sh:2391 +msgid "Decrease Font Size" +msgstr "Diminuisci dimensione caratteri" + +#: git-gui.sh:2395 +msgid "Increase Font Size" +msgstr "Aumenta dimensione caratteri" + +#: git-gui.sh:2400 +msgid "Show Less Context" +msgstr "Mostra meno contesto" + +#: git-gui.sh:2407 +msgid "Show More Context" +msgstr "Mostra più contesto" + +#: git-gui.sh:2422 +msgid "Unstage Hunk From Commit" +msgstr "Sezione non pronta per il commit" + +#: git-gui.sh:2426 git-gui.sh:2430 +msgid "Stage Hunk For Commit" +msgstr "Prepara sezione per il commit" + +#: git-gui.sh:2440 +msgid "Initializing..." +msgstr "Inizializzazione..." + +#: lib/blame.tcl:77 +msgid "File Viewer" +msgstr "Mostra file" + +#: lib/blame.tcl:81 +msgid "Commit:" +msgstr "Commit:" + +#: lib/blame.tcl:249 +msgid "Copy Commit" +msgstr "Copia commit" + +#: lib/blame.tcl:369 +#, tcl-format +msgid "Reading %s..." +msgstr "Lettura di %s..." + +#: lib/branch_checkout.tcl:14 lib/branch_checkout.tcl:19 +msgid "Checkout Branch" +msgstr "Checkout ramo" + +#: lib/branch_checkout.tcl:23 +msgid "Checkout" +msgstr "Checkout" + +#: lib/branch_checkout.tcl:27 lib/branch_create.tcl:35 +#: lib/branch_delete.tcl:32 lib/branch_rename.tcl:30 lib/browser.tcl:283 +#: lib/checkout_op.tcl:522 lib/merge.tcl:172 lib/option.tcl:172 +#: lib/remote_branch_delete.tcl:42 lib/transport.tcl:92 +msgid "Cancel" +msgstr "Annulla" + +#: lib/branch_checkout.tcl:32 lib/browser.tcl:288 +msgid "Revision" +msgstr "Revisione" + +#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:159 +#: lib/option.tcl:274 +msgid "Options" +msgstr "Opzioni" + +#: lib/branch_checkout.tcl:39 lib/branch_create.tcl:92 +msgid "Fetch Tracking Branch" +msgstr "Preleva ramo in 'tracking'" + +#: lib/branch_checkout.tcl:44 +msgid "Detach From Local Branch" +msgstr "Stacca da ramo locale" + +#: lib/branch_create.tcl:22 +msgid "Create Branch" +msgstr "Crea ramo" + +#: lib/branch_create.tcl:27 +msgid "Create New Branch" +msgstr "Crea nuovo ramo" + +#: lib/branch_create.tcl:31 +msgid "Create" +msgstr "Crea" + +#: lib/branch_create.tcl:40 +msgid "Branch Name" +msgstr "Nome del ramo" + +#: lib/branch_create.tcl:43 +msgid "Name:" +msgstr "Nome:" + +#: lib/branch_create.tcl:58 +msgid "Match Tracking Branch Name" +msgstr "Appaia nome del ramo in 'tracking'" + +#: lib/branch_create.tcl:66 +msgid "Starting Revision" +msgstr "Revisione iniziale" + +#: lib/branch_create.tcl:72 +msgid "Update Existing Branch:" +msgstr "Aggiorna ramo esistente:" + +#: lib/branch_create.tcl:75 +msgid "No" +msgstr "No" + +#: lib/branch_create.tcl:80 +msgid "Fast Forward Only" +msgstr "Solo fast forward" + +#: lib/branch_create.tcl:85 lib/checkout_op.tcl:514 +msgid "Reset" +msgstr "Ripristina" + +#: lib/branch_create.tcl:97 +msgid "Checkout After Creation" +msgstr "Checkout dopo la creazione" + +#: lib/branch_create.tcl:131 +msgid "Please select a tracking branch." +msgstr "Scegliere un ramo in 'tracking'" + +#: lib/branch_create.tcl:140 +#, tcl-format +msgid "Tracking branch %s is not a branch in the remote repository." +msgstr "Il ramo in 'tracking' %s non è un ramo nell'archivio remoto." + +#: lib/branch_create.tcl:153 lib/branch_rename.tcl:86 +msgid "Please supply a branch name." +msgstr "Inserire un nome per il ramo." + +#: lib/branch_create.tcl:164 lib/branch_rename.tcl:106 +#, tcl-format +msgid "'%s' is not an acceptable branch name." +msgstr "'%s' non è utilizzabile come nome di ramo." + +#: lib/branch_delete.tcl:15 +msgid "Delete Branch" +msgstr "Elimina ramo" + +#: lib/branch_delete.tcl:20 +msgid "Delete Local Branch" +msgstr "Elimina ramo locale" + +#: lib/branch_delete.tcl:37 +msgid "Local Branches" +msgstr "Rami locali" + +#: lib/branch_delete.tcl:52 +msgid "Delete Only If Merged Into" +msgstr "Cancella solo se fuso con un altro ramo" + +#: lib/branch_delete.tcl:54 +msgid "Always (Do not perform merge test.)" +msgstr "Sempre (Non effettuare controlli durante la fusione)." + +#: lib/branch_delete.tcl:103 +#, tcl-format +msgid "The following branches are not completely merged into %s:" +msgstr "I rami seguenti non sono stati fusi completamente in %s:" + +#: lib/branch_delete.tcl:115 +msgid "" +"Recovering deleted branches is difficult. \n" +"\n" +" Delete the selected branches?" +msgstr "" +"Prelevare rami cancellati può essere complicato. \n" +"\n" +" Eliminare i rami selezionati?" + +#: lib/branch_delete.tcl:141 +#, tcl-format +msgid "" +"Failed to delete branches:\n" +"%s" +msgstr "" +"Cancellazione rami fallita:\n" +"%s" + +#: lib/branch_rename.tcl:14 lib/branch_rename.tcl:22 +msgid "Rename Branch" +msgstr "Rinomina ramo" + +#: lib/branch_rename.tcl:26 +msgid "Rename" +msgstr "Rinomina" + +#: lib/branch_rename.tcl:36 +msgid "Branch:" +msgstr "Ramo:" + +#: lib/branch_rename.tcl:39 +msgid "New Name:" +msgstr "Nuovo Nome:" + +#: lib/branch_rename.tcl:75 +msgid "Please select a branch to rename." +msgstr "Scegliere un ramo da rinominare." + +#: lib/branch_rename.tcl:96 lib/checkout_op.tcl:179 +#, tcl-format +msgid "Branch '%s' already exists." +msgstr "Il ramo '%s' esiste già" + +#: lib/branch_rename.tcl:117 +#, tcl-format +msgid "Failed to rename '%s'." +msgstr "Cambiamento nome '%s' fallito." + +#: lib/browser.tcl:17 +msgid "Starting..." +msgstr "Avvio in corso..." + +#: lib/browser.tcl:26 +msgid "File Browser" +msgstr "File browser" + +#: lib/browser.tcl:127 lib/browser.tcl:144 +#, tcl-format +msgid "Loading %s..." +msgstr "Caricamento %s..." + +#: lib/browser.tcl:188 +msgid "[Up To Parent]" +msgstr "[Directory superiore]" + +#: lib/browser.tcl:268 lib/browser.tcl:274 +msgid "Browse Branch Files" +msgstr "Esplora i file del ramo" + +#: lib/browser.tcl:279 +msgid "Browse" +msgstr "Sfoglia" + +#: lib/checkout_op.tcl:79 +#, tcl-format +msgid "Fetching %s from %s" +msgstr "Recupero %s da %s" + +#: lib/checkout_op.tcl:140 lib/console.tcl:81 lib/database.tcl:31 +msgid "Close" +msgstr "Chiudi" + +#: lib/checkout_op.tcl:169 +#, tcl-format +msgid "Branch '%s' does not exist." +msgstr "Il ramo '%s' non esiste." + +#: lib/checkout_op.tcl:206 +#, tcl-format +msgid "" +"Branch '%s' already exists.\n" +"\n" +"It cannot fast-forward to %s.\n" +"A merge is required." +msgstr "Il ramo '%s' esiste già.\n" +"\n" +"Non può effettuare un 'fast-forward' a %s.\n" +"E' necessaria una fusione." + +#: lib/checkout_op.tcl:220 +#, tcl-format +msgid "Merge strategy '%s' not supported." +msgstr "La strategia di fusione '%s' non è supportata." + +#: lib/checkout_op.tcl:239 +#, tcl-format +msgid "Failed to update '%s'." +msgstr "Aggiornamento di '%s' fallito." + +#: lib/checkout_op.tcl:251 +msgid "Staging area (index) is already locked." +msgstr "L'area di preparazione per il commit (indice) è già bloccata." + +#: lib/checkout_op.tcl:266 +msgid "" +"Last scanned state does not match repository state.\n" +"\n" +"Another Git program has modified this repository since the last scan. A " +"rescan must be performed before the current branch can be changed.\n" +"\n" +"The rescan will be automatically started now.\n" +msgstr "" +"L'ultimo stato analizzato non corrisponde allo stato del repository.\n" +"\n" +"Un altro programma Git ha modificato questo repository dall'ultima analisi. " +"Bisogna effettuare una nuova analisi prima di poter cambiare il ramo " +"corrente.\n" +"\n" +"La nuova analisi comincerà ora.\n" + +#: lib/checkout_op.tcl:353 +#, tcl-format +msgid "Aborted checkout of '%s' (file level merging is required)." +msgstr "Checkout di '%s' fallito (richiesta una fusione a livello file)." + +#: lib/checkout_op.tcl:354 +msgid "File level merge required." +msgstr "E' richiesta una fusione a livello file." + +#: lib/checkout_op.tcl:358 +#, tcl-format +msgid "Staying on branch '%s'." +msgstr "Si rimarrà sul ramo '%s'." + +#: lib/checkout_op.tcl:429 +msgid "" +"You are no longer on a local branch.\n" +"\n" +"If you wanted to be on a branch, create one now starting from 'This Detached " +"Checkout'." +msgstr "" +"Non si è più su un ramo locale\n" +"\n" +"Se si vuole rimanere su un ramo, crearne uno ora a partire da 'Questo checkout " +"staccato'." + +#: lib/checkout_op.tcl:478 +#, tcl-format +msgid "Resetting '%s' to '%s' will lose the following commits:" +msgstr "Ripristinare '%s' a '%s' comporterà la perdita dei seguenti commit:" + +#: lib/checkout_op.tcl:500 +msgid "Recovering lost commits may not be easy." +msgstr "Prelevare i commit perduti potrebbe non essere semplice." + +#: lib/checkout_op.tcl:505 +#, tcl-format +msgid "Reset '%s'?" +msgstr "Ripristinare '%s'?" + +#: lib/checkout_op.tcl:510 lib/merge.tcl:164 +msgid "Visualize" +msgstr "Visualizza" + +#: lib/checkout_op.tcl:578 +#, tcl-format +msgid "" +"Failed to set current branch.\n" +"\n" +"This working directory is only partially switched. We successfully updated " +"your files, but failed to update an internal Git file.\n" +"\n" +"This should not have occurred. %s will now close and give up." +msgstr "" +"Preparazione ramo corrente fallita.\n" +"\n" +"Questa directory di lavoro è stata convertita solo parzialmente. I file " +"sono stati aggiornati correttamente, ma l'aggiornamento di un file di Git ha " +"prodotto degli errori.\n" +"\n" +"Questo non sarebbe dovuto succedere. %s ora terminerà senza altre azioni." + +#: lib/choose_rev.tcl:53 +msgid "This Detached Checkout" +msgstr "Questo checkout staccato" + +#: lib/choose_rev.tcl:60 +msgid "Revision Expression:" +msgstr "Espressione di revisione:" + +#: lib/choose_rev.tcl:74 +msgid "Local Branch" +msgstr "Ramo locale" + +#: lib/choose_rev.tcl:79 +msgid "Tracking Branch" +msgstr "Ramo in 'tracking'" + +#: lib/choose_rev.tcl:84 +msgid "Tag" +msgstr "Etichetta" + +#: lib/choose_rev.tcl:317 +#, tcl-format +msgid "Invalid revision: %s" +msgstr "Revisione non valida: %s" + +#: lib/choose_rev.tcl:338 +msgid "No revision selected." +msgstr "Nessuna revisione selezionata." + +#: lib/choose_rev.tcl:346 +msgid "Revision expression is empty." +msgstr "L'espressione di revisione è vuota." + +#: lib/commit.tcl:9 +msgid "" +"There is nothing to amend.\n" +"\n" +"You are about to create the initial commit. There is no commit before this " +"to amend.\n" +msgstr "" +"Non c'è niente da correggere.\n" +"\n" +"Stai per creare il commit iniziale. Non esiste un commit precedente da " +"correggere.\n" + +#: lib/commit.tcl:18 +msgid "" +"Cannot amend while merging.\n" +"\n" +"You are currently in the middle of a merge that has not been fully " +"completed. You cannot amend the prior commit unless you first abort the " +"current merge activity.\n" +msgstr "" +"Non è possibile effettuare una correzione durante una fusione.\n" +"\n" +"In questo momento si sta effettuando una fusione che non è stata del tutto " +"completata. Non puoi correggere il commit precedente a meno che prima tu non " +"interrompa l'operazione di fusione in corso.\n" + +#: lib/commit.tcl:49 +msgid "Error loading commit data for amend:" +msgstr "Errore durante il caricamento dei dati da correggere:" + +#: lib/commit.tcl:76 +msgid "Unable to obtain your identity:" +msgstr "Impossibile ottenere la tua identità:" + +#: lib/commit.tcl:81 +msgid "Invalid GIT_COMMITTER_IDENT:" +msgstr "GIT_COMMITTER_IDENT non valida:" + +#: lib/commit.tcl:133 +msgid "" +"Last scanned state does not match repository state.\n" +"\n" +"Another Git program has modified this repository since the last scan. A " +"rescan must be performed before another commit can be created.\n" +"\n" +"The rescan will be automatically started now.\n" +msgstr "" +"L'ultimo stato analizzato non corrisponde allo stato del repository.\n" +"\n" +"Un altro programma Git ha modificato questo repository dall'ultima analisi. " +"Bisogna effettuare una nuova analisi prima di poter creare un nuovo commit.\n" +"\n" +"La nuova analisi comincerà ora.\n" + +#: lib/commit.tcl:154 +#, tcl-format +msgid "" +"Unmerged files cannot be committed.\n" +"\n" +"File %s has merge conflicts. You must resolve them and stage the file " +"before committing.\n" +msgstr "" +"Non è possibile effettuare il commit di file non sottoposti a fusione.\n" +"\n" +"Il file %s presenta dei conflitti. Devi risolverli e preparare il file " +"per il commit prima di effettuare questa azione.\n" + +#: lib/commit.tcl:162 +#, tcl-format +msgid "" +"Unknown file state %s detected.\n" +"\n" +"File %s cannot be committed by this program.\n" +msgstr "" +"Stato di file %s sconosciuto.\n" +"\n" +"Non si può effettuare il commit del file %s con questo programma.\n" + +#: lib/commit.tcl:170 +msgid "" +"No changes to commit.\n" +"\n" +"You must stage at least 1 file before you can commit.\n" +msgstr "" +"Nessuna modifica per la quale effettuare il commit.\n" +"\n" +"Devi preparare per il commit almeno 1 file prima di effettuare questa operazione.\n" + +#: lib/commit.tcl:183 +msgid "" +"Please supply a commit message.\n" +"\n" +"A good commit message has the following format:\n" +"\n" +"- First line: Describe in one sentance what you did.\n" +"- Second line: Blank\n" +"- Remaining lines: Describe why this change is good.\n" +msgstr "" +"Bisogna fornire un messaggio di commit.\n" +"\n" +"Un buon messaggio di commit ha il seguente formato:\n" +"\n" +"- Prima linea: descrivi in una frase ciò che hai fatto.\n" +"- Seconda linea: vuota.\n" +"- Terza linea: spiga a cosa serve la tua modifica.\n" + +#: lib/commit.tcl:257 +msgid "write-tree failed:" +msgstr "write-tree fallito:" + +#: lib/commit.tcl:279 +msgid "" +"No changes to commit.\n" +"\n" +"No files were modified by this commit and it was not a merge commit.\n" +"\n" +"A rescan will be automatically started now.\n" +msgstr "" +"Nessuna modifica pronta per il commit.\n" +"\n" +"Questo commit non modifica alcun file e non effettua alcuna fusione.\n" +"\n" +"Si procederà subito ad una nuova analisi.\n" + +#: lib/commit.tcl:286 +msgid "No changes to commit." +msgstr "Nessuna modifica pronta per il commit." + +#: lib/commit.tcl:317 +msgid "commit-tree failed:" +msgstr "commit-tree fallito:" + +#: lib/commit.tcl:339 +msgid "update-ref failed:" +msgstr "update-ref fallito:" + +#: lib/commit.tcl:430 +#, tcl-format +msgid "Created commit %s: %s" +msgstr "Creato commit %s: %s" + +#: lib/console.tcl:55 +msgid "Working... please wait..." +msgstr "Elaborazione in corso... attendere..." + +#: lib/console.tcl:184 +msgid "Success" +msgstr "Successo" + +#: lib/console.tcl:194 +msgid "Error: Command Failed" +msgstr "Errore: comando fallito" + +#: lib/database.tcl:43 +msgid "Number of loose objects" +msgstr "Numero di oggetti slegati" + +#: lib/database.tcl:44 +msgid "Disk space used by loose objects" +msgstr "Spazio su disco utilizzato da oggetti slegati" + +#: lib/database.tcl:45 +msgid "Number of packed objects" +msgstr "Numero di oggetti impacchettati" + +#: lib/database.tcl:46 +msgid "Number of packs" +msgstr "Numero di pacchetti" + +#: lib/database.tcl:47 +msgid "Disk space used by packed objects" +msgstr "Spazio su disco utilizzato da oggetti impacchettati" + +#: lib/database.tcl:48 +msgid "Packed objects waiting for pruning" +msgstr "Oggetti impacchettati che attendono la potatura" + +#: lib/database.tcl:49 +msgid "Garbage files" +msgstr "File inutili" + +#: lib/database.tcl:72 +msgid "Compressing the object database" +msgstr "Compressione del database in corso" + +#: lib/database.tcl:83 +msgid "Verifying the object database with fsck-objects" +msgstr "Verifica dell'archivio con fsck-objects in corso" + +#: lib/diff.tcl:42 +#, tcl-format +msgid "" +"No differences detected.\n" +"\n" +"%s has no changes.\n" +"\n" +"The modification date of this file was updated by another application, but " +"the content within the file was not changed.\n" +"\n" +"A rescan will be automatically started to find other files which may have " +"the same state." +msgstr "" +"Non sono state trovate differenze.\n" +"\n" +"%s non ha modifiche.\n" +"\n" +"La data di modifica di questo file è stata cambiata da un'altra " +"applicazione, ma il contenuto del file è rimasto invariato.\n" +"\n" +"Si procederà automaticamente ad una nuova analisi per trovare altri file che " +"potrebbero avere lo stesso stato." + +#: lib/diff.tcl:97 +msgid "Error loading file:" +msgstr "Errore nel caricamento del file:" + +#: lib/diff.tcl:162 +msgid "Error loading diff:" +msgstr "Errore nel caricamento delle differenze:" + +#: lib/diff.tcl:278 +msgid "Failed to unstage selected hunk." +msgstr "La sezione scelta è ancora pronta per il commit." + +#: lib/diff.tcl:285 +msgid "Failed to stage selected hunk." +msgstr "La sezione scelta non è ancora pronta per il commit." + +#: lib/error.tcl:12 lib/error.tcl:102 +msgid "error" +msgstr "errore" + +#: lib/error.tcl:28 +msgid "warning" +msgstr "avviso" + +#: lib/error.tcl:81 +msgid "You must correct the above errors before committing." +msgstr "Bisogna correggere gli errori suddetti prima di effettuare un commit." + +#: lib/index.tcl:364 +#, tcl-format +msgid "Revert changes in file %s?" +msgstr "Annullare le modifiche nel file %s?" + +#: lib/index.tcl:366 +#, tcl-format +msgid "Revert changes in these %i files?" +msgstr "Annullare le modifiche in questi %i file?" + +#: lib/index.tcl:372 +msgid "Any unstaged changes will be permanently lost by the revert." +msgstr "Tutte le modifiche non preparate per il commit saranno perse per sempre." + +#: lib/index.tcl:375 +msgid "Do Nothing" +msgstr "Non fare niente" + +#: lib/merge.tcl:13 +msgid "" +"Cannot merge while amending.\n" +"\n" +"You must finish amending this commit before starting any type of merge.\n" +msgstr "" +"Non posso effettuare fusioni durante una correzione.\n" +"\n" +"Bisogna finire di correggere questo commit prima di iniziare una qualunque " +"fusione.\n" + +#: lib/merge.tcl:27 +msgid "" +"Last scanned state does not match repository state.\n" +"\n" +"Another Git program has modified this repository since the last scan. A " +"rescan must be performed before a merge can be performed.\n" +"\n" +"The rescan will be automatically started now.\n" +msgstr "" +"L'ultimo stato analizzato non corrisponde allo stato del repository.\n" +"\n" +"Un altro programma Git ha modificato questo repository dall'ultima analisi." +"Bisogna effettuare una nuova analisi prima di poter effettuare una fusione.\n" +"\n" +"La nuova analisi comincerà ora.\n" + +#: lib/merge.tcl:44 +#, tcl-format +msgid "" +"You are in the middle of a conflicted merge.\n" +"\n" +"File %s has merge conflicts.\n" +"\n" +"You must resolve them, stage the file, and commit to complete the current " +"merge. Only then can you begin another merge.\n" +msgstr "" +"Sei nel mezzo di una fusione con conflitti.\n" +"\n" +"Il file %s ha dei conflitti.\n" +"\n" +"Bisogna risolvere i conflitti, preparare il file per il commit ed infine " +"effettuare un commit " +"per completare la fusione corrente. Solo a questo punto potrai iniziare " +"un'altra fusione.\n" + +#: lib/merge.tcl:54 +#, tcl-format +msgid "" +"You are in the middle of a change.\n" +"\n" +"File %s is modified.\n" +"\n" +"You should complete the current commit before starting a merge. Doing so " +"will help you abort a failed merge, should the need arise.\n" +msgstr "" +"Sei nel mezzo di una modifica.\n" +"\n" +"Il file %s è stato modificato.\n" +"\n" +"Bisogna completare il commit corrente prima di iniziare una fusione. In " +"questo modo sarà più facile interrompere una fusione non riuscita, nel caso " +"ce ne fosse bisogno.\n" + +#: lib/merge.tcl:106 +#, tcl-format +msgid "%s of %s" +msgstr "%s di %s" + +#: lib/merge.tcl:119 +#, tcl-format +msgid "Merging %s and %s" +msgstr "Fusione di %s e %s in corso" + +#: lib/merge.tcl:131 +msgid "Merge completed successfully." +msgstr "Fusione completata con successo." + +#: lib/merge.tcl:133 +msgid "Merge failed. Conflict resolution is required." +msgstr "Fusione fallita. Bisogna risolvere i conflitti." + +#: lib/merge.tcl:158 +#, tcl-format +msgid "Merge Into %s" +msgstr "Fusione in %s" + +#: lib/merge.tcl:177 +msgid "Revision To Merge" +msgstr "Revisione da fondere" + +#: lib/merge.tcl:212 +msgid "" +"Cannot abort while amending.\n" +"\n" +"You must finish amending this commit.\n" +msgstr "" +"Interruzione impossibile durante una correzione.\n" +"\n" +"Bisogna finire di correggere questo commit.\n" + +#: lib/merge.tcl:222 +msgid "" +"Abort merge?\n" +"\n" +"Aborting the current merge will cause *ALL* uncommitted changes to be lost.\n" +"\n" +"Continue with aborting the current merge?" +msgstr "" +"Interrompere fusione?\n" +"\n" +"L'interruzione della fusione corrente causerà la perdita di *TUTTE* le " +"modifiche non ancora presenti nei commit.\n" +"\n" +"Continuare con l'interruzione della fusione corrente?" + +#: lib/merge.tcl:228 +msgid "" +"Reset changes?\n" +"\n" +"Resetting the changes will cause *ALL* uncommitted changes to be lost.\n" +"\n" +"Continue with resetting the current changes?" +msgstr "" +"Annullare le modifiche?\n" +"\n" +"L'annullamento delle modifiche causerà la perdita di *TUTTE* le " +"modifiche non ancora presenti nei commit.\n" +"\n" +"Continuare con l'annullamento delle modifiche correnti?" + +#: lib/merge.tcl:239 +msgid "Aborting" +msgstr "Interruzione in corso" + +#: lib/merge.tcl:266 +msgid "Abort failed." +msgstr "Interruzione fallita." + +#: lib/merge.tcl:268 +msgid "Abort completed. Ready." +msgstr "Interruzione completata. Pronto." + +#: lib/option.tcl:77 +msgid "git-gui - a graphical user interface for Git." +msgstr "git-gui - un'interfaccia grafica per Git." + +#: lib/option.tcl:164 +msgid "Restore Defaults" +msgstr "Ripristina predefiniti" + +#: lib/option.tcl:168 +msgid "Save" +msgstr "Salva" + +#: lib/option.tcl:178 +#, tcl-format +msgid "%s Repository" +msgstr "%s archivio" + +#: lib/option.tcl:179 +msgid "Global (All Repositories)" +msgstr "Globale (Tutti i repository)" + +#: lib/option.tcl:185 +msgid "User Name" +msgstr "Nome utente" + +#: lib/option.tcl:186 +msgid "Email Address" +msgstr "Indirizzo Email" + +#: lib/option.tcl:188 +msgid "Summarize Merge Commits" +msgstr "Riepilogo nei commit di fusione" + +#: lib/option.tcl:189 +msgid "Merge Verbosity" +msgstr "Verbosità della fusione" + +#: lib/option.tcl:190 +msgid "Show Diffstat After Merge" +msgstr "Mostra statistiche delle differenze dopo la fusione" + +#: lib/option.tcl:192 +msgid "Trust File Modification Timestamps" +msgstr "Fidati delle date di modifica dei file" + +#: lib/option.tcl:193 +msgid "Prune Tracking Branches During Fetch" +msgstr "Effettua potatura dei rami in 'tracking' durante il recupero" + +#: lib/option.tcl:194 +msgid "Match Tracking Branches" +msgstr "Appaia rami in 'tracking'" + +#: lib/option.tcl:195 +msgid "Number of Diff Context Lines" +msgstr "Numero di linee di contesto nelle differenze" + +#: lib/option.tcl:196 +msgid "New Branch Name Template" +msgstr "Modello per il nome di un nuovo ramo" + +#: lib/option.tcl:305 +msgid "Failed to completely save options:" +msgstr "Fallimento nel salvataggio completo delle opzioni:" + +#: lib/remote_branch_delete.tcl:29 lib/remote_branch_delete.tcl:34 +msgid "Delete Remote Branch" +msgstr "Cancella ramo remoto" + +#: lib/remote_branch_delete.tcl:47 +msgid "From Repository" +msgstr "Da archivio" + +#: lib/remote_branch_delete.tcl:50 lib/transport.tcl:118 +msgid "Remote:" +msgstr "Remoto:" + +#: lib/remote_branch_delete.tcl:66 lib/transport.tcl:133 +msgid "Arbitrary URL:" +msgstr "URL arbitrario:" + +#: lib/remote_branch_delete.tcl:84 +msgid "Branches" +msgstr "Rami" + +#: lib/remote_branch_delete.tcl:109 +msgid "Delete Only If" +msgstr "Elimina solo se" + +#: lib/remote_branch_delete.tcl:111 +msgid "Merged Into:" +msgstr "Fuso in:" + +#: lib/remote_branch_delete.tcl:119 +msgid "Always (Do not perform merge checks)" +msgstr "Sempre (Non effettuare controlli durante la fusione)" + +#: lib/remote_branch_delete.tcl:152 +msgid "A branch is required for 'Merged Into'." +msgstr "Si richiede un ramo per 'Fuso in'." + +#: lib/remote_branch_delete.tcl:189 +#, tcl-format +msgid "" +"One or more of the merge tests failed because you have not fetched the " +"necessary commits. Try fetching from %s first." +msgstr "" +"Una o più verifiche di fusione sono fallite perché mancano i commit " +"necessari. Prova prima a prelevarli da %s." + +#: lib/remote_branch_delete.tcl:207 +msgid "Please select one or more branches to delete." +msgstr "Scegliere uno o più rami da cancellare." + +#: lib/remote_branch_delete.tcl:216 +msgid "" +"Recovering deleted branches is difficult.\n" +"\n" +"Delete the selected branches?" +msgstr "" +"Prelevare rami cancellati è difficile.\n" +"\n" +"Cancellare i rami selezionati?" + +#: lib/remote_branch_delete.tcl:226 +#, tcl-format +msgid "Deleting branches from %s" +msgstr "Cancellazione rami da %s" + +#: lib/remote_branch_delete.tcl:286 +msgid "No repository selected." +msgstr "Nessun archivio selezionato." + +#: lib/remote_branch_delete.tcl:291 +#, tcl-format +msgid "Scanning %s..." +msgstr "Analisi in corso %s..." + +#: lib/remote.tcl:162 +#, tcl-format +msgid "Fetch from %s..." +msgstr "Preleva da %s..." + +#: lib/remote.tcl:172 +#, tcl-format +msgid "Prune from %s..." +msgstr "Effettua potatura da %s..." + +#: lib/remote.tcl:206 +#, tcl-format +msgid "Push to %s..." +msgstr "Propaga verso %s..." + +#: lib/shortcut.tcl:26 lib/shortcut.tcl:74 +msgid "Cannot write script:" +msgstr "Impossibile scrivere script:" + +#: lib/shortcut.tcl:149 +msgid "Cannot write icon:" +msgstr "Impossibile scrivere icona:" + +#: lib/status_bar.tcl:58 +#, tcl-format +msgid "%s ... %i of %i %s (%2i%%)" +msgstr "%s ... %i di %i %s (%2i%%)" + +#: lib/transport.tcl:7 +#, tcl-format +msgid "Fetching new changes from %s" +msgstr "Recupero nuove modifiche da %s" + +#: lib/transport.tcl:19 +#, tcl-format +msgid "Pruning tracking branches deleted from %s" +msgstr "Effettua potatura dei rami in 'tracking' cancellati da %s" + +#: lib/transport.tcl:26 +#, tcl-format +msgid "Pushing changes to %s" +msgstr "Propagazione modifiche a %s" + +#: lib/transport.tcl:68 +#, tcl-format +msgid "Pushing %s %s to %s" +msgstr "Propagazione %s %s a %s" + +#: lib/transport.tcl:84 +msgid "Push Branches" +msgstr "Propaga rami" + +#: lib/transport.tcl:98 +msgid "Source Branches" +msgstr "Rami di origine" + +#: lib/transport.tcl:115 +msgid "Destination Repository" +msgstr "Archivio di destinazione" + +#: lib/transport.tcl:153 +msgid "Transfer Options" +msgstr "Opzioni di trasferimento" + +#: lib/transport.tcl:155 +msgid "Use thin pack (for slow network connections)" +msgstr "Utilizza 'thin pack' (per connessioni lente)" + +#: lib/transport.tcl:159 +msgid "Include tags" +msgstr "Includi etichette" + From e2b7200fcdb7bdafe7af00860df7d5774969e419 Mon Sep 17 00:00:00 2001 From: Irina Riesen Date: Sun, 22 Jul 2007 13:57:12 +0200 Subject: [PATCH 0025/1490] git-gui: initial version of russian translation Signed-off-by: Alex Riesen Signed-off-by: Irina Riesen Signed-off-by: Johannes Schindelin --- po/ru.po | 1480 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1480 insertions(+) create mode 100644 po/ru.po diff --git a/po/ru.po b/po/ru.po new file mode 100644 index 0000000000..c44d30af0a --- /dev/null +++ b/po/ru.po @@ -0,0 +1,1480 @@ +# Translation of git-gui to russian +# Copyright (C) 2007 Shawn Pearce +# This file is distributed under the same license as the git-gui package. +# Irina Riesen , 2007. +# +msgid "" +msgstr "" +"Project-Id-Version: git-gui\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2007-07-27 19:33+0200\n" +"PO-Revision-Date: 2007-07-28 18:30+0200\n" +"Last-Translator: Irina Riesen \n" +"Language-Team: Russian Translation \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: git-gui.sh:531 +msgid "Cannot find git in PATH." +msgstr "git не найден в PATH." + +#: git-gui.sh:550 +msgid "Cannot parse Git version string:" +msgstr "" +"Невозможно распознать строку версии Git: " + +#: git-gui.sh:567 +#, tcl-format +msgid "" +"Git version cannot be determined.\n" +"\n" +"%s claims it is version '%s'.\n" +"\n" +"%s requires at least Git 1.5.0 or later.\n" +"\n" +"Assume '%s' is version 1.5.0?\n" +msgstr "" + +#: git-gui.sh:689 +msgid "Cannot find the git directory:" +msgstr "Каталог Git не найден:" + +#: git-gui.sh:697 +msgid "Git directory not found:" +msgstr "Каталог Git не найден:" + +#: git-gui.sh:703 +msgid "Cannot use funny .git directory:" +msgstr "Каталог.git испорчен: " + +#: git-gui.sh:708 +msgid "No working directory" +msgstr "Отсутствует рабочий каталог" + +#: git-gui.sh:853 +msgid "Refreshing file status..." +msgstr "Обновление состояния файлов проекта..." + +#: git-gui.sh:886 +msgid "Scanning for modified files ..." +msgstr "Поиск измененных файлов..." + +#: git-gui.sh:1052 lib/browser.tcl:233 +msgid "Ready." +msgstr "Готово." + +#: git-gui.sh:1343 +msgid "Unmodified" +msgstr "Не изменено" + +#: git-gui.sh:1345 +msgid "Modified, not staged" +msgstr "Изменено, но не включено" + +#: git-gui.sh:1346 git-gui.sh:1351 +msgid "Staged for commit" +msgstr "Подготовлено для сохранения" + +#: git-gui.sh:1347 git-gui.sh:1352 +msgid "Portions staged for commit" +msgstr "Части, подготовленные для сохранения" + +#: git-gui.sh:1348 git-gui.sh:1353 +#, fuzzy +msgid "Staged for commit, missing" +msgstr "" +"Подготовлено для сохранения, отсутствует" + +#: git-gui.sh:1350 +msgid "Untracked, not staged" +msgstr "Не отслеживается, не подготовлено" + +#: git-gui.sh:1355 +msgid "Missing" +msgstr "Отсутствует" + +#: git-gui.sh:1356 +msgid "Staged for removal" +msgstr "Подготовлено для удаления" + +#: git-gui.sh:1357 +msgid "Staged for removal, still present" +msgstr "" +"Подготовлено для удаления, но еще не " +"удалено" + +#: git-gui.sh:1359 git-gui.sh:1360 git-gui.sh:1361 git-gui.sh:1362 +msgid "Requires merge resolution" +msgstr "" +"Требуется разрешение конфликта при " +"объединении" + +#: git-gui.sh:1404 +msgid "Starting gitk... please wait..." +msgstr "Запускается gitk... пожалуйста, ждите..." + +#: git-gui.sh:1413 +#, tcl-format +msgid "" +"Unable to start gitk:\n" +"\n" +"%s does not exist" +msgstr "" +"Не удалось запустить gitk:\n" +"\n" +"%s не существует" + +#: git-gui.sh:1630 +#, tcl-format +msgid "Invalid font specified in gui.%s:" +msgstr "" +"В оболочке установлен неверный шрифт.%s:" + +#: git-gui.sh:1655 +msgid "Main Font" +msgstr "Шрифт интерфейса" + +#: git-gui.sh:1656 +msgid "Diff/Console Font" +msgstr "Шрифт в консоли diff" + +#: git-gui.sh:1670 +msgid "Repository" +msgstr "Репозиторий" + +#: git-gui.sh:1671 +msgid "Edit" +msgstr "Редактировать" + +#: git-gui.sh:1673 +msgid "Branch" +msgstr "Ветвь" + +#: git-gui.sh:1676 git-gui.sh:1854 git-gui.sh:2193 +msgid "Commit" +msgstr "Сохранить" + +#: git-gui.sh:1679 lib/merge.tcl:96 lib/merge.tcl:157 lib/merge.tcl:173 +msgid "Merge" +msgstr "Объединить" + +#: git-gui.sh:1680 +msgid "Fetch" +msgstr "Получить" + +#: git-gui.sh:1681 git-gui.sh:2199 lib/transport.tcl:88 lib/transport.tcl:172 +msgid "Push" +msgstr "Отправить" + +#: git-gui.sh:1690 +msgid "Browse Current Branch's Files" +msgstr "Просмотреть файлы текущей ветви" + +#: git-gui.sh:1692 +#, fuzzy, tcl-format +msgid "Browse %s's Files" +msgstr "Показать файлы ветви" + +#: git-gui.sh:1694 +#, fuzzy +msgid "Browse Branch Files..." +msgstr "Показать файлы ветви" + +#: git-gui.sh:1699 +msgid "Visualize Current Branch's History" +msgstr "История текущей ветви наглядно" + +#: git-gui.sh:1701 +#, fuzzy, tcl-format +msgid "Visualize %s's History" +msgstr "История всех ветвей наглядно" + +#: git-gui.sh:1703 +msgid "Visualize All Branch History" +msgstr "История всех ветвей наглядно" + +#: git-gui.sh:1708 lib/database.tcl:27 lib/database.tcl:67 +msgid "Database Statistics" +msgstr "Статистика базы данных" + +#: git-gui.sh:1711 lib/database.tcl:34 +msgid "Compress Database" +msgstr "Сжать базу данных" + +#: git-gui.sh:1714 +msgid "Verify Database" +msgstr "Проверить базу данных" + +#: git-gui.sh:1721 git-gui.sh:1725 git-gui.sh:1729 lib/shortcut.tcl:9 +#: lib/shortcut.tcl:45 lib/shortcut.tcl:84 +msgid "Create Desktop Icon" +msgstr "Создать ярлык на рабочем столе" + +#: git-gui.sh:1734 +msgid "Quit" +msgstr "Выход" + +#: git-gui.sh:1741 +msgid "Undo" +msgstr "Отменить" + +#: git-gui.sh:1744 +msgid "Redo" +msgstr "Повторить" + +#: git-gui.sh:1748 git-gui.sh:2263 +msgid "Cut" +msgstr "Вырезать" + +#: git-gui.sh:1751 git-gui.sh:2266 git-gui.sh:2337 git-gui.sh:2409 +#: lib/console.tcl:69 +msgid "Copy" +msgstr "Копировать" + +#: git-gui.sh:1754 git-gui.sh:2269 +msgid "Paste" +msgstr "Вставить" + +#: git-gui.sh:1757 git-gui.sh:2272 lib/branch_delete.tcl:26 +#: lib/remote_branch_delete.tcl:38 +msgid "Delete" +msgstr "Удалить" + +#: git-gui.sh:1761 git-gui.sh:2276 git-gui.sh:2413 lib/console.tcl:71 +msgid "Select All" +msgstr "Выделить все" + +#: git-gui.sh:1770 +msgid "Create..." +msgstr "Создать..." + +#: git-gui.sh:1776 +msgid "Checkout..." +msgstr "Перейти..." + +#: git-gui.sh:1782 +msgid "Rename..." +msgstr "Переименовать..." + +#: git-gui.sh:1787 git-gui.sh:1885 +msgid "Delete..." +msgstr "Удалить..." + +#: git-gui.sh:1792 +msgid "Reset..." +msgstr "Сбросить..." + +#: git-gui.sh:1804 git-gui.sh:2210 +msgid "New Commit" +msgstr "Новое состояние" + +#: git-gui.sh:1812 git-gui.sh:2217 +msgid "Amend Last Commit" +msgstr "Исправить последнее состояние" + +#: git-gui.sh:1821 git-gui.sh:2177 lib/remote_branch_delete.tcl:99 +msgid "Rescan" +msgstr "Перечитать" + +#: git-gui.sh:1827 +msgid "Add To Commit" +msgstr "Подготовить к сохранению" + +#: git-gui.sh:1832 +msgid "Add Existing To Commit" +msgstr "" +"Подготовить имеющиеся файлы к сохранению" + +#: git-gui.sh:1838 +msgid "Unstage From Commit" +msgstr "Убрать из подготовленного" + +#: git-gui.sh:1843 lib/index.tcl:376 +msgid "Revert Changes" +msgstr "Отменить изменения" + +#: git-gui.sh:1850 git-gui.sh:2189 git-gui.sh:2287 +msgid "Sign Off" +msgstr "Подписать" + +#: git-gui.sh:1865 +msgid "Local Merge..." +msgstr "Локальное объединение..." + +#: git-gui.sh:1870 +msgid "Abort Merge..." +msgstr "Прервать объединение..." + +#: git-gui.sh:1882 +msgid "Push..." +msgstr "Отправить..." + +#: git-gui.sh:1892 +msgid "Apple" +msgstr "" + +#: git-gui.sh:1895 git-gui.sh:1942 lib/option.tcl:65 +#, tcl-format +msgid "About %s" +msgstr "О %s" + +#: git-gui.sh:1897 git-gui.sh:1903 git-gui.sh:2455 +msgid "Options..." +msgstr "Настройки..." + +#: git-gui.sh:1917 +msgid "Running miga..." +msgstr "" + +#: git-gui.sh:1938 +msgid "Help" +msgstr "Помощь" + +#: git-gui.sh:1979 +msgid "Online Documentation" +msgstr "Документация в интернете" + +#: git-gui.sh:2095 +msgid "Current Branch:" +msgstr "Текущая ветвь:" + +#: git-gui.sh:2116 +msgid "Staged Changes (Will Be Committed)" +msgstr "Подготовлено (будет сохранено)" + +#: git-gui.sh:2136 +msgid "Unstaged Changes (Will Not Be Committed)" +msgstr "Изменено (не будет сохранено)" + +#: git-gui.sh:2183 +msgid "Add Existing" +msgstr "Добавить имеющиеся файлы" + +#: git-gui.sh:2229 +#, fuzzy +msgid "Initial Commit Message:" +msgstr "" +"Первоначальный комментарий к состоянию:" + +#: git-gui.sh:2230 +#, fuzzy +msgid "Amended Commit Message:" +msgstr "Исправленный комментарий к состоянию:" + +#: git-gui.sh:2231 +#, fuzzy +msgid "Amended Initial Commit Message:" +msgstr "" +"Первоначальный комментарий к " +"исправленному состоянию:" + +#: git-gui.sh:2232 +#, fuzzy +msgid "Amended Merge Commit Message:" +msgstr "" +"Комментарий к исправленному объединению:" + +#: git-gui.sh:2233 +msgid "Merge Commit Message:" +msgstr "Комментарий к объединению:" + +#: git-gui.sh:2234 +msgid "Commit Message:" +msgstr "Комментарий к состоянию:" + +#: git-gui.sh:2279 git-gui.sh:2417 lib/console.tcl:73 +msgid "Copy All" +msgstr "Копировать все" + +#: git-gui.sh:2303 lib/blame.tcl:104 +msgid "File:" +msgstr "Файл:" + +#: git-gui.sh:2405 +msgid "Refresh" +msgstr "Обновить" + +#: git-gui.sh:2426 +msgid "Apply/Reverse Hunk" +msgstr "Применить/Убрать изменение" + +#: git-gui.sh:2432 +msgid "Decrease Font Size" +msgstr "Уменьшить размер шрифта" + +#: git-gui.sh:2436 +msgid "Increase Font Size" +msgstr "Увеличить размер шрифта" + +#: git-gui.sh:2441 +msgid "Show Less Context" +msgstr "Меньше контекста" + +#: git-gui.sh:2448 +msgid "Show More Context" +msgstr "Больше контекста" + +#: git-gui.sh:2461 +msgid "Unstage Hunk From Commit" +msgstr "Не сохранять часть" + +#: git-gui.sh:2463 +msgid "Stage Hunk For Commit" +msgstr "Подготовить часть для сохранения" + +#: git-gui.sh:2473 +msgid "Initializing..." +msgstr "Инициализация..." + +#: lib/blame.tcl:77 +msgid "File Viewer" +msgstr "Просмотр файла" + +#: lib/blame.tcl:81 +msgid "Commit:" +msgstr "Сохраненное состояние:" + +#: lib/blame.tcl:249 +msgid "Copy Commit" +msgstr "Копировать сохраненное состояние" + +#: lib/blame.tcl:369 +#, tcl-format +msgid "Reading %s..." +msgstr "Чтение %s..." + +#: lib/branch_checkout.tcl:14 lib/branch_checkout.tcl:19 +msgid "Checkout Branch" +msgstr "Перейти на ветвь" + +#: lib/branch_checkout.tcl:23 +msgid "Checkout" +msgstr "Перейти" + +#: lib/branch_checkout.tcl:27 lib/branch_create.tcl:35 +#: lib/branch_delete.tcl:32 lib/branch_rename.tcl:30 lib/browser.tcl:269 +#: lib/checkout_op.tcl:519 lib/merge.tcl:176 lib/option.tcl:172 +#: lib/remote_branch_delete.tcl:42 lib/transport.tcl:92 +msgid "Cancel" +msgstr "Отменить" + +#: lib/branch_checkout.tcl:32 lib/browser.tcl:274 +msgid "Revision" +msgstr "Версия" + +#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:159 +#: lib/option.tcl:274 +msgid "Options" +msgstr "Настройки" + +#: lib/branch_checkout.tcl:39 lib/branch_create.tcl:92 +msgid "Fetch Tracking Branch" +msgstr "Получить изменения из внешней ветви" + +#: lib/branch_checkout.tcl:44 +msgid "Detach From Local Branch" +msgstr "Отсоединить от локальной ветви" + +#: lib/branch_create.tcl:22 +msgid "Create Branch" +msgstr "Создание ветви" + +#: lib/branch_create.tcl:27 +msgid "Create New Branch" +msgstr "Создать новую ветвь" + +#: lib/branch_create.tcl:31 +msgid "Create" +msgstr "Создать" + +#: lib/branch_create.tcl:40 +msgid "Branch Name" +msgstr "Название ветви" + +#: lib/branch_create.tcl:43 +msgid "Name:" +msgstr "Название:" + +#: lib/branch_create.tcl:58 +msgid "Match Tracking Branch Name" +msgstr "Взять из имен ветвей слежения" + +#: lib/branch_create.tcl:66 +msgid "Starting Revision" +msgstr "Начальная версия" + +#: lib/branch_create.tcl:72 +msgid "Update Existing Branch:" +msgstr "Обновить имеющуюся ветвь:" + +#: lib/branch_create.tcl:75 +msgid "No" +msgstr "Нет" + +#: lib/branch_create.tcl:80 +msgid "Fast Forward Only" +msgstr "Только Fast Forward" + +#: lib/branch_create.tcl:85 lib/checkout_op.tcl:511 +msgid "Reset" +msgstr "Сброс" + +#: lib/branch_create.tcl:97 +msgid "Checkout After Creation" +msgstr "После создания сделать текущей" + +#: lib/branch_create.tcl:131 +msgid "Please select a tracking branch." +msgstr "Укажите ветвь слежения." + +#: lib/branch_create.tcl:140 +#, tcl-format +msgid "Tracking branch %s is not a branch in the remote repository." +msgstr "" +"Ветвь слежения %s не является ветвью во " +"внешнем репозитории." + +#: lib/branch_create.tcl:153 lib/branch_rename.tcl:86 +msgid "Please supply a branch name." +msgstr "Укажите название ветви." + +#: lib/branch_create.tcl:164 lib/branch_rename.tcl:106 +#, tcl-format +msgid "'%s' is not an acceptable branch name." +msgstr "Недопустимое название ветви '%s'." + +#: lib/branch_delete.tcl:15 +msgid "Delete Branch" +msgstr "Удаление ветви" + +#: lib/branch_delete.tcl:20 +msgid "Delete Local Branch" +msgstr "Удалить локальную ветвь" + +#: lib/branch_delete.tcl:37 +msgid "Local Branches" +msgstr "Локальные ветви" + +#: lib/branch_delete.tcl:52 +msgid "Delete Only If Merged Into" +msgstr "" +"Удалить только в случае, если было " +"объединение с" + +#: lib/branch_delete.tcl:54 +msgid "Always (Do not perform merge test.)" +msgstr "" +"Всегда (не выполнять проверку на " +"объединение)" + +#: lib/branch_delete.tcl:103 +#, tcl-format +msgid "The following branches are not completely merged into %s:" +msgstr "" +"Следующие ветви объединены с %s не " +"полностью:" + +#: lib/branch_delete.tcl:115 +msgid "" +"Recovering deleted branches is difficult. \n" +"\n" +" Delete the selected branches?" +msgstr "" +"Восстановить удаленную ветвь сложно. \n" +"\n" +" Удалить выбранные ветви?" + +#: lib/branch_delete.tcl:141 +#, tcl-format +msgid "" +"Failed to delete branches:\n" +"%s" +msgstr "" +"Не удалось удалить ветви:\n" +"%s" + +#: lib/branch_rename.tcl:14 lib/branch_rename.tcl:22 +msgid "Rename Branch" +msgstr "Переименование ветви" + +#: lib/branch_rename.tcl:26 +msgid "Rename" +msgstr "Переименовать" + +#: lib/branch_rename.tcl:36 +msgid "Branch:" +msgstr "Ветвь:" + +#: lib/branch_rename.tcl:39 +msgid "New Name:" +msgstr "Новое название:" + +#: lib/branch_rename.tcl:75 +msgid "Please select a branch to rename." +msgstr "Укажите ветвь для переименования." + +#: lib/branch_rename.tcl:96 lib/checkout_op.tcl:179 +#, tcl-format +msgid "Branch '%s' already exists." +msgstr "Ветвь '%s' уже существует." + +#: lib/branch_rename.tcl:117 +#, tcl-format +msgid "Failed to rename '%s'." +msgstr "Не удалось переименовать '%s'. " + +#: lib/browser.tcl:10 +msgid "Starting..." +msgstr "Запуск..." + +#: lib/browser.tcl:19 +msgid "File Browser" +msgstr "Просмотр списка файлов" + +#: lib/browser.tcl:120 lib/browser.tcl:137 +#, tcl-format +msgid "Loading %s..." +msgstr "Загрузка %s..." + +#: lib/browser.tcl:254 lib/browser.tcl:260 +msgid "Browse Branch Files" +msgstr "Показать файлы ветви" + +#: lib/browser.tcl:265 +msgid "Browse" +msgstr "Показать" + +#: lib/checkout_op.tcl:79 +#, fuzzy, tcl-format +msgid "Fetching %s from %s" +msgstr "Получение изменений из %s " + +#: lib/checkout_op.tcl:140 lib/console.tcl:81 lib/database.tcl:31 +msgid "Close" +msgstr "Закрыть" + +#: lib/checkout_op.tcl:169 +#, tcl-format +msgid "Branch '%s' does not exist." +msgstr "Ветвь '%s' не существует " + +#: lib/checkout_op.tcl:205 +#, tcl-format +msgid "" +"Branch '%s' already exists.\n" +"\n" +"It cannot fast-forward to %s.\n" +"A merge is required." +msgstr "" +"Ветвь '%s' уже существует.\n" +"\n" +"Она не может быть прокручена(fast-forward) к %s.\n" +"Требуется объединение." + +#: lib/checkout_op.tcl:219 +#, tcl-format +msgid "Merge strategy '%s' not supported." +msgstr "" +"Операция объединения '%s' не " +"поддерживается." + +#: lib/checkout_op.tcl:238 +#, tcl-format +msgid "Failed to update '%s'." +msgstr "Не удалось обновить '%s'." + +#: lib/checkout_op.tcl:250 +msgid "Index is already locked." +msgstr "Индекс заблокирован." + +#: lib/checkout_op.tcl:265 +msgid "" +"Last scanned state does not match repository state.\n" +"\n" +"Another Git program has modified this repository since the last scan. A " +"rescan must be performed before the current branch can be changed.\n" +"\n" +"The rescan will be automatically started now.\n" +msgstr "" +"Последнее прочитанное состояние " +"репозитория не соответствует текущему.\n" +"\n" +"С момента последней проверки репозиторий " +"был изменен другой программой " +"Git.Необходимо перечитать репозиторий, " +"прежде чем изменять текущую ветвь. \n" +"\n" +"Это будет сделано сейчас автоматически.\n" + +#: lib/checkout_op.tcl:352 +#, tcl-format +msgid "Aborted checkout of '%s' (file level merging is required)." +msgstr "" +"Прерван переход на '%s' (требуется " +"объединение на уровне файлов)" + +#: lib/checkout_op.tcl:353 +msgid "File level merge required." +msgstr "" +"Требуется объединение на уровне файлов." + +#: lib/checkout_op.tcl:357 +#, tcl-format +msgid "Staying on branch '%s'." +msgstr "Ветвь '%s' остается текущей." + +#: lib/checkout_op.tcl:426 +msgid "" +"You are no longer on a local branch.\n" +"\n" +"If you wanted to be on a branch, create one now starting from 'This Detached " +"Checkout'." +msgstr "" +"Вы находитесь не в локальной ветви.\n" +"\n" +"Если вы хотите снова вернуться к " +"какой-нибудь ветви, создайте ее сейчас, " +"начиная с 'Текущего отсоединенного " +"состояния'." + +#: lib/checkout_op.tcl:475 +#, tcl-format +msgid "Resetting '%s' to '%s' will lose the following commits:" +msgstr "" +"Сброс '%s' в '%s' приведет к потере следующих " +"сохраненных состояний: " + +#: lib/checkout_op.tcl:497 +msgid "Recovering lost commits may not be easy." +msgstr "" +"Восстановить потерянные сохраненные " +"состояния будет сложно." + +#: lib/checkout_op.tcl:502 +#, tcl-format +msgid "Reset '%s'?" +msgstr "Сбросить '%s'?" + +#: lib/checkout_op.tcl:507 lib/merge.tcl:171 +msgid "Visualize" +msgstr "Наглядно" + +#: lib/checkout_op.tcl:575 +#, tcl-format +msgid "" +"Failed to set current branch.\n" +"\n" +"This working directory is only partially switched. We successfully updated " +"your files, but failed to update an internal Git file.\n" +"\n" +"This should not have occurred. %s will now close and give up." +msgstr "" +"Не удалось установить текущую ветвь.\n" +"\n" +"Ваш рабочий каталог обновлен только " +"частично. Были обновлены все файлы кроме " +"служебных файлов Git. \n" +"\n" +"Этого не должно было произойти. %s " +"завершается." + +#: lib/choose_rev.tcl:35 +msgid "This Detached Checkout" +msgstr "Текущее отсоединенное состояние" + +#: lib/choose_rev.tcl:42 +msgid "Revision Expression:" +msgstr "Выражение для определения версии:" + +#: lib/choose_rev.tcl:56 +msgid "Local Branch" +msgstr "Локальная ветвь:" + +#: lib/choose_rev.tcl:61 +msgid "Tracking Branch" +msgstr "Ветвь слежения" + +#: lib/choose_rev.tcl:66 +msgid "Tag" +msgstr "Метка" + +#: lib/choose_rev.tcl:227 +#, tcl-format +msgid "Invalid revision: %s" +msgstr "Неверная версия: %s" + +#: lib/choose_rev.tcl:248 +msgid "No revision selected." +msgstr "Версия не указана." + +#: lib/choose_rev.tcl:256 +msgid "Revision expression is empty." +msgstr "" +"Пустое выражения для определения версии." + +#: lib/commit.tcl:9 +msgid "" +"There is nothing to amend.\n" +"\n" +"You are about to create the initial commit. There is no commit before this " +"to amend.\n" +msgstr "" +"Отсутствует состояние для исправления.\n" +"\n" +"Вы можете создать начальное сохраненное " +"состояние. Других состояний для " +"исправления нет.\n" + +#: lib/commit.tcl:18 +msgid "" +"Cannot amend while merging.\n" +"\n" +"You are currently in the middle of a merge that has not been fully " +"completed. You cannot amend the prior commit unless you first abort the " +"current merge activity.\n" +msgstr "" +"Невозможно исправить состояние во время " +"объединения.\n" +"\n" +"Текущее объединение не завершено. " +"Невозможно исправить предыдущее " +"сохраненное состояние не прерывая " +"текущее объединение.\n" + +#: lib/commit.tcl:49 +msgid "Error loading commit data for amend:" +msgstr "" +"Ошибка при загрузке данных для " +"исправления сохраненного состояния:" + +#: lib/commit.tcl:76 +msgid "Unable to obtain your identity:" +msgstr "" +"Невозможно получить информацию об " +"авторстве:" + +#: lib/commit.tcl:81 +msgid "Invalid GIT_COMMITTER_IDENT:" +msgstr "Неверная GIT_COMMITTER_IDENT:" + +#: lib/commit.tcl:133 +msgid "" +"Last scanned state does not match repository state.\n" +"\n" +"Another Git program has modified this repository since the last scan. A " +"rescan must be performed before another commit can be created.\n" +"\n" +"The rescan will be automatically started now.\n" +msgstr "" +"Последнее прочитанное состояние " +"репозитория не соответствует текущему.\n" +"\n" +"С момента последней проверки репозиторий " +"был изменен другой программой " +"Git.Необходимо перечитать репозиторий, " +"прежде чем изменять текущую ветвь. \n" +"\n" +"Это будет сделано сейчас автоматически.\n" + +#: lib/commit.tcl:154 +#, tcl-format +msgid "" +"Unmerged files cannot be committed.\n" +"\n" +"File %s has merge conflicts. You must resolve them and add the file before " +"committing.\n" +msgstr "" +"Нельзя сохранить необъединенные файлы.\n" +"\n" +"Для файла %s возник конфликт объединения. " +"Разрешите конфликт и добавьте к " +"подготовленным файлам перед " +"сохранением.\n" + +#: lib/commit.tcl:162 +#, tcl-format +msgid "" +"Unknown file state %s detected.\n" +"\n" +"File %s cannot be committed by this program.\n" +msgstr "" +"Обнаружено неизвестное состояние файла " +"%s.\n" +"\n" +"Файл %s не может быть сохранен данной " +"программой.\n" + +#: lib/commit.tcl:170 +msgid "" +"No changes to commit.\n" +"\n" +"You must add at least 1 file before you can commit.\n" +msgstr "" +"Отсутствуют изменения для сохранения.\n" +"\n" +"Подготовьте хотя бы один файл до создания " +"сохраненного состояния.\n" + +#: lib/commit.tcl:183 +msgid "" +"Please supply a commit message.\n" +"\n" +"A good commit message has the following format:\n" +"\n" +"- First line: Describe in one sentance what you did.\n" +"- Second line: Blank\n" +"- Remaining lines: Describe why this change is good.\n" +msgstr "" +"Напишите комментарий к сохраненному " +"состоянию.\n" +"\n" +"Рекомендуется следующий формат " +"комментария:\n" +"\n" +"- первая строка: краткое описание " +"сделанных изменений.\n" +"- вторая строка пустая\n" +"- оставшиеся строки: опишите, что дают " +"ваши изменения.\n" + +#: lib/commit.tcl:257 +msgid "write-tree failed:" +msgstr "" +"Программа write-tree завершилась с ошибкой:" + +#: lib/commit.tcl:279 +msgid "" +"No changes to commit.\n" +"\n" +"No files were modified by this commit and it was not a merge commit.\n" +"\n" +"A rescan will be automatically started now.\n" +msgstr "" +"Отсутствуют изменения для сохранения.\n" +"\n" +"Ни один файл не был изменен и не было " +"объединения.\n" +"\n" +"Сейчас автоматически запустится " +"перечитывание репозитория.\n" + +#: lib/commit.tcl:286 +msgid "No changes to commit." +msgstr "Отуствуют измения для сохранения." + +#: lib/commit.tcl:317 +msgid "commit-tree failed:" +msgstr "" +"Программа commit-tree завершилась с ошибкой:" + +#: lib/commit.tcl:339 +msgid "update-ref failed:" +msgstr "" +"Программа update-ref завершилась с ошибкой:" + +#: lib/commit.tcl:430 +#, tcl-format +msgid "Created commit %s: %s" +msgstr "Создано состояние %s: %s " + +#: lib/console.tcl:55 +msgid "Working... please wait..." +msgstr "В процессе... пожалуйста, ждите..." + +#: lib/console.tcl:184 +msgid "Success" +msgstr "Процесс успешно завершен" + +#: lib/console.tcl:194 +msgid "Error: Command Failed" +msgstr "Ошибка: не удалось выполнить команду" + +#: lib/database.tcl:43 +msgid "Number of loose objects" +msgstr "Количество несвязанных объектов" + +#: lib/database.tcl:44 +msgid "Disk space used by loose objects" +msgstr "" +"Объем дискового пространства, занятый " +"несвязанными объектами" + +#: lib/database.tcl:45 +msgid "Number of packed objects" +msgstr "Количество упакованных объектов" + +#: lib/database.tcl:46 +msgid "Number of packs" +msgstr "Количество pack-файлов" + +#: lib/database.tcl:47 +msgid "Disk space used by packed objects" +msgstr "" +"Объем дискового пространства, занятый " +"упакованными объектами" + +#: lib/database.tcl:48 +msgid "Packed objects waiting for pruning" +msgstr "" +"Несвязанные объекты, которые можно " +"удалить" + +#: lib/database.tcl:49 +msgid "Garbage files" +msgstr "Мусор" + +#: lib/database.tcl:72 +msgid "Compressing the object database" +msgstr "Сжатие базы объектов" + +#: lib/database.tcl:83 +msgid "Verifying the object database with fsck-objects" +msgstr "Проверка базы объектов при помощи fsck" + +#: lib/diff.tcl:42 +#, tcl-format +msgid "" +"No differences detected.\n" +"\n" +"%s has no changes.\n" +"\n" +"The modification date of this file was updated by another application, but " +"the content within the file was not changed.\n" +"\n" +"A rescan will be automatically started to find other files which may have " +"the same state." +msgstr "" +"Изменений не обнаружено.\n" +"\n" +"в %s отутствуют изменения.\n" +"\n" +"Дата изменения файла была обновлена " +"другой программой, но содержимое файла " +"осталось прежним.\n" +"\n" +"Сейчас будет запущено перечитывание " +"репозитория, чтобы найти подобные файлы." + +#: lib/diff.tcl:97 +msgid "Error loading file:" +msgstr "Ошибка загрузки файла:" + +#: lib/diff.tcl:162 +msgid "Error loading diff:" +msgstr "Ошибка загрузки diff:" + +#: lib/diff.tcl:278 +msgid "Failed to unstage selected hunk." +msgstr "Не удалось исключить выбранную часть" + +#: lib/diff.tcl:285 +msgid "Failed to stage selected hunk." +msgstr "" +"Не удалось подготовить к сохранению " +"выбранную часть" + +#: lib/error.tcl:12 lib/error.tcl:102 +msgid "error" +msgstr "ошибка" + +#: lib/error.tcl:28 +msgid "warning" +msgstr "предупреждение" + +#: lib/error.tcl:81 +msgid "You must correct the above errors before committing." +msgstr "" +"Прежде чем сохранить, исправьте " +"вышеуказанные ошибки." + +#: lib/index.tcl:364 +#, fuzzy, tcl-format +msgid "Revert changes in file %s?" +msgstr "Отменить изменения" + +#: lib/index.tcl:366 +#, tcl-format +msgid "Revert changes in these %i files?" +msgstr "Отменить изменения в %i файле(-ах)?" + +#: lib/index.tcl:372 +#, fuzzy +msgid "Any unadded changes will be permanently lost by the revert." +msgstr "" +"Отменить изменения в %s?\n" +"\n" +"Любые изменения, не подготовленные к " +"сохранению, будут потеряны при данной " +"операции." + +#: lib/index.tcl:375 +msgid "Do Nothing" +msgstr "Ничего не делать" + +#: lib/merge.tcl:14 +msgid "" +"Cannot merge while amending.\n" +"\n" +"You must finish amending this commit before starting any type of merge.\n" +msgstr "" +"Невозможно выполнить объединение во " +"время исправления.\n" +"\n" +"Завершите исправление данного состояния " +"перед выполнением операции объединения.\n" + +#: lib/merge.tcl:28 +msgid "" +"Last scanned state does not match repository state.\n" +"\n" +"Another Git program has modified this repository since the last scan. A " +"rescan must be performed before a merge can be performed.\n" +"\n" +"The rescan will be automatically started now.\n" +msgstr "" +"Последнее прочитанное состояние " +"репозитория не соответствует текущему.\n" +"\n" +"С момента последней проверки репозиторий " +"был изменен другой программой " +"Git.Необходимо перечитать репозиторий, " +"прежде чем изменять текущую ветвь. \n" +"\n" +"Это будет сделано сейчас автоматически.\n" + +#: lib/merge.tcl:45 +#, tcl-format +msgid "" +"You are in the middle of a conflicted merge.\n" +"\n" +"File %s has merge conflicts.\n" +"\n" +"You must resolve them, add the file, and commit to complete the current " +"merge. Only then can you begin another merge.\n" +msgstr "" +"Предыдущее объединение не завершено " +"из-за конфликта.\n" +"\n" +"Для файла %s возник конфликт объединения.\n" +"Разрешите конфликт, подготовьте файл и " +"сохраните. Только после этого можно " +"начать следующее объединение.\n" + +#: lib/merge.tcl:55 +#, tcl-format +msgid "" +"You are in the middle of a change.\n" +"\n" +"File %s is modified.\n" +"\n" +"You should complete the current commit before starting a merge. Doing so " +"will help you abort a failed merge, should the need arise.\n" +msgstr "" +"Изменения не сохранены.\n" +"\n" +"Файл %s изменен.\n" +"\n" +"Подготовьте и сохраните измения перед " +"началом объединения. В случае " +"необходимости это позволит прервать " +"операцию объединения.\n" + +#: lib/merge.tcl:94 +#, tcl-format +msgid "Merging %s and %s" +msgstr "Объединение %s и %s" + +#: lib/merge.tcl:106 +msgid "Merge completed successfully." +msgstr "Объединение успешно завершено." + +#: lib/merge.tcl:108 +msgid "Merge failed. Conflict resolution is required." +msgstr "" +"Не удалось завершить объединение. " +"Требуется разрешение конфликта." + +#: lib/merge.tcl:166 +#, tcl-format +msgid "Merge Into %s" +msgstr "Объединить с %s" + +#: lib/merge.tcl:181 lib/transport.tcl:98 +msgid "Source Branches" +msgstr "Исходные ветви" + +#: lib/merge.tcl:240 +msgid "" +"Cannot abort while amending.\n" +"\n" +"You must finish amending this commit.\n" +msgstr "" +"Невозможно прервать исправление.\n" +"\n" +"Завершите текущее исправление " +"сохраненного состояния.\n" + +#: lib/merge.tcl:250 +msgid "" +"Abort merge?\n" +"\n" +"Aborting the current merge will cause *ALL* uncommitted changes to be lost.\n" +"\n" +"Continue with aborting the current merge?" +msgstr "" +"Прервать объединение?\n" +"Прерывание объединения приведет к потере " +"*ВСЕХ* несохраненных изменений.\n" +"\n" +"Продолжить?" + +#: lib/merge.tcl:256 +msgid "" +"Abort commit?\n" +"\n" +"Aborting the current commit will cause *ALL* uncommitted changes to be " +"lost.\n" +"\n" +"Continue with aborting the current commit?" +msgstr "" +"Отменить изменения?\n" +"\n" +"Вызванная операция приведет к потере " +"*ВСЕХ* несохраненных изменений.\n" +"\n" +"Продолжить?" + +#: lib/merge.tcl:267 +msgid "Aborting... please wait..." +msgstr "" +"Прерывание выполнения... Пожалуйста, " +"ждите..." + +#: lib/merge.tcl:290 +msgid "Abort completed. Ready." +msgstr "Прервано." + +#: lib/option.tcl:77 +msgid "git-gui - a graphical user interface for Git." +msgstr "" +"git-gui - графический пользовательский " +"интерфейс к Git." + +#: lib/option.tcl:164 +msgid "Restore Defaults" +msgstr "Восстановить настройки по умолчанию" + +#: lib/option.tcl:168 +msgid "Save" +msgstr "Сохранить" + +#: lib/option.tcl:178 +#, tcl-format +msgid "%s Repository" +msgstr "для репозитория %s " + +#: lib/option.tcl:179 +msgid "Global (All Repositories)" +msgstr "Общие (для всех репозиториев)" + +#: lib/option.tcl:185 +msgid "User Name" +msgstr "Имя пользователя" + +#: lib/option.tcl:186 +msgid "Email Address" +msgstr "Адес электронной почты" + +#: lib/option.tcl:188 +msgid "Summarize Merge Commits" +msgstr "" +"Суммарный комментарий при объединении" + +#: lib/option.tcl:189 +msgid "Merge Verbosity" +msgstr "" +"Уровень детальности сообщений при " +"объединении" + +#: lib/option.tcl:190 +msgid "Show Diffstat After Merge" +msgstr "" +"Показать отчет об изменениях после " +"объединения" + +#: lib/option.tcl:192 +msgid "Trust File Modification Timestamps" +msgstr "Доверять времени модификации файла" + +#: lib/option.tcl:193 +msgid "Prune Tracking Branches During Fetch" +msgstr "" +"Чистка ветвей слежения при получении " +"изменений" + +#: lib/option.tcl:194 +msgid "Match Tracking Branches" +msgstr "" +"Имя новой ветви взять из имен ветвей " +"слежения" + +#: lib/option.tcl:195 +msgid "Number of Diff Context Lines" +msgstr "Число строк в контексте diff" + +#: lib/option.tcl:196 +msgid "New Branch Name Template" +msgstr "Шаблон для имени новой ветви" + +#: lib/option.tcl:305 +msgid "Failed to completely save options:" +msgstr "" +"Не удалось полностью сохранить настройки:" + +#: lib/remote_branch_delete.tcl:29 lib/remote_branch_delete.tcl:34 +msgid "Delete Remote Branch" +msgstr "Удалить внешнюю ветвь" + +#: lib/remote_branch_delete.tcl:47 +msgid "From Repository" +msgstr "Из репозитория" + +#: lib/remote_branch_delete.tcl:50 lib/transport.tcl:118 +msgid "Remote:" +msgstr "внешний:" + +#: lib/remote_branch_delete.tcl:66 lib/transport.tcl:133 +msgid "Arbitrary URL:" +msgstr "по указанному URL:" + +#: lib/remote_branch_delete.tcl:84 +msgid "Branches" +msgstr "Ветви" + +#: lib/remote_branch_delete.tcl:109 +msgid "Delete Only If" +msgstr "Удалить только в случае, если" + +#: lib/remote_branch_delete.tcl:111 +msgid "Merged Into:" +msgstr "Объединено с:" + +#: lib/remote_branch_delete.tcl:119 +msgid "Always (Do not perform merge checks)" +msgstr "" +"Всегда (не выполнять проверку " +"объединений)" + +#: lib/remote_branch_delete.tcl:152 +msgid "A branch is required for 'Merged Into'." +msgstr "" +"Для опции 'Объединено с' требуется " +"указать ветвь." + +#: lib/remote_branch_delete.tcl:189 +#, tcl-format +msgid "" +"One or more of the merge tests failed because you have not fetched the " +"necessary commits. Try fetching from %s first." +msgstr "" + +#: lib/remote_branch_delete.tcl:207 +msgid "Please select one or more branches to delete." +msgstr "" +"Укажите одну или несколько ветвей для " +"удаления." + +#: lib/remote_branch_delete.tcl:216 +msgid "" +"Recovering deleted branches is difficult.\n" +"\n" +"Delete the selected branches?" +msgstr "" +"Восстановить удаленные ветви сложно.\n" +"\n" +"Продолжить?" + +#: lib/remote_branch_delete.tcl:226 +#, tcl-format +msgid "Deleting branches from %s" +msgstr "Удаление ветвей из %s" + +#: lib/remote_branch_delete.tcl:286 +msgid "No repository selected." +msgstr "Не указан репозиторий" + +#: lib/remote_branch_delete.tcl:291 +#, tcl-format +msgid "Scanning %s..." +msgstr "Перечитывание %s... " + +#: lib/remote.tcl:156 +#, fuzzy, tcl-format +msgid "Fetch from %s..." +msgstr "Чистка %s... " + +#: lib/remote.tcl:166 +#, tcl-format +msgid "Prune from %s..." +msgstr "Чистка %s... " + +#: lib/remote.tcl:200 +#, tcl-format +msgid "Push to %s..." +msgstr "Отправка в %s..." + +#: lib/shortcut.tcl:26 lib/shortcut.tcl:74 +msgid "Cannot write script:" +msgstr "Невозможно записать скрипт:" + +#: lib/shortcut.tcl:149 +msgid "Cannot write icon:" +msgstr "Невозможно записать значок:" + +#: lib/status_bar.tcl:58 +#, tcl-format +msgid "%s ... %i of %i %s (%2i%%)" +msgstr "%s ... %i из %i %s (%2i%%)" + +#: lib/transport.tcl:7 +#, tcl-format +msgid "Fetching new changes from %s" +msgstr "Получение изменений из %s " + +#: lib/transport.tcl:19 +#, tcl-format +msgid "Pruning tracking branches deleted from %s" +msgstr "Чистка ветвей слежения, удаленных из %s" + +#: lib/transport.tcl:26 +#, tcl-format +msgid "Pushing changes to %s" +msgstr "Отправка изменений в %s " + +#: lib/transport.tcl:68 +#, tcl-format +msgid "Pushing %s %s to %s" +msgstr "Отправка %s %s в %s" + +#: lib/transport.tcl:84 +msgid "Push Branches" +msgstr "Отправить изменения" + +#: lib/transport.tcl:115 +msgid "Destination Repository" +msgstr "Репозиторий назначения" + +#: lib/transport.tcl:153 +msgid "Transfer Options" +msgstr "Настройки передачи" + +#: lib/transport.tcl:155 +msgid "Use thin pack (for slow network connections)" +msgstr "" +"Использовать thin pack (для медленных сетевых " +"подключений)" + +#: lib/transport.tcl:159 +msgid "Include tags" +msgstr "Включить метки" From f6b7de2acd704bfa33841e8c771054f18963dfac Mon Sep 17 00:00:00 2001 From: Miklos Vajna Date: Fri, 27 Jul 2007 14:37:33 +0200 Subject: [PATCH 0026/1490] Hungarian translation of git-gui Signed-off-by: Miklos Vajna Signed-off-by: Johannes Schindelin --- po/hu.po | 1422 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1422 insertions(+) create mode 100644 po/hu.po diff --git a/po/hu.po b/po/hu.po new file mode 100644 index 0000000000..faac58f810 --- /dev/null +++ b/po/hu.po @@ -0,0 +1,1422 @@ +# Hungarian translations for git-gui-i package. +# Copyright (C) 2007 THE git-gui-i'S COPYRIGHT HOLDER +# This file is distributed under the same license as the git-gui-i package. +# Miklos Vajna , 2007. +# +msgid "" +msgstr "" +"Project-Id-Version: git-gui-i 18n\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2007-08-11 17:28+0200\n" +"PO-Revision-Date: 2007-07-27 13:15+0200\n" +"Last-Translator: Miklos Vajna \n" +"Language-Team: Hungarian\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: git-gui.sh:531 +msgid "Cannot find git in PATH." +msgstr "A git nem található a PATH-ban." + +#: git-gui.sh:550 +msgid "Cannot parse Git version string:" +msgstr "Nem értelmezhető a Git verzió sztring:" + +#: git-gui.sh:567 +#, tcl-format +msgid "" +"Git version cannot be determined.\n" +"\n" +"%s claims it is version '%s'.\n" +"\n" +"%s requires at least Git 1.5.0 or later.\n" +"\n" +"Assume '%s' is version 1.5.0?\n" +msgstr "" +"Nem állípítható meg a Git verziója.\n" +"\n" +"A(z) %s szerint a verzió '%s'.\n" +"\n" +"A(z) %s a Git 1.5.0 vagy későbbi verzióját igényli.\n" +"\n" +"Feltételezhetjük, hogy a(z) '%s' verziója legalább 1.5.0?\n" + +#: git-gui.sh:689 +msgid "Cannot find the git directory:" +msgstr "Nem található a git könyvtár:" + +#: git-gui.sh:697 +msgid "Git directory not found:" +msgstr "A Git könyvtár nem található:" + +#: git-gui.sh:703 +msgid "Cannot use funny .git directory:" +msgstr "Nem használható vicces .git könyvtár:" + +#: git-gui.sh:708 +msgid "No working directory" +msgstr "Nincs munkakönyvtár" + +#: git-gui.sh:854 +msgid "Refreshing file status..." +msgstr "A fájlok státuszának frissítése..." + +#: git-gui.sh:891 +msgid "Scanning for modified files ..." +msgstr "Módosított fájlok keresése ..." + +#: git-gui.sh:1057 lib/browser.tcl:247 +msgid "Ready." +msgstr "Kész." + +#: git-gui.sh:1322 +msgid "Unmodified" +msgstr "Nem módosított" + +#: git-gui.sh:1324 +msgid "Modified, not staged" +msgstr "Módosított, de nem kiválasztott" + +#: git-gui.sh:1325 git-gui.sh:1330 +msgid "Staged for commit" +msgstr "Kiválasztva commitolásra" + +#: git-gui.sh:1326 git-gui.sh:1331 +msgid "Portions staged for commit" +msgstr "Részek kiválasztva commitolásra" + +#: git-gui.sh:1327 git-gui.sh:1332 +msgid "Staged for commit, missing" +msgstr "Kiválasztva commitolásra, hiányzó" + +#: git-gui.sh:1329 +msgid "Untracked, not staged" +msgstr "Nem követett, nem kiválasztott" + +#: git-gui.sh:1334 +msgid "Missing" +msgstr "Hiányzó" + +#: git-gui.sh:1335 +msgid "Staged for removal" +msgstr "Kiválasztva eltávolításra" + +#: git-gui.sh:1336 +msgid "Staged for removal, still present" +msgstr "Kiválasztva eltávolításra, jelenleg is elérhető" + +#: git-gui.sh:1338 git-gui.sh:1339 git-gui.sh:1340 git-gui.sh:1341 +msgid "Requires merge resolution" +msgstr "Merge feloldás szükséges" + +#: git-gui.sh:1383 +msgid "Starting gitk... please wait..." +msgstr "A gitk indítása... várjunk..." + +#: git-gui.sh:1392 +#, tcl-format +msgid "" +"Unable to start gitk:\n" +"\n" +"%s does not exist" +msgstr "" +"A gitk indítása sikertelen:\n" +"\n" +"A(z) %s nem létezik" + +#: git-gui.sh:1609 +#, tcl-format +msgid "Invalid font specified in gui.%s:" +msgstr "Érvénytelen font lett megadva a grafikus felületben.%s:" + +#: git-gui.sh:1634 +msgid "Main Font" +msgstr "Fő betűtípus" + +#: git-gui.sh:1635 +msgid "Diff/Console Font" +msgstr "Diff/konzol betűtípus" + +#: git-gui.sh:1649 +msgid "Repository" +msgstr "Repó" + +#: git-gui.sh:1650 +msgid "Edit" +msgstr "Szerkesztés" + +#: git-gui.sh:1652 +msgid "Branch" +msgstr "Branch" + +#: git-gui.sh:1655 git-gui.sh:1842 git-gui.sh:2152 +msgid "Commit" +msgstr "Commit" + +#: git-gui.sh:1658 lib/merge.tcl:121 lib/merge.tcl:150 lib/merge.tcl:168 +msgid "Merge" +msgstr "Merge" + +#: git-gui.sh:1659 +msgid "Fetch" +msgstr "Letöltés" + +#: git-gui.sh:1660 git-gui.sh:2158 lib/transport.tcl:88 lib/transport.tcl:172 +msgid "Push" +msgstr "Push" + +#: git-gui.sh:1669 +msgid "Browse Current Branch's Files" +msgstr "A jelenlegi branch fájljainak böngészése" + +#: git-gui.sh:1673 +msgid "Browse Branch Files..." +msgstr "A branch fájljainak böngészése..." + +#: git-gui.sh:1678 +msgid "Visualize Current Branch's History" +msgstr "A jelenlegi branch történetének vizualizálása" + +#: git-gui.sh:1682 +msgid "Visualize All Branch History" +msgstr "Az összes branch történetének vizualizálása" + +#: git-gui.sh:1689 +#, tcl-format +msgid "Browse %s's Files" +msgstr "A(z) %s branch fájljainak böngészése" + +#: git-gui.sh:1691 +#, tcl-format +msgid "Visualize %s's History" +msgstr "A(z) %s branch történetének vizualizálása" + +#: git-gui.sh:1696 lib/database.tcl:27 lib/database.tcl:67 +msgid "Database Statistics" +msgstr "Adatbázis statisztikák" + +#: git-gui.sh:1699 lib/database.tcl:34 +msgid "Compress Database" +msgstr "Adatbázis tömörítése" + +#: git-gui.sh:1702 +msgid "Verify Database" +msgstr "Adatbázis ellenőrzése" + +#: git-gui.sh:1709 git-gui.sh:1713 git-gui.sh:1717 lib/shortcut.tcl:9 +#: lib/shortcut.tcl:45 lib/shortcut.tcl:84 +msgid "Create Desktop Icon" +msgstr "Asztal ikon létrehozása" + +#: git-gui.sh:1722 +msgid "Quit" +msgstr "Kilépés" + +#: git-gui.sh:1729 +msgid "Undo" +msgstr "Visszavonás" + +#: git-gui.sh:1732 +msgid "Redo" +msgstr "Mégis" + +#: git-gui.sh:1736 git-gui.sh:2222 +msgid "Cut" +msgstr "Kivágás" + +#: git-gui.sh:1739 git-gui.sh:2225 git-gui.sh:2296 git-gui.sh:2368 +#: lib/console.tcl:69 +msgid "Copy" +msgstr "Másolás" + +#: git-gui.sh:1742 git-gui.sh:2228 +msgid "Paste" +msgstr "Beillesztés" + +#: git-gui.sh:1745 git-gui.sh:2231 lib/branch_delete.tcl:26 +#: lib/remote_branch_delete.tcl:38 +msgid "Delete" +msgstr "Törlés" + +#: git-gui.sh:1749 git-gui.sh:2235 git-gui.sh:2372 lib/console.tcl:71 +msgid "Select All" +msgstr "Mindent kiválaszt" + +#: git-gui.sh:1758 +msgid "Create..." +msgstr "Létrehozás..." + +#: git-gui.sh:1764 +msgid "Checkout..." +msgstr "Checkout..." + +#: git-gui.sh:1770 +msgid "Rename..." +msgstr "Átnevezés..." + +#: git-gui.sh:1775 git-gui.sh:1873 +msgid "Delete..." +msgstr "Törlés..." + +#: git-gui.sh:1780 +msgid "Reset..." +msgstr "Visszaállítás..." + +#: git-gui.sh:1792 git-gui.sh:2169 +msgid "New Commit" +msgstr "Új commit" + +#: git-gui.sh:1800 git-gui.sh:2176 +msgid "Amend Last Commit" +msgstr "Utolsó commit javítása" + +#: git-gui.sh:1809 git-gui.sh:2136 lib/remote_branch_delete.tcl:99 +msgid "Rescan" +msgstr "Keresés újra" + +#: git-gui.sh:1815 +msgid "Stage To Commit" +msgstr "Kiválasztás commitolásra" + +#: git-gui.sh:1820 +msgid "Stage Changed Files To Commit" +msgstr "Módosított fájlok kiválasztása commitolásra" + +#: git-gui.sh:1826 +msgid "Unstage From Commit" +msgstr "Commitba való kiválasztás visszavonása" + +#: git-gui.sh:1831 lib/index.tcl:376 +msgid "Revert Changes" +msgstr "Változtatások visszaállítása" + +#: git-gui.sh:1838 git-gui.sh:2148 git-gui.sh:2246 +msgid "Sign Off" +msgstr "Aláír" + +#: git-gui.sh:1853 +msgid "Local Merge..." +msgstr "Helyi merge..." + +#: git-gui.sh:1858 +msgid "Abort Merge..." +msgstr "Merge megszakítása..." + +#: git-gui.sh:1870 +msgid "Push..." +msgstr "Push..." + +#: git-gui.sh:1880 +msgid "Apple" +msgstr "Apple" + +#: git-gui.sh:1883 git-gui.sh:1901 lib/option.tcl:65 +#, tcl-format +msgid "About %s" +msgstr "Névjegy: %s" + +#: git-gui.sh:1885 git-gui.sh:1891 git-gui.sh:2414 +msgid "Options..." +msgstr "Opciók..." + +#: git-gui.sh:1897 +msgid "Help" +msgstr "Segítség" + +#: git-gui.sh:1938 +msgid "Online Documentation" +msgstr "Online dokumentáció" + +#: git-gui.sh:2054 +msgid "Current Branch:" +msgstr "Jelenlegi branch:" + +#: git-gui.sh:2075 +msgid "Staged Changes (Will Be Committed)" +msgstr "Kiválasztott változtatások (commitolva lesz)" + +#: git-gui.sh:2095 +msgid "Unstaged Changes (Will Not Be Committed)" +msgstr "Nem kiválasztott változtatások (nem lesz commitolva)" + +#: git-gui.sh:2142 +msgid "Stage Changed" +msgstr "Változtatások kiválasztása" + +#: git-gui.sh:2188 +msgid "Initial Commit Message:" +msgstr "Kezdeti commit üzenet:" + +#: git-gui.sh:2189 +msgid "Amended Commit Message:" +msgstr "Javító commit üzenet:" + +#: git-gui.sh:2190 +msgid "Amended Initial Commit Message:" +msgstr "Kezdeti javító commit üzenet:" + +#: git-gui.sh:2191 +msgid "Amended Merge Commit Message:" +msgstr "Javító merge commit üzenet:" + +#: git-gui.sh:2192 +msgid "Merge Commit Message:" +msgstr "Merge commit üzenet:" + +#: git-gui.sh:2193 +msgid "Commit Message:" +msgstr "Commit üzenet:" + +#: git-gui.sh:2238 git-gui.sh:2376 lib/console.tcl:73 +msgid "Copy All" +msgstr "Összes másolása" + +#: git-gui.sh:2262 lib/blame.tcl:104 +msgid "File:" +msgstr "Fájl:" + +#: git-gui.sh:2364 +msgid "Refresh" +msgstr "Frissítés" + +#: git-gui.sh:2385 +msgid "Apply/Reverse Hunk" +msgstr "Hunk alkalmazása/visszaállítása" + +#: git-gui.sh:2391 +msgid "Decrease Font Size" +msgstr "Font méret csökkentése" + +#: git-gui.sh:2395 +msgid "Increase Font Size" +msgstr "Fönt méret növelése" + +#: git-gui.sh:2400 +msgid "Show Less Context" +msgstr "Kevesebb környezet mutatása" + +#: git-gui.sh:2407 +msgid "Show More Context" +msgstr "Több környezet mutatása" + +#: git-gui.sh:2422 +msgid "Unstage Hunk From Commit" +msgstr "Hunk törlése commitból" + +#: git-gui.sh:2426 git-gui.sh:2430 +msgid "Stage Hunk For Commit" +msgstr "Hunk kiválasztása commitba" + +#: git-gui.sh:2440 +msgid "Initializing..." +msgstr "Inicializálás..." + +#: lib/blame.tcl:77 +msgid "File Viewer" +msgstr "Fájl néző" + +#: lib/blame.tcl:81 +msgid "Commit:" +msgstr "Commit:" + +#: lib/blame.tcl:249 +msgid "Copy Commit" +msgstr "Commit másolása" + +#: lib/blame.tcl:369 +#, tcl-format +msgid "Reading %s..." +msgstr "A(z) %s olvasása..." + +#: lib/branch_checkout.tcl:14 lib/branch_checkout.tcl:19 +msgid "Checkout Branch" +msgstr "Branch checkoutolása" + +#: lib/branch_checkout.tcl:23 +msgid "Checkout" +msgstr "Checkout" + +#: lib/branch_checkout.tcl:27 lib/branch_create.tcl:35 +#: lib/branch_delete.tcl:32 lib/branch_rename.tcl:30 lib/browser.tcl:283 +#: lib/checkout_op.tcl:522 lib/merge.tcl:172 lib/option.tcl:172 +#: lib/remote_branch_delete.tcl:42 lib/transport.tcl:92 +msgid "Cancel" +msgstr "Mégsem" + +#: lib/branch_checkout.tcl:32 lib/browser.tcl:288 +msgid "Revision" +msgstr "Revízió" + +#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:159 +#: lib/option.tcl:274 +msgid "Options" +msgstr "Opciók" + +#: lib/branch_checkout.tcl:39 lib/branch_create.tcl:92 +msgid "Fetch Tracking Branch" +msgstr "Követő branch letöltése" + +#: lib/branch_checkout.tcl:44 +msgid "Detach From Local Branch" +msgstr "Helyi branch leválasztása" + +#: lib/branch_create.tcl:22 +msgid "Create Branch" +msgstr "Branch létrehozása" + +#: lib/branch_create.tcl:27 +msgid "Create New Branch" +msgstr "Új branch létrehozása" + +#: lib/branch_create.tcl:31 +msgid "Create" +msgstr "Létrehozás" + +#: lib/branch_create.tcl:40 +msgid "Branch Name" +msgstr "Branch neve" + +#: lib/branch_create.tcl:43 +msgid "Name:" +msgstr "Név:" + +#: lib/branch_create.tcl:58 +msgid "Match Tracking Branch Name" +msgstr "Egyeztetendő követési branch név" + +#: lib/branch_create.tcl:66 +msgid "Starting Revision" +msgstr "A következő revíziótól" + +#: lib/branch_create.tcl:72 +msgid "Update Existing Branch:" +msgstr "Létező branch frissítése" + +#: lib/branch_create.tcl:75 +msgid "No" +msgstr "Nem" + +#: lib/branch_create.tcl:80 +msgid "Fast Forward Only" +msgstr "Csak fast forward" + +#: lib/branch_create.tcl:85 lib/checkout_op.tcl:514 +msgid "Reset" +msgstr "Visszaállítás" + +#: lib/branch_create.tcl:97 +msgid "Checkout After Creation" +msgstr "Checkout létrehozás után" + +#: lib/branch_create.tcl:131 +msgid "Please select a tracking branch." +msgstr "Válasszunk ki egy követő branchet." + +#: lib/branch_create.tcl:140 +#, tcl-format +msgid "Tracking branch %s is not a branch in the remote repository." +msgstr "A(z) %s követő branch nem branch a távoli repóban." + +#: lib/branch_create.tcl:153 lib/branch_rename.tcl:86 +msgid "Please supply a branch name." +msgstr "Adjunk megy egy branch nevet." + +#: lib/branch_create.tcl:164 lib/branch_rename.tcl:106 +#, tcl-format +msgid "'%s' is not an acceptable branch name." +msgstr "A(z) '%s' nem egy elfogadható branch név." + +#: lib/branch_delete.tcl:15 +msgid "Delete Branch" +msgstr "Branch törlése" + +#: lib/branch_delete.tcl:20 +msgid "Delete Local Branch" +msgstr "Helyi branch törlése" + +#: lib/branch_delete.tcl:37 +msgid "Local Branches" +msgstr "Helyi branchek" + +#: lib/branch_delete.tcl:52 +msgid "Delete Only If Merged Into" +msgstr "Csak már merge-ölt törlése" + +#: lib/branch_delete.tcl:54 +msgid "Always (Do not perform merge test.)" +msgstr "Mindig (Ne legyen merge teszt.)" + +#: lib/branch_delete.tcl:103 +#, tcl-format +msgid "The following branches are not completely merged into %s:" +msgstr "A következő branchek nem teljesen lettek merge-ölve ebbe: %s:" + +#: lib/branch_delete.tcl:115 +msgid "" +"Recovering deleted branches is difficult. \n" +"\n" +" Delete the selected branches?" +msgstr "" +"A törölt branchek visszaállítása bonyolult. \n" +"\n" +" Biztosan törli a kiválasztott brancheket?" + +#: lib/branch_delete.tcl:141 +#, tcl-format +msgid "" +"Failed to delete branches:\n" +"%s" +msgstr "" +"Nem sikerült törölni a következő brancheket:\n" +"%s" + +#: lib/branch_rename.tcl:14 lib/branch_rename.tcl:22 +msgid "Rename Branch" +msgstr "Branch átnevezése" + +#: lib/branch_rename.tcl:26 +msgid "Rename" +msgstr "Átnevezés" + +#: lib/branch_rename.tcl:36 +msgid "Branch:" +msgstr "Branch:" + +#: lib/branch_rename.tcl:39 +msgid "New Name:" +msgstr "Új név:" + +#: lib/branch_rename.tcl:75 +msgid "Please select a branch to rename." +msgstr "Válasszunk ki egy átnevezendő branchet." + +#: lib/branch_rename.tcl:96 lib/checkout_op.tcl:179 +#, tcl-format +msgid "Branch '%s' already exists." +msgstr "A(z) '%s' branch már létezik." + +#: lib/branch_rename.tcl:117 +#, tcl-format +msgid "Failed to rename '%s'." +msgstr "Nem sikerült átnevezni: '%s'." + +#: lib/browser.tcl:17 +msgid "Starting..." +msgstr "Indítás..." + +#: lib/browser.tcl:26 +msgid "File Browser" +msgstr "Fájl böngésző" + +#: lib/browser.tcl:127 lib/browser.tcl:144 +#, tcl-format +msgid "Loading %s..." +msgstr "A(z) %s betöltése..." + +#: lib/browser.tcl:188 +msgid "[Up To Parent]" +msgstr "[Fel a szülőhöz]" + +#: lib/browser.tcl:268 lib/browser.tcl:274 +msgid "Browse Branch Files" +msgstr "A branch fájljainak böngészése" + +#: lib/browser.tcl:279 +msgid "Browse" +msgstr "Böngészés" + +#: lib/checkout_op.tcl:79 +#, tcl-format +msgid "Fetching %s from %s" +msgstr "A(z) %s letöltése innen: %s" + +#: lib/checkout_op.tcl:140 lib/console.tcl:81 lib/database.tcl:31 +msgid "Close" +msgstr "Bezárás" + +#: lib/checkout_op.tcl:169 +#, tcl-format +msgid "Branch '%s' does not exist." +msgstr "A(z) '%s' branch nem létezik." + +#: lib/checkout_op.tcl:206 +#, tcl-format +msgid "" +"Branch '%s' already exists.\n" +"\n" +"It cannot fast-forward to %s.\n" +"A merge is required." +msgstr "" +"A(z) '%s' branch már létezik.\n" +"\n" +"Nem lehet fast-forwardolni a következőhöz: %s.\n" +"Egy merge szükséges." + +#: lib/checkout_op.tcl:220 +#, tcl-format +msgid "Merge strategy '%s' not supported." +msgstr "A(z) '%s' merge strategy nem támogatott." + +#: lib/checkout_op.tcl:239 +#, tcl-format +msgid "Failed to update '%s'." +msgstr "Nem sikerült frissíteni a következőt: '%s'." + +#: lib/checkout_op.tcl:251 +msgid "Staging area (index) is already locked." +msgstr "A kiválasztási terület (index) már zárolva van." + +#: lib/checkout_op.tcl:266 +msgid "" +"Last scanned state does not match repository state.\n" +"\n" +"Another Git program has modified this repository since the last scan. A " +"rescan must be performed before the current branch can be changed.\n" +"\n" +"The rescan will be automatically started now.\n" +msgstr "" +"Az utolsó keresési állapot nem egyezik meg a repó állpotával.\n" +"\n" +"Egy másik Git program módosította ezt a repót az utolsó keresés óta. Egy " +"újrakeresés mindenképpen szükséges mielőtt a jelenlegi branchet módosítani " +"lehetne.\n" +"\n" +"Az újrakeresés most automatikusan el fog indulni.\n" + +#: lib/checkout_op.tcl:353 +#, tcl-format +msgid "Aborted checkout of '%s' (file level merging is required)." +msgstr "A(z) '%s' checkoutja megszakítva (fájlszintű merge-ölés szükséges)." + +#: lib/checkout_op.tcl:354 +msgid "File level merge required." +msgstr "Fájlszintű merge-ölés szükséges." + +#: lib/checkout_op.tcl:358 +#, tcl-format +msgid "Staying on branch '%s'." +msgstr "Jelenleg a(z) '%s' branchen." + +#: lib/checkout_op.tcl:429 +msgid "" +"You are no longer on a local branch.\n" +"\n" +"If you wanted to be on a branch, create one now starting from 'This Detached " +"Checkout'." +msgstr "" +"Már nem egy helyi branchen vagyunk.\n" +"\n" +"Ha egy branchen szeretnénk lenni, hozzunk létre egyet az 'Ez a leválasztott " +"checkout'-ból." + +#: lib/checkout_op.tcl:478 +#, tcl-format +msgid "Resetting '%s' to '%s' will lose the following commits:" +msgstr "" +"A(z) '%s' -> '%s' visszaállítás a következő commitok elvesztését jelenti:" + +#: lib/checkout_op.tcl:500 +msgid "Recovering lost commits may not be easy." +msgstr "Az elveszett commitok helyreállítása nem biztos, hogy egyszerű." + +#: lib/checkout_op.tcl:505 +#, tcl-format +msgid "Reset '%s'?" +msgstr "Visszaállítjuk a következőt: '%s'?" + +#: lib/checkout_op.tcl:510 lib/merge.tcl:164 +msgid "Visualize" +msgstr "Vizualizálás" + +#: lib/checkout_op.tcl:578 +#, tcl-format +msgid "" +"Failed to set current branch.\n" +"\n" +"This working directory is only partially switched. We successfully updated " +"your files, but failed to update an internal Git file.\n" +"\n" +"This should not have occurred. %s will now close and give up." +msgstr "" +"Nem sikerült beállítani a jelenlegi branchet.\n" +"\n" +"A munkakönyvtár csak részben váltott át. A fájlok sikeresen frissítve " +"lettek, de nem sikerült frissíteni egy belső Git fájlt.\n" +"\n" +"Ennek nem szabad megtörténnie. A(z) %s most kilép és feladja." + +#: lib/choose_rev.tcl:53 +msgid "This Detached Checkout" +msgstr "Ez a leválasztott checkout" + +#: lib/choose_rev.tcl:60 +msgid "Revision Expression:" +msgstr "Revízió kifejezés:" + +#: lib/choose_rev.tcl:74 +msgid "Local Branch" +msgstr "Helyi branch" + +#: lib/choose_rev.tcl:79 +msgid "Tracking Branch" +msgstr "Követő branch" + +#: lib/choose_rev.tcl:84 +msgid "Tag" +msgstr "Tag" + +#: lib/choose_rev.tcl:317 +#, tcl-format +msgid "Invalid revision: %s" +msgstr "Érvénytelen revízió: %s" + +#: lib/choose_rev.tcl:338 +msgid "No revision selected." +msgstr "Nincs kiválasztva revízió." + +#: lib/choose_rev.tcl:346 +msgid "Revision expression is empty." +msgstr "A revízió kifejezés üres." + +#: lib/commit.tcl:9 +msgid "" +"There is nothing to amend.\n" +"\n" +"You are about to create the initial commit. There is no commit before this " +"to amend.\n" +msgstr "" +"Nincs semmi javítanivaló.\n" +"\n" +"Az első commit létrehozása előtt nincs semmilyen commit amit javitani " +"lehetne.\n" + +#: lib/commit.tcl:18 +msgid "" +"Cannot amend while merging.\n" +"\n" +"You are currently in the middle of a merge that has not been fully " +"completed. You cannot amend the prior commit unless you first abort the " +"current merge activity.\n" +msgstr "" +"Nem lehet javítani merge alatt.\n" +"\n" +"A jelenlegi merge még nem teljesen fejeződött be. Csak akkor javíthat egy " +"előbbi commitot, hogyha megszakítja a jelenlegi merge folyamatot.\n" + +#: lib/commit.tcl:49 +msgid "Error loading commit data for amend:" +msgstr "Hiba a javítandó commit adat betöltése közben:" + +#: lib/commit.tcl:76 +msgid "Unable to obtain your identity:" +msgstr "Nem sikerült megállapítani az azonosítót:" + +#: lib/commit.tcl:81 +msgid "Invalid GIT_COMMITTER_IDENT:" +msgstr "Érvénytelen GIT_COMMITTER_IDENT:" + +#: lib/commit.tcl:133 +msgid "" +"Last scanned state does not match repository state.\n" +"\n" +"Another Git program has modified this repository since the last scan. A " +"rescan must be performed before another commit can be created.\n" +"\n" +"The rescan will be automatically started now.\n" +msgstr "" +"Az utolsó keresési állapot nem egyezik meg a repó állapotával.\n" +"\n" +"Egy másik Git program módosította ezt a repót az utolsó keresés óta. Egy " +"újrakeresés mindenképpen szükséges mielőtt a jelenlegi branchet módosítani " +"lehetne.\n" +"\n" +"Az újrakeresés most automatikusan el fog indulni.\n" + +#: lib/commit.tcl:154 +#, tcl-format +msgid "" +"Unmerged files cannot be committed.\n" +"\n" +"File %s has merge conflicts. You must resolve them and stage the file " +"before committing.\n" +msgstr "" +"Nem commitolhatunk fájlokat merge előtt.\n" +"\n" +"A(z) %s fájlban ütközések vannak. Egyszer azokat ki kell javítani, majd " +"hozzá ki kell választani a fájlt mielőtt commitolni lehetne.\n" + +#: lib/commit.tcl:162 +#, tcl-format +msgid "" +"Unknown file state %s detected.\n" +"\n" +"File %s cannot be committed by this program.\n" +msgstr "" +"Ismeretlen fájl típus %s érzékelve.\n" +"\n" +"A(z) %s fájlt nem tudja ez a program commitolni.\n" + +#: lib/commit.tcl:170 +msgid "" +"No changes to commit.\n" +"\n" +"You must stage at least 1 file before you can commit.\n" +msgstr "" +"Nincs commitolandó változtatás.\n" +"\n" +"Legalább egy fájl ki kell választani, hogy commitolni lehessen.\n" + +#: lib/commit.tcl:183 +msgid "" +"Please supply a commit message.\n" +"\n" +"A good commit message has the following format:\n" +"\n" +"- First line: Describe in one sentance what you did.\n" +"- Second line: Blank\n" +"- Remaining lines: Describe why this change is good.\n" +msgstr "" +"Adjunk megy egy commit üzenetet.\n" +"\n" +"Egy jó commit üzenetnek a következő a formátuma:\n" +"\n" +"- Első sor: Egy mondatban leírja, hogy mit csináltunk.\n" +"- Második sor: Üres\n" +"- A többi sor: Leírja, hogy miért jó ez a változtatás.\n" + +#: lib/commit.tcl:257 +msgid "write-tree failed:" +msgstr "a write-tree sikertelen:" + +#: lib/commit.tcl:279 +msgid "" +"No changes to commit.\n" +"\n" +"No files were modified by this commit and it was not a merge commit.\n" +"\n" +"A rescan will be automatically started now.\n" +msgstr "" +"Nincs commitolandó változtatás.\n" +"\n" +"Egyetlen fájlt se módosított ez a commit és merge commit se volt.\n" +"\n" +"Az újrakeresés most automatikusan el fog indulni.\n" + +#: lib/commit.tcl:286 +msgid "No changes to commit." +msgstr "Nincs commitolandó változtatás." + +#: lib/commit.tcl:317 +msgid "commit-tree failed:" +msgstr "a commit-tree sikertelen:" + +#: lib/commit.tcl:339 +msgid "update-ref failed:" +msgstr "az update-ref sikertelen:" + +#: lib/commit.tcl:430 +#, tcl-format +msgid "Created commit %s: %s" +msgstr "Létrejött a %s commit: %s" + +#: lib/console.tcl:55 +msgid "Working... please wait..." +msgstr "Munka folyamatban.. Várjunk..." + +#: lib/console.tcl:184 +msgid "Success" +msgstr "Siker" + +#: lib/console.tcl:194 +msgid "Error: Command Failed" +msgstr "Hiba: a parancs sikertelen" + +#: lib/database.tcl:43 +msgid "Number of loose objects" +msgstr "Elvesztett objektumok száma" + +#: lib/database.tcl:44 +msgid "Disk space used by loose objects" +msgstr "Elveszett objektumok által elfoglalt lemezterület" + +#: lib/database.tcl:45 +msgid "Number of packed objects" +msgstr "Csomagolt objektumok számra" + +#: lib/database.tcl:46 +msgid "Number of packs" +msgstr "Csomagok száma" + +#: lib/database.tcl:47 +msgid "Disk space used by packed objects" +msgstr "A csomagolt objektumok által használt lemezterület" + +#: lib/database.tcl:48 +msgid "Packed objects waiting for pruning" +msgstr "Eltávolításra váró csomagolt objektumok számra" + +#: lib/database.tcl:49 +msgid "Garbage files" +msgstr "Hulladék fájlok" + +#: lib/database.tcl:72 +msgid "Compressing the object database" +msgstr "Az objektum adatbázis tömörítése" + +#: lib/database.tcl:83 +msgid "Verifying the object database with fsck-objects" +msgstr "Az objektum adatbázis ellenőrzése az fsck-objects használatával" + +#: lib/diff.tcl:42 +#, tcl-format +msgid "" +"No differences detected.\n" +"\n" +"%s has no changes.\n" +"\n" +"The modification date of this file was updated by another application, but " +"the content within the file was not changed.\n" +"\n" +"A rescan will be automatically started to find other files which may have " +"the same state." +msgstr "" +"Nincsenek változások.\n" +"\n" +"A(z) %s módosítatlan.\n" +"\n" +"A fájl módosítási dátumát frissítette egy másik alkalmazás, de a fájl " +"tartalma változatlan.\n" +"\n" +"Egy újrakeresés fog indulni a hasonló állapotú fájlok megtalálása érdekében." + +#: lib/diff.tcl:97 +msgid "Error loading file:" +msgstr "Hiba a fájl betöltése közben:" + +#: lib/diff.tcl:162 +msgid "Error loading diff:" +msgstr "Hiba a diff betöltése közben:" + +#: lib/diff.tcl:278 +msgid "Failed to unstage selected hunk." +msgstr "Nem visszavonni a hunk kiválasztását." + +#: lib/diff.tcl:285 +msgid "Failed to stage selected hunk." +msgstr "Nem sikerült kiválasztani a hunkot." + +#: lib/error.tcl:12 lib/error.tcl:102 +msgid "error" +msgstr "hiba" + +#: lib/error.tcl:28 +msgid "warning" +msgstr "figyelmeztetés" + +#: lib/error.tcl:81 +msgid "You must correct the above errors before committing." +msgstr "Ki kell javítanunk a fenti hibákat commit előtt." + +#: lib/index.tcl:364 +#, tcl-format +msgid "Revert changes in file %s?" +msgstr "Visszaállítja a változtatásokat a(z) %s fájlban?" + +#: lib/index.tcl:366 +#, tcl-format +msgid "Revert changes in these %i files?" +msgstr "Visszaállítja a változtatásokat ebben e %i fájlban?" + +#: lib/index.tcl:372 +msgid "Any unstaged changes will be permanently lost by the revert." +msgstr "" +"Minden nem kiválasztott változtatás el fog veszni ezáltal a visszaállítás " +"által." + +#: lib/index.tcl:375 +msgid "Do Nothing" +msgstr "Ne csináljunk semmit" + +#: lib/merge.tcl:13 +msgid "" +"Cannot merge while amending.\n" +"\n" +"You must finish amending this commit before starting any type of merge.\n" +msgstr "" +"Javítás közben nem lehetséges a merge.\n" +"\n" +"Egyszer be kell fejezni ennek a commitnak a javítását, majd kezdődhet egy " +"merge.\n" + +#: lib/merge.tcl:27 +msgid "" +"Last scanned state does not match repository state.\n" +"\n" +"Another Git program has modified this repository since the last scan. A " +"rescan must be performed before a merge can be performed.\n" +"\n" +"The rescan will be automatically started now.\n" +msgstr "" +"Az utolsó keresési állapot nem egyezik meg a repó állapotával.\n" +"\n" +"Egy másik Git program módosította ezt a repót az utolsó keresés óta. Egy " +"újrakeresés mindenképpen szükséges mielőtt a jelenlegi branchet módosítani " +"lehetne.\n" +"\n" +"Az újrakeresés most automatikusan el fog indulni.\n" + +#: lib/merge.tcl:44 +#, tcl-format +msgid "" +"You are in the middle of a conflicted merge.\n" +"\n" +"File %s has merge conflicts.\n" +"\n" +"You must resolve them, stage the file, and commit to complete the current " +"merge. Only then can you begin another merge.\n" +msgstr "" +"Jelenleg egy ütközés feloldása közben vagyunk.\n" +"\n" +"A(z) %s fájlban ütközések vannak.\n" +"\n" +"Fel kell oldanunk őket, kiválasztani a fájlt, és commitolni hogy befejezzük " +"a jelenlegi merge-t. Csak ezután kezdhetünk el egy újabbat.\n" + +#: lib/merge.tcl:54 +#, tcl-format +msgid "" +"You are in the middle of a change.\n" +"\n" +"File %s is modified.\n" +"\n" +"You should complete the current commit before starting a merge. Doing so " +"will help you abort a failed merge, should the need arise.\n" +msgstr "" +"Jelenleg egy változtatás közben vagyunk.\n" +"\n" +"A(z) %s fájl megváltozott.\n" +"\n" +"Először be kell fejeznünk a jelenlegi commitot, hogy elkezdhessünk egy merge-" +"t. Ez segíteni fog, hogy félbeszakíthassunk egy merge-t.\n" + +#: lib/merge.tcl:106 +#, tcl-format +msgid "%s of %s" +msgstr "%s / %s" + +#: lib/merge.tcl:119 +#, tcl-format +msgid "Merging %s and %s" +msgstr "A(z) %s és a(z) %s merge-ölése" + +#: lib/merge.tcl:131 +msgid "Merge completed successfully." +msgstr "A merge sikeresen befejeződött." + +#: lib/merge.tcl:133 +msgid "Merge failed. Conflict resolution is required." +msgstr "A merge sikertelen. Fel kell oldanunk az ütközéseket." + +#: lib/merge.tcl:158 +#, tcl-format +msgid "Merge Into %s" +msgstr "Merge-ölés a következőbe: %s" + +#: lib/merge.tcl:177 +msgid "Revision To Merge" +msgstr "Merge-ölni szándékozott revízió" + +#: lib/merge.tcl:212 +msgid "" +"Cannot abort while amending.\n" +"\n" +"You must finish amending this commit.\n" +msgstr "" +"A commit javítás közben megszakítva.\n" +"\n" +"Be kell fejeznünk ennek a commitnak a javítását.\n" + +#: lib/merge.tcl:222 +msgid "" +"Abort merge?\n" +"\n" +"Aborting the current merge will cause *ALL* uncommitted changes to be lost.\n" +"\n" +"Continue with aborting the current merge?" +msgstr "" +"Megszakítjuk a merge-t?\n" +"\n" +"A jelenlegi merge megszakítása *MINDEN* nem commitolt változtatás " +"elvesztését jelenti.\n" +"\n" +"Folytatjuk a jelenlegi merge megszakítását?" + +#: lib/merge.tcl:228 +msgid "" +"Reset changes?\n" +"\n" +"Resetting the changes will cause *ALL* uncommitted changes to be lost.\n" +"\n" +"Continue with resetting the current changes?" +msgstr "" +"Visszavonjuk a módosításokat?\n" +"\n" +"A módosítások visszavonása *MINDEN* nem commitolt változtatás elvesztését " +"jelenti.\n" +"\n" +"Folytatjuk a jelenlegi módosítások visszavonását?" + +#: lib/merge.tcl:239 +msgid "Aborting" +msgstr "Félbeszakítás" + +#: lib/merge.tcl:266 +msgid "Abort failed." +msgstr "A félbeszakítás nem sikerült." + +#: lib/merge.tcl:268 +msgid "Abort completed. Ready." +msgstr "A megkeszakítás befejeződött. Kész." + +#: lib/option.tcl:77 +msgid "git-gui - a graphical user interface for Git." +msgstr "git-gui - egy grafikus felület a Githez." + +#: lib/option.tcl:164 +msgid "Restore Defaults" +msgstr "Alapértelmezés visszaállítása" + +#: lib/option.tcl:168 +msgid "Save" +msgstr "Mentés" + +#: lib/option.tcl:178 +#, tcl-format +msgid "%s Repository" +msgstr "%s Repó" + +#: lib/option.tcl:179 +msgid "Global (All Repositories)" +msgstr "Globális (minden repó)" + +#: lib/option.tcl:185 +msgid "User Name" +msgstr "Felhasználónév" + +#: lib/option.tcl:186 +msgid "Email Address" +msgstr "Email cím" + +#: lib/option.tcl:188 +msgid "Summarize Merge Commits" +msgstr "A merge commitok összegzése" + +#: lib/option.tcl:189 +msgid "Merge Verbosity" +msgstr "Merge beszédesség" + +#: lib/option.tcl:190 +msgid "Show Diffstat After Merge" +msgstr "Diffstat mutatása merge után" + +#: lib/option.tcl:192 +msgid "Trust File Modification Timestamps" +msgstr "A fájl módosítási dátumok megbízhatóak" + +#: lib/option.tcl:193 +msgid "Prune Tracking Branches During Fetch" +msgstr "A követő branchek eltávolítása letöltés alatt" + +#: lib/option.tcl:194 +msgid "Match Tracking Branches" +msgstr "A követő branchek egyeztetése" + +#: lib/option.tcl:195 +msgid "Number of Diff Context Lines" +msgstr "A diff környezeti sorok száma" + +#: lib/option.tcl:196 +msgid "New Branch Name Template" +msgstr "Új branch név sablon" + +#: lib/option.tcl:305 +msgid "Failed to completely save options:" +msgstr "Nem sikerült teljesen elmenteni a beállításokat:" + +#: lib/remote_branch_delete.tcl:29 lib/remote_branch_delete.tcl:34 +msgid "Delete Remote Branch" +msgstr "Távoli branch törlése" + +#: lib/remote_branch_delete.tcl:47 +msgid "From Repository" +msgstr "Forrás repó" + +#: lib/remote_branch_delete.tcl:50 lib/transport.tcl:118 +msgid "Remote:" +msgstr "Távoli:" + +#: lib/remote_branch_delete.tcl:66 lib/transport.tcl:133 +msgid "Arbitrary URL:" +msgstr "Tetszőleges URL:" + +#: lib/remote_branch_delete.tcl:84 +msgid "Branches" +msgstr "Branchek" + +#: lib/remote_branch_delete.tcl:109 +msgid "Delete Only If" +msgstr "Törlés csak akkor ha" + +#: lib/remote_branch_delete.tcl:111 +msgid "Merged Into:" +msgstr "Merge-ölt a következőbe:" + +#: lib/remote_branch_delete.tcl:119 +msgid "Always (Do not perform merge checks)" +msgstr "Mindig (Ne végezzen merge vizsgálatokat)" + +#: lib/remote_branch_delete.tcl:152 +msgid "A branch is required for 'Merged Into'." +msgstr "Egy branch szükséges a 'Merge-ölt a következőbe'-hez." + +#: lib/remote_branch_delete.tcl:189 +#, tcl-format +msgid "" +"One or more of the merge tests failed because you have not fetched the " +"necessary commits. Try fetching from %s first." +msgstr "" +"Egy vagy több merge teszt hibát jelzett, mivel nem töltöttük le a megfelelő " +"commitokat. Próbáljunk meg letölteni a következőből: %s először." + +#: lib/remote_branch_delete.tcl:207 +msgid "Please select one or more branches to delete." +msgstr "Válasszunk ki egy vagy több branchet törlésre." + +#: lib/remote_branch_delete.tcl:216 +msgid "" +"Recovering deleted branches is difficult.\n" +"\n" +"Delete the selected branches?" +msgstr "" +"A törölt branchek visszaállítása nehéz.\n" +"\n" +"Töröljük a kiválasztott brancheket?" + +#: lib/remote_branch_delete.tcl:226 +#, tcl-format +msgid "Deleting branches from %s" +msgstr "Brancek törlése innen: %s" + +#: lib/remote_branch_delete.tcl:286 +msgid "No repository selected." +msgstr "Nincs kiválasztott repó." + +#: lib/remote_branch_delete.tcl:291 +#, tcl-format +msgid "Scanning %s..." +msgstr "Keresés itt: %s..." + +# tcl-format +#: lib/remote.tcl:162 +#, tcl-format +msgid "Fetch from %s..." +msgstr "Letöltés innen: %s..." + +#: lib/remote.tcl:172 +#, tcl-format +msgid "Prune from %s..." +msgstr "Törlés innen: %s..." + +#: lib/remote.tcl:206 +#, tcl-format +msgid "Push to %s..." +msgstr "Pusholás ide: %s..." + +#: lib/shortcut.tcl:26 lib/shortcut.tcl:74 +msgid "Cannot write script:" +msgstr "Nem sikerült írni a scriptet:" + +#: lib/shortcut.tcl:149 +msgid "Cannot write icon:" +msgstr "Nem sikerült írni az ikont:" + +#: lib/status_bar.tcl:58 +#, tcl-format +msgid "%s ... %i of %i %s (%2i%%)" +msgstr "%s ... %i / %i %s (%2i%%)" + +#: lib/transport.tcl:7 +#, tcl-format +msgid "Fetching new changes from %s" +msgstr "Új változások letöltése innen: %s" + +#: lib/transport.tcl:19 +#, tcl-format +msgid "Pruning tracking branches deleted from %s" +msgstr "A %s repóból törölt követő branchek törlése" + +#: lib/transport.tcl:26 +#, tcl-format +msgid "Pushing changes to %s" +msgstr "Változások pusholása ide: %s" + +#: lib/transport.tcl:68 +#, tcl-format +msgid "Pushing %s %s to %s" +msgstr "Pusholás: %s %s, ide: %s" + +#: lib/transport.tcl:84 +msgid "Push Branches" +msgstr "Branchek pusholása" + +#: lib/transport.tcl:98 +msgid "Source Branches" +msgstr "Forrás branchek" + +#: lib/transport.tcl:115 +msgid "Destination Repository" +msgstr "Cél repó" + +#: lib/transport.tcl:153 +msgid "Transfer Options" +msgstr "Átviteli opciók" + +#: lib/transport.tcl:155 +msgid "Use thin pack (for slow network connections)" +msgstr "Vékony csomagok használata (lassú hálózati kapcsolatok számára)" + +#: lib/transport.tcl:159 +msgid "Include tags" +msgstr "Tageket is" + +#~ msgid "Add To Commit" +#~ msgstr "Hozzáadás a commithoz" + +#~ msgid "Add Existing To Commit" +#~ msgstr "Hozzáadás létező commithoz" + +#~ msgid "Running miga..." +#~ msgstr "A miga futtatása..." + +#~ msgid "Add Existing" +#~ msgstr "Létező hozzáadása" + +#~ msgid "" +#~ "Abort commit?\n" +#~ "\n" +#~ "Aborting the current commit will cause *ALL* uncommitted changes to be " +#~ "lost.\n" +#~ "\n" +#~ "Continue with aborting the current commit?" +#~ msgstr "" +#~ "Megszakítjuk a commitot?\n" +#~ "\n" +#~ "A jelenlegi commit megszakítása *MINDEN* nem commitolt változtatás " +#~ "elvesztését jelenti.\n" +#~ "\n" +#~ "Folytatjuk a jelenlegi commit megszakítását?" + +#~ msgid "Aborting... please wait..." +#~ msgstr "Megszakítás... várjunk..." From fcc73b71557c31ba79acd4e186fec00b096f12f2 Mon Sep 17 00:00:00 2001 From: Christian Stimming Date: Tue, 24 Jul 2007 14:59:15 +0200 Subject: [PATCH 0027/1490] German glossary for translation Signed-off-by: Christian Stimming Signed-off-by: Johannes Schindelin --- po/glossary/de.po | 158 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 po/glossary/de.po diff --git a/po/glossary/de.po b/po/glossary/de.po new file mode 100644 index 0000000000..aab3b22f50 --- /dev/null +++ b/po/glossary/de.po @@ -0,0 +1,158 @@ +# Translation of git-gui glossary to German +# Copyright (C) 2007 Shawn Pearce, et al. +# This file is distributed under the same license as the git package. +# Christian Stimming , 2007 +# +msgid "" +msgstr "" +"Project-Id-Version: git-gui glossary\n" +"PO-Revision-Date: 2007-07-26 14:45+0200\n" +"Last-Translator: Christian Stimming \n" +"Language-Team: German \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. "English Definition (Dear translator: This file will never be visible to the user! It should only serve as a tool for you, the translator. Nothing more.)" +msgid "" +"English Term (Dear translator: This file will never be visible to the user!)" +msgstr "" +"Deutsche Übersetzung.\n" +"Andere deutsche SCM:\n" +" http://tortoisesvn.net/docs/release/TortoiseSVN_de/index.html und http://tortoisesvn.tigris.org/svn/tortoisesvn/trunk/Languages/Tortoise_de.po (username=guest, password empty, gut),\n" +" http://msdn.microsoft.com/de-de/library/ms181038(vs.80).aspx (MS Visual Source Safe, kommerziell),\n" +" http://cvsbook.red-bean.com/translations/german/Kap_06.html (mittelmäßig),\n" +" http://tortoisecvs.cvs.sourceforge.net/tortoisecvs/po/TortoiseCVS/de_DE.po?view=markup (mittelmäßig),\n" +" http://rapidsvn.tigris.org/svn/rapidsvn/trunk/src/locale/de/rapidsvn.po (username=guest, password empty, schlecht)" + +#. "" +msgid "amend" +msgstr "nachbessern (ergänzen)" + +#. "" +msgid "annotate" +msgstr "annotieren" + +#. "A 'branch' is an active line of development." +msgid "branch [noun]" +msgstr "Zweig" + +#. "" +msgid "branch [verb]" +msgstr "verzweigen" + +#. "" +msgid "checkout [noun]" +msgstr "Auscheck? Ausspielung? Abruf? (Source Safe: Auscheckvorgang)" + +#. "The action of updating the working tree to a revision which was stored in the object database." +msgid "checkout [verb]" +msgstr "auschecken? ausspielen? abrufen? (Source Safe: auschecken)" + +#. "A single point in the git history." +msgid "commit [noun]" +msgstr "Übertragung (Sendung?, Übergabe?, Einspielung?, Ablagevorgang?)" + +#. "The action of storing a new snapshot of the project's state in the git history." +msgid "commit [verb]" +msgstr "übertragen (TortoiseSVN: übertragen; Source Safe: einchecken; senden?, übergeben?, einspielen?, einpflegen?, ablegen?)" + +#. "" +msgid "diff [noun]" +msgstr "Vergleich (Source Safe: Unterschiede)" + +#. "" +msgid "diff [verb]" +msgstr "vergleichen" + +#. "A fast-forward is a special type of merge where you have a revision and you are merging another branch's changes that happen to be a descendant of what you have." +msgid "fast forward merge" +msgstr "Schnellzusammenführung" + +#. "Fetching a branch means to get the branch's head from a remote repository, to find out which objects are missing from the local object database, and to get them, too." +msgid "fetch" +msgstr "anfordern (holen?)" + +#. "A collection of files. The index is a stored version of your working tree." +msgid "index (in git-gui: staging area)" +msgstr "Bereitstellung" + +#. "A successful merge results in the creation of a new commit representing the result of the merge." +msgid "merge [noun]" +msgstr "Zusammenführung" + +#. "To bring the contents of another branch into the current branch." +msgid "merge [verb]" +msgstr "zusammenführen" + +#. "" +msgid "message" +msgstr "Meldung (Nachricht?; Source Safe: Kommentar)" + +#. "Pulling a branch means to fetch it and merge it." +msgid "pull" +msgstr "übernehmen (ziehen?)" + +#. "Pushing a branch means to get the branch's head ref from a remote repository, and ... (well, can someone please explain it for mere mortals?)" +msgid "push" +msgstr "ausliefern (hochladen? verschicken? schieben?)" + +#. "" +msgid "redo" +msgstr "wiederholen" + +#. "A collection of refs (?) together with an object database containing all objects which are reachable from the refs... (oops, you've lost me here. Again, please an explanation for mere mortals?)" +msgid "repository" +msgstr "Projektarchiv" + +#. "" +msgid "reset" +msgstr "zurücksetzen (zurückkehren?)" + +#. "" +msgid "revert" +msgstr "revidieren" + +#. "A particular state of files and directories which was stored in the object database." +msgid "revision" +msgstr "Version (TortoiseSVN: Revision; Source Safe: Version)" + +#. "" +msgid "sign off" +msgstr "abzeichnen (gegenzeichnen?, freizeichnen?, absegnen?)" + +#. "" +msgid "staging area" +msgstr "Bereitstellung" + +#. "" +msgid "status" +msgstr "Status" + +#. "A ref pointing to a tag or commit object" +msgid "tag [noun]" +msgstr "Markierung" + +#. "" +msgid "tag [verb]" +msgstr "markieren" + +#. "A regular git branch that is used to follow changes from another repository." +msgid "tracking branch" +msgstr "Übernahmezweig" + +#. "" +msgid "undo" +msgstr "rückgängig" + +#. "" +msgid "update" +msgstr "aktualisieren" + +#. "" +msgid "verify" +msgstr "überprüfen" + +#. "The tree of actual checked out files." +msgid "working copy, working tree" +msgstr "Arbeitskopie" From b4b093d1109d0a1fd6f20c21751665ee6ca66f9b Mon Sep 17 00:00:00 2001 From: Xudong Guan Date: Wed, 25 Jul 2007 13:47:17 +0100 Subject: [PATCH 0028/1490] git-gui: Added initial version of po/glossary/zh_cn.po with contributions from LI Yang, WANG Cong, ZHANG Le, and rae l from the zh-kernel.org mailing list. Signed-off-by: Johannes Schindelin --- po/glossary/zh_cn.po | 170 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 po/glossary/zh_cn.po diff --git a/po/glossary/zh_cn.po b/po/glossary/zh_cn.po new file mode 100644 index 0000000000..158835b5c1 --- /dev/null +++ b/po/glossary/zh_cn.po @@ -0,0 +1,170 @@ +# Translation of git-gui glossary to Simplified Chinese +# Copyright (C) 2007 Shawn Pearce, et al. +# This file is distributed under the same license as the git package. +# Xudong Guan and the zh-kernel.org mailing list, 2007 +# +msgid "" +msgstr "" +"Project-Id-Version: git-gui glossary\n" +"PO-Revision-Date: 2007-07-23 22:07+0200\n" +"Last-Translator: Xudong Guan \n" +"Language-Team: Simplified Chinese \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. "English Definition (Dear translator: This file will never be visible to the user! It should only serve as a tool for you, the translator. Nothing more.)" +msgid "" +"English Term (Dear translator: This file will never be visible to the user!)" +msgstr "注:这个文件是为了帮助翻译人员统一名词术语。最终用户不会关心这个文件。" + +#. "" +#. amend指用户修改最近一次commit的操作,修订?修改?修正? +#. [WANG Cong]: 根据我的了解,这个词似乎翻译成“修订”多一些。“修正”也可以,“修改”再次之。 +#. [ZHANG Le]: 修订,感觉一般指对一些大型出版物的大规模升级,比如修订新华字典 +# 修正,其实每次amend的结果也不一定就是最后结果,说不定还需要修改。所以不 +# 如就叫修改 +msgid "amend" +msgstr "修订" + +#. "" +#. git annotate 文件名:用来标注文件的每一行在什么时候被谁最后修改。 +#. [WANG Cong]: "标记"一般是mark。;) +#. [ZHANG Le]: 标注,或者干脆用原意:注解,或注释 +msgid "annotate" +msgstr "标注" + +#. "A 'branch' is an active line of development." +msgid "branch [noun]" +msgstr "分支" + +#. "" +msgid "branch [verb]" +msgstr "建立分支" + +#. "" +#. [WANG Cong]: 网上有人翻译成“检出”,我感觉更好一些,毕竟把check的意思翻译出来了。 +#. [ZHNAG Le]: 提取吧,提取分支/版本 +#. [rae l]: 签出。subversion软件中的大多词汇已有翻译,既然git与subversion同是SCM管理,可以参考同类软件的翻译也不错。 +msgid "checkout [noun]" +msgstr "签出" + +#. "The action of updating the working tree to a revision which was stored in the object database." +msgid "checkout [verb]" +msgstr "签出" + +#. "A single point in the git history." +msgid "commit [noun]" +msgstr "提交" + +#. "The action of storing a new snapshot of the project's state in the git history." +msgid "commit [verb]" +msgstr "提交" + +#. "" +#. 差异?差别? +#. [ZHANG Le]: 个人感觉差别更加中性一些 +msgid "diff [noun]" +msgstr "差别" + +#. "" +msgid "diff [verb]" +msgstr "比较" + +#. "A fast-forward is a special type of merge where you have a revision and you are merging another branch's changes that happen to be a descendant of what you have." +msgid "fast forward merge" +msgstr "快进式合并" + +#. "Fetching a branch means to get the branch's head from a remote repository, to find out which objects are missing from the local object database, and to get them, too." +#. 获取?取得?下载?更新?注意和update的区分 +msgid "fetch" +msgstr "获取" + +#. "A collection of files. The index is a stored version of your working tree." +#. index是working tree和repository之间的缓存 +msgid "index (in git-gui: staging area)" +msgstr "工作缓存?" + +#. "A successful merge results in the creation of a new commit representing the result of the merge." +msgid "merge [noun]" +msgstr "合并" + +#. "To bring the contents of another branch into the current branch." +msgid "merge [verb]" +msgstr "合并" + +#. "" +#. message是指commit中的文字信息 +msgid "message" +msgstr "描述" + +#. "Pulling a branch means to fetch it and merge it." +msgid "pull" +msgstr "获取+合并" + +#. "Pushing a branch means to get the branch's head ref from a remote repository, and ... (well, can someone please explain it for mere mortals?)" +msgid "push" +msgstr "推入" + +#. "" +msgid "redo" +msgstr "重做" + +#. "A collection of refs (?) together with an object database containing all objects which are reachable from the refs... (oops, you've lost me here. Again, please an explanation for mere mortals?)" +msgid "repository" +msgstr "仓库" + +#. "" +msgid "reset" +msgstr "重置" + +#. "" +msgid "revert" +msgstr "恢复" + +#. "A particular state of files and directories which was stored in the object database." +msgid "revision" +msgstr "版本" + +#. "" +msgid "sign off" +msgstr "签名" + +#. "" +#. 似乎是git-gui里面显示的本次提交的文件清单区域 +msgid "staging area" +msgstr "提交暂存区" + +#. "" +msgid "status" +msgstr "状态" + +#. "A ref pointing to a tag or commit object" +msgid "tag [noun]" +msgstr "标签" + +#. "" +msgid "tag [verb]" +msgstr "添加标签" + +#. "A regular git branch that is used to follow changes from another repository." +msgid "tracking branch" +msgstr "跟踪分支" + +#. "" +msgid "undo" +msgstr "撤销" + +#. "" +msgid "update" +msgstr "更新。注意和fetch的区分" + +#. "" +msgid "verify" +msgstr "验证" + +#. "The tree of actual checked out files." +#. "工作副本?工作区域?工作目录" +#. [LI Yang]: 当前副本, 当前源码树? +msgid "working copy, working tree" +msgstr "工作副本,工作源码树" From 2ea22555073a1272ba1dc4ecb9968c0f8616e860 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Mon, 3 Sep 2007 00:17:04 -0400 Subject: [PATCH 0029/1490] git-gui: Update po/README as symlink process is not necessary We don't actually need to create the lib/msgs symlink back to our po directory in the source tree. git-gui.sh is smart enough to figure out this is where the msg files are and will load them from the po directory if invoked as git-gui.sh. Signed-off-by: Shawn O. Pearce --- po/README | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/po/README b/po/README index af5dfad8c7..e7cf405247 100644 --- a/po/README +++ b/po/README @@ -130,12 +130,7 @@ resulting git-gui under your locale: $ make install $ LANG=af git-gui -There is a trick to test your translation without first installing, if -you prefer. First, create this symbolic link in the source tree: - - $ ln -s ../po lib/msgs - -After setting up such a symbolic link, you can: +There is a trick to test your translation without first installing: $ make $ LANG=af ./git-gui.sh From b86882eda026a0da18472587034250a53e0daf51 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Mon, 3 Sep 2007 00:22:19 -0400 Subject: [PATCH 0030/1490] git-gui: Correct stock message for 'Invalid font specified in %s' This particular message is talking about a specific option in the configuration file named "gui.$name". This option is not localized so we cannot localize the "gui." that denotes the section the option $name is found within. Currently there are no plans to localize the configuration options for git-gui, but if that were to change in the future then it would be necessary to localize not only the "gui." section prefix but also the $name (fontui and fontdiff). Signed-off-by: Shawn O. Pearce --- git-gui.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git-gui.sh b/git-gui.sh index 913ba68101..5635eeae36 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -1643,7 +1643,7 @@ proc apply_config {} { font configure $font $cn $cv } } err]} { - error_popup [append [mc "Invalid font specified in gui.%s:" $name] "\n\n$err"] + error_popup [append [mc "Invalid font specified in %s:" "gui.$name"] "\n\n$err"] } foreach {cn cv} [font configure $font] { font configure ${font}bold $cn $cv From 87b63de49c04c3e78d37c68b72a6bcbc86724760 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Mon, 3 Sep 2007 00:42:09 -0400 Subject: [PATCH 0031/1490] git-gui: Quiet the msgfmt part of the make process I really prefer having a very short and sweet makefile output that does not flood the user's screen with a ton of commands that they don't care much about. Traditionally git-gui has hidden away the actual commands from output by the $(QUIET*) series of macros but allow them to be seen with either `make QUIET=` or `make V=1`. This change makes our i18n message generation process to be a lot shorter and easier to digest at a glance: GITGUI_VERSION = 0.8.2.19.gb868-dirty * new locations or Tcl/Tk interpreter GEN git-gui BUILTIN git-citool INDEX lib/ MSGFMT po/de.msg 268 translated. MSGFMT po/hu.msg 268 translated. MSGFMT po/it.msg 268 translated. MSGFMT po/ja.msg 268 translated. MSGFMT po/ru.msg 249 translated, 12 fuzzy, 4 untranslated. MSGFMT po/zh_cn.msg 60 translated, 37 fuzzy, 168 untranslated. Signed-off-by: Shawn O. Pearce --- Makefile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 559e65ecd6..875edacac3 100644 --- a/Makefile +++ b/Makefile @@ -47,6 +47,8 @@ ifndef V QUIET_GEN = $(QUIET)echo ' ' GEN $@ && QUIET_BUILT_IN = $(QUIET)echo ' ' BUILTIN $@ && QUIET_INDEX = $(QUIET)echo ' ' INDEX $(dir $@) && + QUIET_MSGFMT0 = $(QUIET)printf ' MSGFMT %12s ' $@ && + QUIET_MSGFMT1 = 2>&1 | sed -e 's/fuzzy translations/fuzzy/' | sed -e 's/ messages//g' QUIET_2DEVNULL = 2>/dev/null INSTALL_D0 = dir= @@ -104,6 +106,7 @@ $(GITGUI_BUILT_INS): git-gui $(QUIET_BUILT_IN)rm -f $@ && ln git-gui $@ XGETTEXT ?= xgettext +MSGFMT ?= msgfmt msgsdir ?= $(libdir)/msgs msgsdir_SQ = $(subst ','\'',$(msgsdir)) PO_TEMPLATE = po/git-gui.pot @@ -115,8 +118,7 @@ $(PO_TEMPLATE): $(SCRIPT_SH) $(ALL_LIBFILES) update-po:: $(PO_TEMPLATE) $(foreach p, $(ALL_POFILES), echo Updating $p ; msgmerge -U $p $(PO_TEMPLATE) ; ) $(ALL_MSGFILES): %.msg : %.po - @echo Generating catalog $@ - msgfmt --statistics --tcl $< -l $(basename $(notdir $<)) -d $(dir $@) + $(QUIET_MSGFMT0)$(MSGFMT) --statistics --tcl $< -l $(basename $(notdir $<)) -d $(dir $@) $(QUIET_MSGFMT1) lib/tclIndex: $(ALL_LIBFILES) $(QUIET_INDEX)if echo \ From 74e528bf44e715774e3a8e0003a6b2b250f4f0b9 Mon Sep 17 00:00:00 2001 From: Michele Ballabio Date: Sun, 2 Sep 2007 14:43:00 +0200 Subject: [PATCH 0032/1490] git-gui: remove dots in some UI strings Dots in a UI string usually mean that a dialog box will appear waiting for further input. So this patch removes unneeded dots for actions that do not require user's input. Signed-off-by: Michele Ballabio Signed-off-by: Shawn O. Pearce --- lib/remote.tcl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/remote.tcl b/lib/remote.tcl index 62bfe8f741..aba6eb8343 100644 --- a/lib/remote.tcl +++ b/lib/remote.tcl @@ -159,7 +159,7 @@ proc populate_fetch_menu {} { if {$enable} { lappend prune_list $r $m add command \ - -label [mc "Fetch from %s..." $r] \ + -label [mc "Fetch from %s" $r] \ -command [list fetch_from $r] } } @@ -169,7 +169,7 @@ proc populate_fetch_menu {} { } foreach r $prune_list { $m add command \ - -label [mc "Prune from %s..." $r] \ + -label [mc "Prune from %s" $r] \ -command [list prune_from $r] } } @@ -203,7 +203,7 @@ proc populate_push_menu {} { $m add separator } $m add command \ - -label [mc "Push to %s..." $r] \ + -label [mc "Push to %s" $r] \ -command [list push_to $r] incr fast_count } From 12fb223326b561132d528bb010c6bdeaa828acd3 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Mon, 3 Sep 2007 18:54:14 -0400 Subject: [PATCH 0033/1490] git-gui: Ensure msgfmt failure stops GNU make If we have a failure executing msgfmt (such as the process just crashes no matter what arguments you supply it because its own installation is borked) we should stop the build process rather than letting it continue along its merry way as if the .msg files were created. Signed-off-by: Shawn O. Pearce --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 875edacac3..df6f6b7275 100644 --- a/Makefile +++ b/Makefile @@ -47,8 +47,8 @@ ifndef V QUIET_GEN = $(QUIET)echo ' ' GEN $@ && QUIET_BUILT_IN = $(QUIET)echo ' ' BUILTIN $@ && QUIET_INDEX = $(QUIET)echo ' ' INDEX $(dir $@) && - QUIET_MSGFMT0 = $(QUIET)printf ' MSGFMT %12s ' $@ && - QUIET_MSGFMT1 = 2>&1 | sed -e 's/fuzzy translations/fuzzy/' | sed -e 's/ messages//g' + QUIET_MSGFMT0 = $(QUIET)printf ' MSGFMT %12s ' $@ && v=` + QUIET_MSGFMT1 = 2>&1` && echo "$$v" | sed -e 's/fuzzy translations/fuzzy/' | sed -e 's/ messages//g' QUIET_2DEVNULL = 2>/dev/null INSTALL_D0 = dir= From f5f3c2e29f51a38261daa91073a3f227d4532325 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Wed, 5 Sep 2007 02:19:56 +1000 Subject: [PATCH 0034/1490] gitk: Make it possible to lay out all the rows we have received so far This arranges things so that we can do the layout all the way up to the last commit that we have received from git log. If we get more commits we re-lay and redisplay (if necessary) the visible rows. Signed-off-by: Paul Mackerras --- gitk | 127 ++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 91 insertions(+), 36 deletions(-) diff --git a/gitk b/gitk index 251e9242b3..a042efe260 100755 --- a/gitk +++ b/gitk @@ -82,11 +82,12 @@ proc dorunq {} { proc start_rev_list {view} { global startmsecs global commfd leftover tclencoding datemode - global viewargs viewfiles commitidx vnextroot + global viewargs viewfiles commitidx viewcomplete vnextroot global lookingforhead showlocalchanges set startmsecs [clock clicks -milliseconds] set commitidx($view) 0 + set viewcomplete($view) 0 set vnextroot($view) 0 set order "--topo-order" if {$datemode} { @@ -148,7 +149,7 @@ proc strrep {n} { proc getcommitlines {fd view} { global commitlisted global leftover commfd - global displayorder commitidx commitrow commitdata + global displayorder commitidx viewcomplete commitrow commitdata global parentlist children curview hlview global vparentlist vdisporder vcmitlisted global ordertok vnextroot idpending @@ -179,6 +180,7 @@ proc getcommitlines {fd view} { lappend vcmitlisted($view) 0 } } + set viewcomplete($view) 1 global viewname unset commfd($view) notbusy $view @@ -310,15 +312,12 @@ proc getcommitlines {fd view} { } proc chewcommits {view} { - global curview hlview commfd + global curview hlview viewcomplete global selectedline pending_select - set more 0 if {$view == $curview} { - set allread [expr {![info exists commfd($view)]}] - set tlimit [expr {[clock clicks -milliseconds] + 50}] - set more [layoutmore $tlimit $allread] - if {$allread && !$more} { + layoutmore + if {$viewcomplete($view)} { global displayorder commitidx phase global numcommits startmsecs @@ -339,7 +338,7 @@ proc chewcommits {view} { if {[info exists hlview] && $view == $hlview} { vhighlightmore } - return $more + return 0 } proc readcommit {id} { @@ -1949,7 +1948,7 @@ proc unflatten {var l} { proc showview {n} { global curview viewdata viewfiles - global displayorder parentlist rowidlist rowisopt + global displayorder parentlist rowidlist rowisopt rowfinal global colormap rowtextx commitrow nextcolor canvxmax global numcommits commitlisted global selectedline currentid canv canvy0 @@ -1985,13 +1984,11 @@ proc showview {n} { set vparentlist($curview) $parentlist set vdisporder($curview) $displayorder set vcmitlisted($curview) $commitlisted - if {$phase ne {}} { + if {$phase ne {} || + ![info exists viewdata($curview)] || + [lindex $viewdata($curview) 0] ne {}} { set viewdata($curview) \ - [list $phase $rowidlist $rowisopt $numcommits] - } elseif {![info exists viewdata($curview)] - || [lindex $viewdata($curview) 0] ne {}} { - set viewdata($curview) \ - [list {} $rowidlist $rowisopt] + [list $phase $rowidlist $rowisopt $rowfinal] } } catch {unset treediffs} @@ -2023,11 +2020,8 @@ proc showview {n} { set commitlisted $vcmitlisted($n) set rowidlist [lindex $v 1] set rowisopt [lindex $v 2] - if {$phase eq {}} { - set numcommits [llength $displayorder] - } else { - set numcommits [lindex $v 3] - } + set rowfinal [lindex $v 3] + set numcommits $commitidx($n) catch {unset colormap} catch {unset rowtextx} @@ -2660,7 +2654,7 @@ proc idcol {idlist id {i 0}} { } proc initlayout {} { - global rowidlist rowisopt displayorder commitlisted + global rowidlist rowisopt rowfinal displayorder commitlisted global numcommits canvxmax canv global nextcolor global parentlist @@ -2674,6 +2668,7 @@ proc initlayout {} { set nextcolor 0 set rowidlist {} set rowisopt {} + set rowfinal {} set canvxmax [$canv cget -width] catch {unset colormap} catch {unset rowtextx} @@ -2708,19 +2703,14 @@ proc visiblerows {} { return [list $r0 $r1] } -proc layoutmore {tmax allread} { - global commitidx numcommits +proc layoutmore {} { + global commitidx viewcomplete numcommits global uparrowlen downarrowlen mingaplen curview set show $commitidx($curview) - if {!$allread} { - set delay [expr {$uparrowlen + $mingaplen + $downarrowlen + 3}] - set show [expr {$show - $delay}] - } if {$show > $numcommits} { - showstuff $show $allread + showstuff $show $viewcomplete($curview) } - return 0 } proc showstuff {canshow last} { @@ -2901,6 +2891,21 @@ proc nextuse {id row} { return -1 } +proc prevuse {id row} { + global commitrow curview children + + set ret -1 + if {[info exists children($curview,$id)]} { + foreach kid $children($curview,$id) { + if {![info exists commitrow($curview,$kid)]} break + if {$commitrow($curview,$kid) < $row} { + set ret $commitrow($curview,$kid) + } + } + } + return $ret +} + proc make_idlist {row} { global displayorder parentlist uparrowlen downarrowlen mingaplen global commitidx curview ordertok children commitrow @@ -2964,11 +2969,42 @@ proc make_idlist {row} { return $idlist } +proc rowsequal {a b} { + while {[set i [lsearch -exact $a {}]] >= 0} { + set a [lreplace $a $i $i] + } + while {[set i [lsearch -exact $b {}]] >= 0} { + set b [lreplace $b $i $i] + } + return [expr {$a eq $b}] +} + +proc makeupline {id row rend col} { + global rowidlist uparrowlen downarrowlen mingaplen + + for {set r $rend} {1} {set r $rstart} { + set rstart [prevuse $id $r] + if {$rstart < 0} return + if {$rstart < $row} break + } + if {$rstart + $uparrowlen + $mingaplen + $downarrowlen < $rend} { + set rstart [expr {$rend - $uparrowlen - 1}] + } + for {set r $rstart} {[incr r] <= $row} {} { + set idlist [lindex $rowidlist $r] + if {$idlist ne {} && [lsearch -exact $idlist $id] < 0} { + set col [idcol $idlist $id $col] + lset rowidlist $r [linsert $idlist $col $id] + changedrow $r + } + } +} + proc layoutrows {row endrow} { - global rowidlist rowisopt displayorder + global rowidlist rowisopt rowfinal displayorder global uparrowlen downarrowlen maxwidth mingaplen global children parentlist - global commitidx curview commitrow + global commitidx viewcomplete curview commitrow set idlist {} if {$row > 0} { @@ -2982,14 +3018,20 @@ proc layoutrows {row endrow} { set rm1 [expr {$row - 1}] if {$rm1 < 0 || [lindex $rowidlist $rm1] eq {}} { set idlist [make_idlist $row] + set final 1 } else { set id [lindex $displayorder $rm1] + set final [lindex $rowfinal $rm1] set col [lsearch -exact $idlist $id] set idlist [lreplace $idlist $col $col] foreach p [lindex $parentlist $rm1] { if {[lsearch -exact $idlist $p] < 0} { set col [idcol $idlist $p $col] set idlist [linsert $idlist $col $p] + # if not the first child, we have to insert a line going up + if {$id ne [lindex $children($curview,$p) 0]} { + makeupline $p $rm1 $row $col + } } } set id [lindex $displayorder $row] @@ -3008,6 +3050,9 @@ proc layoutrows {row endrow} { if {$col < 0} { set col [idcol $idlist $id] set idlist [linsert $idlist $col $id] + if {$children($curview,$id) ne {}} { + makeupline $id $rm1 $row $col + } } set r [expr {$row + $uparrowlen - 1}] if {$r < $commitidx($curview)} { @@ -3032,18 +3077,28 @@ proc layoutrows {row endrow} { } } } + if {$final && !$viewcomplete($curview) && + $row + $uparrowlen + $mingaplen + $downarrowlen + >= $commitidx($curview)} { + set final 0 + } set l [llength $rowidlist] if {$row == $l} { lappend rowidlist $idlist lappend rowisopt 0 + lappend rowfinal $final } elseif {$row < $l} { - if {$idlist ne [lindex $rowidlist $row]} { + if {![rowsequal $idlist [lindex $rowidlist $row]]} { lset rowidlist $row $idlist + lset rowfinal $row $final changedrow $row } } else { - set rowidlist [concat $rowidlist [ntimes [expr {$row - $l}] {}]] + set pad [ntimes [expr {$row - $l}] {}] + set rowidlist [concat $rowidlist $pad] lappend rowidlist $idlist + set rowfinal [concat $rowfinal $pad] + lappend rowfinal $final set rowisopt [concat $rowisopt [ntimes [expr {$row - $l + 1}] 0]] } } @@ -3659,7 +3714,7 @@ proc drawcmitrow {row} { proc drawcommits {row {endrow {}}} { global numcommits iddrawn displayorder curview need_redisplay - global parentlist rowidlist uparrowlen downarrowlen nrows_drawn + global parentlist rowidlist rowfinal uparrowlen downarrowlen nrows_drawn if {$row < 0} { set row 0 @@ -3684,7 +3739,7 @@ proc drawcommits {row {endrow {}}} { set r2 $numcommits } for {set r $rl1} {$r < $r2} {incr r} { - if {[lindex $rowidlist $r] ne {}} { + if {[lindex $rowidlist $r] ne {} && [lindex $rowfinal $r]} { if {$rl1 < $r} { layoutrows $rl1 $r } From 93716a62c07561467a5c6fb0e14c4897cf264e7e Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Mon, 10 Sep 2007 00:40:46 -0400 Subject: [PATCH 0035/1490] git-gui: Mark revision chooser tooltip for translation Someone on #git today pointed out that the revision chooser's tooltips are were being drawn with untranslated strings for the fixed labels we include, such as "updated", "commit" and "remote". These strings are now passed through mc to allow them to be localized. Signed-off-by: Shawn O. Pearce --- lib/choose_rev.tcl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/choose_rev.tcl b/lib/choose_rev.tcl index a58b752cdd..8c78b4dd7b 100644 --- a/lib/choose_rev.tcl +++ b/lib/choose_rev.tcl @@ -527,14 +527,14 @@ method _open_tooltip {} { set last [_reflog_last $this [lindex $spec 1]] if {$last ne {}} { $tooltip_t insert end "\n" - $tooltip_t insert end "updated" + $tooltip_t insert end [mc "Updated"] $tooltip_t insert end " $last" } $tooltip_t insert end "\n" if {$tag ne {}} { $tooltip_t insert end "\n" - $tooltip_t insert end "tag" section_header + $tooltip_t insert end [mc "Tag"] section_header $tooltip_t insert end " [lindex $tag 1]\n" $tooltip_t insert end [lindex $tag 2] $tooltip_t insert end " ([lindex $tag 3])\n" @@ -544,7 +544,7 @@ method _open_tooltip {} { if {$cmit ne {}} { $tooltip_t insert end "\n" - $tooltip_t insert end "commit" section_header + $tooltip_t insert end [mc "Commit"] section_header $tooltip_t insert end " [lindex $cmit 1]\n" $tooltip_t insert end [lindex $cmit 2] $tooltip_t insert end " ([lindex $cmit 3])\n" @@ -553,11 +553,11 @@ method _open_tooltip {} { if {[llength $spec] > 2} { $tooltip_t insert end "\n" - $tooltip_t insert end "remote" section_header + $tooltip_t insert end [mc "Remote"] section_header $tooltip_t insert end " [lindex $spec 2]\n" - $tooltip_t insert end "url" + $tooltip_t insert end [mc "URL"] $tooltip_t insert end " $remote_url([lindex $spec 2])\n" - $tooltip_t insert end "branch" + $tooltip_t insert end [mc "Branch"] $tooltip_t insert end " [lindex $spec 3]" } From 66c75a5c9f7434d857d836440dc1c3046c59b5f3 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Mon, 10 Sep 2007 01:54:16 -0400 Subject: [PATCH 0036/1490] git-gui: Localize commit/author dates when displaying them Currently the Git plumbing is not localized so it does not know how to output weekday and month names that conform to the user's locale preferences. This doesn't fit with the rest of git-gui's UI as some of our dates are formatted in Tcl and some are just read from the Git plumbing so dates aren't consistently presented. Since git-for-each-ref is presenting us formatted dates and it offers no way to change that setting even in git 1.5.3.1 we need to first do a parse of the text strings it produces, correct for timezones, then reformat the timestamp using Tcl's formatting routines. Not exactly what I wanted to do but it gets us consistently presented date strings in areas like the blame viewer and the revision picker mega-widget's tooltips. Signed-off-by: Shawn O. Pearce --- lib/blame.tcl | 20 ++++------------- lib/choose_rev.tcl | 6 +++--- lib/date.tcl | 53 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 19 deletions(-) create mode 100644 lib/date.tcl diff --git a/lib/blame.tcl b/lib/blame.tcl index b5fdad5643..352aa19421 100644 --- a/lib/blame.tcl +++ b/lib/blame.tcl @@ -743,20 +743,14 @@ method _showcommit {cur_w lno} { set author_time {} catch {set author_name $header($cmit,author)} catch {set author_email $header($cmit,author-mail)} - catch {set author_time [clock format \ - $header($cmit,author-time) \ - -format {%Y-%m-%d %H:%M:%S} - ]} + catch {set author_time [format_date $header($cmit,author-time)]} set committer_name {} set committer_email {} set committer_time {} catch {set committer_name $header($cmit,committer)} catch {set committer_email $header($cmit,committer-mail)} - catch {set committer_time [clock format \ - $header($cmit,committer-time) \ - -format {%Y-%m-%d %H:%M:%S} - ]} + catch {set committer_time [format_date $header($cmit,committer-time)]} if {[catch {set msg $header($cmit,message)}]} { set msg {} @@ -892,10 +886,7 @@ method _open_tooltip {cur_w} { set author_time {} catch {set author_name $header($cmit,author)} catch {set summary $header($cmit,summary)} - catch {set author_time [clock format \ - $header($cmit,author-time) \ - -format {%Y-%m-%d %H:%M:%S} - ]} + catch {set author_time [format_date $header($cmit,author-time)]} $tooltip_t insert end "commit $cmit\n" $tooltip_t insert end "$author_name $author_time\n" @@ -914,10 +905,7 @@ method _open_tooltip {cur_w} { set author_time {} catch {set author_name $header($cmit,author)} catch {set summary $header($cmit,summary)} - catch {set author_time [clock format \ - $header($cmit,author-time) \ - -format {%Y-%m-%d %H:%M:%S} - ]} + catch {set author_time [foramt_date $header($cmit,author-time)]} $tooltip_t insert end "Originally By:\n" section_header $tooltip_t insert end "commit $cmit\n" diff --git a/lib/choose_rev.tcl b/lib/choose_rev.tcl index 8c78b4dd7b..a6a442ae1d 100644 --- a/lib/choose_rev.tcl +++ b/lib/choose_rev.tcl @@ -133,13 +133,13 @@ constructor _new {path unmerged_only title} { append fmt { %(objecttype)} append fmt { %(objectname)} append fmt { [concat %(taggername) %(authorname)]} - append fmt { [concat %(taggerdate) %(authordate)]} + append fmt { [reformat_date [concat %(taggerdate) %(authordate)]]} append fmt { %(subject)} append fmt {] [list} append fmt { %(*objecttype)} append fmt { %(*objectname)} append fmt { %(*authorname)} - append fmt { %(*authordate)} + append fmt { [reformat_date %(*authordate)]} append fmt { %(*subject)} append fmt {]} set all_refn [list] @@ -583,7 +583,7 @@ method _reflog_last {name} { } if {$last ne {}} { - set last [clock format $last -format {%a %b %e %H:%M:%S %Y}] + set last [format_date $last] } set reflog_last($name) $last return $last diff --git a/lib/date.tcl b/lib/date.tcl new file mode 100644 index 0000000000..abe82992b6 --- /dev/null +++ b/lib/date.tcl @@ -0,0 +1,53 @@ +# git-gui date processing support +# Copyright (C) 2007 Shawn Pearce + +set git_month(Jan) 1 +set git_month(Feb) 2 +set git_month(Mar) 3 +set git_month(Apr) 4 +set git_month(May) 5 +set git_month(Jun) 6 +set git_month(Jul) 7 +set git_month(Aug) 8 +set git_month(Sep) 9 +set git_month(Oct) 10 +set git_month(Nov) 11 +set git_month(Dec) 12 + +proc parse_git_date {s} { + if {$s eq {}} { + return {} + } + + if {![regexp \ + {^... (...) (\d{1,2}) (\d\d):(\d\d):(\d\d) (\d{4}) ([+-]?)(\d\d)(\d\d)$} $s s \ + month day hr mm ss yr ew tz_h tz_m]} { + error [mc "Invalid date from Git: %s" $s] + } + + set s [clock scan [format {%4.4i%2.2i%2.2iT%2s%2s%2s} \ + $yr $::git_month($month) $day \ + $hr $mm $ss] \ + -gmt 1] + + regsub ^0 $tz_h {} tz_h + regsub ^0 $tz_m {} tz_m + switch -- $ew { + - {set ew +} + + {set ew -} + {} {set ew -} + } + + return [expr "$s $ew ($tz_h * 3600 + $tz_m * 60)"] +} + +proc format_date {s} { + if {$s eq {}} { + return {} + } + return [clock format $s -format {%a %b %e %H:%M:%S %Y}] +} + +proc reformat_date {s} { + return [format_date [parse_git_date $s]] +} From 146d73a365c3a1c2e61e646a929a5168ffb2810c Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Wed, 12 Sep 2007 16:47:06 -0400 Subject: [PATCH 0037/1490] git-gui: Support context-sensitive i18n Ocassionally, one would want to translate the same string used in different contexts in diffrent ways. This patch provides a wrapper for msgcat::mc that trims "@@" and anything coming after it, whether or not the string actually got translated. Proposed-by: Harri Ilari Tapio Liusvaara Signed-off-by: Shawn O. Pearce --- git-gui.sh | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/git-gui.sh b/git-gui.sh index afee777f1c..d00758e95a 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -86,7 +86,16 @@ if {![catch {set _verbose $env(GITGUI_VERBOSE)}]} { ## http://www.gnu.org/software/gettext/manual/html_node/Tcl.html package require msgcat -namespace import ::msgcat::mc + +proc mc {fmt args} { + set fmt [::msgcat::mc $fmt] + set cmk [string first @@ $fmt] + if {$cmk > 0} { + set fmt [string range $fmt 0 [expr {$cmk - 1}]] + } + return [eval [list format $fmt] $args] +} + ::msgcat::mcload $oguimsg unset oguimsg From a9813cb51d4f64e93e2a028a2b749d70e378a8a0 Mon Sep 17 00:00:00 2001 From: Harri Ilari Tapio Liusvaara Date: Wed, 12 Sep 2007 23:02:35 +0300 Subject: [PATCH 0038/1490] git-gui: Disambiguate "commit" Commit is used as both verb and noun. While these happen to be the same in some languages, they are not the same in all languages, so disambiguate them using context-sensitive i18n. Signed-off-by: Harri Ilari Tapio Liusvaara Signed-off-by: Shawn O. Pearce --- git-gui.sh | 8 ++++---- lib/choose_rev.tcl | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/git-gui.sh b/git-gui.sh index d00758e95a..a4e2ad2fd7 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -10,7 +10,7 @@ set appvers {@@GITGUI_VERSION@@} set copyright { -Copyright 2006, 2007 Shawn Pearce, et. al. +Copyright © 2006, 2007 Shawn Pearce, et. al. 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 @@ -1704,7 +1704,7 @@ if {[is_enabled branch]} { .mbar add cascade -label [mc Branch] -menu .mbar.branch } if {[is_enabled multicommit] || [is_enabled singlecommit]} { - .mbar add cascade -label [mc Commit] -menu .mbar.commit + .mbar add cascade -label [mc Commit@@noun] -menu .mbar.commit } if {[is_enabled transport]} { .mbar add cascade -label [mc Merge] -menu .mbar.merge @@ -1891,7 +1891,7 @@ if {[is_enabled multicommit] || [is_enabled singlecommit]} { -command do_signoff \ -accelerator $M1T-S - .mbar.commit add command -label [mc Commit] \ + .mbar.commit add command -label [mc Commit@@verb] \ -command do_commit \ -accelerator $M1T-Return lappend disable_on_lock \ @@ -2207,7 +2207,7 @@ button .vpane.lower.commarea.buttons.signoff -text [mc "Sign Off"] \ -command do_signoff pack .vpane.lower.commarea.buttons.signoff -side top -fill x -button .vpane.lower.commarea.buttons.commit -text [mc Commit] \ +button .vpane.lower.commarea.buttons.commit -text [mc Commit@@verb] \ -command do_commit pack .vpane.lower.commarea.buttons.commit -side top -fill x lappend disable_on_lock \ diff --git a/lib/choose_rev.tcl b/lib/choose_rev.tcl index a6a442ae1d..5e833a5376 100644 --- a/lib/choose_rev.tcl +++ b/lib/choose_rev.tcl @@ -544,7 +544,7 @@ method _open_tooltip {} { if {$cmit ne {}} { $tooltip_t insert end "\n" - $tooltip_t insert end [mc "Commit"] section_header + $tooltip_t insert end [mc "Commit@@noun"] section_header $tooltip_t insert end " [lindex $cmit 1]\n" $tooltip_t insert end [lindex $cmit 2] $tooltip_t insert end " ([lindex $cmit 3])\n" From 262360f3aa11291816d63fb6d23851db1ae5ff27 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Wed, 12 Sep 2007 17:03:27 -0400 Subject: [PATCH 0039/1490] git-gui: Document the new i18n context support Translators working on po files will likely need to know what the @@noun and @@verb parts are in the original message text, and why these are different messages in the po files. Signed-off-by: Shawn O. Pearce --- po/README | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/po/README b/po/README index e7cf405247..9d8b7364fd 100644 --- a/po/README +++ b/po/README @@ -88,6 +88,15 @@ matching msgid lines. A few tips: you would typically want to have corresponding ones in the string on your msgstr line. + - Some messages contain an optional context indicator at the end, + for example "@@noun" or "@@verb". This indicator allows the + software to select the correct translation depending upon the use. + The indicator is not actually part of the message and will not + be shown to the end-user. + + If your language does not require a different translation you + will still need to translate both messages. + - Often the messages being translated are format strings given to "printf()"-like functions. Make sure "%s", "%d", and "%%" in your translated messages match the original. From c8c4854bec30b03b8e3a56a9b5e52ff358210140 Mon Sep 17 00:00:00 2001 From: Michele Ballabio Date: Thu, 13 Sep 2007 15:19:05 +0200 Subject: [PATCH 0040/1490] git-gui: add some strings to translation Most of these changes were suggested by Shawn Pearce in an answer to Johannes Schindelin. Some strings for the blame module were added too. [sp: Minor edits in blame module formatting] Signed-off-by: Michele Ballabio Signed-off-by: Shawn O. Pearce --- git-gui.sh | 30 +++++++++++++++--------------- lib/blame.tcl | 24 ++++++++++++------------ lib/checkout_op.tcl | 6 +++--- lib/commit.tcl | 4 ++-- lib/database.tcl | 6 +++--- lib/diff.tcl | 8 ++++---- lib/index.tcl | 4 ++-- lib/remote_branch_delete.tcl | 4 ++-- 8 files changed, 43 insertions(+), 43 deletions(-) diff --git a/git-gui.sh b/git-gui.sh index a4e2ad2fd7..2d7a2a82ca 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -37,7 +37,7 @@ if {[catch {package require Tcl 8.4} err] tk_messageBox \ -icon error \ -type ok \ - -title "git-gui: fatal error" \ + -title [mc "git-gui: fatal error"] \ -message $err exit 1 } @@ -526,7 +526,7 @@ if {[catch {set _git_version [git --version]} err]} { tk_messageBox \ -icon error \ -type ok \ - -title "git-gui: fatal error" \ + -title [mc "git-gui: fatal error"] \ -message "Cannot determine Git version: $err @@ -539,7 +539,7 @@ if {![regsub {^git version } $_git_version {} _git_version]} { tk_messageBox \ -icon error \ -type ok \ - -title "git-gui: fatal error" \ + -title [mc "git-gui: fatal error"] \ -message [append [mc "Cannot parse Git version string:"] "\n\n$_git_version"] exit 1 } @@ -621,7 +621,7 @@ if {[git-version < 1.5]} { tk_messageBox \ -icon error \ -type ok \ - -title "git-gui: fatal error" \ + -title [mc "git-gui: fatal error"] \ -message "[appname] requires Git 1.5.0 or later. You are using [git-version]: @@ -640,7 +640,7 @@ if {[catch {set fd [open $idx r]} err]} { tk_messageBox \ -icon error \ -type ok \ - -title "git-gui: fatal error" \ + -title [mc "git-gui: fatal error"] \ -message $err exit 1 } @@ -737,7 +737,7 @@ if {$_prefix ne {}} { regsub -all {[^/]+/} $_prefix ../ cdup if {[catch {cd $cdup} err]} { catch {wm withdraw .} - error_popup "Cannot move to top of working directory:\n\n$err" + error_popup [append [mc "Cannot move to top of working directory:"] "\n\n$err"] exit 1 } unset cdup @@ -2077,7 +2077,7 @@ blame { } blame { if {$head eq {} && ![file exists $path]} { - puts stderr "fatal: cannot stat path $path: No such file or directory" + puts stderr [mc "fatal: cannot stat path %s: No such file or directory" $path] exit 1 } blame::new $head $path @@ -2588,13 +2588,13 @@ focus -force $ui_comm if {[is_Cygwin]} { set ignored_env 0 set suggest_user {} - set msg "Possible environment issues exist. + set msg [mc "Possible environment issues exist. The following environment variables are probably going to be ignored by any Git subprocess run -by [appname]: +by %s: -" +" [appname]] foreach name [array names env] { switch -regexp -- $name { {^GIT_INDEX_FILE$} - @@ -2618,18 +2618,18 @@ by [appname]: } } if {$ignored_env > 0} { - append msg " + append msg [mc " This is due to a known issue with the -Tcl binary distributed by Cygwin." +Tcl binary distributed by Cygwin."] if {$suggest_user ne {}} { - append msg " + append msg [mc " -A good replacement for $suggest_user +A good replacement for %s is placing values for the user.name and user.email settings into your personal ~/.gitconfig file. -" +" $suggest_user] } warn_popup $msg } diff --git a/lib/blame.tcl b/lib/blame.tcl index 352aa19421..d14805e929 100644 --- a/lib/blame.tcl +++ b/lib/blame.tcl @@ -470,7 +470,7 @@ method _read_file {fd jump} { _exec_blame $this $w_asim @asim_data \ [list] \ - { copy/move tracking} + [mc "Loading copy/move tracking annotations..."] } } ifdeleted { catch {close $fd} } @@ -489,8 +489,8 @@ method _exec_blame {cur_w cur_d options cur_s} { set blame_lines 0 $status start \ - "Loading$cur_s annotations..." \ - {lines annotated} + $cur_s \ + [mc "lines annotated"] } method _read_blame {fd cur_w cur_d} { @@ -671,10 +671,10 @@ method _read_blame {fd cur_w cur_d} { if {$cur_w eq $w_asim} { _exec_blame $this $w_amov @amov_data \ $original_options \ - { original location} + [mc "Loading original location annotations..."] } else { set current_fd {} - $status stop {Annotation complete.} + $status stop [mc "Annotation complete."] } } else { $status update $blame_lines $total_lines @@ -728,7 +728,7 @@ method _showcommit {cur_w lno} { if {$dat eq {}} { set cmit {} - $w_cviewer insert end "Loading annotation..." still_loading + $w_cviewer insert end [mc "Loading annotation..."] still_loading } else { set cmit [lindex $dat 0] set file [lindex $dat 1] @@ -784,16 +784,16 @@ method _showcommit {cur_w lno} { } $w_cviewer insert end "commit $cmit\n" header_key - $w_cviewer insert end "Author:\t" header_key + $w_cviewer insert end [append [mc "Author:"] "\t"] header_key $w_cviewer insert end "$author_name $author_email" header_val $w_cviewer insert end " $author_time\n" header_val - $w_cviewer insert end "Committer:\t" header_key + $w_cviewer insert end [append [mc "Committer:"] "\t"] header_key $w_cviewer insert end "$committer_name $committer_email" header_val $w_cviewer insert end " $committer_time\n" header_val if {$file ne $path} { - $w_cviewer insert end "Original File:\t" header_key + $w_cviewer insert end [append [mc "Original File:"] "\t"] header_key $w_cviewer insert end "[escape_path $file]\n" header_val } @@ -907,18 +907,18 @@ method _open_tooltip {cur_w} { catch {set summary $header($cmit,summary)} catch {set author_time [foramt_date $header($cmit,author-time)]} - $tooltip_t insert end "Originally By:\n" section_header + $tooltip_t insert end [append [mc "Originally By:"] "\n"] section_header $tooltip_t insert end "commit $cmit\n" $tooltip_t insert end "$author_name $author_time\n" $tooltip_t insert end "$summary\n" if {$file ne $path} { - $tooltip_t insert end "In File: " section_header + $tooltip_t insert end [append [mc "In File:"] " "] section_header $tooltip_t insert end "$file\n" } $tooltip_t insert end "\n" - $tooltip_t insert end "Copied Or Moved Here By:\n" section_header + $tooltip_t insert end [append [mc "Copied Or Moved Here By:"] "\n"] section_header $tooltip_t insert end $save } diff --git a/lib/checkout_op.tcl b/lib/checkout_op.tcl index f07262ca00..a011044f90 100644 --- a/lib/checkout_op.tcl +++ b/lib/checkout_op.tcl @@ -124,7 +124,7 @@ method _finish_fetch {ok} { } if {[catch {set new_hash [git rev-parse --verify "$l_trck^0"]} err]} { set ok 0 - $w_cons insert "fatal: Cannot resolve $l_trck" + $w_cons insert [mc "fatal: Cannot resolve %s" $l_trck] $w_cons insert $err } } @@ -319,7 +319,7 @@ method _readtree {} { set readtree_d {} $::main_status start \ - "Updating working directory to '[_name $this]'..." \ + [mc "Updating working directory to '%s'..." [_name $this]] \ {files checked out} set fd [git_read --stderr read-tree \ @@ -443,7 +443,7 @@ If you wanted to be on a branch, create one now starting from 'This Detached Che $ui_comm delete 0.0 end $ui_comm edit reset $ui_comm edit modified false - rescan [list ui_status "Checked out '$name'."] + rescan [list ui_status [mc "Checked out '%s'." $name]] } else { repository_state commit_type HEAD MERGE_HEAD set PARENT $HEAD diff --git a/lib/commit.tcl b/lib/commit.tcl index 15489c616b..a037c4f7d0 100644 --- a/lib/commit.tcl +++ b/lib/commit.tcl @@ -272,7 +272,7 @@ proc commit_committree {fd_wt curHEAD msg} { && [string length $old_tree] == 45} { set old_tree [string range $old_tree 5 end] } else { - error "Commit $PARENT appears to be corrupt" + error [mc "Commit %s appears to be corrupt" $PARENT] } if {$tree_id eq $old_tree} { @@ -300,7 +300,7 @@ A rescan will be automatically started now. if {$use_enc ne {}} { fconfigure $msg_wt -encoding $use_enc } else { - puts stderr "warning: Tcl does not support encoding '$enc'." + puts stderr [mc "warning: Tcl does not support encoding '%s'." $enc] fconfigure $msg_wt -encoding utf-8 } puts -nonewline $msg_wt $msg diff --git a/lib/database.tcl b/lib/database.tcl index 118b1b29ab..d66aa3fe33 100644 --- a/lib/database.tcl +++ b/lib/database.tcl @@ -105,11 +105,11 @@ proc hint_gc {} { set objects_current [expr {$objects_current * 256}] set object_limit [expr {$object_limit * 256}] if {[ask_popup \ - "This repository currently has approximately $objects_current loose objects. + [mc "This repository currently has approximately %i loose objects. -To maintain optimal performance it is strongly recommended that you compress the database when more than $object_limit loose objects exist. +To maintain optimal performance it is strongly recommended that you compress the database when more than %i loose objects exist. -Compress the database now?"] eq yes} { +Compress the database now?" $objects_current $object_limit]] eq yes} { do_gc } } diff --git a/lib/diff.tcl b/lib/diff.tcl index d013409640..c2ae4555fe 100644 --- a/lib/diff.tcl +++ b/lib/diff.tcl @@ -78,7 +78,7 @@ proc show_diff {path w {lno {}}} { set current_diff_path $path set current_diff_side $w set current_diff_header {} - ui_status "Loading diff of [escape_path $path]..." + ui_status [mc "Loading diff of %s..." [escape_path $path]] # - Git won't give us the diff, there's nothing to compare to! # @@ -111,7 +111,7 @@ proc show_diff {path w {lno {}}} { } err ]} { set diff_active 0 unlock_index - ui_status "Unable to display [escape_path $path]" + ui_status [mc "Unable to display %s" [escape_path $path]] error_popup [append [mc "Error loading file:"] "\n\n$err"] return } @@ -131,7 +131,7 @@ proc show_diff {path w {lno {}}} { } if {[string first "\0" $content] != -1} { $ui_diff insert end \ - "* Binary file (not showing content)." \ + [mc "* Binary file (not showing content)."] \ d_@ } else { if {$sz > $max_sz} { @@ -181,7 +181,7 @@ proc show_diff {path w {lno {}}} { if {[catch {set fd [eval git_read --nice $cmd]} err]} { set diff_active 0 unlock_index - ui_status "Unable to display [escape_path $path]" + ui_status [mc "Unable to display %s" [escape_path $path]] error_popup [append [mc "Error loading diff:"] "\n\n$err"] return } diff --git a/lib/index.tcl b/lib/index.tcl index 228bccfd82..47255261d2 100644 --- a/lib/index.tcl +++ b/lib/index.tcl @@ -268,7 +268,7 @@ proc do_unstage_selection {} { [array names selected_paths] } elseif {$current_diff_path ne {}} { unstage_helper \ - "Unstaging [short_path $current_diff_path] from commit" \ + [mc "Unstaging %s from commit" [short_path $current_diff_path]] \ [list $current_diff_path] } } @@ -312,7 +312,7 @@ proc do_add_selection {} { [array names selected_paths] } elseif {$current_diff_path ne {}} { add_helper \ - "Adding [short_path $current_diff_path]" \ + [mc "Adding %s" [short_path $current_diff_path]] \ [list $current_diff_path] } } diff --git a/lib/remote_branch_delete.tcl b/lib/remote_branch_delete.tcl index 06b5eabf91..c7b8148698 100644 --- a/lib/remote_branch_delete.tcl +++ b/lib/remote_branch_delete.tcl @@ -181,9 +181,9 @@ method _delete {} { } if {$not_merged ne {}} { - set msg "The following branches are not completely merged into $check_head: + set msg [mc "The following branches are not completely merged into %s: - - [join $not_merged "\n - "]" + - %s" $check_head [join $not_merged "\n - "]] if {$need_fetch} { append msg "\n\n" [mc "One or more of the merge tests failed because you have not fetched the necessary commits. Try fetching from %s first." $uri] From bba060462c8732a5cb46ea00165198a9579517ae Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Thu, 13 Sep 2007 20:52:34 -0400 Subject: [PATCH 0041/1490] git-gui: Make the tree browser also use lightgray selection In 9adccb05 Matthijs Melchior changed our selection colors in the main index/working directory file lists to use a lightgray as the background color as this made the UI easier to read on all platforms. When we did that change we missed doing also doing in the file browser UI. Doing so just makes the entire thing UI consistent. Signed-off-by: Shawn O. Pearce --- lib/browser.tcl | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/browser.tcl b/lib/browser.tcl index 987622933c..3ba5c3a1fa 100644 --- a/lib/browser.tcl +++ b/lib/browser.tcl @@ -47,9 +47,7 @@ constructor new {commit {path {}}} { -width 70 \ -xscrollcommand [list $w.list.sbx set] \ -yscrollcommand [list $w.list.sby set] - $w_list tag conf in_sel \ - -background [$w_list cget -foreground] \ - -foreground [$w_list cget -background] + $w_list tag conf in_sel -background lightgray scrollbar $w.list.sbx -orient h -command [list $w_list xview] scrollbar $w.list.sby -orient v -command [list $w_list yview] pack $w.list.sbx -side bottom -fill x From 31bb1d1b2d1e893836b0d2b091fed9e39ee84853 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 14 Sep 2007 01:50:09 -0400 Subject: [PATCH 0042/1490] git-gui: Paper bag fix missing translated strings The Tcl expression "[append [mc Foo] Bar]" does not return the string "FooBar" after translation; instead it is setting the variable Foo to the value Bar, or if Foo is already defined it is appending Bar onto the end of it. This is *not* what we wanted to have happen here. Tcl's join function is actually the correct function but its default joinStr argument is a single space. Unfortunately all of our call sites do not want an extra space added to their string. So we need a small wrapper function to make the call to join with an empty join string. In C this is (roughly) the job of the strcat function. Since strcat is not yet used at the global level it is a reasonable name to use here. Signed-off-by: Shawn O. Pearce --- git-gui.sh | 18 +++++++++++------- lib/blame.tcl | 12 ++++++------ lib/branch_rename.tcl | 2 +- lib/checkout_op.tcl | 6 +++--- lib/choose_rev.tcl | 2 +- lib/commit.tcl | 12 ++++++------ lib/diff.tcl | 4 ++-- lib/option.tcl | 2 +- lib/shortcut.tcl | 6 +++--- 9 files changed, 34 insertions(+), 30 deletions(-) diff --git a/git-gui.sh b/git-gui.sh index 2d7a2a82ca..4682487ade 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -96,6 +96,10 @@ proc mc {fmt args} { return [eval [list format $fmt] $args] } +proc strcat {args} { + return [join $args {}] +} + ::msgcat::mcload $oguimsg unset oguimsg @@ -540,7 +544,7 @@ if {![regsub {^git version } $_git_version {} _git_version]} { -icon error \ -type ok \ -title [mc "git-gui: fatal error"] \ - -message [append [mc "Cannot parse Git version string:"] "\n\n$_git_version"] + -message [strcat [mc "Cannot parse Git version string:"] "\n\n$_git_version"] exit 1 } @@ -722,7 +726,7 @@ if {[catch { set _prefix [git rev-parse --show-prefix] } err]} { catch {wm withdraw .} - error_popup [append [mc "Cannot find the git directory:"] "\n\n$err"] + error_popup [strcat [mc "Cannot find the git directory:"] "\n\n$err"] exit 1 } if {![file isdirectory $_gitdir] && [is_Cygwin]} { @@ -730,26 +734,26 @@ if {![file isdirectory $_gitdir] && [is_Cygwin]} { } if {![file isdirectory $_gitdir]} { catch {wm withdraw .} - error_popup [append [mc "Git directory not found:"] "\n\n$_gitdir"] + error_popup [strcat [mc "Git directory not found:"] "\n\n$_gitdir"] exit 1 } if {$_prefix ne {}} { regsub -all {[^/]+/} $_prefix ../ cdup if {[catch {cd $cdup} err]} { catch {wm withdraw .} - error_popup [append [mc "Cannot move to top of working directory:"] "\n\n$err"] + error_popup [strcat [mc "Cannot move to top of working directory:"] "\n\n$err"] exit 1 } unset cdup } elseif {![is_enabled bare]} { if {[lindex [file split $_gitdir] end] ne {.git}} { catch {wm withdraw .} - error_popup [append [mc "Cannot use funny .git directory:"] "\n\n$_gitdir"] + error_popup [strcat [mc "Cannot use funny .git directory:"] "\n\n$_gitdir"] exit 1 } if {[catch {cd [file dirname $_gitdir]} err]} { catch {wm withdraw .} - error_popup [append [mc "No working directory"] " [file dirname $_gitdir]:\n\n$err"] + error_popup [strcat [mc "No working directory"] " [file dirname $_gitdir]:\n\n$err"] exit 1 } } @@ -1658,7 +1662,7 @@ proc apply_config {} { font configure $font $cn $cv } } err]} { - error_popup [append [mc "Invalid font specified in %s:" "gui.$name"] "\n\n$err"] + error_popup [strcat [mc "Invalid font specified in %s:" "gui.$name"] "\n\n$err"] } foreach {cn cv} [font configure $font] { font configure ${font}bold $cn $cv diff --git a/lib/blame.tcl b/lib/blame.tcl index d14805e929..a911c3c77d 100644 --- a/lib/blame.tcl +++ b/lib/blame.tcl @@ -784,16 +784,16 @@ method _showcommit {cur_w lno} { } $w_cviewer insert end "commit $cmit\n" header_key - $w_cviewer insert end [append [mc "Author:"] "\t"] header_key + $w_cviewer insert end [strcat [mc "Author:"] "\t"] header_key $w_cviewer insert end "$author_name $author_email" header_val $w_cviewer insert end " $author_time\n" header_val - $w_cviewer insert end [append [mc "Committer:"] "\t"] header_key + $w_cviewer insert end [strcat [mc "Committer:"] "\t"] header_key $w_cviewer insert end "$committer_name $committer_email" header_val $w_cviewer insert end " $committer_time\n" header_val if {$file ne $path} { - $w_cviewer insert end [append [mc "Original File:"] "\t"] header_key + $w_cviewer insert end [strcat [mc "Original File:"] "\t"] header_key $w_cviewer insert end "[escape_path $file]\n" header_val } @@ -907,18 +907,18 @@ method _open_tooltip {cur_w} { catch {set summary $header($cmit,summary)} catch {set author_time [foramt_date $header($cmit,author-time)]} - $tooltip_t insert end [append [mc "Originally By:"] "\n"] section_header + $tooltip_t insert end [strcat [mc "Originally By:"] "\n"] section_header $tooltip_t insert end "commit $cmit\n" $tooltip_t insert end "$author_name $author_time\n" $tooltip_t insert end "$summary\n" if {$file ne $path} { - $tooltip_t insert end [append [mc "In File:"] " "] section_header + $tooltip_t insert end [strcat [mc "In File:"] " "] section_header $tooltip_t insert end "$file\n" } $tooltip_t insert end "\n" - $tooltip_t insert end [append [mc "Copied Or Moved Here By:"] "\n"] section_header + $tooltip_t insert end [strcat [mc "Copied Or Moved Here By:"] "\n"] section_header $tooltip_t insert end $save } diff --git a/lib/branch_rename.tcl b/lib/branch_rename.tcl index d6f040e7a2..166538808f 100644 --- a/lib/branch_rename.tcl +++ b/lib/branch_rename.tcl @@ -114,7 +114,7 @@ method _rename {} { -type ok \ -title [wm title $w] \ -parent $w \ - -message [append [mc "Failed to rename '%s'." $oldname] "\n\n$err"] + -message [strcat [mc "Failed to rename '%s'." $oldname] "\n\n$err"] return } diff --git a/lib/checkout_op.tcl b/lib/checkout_op.tcl index a011044f90..f243966924 100644 --- a/lib/checkout_op.tcl +++ b/lib/checkout_op.tcl @@ -236,7 +236,7 @@ method _update_ref {} { if {[catch { git update-ref -m $reflog_msg $ref $new $cur } err]} { - _error $this [append [mc "Failed to update '%s'." $newbranch] "\n\n$err"] + _error $this [strcat [mc "Failed to update '%s'." $newbranch] "\n\n$err"] return 0 } } @@ -351,7 +351,7 @@ method _readtree_wait {fd} { set err $readtree_d regsub {^fatal: } $err {} err $::main_status stop [mc "Aborted checkout of '%s' (file level merging is required)." [_name $this]] - warn_popup [append [mc "File level merge required."] " + warn_popup [strcat [mc "File level merge required."] " $err @@ -575,7 +575,7 @@ method _toplevel {title} { } method _fatal {err} { - error_popup [append [mc "Failed to set current branch. + error_popup [strcat [mc "Failed to set current branch. This working directory is only partially switched. We successfully updated your files, but failed to update an internal Git file. diff --git a/lib/choose_rev.tcl b/lib/choose_rev.tcl index 5e833a5376..a063c5bc49 100644 --- a/lib/choose_rev.tcl +++ b/lib/choose_rev.tcl @@ -314,7 +314,7 @@ method commit_or_die {} { } set top [winfo toplevel $w] - set msg [append [mc "Invalid revision: %s" [get $this]] "\n\n$err"] + set msg [strcat [mc "Invalid revision: %s" [get $this]] "\n\n$err"] tk_messageBox \ -icon error \ -type ok \ diff --git a/lib/commit.tcl b/lib/commit.tcl index a037c4f7d0..7099f5c6f7 100644 --- a/lib/commit.tcl +++ b/lib/commit.tcl @@ -46,7 +46,7 @@ You are currently in the middle of a merge that has not been fully completed. Y } set msg [string trim $msg] } err]} { - error_popup [append [mc "Error loading commit data for amend:"] "\n\n$err"] + error_popup [strcat [mc "Error loading commit data for amend:"] "\n\n$err"] return } @@ -73,12 +73,12 @@ proc committer_ident {} { if {$GIT_COMMITTER_IDENT eq {}} { if {[catch {set me [git var GIT_COMMITTER_IDENT]} err]} { - error_popup [append [mc "Unable to obtain your identity:"] "\n\n$err"] + error_popup [strcat [mc "Unable to obtain your identity:"] "\n\n$err"] return {} } if {![regexp {^(.*) [0-9]+ [-+0-9]+$} \ $me me GIT_COMMITTER_IDENT]} { - error_popup [append [mc "Invalid GIT_COMMITTER_IDENT:"] "\n\n$me"] + error_popup [strcat [mc "Invalid GIT_COMMITTER_IDENT:"] "\n\n$me"] return {} } } @@ -254,7 +254,7 @@ proc commit_committree {fd_wt curHEAD msg} { gets $fd_wt tree_id if {$tree_id eq {} || [catch {close $fd_wt} err]} { - error_popup [append [mc "write-tree failed:"] "\n\n$err"] + error_popup [strcat [mc "write-tree failed:"] "\n\n$err"] ui_status {Commit failed.} unlock_index return @@ -314,7 +314,7 @@ A rescan will be automatically started now. } lappend cmd <$msg_p if {[catch {set cmt_id [eval git $cmd]} err]} { - error_popup [append [mc "commit-tree failed:"] "\n\n$err"] + error_popup [strcat [mc "commit-tree failed:"] "\n\n$err"] ui_status {Commit failed.} unlock_index return @@ -336,7 +336,7 @@ A rescan will be automatically started now. if {[catch { git update-ref -m $reflogm HEAD $cmt_id $curHEAD } err]} { - error_popup [append [mc "update-ref failed:"] "\n\n$err"] + error_popup [strcat [mc "update-ref failed:"] "\n\n$err"] ui_status {Commit failed.} unlock_index return diff --git a/lib/diff.tcl b/lib/diff.tcl index c2ae4555fe..43565e412f 100644 --- a/lib/diff.tcl +++ b/lib/diff.tcl @@ -112,7 +112,7 @@ proc show_diff {path w {lno {}}} { set diff_active 0 unlock_index ui_status [mc "Unable to display %s" [escape_path $path]] - error_popup [append [mc "Error loading file:"] "\n\n$err"] + error_popup [strcat [mc "Error loading file:"] "\n\n$err"] return } $ui_diff conf -state normal @@ -182,7 +182,7 @@ proc show_diff {path w {lno {}}} { set diff_active 0 unlock_index ui_status [mc "Unable to display %s" [escape_path $path]] - error_popup [append [mc "Error loading diff:"] "\n\n$err"] + error_popup [strcat [mc "Error loading diff:"] "\n\n$err"] return } diff --git a/lib/option.tcl b/lib/option.tcl index 03bc08f128..12e297971a 100644 --- a/lib/option.tcl +++ b/lib/option.tcl @@ -308,7 +308,7 @@ proc do_restore_defaults {} { proc do_save_config {w} { if {[catch {save_config} err]} { - error_popup [append [mc "Failed to completely save options:"] "\n\n$err"] + error_popup [strcat [mc "Failed to completely save options:"] "\n\n$err"] } reshow_diff destroy $w diff --git a/lib/shortcut.tcl b/lib/shortcut.tcl index d0e63a3d0e..a7674a7aee 100644 --- a/lib/shortcut.tcl +++ b/lib/shortcut.tcl @@ -23,7 +23,7 @@ proc do_windows_shortcut {} { puts $fd " \"[file normalize $argv0]\"" close $fd } err]} { - error_popup [append [mc "Cannot write script:"] "\n\n$err"] + error_popup [strcat [mc "Cannot write script:"] "\n\n$err"] } } } @@ -71,7 +71,7 @@ proc do_cygwin_shortcut {} { puts $fd " &\"" close $fd } err]} { - error_popup [append [mc "Cannot write script:"] "\n\n$err"] + error_popup [strcat [mc "Cannot write script:"] "\n\n$err"] } } } @@ -146,7 +146,7 @@ proc do_macosx_app {} { file attributes $exe -permissions u+x,g+x,o+x } err]} { - error_popup [append [mc "Cannot write icon:"] "\n\n$err"] + error_popup [strcat [mc "Cannot write icon:"] "\n\n$err"] } } } From f56782aef4b3d7339461d8f12ff15f6258d9871d Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sat, 15 Sep 2007 09:04:11 +1000 Subject: [PATCH 0043/1490] gitk: Fix bugs in setting rowfinal We weren't updating the rowfinal list in insertrow and removerow, so it was getting out of sync with rowidlist, which resulted in Tcl errors. This also optimizes the setting of rowfinal in layoutrows a bit. Signed-off-by: Paul Mackerras --- gitk | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/gitk b/gitk index a042efe260..fd6bbab3ed 100755 --- a/gitk +++ b/gitk @@ -3008,20 +3008,21 @@ proc layoutrows {row endrow} { set idlist {} if {$row > 0} { - foreach id [lindex $rowidlist [expr {$row - 1}]] { + set rm1 [expr {$row - 1}] + foreach id [lindex $rowidlist $rm1] { if {$id ne {}} { lappend idlist $id } } + set final [lindex $rowfinal $rm1] } for {} {$row < $endrow} {incr row} { set rm1 [expr {$row - 1}] - if {$rm1 < 0 || [lindex $rowidlist $rm1] eq {}} { + if {$rm1 < 0 || $idlist eq {}} { set idlist [make_idlist $row] set final 1 } else { set id [lindex $displayorder $rm1] - set final [lindex $rowfinal $rm1] set col [lsearch -exact $idlist $id] set idlist [lreplace $idlist $col $col] foreach p [lindex $parentlist $rm1] { @@ -3090,9 +3091,9 @@ proc layoutrows {row endrow} { } elseif {$row < $l} { if {![rowsequal $idlist [lindex $rowidlist $row]]} { lset rowidlist $row $idlist - lset rowfinal $row $final changedrow $row } + lset rowfinal $row $final } else { set pad [ntimes [expr {$row - $l}] {}] set rowidlist [concat $rowidlist $pad] @@ -4055,7 +4056,7 @@ proc show_status {msg} { # on that row and below will move down one row. proc insertrow {row newcmit} { global displayorder parentlist commitlisted children - global commitrow curview rowidlist rowisopt numcommits + global commitrow curview rowidlist rowisopt rowfinal numcommits global numcommits global selectedline commitidx ordertok @@ -4089,6 +4090,7 @@ proc insertrow {row newcmit} { } set rowidlist [linsert $rowidlist $row $idlist] set rowisopt [linsert $rowisopt $row 0] + set rowfinal [linsert $rowfinal $row [lindex $rowfinal $row]] incr numcommits @@ -4101,7 +4103,7 @@ proc insertrow {row newcmit} { # Remove a commit that was inserted with insertrow on row $row. proc removerow {row} { global displayorder parentlist commitlisted children - global commitrow curview rowidlist rowisopt numcommits + global commitrow curview rowidlist rowisopt rowfinal numcommits global numcommits global linesegends selectedline commitidx @@ -4130,6 +4132,7 @@ proc removerow {row} { set rowidlist [lreplace $rowidlist $row $row] set rowisopt [lreplace $rowisopt $row $row] + set rowfinal [lreplace $rowfinal $row $row] incr numcommits -1 From 3e6b893f33476e7969c7bd5b8914e8bcc62385e3 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sat, 15 Sep 2007 09:33:39 +1000 Subject: [PATCH 0044/1490] gitk: Get rid of lookingforhead, use commitinterest instead Now that we have a general-purpose way of taking some action when a commit ID of interest is encountered, use that for triggering the git diff-index process when we find the currently checked-out head, rather than the special-purpose lookingforhead variable. Also do the commitinterest processing in getcommitlines rather than in showstuff. Signed-off-by: Paul Mackerras --- gitk | 42 +++++++++++++++++------------------------- 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/gitk b/gitk index fd6bbab3ed..85d33abf4a 100755 --- a/gitk +++ b/gitk @@ -83,7 +83,7 @@ proc start_rev_list {view} { global startmsecs global commfd leftover tclencoding datemode global viewargs viewfiles commitidx viewcomplete vnextroot - global lookingforhead showlocalchanges + global showlocalchanges commitinterest mainheadid set startmsecs [clock clicks -milliseconds] set commitidx($view) 0 @@ -102,7 +102,9 @@ proc start_rev_list {view} { } set commfd($view) $fd set leftover($view) {} - set lookingforhead $showlocalchanges + if {$showlocalchanges} { + lappend commitinterest($mainheadid) {dodiffindex} + } fconfigure $fd -blocking 0 -translation lf -eofchar {} if {$tclencoding != {}} { fconfigure $fd -encoding $tclencoding @@ -147,7 +149,7 @@ proc strrep {n} { } proc getcommitlines {fd view} { - global commitlisted + global commitlisted commitinterest global leftover commfd global displayorder commitidx viewcomplete commitrow commitdata global parentlist children curview hlview @@ -303,6 +305,12 @@ proc getcommitlines {fd view} { lappend vdisporder($view) $id lappend vcmitlisted($view) $listed } + if {[info exists commitinterest($id)]} { + foreach script $commitinterest($id) { + eval [string map [list "%I" $id] $script] + } + unset commitinterest($id) + } set gotsome 1 } if {$gotsome} { @@ -2715,7 +2723,7 @@ proc layoutmore {} { proc showstuff {canshow last} { global numcommits commitrow pending_select selectedline curview - global lookingforhead mainheadid displayorder selectfirst + global mainheadid displayorder selectfirst global lastscrollset commitinterest if {$numcommits == 0} { @@ -2723,15 +2731,6 @@ proc showstuff {canshow last} { set phase "incrdraw" allcanvs delete all } - for {set l $numcommits} {$l < $canshow} {incr l} { - set id [lindex $displayorder $l] - if {[info exists commitinterest($id)]} { - foreach script $commitinterest($id) { - eval [string map [list "%I" $id] $script] - } - unset commitinterest($id) - } - } set r0 $numcommits set prev $numcommits set numcommits $canshow @@ -2762,28 +2761,22 @@ proc showstuff {canshow last} { set selectfirst 0 } } - if {$lookingforhead && [info exists commitrow($curview,$mainheadid)] - && ($last || $commitrow($curview,$mainheadid) < $numcommits - 1)} { - set lookingforhead 0 - dodiffindex - } } proc doshowlocalchanges {} { - global lookingforhead curview mainheadid phase commitrow + global curview mainheadid phase commitrow if {[info exists commitrow($curview,$mainheadid)] && ($phase eq {} || $commitrow($curview,$mainheadid) < $numcommits - 1)} { dodiffindex } elseif {$phase ne {}} { - set lookingforhead 1 + lappend commitinterest($mainheadid) {} } } proc dohidelocalchanges {} { - global lookingforhead localfrow localirow lserial + global localfrow localirow lserial - set lookingforhead 0 if {$localfrow >= 0} { removerow $localfrow set localfrow -1 @@ -2800,8 +2793,9 @@ proc dohidelocalchanges {} { # spawn off a process to do git diff-index --cached HEAD proc dodiffindex {} { - global localirow localfrow lserial + global localirow localfrow lserial showlocalchanges + if {!$showlocalchanges} return incr lserial set localfrow -1 set localirow -1 @@ -6188,7 +6182,6 @@ proc cherrypick {} { proc resethead {} { global mainheadid mainhead rowmenuid confirm_ok resettype - global showlocalchanges set confirm_ok 0 set w ".confirmreset" @@ -8249,7 +8242,6 @@ set cmdlineok 0 set stopped 0 set stuffsaved 0 set patchnum 0 -set lookingforhead 0 set localirow -1 set localfrow -1 set lserial 0 From d372e21613b36d94d595f6627ec603ed11e2fd65 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sat, 15 Sep 2007 12:08:38 +1000 Subject: [PATCH 0045/1490] gitk: Fix bug in generating patches Commit 8f4893639129acfc866c71583317090aa2a46eab changed mkpatchgo to use diffcmd rather than constructing the diff command itself. Unfortunately diffcmd returns the command with a "|" as the first element (ready for use with open), but exec won't accept the "|". Thus we need to remove the "|". Signed-off-by: Paul Mackerras --- gitk | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gitk b/gitk index 85d33abf4a..d5db836528 100755 --- a/gitk +++ b/gitk @@ -5920,6 +5920,8 @@ proc mkpatchgo {} { set newid [$patchtop.tosha1 get] set fname [$patchtop.fname get] set cmd [diffcmd [list $oldid $newid] -p] + # trim off the initial "|" + set cmd [lrange $cmd 1 end] lappend cmd >$fname & if {[catch {eval exec $cmd} err]} { error_popup "Error creating patch: $err" From bc9e7399af3790918140c30a5b2c85bf9a8f1ad3 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 8 Jul 2007 01:38:32 -0700 Subject: [PATCH 0046/1490] stash: implement "stash create" This subcommand creates a stash from the current state and writes out the resulting commit object ID to the standard output, without updating the stash ref nor resetting the tree. It is intended to be used by scripts to temporarily rewind the working tree to a clean state. Signed-off-by: Junio C Hamano --- git-stash.sh | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/git-stash.sh b/git-stash.sh index 7ba61625ba..04af892531 100755 --- a/git-stash.sh +++ b/git-stash.sh @@ -25,19 +25,13 @@ clear_stash () { fi } -save_stash () { +create_stash () { stash_msg="$1" if no_changes then - echo >&2 'No local changes to save' exit 0 fi - test -f "$GIT_DIR/logs/$ref_stash" || - clear_stash || die "Cannot initialize stash" - - # Make sure the reflog for stash is kept. - : >>"$GIT_DIR/logs/$ref_stash" # state of the base commit if b_commit=$(git rev-parse --verify HEAD) @@ -84,7 +78,20 @@ save_stash () { w_commit=$(printf '%s\n' "$stash_msg" | git commit-tree $w_tree -p $b_commit -p $i_commit) || die "Cannot record working tree state" +} +save_stash () { + stash_msg="$1" + + if no_changes + then + echo >&2 'No local changes to save' + exit 0 + fi + test -f "$GIT_DIR/logs/$ref_stash" || + clear_stash || die "Cannot initialize stash" + + create_stash "$stash_msg" git update-ref -m "$stash_msg" $ref_stash $w_commit || die "Cannot save the current status" printf >&2 'Saved "%s"\n' "$stash_msg" @@ -202,6 +209,13 @@ apply) clear) clear_stash ;; +create) + if test $# -gt 0 && test "$1" = create + then + shift + fi + create_stash "$*" && echo "$w_commit" + ;; help | usage) usage ;; From 6c9ad166dbbf9e5a0c09450b892151dbec49b8dc Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 9 Jul 2007 00:51:23 -0700 Subject: [PATCH 0047/1490] rebase: allow starting from a dirty tree. This uses the new "git stash create" interface to stash away the dirty state you have in your working tree before starting a rebase, and then replaying it when you are done with stashing. Signed-off-by: Junio C Hamano --- git-rebase.sh | 72 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 58 insertions(+), 14 deletions(-) diff --git a/git-rebase.sh b/git-rebase.sh index c9942f2400..e342974dc0 100755 --- a/git-rebase.sh +++ b/git-rebase.sh @@ -116,10 +116,30 @@ call_merge () { } finish_rb_merge () { + if test -f "$dotest/stash" + then + stash=$(cat "$dotest/stash") + git stash apply --index "$stash" + fi rm -r "$dotest" echo "All done." } +read_stash () { + if test -f "$1" + then + cat "$1" + fi +} +unstash_and_exit () { + err=$? + if test -f "$1" && test $err = 0 + then + git stash apply --index "$1" + fi + exit $err +} + is_interactive () { test -f "$dotest"/interactive || while case $#,"$1" in 0,|*,-i|*,--interactive) break ;; esac @@ -154,8 +174,9 @@ do finish_rb_merge exit fi + stash=$(read_stash ".dotest/stash") git am --resolved --3way --resolvemsg="$RESOLVEMSG" - exit + unstash_and_exit "$stash" ;; --skip) if test -d "$dotest" @@ -174,21 +195,31 @@ do finish_rb_merge exit fi + stash=$(read_stash ".dotest/stash") git am -3 --skip --resolvemsg="$RESOLVEMSG" - exit + unstash_and_exit "$stash" ;; --abort) git rerere clear if test -d "$dotest" then + if test -f "$dotest/stash" + then + stash=$(cat "$dotest/stash") + fi rm -r "$dotest" elif test -d .dotest then + if test -f ".dotest/stash" + then + stash=$(cat ".dotest/stash") + fi rm -r .dotest else die "No rebase in progress?" fi git reset --hard ORIG_HEAD + test -z "$stash" || git stash apply --index "$stash" exit ;; --onto) @@ -254,16 +285,6 @@ else fi fi -# The tree must be really really clean. -git update-index --refresh || exit -diff=$(git diff-index --cached --name-status -r HEAD) -case "$diff" in -?*) echo "cannot rebase: your index is not up-to-date" - echo "$diff" - exit 1 - ;; -esac - # The upstream head must be given. Make sure it is valid. upstream_name="$1" upstream=`git rev-parse --verify "${upstream_name}^0"` || @@ -273,11 +294,19 @@ upstream=`git rev-parse --verify "${upstream_name}^0"` || onto_name=${newbase-"$upstream_name"} onto=$(git rev-parse --verify "${onto_name}^0") || exit +# The tree must be clean enough for us to create a stash +stash=$(git stash create) || exit +if test -n "$stash" +then + echo >&2 "Stashed away your working tree changes" +fi + # If a hook exists, give it a chance to interrupt if test -x "$GIT_DIR/hooks/pre-rebase" then "$GIT_DIR/hooks/pre-rebase" ${1+"$@"} || { echo >&2 "The pre-rebase hook refused to rebase." + test -z "$stash" || git stash apply --index "$stash" exit 1 } fi @@ -286,7 +315,10 @@ fi case "$#" in 2) branch_name="$2" - git-checkout "$2" || usage + git-checkout "$2" || { + test -z "$stash" || git stash apply --index "$stash" + usage + } ;; *) if branch_name=`git symbolic-ref -q HEAD` @@ -309,6 +341,7 @@ if test "$upstream" = "$onto" && test "$mb" = "$onto" && ! git rev-list --parents "$onto".."$branch" | grep " .* " > /dev/null then echo >&2 "Current branch $branch_name is up to date." + test -z "$stash" || git stash apply --index "$stash" exit 0 fi @@ -328,6 +361,7 @@ git-reset --hard "$onto" if test "$mb" = "$branch" then echo >&2 "Fast-forwarded $branch_name to $onto_name." + test -z "$stash" || git stash apply --index "$stash" exit 0 fi @@ -335,7 +369,16 @@ if test -z "$do_merge" then git format-patch -k --stdout --full-index --ignore-if-in-upstream "$upstream"..ORIG_HEAD | git am $git_am_opt --binary -3 -k --resolvemsg="$RESOLVEMSG" - exit $? + err=$? + + if test $err = 0 + then + test -z "$stash" || git stash apply --index "$stash" + exit + else + test -z "$stash" || echo "$stash" >.dotest/stash + exit $err + fi fi # start doing a rebase with git-merge @@ -346,6 +389,7 @@ echo "$onto" > "$dotest/onto" echo "$onto_name" > "$dotest/onto_name" prev_head=`git rev-parse HEAD^0` echo "$prev_head" > "$dotest/prev_head" +test -z "$stash" || echo "$stash" >"$dotest/stash" msgnum=0 for cmt in `git rev-list --reverse --no-merges "$upstream"..ORIG_HEAD` From 45c1741235a1fbd54484fa1c67ea68569dcfa23e Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Mon, 10 Sep 2007 23:02:28 -0400 Subject: [PATCH 0048/1490] Refactor http.h USE_CURL_MULTI fill_active_slots(). This removes all of the boilerplate and http-internal stuff from fill_active_slots() and makes it easy to turn into a callback. Signed-off-by: Daniel Barkalow Signed-off-by: Junio C Hamano --- http-fetch.c | 23 +++++++---------------- http-push.c | 23 ++++++----------------- http.c | 24 ++++++++++++++++++++++++ http.h | 9 +++------ 4 files changed, 40 insertions(+), 39 deletions(-) diff --git a/http-fetch.c b/http-fetch.c index 202fae0ba8..e9b9f307f8 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -317,30 +317,21 @@ static void release_object_request(struct object_request *obj_req) } #ifdef USE_CURL_MULTI -void fill_active_slots(void) +int fill_active_slot(void) { - struct object_request *obj_req = object_queue_head; - struct active_request_slot *slot = active_queue_head; - int num_transfers; + struct object_request *obj_req; - while (active_requests < max_requests && obj_req != NULL) { + for (obj_req = object_queue_head; obj_req; obj_req = obj_req->next) { if (obj_req->state == WAITING) { if (has_sha1_file(obj_req->sha1)) obj_req->state = COMPLETE; - else + else { start_object_request(obj_req); - curl_multi_perform(curlm, &num_transfers); + return 1; + } } - obj_req = obj_req->next; - } - - while (slot != NULL) { - if (!slot->in_use && slot->curl != NULL) { - curl_easy_cleanup(slot->curl); - slot->curl = NULL; - } - slot = slot->next; } + return 0; } #endif diff --git a/http-push.c b/http-push.c index 7c3720f602..c7471fa11d 100644 --- a/http-push.c +++ b/http-push.c @@ -795,38 +795,27 @@ static void finish_request(struct transfer_request *request) } #ifdef USE_CURL_MULTI -void fill_active_slots(void) +int fill_active_slot(void) { struct transfer_request *request = request_queue_head; - struct transfer_request *next; - struct active_request_slot *slot = active_queue_head; - int num_transfers; if (aborted) - return; + return 0; - while (active_requests < max_requests && request != NULL) { - next = request->next; + for (request = request_queue_head; request; request = request->next) { if (request->state == NEED_FETCH) { start_fetch_loose(request); + return 1; } else if (pushing && request->state == NEED_PUSH) { if (remote_dir_exists[request->obj->sha1[0]] == 1) { start_put(request); } else { start_mkcol(request); } - curl_multi_perform(curlm, &num_transfers); + return 1; } - request = next; - } - - while (slot != NULL) { - if (!slot->in_use && slot->curl != NULL) { - curl_easy_cleanup(slot->curl); - slot->curl = NULL; - } - slot = slot->next; } + return 0; } #endif diff --git a/http.c b/http.c index c6fb8ace9f..1f305bd355 100644 --- a/http.c +++ b/http.c @@ -372,6 +372,7 @@ int start_active_slot(struct active_request_slot *slot) { #ifdef USE_CURL_MULTI CURLMcode curlm_result = curl_multi_add_handle(curlm, slot->curl); + int num_transfers; if (curlm_result != CURLM_OK && curlm_result != CURLM_CALL_MULTI_PERFORM) { @@ -379,11 +380,34 @@ int start_active_slot(struct active_request_slot *slot) slot->in_use = 0; return 0; } + + /* + * We know there must be something to do, since we just added + * something. + */ + curl_multi_perform(curlm, &num_transfers); #endif return 1; } #ifdef USE_CURL_MULTI +void fill_active_slots(void) +{ + struct active_request_slot *slot = active_queue_head; + + while (active_requests < max_requests) + if (!fill_active_slot()) + break; + + while (slot != NULL) { + if (!slot->in_use && slot->curl != NULL) { + curl_easy_cleanup(slot->curl); + slot->curl = NULL; + } + slot = slot->next; + } +} + void step_active_slots(void) { int num_transfers; diff --git a/http.h b/http.h index 69b6b667d9..559105cc03 100644 --- a/http.h +++ b/http.h @@ -71,6 +71,9 @@ extern void release_active_slot(struct active_request_slot *slot); #ifdef USE_CURL_MULTI extern void fill_active_slots(void); extern void step_active_slots(void); + +/* Provided by the program using http. */ +extern int fill_active_slot(void); #endif extern void http_init(void); @@ -79,10 +82,6 @@ extern void http_cleanup(void); extern int data_received; extern int active_requests; -#ifdef USE_CURL_MULTI -extern int max_requests; -extern CURLM *curlm; -#endif #ifndef NO_CURL_EASY_DUPHANDLE extern CURL *curl_default; #endif @@ -103,6 +102,4 @@ extern long curl_low_speed_time; extern struct curl_slist *pragma_header; extern struct curl_slist *no_range_header; -extern struct active_request_slot *active_queue_head; - #endif /* HTTP_H */ From fc57b6aaa5bc59ecbe0c052b98196a93b35760a5 Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Mon, 10 Sep 2007 23:02:34 -0400 Subject: [PATCH 0049/1490] Make function to refill http queue a callback This eliminates the last function provided by the code using http.h as a global symbol, so it should be possible to have multiple programs using http.h in the same executable, and it also adds an argument to that callback, so that info can be passed into the callback without being global. Signed-off-by: Daniel Barkalow Signed-off-by: Junio C Hamano --- http-fetch.c | 6 +++++- http-push.c | 3 ++- http.c | 30 ++++++++++++++++++++++++++++-- http.h | 4 +--- 4 files changed, 36 insertions(+), 7 deletions(-) diff --git a/http-fetch.c b/http-fetch.c index e9b9f307f8..7786110ffc 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -317,7 +317,7 @@ static void release_object_request(struct object_request *obj_req) } #ifdef USE_CURL_MULTI -int fill_active_slot(void) +static int fill_active_slot(void *unused) { struct object_request *obj_req; @@ -1035,6 +1035,10 @@ int main(int argc, const char **argv) alt->packs = NULL; alt->next = NULL; +#ifdef USE_CURL_MULTI + add_fill_function(NULL, fill_active_slot); +#endif + if (pull(commits, commit_id, write_ref, url)) rc = 1; diff --git a/http-push.c b/http-push.c index c7471fa11d..c54230b6f3 100644 --- a/http-push.c +++ b/http-push.c @@ -795,7 +795,7 @@ static void finish_request(struct transfer_request *request) } #ifdef USE_CURL_MULTI -int fill_active_slot(void) +static int fill_active_slot(void *unused) { struct transfer_request *request = request_queue_head; @@ -2496,6 +2496,7 @@ int main(int argc, char **argv) objects_to_send); #ifdef USE_CURL_MULTI fill_active_slots(); + add_fill_function(NULL, fill_active_slot); #endif finish_all_active_slots(); diff --git a/http.c b/http.c index 1f305bd355..a95483be8b 100644 --- a/http.c +++ b/http.c @@ -391,13 +391,39 @@ int start_active_slot(struct active_request_slot *slot) } #ifdef USE_CURL_MULTI +struct fill_chain { + void *data; + int (*fill)(void *); + struct fill_chain *next; +}; + +static struct fill_chain *fill_cfg = NULL; + +void add_fill_function(void *data, int (*fill)(void *)) +{ + struct fill_chain *new = malloc(sizeof(*new)); + struct fill_chain **linkp = &fill_cfg; + new->data = data; + new->fill = fill; + new->next = NULL; + while (*linkp) + linkp = &(*linkp)->next; + *linkp = new; +} + void fill_active_slots(void) { struct active_request_slot *slot = active_queue_head; - while (active_requests < max_requests) - if (!fill_active_slot()) + while (active_requests < max_requests) { + struct fill_chain *fill; + for (fill = fill_cfg; fill; fill = fill->next) + if (fill->fill(fill->data)) + break; + + if (!fill) break; + } while (slot != NULL) { if (!slot->in_use && slot->curl != NULL) { diff --git a/http.h b/http.h index 559105cc03..72abac20f8 100644 --- a/http.h +++ b/http.h @@ -70,10 +70,8 @@ extern void release_active_slot(struct active_request_slot *slot); #ifdef USE_CURL_MULTI extern void fill_active_slots(void); +extern void add_fill_function(void *data, int (*fill)(void *)); extern void step_active_slots(void); - -/* Provided by the program using http. */ -extern int fill_active_slot(void); #endif extern void http_init(void); From fbdeef948bbc085124f9634d5108940dce5fc688 Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Mon, 10 Sep 2007 23:02:40 -0400 Subject: [PATCH 0050/1490] Remove obsolete commit-walkers Removes the commit-walkers that are no longer useful, as well as library code that was only used by ssh-fetch/push. Signed-off-by: Daniel Barkalow Signed-off-by: Junio C Hamano --- Makefile | 20 +--- local-fetch.c | 254 -------------------------------------------------- rsh.c | 83 ----------------- rsh.h | 7 -- ssh-fetch.c | 166 --------------------------------- ssh-pull.c | 4 - ssh-push.c | 4 - ssh-upload.c | 143 ---------------------------- 8 files changed, 4 insertions(+), 677 deletions(-) delete mode 100644 local-fetch.c delete mode 100644 rsh.c delete mode 100644 rsh.h delete mode 100644 ssh-fetch.c delete mode 100644 ssh-pull.c delete mode 100644 ssh-push.c delete mode 100644 ssh-upload.c diff --git a/Makefile b/Makefile index 0055eef24d..520f156f34 100644 --- a/Makefile +++ b/Makefile @@ -234,14 +234,14 @@ SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \ # ... and all the rest that could be moved out of bindir to gitexecdir PROGRAMS = \ git-convert-objects$X git-fetch-pack$X \ - git-hash-object$X git-index-pack$X git-local-fetch$X \ + git-hash-object$X git-index-pack$X \ git-fast-import$X \ git-daemon$X \ git-merge-index$X git-mktag$X git-mktree$X git-patch-id$X \ git-peek-remote$X git-receive-pack$X \ git-send-pack$X git-shell$X \ - git-show-index$X git-ssh-fetch$X \ - git-ssh-upload$X git-unpack-file$X \ + git-show-index$X \ + git-unpack-file$X \ git-update-server-info$X \ git-upload-pack$X \ git-pack-redundant$X git-var$X \ @@ -269,9 +269,6 @@ ifndef NO_TCLTK OTHER_PROGRAMS += gitk-wish endif -# Backward compatibility -- to be removed after 1.0 -PROGRAMS += git-ssh-pull$X git-ssh-push$X - # Set paths to tools early so that they can be used for version tests. ifndef SHELL_PATH SHELL_PATH = /bin/sh @@ -894,14 +891,6 @@ endif git-%$X: %.o $(GITLIBS) $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS) -ssh-pull.o: ssh-fetch.c -ssh-push.o: ssh-upload.c -git-local-fetch$X: fetch.o -git-ssh-fetch$X: rsh.o fetch.o -git-ssh-upload$X: rsh.o -git-ssh-pull$X: rsh.o fetch.o -git-ssh-push$X: rsh.o - git-imap-send$X: imap-send.o $(LIB_FILE) http.o http-fetch.o http-push.o: http.h @@ -1122,8 +1111,7 @@ check-docs:: git-merge-octopus | git-merge-ours | git-merge-recursive | \ git-merge-resolve | git-merge-stupid | \ git-add--interactive | git-fsck-objects | git-init-db | \ - git-repo-config | git-fetch--tool | \ - git-ssh-pull | git-ssh-push ) continue ;; \ + git-repo-config | git-fetch--tool ) continue ;; \ esac ; \ test -f "Documentation/$$v.txt" || \ echo "no doc: $$v"; \ diff --git a/local-fetch.c b/local-fetch.c deleted file mode 100644 index bf7ec6c2a3..0000000000 --- a/local-fetch.c +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Copyright (C) 2005 Junio C Hamano - */ -#include "cache.h" -#include "commit.h" -#include "fetch.h" - -static int use_link; -static int use_symlink; -static int use_filecopy = 1; -static int commits_on_stdin; - -static const char *path; /* "Remote" git repository */ - -void prefetch(unsigned char *sha1) -{ -} - -static struct packed_git *packs; - -static void setup_index(unsigned char *sha1) -{ - struct packed_git *new_pack; - char filename[PATH_MAX]; - strcpy(filename, path); - strcat(filename, "/objects/pack/pack-"); - strcat(filename, sha1_to_hex(sha1)); - strcat(filename, ".idx"); - new_pack = parse_pack_index_file(sha1, filename); - new_pack->next = packs; - packs = new_pack; -} - -static int setup_indices(void) -{ - DIR *dir; - struct dirent *de; - char filename[PATH_MAX]; - unsigned char sha1[20]; - sprintf(filename, "%s/objects/pack/", path); - dir = opendir(filename); - if (!dir) - return -1; - while ((de = readdir(dir)) != NULL) { - int namelen = strlen(de->d_name); - if (namelen != 50 || - !has_extension(de->d_name, ".pack")) - continue; - get_sha1_hex(de->d_name + 5, sha1); - setup_index(sha1); - } - closedir(dir); - return 0; -} - -static int copy_file(const char *source, char *dest, const char *hex, - int warn_if_not_exists) -{ - safe_create_leading_directories(dest); - if (use_link) { - if (!link(source, dest)) { - pull_say("link %s\n", hex); - return 0; - } - /* If we got ENOENT there is no point continuing. */ - if (errno == ENOENT) { - if (!warn_if_not_exists) - return -1; - return error("does not exist %s", source); - } - } - if (use_symlink) { - struct stat st; - if (stat(source, &st)) { - if (!warn_if_not_exists && errno == ENOENT) - return -1; - return error("cannot stat %s: %s", source, - strerror(errno)); - } - if (!symlink(source, dest)) { - pull_say("symlink %s\n", hex); - return 0; - } - } - if (use_filecopy) { - int ifd, ofd, status = 0; - - ifd = open(source, O_RDONLY); - if (ifd < 0) { - if (!warn_if_not_exists && errno == ENOENT) - return -1; - return error("cannot open %s", source); - } - ofd = open(dest, O_WRONLY | O_CREAT | O_EXCL, 0666); - if (ofd < 0) { - close(ifd); - return error("cannot open %s", dest); - } - status = copy_fd(ifd, ofd); - close(ofd); - if (status) - return error("cannot write %s", dest); - pull_say("copy %s\n", hex); - return 0; - } - return error("failed to copy %s with given copy methods.", hex); -} - -static int fetch_pack(const unsigned char *sha1) -{ - struct packed_git *target; - char filename[PATH_MAX]; - if (setup_indices()) - return -1; - target = find_sha1_pack(sha1, packs); - if (!target) - return error("Couldn't find %s: not separate or in any pack", - sha1_to_hex(sha1)); - if (get_verbosely) { - fprintf(stderr, "Getting pack %s\n", - sha1_to_hex(target->sha1)); - fprintf(stderr, " which contains %s\n", - sha1_to_hex(sha1)); - } - sprintf(filename, "%s/objects/pack/pack-%s.pack", - path, sha1_to_hex(target->sha1)); - copy_file(filename, sha1_pack_name(target->sha1), - sha1_to_hex(target->sha1), 1); - sprintf(filename, "%s/objects/pack/pack-%s.idx", - path, sha1_to_hex(target->sha1)); - copy_file(filename, sha1_pack_index_name(target->sha1), - sha1_to_hex(target->sha1), 1); - install_packed_git(target); - return 0; -} - -static int fetch_file(const unsigned char *sha1) -{ - static int object_name_start = -1; - static char filename[PATH_MAX]; - char *hex = sha1_to_hex(sha1); - char *dest_filename = sha1_file_name(sha1); - - if (object_name_start < 0) { - strcpy(filename, path); /* e.g. git.git */ - strcat(filename, "/objects/"); - object_name_start = strlen(filename); - } - filename[object_name_start+0] = hex[0]; - filename[object_name_start+1] = hex[1]; - filename[object_name_start+2] = '/'; - strcpy(filename + object_name_start + 3, hex + 2); - return copy_file(filename, dest_filename, hex, 0); -} - -int fetch(unsigned char *sha1) -{ - if (has_sha1_file(sha1)) - return 0; - else - return fetch_file(sha1) && fetch_pack(sha1); -} - -int fetch_ref(char *ref, unsigned char *sha1) -{ - static int ref_name_start = -1; - static char filename[PATH_MAX]; - static char hex[41]; - int ifd; - - if (ref_name_start < 0) { - sprintf(filename, "%s/refs/", path); - ref_name_start = strlen(filename); - } - strcpy(filename + ref_name_start, ref); - ifd = open(filename, O_RDONLY); - if (ifd < 0) { - close(ifd); - return error("cannot open %s", filename); - } - if (read_in_full(ifd, hex, 40) != 40 || get_sha1_hex(hex, sha1)) { - close(ifd); - return error("cannot read from %s", filename); - } - close(ifd); - pull_say("ref %s\n", sha1_to_hex(sha1)); - return 0; -} - -static const char local_pull_usage[] = -"git-local-fetch [-c] [-t] [-a] [-v] [-w filename] [--recover] [-l] [-s] [-n] [--stdin] commit-id path"; - -/* - * By default we only use file copy. - * If -l is specified, a hard link is attempted. - * If -s is specified, then a symlink is attempted. - * If -n is _not_ specified, then a regular file-to-file copy is done. - */ -int main(int argc, const char **argv) -{ - int commits; - const char **write_ref = NULL; - char **commit_id; - int arg = 1; - - setup_git_directory(); - git_config(git_default_config); - - while (arg < argc && argv[arg][0] == '-') { - if (argv[arg][1] == 't') - get_tree = 1; - else if (argv[arg][1] == 'c') - get_history = 1; - else if (argv[arg][1] == 'a') { - get_all = 1; - get_tree = 1; - get_history = 1; - } - else if (argv[arg][1] == 'l') - use_link = 1; - else if (argv[arg][1] == 's') - use_symlink = 1; - else if (argv[arg][1] == 'n') - use_filecopy = 0; - else if (argv[arg][1] == 'v') - get_verbosely = 1; - else if (argv[arg][1] == 'w') - write_ref = &argv[++arg]; - else if (!strcmp(argv[arg], "--recover")) - get_recover = 1; - else if (!strcmp(argv[arg], "--stdin")) - commits_on_stdin = 1; - else - usage(local_pull_usage); - arg++; - } - if (argc < arg + 2 - commits_on_stdin) - usage(local_pull_usage); - if (commits_on_stdin) { - commits = pull_targets_stdin(&commit_id, &write_ref); - } else { - commit_id = (char **) &argv[arg++]; - commits = 1; - } - path = argv[arg]; - - if (pull(commits, commit_id, write_ref, path)) - return 1; - - if (commits_on_stdin) - pull_targets_free(commits, commit_id, write_ref); - - return 0; -} diff --git a/rsh.c b/rsh.c deleted file mode 100644 index 5754a230e2..0000000000 --- a/rsh.c +++ /dev/null @@ -1,83 +0,0 @@ -#include "cache.h" -#include "rsh.h" -#include "quote.h" - -#define COMMAND_SIZE 4096 - -int setup_connection(int *fd_in, int *fd_out, const char *remote_prog, - char *url, int rmt_argc, char **rmt_argv) -{ - char *host; - char *path; - int sv[2]; - char command[COMMAND_SIZE]; - char *posn; - int sizen; - int of; - int i; - pid_t pid; - - if (!strcmp(url, "-")) { - *fd_in = 0; - *fd_out = 1; - return 0; - } - - host = strstr(url, "//"); - if (host) { - host += 2; - path = strchr(host, '/'); - } else { - host = url; - path = strchr(host, ':'); - if (path) - *(path++) = '\0'; - } - if (!path) { - return error("Bad URL: %s", url); - } - /* $GIT_RSH "env GIT_DIR= " */ - sizen = COMMAND_SIZE; - posn = command; - of = 0; - of |= add_to_string(&posn, &sizen, "env ", 0); - of |= add_to_string(&posn, &sizen, GIT_DIR_ENVIRONMENT "=", 0); - of |= add_to_string(&posn, &sizen, path, 1); - of |= add_to_string(&posn, &sizen, " ", 0); - of |= add_to_string(&posn, &sizen, remote_prog, 1); - - for ( i = 0 ; i < rmt_argc ; i++ ) { - of |= add_to_string(&posn, &sizen, " ", 0); - of |= add_to_string(&posn, &sizen, rmt_argv[i], 1); - } - - of |= add_to_string(&posn, &sizen, " -", 0); - - if ( of ) - return error("Command line too long"); - - if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv)) - return error("Couldn't create socket"); - - pid = fork(); - if (pid < 0) - return error("Couldn't fork"); - if (!pid) { - const char *ssh, *ssh_basename; - ssh = getenv("GIT_SSH"); - if (!ssh) ssh = "ssh"; - ssh_basename = strrchr(ssh, '/'); - if (!ssh_basename) - ssh_basename = ssh; - else - ssh_basename++; - close(sv[1]); - dup2(sv[0], 0); - dup2(sv[0], 1); - execlp(ssh, ssh_basename, host, command, NULL); - } - close(sv[0]); - *fd_in = sv[1]; - *fd_out = sv[1]; - return 0; -} diff --git a/rsh.h b/rsh.h deleted file mode 100644 index ee2f499291..0000000000 --- a/rsh.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef RSH_H -#define RSH_H - -int setup_connection(int *fd_in, int *fd_out, const char *remote_prog, - char *url, int rmt_argc, char **rmt_argv); - -#endif diff --git a/ssh-fetch.c b/ssh-fetch.c deleted file mode 100644 index bdf51a7a14..0000000000 --- a/ssh-fetch.c +++ /dev/null @@ -1,166 +0,0 @@ -#ifndef COUNTERPART_ENV_NAME -#define COUNTERPART_ENV_NAME "GIT_SSH_UPLOAD" -#endif -#ifndef COUNTERPART_PROGRAM_NAME -#define COUNTERPART_PROGRAM_NAME "git-ssh-upload" -#endif -#ifndef MY_PROGRAM_NAME -#define MY_PROGRAM_NAME "git-ssh-fetch" -#endif - -#include "cache.h" -#include "commit.h" -#include "rsh.h" -#include "fetch.h" -#include "refs.h" - -static int fd_in; -static int fd_out; - -static unsigned char remote_version; -static unsigned char local_version = 1; - -static int prefetches; - -static struct object_list *in_transit; -static struct object_list **end_of_transit = &in_transit; - -void prefetch(unsigned char *sha1) -{ - char type = 'o'; - struct object_list *node; - if (prefetches > 100) { - fetch(in_transit->item->sha1); - } - node = xmalloc(sizeof(struct object_list)); - node->next = NULL; - node->item = lookup_unknown_object(sha1); - *end_of_transit = node; - end_of_transit = &node->next; - /* XXX: what if these writes fail? */ - write_in_full(fd_out, &type, 1); - write_in_full(fd_out, sha1, 20); - prefetches++; -} - -static char conn_buf[4096]; -static size_t conn_buf_posn; - -int fetch(unsigned char *sha1) -{ - int ret; - signed char remote; - struct object_list *temp; - - if (hashcmp(sha1, in_transit->item->sha1)) { - /* we must have already fetched it to clean the queue */ - return has_sha1_file(sha1) ? 0 : -1; - } - prefetches--; - temp = in_transit; - in_transit = in_transit->next; - if (!in_transit) - end_of_transit = &in_transit; - free(temp); - - if (conn_buf_posn) { - remote = conn_buf[0]; - memmove(conn_buf, conn_buf + 1, --conn_buf_posn); - } else { - if (xread(fd_in, &remote, 1) < 1) - return -1; - } - /* fprintf(stderr, "Got %d\n", remote); */ - if (remote < 0) - return remote; - ret = write_sha1_from_fd(sha1, fd_in, conn_buf, 4096, &conn_buf_posn); - if (!ret) - pull_say("got %s\n", sha1_to_hex(sha1)); - return ret; -} - -static int get_version(void) -{ - char type = 'v'; - if (write_in_full(fd_out, &type, 1) != 1 || - write_in_full(fd_out, &local_version, 1)) { - return error("Couldn't request version from remote end"); - } - if (xread(fd_in, &remote_version, 1) < 1) { - return error("Couldn't read version from remote end"); - } - return 0; -} - -int fetch_ref(char *ref, unsigned char *sha1) -{ - signed char remote; - char type = 'r'; - int length = strlen(ref) + 1; - if (write_in_full(fd_out, &type, 1) != 1 || - write_in_full(fd_out, ref, length) != length) - return -1; - - if (read_in_full(fd_in, &remote, 1) != 1) - return -1; - if (remote < 0) - return remote; - if (read_in_full(fd_in, sha1, 20) != 20) - return -1; - return 0; -} - -static const char ssh_fetch_usage[] = - MY_PROGRAM_NAME - " [-c] [-t] [-a] [-v] [--recover] [-w ref] commit-id url"; -int main(int argc, char **argv) -{ - const char *write_ref = NULL; - char *commit_id; - char *url; - int arg = 1; - const char *prog; - - prog = getenv("GIT_SSH_PUSH"); - if (!prog) prog = "git-ssh-upload"; - - setup_git_directory(); - git_config(git_default_config); - - while (arg < argc && argv[arg][0] == '-') { - if (argv[arg][1] == 't') { - get_tree = 1; - } else if (argv[arg][1] == 'c') { - get_history = 1; - } else if (argv[arg][1] == 'a') { - get_all = 1; - get_tree = 1; - get_history = 1; - } else if (argv[arg][1] == 'v') { - get_verbosely = 1; - } else if (argv[arg][1] == 'w') { - write_ref = argv[arg + 1]; - arg++; - } else if (!strcmp(argv[arg], "--recover")) { - get_recover = 1; - } - arg++; - } - if (argc < arg + 2) { - usage(ssh_fetch_usage); - return 1; - } - commit_id = argv[arg]; - url = argv[arg + 1]; - - if (setup_connection(&fd_in, &fd_out, prog, url, arg, argv + 1)) - return 1; - - if (get_version()) - return 1; - - if (pull(1, &commit_id, &write_ref, url)) - return 1; - - return 0; -} diff --git a/ssh-pull.c b/ssh-pull.c deleted file mode 100644 index 868ce4d41f..0000000000 --- a/ssh-pull.c +++ /dev/null @@ -1,4 +0,0 @@ -#define COUNTERPART_ENV_NAME "GIT_SSH_PUSH" -#define COUNTERPART_PROGRAM_NAME "git-ssh-push" -#define MY_PROGRAM_NAME "git-ssh-pull" -#include "ssh-fetch.c" diff --git a/ssh-push.c b/ssh-push.c deleted file mode 100644 index a562df1b31..0000000000 --- a/ssh-push.c +++ /dev/null @@ -1,4 +0,0 @@ -#define COUNTERPART_ENV_NAME "GIT_SSH_PULL" -#define COUNTERPART_PROGRAM_NAME "git-ssh-pull" -#define MY_PROGRAM_NAME "git-ssh-push" -#include "ssh-upload.c" diff --git a/ssh-upload.c b/ssh-upload.c deleted file mode 100644 index 20c35f03dd..0000000000 --- a/ssh-upload.c +++ /dev/null @@ -1,143 +0,0 @@ -#ifndef COUNTERPART_ENV_NAME -#define COUNTERPART_ENV_NAME "GIT_SSH_FETCH" -#endif -#ifndef COUNTERPART_PROGRAM_NAME -#define COUNTERPART_PROGRAM_NAME "git-ssh-fetch" -#endif -#ifndef MY_PROGRAM_NAME -#define MY_PROGRAM_NAME "git-ssh-upload" -#endif - -#include "cache.h" -#include "rsh.h" -#include "refs.h" - -static unsigned char local_version = 1; -static unsigned char remote_version; - -static int verbose; - -static int serve_object(int fd_in, int fd_out) { - ssize_t size; - unsigned char sha1[20]; - signed char remote; - - size = read_in_full(fd_in, sha1, 20); - if (size < 0) { - perror("git-ssh-upload: read "); - return -1; - } - if (!size) - return -1; - - if (verbose) - fprintf(stderr, "Serving %s\n", sha1_to_hex(sha1)); - - remote = 0; - - if (!has_sha1_file(sha1)) { - fprintf(stderr, "git-ssh-upload: could not find %s\n", - sha1_to_hex(sha1)); - remote = -1; - } - - if (write_in_full(fd_out, &remote, 1) != 1) - return 0; - - if (remote < 0) - return 0; - - return write_sha1_to_fd(fd_out, sha1); -} - -static int serve_version(int fd_in, int fd_out) -{ - if (xread(fd_in, &remote_version, 1) < 1) - return -1; - write_in_full(fd_out, &local_version, 1); - return 0; -} - -static int serve_ref(int fd_in, int fd_out) -{ - char ref[PATH_MAX]; - unsigned char sha1[20]; - int posn = 0; - signed char remote = 0; - do { - if (posn >= PATH_MAX || xread(fd_in, ref + posn, 1) < 1) - return -1; - posn++; - } while (ref[posn - 1]); - - if (verbose) - fprintf(stderr, "Serving %s\n", ref); - - if (get_ref_sha1(ref, sha1)) - remote = -1; - if (write_in_full(fd_out, &remote, 1) != 1) - return 0; - if (remote) - return 0; - write_in_full(fd_out, sha1, 20); - return 0; -} - - -static void service(int fd_in, int fd_out) { - char type; - ssize_t retval; - do { - retval = xread(fd_in, &type, 1); - if (retval < 1) { - if (retval < 0) - perror("git-ssh-upload: read "); - return; - } - if (type == 'v' && serve_version(fd_in, fd_out)) - return; - if (type == 'o' && serve_object(fd_in, fd_out)) - return; - if (type == 'r' && serve_ref(fd_in, fd_out)) - return; - } while (1); -} - -static const char ssh_push_usage[] = - MY_PROGRAM_NAME " [-c] [-t] [-a] [-w ref] commit-id url"; - -int main(int argc, char **argv) -{ - int arg = 1; - char *commit_id; - char *url; - int fd_in, fd_out; - const char *prog; - unsigned char sha1[20]; - char hex[41]; - - prog = getenv(COUNTERPART_ENV_NAME); - if (!prog) prog = COUNTERPART_PROGRAM_NAME; - - setup_git_directory(); - - while (arg < argc && argv[arg][0] == '-') { - if (argv[arg][1] == 'w') - arg++; - arg++; - } - if (argc < arg + 2) - usage(ssh_push_usage); - commit_id = argv[arg]; - url = argv[arg + 1]; - if (get_sha1(commit_id, sha1)) - die("Not a valid object name %s", commit_id); - memcpy(hex, sha1_to_hex(sha1), sizeof(hex)); - argv[arg] = hex; - - if (setup_connection(&fd_in, &fd_out, prog, url, arg, argv + 1)) - return 1; - - service(fd_in, fd_out); - return 0; -} From 30ae764b1e11f10b5fca723a876a0f3de3ca11ab Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Mon, 10 Sep 2007 23:02:45 -0400 Subject: [PATCH 0051/1490] Modularize commit-walker This turns the extern functions to be provided by the backend into a struct of pointers, renames the functions to be more namespace-friendly, and updates http-fetch to this interface. It removes the unused include from http-push.c. It makes git-http-fetch a builtin (with the implementation a separate file, accessible directly). Signed-off-by: Daniel Barkalow Signed-off-by: Junio C Hamano --- Makefile | 17 +-- builtin-http-fetch.c | 77 ++++++++++++ builtin.h | 1 + fetch.h | 54 -------- git.c | 3 + http-push.c | 1 - http-fetch.c => http-walker.c | 228 +++++++++++++++------------------- fetch.c => walker.c | 83 +++++++------ walker.h | 37 ++++++ 9 files changed, 271 insertions(+), 230 deletions(-) create mode 100644 builtin-http-fetch.c delete mode 100644 fetch.h rename http-fetch.c => http-walker.c (85%) rename fetch.c => walker.c (75%) create mode 100644 walker.h diff --git a/Makefile b/Makefile index 520f156f34..3436a2326a 100644 --- a/Makefile +++ b/Makefile @@ -514,7 +514,9 @@ else CC_LD_DYNPATH = -R endif -ifndef NO_CURL +ifdef NO_CURL + BASIC_CFLAGS += -DNO_CURL +else ifdef CURLDIR # Try "-Wl,-rpath=$(CURLDIR)/$(lib)" in such a case. BASIC_CFLAGS += -I$(CURLDIR)/include @@ -522,7 +524,9 @@ ifndef NO_CURL else CURL_LIBCURL = -lcurl endif - PROGRAMS += git-http-fetch$X + BUILTIN_OBJS += builtin-http-fetch.o + EXTLIBS += $(CURL_LIBCURL) + LIB_OBJS += http.o walker.o http-walker.o curl_check := $(shell (echo 070908; curl-config --vernum) | sort -r | sed -ne 2p) ifeq "$(curl_check)" "070908" ifndef NO_EXPAT @@ -884,7 +888,7 @@ http.o: http.c GIT-CFLAGS $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) -DGIT_USER_AGENT='"git/$(GIT_VERSION)"' $< ifdef NO_EXPAT -http-fetch.o: http-fetch.c http.h GIT-CFLAGS +http-walker.o: http-walker.c http.h GIT-CFLAGS $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) -DNO_EXPAT $< endif @@ -893,16 +897,13 @@ git-%$X: %.o $(GITLIBS) git-imap-send$X: imap-send.o $(LIB_FILE) -http.o http-fetch.o http-push.o: http.h -git-http-fetch$X: fetch.o http.o http-fetch.o $(GITLIBS) - $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \ - $(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT) +http.o http-walker.o http-push.o: http.h git-http-push$X: revision.o http.o http-push.o $(GITLIBS) $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \ $(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT) -$(LIB_OBJS) $(BUILTIN_OBJS) fetch.o: $(LIB_H) +$(LIB_OBJS) $(BUILTIN_OBJS) walker.o: $(LIB_H) $(patsubst git-%$X,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h) $(DIFF_OBJS): diffcore.h diff --git a/builtin-http-fetch.c b/builtin-http-fetch.c new file mode 100644 index 0000000000..4a50dbd95b --- /dev/null +++ b/builtin-http-fetch.c @@ -0,0 +1,77 @@ +#include "cache.h" +#include "walker.h" + +int cmd_http_fetch(int argc, const char **argv, const char *prefix) +{ + struct walker *walker; + int commits_on_stdin = 0; + int commits; + const char **write_ref = NULL; + char **commit_id; + const char *url; + int arg = 1; + int rc = 0; + int get_tree = 0; + int get_history = 0; + int get_all = 0; + int get_verbosely = 0; + int get_recover = 0; + + git_config(git_default_config); + + while (arg < argc && argv[arg][0] == '-') { + if (argv[arg][1] == 't') { + get_tree = 1; + } else if (argv[arg][1] == 'c') { + get_history = 1; + } else if (argv[arg][1] == 'a') { + get_all = 1; + get_tree = 1; + get_history = 1; + } else if (argv[arg][1] == 'v') { + get_verbosely = 1; + } else if (argv[arg][1] == 'w') { + write_ref = &argv[arg + 1]; + arg++; + } else if (!strcmp(argv[arg], "--recover")) { + get_recover = 1; + } else if (!strcmp(argv[arg], "--stdin")) { + commits_on_stdin = 1; + } + arg++; + } + if (argc < arg + 2 - commits_on_stdin) { + usage("git-http-fetch [-c] [-t] [-a] [-v] [--recover] [-w ref] [--stdin] commit-id url"); + return 1; + } + if (commits_on_stdin) { + commits = walker_targets_stdin(&commit_id, &write_ref); + } else { + commit_id = (char **) &argv[arg++]; + commits = 1; + } + url = argv[arg]; + + walker = get_http_walker(url); + walker->get_tree = get_tree; + walker->get_history = get_history; + walker->get_all = get_all; + walker->get_verbosely = get_verbosely; + walker->get_recover = get_recover; + + rc = walker_fetch(walker, commits, commit_id, write_ref, url); + + if (commits_on_stdin) + walker_targets_free(commits, commit_id, write_ref); + + if (walker->corrupt_object_found) { + fprintf(stderr, +"Some loose object were found to be corrupt, but they might be just\n" +"a false '404 Not Found' error message sent with incorrect HTTP\n" +"status code. Suggest running git-fsck.\n"); + } + + walker_free(walker); + + return rc; +} diff --git a/builtin.h b/builtin.h index 03ee7bf780..1fa1444e33 100644 --- a/builtin.h +++ b/builtin.h @@ -40,6 +40,7 @@ extern int cmd_gc(int argc, const char **argv, const char *prefix); extern int cmd_get_tar_commit_id(int argc, const char **argv, const char *prefix); extern int cmd_grep(int argc, const char **argv, const char *prefix); extern int cmd_help(int argc, const char **argv, const char *prefix); +extern int cmd_http_fetch(int argc, const char **argv, const char *prefix); extern int cmd_init_db(int argc, const char **argv, const char *prefix); extern int cmd_log(int argc, const char **argv, const char *prefix); extern int cmd_log_reflog(int argc, const char **argv, const char *prefix); diff --git a/fetch.h b/fetch.h deleted file mode 100644 index be48c6f190..0000000000 --- a/fetch.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef PULL_H -#define PULL_H - -/* - * Fetch object given SHA1 from the remote, and store it locally under - * GIT_OBJECT_DIRECTORY. Return 0 on success, -1 on failure. To be - * provided by the particular implementation. - */ -extern int fetch(unsigned char *sha1); - -/* - * Fetch the specified object and store it locally; fetch() will be - * called later to determine success. To be provided by the particular - * implementation. - */ -extern void prefetch(unsigned char *sha1); - -/* - * Fetch ref (relative to $GIT_DIR/refs) from the remote, and store - * the 20-byte SHA1 in sha1. Return 0 on success, -1 on failure. To - * be provided by the particular implementation. - */ -extern int fetch_ref(char *ref, unsigned char *sha1); - -/* Set to fetch the target tree. */ -extern int get_tree; - -/* Set to fetch the commit history. */ -extern int get_history; - -/* Set to fetch the trees in the commit history. */ -extern int get_all; - -/* Set to be verbose */ -extern int get_verbosely; - -/* Set to check on all reachable objects. */ -extern int get_recover; - -/* Report what we got under get_verbosely */ -extern void pull_say(const char *, const char *); - -/* Load pull targets from stdin */ -extern int pull_targets_stdin(char ***target, const char ***write_ref); - -/* Free up loaded targets */ -extern void pull_targets_free(int targets, char **target, const char **write_ref); - -/* If write_ref is set, the ref filename to write the target value to. */ -/* If write_ref_log_details is set, additional text will appear in the ref log. */ -extern int pull(int targets, char **target, const char **write_ref, - const char *write_ref_log_details); - -#endif /* PULL_H */ diff --git a/git.c b/git.c index 56ae8ccccf..41fe73eff9 100644 --- a/git.c +++ b/git.c @@ -344,6 +344,9 @@ static void handle_internal_command(int argc, const char **argv) { "get-tar-commit-id", cmd_get_tar_commit_id }, { "grep", cmd_grep, RUN_SETUP | USE_PAGER }, { "help", cmd_help }, +#ifndef NO_CURL + { "http-fetch", cmd_http_fetch, RUN_SETUP }, +#endif { "init", cmd_init_db }, { "init-db", cmd_init_db }, { "log", cmd_log, RUN_SETUP | USE_PAGER }, diff --git a/http-push.c b/http-push.c index c54230b6f3..8e1fdfddf5 100644 --- a/http-push.c +++ b/http-push.c @@ -1,7 +1,6 @@ #include "cache.h" #include "commit.h" #include "pack.h" -#include "fetch.h" #include "tag.h" #include "blob.h" #include "http.h" diff --git a/http-fetch.c b/http-walker.c similarity index 85% rename from http-fetch.c rename to http-walker.c index 7786110ffc..444aebf526 100644 --- a/http-fetch.c +++ b/http-walker.c @@ -1,19 +1,12 @@ #include "cache.h" #include "commit.h" #include "pack.h" -#include "fetch.h" +#include "walker.h" #include "http.h" #define PREV_BUF_SIZE 4096 #define RANGE_HEADER_SIZE 30 -static int commits_on_stdin; - -static int got_alternates = -1; -static int corrupt_object_found; - -static struct curl_slist *no_pragma_header; - struct alt_base { char *base; @@ -22,8 +15,6 @@ struct alt_base struct alt_base *next; }; -static struct alt_base *alt; - enum object_request_state { WAITING, ABORTED, @@ -33,6 +24,7 @@ enum object_request_state { struct object_request { + struct walker *walker; unsigned char sha1[20]; struct alt_base *repo; char *url; @@ -53,6 +45,7 @@ struct object_request }; struct alternates_request { + struct walker *walker; const char *base; char *url; struct buffer *buffer; @@ -60,6 +53,13 @@ struct alternates_request { int http_specific; }; +struct walker_data { + const char *url; + int got_alternates; + struct alt_base *alt; + struct curl_slist *no_pragma_header; +}; + static struct object_request *object_queue_head; static size_t fwrite_sha1_file(void *ptr, size_t eltsize, size_t nmemb, @@ -103,11 +103,12 @@ static int missing__target(int code, int result) #define missing_target(a) missing__target((a)->http_code, (a)->curl_result) -static void fetch_alternates(const char *base); +static void fetch_alternates(struct walker *walker, const char *base); static void process_object_response(void *callback_data); -static void start_object_request(struct object_request *obj_req) +static void start_object_request(struct walker *walker, + struct object_request *obj_req) { char *hex = sha1_to_hex(obj_req->sha1); char prevfile[PATH_MAX]; @@ -120,6 +121,7 @@ static void start_object_request(struct object_request *obj_req) char range[RANGE_HEADER_SIZE]; struct curl_slist *range_header = NULL; struct active_request_slot *slot; + struct walker_data *data = walker->data; snprintf(prevfile, sizeof(prevfile), "%s.prev", obj_req->filename); unlink(prevfile); @@ -212,12 +214,12 @@ static void start_object_request(struct object_request *obj_req) curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_sha1_file); curl_easy_setopt(slot->curl, CURLOPT_ERRORBUFFER, obj_req->errorstr); curl_easy_setopt(slot->curl, CURLOPT_URL, url); - curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, no_pragma_header); + curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, data->no_pragma_header); /* If we have successfully processed data from a previous fetch attempt, only fetch the data we don't already have. */ if (prev_posn>0) { - if (get_verbosely) + if (walker->get_verbosely) fprintf(stderr, "Resuming fetch of object %s at byte %ld\n", hex, prev_posn); @@ -268,13 +270,16 @@ static void finish_object_request(struct object_request *obj_req) move_temp_to_file(obj_req->tmpfile, obj_req->filename); if (obj_req->rename == 0) - pull_say("got %s\n", sha1_to_hex(obj_req->sha1)); + walker_say(obj_req->walker, "got %s\n", sha1_to_hex(obj_req->sha1)); } static void process_object_response(void *callback_data) { struct object_request *obj_req = (struct object_request *)callback_data; + struct walker *walker = obj_req->walker; + struct walker_data *data = walker->data; + struct alt_base *alt = data->alt; obj_req->curl_result = obj_req->slot->curl_result; obj_req->http_code = obj_req->slot->http_code; @@ -283,13 +288,13 @@ static void process_object_response(void *callback_data) /* Use alternates if necessary */ if (missing_target(obj_req)) { - fetch_alternates(alt->base); + fetch_alternates(walker, alt->base); if (obj_req->repo->next != NULL) { obj_req->repo = obj_req->repo->next; close(obj_req->local); obj_req->local = -1; - start_object_request(obj_req); + start_object_request(walker, obj_req); return; } } @@ -317,7 +322,7 @@ static void release_object_request(struct object_request *obj_req) } #ifdef USE_CURL_MULTI -static int fill_active_slot(void *unused) +static int fill_active_slot(struct walker *walker) { struct object_request *obj_req; @@ -326,7 +331,7 @@ static int fill_active_slot(void *unused) if (has_sha1_file(obj_req->sha1)) obj_req->state = COMPLETE; else { - start_object_request(obj_req); + start_object_request(walker, obj_req); return 1; } } @@ -335,15 +340,17 @@ static int fill_active_slot(void *unused) } #endif -void prefetch(unsigned char *sha1) +static void prefetch(struct walker *walker, unsigned char *sha1) { struct object_request *newreq; struct object_request *tail; + struct walker_data *data = walker->data; char *filename = sha1_file_name(sha1); newreq = xmalloc(sizeof(*newreq)); + newreq->walker = walker; hashcpy(newreq->sha1, sha1); - newreq->repo = alt; + newreq->repo = data->alt; newreq->url = NULL; newreq->local = -1; newreq->state = WAITING; @@ -369,7 +376,7 @@ void prefetch(unsigned char *sha1) #endif } -static int fetch_index(struct alt_base *repo, unsigned char *sha1) +static int fetch_index(struct walker *walker, struct alt_base *repo, unsigned char *sha1) { char *hex = sha1_to_hex(sha1); char *filename; @@ -378,6 +385,7 @@ static int fetch_index(struct alt_base *repo, unsigned char *sha1) long prev_posn = 0; char range[RANGE_HEADER_SIZE]; struct curl_slist *range_header = NULL; + struct walker_data *data = walker->data; FILE *indexfile; struct active_request_slot *slot; @@ -386,7 +394,7 @@ static int fetch_index(struct alt_base *repo, unsigned char *sha1) if (has_pack_index(sha1)) return 0; - if (get_verbosely) + if (walker->get_verbosely) fprintf(stderr, "Getting index for pack %s\n", hex); url = xmalloc(strlen(repo->base) + 64); @@ -404,14 +412,14 @@ static int fetch_index(struct alt_base *repo, unsigned char *sha1) curl_easy_setopt(slot->curl, CURLOPT_FILE, indexfile); curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite); curl_easy_setopt(slot->curl, CURLOPT_URL, url); - curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, no_pragma_header); + curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, data->no_pragma_header); slot->local = indexfile; /* If there is data present from a previous transfer attempt, resume where it left off */ prev_posn = ftell(indexfile); if (prev_posn>0) { - if (get_verbosely) + if (walker->get_verbosely) fprintf(stderr, "Resuming fetch of index for pack %s at byte %ld\n", hex, prev_posn); @@ -437,13 +445,13 @@ static int fetch_index(struct alt_base *repo, unsigned char *sha1) return move_temp_to_file(tmpfile, filename); } -static int setup_index(struct alt_base *repo, unsigned char *sha1) +static int setup_index(struct walker *walker, struct alt_base *repo, unsigned char *sha1) { struct packed_git *new_pack; if (has_pack_file(sha1)) return 0; /* don't list this as something we can get */ - if (fetch_index(repo, sha1)) + if (fetch_index(walker, repo, sha1)) return -1; new_pack = parse_pack_index(sha1); @@ -456,8 +464,10 @@ static void process_alternates_response(void *callback_data) { struct alternates_request *alt_req = (struct alternates_request *)callback_data; + struct walker *walker = alt_req->walker; + struct walker_data *cdata = walker->data; struct active_request_slot *slot = alt_req->slot; - struct alt_base *tail = alt; + struct alt_base *tail = cdata->alt; const char *base = alt_req->base; static const char null_byte = '\0'; char *data; @@ -478,7 +488,7 @@ static void process_alternates_response(void *callback_data) if (slot->finished != NULL) (*slot->finished) = 0; if (!start_active_slot(slot)) { - got_alternates = -1; + cdata->got_alternates = -1; slot->in_use = 0; if (slot->finished != NULL) (*slot->finished) = 1; @@ -487,7 +497,7 @@ static void process_alternates_response(void *callback_data) } } else if (slot->curl_result != CURLE_OK) { if (!missing_target(slot)) { - got_alternates = -1; + cdata->got_alternates = -1; return; } } @@ -564,7 +574,7 @@ static void process_alternates_response(void *callback_data) memcpy(target + serverlen, data + i, posn - i - 7); target[serverlen + posn - i - 7] = 0; - if (get_verbosely) + if (walker->get_verbosely) fprintf(stderr, "Also look at %s\n", target); newalt = xmalloc(sizeof(*newalt)); @@ -581,39 +591,40 @@ static void process_alternates_response(void *callback_data) i = posn + 1; } - got_alternates = 1; + cdata->got_alternates = 1; } -static void fetch_alternates(const char *base) +static void fetch_alternates(struct walker *walker, const char *base) { struct buffer buffer; char *url; char *data; struct active_request_slot *slot; struct alternates_request alt_req; + struct walker_data *cdata = walker->data; /* If another request has already started fetching alternates, wait for them to arrive and return to processing this request's curl message */ #ifdef USE_CURL_MULTI - while (got_alternates == 0) { + while (cdata->got_alternates == 0) { step_active_slots(); } #endif /* Nothing to do if they've already been fetched */ - if (got_alternates == 1) + if (cdata->got_alternates == 1) return; /* Start the fetch */ - got_alternates = 0; + cdata->got_alternates = 0; data = xmalloc(4096); buffer.size = 4096; buffer.posn = 0; buffer.buffer = data; - if (get_verbosely) + if (walker->get_verbosely) fprintf(stderr, "Getting alternates list for %s\n", base); url = xmalloc(strlen(base) + 31); @@ -623,6 +634,7 @@ static void fetch_alternates(const char *base) may fail and need to have alternates loaded before continuing */ slot = get_active_slot(); slot->callback_func = process_alternates_response; + alt_req.walker = walker; slot->callback_data = &alt_req; curl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer); @@ -638,13 +650,13 @@ static void fetch_alternates(const char *base) if (start_active_slot(slot)) run_active_slot(slot); else - got_alternates = -1; + cdata->got_alternates = -1; free(data); free(url); } -static int fetch_indices(struct alt_base *repo) +static int fetch_indices(struct walker *walker, struct alt_base *repo) { unsigned char sha1[20]; char *url; @@ -663,7 +675,7 @@ static int fetch_indices(struct alt_base *repo) buffer.posn = 0; buffer.buffer = data; - if (get_verbosely) + if (walker->get_verbosely) fprintf(stderr, "Getting pack list for %s\n", repo->base); url = xmalloc(strlen(repo->base) + 21); @@ -703,7 +715,7 @@ static int fetch_indices(struct alt_base *repo) !prefixcmp(data + i, " pack-") && !prefixcmp(data + i + 46, ".pack\n")) { get_sha1_hex(data + i + 6, sha1); - setup_index(repo, sha1); + setup_index(walker, repo, sha1); i += 51; break; } @@ -719,7 +731,7 @@ static int fetch_indices(struct alt_base *repo) return 0; } -static int fetch_pack(struct alt_base *repo, unsigned char *sha1) +static int fetch_pack(struct walker *walker, struct alt_base *repo, unsigned char *sha1) { char *url; struct packed_git *target; @@ -731,17 +743,18 @@ static int fetch_pack(struct alt_base *repo, unsigned char *sha1) long prev_posn = 0; char range[RANGE_HEADER_SIZE]; struct curl_slist *range_header = NULL; + struct walker_data *data = walker->data; struct active_request_slot *slot; struct slot_results results; - if (fetch_indices(repo)) + if (fetch_indices(walker, repo)) return -1; target = find_sha1_pack(sha1, repo->packs); if (!target) return -1; - if (get_verbosely) { + if (walker->get_verbosely) { fprintf(stderr, "Getting pack %s\n", sha1_to_hex(target->sha1)); fprintf(stderr, " which contains %s\n", @@ -764,14 +777,14 @@ static int fetch_pack(struct alt_base *repo, unsigned char *sha1) curl_easy_setopt(slot->curl, CURLOPT_FILE, packfile); curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite); curl_easy_setopt(slot->curl, CURLOPT_URL, url); - curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, no_pragma_header); + curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, data->no_pragma_header); slot->local = packfile; /* If there is data present from a previous transfer attempt, resume where it left off */ prev_posn = ftell(packfile); if (prev_posn>0) { - if (get_verbosely) + if (walker->get_verbosely) fprintf(stderr, "Resuming fetch of pack %s at byte %ld\n", sha1_to_hex(target->sha1), prev_posn); @@ -825,7 +838,7 @@ static void abort_object_request(struct object_request *obj_req) release_object_request(obj_req); } -static int fetch_object(struct alt_base *repo, unsigned char *sha1) +static int fetch_object(struct walker *walker, struct alt_base *repo, unsigned char *sha1) { char *hex = sha1_to_hex(sha1); int ret = 0; @@ -846,7 +859,7 @@ static int fetch_object(struct alt_base *repo, unsigned char *sha1) step_active_slots(); } #else - start_object_request(obj_req); + start_object_request(walker, obj_req); #endif while (obj_req->state == ACTIVE) { @@ -867,7 +880,7 @@ static int fetch_object(struct alt_base *repo, unsigned char *sha1) obj_req->errorstr, obj_req->curl_result, obj_req->http_code, hex); } else if (obj_req->zret != Z_STREAM_END) { - corrupt_object_found++; + walker->corrupt_object_found++; ret = error("File %s (%s) corrupt", hex, obj_req->url); } else if (hashcmp(obj_req->sha1, obj_req->real_sha1)) { ret = error("File %s has bad hash", hex); @@ -880,20 +893,21 @@ static int fetch_object(struct alt_base *repo, unsigned char *sha1) return ret; } -int fetch(unsigned char *sha1) +static int fetch(struct walker *walker, unsigned char *sha1) { - struct alt_base *altbase = alt; + struct walker_data *data = walker->data; + struct alt_base *altbase = data->alt; - if (!fetch_object(altbase, sha1)) + if (!fetch_object(walker, altbase, sha1)) return 0; while (altbase) { - if (!fetch_pack(altbase, sha1)) + if (!fetch_pack(walker, altbase, sha1)) return 0; - fetch_alternates(alt->base); + fetch_alternates(walker, data->alt->base); altbase = altbase->next; } return error("Unable to find %s under %s", sha1_to_hex(sha1), - alt->base); + data->alt->base); } static inline int needs_quote(int ch) @@ -942,12 +956,13 @@ static char *quote_ref_url(const char *base, const char *ref) return qref; } -int fetch_ref(char *ref, unsigned char *sha1) +static int fetch_ref(struct walker *walker, char *ref, unsigned char *sha1) { char *url; char hex[42]; struct buffer buffer; - const char *base = alt->base; + struct walker_data *data = walker->data; + const char *base = data->alt->base; struct active_request_slot *slot; struct slot_results results; buffer.size = 41; @@ -976,84 +991,45 @@ int fetch_ref(char *ref, unsigned char *sha1) return 0; } -int main(int argc, const char **argv) +static void cleanup(struct walker *walker) +{ + struct walker_data *data = walker->data; + http_cleanup(); + + curl_slist_free_all(data->no_pragma_header); +} + +struct walker *get_http_walker(const char *url) { - int commits; - const char **write_ref = NULL; - char **commit_id; - const char *url; char *s; - int arg = 1; - int rc = 0; - - setup_git_directory(); - git_config(git_default_config); - - while (arg < argc && argv[arg][0] == '-') { - if (argv[arg][1] == 't') { - get_tree = 1; - } else if (argv[arg][1] == 'c') { - get_history = 1; - } else if (argv[arg][1] == 'a') { - get_all = 1; - get_tree = 1; - get_history = 1; - } else if (argv[arg][1] == 'v') { - get_verbosely = 1; - } else if (argv[arg][1] == 'w') { - write_ref = &argv[arg + 1]; - arg++; - } else if (!strcmp(argv[arg], "--recover")) { - get_recover = 1; - } else if (!strcmp(argv[arg], "--stdin")) { - commits_on_stdin = 1; - } - arg++; - } - if (argc < arg + 2 - commits_on_stdin) { - usage("git-http-fetch [-c] [-t] [-a] [-v] [--recover] [-w ref] [--stdin] commit-id url"); - return 1; - } - if (commits_on_stdin) { - commits = pull_targets_stdin(&commit_id, &write_ref); - } else { - commit_id = (char **) &argv[arg++]; - commits = 1; - } - url = argv[arg]; + struct walker_data *data = xmalloc(sizeof(struct walker_data)); + struct walker *walker = xmalloc(sizeof(struct walker)); http_init(); - no_pragma_header = curl_slist_append(no_pragma_header, "Pragma:"); + data->no_pragma_header = curl_slist_append(NULL, "Pragma:"); - alt = xmalloc(sizeof(*alt)); - alt->base = xmalloc(strlen(url) + 1); - strcpy(alt->base, url); - for (s = alt->base + strlen(alt->base) - 1; *s == '/'; --s) + data->alt = xmalloc(sizeof(*data->alt)); + data->alt->base = xmalloc(strlen(url) + 1); + strcpy(data->alt->base, url); + for (s = data->alt->base + strlen(data->alt->base) - 1; *s == '/'; --s) *s = 0; - alt->got_indices = 0; - alt->packs = NULL; - alt->next = NULL; + + data->alt->got_indices = 0; + data->alt->packs = NULL; + data->alt->next = NULL; + data->got_alternates = -1; + + walker->corrupt_object_found = 0; + walker->fetch = fetch; + walker->fetch_ref = fetch_ref; + walker->prefetch = prefetch; + walker->cleanup = cleanup; + walker->data = data; #ifdef USE_CURL_MULTI - add_fill_function(NULL, fill_active_slot); + add_fill_function(walker, (int (*)(void *)) fill_active_slot); #endif - if (pull(commits, commit_id, write_ref, url)) - rc = 1; - - http_cleanup(); - - curl_slist_free_all(no_pragma_header); - - if (commits_on_stdin) - pull_targets_free(commits, commit_id, write_ref); - - if (corrupt_object_found) { - fprintf(stderr, -"Some loose object were found to be corrupt, but they might be just\n" -"a false '404 Not Found' error message sent with incorrect HTTP\n" -"status code. Suggest running git-fsck.\n"); - } - return rc; + return walker; } diff --git a/fetch.c b/walker.c similarity index 75% rename from fetch.c rename to walker.c index 811be87a3c..5c65ea494d 100644 --- a/fetch.c +++ b/walker.c @@ -1,5 +1,5 @@ #include "cache.h" -#include "fetch.h" +#include "walker.h" #include "commit.h" #include "tree.h" #include "tree-walk.h" @@ -8,16 +8,11 @@ #include "refs.h" #include "strbuf.h" -int get_tree = 0; -int get_history = 0; -int get_all = 0; -int get_verbosely = 0; -int get_recover = 0; static unsigned char current_commit_sha1[20]; -void pull_say(const char *fmt, const char *hex) +void walker_say(struct walker *walker, const char *fmt, const char *hex) { - if (get_verbosely) + if (walker->get_verbosely) fprintf(stderr, fmt, hex); } @@ -32,9 +27,9 @@ static void report_missing(const struct object *obj) sha1_to_hex(current_commit_sha1)); } -static int process(struct object *obj); +static int process(struct walker *walker, struct object *obj); -static int process_tree(struct tree *tree) +static int process_tree(struct walker *walker, struct tree *tree) { struct tree_desc desc; struct name_entry entry; @@ -59,7 +54,7 @@ static int process_tree(struct tree *tree) if (blob) obj = &blob->object; } - if (!obj || process(obj)) + if (!obj || process(walker, obj)) return -1; } free(tree->buffer); @@ -74,7 +69,7 @@ static int process_tree(struct tree *tree) static struct commit_list *complete = NULL; -static int process_commit(struct commit *commit) +static int process_commit(struct walker *walker, struct commit *commit) { if (parse_commit(commit)) return -1; @@ -88,43 +83,43 @@ static int process_commit(struct commit *commit) hashcpy(current_commit_sha1, commit->object.sha1); - pull_say("walk %s\n", sha1_to_hex(commit->object.sha1)); + walker_say(walker, "walk %s\n", sha1_to_hex(commit->object.sha1)); - if (get_tree) { - if (process(&commit->tree->object)) + if (walker->get_tree) { + if (process(walker, &commit->tree->object)) return -1; - if (!get_all) - get_tree = 0; + if (!walker->get_all) + walker->get_tree = 0; } - if (get_history) { + if (walker->get_history) { struct commit_list *parents = commit->parents; for (; parents; parents = parents->next) { - if (process(&parents->item->object)) + if (process(walker, &parents->item->object)) return -1; } } return 0; } -static int process_tag(struct tag *tag) +static int process_tag(struct walker *walker, struct tag *tag) { if (parse_tag(tag)) return -1; - return process(tag->tagged); + return process(walker, tag->tagged); } static struct object_list *process_queue = NULL; static struct object_list **process_queue_end = &process_queue; -static int process_object(struct object *obj) +static int process_object(struct walker *walker, struct object *obj) { if (obj->type == OBJ_COMMIT) { - if (process_commit((struct commit *)obj)) + if (process_commit(walker, (struct commit *)obj)) return -1; return 0; } if (obj->type == OBJ_TREE) { - if (process_tree((struct tree *)obj)) + if (process_tree(walker, (struct tree *)obj)) return -1; return 0; } @@ -132,7 +127,7 @@ static int process_object(struct object *obj) return 0; } if (obj->type == OBJ_TAG) { - if (process_tag((struct tag *)obj)) + if (process_tag(walker, (struct tag *)obj)) return -1; return 0; } @@ -141,7 +136,7 @@ static int process_object(struct object *obj) typename(obj->type), sha1_to_hex(obj->sha1)); } -static int process(struct object *obj) +static int process(struct walker *walker, struct object *obj) { if (obj->flags & SEEN) return 0; @@ -154,7 +149,7 @@ static int process(struct object *obj) else { if (obj->flags & COMPLETE) return 0; - prefetch(obj->sha1); + walker->prefetch(walker, obj->sha1); } object_list_insert(obj, process_queue_end); @@ -162,7 +157,7 @@ static int process(struct object *obj) return 0; } -static int loop(void) +static int loop(struct walker *walker) { struct object_list *elem; @@ -178,25 +173,25 @@ static int loop(void) * the queue because we needed to fetch it first. */ if (! (obj->flags & TO_SCAN)) { - if (fetch(obj->sha1)) { + if (walker->fetch(walker, obj->sha1)) { report_missing(obj); return -1; } } if (!obj->type) parse_object(obj->sha1); - if (process_object(obj)) + if (process_object(walker, obj)) return -1; } return 0; } -static int interpret_target(char *target, unsigned char *sha1) +static int interpret_target(struct walker *walker, char *target, unsigned char *sha1) { if (!get_sha1_hex(target, sha1)) return 0; if (!check_ref_format(target)) { - if (!fetch_ref(target, sha1)) { + if (!walker->fetch_ref(walker, target, sha1)) { return 0; } } @@ -213,7 +208,7 @@ static int mark_complete(const char *path, const unsigned char *sha1, int flag, return 0; } -int pull_targets_stdin(char ***target, const char ***write_ref) +int walker_targets_stdin(char ***target, const char ***write_ref) { int targets = 0, targets_alloc = 0; struct strbuf buf; @@ -243,7 +238,7 @@ int pull_targets_stdin(char ***target, const char ***write_ref) return targets; } -void pull_targets_free(int targets, char **target, const char **write_ref) +void walker_targets_free(int targets, char **target, const char **write_ref) { while (targets--) { free(target[targets]); @@ -252,8 +247,8 @@ void pull_targets_free(int targets, char **target, const char **write_ref) } } -int pull(int targets, char **target, const char **write_ref, - const char *write_ref_log_details) +int walker_fetch(struct walker *walker, int targets, char **target, + const char **write_ref, const char *write_ref_log_details) { struct ref_lock **lock = xcalloc(targets, sizeof(struct ref_lock *)); unsigned char *sha1 = xmalloc(targets * 20); @@ -275,19 +270,19 @@ int pull(int targets, char **target, const char **write_ref, } } - if (!get_recover) + if (!walker->get_recover) for_each_ref(mark_complete, NULL); for (i = 0; i < targets; i++) { - if (interpret_target(target[i], &sha1[20 * i])) { + if (interpret_target(walker, target[i], &sha1[20 * i])) { error("Could not interpret %s as something to pull", target[i]); goto unlock_and_fail; } - if (process(lookup_unknown_object(&sha1[20 * i]))) + if (process(walker, lookup_unknown_object(&sha1[20 * i]))) goto unlock_and_fail; } - if (loop()) + if (loop(walker)) goto unlock_and_fail; if (write_ref_log_details) { @@ -308,10 +303,16 @@ int pull(int targets, char **target, const char **write_ref, return 0; - unlock_and_fail: for (i = 0; i < targets; i++) if (lock[i]) unlock_ref(lock[i]); + return -1; } + +void walker_free(struct walker *walker) +{ + walker->cleanup(walker); + free(walker); +} diff --git a/walker.h b/walker.h new file mode 100644 index 0000000000..ea2c363f4e --- /dev/null +++ b/walker.h @@ -0,0 +1,37 @@ +#ifndef WALKER_H +#define WALKER_H + +struct walker { + void *data; + int (*fetch_ref)(struct walker *, char *ref, unsigned char *sha1); + void (*prefetch)(struct walker *, unsigned char *sha1); + int (*fetch)(struct walker *, unsigned char *sha1); + void (*cleanup)(struct walker *); + int get_tree; + int get_history; + int get_all; + int get_verbosely; + int get_recover; + + int corrupt_object_found; +}; + +/* Report what we got under get_verbosely */ +void walker_say(struct walker *walker, const char *, const char *); + +/* Load pull targets from stdin */ +int walker_targets_stdin(char ***target, const char ***write_ref); + +/* Free up loaded targets */ +void walker_targets_free(int targets, char **target, const char **write_ref); + +/* If write_ref is set, the ref filename to write the target value to. */ +/* If write_ref_log_details is set, additional text will appear in the ref log. */ +int walker_fetch(struct walker *impl, int targets, char **target, + const char **write_ref, const char *write_ref_log_details); + +void walker_free(struct walker *walker); + +struct walker *get_http_walker(const char *url); + +#endif /* WALKER_H */ From 0012ba2108aa42947dedf19f3db2de73a67cc4f5 Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Mon, 10 Sep 2007 23:02:51 -0400 Subject: [PATCH 0052/1490] Add uploadpack configuration info to remote. Signed-off-by: Daniel Barkalow Signed-off-by: Junio C Hamano --- remote.c | 5 +++++ remote.h | 1 + 2 files changed, 6 insertions(+) diff --git a/remote.c b/remote.c index bb774d0bcc..a8196b1b5d 100644 --- a/remote.c +++ b/remote.c @@ -196,6 +196,11 @@ static int handle_config(const char *key, const char *value) remote->receivepack = xstrdup(value); else error("more than one receivepack given, using the first"); + } else if (!strcmp(subkey, ".uploadpack")) { + if (!remote->uploadpack) + remote->uploadpack = xstrdup(value); + else + error("more than one uploadpack given, using the first"); } return 0; } diff --git a/remote.h b/remote.h index 17b8b5b5d5..72c9153783 100644 --- a/remote.h +++ b/remote.h @@ -16,6 +16,7 @@ struct remote { int fetch_refspec_nr; const char *receivepack; + const char *uploadpack; }; struct remote *remote_get(const char *name); From cf818348f1ab577d2ecb5d11a00a1d4122435ece Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Mon, 10 Sep 2007 23:02:56 -0400 Subject: [PATCH 0053/1490] Report information on branches from remote.h This adds full parsing for branch. sections and functions to interpret the results usefully. It incidentally corrects the fetch configuration information for legacy branches/* files with '#' characters in the URLs. Signed-off-by: Daniel Barkalow Signed-off-by: Junio C Hamano --- remote.c | 157 +++++++++++++++++++++++++++++++++++++++++++++++++++---- remote.h | 18 +++++++ 2 files changed, 164 insertions(+), 11 deletions(-) diff --git a/remote.c b/remote.c index a8196b1b5d..711aa04ce1 100644 --- a/remote.c +++ b/remote.c @@ -5,6 +5,12 @@ static struct remote **remotes; static int allocated_remotes; +static struct branch **branches; +static int allocated_branches; + +static struct branch *current_branch; +static const char *default_remote_name; + #define BUF_SIZE (2048) static char buffer[BUF_SIZE]; @@ -67,6 +73,54 @@ static struct remote *make_remote(const char *name, int len) return remotes[empty]; } +static void add_merge(struct branch *branch, const char *name) +{ + int nr = branch->merge_nr + 1; + branch->merge_name = + xrealloc(branch->merge_name, nr * sizeof(char *)); + branch->merge_name[nr-1] = name; + branch->merge_nr = nr; +} + +static struct branch *make_branch(const char *name, int len) +{ + int i, empty = -1; + char *refname; + + for (i = 0; i < allocated_branches; i++) { + if (!branches[i]) { + if (empty < 0) + empty = i; + } else { + if (len ? (!strncmp(name, branches[i]->name, len) && + !branches[i]->name[len]) : + !strcmp(name, branches[i]->name)) + return branches[i]; + } + } + + if (empty < 0) { + empty = allocated_branches; + allocated_branches += allocated_branches ? allocated_branches : 1; + branches = xrealloc(branches, + sizeof(*branches) * allocated_branches); + memset(branches + empty, 0, + (allocated_branches - empty) * sizeof(*branches)); + } + branches[empty] = xcalloc(1, sizeof(struct branch)); + if (len) + branches[empty]->name = xstrndup(name, len); + else + branches[empty]->name = xstrdup(name); + refname = malloc(strlen(name) + strlen("refs/heads/") + 1); + strcpy(refname, "refs/heads/"); + strcpy(refname + strlen("refs/heads/"), + branches[empty]->name); + branches[empty]->refname = refname; + + return branches[empty]; +} + static void read_remotes_file(struct remote *remote) { FILE *f = fopen(git_path("remotes/%s", remote->name), "r"); @@ -116,6 +170,8 @@ static void read_remotes_file(struct remote *remote) static void read_branches_file(struct remote *remote) { const char *slash = strchr(remote->name, '/'); + char *frag; + char *branch; int n = slash ? slash - remote->name : 1000; FILE *f = fopen(git_path("branches/%.*s", n, remote->name), "r"); char *s, *p; @@ -141,23 +197,40 @@ static void read_branches_file(struct remote *remote) strcpy(p, s); if (slash) strcat(p, slash); + frag = strchr(p, '#'); + if (frag) { + *(frag++) = '\0'; + branch = xmalloc(strlen(frag) + 12); + strcpy(branch, "refs/heads/"); + strcat(branch, frag); + } else { + branch = "refs/heads/master"; + } add_uri(remote, p); + add_fetch_refspec(remote, branch); } -static char *default_remote_name = NULL; -static const char *current_branch = NULL; -static int current_branch_len = 0; - static int handle_config(const char *key, const char *value) { const char *name; const char *subkey; struct remote *remote; - if (!prefixcmp(key, "branch.") && current_branch && - !strncmp(key + 7, current_branch, current_branch_len) && - !strcmp(key + 7 + current_branch_len, ".remote")) { - free(default_remote_name); - default_remote_name = xstrdup(value); + struct branch *branch; + if (!prefixcmp(key, "branch.")) { + name = key + 7; + subkey = strrchr(name, '.'); + branch = make_branch(name, subkey - name); + if (!subkey) + return 0; + if (!value) + return 0; + if (!strcmp(subkey, ".remote")) { + branch->remote_name = xstrdup(value); + if (branch == current_branch) + default_remote_name = branch->remote_name; + } else if (!strcmp(subkey, ".merge")) + add_merge(branch, xstrdup(value)); + return 0; } if (prefixcmp(key, "remote.")) return 0; @@ -217,8 +290,8 @@ static void read_config(void) head_ref = resolve_ref("HEAD", sha1, 0, &flag); if (head_ref && (flag & REF_ISSYMREF) && !prefixcmp(head_ref, "refs/heads/")) { - current_branch = head_ref + strlen("refs/heads/"); - current_branch_len = strlen(current_branch); + current_branch = + make_branch(head_ref + strlen("refs/heads/"), 0); } git_config(handle_config); } @@ -313,6 +386,25 @@ int remote_has_uri(struct remote *remote, const char *uri) return 0; } +/* + * Returns true if, under the matching rules for fetching, name is the + * same as the given full name. + */ +static int ref_matches_abbrev(const char *name, const char *full) +{ + if (!prefixcmp(name, "refs/") || !strcmp(name, "HEAD")) + return !strcmp(name, full); + if (prefixcmp(full, "refs/")) + return 0; + if (!prefixcmp(name, "heads/") || + !prefixcmp(name, "tags/") || + !prefixcmp(name, "remotes/")) + return !strcmp(name, full + 5); + if (prefixcmp(full + 5, "heads/")) + return 0; + return !strcmp(full + 11, name); +} + int remote_find_tracking(struct remote *remote, struct refspec *refspec) { int find_src = refspec->src == NULL; @@ -636,3 +728,46 @@ int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail, } return 0; } + +struct branch *branch_get(const char *name) +{ + struct branch *ret; + + read_config(); + if (!name || !*name || !strcmp(name, "HEAD")) + ret = current_branch; + else + ret = make_branch(name, 0); + if (ret && ret->remote_name) { + ret->remote = remote_get(ret->remote_name); + if (ret->merge_nr) { + int i; + ret->merge = xcalloc(sizeof(*ret->merge), + ret->merge_nr); + for (i = 0; i < ret->merge_nr; i++) { + ret->merge[i] = xcalloc(1, sizeof(**ret->merge)); + ret->merge[i]->src = xstrdup(ret->merge_name[i]); + remote_find_tracking(ret->remote, + ret->merge[i]); + } + } + } + return ret; +} + +int branch_has_merge_config(struct branch *branch) +{ + return branch && !!branch->merge; +} + +int branch_merges(struct branch *branch, const char *refname) +{ + int i; + if (!branch) + return 0; + for (i = 0; i < branch->merge_nr; i++) { + if (ref_matches_abbrev(branch->merge[i]->src, refname)) + return 1; + } + return 0; +} diff --git a/remote.h b/remote.h index 72c9153783..f21b6a6da1 100644 --- a/remote.h +++ b/remote.h @@ -49,4 +49,22 @@ int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail, */ int remote_find_tracking(struct remote *remote, struct refspec *refspec); +struct branch { + const char *name; + const char *refname; + + const char *remote_name; + struct remote *remote; + + const char **merge_name; + struct refspec **merge; + int merge_nr; +}; + +struct branch *branch_get(const char *name); + +int branch_has_merge_config(struct branch *branch); + +int branch_merges(struct branch *branch, const char *refname); + #endif From 2d4177c01c238071777db5b1fbd8a14efb62ce02 Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Mon, 10 Sep 2007 23:03:00 -0400 Subject: [PATCH 0054/1490] Make fetch-pack a builtin with an internal API Signed-off-by: Daniel Barkalow Signed-off-by: Junio C Hamano --- Makefile | 1 + fetch-pack.c => builtin-fetch-pack.c | 84 ++++++++++++++++++++-------- builtin.h | 1 + fetch-pack.h | 21 +++++++ git.c | 1 + 5 files changed, 86 insertions(+), 22 deletions(-) rename fetch-pack.c => builtin-fetch-pack.c (93%) create mode 100644 fetch-pack.h diff --git a/Makefile b/Makefile index 3436a2326a..9ce6a9ba31 100644 --- a/Makefile +++ b/Makefile @@ -331,6 +331,7 @@ BUILTIN_OBJS = \ builtin-diff-files.o \ builtin-diff-index.o \ builtin-diff-tree.o \ + builtin-fetch-pack.o \ builtin-fetch--tool.o \ builtin-fmt-merge-msg.o \ builtin-for-each-ref.o \ diff --git a/fetch-pack.c b/builtin-fetch-pack.c similarity index 93% rename from fetch-pack.c rename to builtin-fetch-pack.c index 9c81305be5..3b217d96f0 100644 --- a/fetch-pack.c +++ b/builtin-fetch-pack.c @@ -6,6 +6,7 @@ #include "exec_cmd.h" #include "pack.h" #include "sideband.h" +#include "fetch-pack.h" static int keep_pack; static int transfer_unpack_limit = -1; @@ -573,7 +574,7 @@ static int get_pack(int xd[2]) die("%s died of unnatural causes %d", argv[0], status); } -static int fetch_pack(int fd[2], int nr_match, char **match) +static struct ref *do_fetch_pack(int fd[2], int nr_match, char **match) { struct ref *ref; unsigned char sha1[20]; @@ -615,12 +616,7 @@ static int fetch_pack(int fd[2], int nr_match, char **match) die("git-fetch-pack: fetch failed."); all_done: - while (ref) { - printf("%s %s\n", - sha1_to_hex(ref->old_sha1), ref->name); - ref = ref->next; - } - return 0; + return ref; } static int remove_duplicates(int nr_heads, char **heads) @@ -663,15 +659,28 @@ static int fetch_pack_config(const char *var, const char *value) static struct lock_file lock; -int main(int argc, char **argv) +void setup_fetch_pack(struct fetch_pack_args *args) +{ + uploadpack = args->uploadpack; + quiet = args->quiet; + keep_pack = args->keep_pack; + if (args->unpacklimit >= 0) + unpack_limit = args->unpacklimit; + if (args->keep_pack) + unpack_limit = 0; + use_thin_pack = args->use_thin_pack; + fetch_all = args->fetch_all; + verbose = args->verbose; + depth = args->depth; + no_progress = args->no_progress; +} + +int cmd_fetch_pack(int argc, const char **argv, const char *prefix) { int i, ret, nr_heads; + struct ref *ref; char *dest = NULL, **heads; - int fd[2]; - pid_t pid; - struct stat st; - setup_git_directory(); git_config(fetch_pack_config); if (0 <= transfer_unpack_limit) @@ -682,7 +691,7 @@ int main(int argc, char **argv) nr_heads = 0; heads = NULL; for (i = 1; i < argc; i++) { - char *arg = argv[i]; + const char *arg = argv[i]; if (*arg == '-') { if (!prefixcmp(arg, "--upload-pack=")) { @@ -716,8 +725,6 @@ int main(int argc, char **argv) } if (!prefixcmp(arg, "--depth=")) { depth = strtol(arg + 8, NULL, 0); - if (stat(git_path("shallow"), &st)) - st.st_mtime = 0; continue; } if (!strcmp("--no-progress", arg)) { @@ -726,22 +733,52 @@ int main(int argc, char **argv) } usage(fetch_pack_usage); } - dest = arg; - heads = argv + i + 1; + dest = (char *)arg; + heads = (char **)(argv + i + 1); nr_heads = argc - i - 1; break; } if (!dest) usage(fetch_pack_usage); - pid = git_connect(fd, dest, uploadpack, verbose ? CONNECT_VERBOSE : 0); + + ref = fetch_pack(dest, nr_heads, heads); + + ret = !ref; + + while (ref) { + printf("%s %s\n", + sha1_to_hex(ref->old_sha1), ref->name); + ref = ref->next; + } + + return ret; +} + +struct ref *fetch_pack(const char *dest, int nr_heads, char **heads) +{ + int i, ret; + int fd[2]; + pid_t pid; + struct ref *ref; + struct stat st; + + if (depth > 0) { + if (stat(git_path("shallow"), &st)) + st.st_mtime = 0; + } + + printf("connect to %s\n", dest); + + pid = git_connect(fd, (char *)dest, uploadpack, + verbose ? CONNECT_VERBOSE : 0); if (pid < 0) - return 1; + return NULL; if (heads && nr_heads) nr_heads = remove_duplicates(nr_heads, heads); - ret = fetch_pack(fd, nr_heads, heads); + ref = do_fetch_pack(fd, nr_heads, heads); close(fd[0]); close(fd[1]); - ret |= finish_connect(pid); + ret = finish_connect(pid); if (!ret && nr_heads) { /* If the heads to pull were given, we should have @@ -785,5 +822,8 @@ int main(int argc, char **argv) } } - return !!ret; + if (ret) + ref = NULL; + + return ref; } diff --git a/builtin.h b/builtin.h index 1fa1444e33..d424bfdeb1 100644 --- a/builtin.h +++ b/builtin.h @@ -31,6 +31,7 @@ extern int cmd_diff_files(int argc, const char **argv, const char *prefix); extern int cmd_diff_index(int argc, const char **argv, const char *prefix); extern int cmd_diff(int argc, const char **argv, const char *prefix); extern int cmd_diff_tree(int argc, const char **argv, const char *prefix); +extern int cmd_fetch_pack(int argc, const char **argv, const char *prefix); extern int cmd_fetch__tool(int argc, const char **argv, const char *prefix); extern int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix); extern int cmd_for_each_ref(int argc, const char **argv, const char *prefix); diff --git a/fetch-pack.h b/fetch-pack.h new file mode 100644 index 0000000000..e06bf5b5c4 --- /dev/null +++ b/fetch-pack.h @@ -0,0 +1,21 @@ +#ifndef FETCH_PACK_H +#define FETCH_PACK_H + +struct fetch_pack_args +{ + const char *uploadpack; + int quiet; + int keep_pack; + int unpacklimit; + int use_thin_pack; + int fetch_all; + int verbose; + int depth; + int no_progress; +}; + +void setup_fetch_pack(struct fetch_pack_args *args); + +struct ref *fetch_pack(const char *dest, int nr_heads, char **heads); + +#endif diff --git a/git.c b/git.c index 41fe73eff9..6ca36c0265 100644 --- a/git.c +++ b/git.c @@ -334,6 +334,7 @@ static void handle_internal_command(int argc, const char **argv) { "diff-files", cmd_diff_files }, { "diff-index", cmd_diff_index, RUN_SETUP }, { "diff-tree", cmd_diff_tree, RUN_SETUP }, + { "fetch-pack", cmd_fetch_pack, RUN_SETUP }, { "fetch--tool", cmd_fetch__tool, RUN_SETUP }, { "fmt-merge-msg", cmd_fmt_merge_msg, RUN_SETUP }, { "for-each-ref", cmd_for_each_ref, RUN_SETUP }, From 9b288516ee63cea91dd9d102edcdf112caea4c75 Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Mon, 10 Sep 2007 23:03:04 -0400 Subject: [PATCH 0055/1490] Push code for transport library This moves the code to call push backends into a library that can be extended to make matching fetch and push decisions based on the URL it gets, and which could be changed to have built-in implementations instead of calling external programs. Signed-off-by: Daniel Barkalow Signed-off-by: Junio C Hamano --- Makefile | 3 +- builtin-push.c | 82 ++++++--------------- transport.c | 196 +++++++++++++++++++++++++++++++++++++++++++++++++ transport.h | 61 +++++++++++++++ 4 files changed, 280 insertions(+), 62 deletions(-) create mode 100644 transport.c create mode 100644 transport.h diff --git a/Makefile b/Makefile index 9ce6a9ba31..da6abdfd81 100644 --- a/Makefile +++ b/Makefile @@ -310,7 +310,8 @@ LIB_OBJS = \ write_or_die.o trace.o list-objects.o grep.o match-trees.o \ alloc.o merge-file.o path-list.o help.o unpack-trees.o $(DIFF_OBJS) \ color.o wt-status.o archive-zip.o archive-tar.o shallow.o utf8.o \ - convert.o attr.o decorate.o progress.o mailmap.o symlinks.o remote.o + convert.o attr.o decorate.o progress.o mailmap.o symlinks.o remote.o \ + transport.o BUILTIN_OBJS = \ builtin-add.o \ diff --git a/builtin-push.c b/builtin-push.c index 88c5024da7..f496b46007 100644 --- a/builtin-push.c +++ b/builtin-push.c @@ -6,10 +6,11 @@ #include "run-command.h" #include "builtin.h" #include "remote.h" +#include "transport.h" static const char push_usage[] = "git-push [--all] [--tags] [--receive-pack=] [--repo=all] [-f | --force] [-v] [ ...]"; -static int all, force, thin, verbose; +static int all, thin, verbose; static const char *receivepack; static const char **refspec; @@ -43,80 +44,38 @@ static void set_refspecs(const char **refs, int nr) } } -static int do_push(const char *repo) +static int do_push(const char *repo, int flags) { int i, errs; - int common_argc; - const char **argv; - int argc; struct remote *remote = remote_get(repo); if (!remote) die("bad repository '%s'", repo); - if (remote->receivepack) { - char *rp = xmalloc(strlen(remote->receivepack) + 16); - sprintf(rp, "--receive-pack=%s", remote->receivepack); - receivepack = rp; - } if (!refspec && !all && remote->push_refspec_nr) { refspec = remote->push_refspec; refspec_nr = remote->push_refspec_nr; } - - argv = xmalloc((refspec_nr + 10) * sizeof(char *)); - argv[0] = "dummy-send-pack"; - argc = 1; - if (all) - argv[argc++] = "--all"; - if (force) - argv[argc++] = "--force"; - if (receivepack) - argv[argc++] = receivepack; - common_argc = argc; - errs = 0; for (i = 0; i < remote->uri_nr; i++) { + struct transport *transport = + transport_get(remote, remote->uri[i], 0); int err; - int dest_argc = common_argc; - int dest_refspec_nr = refspec_nr; - const char **dest_refspec = refspec; - const char *dest = remote->uri[i]; - const char *sender = "send-pack"; - if (!prefixcmp(dest, "http://") || - !prefixcmp(dest, "https://")) - sender = "http-push"; - else { - char *rem = xmalloc(strlen(remote->name) + 10); - sprintf(rem, "--remote=%s", remote->name); - argv[dest_argc++] = rem; - if (thin) - argv[dest_argc++] = "--thin"; - } - argv[0] = sender; - argv[dest_argc++] = dest; - while (dest_refspec_nr--) - argv[dest_argc++] = *dest_refspec++; - argv[dest_argc] = NULL; + if (receivepack) + transport_set_option(transport, + TRANS_OPT_RECEIVEPACK, receivepack); + if (thin) + transport_set_option(transport, TRANS_OPT_THIN, "yes"); + if (verbose) - fprintf(stderr, "Pushing to %s\n", dest); - err = run_command_v_opt(argv, RUN_GIT_CMD); + fprintf(stderr, "Pushing to %s\n", remote->uri[i]); + err = transport_push(transport, refspec_nr, refspec, flags); + err |= transport_disconnect(transport); + if (!err) continue; error("failed to push to '%s'", remote->uri[i]); - switch (err) { - case -ERR_RUN_COMMAND_FORK: - error("unable to fork for %s", sender); - case -ERR_RUN_COMMAND_EXEC: - error("unable to exec %s", sender); - break; - case -ERR_RUN_COMMAND_WAITPID: - case -ERR_RUN_COMMAND_WAITPID_WRONG_PID: - case -ERR_RUN_COMMAND_WAITPID_SIGNAL: - case -ERR_RUN_COMMAND_WAITPID_NOEXIT: - error("%s died with strange error", sender); - } errs++; } return !!errs; @@ -125,6 +84,7 @@ static int do_push(const char *repo) int cmd_push(int argc, const char **argv, const char *prefix) { int i; + int flags = 0; const char *repo = NULL; /* default repository */ for (i = 1; i < argc; i++) { @@ -144,7 +104,7 @@ int cmd_push(int argc, const char **argv, const char *prefix) continue; } if (!strcmp(arg, "--all")) { - all = 1; + flags |= TRANSPORT_PUSH_ALL; continue; } if (!strcmp(arg, "--tags")) { @@ -152,7 +112,7 @@ int cmd_push(int argc, const char **argv, const char *prefix) continue; } if (!strcmp(arg, "--force") || !strcmp(arg, "-f")) { - force = 1; + flags |= TRANSPORT_PUSH_FORCE; continue; } if (!strcmp(arg, "--thin")) { @@ -164,11 +124,11 @@ int cmd_push(int argc, const char **argv, const char *prefix) continue; } if (!prefixcmp(arg, "--receive-pack=")) { - receivepack = arg; + receivepack = arg + 15; continue; } if (!prefixcmp(arg, "--exec=")) { - receivepack = arg; + receivepack = arg + 7; continue; } usage(push_usage); @@ -177,5 +137,5 @@ int cmd_push(int argc, const char **argv, const char *prefix) if (all && refspec) usage(push_usage); - return do_push(repo); + return do_push(repo, flags); } diff --git a/transport.c b/transport.c new file mode 100644 index 0000000000..edbdc3c60e --- /dev/null +++ b/transport.c @@ -0,0 +1,196 @@ +#include "cache.h" +#include "transport.h" +#include "run-command.h" + +static const struct transport_ops rsync_transport; + +static int curl_transport_push(struct transport *transport, int refspec_nr, const char **refspec, int flags) { + const char **argv; + int argc; + int err; + + argv = xmalloc((refspec_nr + 11) * sizeof(char *)); + argv[0] = "http-push"; + argc = 1; + if (flags & TRANSPORT_PUSH_ALL) + argv[argc++] = "--all"; + if (flags & TRANSPORT_PUSH_FORCE) + argv[argc++] = "--force"; + argv[argc++] = transport->url; + while (refspec_nr--) + argv[argc++] = *refspec++; + argv[argc] = NULL; + err = run_command_v_opt(argv, RUN_GIT_CMD); + switch (err) { + case -ERR_RUN_COMMAND_FORK: + error("unable to fork for %s", argv[0]); + case -ERR_RUN_COMMAND_EXEC: + error("unable to exec %s", argv[0]); + break; + case -ERR_RUN_COMMAND_WAITPID: + case -ERR_RUN_COMMAND_WAITPID_WRONG_PID: + case -ERR_RUN_COMMAND_WAITPID_SIGNAL: + case -ERR_RUN_COMMAND_WAITPID_NOEXIT: + error("%s died with strange error", argv[0]); + } + return !!err; +} + +static const struct transport_ops curl_transport = { + /* set_option */ NULL, + /* push */ curl_transport_push +}; + +static const struct transport_ops bundle_transport = { +}; + +struct git_transport_data { + unsigned thin : 1; + + const char *receivepack; +}; + +static int set_git_option(struct transport *connection, + const char *name, const char *value) +{ + struct git_transport_data *data = connection->data; + if (!strcmp(name, TRANS_OPT_RECEIVEPACK)) { + data->receivepack = value; + return 0; + } else if (!strcmp(name, TRANS_OPT_THIN)) { + data->thin = !!value; + return 0; + } + return 1; +} + +static int git_transport_push(struct transport *transport, int refspec_nr, const char **refspec, int flags) { + struct git_transport_data *data = transport->data; + const char **argv; + char *rem; + int argc; + int err; + + argv = xmalloc((refspec_nr + 11) * sizeof(char *)); + argv[0] = "send-pack"; + argc = 1; + if (flags & TRANSPORT_PUSH_ALL) + argv[argc++] = "--all"; + if (flags & TRANSPORT_PUSH_FORCE) + argv[argc++] = "--force"; + if (data->receivepack) { + char *rp = xmalloc(strlen(data->receivepack) + 16); + sprintf(rp, "--receive-pack=%s", data->receivepack); + argv[argc++] = rp; + } + if (data->thin) + argv[argc++] = "--thin"; + rem = xmalloc(strlen(transport->remote->name) + 10); + sprintf(rem, "--remote=%s", transport->remote->name); + argv[argc++] = rem; + argv[argc++] = transport->url; + while (refspec_nr--) + argv[argc++] = *refspec++; + argv[argc] = NULL; + err = run_command_v_opt(argv, RUN_GIT_CMD); + switch (err) { + case -ERR_RUN_COMMAND_FORK: + error("unable to fork for %s", argv[0]); + case -ERR_RUN_COMMAND_EXEC: + error("unable to exec %s", argv[0]); + break; + case -ERR_RUN_COMMAND_WAITPID: + case -ERR_RUN_COMMAND_WAITPID_WRONG_PID: + case -ERR_RUN_COMMAND_WAITPID_SIGNAL: + case -ERR_RUN_COMMAND_WAITPID_NOEXIT: + error("%s died with strange error", argv[0]); + } + return !!err; +} + +static const struct transport_ops git_transport = { + /* set_option */ set_git_option, + /* push */ git_transport_push +}; + +static int is_local(const char *url) +{ + const char *colon = strchr(url, ':'); + const char *slash = strchr(url, '/'); + return !colon || (slash && slash < colon); +} + +static int is_file(const char *url) +{ + struct stat buf; + if (stat(url, &buf)) + return 0; + return S_ISREG(buf.st_mode); +} + +struct transport *transport_get(struct remote *remote, const char *url, + int fetch) +{ + struct transport *ret = NULL; + if (!prefixcmp(url, "rsync://")) { + ret = xmalloc(sizeof(*ret)); + ret->data = NULL; + ret->ops = &rsync_transport; + } else if (!prefixcmp(url, "http://") || !prefixcmp(url, "https://") || + !prefixcmp(url, "ftp://")) { + ret = xmalloc(sizeof(*ret)); + ret->ops = &curl_transport; + ret->data = NULL; + } else if (is_local(url) && is_file(url)) { + ret = xmalloc(sizeof(*ret)); + ret->data = NULL; + ret->ops = &bundle_transport; + } else { + struct git_transport_data *data = xcalloc(1, sizeof(*data)); + ret = xcalloc(1, sizeof(*ret)); + ret->data = data; + data->thin = 1; + data->receivepack = "git-receive-pack"; + if (remote && remote->receivepack) + data->receivepack = remote->receivepack; + ret->ops = &git_transport; + } + if (ret) { + ret->remote = remote; + ret->url = url; + ret->fetch = !!fetch; + } + return ret; +} + +int transport_set_option(struct transport *transport, + const char *name, const char *value) +{ + int ret = 1; + if (transport->ops->set_option) + ret = transport->ops->set_option(transport, name, value); + if (ret < 0) + fprintf(stderr, "For '%s' option %s cannot be set to '%s'\n", + transport->url, name, value); + if (ret > 0) + fprintf(stderr, "For '%s' option %s is ignored\n", + transport->url, name); + return ret; +} + +int transport_push(struct transport *transport, + int refspec_nr, const char **refspec, int flags) +{ + if (!transport->ops->push) + return 1; + return transport->ops->push(transport, refspec_nr, refspec, flags); +} + +int transport_disconnect(struct transport *transport) +{ + int ret = 0; + if (transport->ops->disconnect) + ret = transport->ops->disconnect(transport); + free(transport); + return ret; +} diff --git a/transport.h b/transport.h new file mode 100644 index 0000000000..5c2eb959b2 --- /dev/null +++ b/transport.h @@ -0,0 +1,61 @@ +#ifndef TRANSPORT_H +#define TRANSPORT_H + +#include "cache.h" +#include "remote.h" + +struct transport { + unsigned verbose : 1; + unsigned fetch : 1; + struct remote *remote; + const char *url; + + void *data; + + struct ref *remote_refs; + + const struct transport_ops *ops; +}; + +#define TRANSPORT_PUSH_ALL 1 +#define TRANSPORT_PUSH_FORCE 2 + +struct transport_ops { + /** + * Returns 0 if successful, positive if the option is not + * recognized or is inapplicable, and negative if the option + * is applicable but the value is invalid. + **/ + int (*set_option)(struct transport *connection, const char *name, + const char *value); + + int (*push)(struct transport *connection, int refspec_nr, const char **refspec, int flags); + + int (*disconnect)(struct transport *connection); +}; + +/* Returns a transport suitable for the url */ +struct transport *transport_get(struct remote *remote, const char *url, + int fetch); + +/* Transport options which apply to git:// and scp-style URLs */ + +/* The program to use on the remote side to receive a pack */ +#define TRANS_OPT_RECEIVEPACK "receivepack" + +/* Transfer the data as a thin pack if not null */ +#define TRANS_OPT_THIN "thin" + +/** + * Returns 0 if the option was used, non-zero otherwise. Prints a + * message to stderr if the option is not used. + **/ +int transport_set_option(struct transport *transport, const char *name, + const char *value); + +int transport_push(struct transport *connection, + int refspec_nr, const char **refspec, int flags); + +int transport_disconnect(struct transport *transport); + +#endif From d71ab17470ab2011c7cb398b75385bb0d0c4bdb4 Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Mon, 10 Sep 2007 23:03:08 -0400 Subject: [PATCH 0056/1490] Add matching and parsing for fetch-side refspec rules Also exports parse_ref_spec(). Signed-off-by: Daniel Barkalow Signed-off-by: Junio C Hamano --- remote.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- remote.h | 24 +++++++++++ 2 files changed, 148 insertions(+), 1 deletion(-) diff --git a/remote.c b/remote.c index 711aa04ce1..df91b2ff99 100644 --- a/remote.c +++ b/remote.c @@ -208,6 +208,7 @@ static void read_branches_file(struct remote *remote) } add_uri(remote, p); add_fetch_refspec(remote, branch); + remote->fetch_tags = 1; /* always auto-follow */ } static int handle_config(const char *key, const char *value) @@ -274,6 +275,9 @@ static int handle_config(const char *key, const char *value) remote->uploadpack = xstrdup(value); else error("more than one uploadpack given, using the first"); + } else if (!strcmp(subkey, ".tagopt")) { + if (!strcmp(value, "--no-tags")) + remote->fetch_tags = -1; } return 0; } @@ -296,7 +300,7 @@ static void read_config(void) git_config(handle_config); } -static struct refspec *parse_ref_spec(int nr_refspec, const char **refspec) +struct refspec *parse_ref_spec(int nr_refspec, const char **refspec) { int i; struct refspec *rs = xcalloc(sizeof(*rs), nr_refspec); @@ -352,6 +356,10 @@ struct remote *remote_get(const char *name) add_uri(ret, name); if (!ret->uri) return NULL; + if (!strcmp(name, ".")) { + // we always fetch "refs/*:refs/*", which is trivial + add_fetch_refspec(ret, "refs/*:refs/*"); + } ret->fetch = parse_ref_spec(ret->fetch_refspec_nr, ret->fetch_refspec); ret->push = parse_ref_spec(ret->push_refspec_nr, ret->push_refspec); return ret; @@ -454,6 +462,14 @@ struct ref *alloc_ref(unsigned namelen) return ret; } +static struct ref *copy_ref(struct ref *ref) +{ + struct ref *ret = xmalloc(sizeof(struct ref) + strlen(ref->name) + 1); + memcpy(ret, ref, sizeof(struct ref) + strlen(ref->name) + 1); + ret->next = NULL; + return ret; +} + void free_refs(struct ref *ref) { struct ref *next; @@ -771,3 +787,110 @@ int branch_merges(struct branch *branch, const char *refname) } return 0; } + +static struct ref *get_expanded_map(struct ref *remote_refs, + const struct refspec *refspec) +{ + struct ref *ref; + struct ref *ret = NULL; + struct ref **tail = &ret; + + int remote_prefix_len = strlen(refspec->src); + int local_prefix_len = strlen(refspec->dst); + + for (ref = remote_refs; ref; ref = ref->next) { + if (strchr(ref->name, '^')) + continue; /* a dereference item */ + if (!prefixcmp(ref->name, refspec->src)) { + char *match; + struct ref *cpy = copy_ref(ref); + match = ref->name + remote_prefix_len; + + cpy->peer_ref = alloc_ref(local_prefix_len + + strlen(match) + 1); + sprintf(cpy->peer_ref->name, "%s%s", + refspec->dst, match); + if (refspec->force) + cpy->peer_ref->force = 1; + *tail = cpy; + tail = &cpy->next; + } + } + + return ret; +} + +static struct ref *find_ref_by_name_abbrev(struct ref *refs, const char *name) +{ + struct ref *ref; + for (ref = refs; ref; ref = ref->next) { + if (ref_matches_abbrev(name, ref->name)) + return ref; + } + return NULL; +} + +struct ref *get_remote_ref(struct ref *remote_refs, const char *name) +{ + struct ref *ref = find_ref_by_name_abbrev(remote_refs, name); + + if (!ref) + die("Couldn't find remote ref %s\n", name); + + return copy_ref(ref); +} + +static struct ref *get_local_ref(const char *name) +{ + struct ref *ret; + if (!name) + return NULL; + + if (!prefixcmp(name, "refs/")) { + ret = alloc_ref(strlen(name) + 1); + strcpy(ret->name, name); + return ret; + } + + if (!prefixcmp(name, "heads/") || + !prefixcmp(name, "tags/") || + !prefixcmp(name, "remotes/")) { + ret = alloc_ref(strlen(name) + 6); + sprintf(ret->name, "refs/%s", name); + return ret; + } + + ret = alloc_ref(strlen(name) + 12); + sprintf(ret->name, "refs/heads/%s", name); + return ret; +} + +int get_fetch_map(struct ref *remote_refs, + const struct refspec *refspec, + struct ref ***tail) +{ + struct ref *ref_map, *rm; + + if (refspec->pattern) { + ref_map = get_expanded_map(remote_refs, refspec); + } else { + ref_map = get_remote_ref(remote_refs, + refspec->src[0] ? + refspec->src : "HEAD"); + + ref_map->peer_ref = get_local_ref(refspec->dst); + + if (refspec->force) + ref_map->peer_ref->force = 1; + } + + for (rm = ref_map; rm; rm = rm->next) { + if (rm->peer_ref && check_ref_format(rm->peer_ref->name + 5)) + die("* refusing to create funny ref '%s' locally", + rm->peer_ref->name); + } + + tail_link_ref(ref_map, tail); + + return 0; +} diff --git a/remote.h b/remote.h index f21b6a6da1..89940527ad 100644 --- a/remote.h +++ b/remote.h @@ -15,6 +15,14 @@ struct remote { struct refspec *fetch; int fetch_refspec_nr; + /* + * -1 to never fetch tags + * 0 to auto-follow tags on heuristic (default) + * 1 to always auto-follow tags + * 2 to always fetch tags + */ + int fetch_tags; + const char *receivepack; const char *uploadpack; }; @@ -41,9 +49,25 @@ struct ref *alloc_ref(unsigned namelen); */ void free_refs(struct ref *ref); +struct refspec *parse_ref_spec(int nr_refspec, const char **refspec); + int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail, int nr_refspec, char **refspec, int all); +/* + * Given a list of the remote refs and the specification of things to + * fetch, makes a (separate) list of the refs to fetch and the local + * refs to store into. + * + * *tail is the pointer to the tail pointer of the list of results + * beforehand, and will be set to the tail pointer of the list of + * results afterward. + */ +int get_fetch_map(struct ref *remote_refs, const struct refspec *refspec, + struct ref ***tail); + +struct ref *get_remote_ref(struct ref *remote_refs, const char *name); + /* * For the given remote, reads the refspec's src and sets the other fields. */ From c29727d5241be0fee2265fbbe65d1b275b01dc1c Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Mon, 10 Sep 2007 23:03:11 -0400 Subject: [PATCH 0057/1490] Add fetch methods to transport library. Signed-off-by: Daniel Barkalow Signed-off-by: Junio C Hamano --- transport.c | 284 +++++++++++++++++++++++++++++++++++++++++++++++++++- transport.h | 21 ++++ 2 files changed, 302 insertions(+), 3 deletions(-) diff --git a/transport.c b/transport.c index edbdc3c60e..1e7374977e 100644 --- a/transport.c +++ b/transport.c @@ -1,6 +1,39 @@ #include "cache.h" #include "transport.h" #include "run-command.h" +#include "http.h" +#include "pkt-line.h" +#include "fetch-pack.h" +#include "walker.h" + +/* Generic functions for using commit walkers */ + +static int fetch_objs_via_walker(const struct transport *transport, + int nr_objs, char **objs) +{ + char *dest = xstrdup(transport->url); + struct walker *walker = transport->data; + + walker->get_all = 1; + walker->get_tree = 1; + walker->get_history = 1; + walker->get_verbosely = transport->verbose; + walker->get_recover = 0; + + if (walker_fetch(walker, nr_objs, objs, NULL, dest)) + die("Fetch failed."); + + free(dest); + return 0; +} + +static int disconnect_walker(struct transport *transport) +{ + struct walker *walker = transport->data; + if (walker) + walker_free(walker); + return 0; +} static const struct transport_ops rsync_transport; @@ -36,9 +69,119 @@ static int curl_transport_push(struct transport *transport, int refspec_nr, cons return !!err; } +#ifndef NO_CURL +static int missing__target(int code, int result) +{ + return /* file:// URL -- do we ever use one??? */ + (result == CURLE_FILE_COULDNT_READ_FILE) || + /* http:// and https:// URL */ + (code == 404 && result == CURLE_HTTP_RETURNED_ERROR) || + /* ftp:// URL */ + (code == 550 && result == CURLE_FTP_COULDNT_RETR_FILE) + ; +} + +#define missing_target(a) missing__target((a)->http_code, (a)->curl_result) + +static struct ref *get_refs_via_curl(const struct transport *transport) +{ + struct buffer buffer; + char *data, *start, *mid; + char *ref_name; + char *refs_url; + int i = 0; + + struct active_request_slot *slot; + struct slot_results results; + + struct ref *refs = NULL; + struct ref *ref = NULL; + struct ref *last_ref = NULL; + + data = xmalloc(4096); + buffer.size = 4096; + buffer.posn = 0; + buffer.buffer = data; + + refs_url = xmalloc(strlen(transport->url) + 11); + sprintf(refs_url, "%s/info/refs", transport->url); + + http_init(); + + slot = get_active_slot(); + slot->results = &results; + curl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer); + curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer); + curl_easy_setopt(slot->curl, CURLOPT_URL, refs_url); + curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, NULL); + if (start_active_slot(slot)) { + run_active_slot(slot); + if (results.curl_result != CURLE_OK) { + if (missing_target(&results)) { + free(buffer.buffer); + return NULL; + } else { + free(buffer.buffer); + error("%s", curl_errorstr); + return NULL; + } + } + } else { + free(buffer.buffer); + error("Unable to start request"); + return NULL; + } + + http_cleanup(); + + data = buffer.buffer; + start = NULL; + mid = data; + while (i < buffer.posn) { + if (!start) + start = &data[i]; + if (data[i] == '\t') + mid = &data[i]; + if (data[i] == '\n') { + data[i] = 0; + ref_name = mid + 1; + ref = xmalloc(sizeof(struct ref) + + strlen(ref_name) + 1); + memset(ref, 0, sizeof(struct ref)); + strcpy(ref->name, ref_name); + get_sha1_hex(start, ref->old_sha1); + if (!refs) + refs = ref; + if (last_ref) + last_ref->next = ref; + last_ref = ref; + start = NULL; + } + i++; + } + + free(buffer.buffer); + + return refs; +} + +#else + +static struct ref *get_refs_via_curl(const struct transport *transport) +{ + die("Cannot fetch from '%s' without curl ...", transport->url); + return NULL; +} + +#endif + static const struct transport_ops curl_transport = { /* set_option */ NULL, - /* push */ curl_transport_push + /* get_refs_list */ get_refs_via_curl, + /* fetch_refs */ NULL, + /* fetch_objs */ fetch_objs_via_walker, + /* push */ curl_transport_push, + /* disconnect */ disconnect_walker }; static const struct transport_ops bundle_transport = { @@ -46,7 +189,13 @@ static const struct transport_ops bundle_transport = { struct git_transport_data { unsigned thin : 1; + unsigned keep : 1; + int unpacklimit; + + int depth; + + const char *uploadpack; const char *receivepack; }; @@ -54,16 +203,86 @@ static int set_git_option(struct transport *connection, const char *name, const char *value) { struct git_transport_data *data = connection->data; - if (!strcmp(name, TRANS_OPT_RECEIVEPACK)) { + if (!strcmp(name, TRANS_OPT_UPLOADPACK)) { + data->uploadpack = value; + return 0; + } else if (!strcmp(name, TRANS_OPT_RECEIVEPACK)) { data->receivepack = value; return 0; } else if (!strcmp(name, TRANS_OPT_THIN)) { data->thin = !!value; return 0; + } else if (!strcmp(name, TRANS_OPT_KEEP)) { + data->keep = !!value; + return 0; + } else if (!strcmp(name, TRANS_OPT_UNPACKLIMIT)) { + data->unpacklimit = atoi(value); + return 0; + } else if (!strcmp(name, TRANS_OPT_DEPTH)) { + if (!value) + data->depth = 0; + else + data->depth = atoi(value); + return 0; } return 1; } +static struct ref *get_refs_via_connect(const struct transport *transport) +{ + struct git_transport_data *data = transport->data; + struct ref *refs; + int fd[2]; + pid_t pid; + char *dest = xstrdup(transport->url); + + pid = git_connect(fd, dest, data->uploadpack, 0); + + if (pid < 0) + die("Failed to connect to \"%s\"", transport->url); + + get_remote_heads(fd[0], &refs, 0, NULL, 0); + packet_flush(fd[1]); + + finish_connect(pid); + + free(dest); + + return refs; +} + +static int fetch_refs_via_pack(const struct transport *transport, + int nr_heads, char **heads) +{ + struct git_transport_data *data = transport->data; + struct ref *refs; + char *dest = xstrdup(transport->url); + struct fetch_pack_args args; + + args.uploadpack = data->uploadpack; + args.quiet = 0; + args.keep_pack = data->keep; + args.unpacklimit = data->unpacklimit; + args.use_thin_pack = data->thin; + args.fetch_all = 0; + args.verbose = transport->verbose; + args.depth = data->depth; + args.no_progress = 0; + + setup_fetch_pack(&args); + + refs = fetch_pack(dest, nr_heads, heads); + + // ???? check that refs got everything? + + /* free the memory used for the refs list ... */ + + free_refs(refs); + + free(dest); + return 0; +} + static int git_transport_push(struct transport *transport, int refspec_nr, const char **refspec, int flags) { struct git_transport_data *data = transport->data; const char **argv; @@ -110,6 +329,9 @@ static int git_transport_push(struct transport *transport, int refspec_nr, const static const struct transport_ops git_transport = { /* set_option */ set_git_option, + /* get_refs_list */ get_refs_via_connect, + /* fetch_refs */ fetch_refs_via_pack, + /* fetch_objs */ NULL, /* push */ git_transport_push }; @@ -140,7 +362,10 @@ struct transport *transport_get(struct remote *remote, const char *url, !prefixcmp(url, "ftp://")) { ret = xmalloc(sizeof(*ret)); ret->ops = &curl_transport; - ret->data = NULL; + if (fetch) + ret->data = get_http_walker(url); + else + ret->data = NULL; } else if (is_local(url) && is_file(url)) { ret = xmalloc(sizeof(*ret)); ret->data = NULL; @@ -150,14 +375,19 @@ struct transport *transport_get(struct remote *remote, const char *url, ret = xcalloc(1, sizeof(*ret)); ret->data = data; data->thin = 1; + data->uploadpack = "git-upload-pack"; + if (remote && remote->uploadpack) + data->uploadpack = remote->uploadpack; data->receivepack = "git-receive-pack"; if (remote && remote->receivepack) data->receivepack = remote->receivepack; + data->unpacklimit = -1; ret->ops = &git_transport; } if (ret) { ret->remote = remote; ret->url = url; + ret->remote_refs = NULL; ret->fetch = !!fetch; } return ret; @@ -186,6 +416,54 @@ int transport_push(struct transport *transport, return transport->ops->push(transport, refspec_nr, refspec, flags); } +struct ref *transport_get_remote_refs(struct transport *transport) +{ + if (!transport->remote_refs) + transport->remote_refs = + transport->ops->get_refs_list(transport); + return transport->remote_refs; +} + +#define PACK_HEADS_CHUNK_COUNT 256 + +int transport_fetch_refs(struct transport *transport, struct ref *refs) +{ + int i; + int nr_heads = 0; + char **heads = xmalloc(PACK_HEADS_CHUNK_COUNT * sizeof(char *)); + struct ref *rm; + int use_objs = !transport->ops->fetch_refs; + + for (rm = refs; rm; rm = rm->next) { + if (rm->peer_ref && + !hashcmp(rm->peer_ref->old_sha1, rm->old_sha1)) + continue; + if (use_objs) { + heads[nr_heads++] = xstrdup(sha1_to_hex(rm->old_sha1)); + } else { + heads[nr_heads++] = xstrdup(rm->name); + } + if (nr_heads % PACK_HEADS_CHUNK_COUNT == 0) + heads = xrealloc(heads, + (nr_heads + PACK_HEADS_CHUNK_COUNT) * + sizeof(char *)); + } + + if (use_objs) { + if (transport->ops->fetch_objs(transport, nr_heads, heads)) + return -1; + } else { + if (transport->ops->fetch_refs(transport, nr_heads, heads)) + return -1; + } + + /* free the memory used for the heads list ... */ + for (i = 0; i < nr_heads; i++) + free(heads[i]); + free(heads); + return 0; +} + int transport_disconnect(struct transport *transport) { int ret = 0; diff --git a/transport.h b/transport.h index 5c2eb959b2..5b0a6b0658 100644 --- a/transport.h +++ b/transport.h @@ -29,6 +29,11 @@ struct transport_ops { int (*set_option)(struct transport *connection, const char *name, const char *value); + struct ref *(*get_refs_list)(const struct transport *transport); + int (*fetch_refs)(const struct transport *transport, + int nr_refs, char **refs); + int (*fetch_objs)(const struct transport *transport, + int nr_objs, char **objs); int (*push)(struct transport *connection, int refspec_nr, const char **refspec, int flags); int (*disconnect)(struct transport *connection); @@ -40,12 +45,24 @@ struct transport *transport_get(struct remote *remote, const char *url, /* Transport options which apply to git:// and scp-style URLs */ +/* The program to use on the remote side to send a pack */ +#define TRANS_OPT_UPLOADPACK "uploadpack" + /* The program to use on the remote side to receive a pack */ #define TRANS_OPT_RECEIVEPACK "receivepack" /* Transfer the data as a thin pack if not null */ #define TRANS_OPT_THIN "thin" +/* Keep the pack that was transferred if not null */ +#define TRANS_OPT_KEEP "keep" + +/* Unpack the objects if fewer than this number of objects are fetched */ +#define TRANS_OPT_UNPACKLIMIT "unpacklimit" + +/* Limit the depth of the fetch if not null */ +#define TRANS_OPT_DEPTH "depth" + /** * Returns 0 if the option was used, non-zero otherwise. Prints a * message to stderr if the option is not used. @@ -56,6 +73,10 @@ int transport_set_option(struct transport *transport, const char *name, int transport_push(struct transport *connection, int refspec_nr, const char **refspec, int flags); +struct ref *transport_get_remote_refs(struct transport *transport); + +int transport_fetch_refs(struct transport *transport, struct ref *refs); + int transport_disconnect(struct transport *transport); #endif From 30415d50cccef0ec22bb4a6d58138760b142758d Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Mon, 10 Sep 2007 23:03:15 -0400 Subject: [PATCH 0058/1490] Move bundle specific stuff into bundle.[ch] The transport specific stuff was moved into libgit.a, and the bundle specific stuff will not be left behind. This is a big code move, with one exception: the function unbundle() no longer outputs the list of refs. You have to call list_bundle_refs() yourself for that. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- Makefile | 2 +- builtin-bundle.c | 365 +---------------------------------------------- bundle.c | 343 ++++++++++++++++++++++++++++++++++++++++++++ bundle.h | 25 ++++ 4 files changed, 375 insertions(+), 360 deletions(-) create mode 100644 bundle.c create mode 100644 bundle.h diff --git a/Makefile b/Makefile index da6abdfd81..b32c383bdc 100644 --- a/Makefile +++ b/Makefile @@ -311,7 +311,7 @@ LIB_OBJS = \ alloc.o merge-file.o path-list.o help.o unpack-trees.o $(DIFF_OBJS) \ color.o wt-status.o archive-zip.o archive-tar.o shallow.o utf8.o \ convert.o attr.o decorate.o progress.o mailmap.o symlinks.o remote.o \ - transport.o + transport.o bundle.o BUILTIN_OBJS = \ builtin-add.o \ diff --git a/builtin-bundle.c b/builtin-bundle.c index 1b650069c9..9f38e2176a 100644 --- a/builtin-bundle.c +++ b/builtin-bundle.c @@ -1,11 +1,6 @@ #include "builtin.h" #include "cache.h" -#include "object.h" -#include "commit.h" -#include "diff.h" -#include "revision.h" -#include "list-objects.h" -#include "run-command.h" +#include "bundle.h" /* * Basic handler for bundle files to connect repositories via sneakernet. @@ -16,355 +11,6 @@ static const char *bundle_usage="git-bundle (create | verify | list-heads [refname]... | unbundle [refname]... )"; -static const char bundle_signature[] = "# v2 git bundle\n"; - -struct ref_list { - unsigned int nr, alloc; - struct ref_list_entry { - unsigned char sha1[20]; - char *name; - } *list; -}; - -static void add_to_ref_list(const unsigned char *sha1, const char *name, - struct ref_list *list) -{ - if (list->nr + 1 >= list->alloc) { - list->alloc = alloc_nr(list->nr + 1); - list->list = xrealloc(list->list, - list->alloc * sizeof(list->list[0])); - } - memcpy(list->list[list->nr].sha1, sha1, 20); - list->list[list->nr].name = xstrdup(name); - list->nr++; -} - -struct bundle_header { - struct ref_list prerequisites; - struct ref_list references; -}; - -/* returns an fd */ -static int read_header(const char *path, struct bundle_header *header) { - char buffer[1024]; - int fd; - long fpos; - FILE *ffd = fopen(path, "rb"); - - if (!ffd) - return error("could not open '%s'", path); - if (!fgets(buffer, sizeof(buffer), ffd) || - strcmp(buffer, bundle_signature)) { - fclose(ffd); - return error("'%s' does not look like a v2 bundle file", path); - } - while (fgets(buffer, sizeof(buffer), ffd) - && buffer[0] != '\n') { - int is_prereq = buffer[0] == '-'; - int offset = is_prereq ? 1 : 0; - int len = strlen(buffer); - unsigned char sha1[20]; - struct ref_list *list = is_prereq ? &header->prerequisites - : &header->references; - char delim; - - if (buffer[len - 1] == '\n') - buffer[len - 1] = '\0'; - if (get_sha1_hex(buffer + offset, sha1)) { - warning("unrecognized header: %s", buffer); - continue; - } - delim = buffer[40 + offset]; - if (!isspace(delim) && (delim != '\0' || !is_prereq)) - die ("invalid header: %s", buffer); - add_to_ref_list(sha1, isspace(delim) ? - buffer + 41 + offset : "", list); - } - fpos = ftell(ffd); - fclose(ffd); - fd = open(path, O_RDONLY); - if (fd < 0) - return error("could not open '%s'", path); - lseek(fd, fpos, SEEK_SET); - return fd; -} - -static int list_refs(struct ref_list *r, int argc, const char **argv) -{ - int i; - - for (i = 0; i < r->nr; i++) { - if (argc > 1) { - int j; - for (j = 1; j < argc; j++) - if (!strcmp(r->list[i].name, argv[j])) - break; - if (j == argc) - continue; - } - printf("%s %s\n", sha1_to_hex(r->list[i].sha1), - r->list[i].name); - } - return 0; -} - -#define PREREQ_MARK (1u<<16) - -static int verify_bundle(struct bundle_header *header, int verbose) -{ - /* - * Do fast check, then if any prereqs are missing then go line by line - * to be verbose about the errors - */ - struct ref_list *p = &header->prerequisites; - struct rev_info revs; - const char *argv[] = {NULL, "--all"}; - struct object_array refs; - struct commit *commit; - int i, ret = 0, req_nr; - const char *message = "Repository lacks these prerequisite commits:"; - - init_revisions(&revs, NULL); - for (i = 0; i < p->nr; i++) { - struct ref_list_entry *e = p->list + i; - struct object *o = parse_object(e->sha1); - if (o) { - o->flags |= PREREQ_MARK; - add_pending_object(&revs, o, e->name); - continue; - } - if (++ret == 1) - error(message); - error("%s %s", sha1_to_hex(e->sha1), e->name); - } - if (revs.pending.nr != p->nr) - return ret; - req_nr = revs.pending.nr; - setup_revisions(2, argv, &revs, NULL); - - memset(&refs, 0, sizeof(struct object_array)); - for (i = 0; i < revs.pending.nr; i++) { - struct object_array_entry *e = revs.pending.objects + i; - add_object_array(e->item, e->name, &refs); - } - - prepare_revision_walk(&revs); - - i = req_nr; - while (i && (commit = get_revision(&revs))) - if (commit->object.flags & PREREQ_MARK) - i--; - - for (i = 0; i < req_nr; i++) - if (!(refs.objects[i].item->flags & SHOWN)) { - if (++ret == 1) - error(message); - error("%s %s", sha1_to_hex(refs.objects[i].item->sha1), - refs.objects[i].name); - } - - for (i = 0; i < refs.nr; i++) - clear_commit_marks((struct commit *)refs.objects[i].item, -1); - - if (verbose) { - struct ref_list *r; - - r = &header->references; - printf("The bundle contains %d ref%s\n", - r->nr, (1 < r->nr) ? "s" : ""); - list_refs(r, 0, NULL); - r = &header->prerequisites; - printf("The bundle requires these %d ref%s\n", - r->nr, (1 < r->nr) ? "s" : ""); - list_refs(r, 0, NULL); - } - return ret; -} - -static int list_heads(struct bundle_header *header, int argc, const char **argv) -{ - return list_refs(&header->references, argc, argv); -} - -static int create_bundle(struct bundle_header *header, const char *path, - int argc, const char **argv) -{ - static struct lock_file lock; - int bundle_fd = -1; - int bundle_to_stdout; - const char **argv_boundary = xmalloc((argc + 4) * sizeof(const char *)); - const char **argv_pack = xmalloc(5 * sizeof(const char *)); - int i, ref_count = 0; - char buffer[1024]; - struct rev_info revs; - struct child_process rls; - FILE *rls_fout; - - bundle_to_stdout = !strcmp(path, "-"); - if (bundle_to_stdout) - bundle_fd = 1; - else - bundle_fd = hold_lock_file_for_update(&lock, path, 1); - - /* write signature */ - write_or_die(bundle_fd, bundle_signature, strlen(bundle_signature)); - - /* init revs to list objects for pack-objects later */ - save_commit_buffer = 0; - init_revisions(&revs, NULL); - - /* write prerequisites */ - memcpy(argv_boundary + 3, argv + 1, argc * sizeof(const char *)); - argv_boundary[0] = "rev-list"; - argv_boundary[1] = "--boundary"; - argv_boundary[2] = "--pretty=oneline"; - argv_boundary[argc + 2] = NULL; - memset(&rls, 0, sizeof(rls)); - rls.argv = argv_boundary; - rls.out = -1; - rls.git_cmd = 1; - if (start_command(&rls)) - return -1; - rls_fout = fdopen(rls.out, "r"); - while (fgets(buffer, sizeof(buffer), rls_fout)) { - unsigned char sha1[20]; - if (buffer[0] == '-') { - write_or_die(bundle_fd, buffer, strlen(buffer)); - if (!get_sha1_hex(buffer + 1, sha1)) { - struct object *object = parse_object(sha1); - object->flags |= UNINTERESTING; - add_pending_object(&revs, object, buffer); - } - } else if (!get_sha1_hex(buffer, sha1)) { - struct object *object = parse_object(sha1); - object->flags |= SHOWN; - } - } - fclose(rls_fout); - if (finish_command(&rls)) - return error("rev-list died"); - - /* write references */ - argc = setup_revisions(argc, argv, &revs, NULL); - if (argc > 1) - return error("unrecognized argument: %s'", argv[1]); - - for (i = 0; i < revs.pending.nr; i++) { - struct object_array_entry *e = revs.pending.objects + i; - unsigned char sha1[20]; - char *ref; - - if (e->item->flags & UNINTERESTING) - continue; - if (dwim_ref(e->name, strlen(e->name), sha1, &ref) != 1) - continue; - /* - * Make sure the refs we wrote out is correct; --max-count and - * other limiting options could have prevented all the tips - * from getting output. - * - * Non commit objects such as tags and blobs do not have - * this issue as they are not affected by those extra - * constraints. - */ - if (!(e->item->flags & SHOWN) && e->item->type == OBJ_COMMIT) { - warning("ref '%s' is excluded by the rev-list options", - e->name); - free(ref); - continue; - } - /* - * If you run "git bundle create bndl v1.0..v2.0", the - * name of the positive ref is "v2.0" but that is the - * commit that is referenced by the tag, and not the tag - * itself. - */ - if (hashcmp(sha1, e->item->sha1)) { - /* - * Is this the positive end of a range expressed - * in terms of a tag (e.g. v2.0 from the range - * "v1.0..v2.0")? - */ - struct commit *one = lookup_commit_reference(sha1); - struct object *obj; - - if (e->item == &(one->object)) { - /* - * Need to include e->name as an - * independent ref to the pack-objects - * input, so that the tag is included - * in the output; otherwise we would - * end up triggering "empty bundle" - * error. - */ - obj = parse_object(sha1); - obj->flags |= SHOWN; - add_pending_object(&revs, obj, e->name); - } - free(ref); - continue; - } - - ref_count++; - write_or_die(bundle_fd, sha1_to_hex(e->item->sha1), 40); - write_or_die(bundle_fd, " ", 1); - write_or_die(bundle_fd, ref, strlen(ref)); - write_or_die(bundle_fd, "\n", 1); - free(ref); - } - if (!ref_count) - die ("Refusing to create empty bundle."); - - /* end header */ - write_or_die(bundle_fd, "\n", 1); - - /* write pack */ - argv_pack[0] = "pack-objects"; - argv_pack[1] = "--all-progress"; - argv_pack[2] = "--stdout"; - argv_pack[3] = "--thin"; - argv_pack[4] = NULL; - memset(&rls, 0, sizeof(rls)); - rls.argv = argv_pack; - rls.in = -1; - rls.out = bundle_fd; - rls.git_cmd = 1; - if (start_command(&rls)) - return error("Could not spawn pack-objects"); - for (i = 0; i < revs.pending.nr; i++) { - struct object *object = revs.pending.objects[i].item; - if (object->flags & UNINTERESTING) - write(rls.in, "^", 1); - write(rls.in, sha1_to_hex(object->sha1), 40); - write(rls.in, "\n", 1); - } - if (finish_command(&rls)) - return error ("pack-objects died"); - close(bundle_fd); - if (!bundle_to_stdout) - commit_lock_file(&lock); - return 0; -} - -static int unbundle(struct bundle_header *header, int bundle_fd, - int argc, const char **argv) -{ - const char *argv_index_pack[] = {"index-pack", - "--fix-thin", "--stdin", NULL}; - struct child_process ip; - - if (verify_bundle(header, 0)) - return -1; - memset(&ip, 0, sizeof(ip)); - ip.argv = argv_index_pack; - ip.in = bundle_fd; - ip.no_stdout = 1; - ip.git_cmd = 1; - if (run_command(&ip)) - return error("index-pack died"); - return list_heads(header, argc, argv); -} - int cmd_bundle(int argc, const char **argv, const char *prefix) { struct bundle_header header; @@ -388,8 +34,8 @@ int cmd_bundle(int argc, const char **argv, const char *prefix) } memset(&header, 0, sizeof(header)); - if (strcmp(cmd, "create") && - (bundle_fd = read_header(bundle_file, &header)) < 0) + if (strcmp(cmd, "create") && (bundle_fd = + read_bundle_header(bundle_file, &header)) < 0) return 1; if (!strcmp(cmd, "verify")) { @@ -401,7 +47,7 @@ int cmd_bundle(int argc, const char **argv, const char *prefix) } if (!strcmp(cmd, "list-heads")) { close(bundle_fd); - return !!list_heads(&header, argc, argv); + return !!list_bundle_refs(&header, argc, argv); } if (!strcmp(cmd, "create")) { if (nongit) @@ -410,7 +56,8 @@ int cmd_bundle(int argc, const char **argv, const char *prefix) } else if (!strcmp(cmd, "unbundle")) { if (nongit) die("Need a repository to unbundle."); - return !!unbundle(&header, bundle_fd, argc, argv); + return !!unbundle(&header, bundle_fd) || + list_bundle_refs(&header, argc, argv); } else usage(bundle_usage); } diff --git a/bundle.c b/bundle.c new file mode 100644 index 0000000000..0869fcf026 --- /dev/null +++ b/bundle.c @@ -0,0 +1,343 @@ +#include "cache.h" +#include "bundle.h" +#include "object.h" +#include "commit.h" +#include "diff.h" +#include "revision.h" +#include "list-objects.h" +#include "run-command.h" + +static const char bundle_signature[] = "# v2 git bundle\n"; + +static void add_to_ref_list(const unsigned char *sha1, const char *name, + struct ref_list *list) +{ + if (list->nr + 1 >= list->alloc) { + list->alloc = alloc_nr(list->nr + 1); + list->list = xrealloc(list->list, + list->alloc * sizeof(list->list[0])); + } + memcpy(list->list[list->nr].sha1, sha1, 20); + list->list[list->nr].name = xstrdup(name); + list->nr++; +} + +/* returns an fd */ +int read_bundle_header(const char *path, struct bundle_header *header) { + char buffer[1024]; + int fd; + long fpos; + FILE *ffd = fopen(path, "rb"); + + if (!ffd) + return error("could not open '%s'", path); + if (!fgets(buffer, sizeof(buffer), ffd) || + strcmp(buffer, bundle_signature)) { + fclose(ffd); + return error("'%s' does not look like a v2 bundle file", path); + } + while (fgets(buffer, sizeof(buffer), ffd) + && buffer[0] != '\n') { + int is_prereq = buffer[0] == '-'; + int offset = is_prereq ? 1 : 0; + int len = strlen(buffer); + unsigned char sha1[20]; + struct ref_list *list = is_prereq ? &header->prerequisites + : &header->references; + char delim; + + if (buffer[len - 1] == '\n') + buffer[len - 1] = '\0'; + if (get_sha1_hex(buffer + offset, sha1)) { + warning("unrecognized header: %s", buffer); + continue; + } + delim = buffer[40 + offset]; + if (!isspace(delim) && (delim != '\0' || !is_prereq)) + die ("invalid header: %s", buffer); + add_to_ref_list(sha1, isspace(delim) ? + buffer + 41 + offset : "", list); + } + fpos = ftell(ffd); + fclose(ffd); + fd = open(path, O_RDONLY); + if (fd < 0) + return error("could not open '%s'", path); + lseek(fd, fpos, SEEK_SET); + return fd; +} + +static int list_refs(struct ref_list *r, int argc, const char **argv) +{ + int i; + + for (i = 0; i < r->nr; i++) { + if (argc > 1) { + int j; + for (j = 1; j < argc; j++) + if (!strcmp(r->list[i].name, argv[j])) + break; + if (j == argc) + continue; + } + printf("%s %s\n", sha1_to_hex(r->list[i].sha1), + r->list[i].name); + } + return 0; +} + +#define PREREQ_MARK (1u<<16) + +int verify_bundle(struct bundle_header *header, int verbose) +{ + /* + * Do fast check, then if any prereqs are missing then go line by line + * to be verbose about the errors + */ + struct ref_list *p = &header->prerequisites; + struct rev_info revs; + const char *argv[] = {NULL, "--all"}; + struct object_array refs; + struct commit *commit; + int i, ret = 0, req_nr; + const char *message = "Repository lacks these prerequisite commits:"; + + init_revisions(&revs, NULL); + for (i = 0; i < p->nr; i++) { + struct ref_list_entry *e = p->list + i; + struct object *o = parse_object(e->sha1); + if (o) { + o->flags |= PREREQ_MARK; + add_pending_object(&revs, o, e->name); + continue; + } + if (++ret == 1) + error(message); + error("%s %s", sha1_to_hex(e->sha1), e->name); + } + if (revs.pending.nr != p->nr) + return ret; + req_nr = revs.pending.nr; + setup_revisions(2, argv, &revs, NULL); + + memset(&refs, 0, sizeof(struct object_array)); + for (i = 0; i < revs.pending.nr; i++) { + struct object_array_entry *e = revs.pending.objects + i; + add_object_array(e->item, e->name, &refs); + } + + prepare_revision_walk(&revs); + + i = req_nr; + while (i && (commit = get_revision(&revs))) + if (commit->object.flags & PREREQ_MARK) + i--; + + for (i = 0; i < req_nr; i++) + if (!(refs.objects[i].item->flags & SHOWN)) { + if (++ret == 1) + error(message); + error("%s %s", sha1_to_hex(refs.objects[i].item->sha1), + refs.objects[i].name); + } + + for (i = 0; i < refs.nr; i++) + clear_commit_marks((struct commit *)refs.objects[i].item, -1); + + if (verbose) { + struct ref_list *r; + + r = &header->references; + printf("The bundle contains %d ref%s\n", + r->nr, (1 < r->nr) ? "s" : ""); + list_refs(r, 0, NULL); + r = &header->prerequisites; + printf("The bundle requires these %d ref%s\n", + r->nr, (1 < r->nr) ? "s" : ""); + list_refs(r, 0, NULL); + } + return ret; +} + +int list_bundle_refs(struct bundle_header *header, int argc, const char **argv) +{ + return list_refs(&header->references, argc, argv); +} + +int create_bundle(struct bundle_header *header, const char *path, + int argc, const char **argv) +{ + static struct lock_file lock; + int bundle_fd = -1; + int bundle_to_stdout; + const char **argv_boundary = xmalloc((argc + 4) * sizeof(const char *)); + const char **argv_pack = xmalloc(5 * sizeof(const char *)); + int i, ref_count = 0; + char buffer[1024]; + struct rev_info revs; + struct child_process rls; + FILE *rls_fout; + + bundle_to_stdout = !strcmp(path, "-"); + if (bundle_to_stdout) + bundle_fd = 1; + else + bundle_fd = hold_lock_file_for_update(&lock, path, 1); + + /* write signature */ + write_or_die(bundle_fd, bundle_signature, strlen(bundle_signature)); + + /* init revs to list objects for pack-objects later */ + save_commit_buffer = 0; + init_revisions(&revs, NULL); + + /* write prerequisites */ + memcpy(argv_boundary + 3, argv + 1, argc * sizeof(const char *)); + argv_boundary[0] = "rev-list"; + argv_boundary[1] = "--boundary"; + argv_boundary[2] = "--pretty=oneline"; + argv_boundary[argc + 2] = NULL; + memset(&rls, 0, sizeof(rls)); + rls.argv = argv_boundary; + rls.out = -1; + rls.git_cmd = 1; + if (start_command(&rls)) + return -1; + rls_fout = fdopen(rls.out, "r"); + while (fgets(buffer, sizeof(buffer), rls_fout)) { + unsigned char sha1[20]; + if (buffer[0] == '-') { + write_or_die(bundle_fd, buffer, strlen(buffer)); + if (!get_sha1_hex(buffer + 1, sha1)) { + struct object *object = parse_object(sha1); + object->flags |= UNINTERESTING; + add_pending_object(&revs, object, buffer); + } + } else if (!get_sha1_hex(buffer, sha1)) { + struct object *object = parse_object(sha1); + object->flags |= SHOWN; + } + } + fclose(rls_fout); + if (finish_command(&rls)) + return error("rev-list died"); + + /* write references */ + argc = setup_revisions(argc, argv, &revs, NULL); + if (argc > 1) + return error("unrecognized argument: %s'", argv[1]); + + for (i = 0; i < revs.pending.nr; i++) { + struct object_array_entry *e = revs.pending.objects + i; + unsigned char sha1[20]; + char *ref; + + if (e->item->flags & UNINTERESTING) + continue; + if (dwim_ref(e->name, strlen(e->name), sha1, &ref) != 1) + continue; + /* + * Make sure the refs we wrote out is correct; --max-count and + * other limiting options could have prevented all the tips + * from getting output. + * + * Non commit objects such as tags and blobs do not have + * this issue as they are not affected by those extra + * constraints. + */ + if (!(e->item->flags & SHOWN) && e->item->type == OBJ_COMMIT) { + warning("ref '%s' is excluded by the rev-list options", + e->name); + free(ref); + continue; + } + /* + * If you run "git bundle create bndl v1.0..v2.0", the + * name of the positive ref is "v2.0" but that is the + * commit that is referenced by the tag, and not the tag + * itself. + */ + if (hashcmp(sha1, e->item->sha1)) { + /* + * Is this the positive end of a range expressed + * in terms of a tag (e.g. v2.0 from the range + * "v1.0..v2.0")? + */ + struct commit *one = lookup_commit_reference(sha1); + struct object *obj; + + if (e->item == &(one->object)) { + /* + * Need to include e->name as an + * independent ref to the pack-objects + * input, so that the tag is included + * in the output; otherwise we would + * end up triggering "empty bundle" + * error. + */ + obj = parse_object(sha1); + obj->flags |= SHOWN; + add_pending_object(&revs, obj, e->name); + } + free(ref); + continue; + } + + ref_count++; + write_or_die(bundle_fd, sha1_to_hex(e->item->sha1), 40); + write_or_die(bundle_fd, " ", 1); + write_or_die(bundle_fd, ref, strlen(ref)); + write_or_die(bundle_fd, "\n", 1); + free(ref); + } + if (!ref_count) + die ("Refusing to create empty bundle."); + + /* end header */ + write_or_die(bundle_fd, "\n", 1); + + /* write pack */ + argv_pack[0] = "pack-objects"; + argv_pack[1] = "--all-progress"; + argv_pack[2] = "--stdout"; + argv_pack[3] = "--thin"; + argv_pack[4] = NULL; + memset(&rls, 0, sizeof(rls)); + rls.argv = argv_pack; + rls.in = -1; + rls.out = bundle_fd; + rls.git_cmd = 1; + if (start_command(&rls)) + return error("Could not spawn pack-objects"); + for (i = 0; i < revs.pending.nr; i++) { + struct object *object = revs.pending.objects[i].item; + if (object->flags & UNINTERESTING) + write(rls.in, "^", 1); + write(rls.in, sha1_to_hex(object->sha1), 40); + write(rls.in, "\n", 1); + } + if (finish_command(&rls)) + return error ("pack-objects died"); + close(bundle_fd); + if (!bundle_to_stdout) + commit_lock_file(&lock); + return 0; +} + +int unbundle(struct bundle_header *header, int bundle_fd) +{ + const char *argv_index_pack[] = {"index-pack", + "--fix-thin", "--stdin", NULL}; + struct child_process ip; + + if (verify_bundle(header, 0)) + return -1; + memset(&ip, 0, sizeof(ip)); + ip.argv = argv_index_pack; + ip.in = bundle_fd; + ip.no_stdout = 1; + ip.git_cmd = 1; + if (run_command(&ip)) + return error("index-pack died"); + return 0; +} diff --git a/bundle.h b/bundle.h new file mode 100644 index 0000000000..e2aedd60d6 --- /dev/null +++ b/bundle.h @@ -0,0 +1,25 @@ +#ifndef BUNDLE_H +#define BUNDLE_H + +struct ref_list { + unsigned int nr, alloc; + struct ref_list_entry { + unsigned char sha1[20]; + char *name; + } *list; +}; + +struct bundle_header { + struct ref_list prerequisites; + struct ref_list references; +}; + +int read_bundle_header(const char *path, struct bundle_header *header); +int create_bundle(struct bundle_header *header, const char *path, + int argc, const char **argv); +int verify_bundle(struct bundle_header *header, int verbose); +int unbundle(struct bundle_header *header, int bundle_fd); +int list_bundle_refs(struct bundle_header *header, + int argc, const char **argv); + +#endif From c7a8a16239c6bdbb4041dd8a8773ae055d3cccf8 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Mon, 10 Sep 2007 23:03:21 -0400 Subject: [PATCH 0059/1490] Add bundle transport Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- transport.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/transport.c b/transport.c index 1e7374977e..e0111dcf0b 100644 --- a/transport.c +++ b/transport.c @@ -5,6 +5,7 @@ #include "pkt-line.h" #include "fetch-pack.h" #include "walker.h" +#include "bundle.h" /* Generic functions for using commit walkers */ @@ -184,7 +185,55 @@ static const struct transport_ops curl_transport = { /* disconnect */ disconnect_walker }; +struct bundle_transport_data { + int fd; + struct bundle_header header; +}; + +static struct ref *get_refs_from_bundle(const struct transport *transport) +{ + struct bundle_transport_data *data = transport->data; + struct ref *result = NULL; + int i; + + if (data->fd > 0) + close(data->fd); + data->fd = read_bundle_header(transport->url, &data->header); + if (data->fd < 0) + die ("Could not read bundle '%s'.", transport->url); + for (i = 0; i < data->header.references.nr; i++) { + struct ref_list_entry *e = data->header.references.list + i; + struct ref *ref = alloc_ref(strlen(e->name)); + hashcpy(ref->old_sha1, e->sha1); + strcpy(ref->name, e->name); + ref->next = result; + result = ref; + } + return result; +} + +static int fetch_refs_from_bundle(const struct transport *transport, + int nr_heads, char **heads) +{ + struct bundle_transport_data *data = transport->data; + return unbundle(&data->header, data->fd); +} + +static int close_bundle(struct transport *transport) +{ + struct bundle_transport_data *data = transport->data; + if (data->fd > 0) + close(data->fd); + return 0; +} + static const struct transport_ops bundle_transport = { + /* set_option */ NULL, + /* get_refs_list */ get_refs_from_bundle, + /* fetch_refs */ fetch_refs_from_bundle, + /* fetch_objs */ NULL, + /* push */ NULL, + /* disconnect */ close_bundle }; struct git_transport_data { @@ -367,8 +416,9 @@ struct transport *transport_get(struct remote *remote, const char *url, else ret->data = NULL; } else if (is_local(url) && is_file(url)) { + struct bundle_transport_data *data = xcalloc(1, sizeof(*data)); ret = xmalloc(sizeof(*ret)); - ret->data = NULL; + ret->data = data; ret->ops = &bundle_transport; } else { struct git_transport_data *data = xcalloc(1, sizeof(*data)); From b888d61c8308027433df9c243fa551f42db1c76a Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Mon, 10 Sep 2007 23:03:25 -0400 Subject: [PATCH 0060/1490] Make fetch a builtin Thanks to Johannes Schindelin for review and fixes, and Julian Phillips for the original C translation. This changes a few small bits of behavior: branch..merge is parsed as if it were the lhs of a fetch refspec, and does not have to exactly match the actual lhs of a refspec, so long as it is a valid abbreviation for the same ref. branch..merge is no longer ignored if the remote is configured with a branches/* file. Neither behavior is useful, because there can only be one ref that gets fetched, but this is more consistant. Also, fetch prints different information to standard out. Signed-off-by: Daniel Barkalow Signed-off-by: Junio C Hamano --- Documentation/config.txt | 9 +- Makefile | 2 +- builtin-fetch.c | 552 ++++++++++++++++++ builtin.h | 1 + cache.h | 1 + git-fetch.sh => contrib/examples/git-fetch.sh | 0 git.c | 1 + t/t5515/fetch.br-branches-default-merge | 2 +- ...br-branches-default-merge_branches-default | 2 +- t/t5515/fetch.br-branches-default-octopus | 2 +- ...-branches-default-octopus_branches-default | 2 +- t/t5515/fetch.br-branches-one-merge | 2 +- .../fetch.br-branches-one-merge_branches-one | 2 +- t/t5515/fetch.br-config-glob-octopus | 2 +- .../fetch.br-config-glob-octopus_config-glob | 2 +- t/t5515/fetch.br-remote-glob-octopus | 2 +- .../fetch.br-remote-glob-octopus_remote-glob | 2 +- 17 files changed, 571 insertions(+), 15 deletions(-) create mode 100644 builtin-fetch.c rename git-fetch.sh => contrib/examples/git-fetch.sh (100%) diff --git a/Documentation/config.txt b/Documentation/config.txt index 015910f27a..518acc6194 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -324,10 +324,11 @@ branch..remote:: If this option is not given, `git fetch` defaults to remote "origin". branch..merge:: - When in branch , it tells `git fetch` the default refspec to - be marked for merging in FETCH_HEAD. The value has exactly to match - a remote part of one of the refspecs which are fetched from the remote - given by "branch..remote". + When in branch , it tells `git fetch` the default + refspec to be marked for merging in FETCH_HEAD. The value is + handled like the remote part of a refspec, and must match a + ref which is fetched from the remote given by + "branch..remote". The merge information is used by `git pull` (which at first calls `git fetch`) to lookup the default branch for merging. Without this option, `git pull` defaults to merge the first refspec fetched. diff --git a/Makefile b/Makefile index b32c383bdc..5b447d4f73 100644 --- a/Makefile +++ b/Makefile @@ -207,7 +207,6 @@ BASIC_LDFLAGS = SCRIPT_SH = \ git-bisect.sh git-checkout.sh \ git-clean.sh git-clone.sh git-commit.sh \ - git-fetch.sh \ git-ls-remote.sh \ git-merge-one-file.sh git-mergetool.sh git-parse-remote.sh \ git-pull.sh git-rebase.sh git-rebase--interactive.sh \ @@ -332,6 +331,7 @@ BUILTIN_OBJS = \ builtin-diff-files.o \ builtin-diff-index.o \ builtin-diff-tree.o \ + builtin-fetch.o \ builtin-fetch-pack.o \ builtin-fetch--tool.o \ builtin-fmt-merge-msg.o \ diff --git a/builtin-fetch.c b/builtin-fetch.c new file mode 100644 index 0000000000..64392f317d --- /dev/null +++ b/builtin-fetch.c @@ -0,0 +1,552 @@ +/* + * "git fetch" + */ +#include "cache.h" +#include "refs.h" +#include "commit.h" +#include "builtin.h" +#include "path-list.h" +#include "remote.h" +#include "transport.h" + +static const char fetch_usage[] = "git-fetch [-a | --append] [--upload-pack ] [-f | --force] [--no-tags] [-t | --tags] [-k | --keep] [-u | --update-head-ok] [--depth ] [-v | --verbose] [ ...]"; + +static int append, force, tags, no_tags, update_head_ok, verbose, quiet; + +static int unpacklimit; + +static char *default_rla = NULL; + +static void find_merge_config(struct ref *ref_map, struct remote *remote) +{ + struct ref *rm = ref_map; + struct branch *branch = branch_get(NULL); + + for (rm = ref_map; rm; rm = rm->next) { + if (!branch_has_merge_config(branch)) { + if (remote && remote->fetch && + !strcmp(remote->fetch[0].src, rm->name)) + rm->merge = 1; + } else { + if (branch_merges(branch, rm->name)) + rm->merge = 1; + } + } +} + +static struct ref *get_ref_map(struct transport *transport, + struct refspec *refs, int ref_count, int tags, + int *autotags) +{ + int i; + struct ref *rm; + struct ref *ref_map = NULL; + struct ref **tail = &ref_map; + + struct ref *remote_refs = transport_get_remote_refs(transport); + + if (ref_count || tags) { + for (i = 0; i < ref_count; i++) { + get_fetch_map(remote_refs, &refs[i], &tail); + if (refs[i].dst && refs[i].dst[0]) + *autotags = 1; + } + /* Merge everything on the command line, but not --tags */ + for (rm = ref_map; rm; rm = rm->next) + rm->merge = 1; + if (tags) { + struct refspec refspec; + refspec.src = "refs/tags/"; + refspec.dst = "refs/tags/"; + refspec.pattern = 1; + refspec.force = 0; + get_fetch_map(remote_refs, &refspec, &tail); + } + } else { + /* Use the defaults */ + struct remote *remote = transport->remote; + if (remote->fetch_refspec_nr) { + for (i = 0; i < remote->fetch_refspec_nr; i++) { + get_fetch_map(remote_refs, &remote->fetch[i], &tail); + if (remote->fetch[i].dst && + remote->fetch[i].dst[0]) + *autotags = 1; + } + find_merge_config(ref_map, remote); + } else { + ref_map = get_remote_ref(remote_refs, "HEAD"); + + ref_map->merge = 1; + } + } + + return ref_map; +} + +static void show_new(enum object_type type, unsigned char *sha1_new) +{ + fprintf(stderr, " %s: %s\n", typename(type), + find_unique_abbrev(sha1_new, DEFAULT_ABBREV)); +} + +static int s_update_ref(const char *action, + struct ref *ref, + int check_old) +{ + char msg[1024]; + char *rla = getenv("GIT_REFLOG_ACTION"); + static struct ref_lock *lock; + + if (!rla) + rla = default_rla; + snprintf(msg, sizeof(msg), "%s: %s", rla, action); + lock = lock_any_ref_for_update(ref->name, + check_old ? ref->old_sha1 : NULL, 0); + if (!lock) + return 1; + if (write_ref_sha1(lock, ref->new_sha1, msg) < 0) + return 1; + return 0; +} + +static int update_local_ref(struct ref *ref, + const char *note, + int verbose) +{ + char oldh[41], newh[41]; + struct commit *current = NULL, *updated; + enum object_type type; + struct branch *current_branch = branch_get(NULL); + + type = sha1_object_info(ref->new_sha1, NULL); + if (type < 0) + die("object %s not found", sha1_to_hex(ref->new_sha1)); + + if (!*ref->name) { + /* Not storing */ + if (verbose) { + fprintf(stderr, "* fetched %s\n", note); + show_new(type, ref->new_sha1); + } + return 0; + } + + if (!hashcmp(ref->old_sha1, ref->new_sha1)) { + if (verbose) { + fprintf(stderr, "* %s: same as %s\n", + ref->name, note); + show_new(type, ref->new_sha1); + } + return 0; + } + + if (!strcmp(ref->name, current_branch->name) && + !(update_head_ok || is_bare_repository()) && + !is_null_sha1(ref->old_sha1)) { + /* + * If this is the head, and it's not okay to update + * the head, and the old value of the head isn't empty... + */ + fprintf(stderr, + " * %s: Cannot fetch into the current branch.\n", + ref->name); + return 1; + } + + if (!is_null_sha1(ref->old_sha1) && + !prefixcmp(ref->name, "refs/tags/")) { + fprintf(stderr, "* %s: updating with %s\n", + ref->name, note); + show_new(type, ref->new_sha1); + return s_update_ref("updating tag", ref, 0); + } + + current = lookup_commit_reference(ref->old_sha1); + updated = lookup_commit_reference(ref->new_sha1); + if (!current || !updated) { + char *msg; + if (!strncmp(ref->name, "refs/tags/", 10)) + msg = "storing tag"; + else + msg = "storing head"; + fprintf(stderr, "* %s: storing %s\n", + ref->name, note); + show_new(type, ref->new_sha1); + return s_update_ref(msg, ref, 0); + } + + strcpy(oldh, find_unique_abbrev(current->object.sha1, DEFAULT_ABBREV)); + strcpy(newh, find_unique_abbrev(ref->new_sha1, DEFAULT_ABBREV)); + + if (in_merge_bases(current, &updated, 1)) { + fprintf(stderr, "* %s: fast forward to %s\n", + ref->name, note); + fprintf(stderr, " old..new: %s..%s\n", oldh, newh); + return s_update_ref("fast forward", ref, 1); + } + if (!force && !ref->force) { + fprintf(stderr, + "* %s: not updating to non-fast forward %s\n", + ref->name, note); + fprintf(stderr, + " old...new: %s...%s\n", oldh, newh); + return 1; + } + fprintf(stderr, + "* %s: forcing update to non-fast forward %s\n", + ref->name, note); + fprintf(stderr, " old...new: %s...%s\n", oldh, newh); + return s_update_ref("forced-update", ref, 1); +} + +static void store_updated_refs(const char *url, struct ref *ref_map) +{ + FILE *fp; + struct commit *commit; + int url_len, i, note_len; + char note[1024]; + const char *what, *kind; + struct ref *rm; + + fp = fopen(git_path("FETCH_HEAD"), "a"); + for (rm = ref_map; rm; rm = rm->next) { + struct ref *ref = NULL; + + if (rm->peer_ref) { + ref = xcalloc(1, sizeof(*ref) + strlen(rm->peer_ref->name) + 1); + strcpy(ref->name, rm->peer_ref->name); + hashcpy(ref->old_sha1, rm->peer_ref->old_sha1); + hashcpy(ref->new_sha1, rm->old_sha1); + ref->force = rm->force; + } + + commit = lookup_commit_reference(rm->old_sha1); + if (!commit) + rm->merge = 0; + + if (!strcmp(rm->name, "HEAD")) { + kind = ""; + what = ""; + } + else if (!prefixcmp(rm->name, "refs/heads/")) { + kind = "branch"; + what = rm->name + 11; + } + else if (!prefixcmp(rm->name, "refs/tags/")) { + kind = "tag"; + what = rm->name + 10; + } + else if (!prefixcmp(rm->name, "refs/remotes/")) { + kind = "remote branch"; + what = rm->name + 13; + } + else { + kind = ""; + what = rm->name; + } + + url_len = strlen(url); + for (i = url_len - 1; url[i] == '/' && 0 <= i; i--) + ; + url_len = i + 1; + if (4 < i && !strncmp(".git", url + i - 3, 4)) + url_len = i - 3; + + note_len = 0; + if (*what) { + if (*kind) + note_len += sprintf(note + note_len, "%s ", + kind); + note_len += sprintf(note + note_len, "'%s' of ", what); + } + note_len += sprintf(note + note_len, "%.*s", url_len, url); + fprintf(fp, "%s\t%s\t%s\n", + sha1_to_hex(commit ? commit->object.sha1 : + rm->old_sha1), + rm->merge ? "" : "not-for-merge", + note); + + if (ref) + update_local_ref(ref, note, verbose); + } + fclose(fp); +} + +static int fetch_refs(struct transport *transport, struct ref *ref_map) +{ + int ret = transport_fetch_refs(transport, ref_map); + if (!ret) + store_updated_refs(transport->url, ref_map); + return ret; +} + +static int add_existing(const char *refname, const unsigned char *sha1, + int flag, void *cbdata) +{ + struct path_list *list = (struct path_list *)cbdata; + path_list_insert(refname, list); + return 0; +} + +static struct ref *find_non_local_tags(struct transport *transport, + struct ref *fetch_map) +{ + static struct path_list existing_refs = { NULL, 0, 0, 0 }; + struct path_list new_refs = { NULL, 0, 0, 1 }; + char *ref_name; + int ref_name_len; + unsigned char *ref_sha1; + struct ref *tag_ref; + struct ref *rm = NULL; + struct ref *ref_map = NULL; + struct ref **tail = &ref_map; + struct ref *ref; + + for_each_ref(add_existing, &existing_refs); + for (ref = transport_get_remote_refs(transport); ref; ref = ref->next) { + if (prefixcmp(ref->name, "refs/tags")) + continue; + + ref_name = xstrdup(ref->name); + ref_name_len = strlen(ref_name); + ref_sha1 = ref->old_sha1; + + if (!strcmp(ref_name + ref_name_len - 3, "^{}")) { + ref_name[ref_name_len - 3] = 0; + tag_ref = transport_get_remote_refs(transport); + while (tag_ref) { + if (!strcmp(tag_ref->name, ref_name)) { + ref_sha1 = tag_ref->old_sha1; + break; + } + tag_ref = tag_ref->next; + } + } + + if (!path_list_has_path(&existing_refs, ref_name) && + !path_list_has_path(&new_refs, ref_name) && + lookup_object(ref->old_sha1)) { + fprintf(stderr, "Auto-following %s\n", + ref_name); + + path_list_insert(ref_name, &new_refs); + + rm = alloc_ref(strlen(ref_name) + 1); + strcpy(rm->name, ref_name); + rm->peer_ref = alloc_ref(strlen(ref_name) + 1); + strcpy(rm->peer_ref->name, ref_name); + hashcpy(rm->old_sha1, ref_sha1); + + *tail = rm; + tail = &rm->next; + } + free(ref_name); + } + + return ref_map; +} + +static int do_fetch(struct transport *transport, + struct refspec *refs, int ref_count) +{ + struct ref *ref_map, *fetch_map; + struct ref *rm; + int autotags = (transport->remote->fetch_tags == 1); + if (transport->remote->fetch_tags == 2 && !no_tags) + tags = 1; + if (transport->remote->fetch_tags == -1) + no_tags = 1; + + if (!transport->ops || !transport->ops->get_refs_list || + !(transport->ops->fetch_refs || transport->ops->fetch_objs)) + die("Don't know how to fetch from %s", transport->url); + + /* if not appending, truncate FETCH_HEAD */ + if (!append) + fclose(fopen(git_path("FETCH_HEAD"), "w")); + + ref_map = get_ref_map(transport, refs, ref_count, tags, &autotags); + + for (rm = ref_map; rm; rm = rm->next) { + if (rm->peer_ref) + read_ref(rm->peer_ref->name, rm->peer_ref->old_sha1); + + printf("%s : %s\n", rm->name, rm->peer_ref ? rm->peer_ref->name : NULL); + printf(" < %s\n", sha1_to_hex(rm->old_sha1)); + if (rm->peer_ref) + printf(" > %s\n", sha1_to_hex(rm->peer_ref->old_sha1)); + if (!rm->peer_ref || + hashcmp(rm->old_sha1, rm->peer_ref->old_sha1)) { + printf("%s needs update.\n", rm->name); + } + } + + if (fetch_refs(transport, ref_map)) { + free_refs(ref_map); + return 1; + } + + fetch_map = ref_map; + + /* if neither --no-tags nor --tags was specified, do automated tag + * following ... */ + if (!(tags || no_tags) && autotags) { + ref_map = find_non_local_tags(transport, fetch_map); + if (ref_map) { + transport_set_option(transport, TRANS_OPT_DEPTH, "0"); + fetch_refs(transport, ref_map); + } + free_refs(ref_map); + } + + free_refs(fetch_map); + + return 0; +} + +static int fetch_config(const char *var, const char *value) +{ + if (strcmp(var, "fetch.unpacklimit") == 0) { + unpacklimit = git_config_int(var, value); + return 0; + } + + if (strcmp(var, "transfer.unpacklimit") == 0) { + unpacklimit = git_config_int(var, value); + return 0; + } + + return git_default_config(var, value); +} + +int cmd_fetch(int argc, const char **argv, const char *prefix) +{ + struct remote *remote; + struct transport *transport; + int i, j, rla_offset; + static const char **refs = NULL; + int ref_nr = 0; + int cmd_len = 0; + const char *depth = NULL, *upload_pack = NULL; + int keep = 0; + + git_config(fetch_config); + + for (i = 1; i < argc; i++) { + const char *arg = argv[i]; + cmd_len += strlen(arg); + + if (arg[0] != '-') + break; + if (!strcmp(arg, "--append") || !strcmp(arg, "-a")) { + append = 1; + continue; + } + if (!prefixcmp(arg, "--upload-pack=")) { + upload_pack = arg + 14; + continue; + } + if (!strcmp(arg, "--upload-pack")) { + i++; + if (i == argc) + usage(fetch_usage); + upload_pack = argv[i]; + continue; + } + if (!strcmp(arg, "--force") || !strcmp(arg, "-f")) { + force = 1; + continue; + } + if (!strcmp(arg, "--no-tags")) { + no_tags = 1; + continue; + } + if (!strcmp(arg, "--tags") || !strcmp(arg, "-t")) { + tags = 1; + continue; + } + if (!strcmp(arg, "--keep") || !strcmp(arg, "-k")) { + keep = 1; + continue; + } + if (!strcmp(arg, "--update-head-ok") || !strcmp(arg, "-u")) { + update_head_ok = 1; + continue; + } + if (!prefixcmp(arg, "--depth=")) { + depth = arg + 8; + continue; + } + if (!strcmp(arg, "--depth")) { + i++; + if (i == argc) + usage(fetch_usage); + depth = argv[i]; + continue; + } + if (!strcmp(arg, "--quiet")) { + quiet = 1; + continue; + } + if (!strcmp(arg, "--verbose") || !strcmp(arg, "-v")) { + verbose++; + continue; + } + usage(fetch_usage); + } + + for (j = i; j < argc; j++) + cmd_len += strlen(argv[j]); + + default_rla = xmalloc(cmd_len + 5 + argc + 1); + sprintf(default_rla, "fetch"); + rla_offset = strlen(default_rla); + for (j = 1; j < argc; j++) { + sprintf(default_rla + rla_offset, " %s", argv[j]); + rla_offset += strlen(argv[j]); + } + + if (i == argc) + remote = remote_get(NULL); + else + remote = remote_get(argv[i++]); + + transport = transport_get(remote, remote->uri[0], 1); + if (verbose >= 2) + transport->verbose = 1; + if (quiet) + transport->verbose = 0; + if (upload_pack) + transport_set_option(transport, TRANS_OPT_UPLOADPACK, upload_pack); + if (keep) + transport_set_option(transport, TRANS_OPT_KEEP, "yes"); + transport_set_option(transport, TRANS_OPT_DEPTH, depth); + + if (!transport->url) + die("Where do you want to fetch from today?"); + + if (i < argc) { + int j = 0; + refs = xcalloc(argc - i + 1, sizeof(const char *)); + while (i < argc) { + if (!strcmp(argv[i], "tag")) { + char *ref; + i++; + ref = xmalloc(strlen(argv[i]) * 2 + 22); + strcpy(ref, "refs/tags/"); + strcat(ref, argv[i]); + strcat(ref, ":refs/tags/"); + strcat(ref, argv[i]); + refs[j++] = ref; + } else + refs[j++] = argv[i]; + i++; + } + refs[j] = NULL; + ref_nr = j; + for (j = 0; refs[j]; j++) + printf("ref: %s\n", refs[j]); + } + + return do_fetch(transport, parse_ref_spec(ref_nr, refs), ref_nr); +} diff --git a/builtin.h b/builtin.h index d424bfdeb1..a20cb6ba97 100644 --- a/builtin.h +++ b/builtin.h @@ -31,6 +31,7 @@ extern int cmd_diff_files(int argc, const char **argv, const char *prefix); extern int cmd_diff_index(int argc, const char **argv, const char *prefix); extern int cmd_diff(int argc, const char **argv, const char *prefix); extern int cmd_diff_tree(int argc, const char **argv, const char *prefix); +extern int cmd_fetch(int argc, const char **argv, const char *prefix); extern int cmd_fetch_pack(int argc, const char **argv, const char *prefix); extern int cmd_fetch__tool(int argc, const char **argv, const char *prefix); extern int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix); diff --git a/cache.h b/cache.h index 8246500166..16bdbb2591 100644 --- a/cache.h +++ b/cache.h @@ -492,6 +492,7 @@ struct ref { unsigned char old_sha1[20]; unsigned char new_sha1[20]; unsigned char force; + unsigned char merge; struct ref *peer_ref; /* when renaming */ char name[FLEX_ARRAY]; /* more */ }; diff --git a/git-fetch.sh b/contrib/examples/git-fetch.sh similarity index 100% rename from git-fetch.sh rename to contrib/examples/git-fetch.sh diff --git a/git.c b/git.c index 6ca36c0265..6773c12a14 100644 --- a/git.c +++ b/git.c @@ -334,6 +334,7 @@ static void handle_internal_command(int argc, const char **argv) { "diff-files", cmd_diff_files }, { "diff-index", cmd_diff_index, RUN_SETUP }, { "diff-tree", cmd_diff_tree, RUN_SETUP }, + { "fetch", cmd_fetch, RUN_SETUP }, { "fetch-pack", cmd_fetch_pack, RUN_SETUP }, { "fetch--tool", cmd_fetch__tool, RUN_SETUP }, { "fmt-merge-msg", cmd_fmt_merge_msg, RUN_SETUP }, diff --git a/t/t5515/fetch.br-branches-default-merge b/t/t5515/fetch.br-branches-default-merge index ea65f31bde..828bfd8e9e 100644 --- a/t/t5515/fetch.br-branches-default-merge +++ b/t/t5515/fetch.br-branches-default-merge @@ -1,5 +1,5 @@ # br-branches-default-merge -754b754407bf032e9a2f9d5a9ad05ca79a6b228f branch 'master' of ../ +754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ diff --git a/t/t5515/fetch.br-branches-default-merge_branches-default b/t/t5515/fetch.br-branches-default-merge_branches-default index 7b5fa949e6..f1486730fa 100644 --- a/t/t5515/fetch.br-branches-default-merge_branches-default +++ b/t/t5515/fetch.br-branches-default-merge_branches-default @@ -1,5 +1,5 @@ # br-branches-default-merge branches-default -754b754407bf032e9a2f9d5a9ad05ca79a6b228f branch 'master' of ../ +754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ diff --git a/t/t5515/fetch.br-branches-default-octopus b/t/t5515/fetch.br-branches-default-octopus index 128397d737..bb1a1915c6 100644 --- a/t/t5515/fetch.br-branches-default-octopus +++ b/t/t5515/fetch.br-branches-default-octopus @@ -1,5 +1,5 @@ # br-branches-default-octopus -754b754407bf032e9a2f9d5a9ad05ca79a6b228f branch 'master' of ../ +754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ diff --git a/t/t5515/fetch.br-branches-default-octopus_branches-default b/t/t5515/fetch.br-branches-default-octopus_branches-default index 4b37cd481a..970fc93725 100644 --- a/t/t5515/fetch.br-branches-default-octopus_branches-default +++ b/t/t5515/fetch.br-branches-default-octopus_branches-default @@ -1,5 +1,5 @@ # br-branches-default-octopus branches-default -754b754407bf032e9a2f9d5a9ad05ca79a6b228f branch 'master' of ../ +754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ diff --git a/t/t5515/fetch.br-branches-one-merge b/t/t5515/fetch.br-branches-one-merge index 3a4e77ead5..24099fd53e 100644 --- a/t/t5515/fetch.br-branches-one-merge +++ b/t/t5515/fetch.br-branches-one-merge @@ -1,5 +1,5 @@ # br-branches-one-merge -8e32a6d901327a23ef831511badce7bf3bf46689 branch 'one' of ../ +8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge branch 'one' of ../ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ diff --git a/t/t5515/fetch.br-branches-one-merge_branches-one b/t/t5515/fetch.br-branches-one-merge_branches-one index 00e04b435e..e4b4fdee4c 100644 --- a/t/t5515/fetch.br-branches-one-merge_branches-one +++ b/t/t5515/fetch.br-branches-one-merge_branches-one @@ -1,5 +1,5 @@ # br-branches-one-merge branches-one -8e32a6d901327a23ef831511badce7bf3bf46689 branch 'one' of ../ +8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge branch 'one' of ../ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ diff --git a/t/t5515/fetch.br-config-glob-octopus b/t/t5515/fetch.br-config-glob-octopus index 9ee213ea45..938e532db2 100644 --- a/t/t5515/fetch.br-config-glob-octopus +++ b/t/t5515/fetch.br-config-glob-octopus @@ -2,7 +2,7 @@ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 branch 'one' of ../ 0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge branch 'three' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge branch 'two' of ../ +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 branch 'two' of ../ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ diff --git a/t/t5515/fetch.br-config-glob-octopus_config-glob b/t/t5515/fetch.br-config-glob-octopus_config-glob index 44bd0ec59f..c9225bf6ff 100644 --- a/t/t5515/fetch.br-config-glob-octopus_config-glob +++ b/t/t5515/fetch.br-config-glob-octopus_config-glob @@ -2,7 +2,7 @@ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 branch 'one' of ../ 0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge branch 'three' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge branch 'two' of ../ +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 branch 'two' of ../ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ diff --git a/t/t5515/fetch.br-remote-glob-octopus b/t/t5515/fetch.br-remote-glob-octopus index c1554f8f2d..b08e046195 100644 --- a/t/t5515/fetch.br-remote-glob-octopus +++ b/t/t5515/fetch.br-remote-glob-octopus @@ -2,7 +2,7 @@ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 branch 'one' of ../ 0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge branch 'three' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge branch 'two' of ../ +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 branch 'two' of ../ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ diff --git a/t/t5515/fetch.br-remote-glob-octopus_remote-glob b/t/t5515/fetch.br-remote-glob-octopus_remote-glob index e6134345b8..d4d547c847 100644 --- a/t/t5515/fetch.br-remote-glob-octopus_remote-glob +++ b/t/t5515/fetch.br-remote-glob-octopus_remote-glob @@ -2,7 +2,7 @@ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 branch 'one' of ../ 0567da4d5edd2ff4bb292a465ba9e64dcad9536b not-for-merge branch 'three' of ../ -6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge branch 'two' of ../ +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 branch 'two' of ../ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ From 1aad91f5a715af92892aea7764beb829938ab111 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 14 Sep 2007 03:31:07 -0400 Subject: [PATCH 0061/1490] Correct builtin-fetch to handle + in refspecs If we are fetching to a local reference (the so called peer_ref) and the refspec that created this ref/peer_ref association had started with '+' we are supposed to allow a non-fast-forward update during fetch, even if --force was not supplied on the command line. The builtin-fetch implementation was not honoring this setting as it was copied from the wrong struct ref instance. Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- builtin-fetch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin-fetch.c b/builtin-fetch.c index 64392f317d..c8c24d28a2 100644 --- a/builtin-fetch.c +++ b/builtin-fetch.c @@ -217,7 +217,7 @@ static void store_updated_refs(const char *url, struct ref *ref_map) strcpy(ref->name, rm->peer_ref->name); hashcpy(ref->old_sha1, rm->peer_ref->old_sha1); hashcpy(ref->new_sha1, rm->old_sha1); - ref->force = rm->force; + ref->force = rm->peer_ref->force; } commit = lookup_commit_reference(rm->old_sha1); From 4ad1eada9774a1f340beb4fdf78f1735534741bb Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 14 Sep 2007 03:31:09 -0400 Subject: [PATCH 0062/1490] Fix off by one bug in reflog messages written by builtin-fetch We are adding a space between each argument in the sprintf above so we must account for this as we update our position within the reflog message and append in any remaining arguments. Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- builtin-fetch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin-fetch.c b/builtin-fetch.c index c8c24d28a2..016c6e43ec 100644 --- a/builtin-fetch.c +++ b/builtin-fetch.c @@ -503,7 +503,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) rla_offset = strlen(default_rla); for (j = 1; j < argc; j++) { sprintf(default_rla + rla_offset, " %s", argv[j]); - rla_offset += strlen(argv[j]); + rla_offset += strlen(argv[j]) + 1; } if (i == argc) From 133296f00cd441b5525ccc3e82ee13cbfc62d246 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 14 Sep 2007 03:31:11 -0400 Subject: [PATCH 0063/1490] Remove unnecessary debugging from builtin-fetch The older git-fetch client did not produce all of this debugging information to stdout. Most end-users and Porcelain (e.g. StGIT, git-gui, qgit) do not want to see these low-level details on the console so they should be removed. Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- builtin-fetch-pack.c | 2 -- builtin-fetch.c | 9 --------- 2 files changed, 11 deletions(-) diff --git a/builtin-fetch-pack.c b/builtin-fetch-pack.c index 3b217d96f0..e77cd26719 100644 --- a/builtin-fetch-pack.c +++ b/builtin-fetch-pack.c @@ -767,8 +767,6 @@ struct ref *fetch_pack(const char *dest, int nr_heads, char **heads) st.st_mtime = 0; } - printf("connect to %s\n", dest); - pid = git_connect(fd, (char *)dest, uploadpack, verbose ? CONNECT_VERBOSE : 0); if (pid < 0) diff --git a/builtin-fetch.c b/builtin-fetch.c index 016c6e43ec..33b740cd10 100644 --- a/builtin-fetch.c +++ b/builtin-fetch.c @@ -370,15 +370,6 @@ static int do_fetch(struct transport *transport, for (rm = ref_map; rm; rm = rm->next) { if (rm->peer_ref) read_ref(rm->peer_ref->name, rm->peer_ref->old_sha1); - - printf("%s : %s\n", rm->name, rm->peer_ref ? rm->peer_ref->name : NULL); - printf(" < %s\n", sha1_to_hex(rm->old_sha1)); - if (rm->peer_ref) - printf(" > %s\n", sha1_to_hex(rm->peer_ref->old_sha1)); - if (!rm->peer_ref || - hashcmp(rm->old_sha1, rm->peer_ref->old_sha1)) { - printf("%s needs update.\n", rm->name); - } } if (fetch_refs(transport, ref_map)) { From f1ae391e17be638a14c7505598b73430dbf328f1 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 14 Sep 2007 03:31:13 -0400 Subject: [PATCH 0064/1490] Remove unused unpacklimit variable from builtin-fetch Never referenced. This should actually be handled down inside of builtin-fetch-pack, not up here in the generic user frontend. Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- builtin-fetch.c | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/builtin-fetch.c b/builtin-fetch.c index 33b740cd10..a041df9faf 100644 --- a/builtin-fetch.c +++ b/builtin-fetch.c @@ -12,9 +12,6 @@ static const char fetch_usage[] = "git-fetch [-a | --append] [--upload-pack ] [-f | --force] [--no-tags] [-t | --tags] [-k | --keep] [-u | --update-head-ok] [--depth ] [-v | --verbose] [ ...]"; static int append, force, tags, no_tags, update_head_ok, verbose, quiet; - -static int unpacklimit; - static char *default_rla = NULL; static void find_merge_config(struct ref *ref_map, struct remote *remote) @@ -395,21 +392,6 @@ static int do_fetch(struct transport *transport, return 0; } -static int fetch_config(const char *var, const char *value) -{ - if (strcmp(var, "fetch.unpacklimit") == 0) { - unpacklimit = git_config_int(var, value); - return 0; - } - - if (strcmp(var, "transfer.unpacklimit") == 0) { - unpacklimit = git_config_int(var, value); - return 0; - } - - return git_default_config(var, value); -} - int cmd_fetch(int argc, const char **argv, const char *prefix) { struct remote *remote; @@ -421,8 +403,6 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) const char *depth = NULL, *upload_pack = NULL; int keep = 0; - git_config(fetch_config); - for (i = 1; i < argc; i++) { const char *arg = argv[i]; cmd_len += strlen(arg); From 7a2bff45937a60d846abf3ccb42015539aedcb40 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 14 Sep 2007 03:31:18 -0400 Subject: [PATCH 0065/1490] Replace custom memory growth allocator with ALLOC_GROW The ALLOC_GROW macro is a shorter way to implement an array that grows upon demand as additional items are added to it. We have mostly standardized upon its use within git and transport.c is not an exception. Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- transport.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/transport.c b/transport.c index e0111dcf0b..2258492ae7 100644 --- a/transport.c +++ b/transport.c @@ -474,13 +474,11 @@ struct ref *transport_get_remote_refs(struct transport *transport) return transport->remote_refs; } -#define PACK_HEADS_CHUNK_COUNT 256 - int transport_fetch_refs(struct transport *transport, struct ref *refs) { int i; - int nr_heads = 0; - char **heads = xmalloc(PACK_HEADS_CHUNK_COUNT * sizeof(char *)); + int nr_heads = 0, nr_alloc = 0; + char **heads = NULL; struct ref *rm; int use_objs = !transport->ops->fetch_refs; @@ -488,15 +486,12 @@ int transport_fetch_refs(struct transport *transport, struct ref *refs) if (rm->peer_ref && !hashcmp(rm->peer_ref->old_sha1, rm->old_sha1)) continue; + ALLOC_GROW(heads, nr_heads + 1, nr_alloc); if (use_objs) { heads[nr_heads++] = xstrdup(sha1_to_hex(rm->old_sha1)); } else { heads[nr_heads++] = xstrdup(rm->name); } - if (nr_heads % PACK_HEADS_CHUNK_COUNT == 0) - heads = xrealloc(heads, - (nr_heads + PACK_HEADS_CHUNK_COUNT) * - sizeof(char *)); } if (use_objs) { From 425b1393139d99d89c7a95906686d9b041f2ee3d Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 14 Sep 2007 03:31:21 -0400 Subject: [PATCH 0066/1490] Simplify fetch transport API to just one function Commit walkers need to know the SHA-1 name of any objects they have been asked to fetch while the native pack transport only wants to know the names of the remote refs as the remote side must do the name->SHA-1 translation. Since we only have three fetch implementations and one of them (bundle) doesn't even need the name information we can reduce the code required to perform a fetch by having just one function and passing of the filtered list of refs to be fetched. Each transport can then obtain the information it needs from that ref array to construct its own internal operation state. Signed-off-by: Shawn O. Pearce Conflicts: transport.c Signed-off-by: Junio C Hamano --- builtin-fetch.c | 2 +- transport.c | 59 +++++++++++++++++++++---------------------------- transport.h | 5 +---- 3 files changed, 27 insertions(+), 39 deletions(-) diff --git a/builtin-fetch.c b/builtin-fetch.c index a041df9faf..f5a2718acc 100644 --- a/builtin-fetch.c +++ b/builtin-fetch.c @@ -355,7 +355,7 @@ static int do_fetch(struct transport *transport, no_tags = 1; if (!transport->ops || !transport->ops->get_refs_list || - !(transport->ops->fetch_refs || transport->ops->fetch_objs)) + !transport->ops->fetch) die("Don't know how to fetch from %s", transport->url); /* if not appending, truncate FETCH_HEAD */ diff --git a/transport.c b/transport.c index 2258492ae7..d2cbf3acc1 100644 --- a/transport.c +++ b/transport.c @@ -10,10 +10,12 @@ /* Generic functions for using commit walkers */ static int fetch_objs_via_walker(const struct transport *transport, - int nr_objs, char **objs) + int nr_objs, struct ref **to_fetch) { char *dest = xstrdup(transport->url); struct walker *walker = transport->data; + char **objs = xmalloc(nr_objs * sizeof(*objs)); + int i; walker->get_all = 1; walker->get_tree = 1; @@ -21,9 +23,15 @@ static int fetch_objs_via_walker(const struct transport *transport, walker->get_verbosely = transport->verbose; walker->get_recover = 0; + for (i = 0; i < nr_objs; i++) + objs[i] = xstrdup(sha1_to_hex(to_fetch[i]->old_sha1)); + if (walker_fetch(walker, nr_objs, objs, NULL, dest)) die("Fetch failed."); + for (i = 0; i < nr_objs; i++) + free(objs[i]); + free(objs); free(dest); return 0; } @@ -179,8 +187,7 @@ static struct ref *get_refs_via_curl(const struct transport *transport) static const struct transport_ops curl_transport = { /* set_option */ NULL, /* get_refs_list */ get_refs_via_curl, - /* fetch_refs */ NULL, - /* fetch_objs */ fetch_objs_via_walker, + /* fetch */ fetch_objs_via_walker, /* push */ curl_transport_push, /* disconnect */ disconnect_walker }; @@ -213,7 +220,7 @@ static struct ref *get_refs_from_bundle(const struct transport *transport) } static int fetch_refs_from_bundle(const struct transport *transport, - int nr_heads, char **heads) + int nr_heads, struct ref **to_fetch) { struct bundle_transport_data *data = transport->data; return unbundle(&data->header, data->fd); @@ -230,8 +237,7 @@ static int close_bundle(struct transport *transport) static const struct transport_ops bundle_transport = { /* set_option */ NULL, /* get_refs_list */ get_refs_from_bundle, - /* fetch_refs */ fetch_refs_from_bundle, - /* fetch_objs */ NULL, + /* fetch */ fetch_refs_from_bundle, /* push */ NULL, /* disconnect */ close_bundle }; @@ -301,12 +307,14 @@ static struct ref *get_refs_via_connect(const struct transport *transport) } static int fetch_refs_via_pack(const struct transport *transport, - int nr_heads, char **heads) + int nr_heads, struct ref **to_fetch) { struct git_transport_data *data = transport->data; + char **heads = xmalloc(nr_heads * sizeof(*heads)); struct ref *refs; char *dest = xstrdup(transport->url); struct fetch_pack_args args; + int i; args.uploadpack = data->uploadpack; args.quiet = 0; @@ -320,14 +328,13 @@ static int fetch_refs_via_pack(const struct transport *transport, setup_fetch_pack(&args); + for (i = 0; i < nr_heads; i++) + heads[i] = xstrdup(to_fetch[i]->name); refs = fetch_pack(dest, nr_heads, heads); - // ???? check that refs got everything? - - /* free the memory used for the refs list ... */ - + for (i = 0; i < nr_heads; i++) + free(heads[i]); free_refs(refs); - free(dest); return 0; } @@ -379,8 +386,7 @@ static int git_transport_push(struct transport *transport, int refspec_nr, const static const struct transport_ops git_transport = { /* set_option */ set_git_option, /* get_refs_list */ get_refs_via_connect, - /* fetch_refs */ fetch_refs_via_pack, - /* fetch_objs */ NULL, + /* fetch */ fetch_refs_via_pack, /* push */ git_transport_push }; @@ -476,37 +482,22 @@ struct ref *transport_get_remote_refs(struct transport *transport) int transport_fetch_refs(struct transport *transport, struct ref *refs) { - int i; + int rc; int nr_heads = 0, nr_alloc = 0; - char **heads = NULL; + struct ref **heads = NULL; struct ref *rm; - int use_objs = !transport->ops->fetch_refs; for (rm = refs; rm; rm = rm->next) { if (rm->peer_ref && !hashcmp(rm->peer_ref->old_sha1, rm->old_sha1)) continue; ALLOC_GROW(heads, nr_heads + 1, nr_alloc); - if (use_objs) { - heads[nr_heads++] = xstrdup(sha1_to_hex(rm->old_sha1)); - } else { - heads[nr_heads++] = xstrdup(rm->name); - } + heads[nr_heads++] = rm; } - if (use_objs) { - if (transport->ops->fetch_objs(transport, nr_heads, heads)) - return -1; - } else { - if (transport->ops->fetch_refs(transport, nr_heads, heads)) - return -1; - } - - /* free the memory used for the heads list ... */ - for (i = 0; i < nr_heads; i++) - free(heads[i]); + rc = transport->ops->fetch(transport, nr_heads, heads); free(heads); - return 0; + return rc; } int transport_disconnect(struct transport *transport) diff --git a/transport.h b/transport.h index 5b0a6b0658..b354a8fd18 100644 --- a/transport.h +++ b/transport.h @@ -30,10 +30,7 @@ struct transport_ops { const char *value); struct ref *(*get_refs_list)(const struct transport *transport); - int (*fetch_refs)(const struct transport *transport, - int nr_refs, char **refs); - int (*fetch_objs)(const struct transport *transport, - int nr_objs, char **objs); + int (*fetch)(const struct transport *transport, int refs_nr, struct ref **refs); int (*push)(struct transport *connection, int refspec_nr, const char **refspec, int flags); int (*disconnect)(struct transport *connection); From 106764e6515dd0fb9fda8bb8cab523932ae903b3 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 14 Sep 2007 03:31:16 -0400 Subject: [PATCH 0067/1490] Refactor index-pack "keep $sha1" handling for reuse There is a subtle (but important) linkage between receive-pack and index-pack that allows index-pack to create a packfile but protect it from being deleted by a concurrent `git repack -a -d` operation. The linkage works by having index-pack mark the newly created pack with a ".keep" file and then it passes the SHA-1 name of that new packfile to receive-pack along its stdout channel. The receive-pack process must unkeep the packfile by deleting the .keep file, but can it can only do so after all elgible refs have been updated in the receiving repository. This ensures that the packfile is either kept or its objects are reachable, preventing a concurrent repacker from deleting the packfile before it can determine that its objects are actually needed by the repository. The new builtin-fetch code needs to perform the same actions if it choose to run index-pack rather than unpack-objects, so I am moving this code out to its own function where both receive-pack and fetch-pack are able to invoke it when necessary. The caller is responsible for deleting the returned ".keep" and freeing the path if the returned path is not NULL. Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- pack-write.c | 26 ++++++++++++++++++++++++++ pack.h | 1 + receive-pack.c | 24 ++---------------------- 3 files changed, 29 insertions(+), 22 deletions(-) diff --git a/pack-write.c b/pack-write.c index e59b197e5e..979bdfff7c 100644 --- a/pack-write.c +++ b/pack-write.c @@ -179,3 +179,29 @@ void fixup_pack_header_footer(int pack_fd, SHA1_Final(pack_file_sha1, &c); write_or_die(pack_fd, pack_file_sha1, 20); } + +char *index_pack_lockfile(int ip_out) +{ + int len, s; + char packname[46]; + + /* + * The first thing we expects from index-pack's output + * is "pack\t%40s\n" or "keep\t%40s\n" (46 bytes) where + * %40s is the newly created pack SHA1 name. In the "keep" + * case, we need it to remove the corresponding .keep file + * later on. If we don't get that then tough luck with it. + */ + for (len = 0; + len < 46 && (s = xread(ip_out, packname+len, 46-len)) > 0; + len += s); + if (len == 46 && packname[45] == '\n' && + memcmp(packname, "keep\t", 5) == 0) { + char path[PATH_MAX]; + packname[45] = 0; + snprintf(path, sizeof(path), "%s/pack/pack-%s.keep", + get_object_directory(), packname + 5); + return xstrdup(path); + } + return NULL; +} diff --git a/pack.h b/pack.h index f357c9f428..b57ba2d9ed 100644 --- a/pack.h +++ b/pack.h @@ -59,6 +59,7 @@ extern const char *write_idx_file(const char *index_name, struct pack_idx_entry extern int verify_pack(struct packed_git *, int); extern void fixup_pack_header_footer(int, unsigned char *, const char *, uint32_t); +extern char *index_pack_lockfile(int fd); #define PH_ERROR_EOF (-1) #define PH_ERROR_PACK_SIGNATURE (-2) diff --git a/receive-pack.c b/receive-pack.c index d3c422be58..61e9929763 100644 --- a/receive-pack.c +++ b/receive-pack.c @@ -382,9 +382,8 @@ static const char *unpack(void) } } else { const char *keeper[6]; - int s, len, status; + int s, status; char keep_arg[256]; - char packname[46]; struct child_process ip; s = sprintf(keep_arg, "--keep=receive-pack %i on ", getpid()); @@ -403,26 +402,7 @@ static const char *unpack(void) ip.git_cmd = 1; if (start_command(&ip)) return "index-pack fork failed"; - - /* - * The first thing we expects from index-pack's output - * is "pack\t%40s\n" or "keep\t%40s\n" (46 bytes) where - * %40s is the newly created pack SHA1 name. In the "keep" - * case, we need it to remove the corresponding .keep file - * later on. If we don't get that then tough luck with it. - */ - for (len = 0; - len < 46 && (s = xread(ip.out, packname+len, 46-len)) > 0; - len += s); - if (len == 46 && packname[45] == '\n' && - memcmp(packname, "keep\t", 5) == 0) { - char path[PATH_MAX]; - packname[45] = 0; - snprintf(path, sizeof(path), "%s/pack/pack-%s.keep", - get_object_directory(), packname + 5); - pack_lockfile = xstrdup(path); - } - + pack_lockfile = index_pack_lockfile(ip.out); status = finish_command(&ip); if (!status) { reprepare_packed_git(); From 1788c39cd0742439b9bedc28bc10bc4d105b6c0f Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 14 Sep 2007 03:31:23 -0400 Subject: [PATCH 0068/1490] Remove pack.keep after ref updates in git-fetch If we are using a native packfile to perform a git-fetch invocation and the received packfile contained more than the configured limits of fetch.unpackLimit/transfer.unpackLimit then index-pack will output a single line saying "keep\t$sha1\n" to stdout. This line needs to be captured and retained so we can delete the corresponding .keep file ("$GIT_DIR/objects/pack/pack-$sha1.keep") once all refs have been safely updated. This trick has long been in use with git-fetch.sh and its lower level helper git-fetch--tool as a way to allow index-pack to save the new packfile before the refs have been updated and yet avoid a race with any concurrently running git-repack process. It was unfortunately lost when git-fetch.sh was converted to pure C and fetch--tool was no longer being invoked. Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- builtin-fetch-pack.c | 31 +++++++++++++++++++++++++------ builtin-fetch.c | 1 + fetch-pack.h | 2 +- transport.c | 18 ++++++++++++++---- transport.h | 5 +++-- 5 files changed, 44 insertions(+), 13 deletions(-) diff --git a/builtin-fetch-pack.c b/builtin-fetch-pack.c index e77cd26719..b0936ccf0c 100644 --- a/builtin-fetch-pack.c +++ b/builtin-fetch-pack.c @@ -493,7 +493,7 @@ static pid_t setup_sideband(int fd[2], int xd[2]) return side_pid; } -static int get_pack(int xd[2]) +static int get_pack(int xd[2], char **pack_lockfile) { int status; pid_t pid, side_pid; @@ -503,6 +503,7 @@ static int get_pack(int xd[2]) char hdr_arg[256]; const char **av; int do_keep = keep_pack; + int keep_pipe[2]; side_pid = setup_sideband(fd, xd); @@ -522,6 +523,8 @@ static int get_pack(int xd[2]) } if (do_keep) { + if (pack_lockfile && pipe(keep_pipe)) + die("fetch-pack: pipe setup failure: %s", strerror(errno)); *av++ = "index-pack"; *av++ = "--stdin"; if (!quiet && !no_progress) @@ -550,6 +553,11 @@ static int get_pack(int xd[2]) die("fetch-pack: unable to fork off %s", argv[0]); if (!pid) { dup2(fd[0], 0); + if (do_keep && pack_lockfile) { + dup2(keep_pipe[1], 1); + close(keep_pipe[0]); + close(keep_pipe[1]); + } close(fd[0]); close(fd[1]); execv_git_cmd(argv); @@ -557,6 +565,11 @@ static int get_pack(int xd[2]) } close(fd[0]); close(fd[1]); + if (do_keep && pack_lockfile) { + close(keep_pipe[1]); + *pack_lockfile = index_pack_lockfile(keep_pipe[0]); + close(keep_pipe[0]); + } while (waitpid(pid, &status, 0) < 0) { if (errno != EINTR) die("waiting for %s: %s", argv[0], strerror(errno)); @@ -574,7 +587,10 @@ static int get_pack(int xd[2]) die("%s died of unnatural causes %d", argv[0], status); } -static struct ref *do_fetch_pack(int fd[2], int nr_match, char **match) +static struct ref *do_fetch_pack(int fd[2], + int nr_match, + char **match, + char **pack_lockfile) { struct ref *ref; unsigned char sha1[20]; @@ -612,7 +628,7 @@ static struct ref *do_fetch_pack(int fd[2], int nr_match, char **match) */ fprintf(stderr, "warning: no common commits\n"); - if (get_pack(fd)) + if (get_pack(fd, pack_lockfile)) die("git-fetch-pack: fetch failed."); all_done: @@ -741,7 +757,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix) if (!dest) usage(fetch_pack_usage); - ref = fetch_pack(dest, nr_heads, heads); + ref = fetch_pack(dest, nr_heads, heads, NULL); ret = !ref; @@ -754,7 +770,10 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix) return ret; } -struct ref *fetch_pack(const char *dest, int nr_heads, char **heads) +struct ref *fetch_pack(const char *dest, + int nr_heads, + char **heads, + char **pack_lockfile) { int i, ret; int fd[2]; @@ -773,7 +792,7 @@ struct ref *fetch_pack(const char *dest, int nr_heads, char **heads) return NULL; if (heads && nr_heads) nr_heads = remove_duplicates(nr_heads, heads); - ref = do_fetch_pack(fd, nr_heads, heads); + ref = do_fetch_pack(fd, nr_heads, heads, pack_lockfile); close(fd[0]); close(fd[1]); ret = finish_connect(pid); diff --git a/builtin-fetch.c b/builtin-fetch.c index f5a2718acc..8e433d1bf2 100644 --- a/builtin-fetch.c +++ b/builtin-fetch.c @@ -274,6 +274,7 @@ static int fetch_refs(struct transport *transport, struct ref *ref_map) int ret = transport_fetch_refs(transport, ref_map); if (!ret) store_updated_refs(transport->url, ref_map); + transport_unlock_pack(transport); return ret; } diff --git a/fetch-pack.h b/fetch-pack.h index e06bf5b5c4..cdcd84f2b5 100644 --- a/fetch-pack.h +++ b/fetch-pack.h @@ -16,6 +16,6 @@ struct fetch_pack_args void setup_fetch_pack(struct fetch_pack_args *args); -struct ref *fetch_pack(const char *dest, int nr_heads, char **heads); +struct ref *fetch_pack(const char *dest, int nr_heads, char **heads, char **pack_lockfile); #endif diff --git a/transport.c b/transport.c index d2cbf3acc1..0882edd381 100644 --- a/transport.c +++ b/transport.c @@ -9,7 +9,7 @@ /* Generic functions for using commit walkers */ -static int fetch_objs_via_walker(const struct transport *transport, +static int fetch_objs_via_walker(struct transport *transport, int nr_objs, struct ref **to_fetch) { char *dest = xstrdup(transport->url); @@ -219,7 +219,7 @@ static struct ref *get_refs_from_bundle(const struct transport *transport) return result; } -static int fetch_refs_from_bundle(const struct transport *transport, +static int fetch_refs_from_bundle(struct transport *transport, int nr_heads, struct ref **to_fetch) { struct bundle_transport_data *data = transport->data; @@ -306,7 +306,7 @@ static struct ref *get_refs_via_connect(const struct transport *transport) return refs; } -static int fetch_refs_via_pack(const struct transport *transport, +static int fetch_refs_via_pack(struct transport *transport, int nr_heads, struct ref **to_fetch) { struct git_transport_data *data = transport->data; @@ -330,7 +330,7 @@ static int fetch_refs_via_pack(const struct transport *transport, for (i = 0; i < nr_heads; i++) heads[i] = xstrdup(to_fetch[i]->name); - refs = fetch_pack(dest, nr_heads, heads); + refs = fetch_pack(dest, nr_heads, heads, &transport->pack_lockfile); for (i = 0; i < nr_heads; i++) free(heads[i]); @@ -445,6 +445,7 @@ struct transport *transport_get(struct remote *remote, const char *url, ret->url = url; ret->remote_refs = NULL; ret->fetch = !!fetch; + ret->pack_lockfile = NULL; } return ret; } @@ -500,6 +501,15 @@ int transport_fetch_refs(struct transport *transport, struct ref *refs) return rc; } +void transport_unlock_pack(struct transport *transport) +{ + if (transport->pack_lockfile) { + unlink(transport->pack_lockfile); + free(transport->pack_lockfile); + transport->pack_lockfile = NULL; + } +} + int transport_disconnect(struct transport *transport) { int ret = 0; diff --git a/transport.h b/transport.h index b354a8fd18..f2bbdf778a 100644 --- a/transport.h +++ b/transport.h @@ -15,6 +15,7 @@ struct transport { struct ref *remote_refs; const struct transport_ops *ops; + char *pack_lockfile; }; #define TRANSPORT_PUSH_ALL 1 @@ -30,7 +31,7 @@ struct transport_ops { const char *value); struct ref *(*get_refs_list)(const struct transport *transport); - int (*fetch)(const struct transport *transport, int refs_nr, struct ref **refs); + int (*fetch)(struct transport *transport, int refs_nr, struct ref **refs); int (*push)(struct transport *connection, int refspec_nr, const char **refspec, int flags); int (*disconnect)(struct transport *connection); @@ -73,7 +74,7 @@ int transport_push(struct transport *connection, struct ref *transport_get_remote_refs(struct transport *transport); int transport_fetch_refs(struct transport *transport, struct ref *refs); - +void transport_unlock_pack(struct transport *transport); int transport_disconnect(struct transport *transport); #endif From e4022ed2c85825f238661e3e532b0bb108b5e318 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 14 Sep 2007 03:31:25 -0400 Subject: [PATCH 0069/1490] Always ensure the pack.keep file is removed by git-fetch If we are using a native transport and the transport chose to save the packfile it may have created a .keep file to protect the packfile from a concurrently running git-repack process. In such a case the git-fetch process should make sure it will unlink the .keep file even if it fails to update any refs as otherwise the newly downloaded packfile's diskspace will never be reclaimed if the objects are not actually referenced. Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- builtin-fetch.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/builtin-fetch.c b/builtin-fetch.c index 8e433d1bf2..8b0fdbe905 100644 --- a/builtin-fetch.c +++ b/builtin-fetch.c @@ -13,6 +13,20 @@ static const char fetch_usage[] = "git-fetch [-a | --append] [--upload-pack Date: Fri, 14 Sep 2007 18:59:53 -0400 Subject: [PATCH 0070/1490] Fix builtin-fetch memory corruption by not overstepping array A long time ago Junio added this line to always ensure that the output array created by remove_duplicates() had a NULL as its terminating node. Today none of the downstream consumers of this array care about a NULL terminator; they only pay attention to the size of the array (as indicated by nr_heads). In (nearly?) all cases passing a NULL element will cause SIGSEGV failures. So this NULL terminal is not actually necessary. Unfortunately we cannot continue to NULL terminate the array at this point as the array may only have been allocated large enough to match the input of nr_heads. If there are no duplicates than we would be trying to store NULL into heads[nr_heads] and that may be outside of the array. My recent series to cleanup builtin-fetch changed the allocation of the heads array from 256 entries to exactly nr_heads thus ensuring we were always overstepping the array and causing memory corruption. Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- builtin-fetch-pack.c | 1 - 1 file changed, 1 deletion(-) diff --git a/builtin-fetch-pack.c b/builtin-fetch-pack.c index b0936ccf0c..2977a94197 100644 --- a/builtin-fetch-pack.c +++ b/builtin-fetch-pack.c @@ -654,7 +654,6 @@ static int remove_duplicates(int nr_heads, char **heads) heads[dst] = heads[src]; dst++; } - heads[dst] = 0; return dst; } From e4cd6c7a20bfc776086817671d58e09060a8079a Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 14 Sep 2007 18:57:11 -0400 Subject: [PATCH 0071/1490] Backup the array passed to fetch_pack so we can free items fetch_pack() can call remove_duplicates() on its input array and this will possibly overwrite an earlier entry with a later one if there are any duplicates in the input array. In such a case the caller here might then attempt to free an item multiple times as it goes through its cleanup. I also forgot to free the heads array we pass down into fetch_pack() when I introduced the allocation of it in this function during my builtin-fetch cleanup series. Better free it while we are here working on related memory management fixes. Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- transport.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/transport.c b/transport.c index 0882edd381..0338ed45b9 100644 --- a/transport.c +++ b/transport.c @@ -311,6 +311,7 @@ static int fetch_refs_via_pack(struct transport *transport, { struct git_transport_data *data = transport->data; char **heads = xmalloc(nr_heads * sizeof(*heads)); + char **origh = xmalloc(nr_heads * sizeof(*origh)); struct ref *refs; char *dest = xstrdup(transport->url); struct fetch_pack_args args; @@ -329,11 +330,13 @@ static int fetch_refs_via_pack(struct transport *transport, setup_fetch_pack(&args); for (i = 0; i < nr_heads; i++) - heads[i] = xstrdup(to_fetch[i]->name); + origh[i] = heads[i] = xstrdup(to_fetch[i]->name); refs = fetch_pack(dest, nr_heads, heads, &transport->pack_lockfile); for (i = 0; i < nr_heads; i++) - free(heads[i]); + free(origh[i]); + free(origh); + free(heads); free_refs(refs); free(dest); return 0; From 3278cd0a39c30c6c3082fc5feed0f9bd98b5f628 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Sat, 15 Sep 2007 03:23:00 -0400 Subject: [PATCH 0072/1490] Properly cleanup in http_cleanup so builtin-fetch does not segfault Junio and I both noticed that the new builtin-fetch was segfaulting immediately on http/https/ftp style URLs (those that went through libcurl and the commit walker). Although the builtin-fetch changes in this area were really just minor refactorings there was one major change made: we invoked http_init(), http_cleanup() then http_init() again in the same process. When we call curl_easy_cleanup() on each active_request_slot we are telling libcurl we did not want that buffer to be used again. Unfortunately we did not also deallocate the active_request_slot itself nor did we NULL out active_queue_head. This lead us to attempt to reuse these cleaned up libcurl handles when we later tried to invoke http_init() a second time to reactivate the curl library. The next file get operation then immediately segfaulted on most versions of libcurl. Properly freeing our own buffers and clearing the list causes us to reinitialize the curl buffers again if/when we need to use libcurl from within this same process. Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- http.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/http.c b/http.c index a95483be8b..87ebf7b865 100644 --- a/http.c +++ b/http.c @@ -276,6 +276,7 @@ void http_cleanup(void) #endif while (slot != NULL) { + struct active_request_slot *next = slot->next; #ifdef USE_CURL_MULTI if (slot->in_use) { curl_easy_getinfo(slot->curl, @@ -287,8 +288,10 @@ void http_cleanup(void) #endif if (slot->curl != NULL) curl_easy_cleanup(slot->curl); - slot = slot->next; + free(slot); + slot = next; } + active_queue_head = NULL; #ifndef NO_CURL_EASY_DUPHANDLE curl_easy_cleanup(curl_default); @@ -300,7 +303,7 @@ void http_cleanup(void) curl_global_cleanup(); curl_slist_free_all(pragma_header); - pragma_header = NULL; + pragma_header = NULL; } struct active_request_slot *get_active_slot(void) From b6abb48a152879259ab59f6e470e62b59562d712 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Sat, 15 Sep 2007 03:23:04 -0400 Subject: [PATCH 0073/1490] Don't bother passing ref log details to walker in builtin-fetch When using the walker API within builtin-fetch we don't allow it to update refs locally; instead that action is reserved for builtin-fetch's own main loop once the objects have actually been downloaded. Passing NULL here will bypass the unnecessary malloc/free of a string buffer within the walker API. That buffer is never used because the prior argument (the refs to update) is also NULL. Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- transport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/transport.c b/transport.c index 0338ed45b9..002119061e 100644 --- a/transport.c +++ b/transport.c @@ -26,7 +26,7 @@ static int fetch_objs_via_walker(struct transport *transport, for (i = 0; i < nr_objs; i++) objs[i] = xstrdup(sha1_to_hex(to_fetch[i]->old_sha1)); - if (walker_fetch(walker, nr_objs, objs, NULL, dest)) + if (walker_fetch(walker, nr_objs, objs, NULL, NULL)) die("Fetch failed."); for (i = 0; i < nr_objs; i++) From 8eb554ae628d2504922912fb5f046741da4654fc Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Sat, 15 Sep 2007 03:23:07 -0400 Subject: [PATCH 0074/1490] Cleanup duplicate initialization code in transport_get We always allocate and return a struct transport* right now as every URL is considered to be a native Git transport if it is not rsync, http/https/ftp or a bundle. So we can simplify the initialization of a new transport object by performing one xcalloc call and filling in only the attributes required. Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- transport.c | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/transport.c b/transport.c index 002119061e..5eabe8de0b 100644 --- a/transport.c +++ b/transport.c @@ -411,27 +411,26 @@ static int is_file(const char *url) struct transport *transport_get(struct remote *remote, const char *url, int fetch) { - struct transport *ret = NULL; + struct transport *ret = xcalloc(1, sizeof(*ret)); + + ret->remote = remote; + ret->url = url; + ret->fetch = !!fetch; + if (!prefixcmp(url, "rsync://")) { - ret = xmalloc(sizeof(*ret)); - ret->data = NULL; ret->ops = &rsync_transport; - } else if (!prefixcmp(url, "http://") || !prefixcmp(url, "https://") || - !prefixcmp(url, "ftp://")) { - ret = xmalloc(sizeof(*ret)); + } else if (!prefixcmp(url, "http://") + || !prefixcmp(url, "https://") + || !prefixcmp(url, "ftp://")) { ret->ops = &curl_transport; if (fetch) ret->data = get_http_walker(url); - else - ret->data = NULL; } else if (is_local(url) && is_file(url)) { struct bundle_transport_data *data = xcalloc(1, sizeof(*data)); - ret = xmalloc(sizeof(*ret)); ret->data = data; ret->ops = &bundle_transport; } else { struct git_transport_data *data = xcalloc(1, sizeof(*data)); - ret = xcalloc(1, sizeof(*ret)); ret->data = data; data->thin = 1; data->uploadpack = "git-upload-pack"; @@ -443,13 +442,7 @@ struct transport *transport_get(struct remote *remote, const char *url, data->unpacklimit = -1; ret->ops = &git_transport; } - if (ret) { - ret->remote = remote; - ret->url = url; - ret->remote_refs = NULL; - ret->fetch = !!fetch; - ret->pack_lockfile = NULL; - } + return ret; } From be6042cfa59358b733b6f9ba05bcbc317998d9fe Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Sat, 15 Sep 2007 03:23:10 -0400 Subject: [PATCH 0075/1490] Add transport.h to LIB_H as transport.o is in LIB_OBJS Any changes to transport.h probably will require rebuilding a number of object files so we should make sure it is included in our set of headers. Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 5b447d4f73..23dc52c1d9 100644 --- a/Makefile +++ b/Makefile @@ -287,7 +287,7 @@ LIB_H = \ run-command.h strbuf.h tag.h tree.h git-compat-util.h revision.h \ tree-walk.h log-tree.h dir.h path-list.h unpack-trees.h builtin.h \ utf8.h reflog-walk.h patch-ids.h attr.h decorate.h progress.h \ - mailmap.h remote.h + mailmap.h remote.h transport.h DIFF_OBJS = \ diff.o diff-lib.o diffcore-break.o diffcore-order.o \ From e5f4e214636f9c9bd36c2897634108d5ad5587a1 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Sat, 15 Sep 2007 03:23:14 -0400 Subject: [PATCH 0076/1490] Remove unnecessary 'fetch' argument from transport_get API We don't actually need to know at the time of transport_get if the caller wants to fetch, push, or do both on the returned object. It is easier to just delay the initialization of the HTTP walker until we know we will need it by providing a CURL specific fetch function in the curl_transport that makes sure the walker instance is initialized before use. Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- builtin-fetch.c | 2 +- builtin-push.c | 2 +- transport.c | 23 +++++++++++++++++------ transport.h | 4 +--- 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/builtin-fetch.c b/builtin-fetch.c index 8b0fdbe905..300d5635b0 100644 --- a/builtin-fetch.c +++ b/builtin-fetch.c @@ -496,7 +496,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) else remote = remote_get(argv[i++]); - transport = transport_get(remote, remote->uri[0], 1); + transport = transport_get(remote, remote->uri[0]); if (verbose >= 2) transport->verbose = 1; if (quiet) diff --git a/builtin-push.c b/builtin-push.c index f496b46007..7d7e826a39 100644 --- a/builtin-push.c +++ b/builtin-push.c @@ -59,7 +59,7 @@ static int do_push(const char *repo, int flags) errs = 0; for (i = 0; i < remote->uri_nr; i++) { struct transport *transport = - transport_get(remote, remote->uri[i], 0); + transport_get(remote, remote->uri[i]); int err; if (receivepack) transport_set_option(transport, diff --git a/transport.c b/transport.c index 5eabe8de0b..7f94d30f95 100644 --- a/transport.c +++ b/transport.c @@ -174,6 +174,14 @@ static struct ref *get_refs_via_curl(const struct transport *transport) return refs; } +static int fetch_objs_via_curl(struct transport *transport, + int nr_objs, struct ref **to_fetch) +{ + if (!transport->data) + transport->data = get_http_walker(transport->url); + return fetch_objs_via_walker(transport, nr_objs, to_fetch); +} + #else static struct ref *get_refs_via_curl(const struct transport *transport) @@ -182,12 +190,19 @@ static struct ref *get_refs_via_curl(const struct transport *transport) return NULL; } +static int fetch_objs_via_curl(struct transport *transport, + int nr_objs, struct ref **to_fetch) +{ + die("Cannot fetch from '%s' without curl ...", transport->url); + return -1; +} + #endif static const struct transport_ops curl_transport = { /* set_option */ NULL, /* get_refs_list */ get_refs_via_curl, - /* fetch */ fetch_objs_via_walker, + /* fetch */ fetch_objs_via_curl, /* push */ curl_transport_push, /* disconnect */ disconnect_walker }; @@ -408,14 +423,12 @@ static int is_file(const char *url) return S_ISREG(buf.st_mode); } -struct transport *transport_get(struct remote *remote, const char *url, - int fetch) +struct transport *transport_get(struct remote *remote, const char *url) { struct transport *ret = xcalloc(1, sizeof(*ret)); ret->remote = remote; ret->url = url; - ret->fetch = !!fetch; if (!prefixcmp(url, "rsync://")) { ret->ops = &rsync_transport; @@ -423,8 +436,6 @@ struct transport *transport_get(struct remote *remote, const char *url, || !prefixcmp(url, "https://") || !prefixcmp(url, "ftp://")) { ret->ops = &curl_transport; - if (fetch) - ret->data = get_http_walker(url); } else if (is_local(url) && is_file(url)) { struct bundle_transport_data *data = xcalloc(1, sizeof(*data)); ret->data = data; diff --git a/transport.h b/transport.h index f2bbdf778a..6a95d66053 100644 --- a/transport.h +++ b/transport.h @@ -6,7 +6,6 @@ struct transport { unsigned verbose : 1; - unsigned fetch : 1; struct remote *remote; const char *url; @@ -38,8 +37,7 @@ struct transport_ops { }; /* Returns a transport suitable for the url */ -struct transport *transport_get(struct remote *remote, const char *url, - int fetch); +struct transport *transport_get(struct remote *, const char *); /* Transport options which apply to git:// and scp-style URLs */ From b3abdd9d216c578383b66bb10b95edb3380640e7 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Sun, 16 Sep 2007 02:31:26 -0400 Subject: [PATCH 0077/1490] Allow builtin-fetch to work on a detached HEAD If we are running fetch in a repository that has a detached HEAD then there is no current_branch available. In such a case any ref that the fetch might update by definition cannot also be the current branch so we should always bypass the "don't update HEAD" test. Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- builtin-fetch.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/builtin-fetch.c b/builtin-fetch.c index 300d5635b0..d9272edae9 100644 --- a/builtin-fetch.c +++ b/builtin-fetch.c @@ -151,7 +151,8 @@ static int update_local_ref(struct ref *ref, return 0; } - if (!strcmp(ref->name, current_branch->name) && + if (current_branch && + !strcmp(ref->name, current_branch->name) && !(update_head_ok || is_bare_repository()) && !is_null_sha1(ref->old_sha1)) { /* From ad23603c3af77b47f65382ea22b30d1ecccaab6f Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Sun, 16 Sep 2007 02:32:11 -0400 Subject: [PATCH 0078/1490] Don't configure remote "." to fetch everything to itself When we are talking about a remote URI of "." we are really talking about *this* repository that we are fetching into or pushing out of. There are no matching tracking branches for this repository; we do not attempt to map a ref back to ourselves as this would either create an infinite cycle (for example "fetch = +refs/*:refs/mine/*") or it causes problems when we attempt to push back to ourselves. So we really cannot setup a remote like this: [remote "."] url = . fetch = +refs/*:refs/* In the case of `git push . B:T` to fast-forward branch T to B's current commit git-send-pack will update branch T to B, assuming that T is the remote tracking branch for B. This update is performed immediately before git-send-pack asks git-receive-pack to perform the same update, and git-receive-pack then fails because T is not where git-send-pack told it to expect T to be at. In the case of `git fetch .` we really should do the same thing as `git fetch $otherrepo`, that is load .git/FETCH_HEAD with the commit of HEAD, so that `git pull .` will report "Already up-to-date". We have always behaved like this before on this insane request and we should at least continue to behave the same way. With the above (bad) remote configuration we were instead getting fetch errors about funny refs, e.g. "refs/stash". Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- remote.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/remote.c b/remote.c index df91b2ff99..73a34c9e36 100644 --- a/remote.c +++ b/remote.c @@ -356,10 +356,6 @@ struct remote *remote_get(const char *name) add_uri(ret, name); if (!ret->uri) return NULL; - if (!strcmp(name, ".")) { - // we always fetch "refs/*:refs/*", which is trivial - add_fetch_refspec(ret, "refs/*:refs/*"); - } ret->fetch = parse_ref_spec(ret->fetch_refspec_nr, ret->fetch_refspec); ret->push = parse_ref_spec(ret->push_refspec_nr, ret->push_refspec); return ret; From f38395905b3d49bd68e0c01ca2310bf3387e1063 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Sun, 16 Sep 2007 02:32:17 -0400 Subject: [PATCH 0079/1490] Remove more debugging from builtin-fetch Older git-fetch.sh doesn't print "ref: X" when invoked as `git fetch $url X" so we shouldn't do that now in the new builtin version. Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- builtin-fetch.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/builtin-fetch.c b/builtin-fetch.c index d9272edae9..20926e0543 100644 --- a/builtin-fetch.c +++ b/builtin-fetch.c @@ -530,8 +530,6 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) } refs[j] = NULL; ref_nr = j; - for (j = 0; refs[j]; j++) - printf("ref: %s\n", refs[j]); } signal(SIGINT, unlock_pack_on_signal); From 27e13374bf1864eb8aea44cca3afd81eedb007aa Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Tue, 18 Sep 2007 04:54:48 -0400 Subject: [PATCH 0080/1490] builtin-fetch: Don't segfault on "fetch +foo" If we are fetching something and were configured to do a forced fetch and have no local ref to store the fetched object into we cannot mark the local ref as having a forced update. Instead we should just silently discard the + request. Signed-off-by: Shawn O. Pearce --- remote.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/remote.c b/remote.c index 73a34c9e36..af3c46bb35 100644 --- a/remote.c +++ b/remote.c @@ -875,8 +875,7 @@ int get_fetch_map(struct ref *remote_refs, refspec->src : "HEAD"); ref_map->peer_ref = get_local_ref(refspec->dst); - - if (refspec->force) + if (ref_map->peer_ref && refspec->force) ref_map->peer_ref->force = 1; } From d8b3a2bf189a9e7fea76454157b77fa71c9abc05 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Tue, 18 Sep 2007 04:54:51 -0400 Subject: [PATCH 0081/1490] Don't attempt to merge non-existant remotes in t5515 This was actually reverted in 756373da by Junio. We no longer support merging the right hand side of a fetchspec in a branch's branch.$name.merge configuration setting as we interpret these names as being only those published by the remote we are going to fetch from. The older shell based implementation of git-fetch did not report an error when branch.$name.merge was referencing a branch that does not exist on the remote and we are running `git fetch` for the current branch. The new builtin-fetch does notice this failure and aborts the fetch, thus breaking the tests. Junio and I kicked it around on #git earlier today and decided that the best approach here is to error out and tell the user that their configuration is wrong, as this is likely more user friendly than silently ignoring the user's request. Since the new builtin-fetch is already issuing the error there is no code change required, we just need to remove the bad configuration from our test. Signed-off-by: Shawn O. Pearce --- t/t5515-fetch-merge-logic.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/t/t5515-fetch-merge-logic.sh b/t/t5515-fetch-merge-logic.sh index 6c9cc67508..31c1081617 100755 --- a/t/t5515-fetch-merge-logic.sh +++ b/t/t5515-fetch-merge-logic.sh @@ -84,8 +84,7 @@ test_expect_success setup ' git config branch.br-$remote-merge.merge refs/heads/three && git config branch.br-$remote-octopus.remote $remote && git config branch.br-$remote-octopus.merge refs/heads/one && - git config --add branch.br-$remote-octopus.merge two && - git config --add branch.br-$remote-octopus.merge remotes/rem/three + git config --add branch.br-$remote-octopus.merge two done ' From 85682c1903a4ae776b0bf2d30d9ecd1e19689131 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Tue, 18 Sep 2007 04:54:53 -0400 Subject: [PATCH 0082/1490] Correct handling of branch.$name.merge in builtin-fetch My prior bug fix for git-push titled "Don't configure remote "." to fetch everything to itself" actually broke t5520 as we were unable to evaluate a branch configuration of: [branch "copy"] remote = . merge = refs/heads/master as remote "." did not have a "remote...fetch" configuration entry to offer up refs/heads/master as a possible candidate available to be fetched and merged. In shell script git-fetch and prior to the above mentioned commit this was hardcoded for a url of "." to be the set of local branches. Chasing down this bug led me to the conclusion that our prior behavior with regards to branch.$name.merge was incorrect. In the shell script based git-fetch implementation we only fetched and merged a branch if it appeared both in branch.$name.merge *and* in remote.$r.fetch, where $r = branch.$name.remote. In other words in the following config file: [remote "origin"] url = git://git.kernel.org/pub/scm/git/git.git fetch = refs/heads/master:refs/remotes/origin/master [branch "master"] remote = origin merge = refs/heads/master [branch "pu"] remote = origin merge = refs/heads/pu Attempting to run `git pull` while on branch "pu" would always give the user "Already up-to-date" as git-fetch did not fetch pu and thus did not mark it for merge in .git/FETCH_HEAD. The configured merge would always be ignored and the user would be left scratching her confused head wondering why merge did not work on "pu" but worked fine on "master". If we are using the "default fetch" specification for the current branch and the current branch has a branch.$name.merge configured we now union it with the list of refs in remote.$r.fetch. This way the above configuration does what the user expects it to do, which is to fetch only "master" by default but when on "pu" to fetch both "master" and "pu". This uncovered some breakage in the test suite where old-style Cogito branches (.git/branches/$r) did not fetch the branches listed in .git/config for merging and thus did not actually merge them if the user tried to use `git pull` on that branch. Junio and I discussed it on list and felt that the union approach here makes more sense to DWIM for the end-user than silently ignoring their configured request so the test vectors for t5515 have been updated to include for-merge lines in .git/FETCH_HEAD where they have been configured for-merge in .git/config. Since we are now performing a union of the fetch specification and the merge specification and we cannot allow a branch to be listed twice (otherwise it comes out twice in .git/FETCH_HEAD) we need to perform a double loop here over all of the branch.$name.merge lines and try to set their merge flag if we have already schedule that branch for fetching by remote.$r.fetch. If no match is found then we must add new specifications to fetch the branch but not store it as no local tracking branch has been designated. Signed-off-by: Shawn O. Pearce --- builtin-fetch.c | 48 ++++++++++++++----- remote.c | 13 ++--- remote.h | 3 +- t/t5515/fetch.br-branches-default-merge | 1 + ...br-branches-default-merge_branches-default | 1 + t/t5515/fetch.br-branches-default-octopus | 2 + ...-branches-default-octopus_branches-default | 2 + t/t5515/fetch.br-branches-one-merge | 1 + .../fetch.br-branches-one-merge_branches-one | 1 + t/t5515/fetch.br-branches-one-octopus | 1 + ...fetch.br-branches-one-octopus_branches-one | 1 + 11 files changed, 51 insertions(+), 23 deletions(-) diff --git a/builtin-fetch.c b/builtin-fetch.c index 20926e0543..670af0b53f 100644 --- a/builtin-fetch.c +++ b/builtin-fetch.c @@ -28,20 +28,37 @@ static void unlock_pack_on_signal(int signo) raise(signo); } -static void find_merge_config(struct ref *ref_map, struct remote *remote) +static void add_merge_config(struct ref **head, + struct ref *remote_refs, + struct branch *branch, + struct ref ***tail) { - struct ref *rm = ref_map; - struct branch *branch = branch_get(NULL); + int i; - for (rm = ref_map; rm; rm = rm->next) { - if (!branch_has_merge_config(branch)) { - if (remote && remote->fetch && - !strcmp(remote->fetch[0].src, rm->name)) - rm->merge = 1; - } else { - if (branch_merges(branch, rm->name)) + for (i = 0; i < branch->merge_nr; i++) { + struct ref *rm, **old_tail = *tail; + struct refspec refspec; + + for (rm = *head; rm; rm = rm->next) { + if (branch_merge_matches(branch, i, rm->name)) { rm->merge = 1; + break; + } } + if (rm) + continue; + + /* Not fetched to a tracking branch? We need to fetch + * it anyway to allow this branch's "branch.$name.merge" + * to be honored by git-pull. + */ + refspec.src = branch->merge[i]->src; + refspec.dst = NULL; + refspec.pattern = 0; + refspec.force = 0; + get_fetch_map(remote_refs, &refspec, tail); + for (rm = *old_tail; rm; rm = rm->next) + rm->merge = 1; } } @@ -76,17 +93,22 @@ static struct ref *get_ref_map(struct transport *transport, } else { /* Use the defaults */ struct remote *remote = transport->remote; - if (remote->fetch_refspec_nr) { + struct branch *branch = branch_get(NULL); + int has_merge = branch_has_merge_config(branch); + if (remote && (remote->fetch_refspec_nr || has_merge)) { for (i = 0; i < remote->fetch_refspec_nr; i++) { get_fetch_map(remote_refs, &remote->fetch[i], &tail); if (remote->fetch[i].dst && remote->fetch[i].dst[0]) *autotags = 1; + if (!i && !has_merge && ref_map && + !strcmp(remote->fetch[0].src, ref_map->name)) + ref_map->merge = 1; } - find_merge_config(ref_map, remote); + if (has_merge) + add_merge_config(&ref_map, remote_refs, branch, &tail); } else { ref_map = get_remote_ref(remote_refs, "HEAD"); - ref_map->merge = 1; } } diff --git a/remote.c b/remote.c index af3c46bb35..31e2b70d37 100644 --- a/remote.c +++ b/remote.c @@ -772,16 +772,13 @@ int branch_has_merge_config(struct branch *branch) return branch && !!branch->merge; } -int branch_merges(struct branch *branch, const char *refname) +int branch_merge_matches(struct branch *branch, + int i, + const char *refname) { - int i; - if (!branch) + if (!branch || i < 0 || i >= branch->merge_nr) return 0; - for (i = 0; i < branch->merge_nr; i++) { - if (ref_matches_abbrev(branch->merge[i]->src, refname)) - return 1; - } - return 0; + return ref_matches_abbrev(branch->merge[i]->src, refname); } static struct ref *get_expanded_map(struct ref *remote_refs, diff --git a/remote.h b/remote.h index 89940527ad..b5b558f1f1 100644 --- a/remote.h +++ b/remote.h @@ -88,7 +88,6 @@ struct branch { struct branch *branch_get(const char *name); int branch_has_merge_config(struct branch *branch); - -int branch_merges(struct branch *branch, const char *refname); +int branch_merge_matches(struct branch *, int n, const char *); #endif diff --git a/t/t5515/fetch.br-branches-default-merge b/t/t5515/fetch.br-branches-default-merge index 828bfd8e9e..ca2cc1d1b4 100644 --- a/t/t5515/fetch.br-branches-default-merge +++ b/t/t5515/fetch.br-branches-default-merge @@ -1,5 +1,6 @@ # br-branches-default-merge 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b branch 'three' of ../ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ diff --git a/t/t5515/fetch.br-branches-default-merge_branches-default b/t/t5515/fetch.br-branches-default-merge_branches-default index f1486730fa..7d947cd80f 100644 --- a/t/t5515/fetch.br-branches-default-merge_branches-default +++ b/t/t5515/fetch.br-branches-default-merge_branches-default @@ -1,5 +1,6 @@ # br-branches-default-merge branches-default 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b branch 'three' of ../ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ diff --git a/t/t5515/fetch.br-branches-default-octopus b/t/t5515/fetch.br-branches-default-octopus index bb1a1915c6..ec39c54b7e 100644 --- a/t/t5515/fetch.br-branches-default-octopus +++ b/t/t5515/fetch.br-branches-default-octopus @@ -1,5 +1,7 @@ # br-branches-default-octopus 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ +8e32a6d901327a23ef831511badce7bf3bf46689 branch 'one' of ../ +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 branch 'two' of ../ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ diff --git a/t/t5515/fetch.br-branches-default-octopus_branches-default b/t/t5515/fetch.br-branches-default-octopus_branches-default index 970fc93725..6bf42e24b6 100644 --- a/t/t5515/fetch.br-branches-default-octopus_branches-default +++ b/t/t5515/fetch.br-branches-default-octopus_branches-default @@ -1,5 +1,7 @@ # br-branches-default-octopus branches-default 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../ +8e32a6d901327a23ef831511badce7bf3bf46689 branch 'one' of ../ +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 branch 'two' of ../ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ diff --git a/t/t5515/fetch.br-branches-one-merge b/t/t5515/fetch.br-branches-one-merge index 24099fd53e..b4b3b35ce0 100644 --- a/t/t5515/fetch.br-branches-one-merge +++ b/t/t5515/fetch.br-branches-one-merge @@ -1,5 +1,6 @@ # br-branches-one-merge 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge branch 'one' of ../ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b branch 'three' of ../ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ diff --git a/t/t5515/fetch.br-branches-one-merge_branches-one b/t/t5515/fetch.br-branches-one-merge_branches-one index e4b4fdee4c..2ecef384eb 100644 --- a/t/t5515/fetch.br-branches-one-merge_branches-one +++ b/t/t5515/fetch.br-branches-one-merge_branches-one @@ -1,5 +1,6 @@ # br-branches-one-merge branches-one 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge branch 'one' of ../ +0567da4d5edd2ff4bb292a465ba9e64dcad9536b branch 'three' of ../ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ diff --git a/t/t5515/fetch.br-branches-one-octopus b/t/t5515/fetch.br-branches-one-octopus index 53fe808a3b..96e3029416 100644 --- a/t/t5515/fetch.br-branches-one-octopus +++ b/t/t5515/fetch.br-branches-one-octopus @@ -1,5 +1,6 @@ # br-branches-one-octopus 8e32a6d901327a23ef831511badce7bf3bf46689 branch 'one' of ../ +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 branch 'two' of ../ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ diff --git a/t/t5515/fetch.br-branches-one-octopus_branches-one b/t/t5515/fetch.br-branches-one-octopus_branches-one index 41b18ff78a..55e0bad621 100644 --- a/t/t5515/fetch.br-branches-one-octopus_branches-one +++ b/t/t5515/fetch.br-branches-one-octopus_branches-one @@ -1,5 +1,6 @@ # br-branches-one-octopus branches-one 8e32a6d901327a23ef831511badce7bf3bf46689 branch 'one' of ../ +6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 branch 'two' of ../ 754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge tag 'tag-master' of ../ 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../ 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../ From ab865e6eec1f40938604b1c28a32525c1fdc7227 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Tue, 18 Sep 2007 04:54:57 -0400 Subject: [PATCH 0083/1490] Avoid printing unnecessary warnings during fetch and push If a transport doesn't support an option we already are telling the higher level application (fetch or push) that the option is not valid by sending back a >0 return value from transport_set_option so there's not a strong motivation to have the function perform the output itself. Instead we should let the higher level application do the output if it is necessary. This avoids always telling the user that depth isn't supported on HTTP urls even when they did not pass a --depth option to git-fetch. If the user passes an option and the option value is invalid we now properly die in git-fetch instead of just spitting out a message and running anyway. This mimics prior behavior better where incorrect/malformed options are not accepted by the process. Signed-off-by: Shawn O. Pearce --- builtin-fetch.c | 18 +++++++++++++++--- transport.c | 11 ++--------- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/builtin-fetch.c b/builtin-fetch.c index 670af0b53f..b9722e5fbd 100644 --- a/builtin-fetch.c +++ b/builtin-fetch.c @@ -430,6 +430,17 @@ static int do_fetch(struct transport *transport, return 0; } +static void set_option(const char *name, const char *value) +{ + int r = transport_set_option(transport, name, value); + if (r < 0) + die("Option \"%s\" value \"%s\" is not valid for %s\n", + name, value, transport->url); + if (r > 0) + warning("Option \"%s\" is ignored for %s\n", + name, transport->url); +} + int cmd_fetch(int argc, const char **argv, const char *prefix) { struct remote *remote; @@ -525,10 +536,11 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) if (quiet) transport->verbose = 0; if (upload_pack) - transport_set_option(transport, TRANS_OPT_UPLOADPACK, upload_pack); + set_option(TRANS_OPT_UPLOADPACK, upload_pack); if (keep) - transport_set_option(transport, TRANS_OPT_KEEP, "yes"); - transport_set_option(transport, TRANS_OPT_DEPTH, depth); + set_option(TRANS_OPT_KEEP, "yes"); + if (depth) + set_option(TRANS_OPT_DEPTH, depth); if (!transport->url) die("Where do you want to fetch from today?"); diff --git a/transport.c b/transport.c index 7f94d30f95..cc76e3f59b 100644 --- a/transport.c +++ b/transport.c @@ -460,16 +460,9 @@ struct transport *transport_get(struct remote *remote, const char *url) int transport_set_option(struct transport *transport, const char *name, const char *value) { - int ret = 1; if (transport->ops->set_option) - ret = transport->ops->set_option(transport, name, value); - if (ret < 0) - fprintf(stderr, "For '%s' option %s cannot be set to '%s'\n", - transport->url, name, value); - if (ret > 0) - fprintf(stderr, "For '%s' option %s is ignored\n", - transport->url, name); - return ret; + return transport->ops->set_option(transport, name, value); + return 1; } int transport_push(struct transport *transport, From bbaf4584286657582a92d5bb4038a5a06654ebb1 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Tue, 18 Sep 2007 04:55:00 -0400 Subject: [PATCH 0084/1490] Use 'unsigned:1' when we mean boolean options These options are all strictly boolean (true/false). Its easier to document this implicitly by making their storage type a single bit. There is no compelling memory space reduction reason for this change, it just makes the structure definition slightly more readable. Signed-off-by: Shawn O. Pearce --- fetch-pack.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/fetch-pack.h b/fetch-pack.h index cdcd84f2b5..ad1307689d 100644 --- a/fetch-pack.h +++ b/fetch-pack.h @@ -4,14 +4,14 @@ struct fetch_pack_args { const char *uploadpack; - int quiet; - int keep_pack; int unpacklimit; - int use_thin_pack; - int fetch_all; - int verbose; int depth; - int no_progress; + unsigned quiet:1, + keep_pack:1, + use_thin_pack:1, + fetch_all:1, + verbose:1, + no_progress:1; }; void setup_fetch_pack(struct fetch_pack_args *args); From 28b91f8ad9e4791b5c35ca6bffbb78725b4e5bbf Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Wed, 19 Sep 2007 00:49:27 -0400 Subject: [PATCH 0085/1490] Rename remote.uri to remote.url within remote handling internals Anyplace we talk about the address of a remote repository we always refer to it as a URL, especially in the configuration file and .git/remotes where we call it "remote.$n.url" or start the first line with "URL:". Calling this value a uri within the internal C code just doesn't jive well with our commonly accepted terms. Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- builtin-fetch.c | 2 +- builtin-push.c | 8 ++++---- remote.c | 34 +++++++++++++++++----------------- remote.h | 6 +++--- send-pack.c | 2 +- 5 files changed, 26 insertions(+), 26 deletions(-) diff --git a/builtin-fetch.c b/builtin-fetch.c index b9722e5fbd..997a8ff954 100644 --- a/builtin-fetch.c +++ b/builtin-fetch.c @@ -530,7 +530,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) else remote = remote_get(argv[i++]); - transport = transport_get(remote, remote->uri[0]); + transport = transport_get(remote, remote->url[0]); if (verbose >= 2) transport->verbose = 1; if (quiet) diff --git a/builtin-push.c b/builtin-push.c index 7d7e826a39..4ee36c292d 100644 --- a/builtin-push.c +++ b/builtin-push.c @@ -57,9 +57,9 @@ static int do_push(const char *repo, int flags) refspec_nr = remote->push_refspec_nr; } errs = 0; - for (i = 0; i < remote->uri_nr; i++) { + for (i = 0; i < remote->url_nr; i++) { struct transport *transport = - transport_get(remote, remote->uri[i]); + transport_get(remote, remote->url[i]); int err; if (receivepack) transport_set_option(transport, @@ -68,14 +68,14 @@ static int do_push(const char *repo, int flags) transport_set_option(transport, TRANS_OPT_THIN, "yes"); if (verbose) - fprintf(stderr, "Pushing to %s\n", remote->uri[i]); + fprintf(stderr, "Pushing to %s\n", remote->url[i]); err = transport_push(transport, refspec_nr, refspec, flags); err |= transport_disconnect(transport); if (!err) continue; - error("failed to push to '%s'", remote->uri[i]); + error("failed to push to '%s'", remote->url[i]); errs++; } return !!errs; diff --git a/remote.c b/remote.c index 31e2b70d37..e3c3df556d 100644 --- a/remote.c +++ b/remote.c @@ -32,13 +32,13 @@ static void add_fetch_refspec(struct remote *remote, const char *ref) remote->fetch_refspec_nr = nr; } -static void add_uri(struct remote *remote, const char *uri) +static void add_url(struct remote *remote, const char *url) { - int nr = remote->uri_nr + 1; - remote->uri = - xrealloc(remote->uri, nr * sizeof(char *)); - remote->uri[nr-1] = uri; - remote->uri_nr = nr; + int nr = remote->url_nr + 1; + remote->url = + xrealloc(remote->url, nr * sizeof(char *)); + remote->url[nr-1] = url; + remote->url_nr = nr; } static struct remote *make_remote(const char *name, int len) @@ -154,7 +154,7 @@ static void read_remotes_file(struct remote *remote) switch (value_list) { case 0: - add_uri(remote, xstrdup(s)); + add_url(remote, xstrdup(s)); break; case 1: add_push_refspec(remote, xstrdup(s)); @@ -206,7 +206,7 @@ static void read_branches_file(struct remote *remote) } else { branch = "refs/heads/master"; } - add_uri(remote, p); + add_url(remote, p); add_fetch_refspec(remote, branch); remote->fetch_tags = 1; /* always auto-follow */ } @@ -260,7 +260,7 @@ static int handle_config(const char *key, const char *value) return 0; /* ignore unknown booleans */ } if (!strcmp(subkey, ".url")) { - add_uri(remote, xstrdup(value)); + add_url(remote, xstrdup(value)); } else if (!strcmp(subkey, ".push")) { add_push_refspec(remote, xstrdup(value)); } else if (!strcmp(subkey, ".fetch")) { @@ -347,14 +347,14 @@ struct remote *remote_get(const char *name) name = default_remote_name; ret = make_remote(name, 0); if (name[0] != '/') { - if (!ret->uri) + if (!ret->url) read_remotes_file(ret); - if (!ret->uri) + if (!ret->url) read_branches_file(ret); } - if (!ret->uri) - add_uri(ret, name); - if (!ret->uri) + if (!ret->url) + add_url(ret, name); + if (!ret->url) return NULL; ret->fetch = parse_ref_spec(ret->fetch_refspec_nr, ret->fetch_refspec); ret->push = parse_ref_spec(ret->push_refspec_nr, ret->push_refspec); @@ -380,11 +380,11 @@ int for_each_remote(each_remote_fn fn, void *priv) return result; } -int remote_has_uri(struct remote *remote, const char *uri) +int remote_has_url(struct remote *remote, const char *url) { int i; - for (i = 0; i < remote->uri_nr; i++) { - if (!strcmp(remote->uri[i], uri)) + for (i = 0; i < remote->url_nr; i++) { + if (!strcmp(remote->url[i], url)) return 1; } return 0; diff --git a/remote.h b/remote.h index b5b558f1f1..05add06e48 100644 --- a/remote.h +++ b/remote.h @@ -4,8 +4,8 @@ struct remote { const char *name; - const char **uri; - int uri_nr; + const char **url; + int url_nr; const char **push_refspec; struct refspec *push; @@ -32,7 +32,7 @@ struct remote *remote_get(const char *name); typedef int each_remote_fn(struct remote *remote, void *priv); int for_each_remote(each_remote_fn fn, void *priv); -int remote_has_uri(struct remote *remote, const char *uri); +int remote_has_url(struct remote *remote, const char *url); struct refspec { unsigned force : 1; diff --git a/send-pack.c b/send-pack.c index f74e66a8ba..4533d1bf8e 100644 --- a/send-pack.c +++ b/send-pack.c @@ -420,7 +420,7 @@ int main(int argc, char **argv) if (remote_name) { remote = remote_get(remote_name); - if (!remote_has_uri(remote, dest)) { + if (!remote_has_url(remote, dest)) { die("Destination %s is not a uri for %s", dest, remote_name); } From 824d5776c3f275c644c71b8c7e254bd2d7b08071 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Wed, 19 Sep 2007 00:49:31 -0400 Subject: [PATCH 0086/1490] Refactor struct transport_ops inlined into struct transport Aside from reducing the code by 20 lines this refactoring removes a level of indirection when trying to access the operations of a given transport "instance", making the code clearer and easier to follow. It also has the nice effect of giving us the benefits of C99 style struct initialization (namely ".fetch = X") without requiring that level of language support from our compiler. We don't need to worry about new operation methods being added as they will now be NULL'd out automatically by the xcalloc() we use to create the new struct transport we supply to the caller. This pattern already exists in struct walker, so we already have a precedent for it in Git. We also don't really need to worry about any sort of performance decreases that may occur as a result of filling out 4-8 op pointers when we make a "struct transport". The extra few CPU cycles this requires over filling in the "struct transport_ops" is killed by the time it will take Git to actually *use* one of those functions, as most transport operations are going over the wire or will be copying object data locally between two directories. Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- builtin-fetch.c | 3 +-- transport.c | 62 +++++++++++++++++++------------------------------ transport.h | 16 ++++--------- 3 files changed, 30 insertions(+), 51 deletions(-) diff --git a/builtin-fetch.c b/builtin-fetch.c index 997a8ff954..2f639ccef2 100644 --- a/builtin-fetch.c +++ b/builtin-fetch.c @@ -392,8 +392,7 @@ static int do_fetch(struct transport *transport, if (transport->remote->fetch_tags == -1) no_tags = 1; - if (!transport->ops || !transport->ops->get_refs_list || - !transport->ops->fetch) + if (!transport->get_refs_list || !transport->fetch) die("Don't know how to fetch from %s", transport->url); /* if not appending, truncate FETCH_HEAD */ diff --git a/transport.c b/transport.c index cc76e3f59b..d8458dc85a 100644 --- a/transport.c +++ b/transport.c @@ -44,8 +44,6 @@ static int disconnect_walker(struct transport *transport) return 0; } -static const struct transport_ops rsync_transport; - static int curl_transport_push(struct transport *transport, int refspec_nr, const char **refspec, int flags) { const char **argv; int argc; @@ -199,14 +197,6 @@ static int fetch_objs_via_curl(struct transport *transport, #endif -static const struct transport_ops curl_transport = { - /* set_option */ NULL, - /* get_refs_list */ get_refs_via_curl, - /* fetch */ fetch_objs_via_curl, - /* push */ curl_transport_push, - /* disconnect */ disconnect_walker -}; - struct bundle_transport_data { int fd; struct bundle_header header; @@ -249,14 +239,6 @@ static int close_bundle(struct transport *transport) return 0; } -static const struct transport_ops bundle_transport = { - /* set_option */ NULL, - /* get_refs_list */ get_refs_from_bundle, - /* fetch */ fetch_refs_from_bundle, - /* push */ NULL, - /* disconnect */ close_bundle -}; - struct git_transport_data { unsigned thin : 1; unsigned keep : 1; @@ -401,13 +383,6 @@ static int git_transport_push(struct transport *transport, int refspec_nr, const return !!err; } -static const struct transport_ops git_transport = { - /* set_option */ set_git_option, - /* get_refs_list */ get_refs_via_connect, - /* fetch */ fetch_refs_via_pack, - /* push */ git_transport_push -}; - static int is_local(const char *url) { const char *colon = strchr(url, ':'); @@ -431,18 +406,31 @@ struct transport *transport_get(struct remote *remote, const char *url) ret->url = url; if (!prefixcmp(url, "rsync://")) { - ret->ops = &rsync_transport; + /* not supported; don't populate any ops */ + } else if (!prefixcmp(url, "http://") || !prefixcmp(url, "https://") || !prefixcmp(url, "ftp://")) { - ret->ops = &curl_transport; + ret->get_refs_list = get_refs_via_curl; + ret->fetch = fetch_objs_via_curl; + ret->push = curl_transport_push; + ret->disconnect = disconnect_walker; + } else if (is_local(url) && is_file(url)) { struct bundle_transport_data *data = xcalloc(1, sizeof(*data)); ret->data = data; - ret->ops = &bundle_transport; + ret->get_refs_list = get_refs_from_bundle; + ret->fetch = fetch_refs_from_bundle; + ret->disconnect = close_bundle; + } else { struct git_transport_data *data = xcalloc(1, sizeof(*data)); ret->data = data; + ret->set_option = set_git_option; + ret->get_refs_list = get_refs_via_connect; + ret->fetch = fetch_refs_via_pack; + ret->push = git_transport_push; + data->thin = 1; data->uploadpack = "git-upload-pack"; if (remote && remote->uploadpack) @@ -451,7 +439,6 @@ struct transport *transport_get(struct remote *remote, const char *url) if (remote && remote->receivepack) data->receivepack = remote->receivepack; data->unpacklimit = -1; - ret->ops = &git_transport; } return ret; @@ -460,24 +447,23 @@ struct transport *transport_get(struct remote *remote, const char *url) int transport_set_option(struct transport *transport, const char *name, const char *value) { - if (transport->ops->set_option) - return transport->ops->set_option(transport, name, value); + if (transport->set_option) + return transport->set_option(transport, name, value); return 1; } int transport_push(struct transport *transport, int refspec_nr, const char **refspec, int flags) { - if (!transport->ops->push) + if (!transport->push) return 1; - return transport->ops->push(transport, refspec_nr, refspec, flags); + return transport->push(transport, refspec_nr, refspec, flags); } struct ref *transport_get_remote_refs(struct transport *transport) { if (!transport->remote_refs) - transport->remote_refs = - transport->ops->get_refs_list(transport); + transport->remote_refs = transport->get_refs_list(transport); return transport->remote_refs; } @@ -496,7 +482,7 @@ int transport_fetch_refs(struct transport *transport, struct ref *refs) heads[nr_heads++] = rm; } - rc = transport->ops->fetch(transport, nr_heads, heads); + rc = transport->fetch(transport, nr_heads, heads); free(heads); return rc; } @@ -513,8 +499,8 @@ void transport_unlock_pack(struct transport *transport) int transport_disconnect(struct transport *transport) { int ret = 0; - if (transport->ops->disconnect) - ret = transport->ops->disconnect(transport); + if (transport->disconnect) + ret = transport->disconnect(transport); free(transport); return ret; } diff --git a/transport.h b/transport.h index 6a95d66053..3e332ff53a 100644 --- a/transport.h +++ b/transport.h @@ -5,22 +5,11 @@ #include "remote.h" struct transport { - unsigned verbose : 1; struct remote *remote; const char *url; - void *data; - struct ref *remote_refs; - const struct transport_ops *ops; - char *pack_lockfile; -}; - -#define TRANSPORT_PUSH_ALL 1 -#define TRANSPORT_PUSH_FORCE 2 - -struct transport_ops { /** * Returns 0 if successful, positive if the option is not * recognized or is inapplicable, and negative if the option @@ -34,8 +23,13 @@ struct transport_ops { int (*push)(struct transport *connection, int refspec_nr, const char **refspec, int flags); int (*disconnect)(struct transport *connection); + char *pack_lockfile; + unsigned verbose : 1; }; +#define TRANSPORT_PUSH_ALL 1 +#define TRANSPORT_PUSH_FORCE 2 + /* Returns a transport suitable for the url */ struct transport *transport_get(struct remote *, const char *); From fa74052922cf39e5a39ad7178d1b13c2da9b4519 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Wed, 19 Sep 2007 00:49:35 -0400 Subject: [PATCH 0087/1490] Always obtain fetch-pack arguments from struct fetch_pack_args Copying the arguments from a fetch_pack_args into static globals within the builtin-fetch-pack module is error-prone and may lead rise to cases where arguments supplied via the struct from the new fetch_pack() API may not be honored by the implementation. Here we reorganize all of the static globals into a single static struct fetch_pack_args instance and use memcpy() to move the data from the caller supplied structure into the globals before we execute our pack fetching implementation. This strategy is more robust to additions and deletions of properties. As keep_pack is a single bit we have also introduced lock_pack to mean not only download and store the packfile via index-pack but also to lock it against repacking by creating a .keep file when the packfile itself is stored. The caller must remove the .keep file when it is safe to do so. Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- builtin-fetch-pack.c | 111 ++++++++++++++++++------------------------- fetch-pack.h | 9 ++-- transport.c | 9 ++-- 3 files changed, 55 insertions(+), 74 deletions(-) diff --git a/builtin-fetch-pack.c b/builtin-fetch-pack.c index 2977a94197..77eb181b5f 100644 --- a/builtin-fetch-pack.c +++ b/builtin-fetch-pack.c @@ -8,15 +8,11 @@ #include "sideband.h" #include "fetch-pack.h" -static int keep_pack; static int transfer_unpack_limit = -1; static int fetch_unpack_limit = -1; static int unpack_limit = 100; -static int quiet; -static int verbose; -static int fetch_all; -static int depth; -static int no_progress; +static struct fetch_pack_args args; + static const char fetch_pack_usage[] = "git-fetch-pack [--all] [--quiet|-q] [--keep|-k] [--thin] [--upload-pack=] [--depth=] [--no-progress] [-v] [:] [...]"; static const char *uploadpack = "git-upload-pack"; @@ -181,7 +177,7 @@ static int find_common(int fd[2], unsigned char *result_sha1, (use_sideband == 2 ? " side-band-64k" : ""), (use_sideband == 1 ? " side-band" : ""), (use_thin_pack ? " thin-pack" : ""), - (no_progress ? " no-progress" : ""), + (args.no_progress ? " no-progress" : ""), " ofs-delta"); else packet_write(fd[1], "want %s\n", sha1_to_hex(remote)); @@ -189,13 +185,13 @@ static int find_common(int fd[2], unsigned char *result_sha1, } if (is_repository_shallow()) write_shallow_commits(fd[1], 1); - if (depth > 0) - packet_write(fd[1], "deepen %d", depth); + if (args.depth > 0) + packet_write(fd[1], "deepen %d", args.depth); packet_flush(fd[1]); if (!fetching) return 1; - if (depth > 0) { + if (args.depth > 0) { char line[1024]; unsigned char sha1[20]; int len; @@ -226,7 +222,7 @@ static int find_common(int fd[2], unsigned char *result_sha1, retval = -1; while ((sha1 = get_rev())) { packet_write(fd[1], "have %s\n", sha1_to_hex(sha1)); - if (verbose) + if (args.verbose) fprintf(stderr, "have %s\n", sha1_to_hex(sha1)); in_vain++; if (!(31 & ++count)) { @@ -244,7 +240,7 @@ static int find_common(int fd[2], unsigned char *result_sha1, do { ack = get_ack(fd[0], result_sha1); - if (verbose && ack) + if (args.verbose && ack) fprintf(stderr, "got ack %d %s\n", ack, sha1_to_hex(result_sha1)); if (ack == 1) { @@ -263,7 +259,7 @@ static int find_common(int fd[2], unsigned char *result_sha1, } while (ack); flushes--; if (got_continue && MAX_IN_VAIN < in_vain) { - if (verbose) + if (args.verbose) fprintf(stderr, "giving up\n"); break; /* give up */ } @@ -271,7 +267,7 @@ static int find_common(int fd[2], unsigned char *result_sha1, } done: packet_write(fd[1], "done\n"); - if (verbose) + if (args.verbose) fprintf(stderr, "done\n"); if (retval != 0) { multi_ack = 0; @@ -280,7 +276,7 @@ static int find_common(int fd[2], unsigned char *result_sha1, while (flushes || multi_ack) { int ack = get_ack(fd[0], result_sha1); if (ack) { - if (verbose) + if (args.verbose) fprintf(stderr, "got ack (%d) %s\n", ack, sha1_to_hex(result_sha1)); if (ack == 1) @@ -317,7 +313,7 @@ static int mark_complete(const char *path, const unsigned char *sha1, int flag, static void mark_recent_complete_commits(unsigned long cutoff) { while (complete && cutoff <= complete->item->date) { - if (verbose) + if (args.verbose) fprintf(stderr, "Marking %s as complete\n", sha1_to_hex(complete->item->object.sha1)); pop_most_recent_commit(&complete, COMPLETE); @@ -332,7 +328,7 @@ static void filter_refs(struct ref **refs, int nr_match, char **match) struct ref *ref, *next; struct ref *fastarray[32]; - if (nr_match && !fetch_all) { + if (nr_match && !args.fetch_all) { if (ARRAY_SIZE(fastarray) < nr_match) return_refs = xcalloc(nr_match, sizeof(struct ref *)); else { @@ -348,8 +344,8 @@ static void filter_refs(struct ref **refs, int nr_match, char **match) if (!memcmp(ref->name, "refs/", 5) && check_ref_format(ref->name + 5)) ; /* trash */ - else if (fetch_all && - (!depth || prefixcmp(ref->name, "refs/tags/") )) { + else if (args.fetch_all && + (!args.depth || prefixcmp(ref->name, "refs/tags/") )) { *newtail = ref; ref->next = NULL; newtail = &ref->next; @@ -365,7 +361,7 @@ static void filter_refs(struct ref **refs, int nr_match, char **match) free(ref); } - if (!fetch_all) { + if (!args.fetch_all) { int i; for (i = 0; i < nr_match; i++) { ref = return_refs[i]; @@ -408,7 +404,7 @@ static int everything_local(struct ref **refs, int nr_match, char **match) } } - if (!depth) { + if (!args.depth) { for_each_ref(mark_complete, NULL); if (cutoff) mark_recent_complete_commits(cutoff); @@ -442,7 +438,7 @@ static int everything_local(struct ref **refs, int nr_match, char **match) o = lookup_object(remote); if (!o || !(o->flags & COMPLETE)) { retval = 0; - if (!verbose) + if (!args.verbose) continue; fprintf(stderr, "want %s (%s)\n", sha1_to_hex(remote), @@ -451,7 +447,7 @@ static int everything_local(struct ref **refs, int nr_match, char **match) } hashcpy(ref->new_sha1, local); - if (!verbose) + if (!args.verbose) continue; fprintf(stderr, "already have %s (%s)\n", sha1_to_hex(remote), @@ -502,14 +498,14 @@ static int get_pack(int xd[2], char **pack_lockfile) char keep_arg[256]; char hdr_arg[256]; const char **av; - int do_keep = keep_pack; + int do_keep = args.keep_pack; int keep_pipe[2]; side_pid = setup_sideband(fd, xd); av = argv; *hdr_arg = 0; - if (unpack_limit) { + if (!args.keep_pack && unpack_limit) { struct pack_header header; if (read_pack_header(fd[0], &header)) @@ -527,11 +523,11 @@ static int get_pack(int xd[2], char **pack_lockfile) die("fetch-pack: pipe setup failure: %s", strerror(errno)); *av++ = "index-pack"; *av++ = "--stdin"; - if (!quiet && !no_progress) + if (!args.quiet && !args.no_progress) *av++ = "-v"; - if (use_thin_pack) + if (args.use_thin_pack) *av++ = "--fix-thin"; - if (keep_pack > 1 || unpack_limit) { + if (args.lock_pack || unpack_limit) { int s = sprintf(keep_arg, "--keep=fetch-pack %d on ", getpid()); if (gethostname(keep_arg + s, sizeof(keep_arg) - s)) @@ -541,7 +537,7 @@ static int get_pack(int xd[2], char **pack_lockfile) } else { *av++ = "unpack-objects"; - if (quiet) + if (args.quiet) *av++ = "-q"; } if (*hdr_arg) @@ -599,17 +595,17 @@ static struct ref *do_fetch_pack(int fd[2], if (is_repository_shallow() && !server_supports("shallow")) die("Server does not support shallow clients"); if (server_supports("multi_ack")) { - if (verbose) + if (args.verbose) fprintf(stderr, "Server supports multi_ack\n"); multi_ack = 1; } if (server_supports("side-band-64k")) { - if (verbose) + if (args.verbose) fprintf(stderr, "Server supports side-band-64k\n"); use_sideband = 2; } else if (server_supports("side-band")) { - if (verbose) + if (args.verbose) fprintf(stderr, "Server supports side-band\n"); use_sideband = 1; } @@ -622,7 +618,7 @@ static struct ref *do_fetch_pack(int fd[2], goto all_done; } if (find_common(fd, sha1, ref) < 0) - if (keep_pack != 1) + if (!args.keep_pack) /* When cloning, it is not unusual to have * no common commit. */ @@ -674,22 +670,6 @@ static int fetch_pack_config(const char *var, const char *value) static struct lock_file lock; -void setup_fetch_pack(struct fetch_pack_args *args) -{ - uploadpack = args->uploadpack; - quiet = args->quiet; - keep_pack = args->keep_pack; - if (args->unpacklimit >= 0) - unpack_limit = args->unpacklimit; - if (args->keep_pack) - unpack_limit = 0; - use_thin_pack = args->use_thin_pack; - fetch_all = args->fetch_all; - verbose = args->verbose; - depth = args->depth; - no_progress = args->no_progress; -} - int cmd_fetch_pack(int argc, const char **argv, const char *prefix) { int i, ret, nr_heads; @@ -710,40 +690,40 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix) if (*arg == '-') { if (!prefixcmp(arg, "--upload-pack=")) { - uploadpack = arg + 14; + args.uploadpack = arg + 14; continue; } if (!prefixcmp(arg, "--exec=")) { - uploadpack = arg + 7; + args.uploadpack = arg + 7; continue; } if (!strcmp("--quiet", arg) || !strcmp("-q", arg)) { - quiet = 1; + args.quiet = 1; continue; } if (!strcmp("--keep", arg) || !strcmp("-k", arg)) { - keep_pack++; - unpack_limit = 0; + args.lock_pack = args.keep_pack; + args.keep_pack = 1; continue; } if (!strcmp("--thin", arg)) { - use_thin_pack = 1; + args.use_thin_pack = 1; continue; } if (!strcmp("--all", arg)) { - fetch_all = 1; + args.fetch_all = 1; continue; } if (!strcmp("-v", arg)) { - verbose = 1; + args.verbose = 1; continue; } if (!prefixcmp(arg, "--depth=")) { - depth = strtol(arg + 8, NULL, 0); + args.depth = strtol(arg + 8, NULL, 0); continue; } if (!strcmp("--no-progress", arg)) { - no_progress = 1; + args.no_progress = 1; continue; } usage(fetch_pack_usage); @@ -756,8 +736,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix) if (!dest) usage(fetch_pack_usage); - ref = fetch_pack(dest, nr_heads, heads, NULL); - + ref = fetch_pack(&args, dest, nr_heads, heads, NULL); ret = !ref; while (ref) { @@ -769,7 +748,8 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix) return ret; } -struct ref *fetch_pack(const char *dest, +struct ref *fetch_pack(struct fetch_pack_args *my_args, + const char *dest, int nr_heads, char **heads, char **pack_lockfile) @@ -780,13 +760,14 @@ struct ref *fetch_pack(const char *dest, struct ref *ref; struct stat st; - if (depth > 0) { + memcpy(&args, my_args, sizeof(args)); + if (args.depth > 0) { if (stat(git_path("shallow"), &st)) st.st_mtime = 0; } pid = git_connect(fd, (char *)dest, uploadpack, - verbose ? CONNECT_VERBOSE : 0); + args.verbose ? CONNECT_VERBOSE : 0); if (pid < 0) return NULL; if (heads && nr_heads) @@ -809,7 +790,7 @@ struct ref *fetch_pack(const char *dest, } } - if (!ret && depth > 0) { + if (!ret && args.depth > 0) { struct cache_time mtime; char *shallow = git_path("shallow"); int fd; diff --git a/fetch-pack.h b/fetch-pack.h index ad1307689d..a7888ea302 100644 --- a/fetch-pack.h +++ b/fetch-pack.h @@ -8,14 +8,17 @@ struct fetch_pack_args int depth; unsigned quiet:1, keep_pack:1, + lock_pack:1, use_thin_pack:1, fetch_all:1, verbose:1, no_progress:1; }; -void setup_fetch_pack(struct fetch_pack_args *args); - -struct ref *fetch_pack(const char *dest, int nr_heads, char **heads, char **pack_lockfile); +struct ref *fetch_pack(struct fetch_pack_args *args, + const char *dest, + int nr_heads, + char **heads, + char **pack_lockfile); #endif diff --git a/transport.c b/transport.c index d8458dc85a..85f5b1ed4c 100644 --- a/transport.c +++ b/transport.c @@ -314,21 +314,18 @@ static int fetch_refs_via_pack(struct transport *transport, struct fetch_pack_args args; int i; + memset(&args, 0, sizeof(args)); args.uploadpack = data->uploadpack; - args.quiet = 0; args.keep_pack = data->keep; + args.lock_pack = 1; args.unpacklimit = data->unpacklimit; args.use_thin_pack = data->thin; - args.fetch_all = 0; args.verbose = transport->verbose; args.depth = data->depth; - args.no_progress = 0; - - setup_fetch_pack(&args); for (i = 0; i < nr_heads; i++) origh[i] = heads[i] = xstrdup(to_fetch[i]->name); - refs = fetch_pack(dest, nr_heads, heads, &transport->pack_lockfile); + refs = fetch_pack(&args, dest, nr_heads, heads, &transport->pack_lockfile); for (i = 0; i < nr_heads; i++) free(origh[i]); From 50ab5fd3fc16fbe01170059977533fa2c7c4d448 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Wed, 19 Sep 2007 00:49:39 -0400 Subject: [PATCH 0088/1490] Ensure builtin-fetch honors {fetch,transfer}.unpackLimit The only way to configure the unpacking limit is currently through the .git/config (or ~/.gitconfig) mechanism as we have no existing command line option interface to control this threshold on a per invocation basis. This was intentional by design as the storage policy of the repository should be a repository-wide decision and should not be subject to variations made on individual command executions. Earlier builtin-fetch was bypassing the unpacking limit chosen by the user through the configuration file as it did not reread the configuration options through fetch_pack_config if we called the internal fetch_pack() API directly. We now ensure we always run the config file through fetch_pack_config at least once in this process, thereby setting our unpackLimit properly. Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- builtin-fetch-pack.c | 21 ++++++++++++++------- transport.c | 9 --------- transport.h | 3 --- 3 files changed, 14 insertions(+), 19 deletions(-) diff --git a/builtin-fetch-pack.c b/builtin-fetch-pack.c index 77eb181b5f..8f25d509a0 100644 --- a/builtin-fetch-pack.c +++ b/builtin-fetch-pack.c @@ -670,19 +670,25 @@ static int fetch_pack_config(const char *var, const char *value) static struct lock_file lock; +static void fetch_pack_setup(void) +{ + static int did_setup; + if (did_setup) + return; + git_config(fetch_pack_config); + if (0 <= transfer_unpack_limit) + unpack_limit = transfer_unpack_limit; + else if (0 <= fetch_unpack_limit) + unpack_limit = fetch_unpack_limit; + did_setup = 1; +} + int cmd_fetch_pack(int argc, const char **argv, const char *prefix) { int i, ret, nr_heads; struct ref *ref; char *dest = NULL, **heads; - git_config(fetch_pack_config); - - if (0 <= transfer_unpack_limit) - unpack_limit = transfer_unpack_limit; - else if (0 <= fetch_unpack_limit) - unpack_limit = fetch_unpack_limit; - nr_heads = 0; heads = NULL; for (i = 1; i < argc; i++) { @@ -760,6 +766,7 @@ struct ref *fetch_pack(struct fetch_pack_args *my_args, struct ref *ref; struct stat st; + fetch_pack_setup(); memcpy(&args, my_args, sizeof(args)); if (args.depth > 0) { if (stat(git_path("shallow"), &st)) diff --git a/transport.c b/transport.c index 85f5b1ed4c..a1d0a3c899 100644 --- a/transport.c +++ b/transport.c @@ -242,11 +242,7 @@ static int close_bundle(struct transport *transport) struct git_transport_data { unsigned thin : 1; unsigned keep : 1; - - int unpacklimit; - int depth; - const char *uploadpack; const char *receivepack; }; @@ -267,9 +263,6 @@ static int set_git_option(struct transport *connection, } else if (!strcmp(name, TRANS_OPT_KEEP)) { data->keep = !!value; return 0; - } else if (!strcmp(name, TRANS_OPT_UNPACKLIMIT)) { - data->unpacklimit = atoi(value); - return 0; } else if (!strcmp(name, TRANS_OPT_DEPTH)) { if (!value) data->depth = 0; @@ -318,7 +311,6 @@ static int fetch_refs_via_pack(struct transport *transport, args.uploadpack = data->uploadpack; args.keep_pack = data->keep; args.lock_pack = 1; - args.unpacklimit = data->unpacklimit; args.use_thin_pack = data->thin; args.verbose = transport->verbose; args.depth = data->depth; @@ -435,7 +427,6 @@ struct transport *transport_get(struct remote *remote, const char *url) data->receivepack = "git-receive-pack"; if (remote && remote->receivepack) data->receivepack = remote->receivepack; - data->unpacklimit = -1; } return ret; diff --git a/transport.h b/transport.h index 3e332ff53a..6e318e4e8c 100644 --- a/transport.h +++ b/transport.h @@ -47,9 +47,6 @@ struct transport *transport_get(struct remote *, const char *); /* Keep the pack that was transferred if not null */ #define TRANS_OPT_KEEP "keep" -/* Unpack the objects if fewer than this number of objects are fetched */ -#define TRANS_OPT_UNPACKLIMIT "unpacklimit" - /* Limit the depth of the fetch if not null */ #define TRANS_OPT_DEPTH "depth" From f4e95765b042f3e31a8902e78a5101768b33e445 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Wed, 19 Sep 2007 00:49:42 -0400 Subject: [PATCH 0089/1490] Fix memory leaks when disconnecting transport instances Most transport implementations tend to allocate a data buffer in the struct transport instance during transport_get() so we need to free that data buffer when we disconnect it. Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- transport.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/transport.c b/transport.c index a1d0a3c899..4f9cddc308 100644 --- a/transport.c +++ b/transport.c @@ -236,6 +236,7 @@ static int close_bundle(struct transport *transport) struct bundle_transport_data *data = transport->data; if (data->fd > 0) close(data->fd); + free(data); return 0; } @@ -372,6 +373,12 @@ static int git_transport_push(struct transport *transport, int refspec_nr, const return !!err; } +static int disconnect_git(struct transport *transport) +{ + free(transport->data); + return 0; +} + static int is_local(const char *url) { const char *colon = strchr(url, ':'); @@ -419,6 +426,7 @@ struct transport *transport_get(struct remote *remote, const char *url) ret->get_refs_list = get_refs_via_connect; ret->fetch = fetch_refs_via_pack; ret->push = git_transport_push; + ret->disconnect = disconnect_git; data->thin = 1; data->uploadpack = "git-upload-pack"; From f26a0012262106e0c7e92d8d07f00611112d3a8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Mon, 17 Sep 2007 20:06:42 -0400 Subject: [PATCH 0090/1490] Enable wt-status output to a given FILE pointer. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Still defaults to stdout, but you can now override wt_status.fp after calling wt_status_prepare(). Signed-off-by: Kristian Høgsberg Signed-off-by: Junio C Hamano --- color.c | 18 ++++++------ color.h | 4 +-- wt-status.c | 85 +++++++++++++++++++++++++++-------------------------- wt-status.h | 3 ++ 4 files changed, 58 insertions(+), 52 deletions(-) diff --git a/color.c b/color.c index 09d82eec3d..124ba331c7 100644 --- a/color.c +++ b/color.c @@ -135,39 +135,39 @@ int git_config_colorbool(const char *var, const char *value) return git_config_bool(var, value); } -static int color_vprintf(const char *color, const char *fmt, +static int color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args, const char *trail) { int r = 0; if (*color) - r += printf("%s", color); - r += vprintf(fmt, args); + r += fprintf(fp, "%s", color); + r += vfprintf(fp, fmt, args); if (*color) - r += printf("%s", COLOR_RESET); + r += fprintf(fp, "%s", COLOR_RESET); if (trail) - r += printf("%s", trail); + r += fprintf(fp, "%s", trail); return r; } -int color_printf(const char *color, const char *fmt, ...) +int color_fprintf(FILE *fp, const char *color, const char *fmt, ...) { va_list args; int r; va_start(args, fmt); - r = color_vprintf(color, fmt, args, NULL); + r = color_vfprintf(fp, color, fmt, args, NULL); va_end(args); return r; } -int color_printf_ln(const char *color, const char *fmt, ...) +int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...) { va_list args; int r; va_start(args, fmt); - r = color_vprintf(color, fmt, args, "\n"); + r = color_vfprintf(fp, color, fmt, args, "\n"); va_end(args); return r; } diff --git a/color.h b/color.h index 88bb8ff1bd..68098006ed 100644 --- a/color.h +++ b/color.h @@ -6,7 +6,7 @@ int git_config_colorbool(const char *var, const char *value); void color_parse(const char *var, const char *value, char *dst); -int color_printf(const char *color, const char *fmt, ...); -int color_printf_ln(const char *color, const char *fmt, ...); +int color_fprintf(FILE *fp, const char *color, const char *fmt, ...); +int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...); #endif /* COLOR_H */ diff --git a/wt-status.c b/wt-status.c index 10ce6eedc7..eeb16915c2 100644 --- a/wt-status.c +++ b/wt-status.c @@ -52,31 +52,33 @@ void wt_status_prepare(struct wt_status *s) head = resolve_ref("HEAD", sha1, 0, NULL); s->branch = head ? xstrdup(head) : NULL; s->reference = "HEAD"; + s->fp = stdout; } -static void wt_status_print_cached_header(const char *reference) +static void wt_status_print_cached_header(struct wt_status *s) { const char *c = color(WT_STATUS_HEADER); - color_printf_ln(c, "# Changes to be committed:"); - if (reference) { - color_printf_ln(c, "# (use \"git reset %s ...\" to unstage)", reference); + color_fprintf_ln(s->fp, c, "# Changes to be committed:"); + if (s->reference) { + color_fprintf_ln(s->fp, c, "# (use \"git reset %s ...\" to unstage)", s->reference); } else { - color_printf_ln(c, "# (use \"git rm --cached ...\" to unstage)"); + color_fprintf_ln(s->fp, c, "# (use \"git rm --cached ...\" to unstage)"); } - color_printf_ln(c, "#"); + color_fprintf_ln(s->fp, c, "#"); } -static void wt_status_print_header(const char *main, const char *sub) +static void wt_status_print_header(struct wt_status *s, + const char *main, const char *sub) { const char *c = color(WT_STATUS_HEADER); - color_printf_ln(c, "# %s:", main); - color_printf_ln(c, "# (%s)", sub); - color_printf_ln(c, "#"); + color_fprintf_ln(s->fp, c, "# %s:", main); + color_fprintf_ln(s->fp, c, "# (%s)", sub); + color_fprintf_ln(s->fp, c, "#"); } -static void wt_status_print_trailer(void) +static void wt_status_print_trailer(struct wt_status *s) { - color_printf_ln(color(WT_STATUS_HEADER), "#"); + color_fprintf_ln(s->fp, color(WT_STATUS_HEADER), "#"); } static const char *quote_crlf(const char *in, char *buf, size_t sz) @@ -108,7 +110,8 @@ static const char *quote_crlf(const char *in, char *buf, size_t sz) return ret; } -static void wt_status_print_filepair(int t, struct diff_filepair *p) +static void wt_status_print_filepair(struct wt_status *s, + int t, struct diff_filepair *p) { const char *c = color(t); const char *one, *two; @@ -117,36 +120,36 @@ static void wt_status_print_filepair(int t, struct diff_filepair *p) one = quote_crlf(p->one->path, onebuf, sizeof(onebuf)); two = quote_crlf(p->two->path, twobuf, sizeof(twobuf)); - color_printf(color(WT_STATUS_HEADER), "#\t"); + color_fprintf(s->fp, color(WT_STATUS_HEADER), "#\t"); switch (p->status) { case DIFF_STATUS_ADDED: - color_printf(c, "new file: %s", one); + color_fprintf(s->fp, c, "new file: %s", one); break; case DIFF_STATUS_COPIED: - color_printf(c, "copied: %s -> %s", one, two); + color_fprintf(s->fp, c, "copied: %s -> %s", one, two); break; case DIFF_STATUS_DELETED: - color_printf(c, "deleted: %s", one); + color_fprintf(s->fp, c, "deleted: %s", one); break; case DIFF_STATUS_MODIFIED: - color_printf(c, "modified: %s", one); + color_fprintf(s->fp, c, "modified: %s", one); break; case DIFF_STATUS_RENAMED: - color_printf(c, "renamed: %s -> %s", one, two); + color_fprintf(s->fp, c, "renamed: %s -> %s", one, two); break; case DIFF_STATUS_TYPE_CHANGED: - color_printf(c, "typechange: %s", one); + color_fprintf(s->fp, c, "typechange: %s", one); break; case DIFF_STATUS_UNKNOWN: - color_printf(c, "unknown: %s", one); + color_fprintf(s->fp, c, "unknown: %s", one); break; case DIFF_STATUS_UNMERGED: - color_printf(c, "unmerged: %s", one); + color_fprintf(s->fp, c, "unmerged: %s", one); break; default: die("bug: unhandled diff status %c", p->status); } - printf("\n"); + fprintf(s->fp, "\n"); } static void wt_status_print_updated_cb(struct diff_queue_struct *q, @@ -160,14 +163,14 @@ static void wt_status_print_updated_cb(struct diff_queue_struct *q, if (q->queue[i]->status == 'U') continue; if (!shown_header) { - wt_status_print_cached_header(s->reference); + wt_status_print_cached_header(s); s->commitable = 1; shown_header = 1; } - wt_status_print_filepair(WT_STATUS_UPDATED, q->queue[i]); + wt_status_print_filepair(s, WT_STATUS_UPDATED, q->queue[i]); } if (shown_header) - wt_status_print_trailer(); + wt_status_print_trailer(s); } static void wt_status_print_changed_cb(struct diff_queue_struct *q, @@ -184,12 +187,12 @@ static void wt_status_print_changed_cb(struct diff_queue_struct *q, msg = use_add_rm_msg; break; } - wt_status_print_header("Changed but not updated", msg); + wt_status_print_header(s, "Changed but not updated", msg); } for (i = 0; i < q->nr; i++) - wt_status_print_filepair(WT_STATUS_CHANGED, q->queue[i]); + wt_status_print_filepair(s, WT_STATUS_CHANGED, q->queue[i]); if (q->nr) - wt_status_print_trailer(); + wt_status_print_trailer(s); } static void wt_read_cache(struct wt_status *s) @@ -206,16 +209,16 @@ static void wt_status_print_initial(struct wt_status *s) wt_read_cache(s); if (active_nr) { s->commitable = 1; - wt_status_print_cached_header(NULL); + wt_status_print_cached_header(s); } for (i = 0; i < active_nr; i++) { - color_printf(color(WT_STATUS_HEADER), "#\t"); - color_printf_ln(color(WT_STATUS_UPDATED), "new file: %s", + color_fprintf(s->fp, color(WT_STATUS_HEADER), "#\t"); + color_fprintf_ln(s->fp, color(WT_STATUS_UPDATED), "new file: %s", quote_crlf(active_cache[i]->name, buf, sizeof(buf))); } if (active_nr) - wt_status_print_trailer(); + wt_status_print_trailer(s); } static void wt_status_print_updated(struct wt_status *s) @@ -282,12 +285,12 @@ static void wt_status_print_untracked(struct wt_status *s) } if (!shown_header) { s->workdir_untracked = 1; - wt_status_print_header("Untracked files", + wt_status_print_header(s, "Untracked files", use_add_to_include_msg); shown_header = 1; } - color_printf(color(WT_STATUS_HEADER), "#\t"); - color_printf_ln(color(WT_STATUS_UNTRACKED), "%.*s", + color_fprintf(s->fp, color(WT_STATUS_HEADER), "#\t"); + color_fprintf_ln(s->fp, color(WT_STATUS_UNTRACKED), "%.*s", ent->len, ent->name); } } @@ -317,14 +320,14 @@ void wt_status_print(struct wt_status *s) branch_name = ""; on_what = "Not currently on any branch."; } - color_printf_ln(color(WT_STATUS_HEADER), + color_fprintf_ln(s->fp, color(WT_STATUS_HEADER), "# %s%s", on_what, branch_name); } if (s->is_initial) { - color_printf_ln(color(WT_STATUS_HEADER), "#"); - color_printf_ln(color(WT_STATUS_HEADER), "# Initial commit"); - color_printf_ln(color(WT_STATUS_HEADER), "#"); + color_fprintf_ln(s->fp, color(WT_STATUS_HEADER), "#"); + color_fprintf_ln(s->fp, color(WT_STATUS_HEADER), "# Initial commit"); + color_fprintf_ln(s->fp, color(WT_STATUS_HEADER), "#"); wt_status_print_initial(s); } else { @@ -338,7 +341,7 @@ void wt_status_print(struct wt_status *s) wt_status_print_verbose(s); if (!s->commitable) { if (s->amend) - printf("# No changes\n"); + fprintf(s->fp, "# No changes\n"); else if (s->workdir_dirty) printf("no changes added to commit (use \"git add\" and/or \"git commit -a\")\n"); else if (s->workdir_untracked) diff --git a/wt-status.h b/wt-status.h index cfea4ae688..4f3a615c32 100644 --- a/wt-status.h +++ b/wt-status.h @@ -1,6 +1,8 @@ #ifndef STATUS_H #define STATUS_H +#include + enum color_wt_status { WT_STATUS_HEADER, WT_STATUS_UPDATED, @@ -19,6 +21,7 @@ struct wt_status { int commitable; int workdir_dirty; int workdir_untracked; + FILE *fp; }; int git_status_config(const char *var, const char *value); From 0f729f21348c43a1c80f48faed2e753b1c923e85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Mon, 17 Sep 2007 20:06:43 -0400 Subject: [PATCH 0091/1490] Enable wt-status to run against non-standard index file. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We still default to get_index_file(), but this can be overridden by setting wt_status.index_file after calling wt_status_prepare(). Signed-off-by: Kristian Høgsberg Signed-off-by: Junio C Hamano --- wt-status.c | 3 ++- wt-status.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/wt-status.c b/wt-status.c index eeb16915c2..03b5ec4488 100644 --- a/wt-status.c +++ b/wt-status.c @@ -53,6 +53,7 @@ void wt_status_prepare(struct wt_status *s) s->branch = head ? xstrdup(head) : NULL; s->reference = "HEAD"; s->fp = stdout; + s->index_file = get_index_file(); } static void wt_status_print_cached_header(struct wt_status *s) @@ -198,7 +199,7 @@ static void wt_status_print_changed_cb(struct diff_queue_struct *q, static void wt_read_cache(struct wt_status *s) { discard_cache(); - read_cache(); + read_cache_from(s->index_file); } static void wt_status_print_initial(struct wt_status *s) diff --git a/wt-status.h b/wt-status.h index 4f3a615c32..77449326db 100644 --- a/wt-status.h +++ b/wt-status.h @@ -21,6 +21,7 @@ struct wt_status { int commitable; int workdir_dirty; int workdir_untracked; + const char *index_file; FILE *fp; }; From ae0754ac9a24afa2693246222fc078fe9c133b3a Mon Sep 17 00:00:00 2001 From: Simon Sasburg Date: Wed, 19 Sep 2007 00:33:34 +0200 Subject: [PATCH 0092/1490] git-gui: Avoid using bold text in entire gui for some fonts Signed-off-by: Shawn O. Pearce --- git-gui.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git-gui.sh b/git-gui.sh index f789e91b66..28d7c21692 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -1648,7 +1648,7 @@ proc apply_config {} { set font [lindex $option 1] if {[catch { foreach {cn cv} $repo_config(gui.$name) { - font configure $font $cn $cv + font configure $font $cn $cv -weight normal } } err]} { error_popup "Invalid font specified in gui.$name:\n\n$err" From d4278b51e362e7a0f0e7922db47552f8c6726986 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Thu, 20 Sep 2007 13:03:43 -0400 Subject: [PATCH 0093/1490] git-gui: Fix missing i18n markup in push/fetch windows The console window titles should also be marked up with i18n strings so these can be properly localized. Signed-off-by: Shawn O. Pearce --- lib/transport.tcl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/transport.tcl b/lib/transport.tcl index 1c7baef173..3b05b8fc2c 100644 --- a/lib/transport.tcl +++ b/lib/transport.tcl @@ -3,7 +3,7 @@ proc fetch_from {remote} { set w [console::new \ - "fetch $remote" \ + [mc "fetch %s" $remote] \ [mc "Fetching new changes from %s" $remote]] set cmds [list] lappend cmds [list exec git fetch $remote] @@ -15,14 +15,14 @@ proc fetch_from {remote} { proc prune_from {remote} { set w [console::new \ - "remote prune $remote" \ + [mc "remote prune %s" $remote] \ [mc "Pruning tracking branches deleted from %s" $remote]] console::exec $w [list git remote prune $remote] } proc push_to {remote} { set w [console::new \ - "push $remote" \ + [mc "push %s" $remote] \ [mc "Pushing changes to %s" $remote]] set cmd [list git push] lappend cmd -v @@ -64,7 +64,7 @@ proc start_push_anywhere_action {w} { } set cons [console::new \ - "push $r_url" \ + [mc "push %s" $r_url] \ [mc "Pushing %s %s to %s" $cnt $unit $r_url]] console::exec $cons $cmd destroy $w From 2f7c9a7f310dae23989b4acd49514abc58334e5b Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Thu, 20 Sep 2007 21:25:34 -0400 Subject: [PATCH 0094/1490] git-gui: Support native Win32 Tcl/Tk under Cygwin Cygwin has been stuck on the 8.4.1 version of Tcl/Tk for quite some time, even though the main Tcl/Tk distribution is already shipping an 8.4.15. The problem is Tcl/Tk no longer supports Cygwin so apparently building the package for Cygwin is now a non-trivial task. Its actually quite easy to build the native Win32 version of Tcl/Tk by compiling with the -mno-cygwin flag passed to GCC but this means we lose all of the "fancy" Cygwin path translations that the Tcl library was doing for us. This is particularly an issue when we are trying to start git-gui through the git wrapper as the git wrapper is passing off a Cygwin path for $0 and Tcl cannot find the startup script or the library directory. We now use `cygpath -m -a` to convert the UNIX style paths to Windows style paths in our startup script if we are building on Cygwin. Doing so allows either the Cygwin-ized Tcl/Tk 8.4.1 that comes with Cygwin or a manually built 8.4.15 that is running the pure Win32 implementation to read our script. Signed-off-by: Shawn O. Pearce --- Makefile | 32 ++++++++++++++++++++------------ git-gui.sh | 5 +++-- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index 8c87d836d8..6236dd6ad3 100644 --- a/Makefile +++ b/Makefile @@ -92,27 +92,35 @@ gitexecdir_SQ = $(subst ','\'',$(gitexecdir)) SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH)) TCL_PATH_SQ = $(subst ','\'',$(TCL_PATH)) TCLTK_PATH_SQ = $(subst ','\'',$(TCLTK_PATH)) +TCLTK_PATH_SED = $(subst ','\'',$(subst \,\\,$(TCLTK_PATH))) gg_libdir ?= $(sharedir)/git-gui/lib libdir_SQ = $(subst ','\'',$(gg_libdir)) +libdir_SED = $(subst ','\'',$(subst \,\\,$(gg_libdir))) +exedir = $(dir $(gitexecdir))share/git-gui/lib -exedir = $(dir $(gitexecdir))share/git-gui/lib -exedir_SQ = $(subst ','\'',$(exedir)) +GITGUI_SCRIPT := $$0 +GITGUI_RELATIVE := + +ifeq ($(exedir),$(gg_libdir)) + GITGUI_RELATIVE := 1 +endif + +ifeq ($(uname_O),Cygwin) + GITGUI_SCRIPT := `cygpath --windows --absolute "$(GITGUI_SCRIPT)"` + ifeq ($(GITGUI_RELATIVE),) + gg_libdir := $(shell cygpath --windows --absolute "$(gg_libdir)") + endif +endif $(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh $(QUIET_GEN)rm -f $@ $@+ && \ - GITGUI_RELATIVE= && \ - if test '$(exedir_SQ)' = '$(libdir_SQ)'; then \ - if test "$(uname_O)" = Cygwin; \ - then GITGUI_RELATIVE= ; \ - else GITGUI_RELATIVE=1; \ - fi; \ - fi && \ sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \ - -e 's|^ exec wish "$$0"| exec $(subst |,'\|',$(TCLTK_PATH_SQ)) "$$0"|' \ + -e '1,30s|^ argv0=$$0| argv0=$(GITGUI_SCRIPT)|' \ + -e '1,30s|^ exec wish | exec '\''$(TCLTK_PATH_SED)'\'' |' \ -e 's/@@GITGUI_VERSION@@/$(GITGUI_VERSION)/g' \ - -e 's|@@GITGUI_RELATIVE@@|'$$GITGUI_RELATIVE'|' \ - -e $$GITGUI_RELATIVE's|@@GITGUI_LIBDIR@@|$(libdir_SQ)|' \ + -e 's|@@GITGUI_RELATIVE@@|$(GITGUI_RELATIVE)|' \ + -e '$(GITGUI_RELATIVE)s|@@GITGUI_LIBDIR@@|$(libdir_SED)|' \ $@.sh >$@+ && \ chmod +x $@+ && \ mv $@+ $@ diff --git a/git-gui.sh b/git-gui.sh index db1507cdec..5a465e1c7d 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -6,7 +6,8 @@ echo 'git-gui version @@GITGUI_VERSION@@'; \ exit; \ fi; \ - exec wish "$0" -- "$@" + argv0=$0; \ + exec wish "$argv0" -- "$@" set appvers {@@GITGUI_VERSION@@} set copyright { @@ -740,7 +741,7 @@ if {[catch { exit 1 } if {![file isdirectory $_gitdir] && [is_Cygwin]} { - catch {set _gitdir [exec cygpath --unix $_gitdir]} + catch {set _gitdir [exec cygpath --windows $_gitdir]} } if {![file isdirectory $_gitdir]} { catch {wm withdraw .} From 183a1d1496921e16d316ac523146385af39fcdb0 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 21 Sep 2007 10:58:02 -0400 Subject: [PATCH 0095/1490] git-gui: Display message box when we cannot find git in $PATH If we cannot find the git executable in the user's $PATH then we cannot function correctly. Because we need that to get the version so we can load our library correctly we cannot rely on the library function "error_popup" here, as this is all running before the library path has been configured, so error_popup is not available to us. Signed-off-by: Shawn O. Pearce --- git-gui.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/git-gui.sh b/git-gui.sh index 28d7c21692..10710e26c6 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -498,7 +498,11 @@ proc rmsel_tag {text} { set _git [_which git] if {$_git eq {}} { catch {wm withdraw .} - error_popup "Cannot find git in PATH." + tk_messageBox \ + -icon error \ + -type ok \ + -title [mc "git-gui: fatal error"] \ + -message [mc "Cannot find git in PATH."] exit 1 } From 299077fb40eac1e128b7bc09d5d992960e6f11c2 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 21 Sep 2007 11:08:50 -0400 Subject: [PATCH 0096/1490] git-gui: Handle starting on mapped shares under Cygwin I really cannot explain Cygwin's behavior here but if we start git-gui through Cygwin on a local drive it appears that Cygwin is leaving $env(PATH) in Unix style, even if it started a native (non-Cygwin) Tcl/Tk process to run git-gui. Yet starting that same git-gui and Tcl/Tk combination through Cygwin on a network share causes it to automatically convert $env(PATH) into Windows style, which broke our internal "which" implementation. Signed-off-by: Shawn O. Pearce --- git-gui.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git-gui.sh b/git-gui.sh index 10710e26c6..62e1652276 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -305,7 +305,7 @@ proc _which {what} { global env _search_exe _search_path if {$_search_path eq {}} { - if {[is_Cygwin]} { + if {[is_Cygwin] && [regexp {^(/|\.:)} $env(PATH)]} { set _search_path [split [exec cygpath \ --windows \ --path \ From 2fe167b67a479b19e52b974f9518436565e6793b Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 21 Sep 2007 11:44:23 -0400 Subject: [PATCH 0097/1490] git-gui: Ensure .git/info/exclude is honored in Cygwin workdirs If we are using Cygwin and the git repository is actually a workdir (by way of git-new-workdir) but this Tcl process is a native Tcl/Tk and not the Cygwin Tcl/Tk then we are unable to traverse the .git/info path as it is a Cygwin symlink and not a standard Windows directory. So we actually need to start a Cygwin process that can do the path translation for us and let it test for .git/info/exclude so we know if we can include that file in our git-ls-files or not. Signed-off-by: Shawn O. Pearce --- git-gui.sh | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/git-gui.sh b/git-gui.sh index 62e1652276..c8375029dd 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -907,6 +907,35 @@ proc rescan {after {honor_trustmtime 1}} { } } +if {[is_Cygwin]} { + set is_git_info_link {} + set is_git_info_exclude {} + proc have_info_exclude {} { + global is_git_info_link is_git_info_exclude + + if {$is_git_info_link eq {}} { + set is_git_info_link [file isfile [gitdir info.lnk]] + } + + if {$is_git_info_link} { + if {$is_git_info_exclude eq {}} { + if {[catch {exec test -f [gitdir info exclude]}]} { + set is_git_info_exclude 0 + } else { + set is_git_info_exclude 1 + } + } + return $is_git_info_exclude + } else { + return [file readable [gitdir info exclude]] + } + } +} else { + proc have_info_exclude {} { + return [file readable [gitdir info exclude]] + } +} + proc rescan_stage2 {fd after} { global rescan_active buf_rdi buf_rdf buf_rlo @@ -917,9 +946,8 @@ proc rescan_stage2 {fd after} { } set ls_others [list --exclude-per-directory=.gitignore] - set info_exclude [gitdir info exclude] - if {[file readable $info_exclude]} { - lappend ls_others "--exclude-from=$info_exclude" + if {[have_info_exclude]} { + lappend ls_others "--exclude-from=[gitdir info exclude]" } set user_exclude [get_config core.excludesfile] if {$user_exclude ne {} && [file readable $user_exclude]} { From 687c8765ec996225a01cadc7d91354ae3cfbdf8a Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sat, 22 Sep 2007 12:49:33 +1000 Subject: [PATCH 0098/1490] gitk: Simplify highlighting interface and combine with Find function This effectively coaelesces the highlighting function and the search function. Instead of separate highlight and find controls, there is now one set of interface elements that controls both. The main selector is a drop-down menu that controls whether commits are highlighted and searched for on the basis of text in the commit (i.e. the commit object), files affected by the commit or strings added/removed by the commit. The functions to highlight by membership of a view or by ancestor/ descendent relation to the selected commit are gone, as is the move to next/previous highlighted commit (shift-up/down) function. Signed-off-by: Paul Mackerras --- gitk | 430 +++++++++++++++++++++++++++++++---------------------------- 1 file changed, 225 insertions(+), 205 deletions(-) diff --git a/gitk b/gitk index d5db836528..a5d0d66e6c 100755 --- a/gitk +++ b/gitk @@ -706,62 +706,43 @@ proc makewindow {} { -state disabled -width 26 pack .tf.bar.rightbut -side left -fill y - button .tf.bar.findbut -text "Find" -command dofind -font $uifont - pack .tf.bar.findbut -side left - set findstring {} - set fstring .tf.bar.findstring - lappend entries $fstring - entry $fstring -width 30 -font $textfont -textvariable findstring - trace add variable findstring write find_change - pack $fstring -side left -expand 1 -fill x -in .tf.bar - set findtype Exact - set findtypemenu [tk_optionMenu .tf.bar.findtype \ - findtype Exact IgnCase Regexp] - trace add variable findtype write find_change - .tf.bar.findtype configure -font $uifont - .tf.bar.findtype.menu configure -font $uifont - set findloc "All fields" - tk_optionMenu .tf.bar.findloc findloc "All fields" Headline \ - Comments Author Committer - trace add variable findloc write find_change - .tf.bar.findloc configure -font $uifont - .tf.bar.findloc.menu configure -font $uifont - pack .tf.bar.findloc -side right - pack .tf.bar.findtype -side right - # build up the bottom bar of upper window - label .tf.lbar.flabel -text "Highlight: Commits " \ - -font $uifont - pack .tf.lbar.flabel -side left -fill y - set gdttype "touching paths:" - set gm [tk_optionMenu .tf.lbar.gdttype gdttype "touching paths:" \ - "adding/removing string:"] - trace add variable gdttype write hfiles_change + label .tf.lbar.flabel -text "Find " -font $uifont + button .tf.lbar.fnext -text "next" -command dofind -font $uifont + button .tf.lbar.fprev -text "prev" -command {dofind 1} -font $uifont + label .tf.lbar.flab2 -text " commit " -font $uifont + pack .tf.lbar.flabel .tf.lbar.fnext .tf.lbar.fprev .tf.lbar.flab2 \ + -side left -fill y + set gdttype "containing:" + set gm [tk_optionMenu .tf.lbar.gdttype gdttype \ + "containing:" \ + "touching paths:" \ + "adding/removing string:"] + trace add variable gdttype write gdttype_change $gm conf -font $uifont .tf.lbar.gdttype conf -font $uifont pack .tf.lbar.gdttype -side left -fill y - entry .tf.lbar.fent -width 25 -font $textfont \ - -textvariable highlight_files - trace add variable highlight_files write hfiles_change - lappend entries .tf.lbar.fent - pack .tf.lbar.fent -side left -fill x -expand 1 - label .tf.lbar.vlabel -text " OR in view" -font $uifont - pack .tf.lbar.vlabel -side left -fill y - global viewhlmenu selectedhlview - set viewhlmenu [tk_optionMenu .tf.lbar.vhl selectedhlview None] - $viewhlmenu entryconf None -command delvhighlight - $viewhlmenu conf -font $uifont - .tf.lbar.vhl conf -font $uifont - pack .tf.lbar.vhl -side left -fill y - label .tf.lbar.rlabel -text " OR " -font $uifont - pack .tf.lbar.rlabel -side left -fill y - global highlight_related - set m [tk_optionMenu .tf.lbar.relm highlight_related None \ - "Descendent" "Not descendent" "Ancestor" "Not ancestor"] - $m conf -font $uifont - .tf.lbar.relm conf -font $uifont - trace add variable highlight_related write vrel_change - pack .tf.lbar.relm -side left -fill y + + set findstring {} + set fstring .tf.lbar.findstring + lappend entries $fstring + entry $fstring -width 30 -font $textfont -textvariable findstring + trace add variable findstring write find_change + set findtype Exact + set findtypemenu [tk_optionMenu .tf.lbar.findtype \ + findtype Exact IgnCase Regexp] + trace add variable findtype write findcom_change + .tf.lbar.findtype configure -font $uifont + .tf.lbar.findtype.menu configure -font $uifont + set findloc "All fields" + tk_optionMenu .tf.lbar.findloc findloc "All fields" Headline \ + Comments Author Committer + trace add variable findloc write find_change + .tf.lbar.findloc configure -font $uifont + .tf.lbar.findloc.menu configure -font $uifont + pack .tf.lbar.findloc -side right + pack .tf.lbar.findtype -side right + pack $fstring -side left -expand 1 -fill x # Finish putting the upper half of the viewer together pack .tf.lbar -in .tf -side bottom -fill x @@ -914,8 +895,6 @@ proc makewindow {} { bindkey sellastline bind . "selnextline -1" bind . "selnextline 1" - bind . "next_highlight -1" - bind . "next_highlight 1" bindkey "goforw" bindkey "goback" bind . "selnextpage -1" @@ -1852,10 +1831,10 @@ proc doviewmenu {m first cmd op argv} { } proc allviewmenus {n op args} { - global viewhlmenu + # global viewhlmenu doviewmenu .bar.view 5 [list showview $n] $op $args - doviewmenu $viewhlmenu 1 [list addvhighlight $n] $op $args + # doviewmenu $viewhlmenu 1 [list addvhighlight $n] $op $args } proc newviewok {top n} { @@ -1898,8 +1877,8 @@ proc newviewok {top n} { set viewname($n) $newviewname($n) doviewmenu .bar.view 5 [list showview $n] \ entryconf [list -label $viewname($n)] - doviewmenu $viewhlmenu 1 [list addvhighlight $n] \ - entryconf [list -label $viewname($n) -value $viewname($n)] + # doviewmenu $viewhlmenu 1 [list addvhighlight $n] \ + # entryconf [list -label $viewname($n) -value $viewname($n)] } if {$files ne $viewfiles($n) || $newargs ne $viewargs($n)} { set viewfiles($n) $files @@ -1931,8 +1910,8 @@ proc addviewmenu {n} { .bar.view add radiobutton -label $viewname($n) \ -command [list showview $n] -variable selectedview -value $n - $viewhlmenu add radiobutton -label $viewname($n) \ - -command [list addvhighlight $n] -variable selectedhlview + #$viewhlmenu add radiobutton -label $viewname($n) \ + # -command [list addvhighlight $n] -variable selectedhlview } proc flatten {var} { @@ -2208,9 +2187,9 @@ proc askvhighlight {row id} { } } -proc hfiles_change {name ix op} { +proc hfiles_change {} { global highlight_files filehighlight fhighlights fh_serial - global mainfont highlight_paths + global mainfont highlight_paths gdttype if {[info exists filehighlight]} { # delete previous highlights @@ -2228,6 +2207,66 @@ proc hfiles_change {name ix op} { } } +proc gdttype_change {name ix op} { + global gdttype highlight_files findstring findpattern + + if {$findstring ne {}} { + if {$gdttype eq "containing:"} { + if {$highlight_files ne {}} { + set highlight_files {} + hfiles_change + } + findcom_change + } else { + if {$findpattern ne {}} { + set findpattern {} + findcom_change + } + set highlight_files $findstring + hfiles_change + } + drawvisible + } + # enable/disable findtype/findloc menus too +} + +proc find_change {name ix op} { + global gdttype findstring highlight_files + + if {$gdttype eq "containing:"} { + findcom_change + } else { + if {$highlight_files ne $findstring} { + set highlight_files $findstring + hfiles_change + } + } + drawvisible +} + +proc findcom_change {} { + global nhighlights mainfont boldnamerows + global findpattern findtype findstring gdttype + + # delete previous highlights, if any + foreach row $boldnamerows { + bolden_name $row $mainfont + } + set boldnamerows {} + catch {unset nhighlights} + unbolden + unmarkmatches + if {$gdttype ne "containing:" || $findstring eq {}} { + set findpattern {} + } elseif {$findtype eq "Regexp"} { + set findpattern $findstring + } else { + set e [string map {"*" "\\*" "?" "\\?" "\[" "\\\[" "\\" "\\\\"} \ + $findstring] + set findpattern "*$e*" + } +} + proc makepatterns {l} { set ret {} foreach e $l { @@ -2250,8 +2289,11 @@ proc do_file_hl {serial} { set highlight_paths [makepatterns $paths] highlight_filelist set gdtargs [concat -- $paths] - } else { + } elseif {$gdttype eq "adding/removing string:"} { set gdtargs [list "-S$highlight_files"] + } else { + # must be "containing:", i.e. we're searching commit info + return } set cmd [concat | git diff-tree -r -s --stdin $gdtargs] set filehighlight [open $cmd r+] @@ -2282,7 +2324,7 @@ proc askfilehighlight {row id} { proc readfhighlight {} { global filehighlight fhighlights commitrow curview mainfont iddrawn - global fhl_list + global fhl_list find_dirn if {![info exists filehighlight]} { return 0 @@ -2314,35 +2356,21 @@ proc readfhighlight {} { unset filehighlight return 0 } - next_hlcont + if {[info exists find_dirn]} { + if {$find_dirn > 0} { + run findmore + } else { + run findmorerev + } + } return 1 } -proc find_change {name ix op} { - global nhighlights mainfont boldnamerows - global findstring findpattern findtype - - # delete previous highlights, if any - foreach row $boldnamerows { - bolden_name $row $mainfont - } - set boldnamerows {} - catch {unset nhighlights} - unbolden - unmarkmatches - if {$findtype ne "Regexp"} { - set e [string map {"*" "\\*" "?" "\\?" "\[" "\\\[" "\\" "\\\\"} \ - $findstring] - set findpattern "*$e*" - } - drawvisible -} - proc doesmatch {f} { - global findtype findstring findpattern + global findtype findpattern if {$findtype eq "Regexp"} { - return [regexp $findstring $f] + return [regexp $findpattern $f] } elseif {$findtype eq "IgnCase"} { return [string match -nocase $findpattern $f] } else { @@ -2535,81 +2563,6 @@ proc askrelhighlight {row id} { set rhighlights($row) $isbold } -proc next_hlcont {} { - global fhl_row fhl_dirn displayorder numcommits - global vhighlights fhighlights nhighlights rhighlights - global hlview filehighlight findstring highlight_related - - if {![info exists fhl_dirn] || $fhl_dirn == 0} return - set row $fhl_row - while {1} { - if {$row < 0 || $row >= $numcommits} { - bell - set fhl_dirn 0 - return - } - set id [lindex $displayorder $row] - if {[info exists hlview]} { - if {![info exists vhighlights($row)]} { - askvhighlight $row $id - } - if {$vhighlights($row) > 0} break - } - if {$findstring ne {}} { - if {![info exists nhighlights($row)]} { - askfindhighlight $row $id - } - if {$nhighlights($row) > 0} break - } - if {$highlight_related ne "None"} { - if {![info exists rhighlights($row)]} { - askrelhighlight $row $id - } - if {$rhighlights($row) > 0} break - } - if {[info exists filehighlight]} { - if {![info exists fhighlights($row)]} { - # ask for a few more while we're at it... - set r $row - for {set n 0} {$n < 100} {incr n} { - if {![info exists fhighlights($r)]} { - askfilehighlight $r [lindex $displayorder $r] - } - incr r $fhl_dirn - if {$r < 0 || $r >= $numcommits} break - } - flushhighlights - } - if {$fhighlights($row) < 0} { - set fhl_row $row - return - } - if {$fhighlights($row) > 0} break - } - incr row $fhl_dirn - } - set fhl_dirn 0 - selectline $row 1 -} - -proc next_highlight {dirn} { - global selectedline fhl_row fhl_dirn - global hlview filehighlight findstring highlight_related - - if {![info exists selectedline]} return - if {!([info exists hlview] || $findstring ne {} || - $highlight_related ne "None" || [info exists filehighlight])} return - set fhl_row [expr {$selectedline + $dirn}] - set fhl_dirn $dirn - next_hlcont -} - -proc cancel_next_highlight {} { - global fhl_dirn - - set fhl_dirn 0 -} - # Graph layout functions proc shortids {ids} { @@ -3669,7 +3622,7 @@ proc drawcmitrow {row} { global displayorder rowidlist nrows_drawn global iddrawn markingmatches global commitinfo parentlist numcommits - global filehighlight fhighlights findstring nhighlights + global filehighlight fhighlights findpattern nhighlights global hlview vhighlights global highlight_related rhighlights @@ -3682,7 +3635,7 @@ proc drawcmitrow {row} { if {[info exists filehighlight] && ![info exists fhighlights($row)]} { askfilehighlight $row $id } - if {$findstring ne {} && ![info exists nhighlights($row)]} { + if {$findpattern ne {} && ![info exists nhighlights($row)]} { askfindhighlight $row $id } if {$highlight_related ne "None" && ![info exists rhighlights($row)]} { @@ -4190,9 +4143,9 @@ proc findmatches {f} { proc dofind {{rev 0}} { global findstring findstartline findcurline selectedline numcommits + global gdttype filehighlight fh_serial find_dirn unmarkmatches - cancel_next_highlight focus . if {$findstring eq {} || $numcommits == 0} return if {![info exists selectedline]} { @@ -4202,19 +4155,24 @@ proc dofind {{rev 0}} { } set findcurline $findstartline nowbusy finding + if {$gdttype ne "containing:" && ![info exists filehighlight]} { + after cancel do_file_hl $fh_serial + do_file_hl $fh_serial + } if {!$rev} { + set find_dirn 1 run findmore } else { - if {$findcurline == 0} { - set findcurline $numcommits - } - incr findcurline -1 + set find_dirn -1 run findmorerev } } proc findnext {restart} { - global findcurline + global findcurline find_dirn + + if {[info exists find_dirn]} return + set find_dirn 1 if {![info exists findcurline]} { if {$restart} { dofind @@ -4228,7 +4186,10 @@ proc findnext {restart} { } proc findprev {} { - global findcurline + global findcurline find_dirn + + if {[info exists find_dirn]} return + set find_dirn -1 if {![info exists findcurline]} { dofind 1 } else { @@ -4238,8 +4199,9 @@ proc findprev {} { } proc findmore {} { - global commitdata commitinfo numcommits findstring findpattern findloc + global commitdata commitinfo numcommits findpattern findloc global findstartline findcurline displayorder + global find_dirn gdttype fhighlights set fldtypes {Headline Author Date Committer CDate Comments} set l [expr {$findcurline + 1}] @@ -4254,28 +4216,56 @@ proc findmore {} { if {$lim - $l > 500} { set lim [expr {$l + 500}] } - set last 0 - for {} {$l < $lim} {incr l} { - set id [lindex $displayorder $l] - # shouldn't happen unless git log doesn't give all the commits... - if {![info exists commitdata($id)]} continue - if {![doesmatch $commitdata($id)]} continue - if {![info exists commitinfo($id)]} { - getcommit $id + set found 0 + set domore 1 + if {$gdttype eq "containing:"} { + for {} {$l < $lim} {incr l} { + set id [lindex $displayorder $l] + # shouldn't happen unless git log doesn't give all the commits... + if {![info exists commitdata($id)]} continue + if {![doesmatch $commitdata($id)]} continue + if {![info exists commitinfo($id)]} { + getcommit $id + } + set info $commitinfo($id) + foreach f $info ty $fldtypes { + if {($findloc eq "All fields" || $findloc eq $ty) && + [doesmatch $f]} { + set found 1 + break + } + } + if {$found} break } - set info $commitinfo($id) - foreach f $info ty $fldtypes { - if {($findloc eq "All fields" || $findloc eq $ty) && - [doesmatch $f]} { - findselectline $l - notbusy finding - return 0 + } else { + for {} {$l < $lim} {incr l} { + set id [lindex $displayorder $l] + if {![info exists fhighlights($l)]} { + askfilehighlight $l $id + if {$domore} { + set domore 0 + set findcurline [expr {$l - 1}] + } + } elseif {$fhighlights($l)} { + set found $domore + break } } } + if {$found} { + unset find_dirn + findselectline $l + notbusy finding + return 0 + } + if {!$domore} { + flushhighlights + return 0 + } if {$l == $findstartline + 1} { bell unset findcurline + unset find_dirn notbusy finding return 0 } @@ -4284,8 +4274,9 @@ proc findmore {} { } proc findmorerev {} { - global commitdata commitinfo numcommits findstring findpattern findloc + global commitdata commitinfo numcommits findpattern findloc global findstartline findcurline displayorder + global find_dirn gdttype fhighlights set fldtypes {Headline Author Date Committer CDate Comments} set l $findcurline @@ -4301,27 +4292,55 @@ proc findmorerev {} { if {$l - $lim > 500} { set lim [expr {$l - 500}] } - set last 0 - for {} {$l > $lim} {incr l -1} { - set id [lindex $displayorder $l] - if {![info exists commitdata($id)]} continue - if {![doesmatch $commitdata($id)]} continue - if {![info exists commitinfo($id)]} { - getcommit $id + set found 0 + set domore 1 + if {$gdttype eq "containing:"} { + for {} {$l > $lim} {incr l -1} { + set id [lindex $displayorder $l] + if {![info exists commitdata($id)]} continue + if {![doesmatch $commitdata($id)]} continue + if {![info exists commitinfo($id)]} { + getcommit $id + } + set info $commitinfo($id) + foreach f $info ty $fldtypes { + if {($findloc eq "All fields" || $findloc eq $ty) && + [doesmatch $f]} { + set found 1 + break + } + } + if {$found} break } - set info $commitinfo($id) - foreach f $info ty $fldtypes { - if {($findloc eq "All fields" || $findloc eq $ty) && - [doesmatch $f]} { - findselectline $l - notbusy finding - return 0 + } else { + for {} {$l > $lim} {incr l -1} { + set id [lindex $displayorder $l] + if {![info exists fhighlights($l)]} { + askfilehighlight $l $id + if {$domore} { + set domore 0 + set findcurline [expr {$l + 1}] + } + } elseif {$fhighlights($l)} { + set found $domore + break } } } + if {$found} { + unset find_dirn + findselectline $l + notbusy finding + return 0 + } + if {!$domore} { + flushhighlights + return 0 + } if {$l == -1} { bell unset findcurline + unset find_dirn notbusy finding return 0 } @@ -4330,7 +4349,7 @@ proc findmorerev {} { } proc findselectline {l} { - global findloc commentend ctext findcurline markingmatches + global findloc commentend ctext findcurline markingmatches gdttype set markingmatches 1 set findcurline $l @@ -4599,7 +4618,6 @@ proc selectline {l isnew} { catch {unset pending_select} $canv delete hover normalline - cancel_next_highlight unsel_reflist if {$l < 0 || $l >= $numcommits} return set y [expr {$canvy0 + $l * $linespc}] @@ -4781,7 +4799,6 @@ proc unselectline {} { catch {unset currentid} allcanvs delete secsel rhighlight_none - cancel_next_highlight } proc reselectline {} { @@ -8223,6 +8240,7 @@ set historyindex 0 set fh_serial 0 set nhl_names {} set highlight_paths {} +set findpattern {} set searchdirn -forwards set boldrows {} set boldnamerows {} @@ -8236,6 +8254,8 @@ set nextviewnum 1 set curview 0 set selectedview 0 set selectedhlview None +set highlight_related None +set highlight_files {} set viewfiles(0) {} set viewperm(0) 0 set viewargs(0) {} From a4bee597134aee9883adba1e79be926a92f80367 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 21 Sep 2007 03:41:51 -0400 Subject: [PATCH 0099/1490] git-gui: Refactor some UI init to occur earlier I'm starting to setup a main window that the user can use to locate an existing repository, clone an existing repository, or create a new repository from scratch. To help do that I want most of our common UI support already defined before we start to look for the Git repository, this way if it was not found we can open a window to help the user locate it. Signed-off-by: Shawn O. Pearce --- git-gui.sh | 190 ++++++++++++++++++++++++++--------------------------- 1 file changed, 95 insertions(+), 95 deletions(-) diff --git a/git-gui.sh b/git-gui.sh index e19fb688b2..3ddfcd50eb 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -521,6 +521,99 @@ proc rmsel_tag {text} { return $text } +set root_exists 0 +bind . { + bind . {} + set root_exists 1 +} + +###################################################################### +## +## config defaults + +set cursor_ptr arrow +font create font_diff -family Courier -size 10 +font create font_ui +catch { + label .dummy + eval font configure font_ui [font actual [.dummy cget -font]] + destroy .dummy +} + +font create font_uiitalic +font create font_uibold +font create font_diffbold +font create font_diffitalic + +foreach class {Button Checkbutton Entry Label + Labelframe Listbox Menu Message + Radiobutton Spinbox Text} { + option add *$class.font font_ui +} +unset class + +if {[is_Windows] || [is_MacOSX]} { + option add *Menu.tearOff 0 +} + +if {[is_MacOSX]} { + set M1B M1 + set M1T Cmd +} else { + set M1B Control + set M1T Ctrl +} + +proc bind_button3 {w cmd} { + bind $w $cmd + if {[is_MacOSX]} { + # Mac OS X sends Button-2 on right click through three-button mouse, + # or through trackpad right-clicking (two-finger touch + click). + bind $w $cmd + bind $w $cmd + } +} + +proc apply_config {} { + global repo_config font_descs + + foreach option $font_descs { + set name [lindex $option 0] + set font [lindex $option 1] + if {[catch { + foreach {cn cv} $repo_config(gui.$name) { + font configure $font $cn $cv -weight normal + } + } err]} { + error_popup [strcat [mc "Invalid font specified in %s:" "gui.$name"] "\n\n$err"] + } + foreach {cn cv} [font configure $font] { + font configure ${font}bold $cn $cv + font configure ${font}italic $cn $cv + } + font configure ${font}bold -weight bold + font configure ${font}italic -slant italic + } +} + +set default_config(merge.diffstat) true +set default_config(merge.summary) false +set default_config(merge.verbosity) 2 +set default_config(user.name) {} +set default_config(user.email) {} + +set default_config(gui.matchtrackingbranch) false +set default_config(gui.pruneduringfetch) false +set default_config(gui.trustmtime) false +set default_config(gui.diffcontext) 5 +set default_config(gui.newbranchtemplate) {} +set default_config(gui.fontui) [font configure font_ui] +set default_config(gui.fontdiff) [font configure font_diff] +set font_descs { + {fontui font_ui {mc "Main Font"}} + {fontdiff font_diff {mc "Diff/Console Font"}} +} + ###################################################################### ## ## find git @@ -1448,16 +1541,6 @@ unset i ## ## util -proc bind_button3 {w cmd} { - bind $w $cmd - if {[is_MacOSX]} { - # Mac OS X sends Button-2 on right click through three-button mouse, - # or through trackpad right-clicking (two-finger touch + click). - bind $w $cmd - bind $w $cmd - } -} - proc scrollbar2many {list mode args} { foreach w $list {eval $w $mode $args} } @@ -1657,89 +1740,12 @@ proc add_range_to_selection {w x y} { $w tag add in_sel $begin.0 [expr {$end + 1}].0 } -###################################################################### -## -## config defaults - -set cursor_ptr arrow -font create font_diff -family Courier -size 10 -font create font_ui -catch { - label .dummy - eval font configure font_ui [font actual [.dummy cget -font]] - destroy .dummy -} - -font create font_uiitalic -font create font_uibold -font create font_diffbold -font create font_diffitalic - -foreach class {Button Checkbutton Entry Label - Labelframe Listbox Menu Message - Radiobutton Spinbox Text} { - option add *$class.font font_ui -} -unset class - -if {[is_Windows] || [is_MacOSX]} { - option add *Menu.tearOff 0 -} - -if {[is_MacOSX]} { - set M1B M1 - set M1T Cmd -} else { - set M1B Control - set M1T Ctrl -} - -proc apply_config {} { - global repo_config font_descs - - foreach option $font_descs { - set name [lindex $option 0] - set font [lindex $option 1] - if {[catch { - foreach {cn cv} $repo_config(gui.$name) { - font configure $font $cn $cv -weight normal - } - } err]} { - error_popup [strcat [mc "Invalid font specified in %s:" "gui.$name"] "\n\n$err"] - } - foreach {cn cv} [font configure $font] { - font configure ${font}bold $cn $cv - font configure ${font}italic $cn $cv - } - font configure ${font}bold -weight bold - font configure ${font}italic -slant italic - } -} - -set default_config(merge.diffstat) true -set default_config(merge.summary) false -set default_config(merge.verbosity) 2 -set default_config(user.name) {} -set default_config(user.email) {} - -set default_config(gui.matchtrackingbranch) false -set default_config(gui.pruneduringfetch) false -set default_config(gui.trustmtime) false -set default_config(gui.diffcontext) 5 -set default_config(gui.newbranchtemplate) {} -set default_config(gui.fontui) [font configure font_ui] -set default_config(gui.fontdiff) [font configure font_diff] -set font_descs { - {fontui font_ui {mc "Main Font"}} - {fontdiff font_diff {mc "Diff/Console Font"}} -} -load_config 0 -apply_config - ###################################################################### ## ## ui construction +load_config 0 +apply_config set ui_comm {} # -- Menu Bar @@ -2039,12 +2045,6 @@ if {$browser ne {}} { } unset browser doc_path doc_url -set root_exists 0 -bind . { - bind . {} - set root_exists 1 -} - # -- Standard bindings # wm protocol . WM_DELETE_WINDOW do_quit From ab08b3630414dfb867825c4a5828438e1c69199d Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Sat, 22 Sep 2007 03:47:43 -0400 Subject: [PATCH 0100/1490] git-gui: Allow users to choose/create/clone a repository If we are started outside of a git repository than it is likely the user started us from some sort of desktop shortcut icon in the operating system. In such a case the user is expecting us to prompt them to locate the git repository they want to work on, or to help them make a new repository, or to clone one from an existing location. This is a very simple wizard that offers the user one of these three choices. When we clone a repository we always use the name `master` in the local repository, even if the remote side does not appear to point to that name. I chose this as a policy decision. Much of the Git documentation talks about `master` being the default branch in a repository and that's what git-init does too. If the remote side doesn't call its default branch `master` most users just don't care, they just want to use Git the way the documentation describes. Rather than relying on the git-clone Porcelain that ships with git we build the new repository ourselves and then obtain content by git-fetch. This technique simplifies the entire clone process to roughly: `git init && git fetch && git pull`. Today we use three passes with git-fetch; the first pass gets us the bulk of the objects and the branches, the second pass gets us the tags, and the final pass gets us the current value of HEAD to initialize the default branch. If the source repository is on the local disk we try to use a hardlink to connect the objects into the new clone as this can be many times faster than copying the objects or packing them and passing the data through a pipe to index-pack. Unlike git-clone we stick to pure Tcl [file link -hard] operation thus avoiding the need to fork a cpio process to setup the hardlinks. If hardlinks do not appear to be supported (e.g. filesystem doesn't allow them or we are crossing filesystem boundaries) we use file copying instead. Signed-off-by: Shawn O. Pearce --- git-gui.sh | 6 +- lib/choose_repository.tcl | 838 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 841 insertions(+), 3 deletions(-) create mode 100644 lib/choose_repository.tcl diff --git a/git-gui.sh b/git-gui.sh index 3ddfcd50eb..37da8fde3b 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -833,9 +833,9 @@ if {[catch { set _gitdir [git rev-parse --git-dir] set _prefix [git rev-parse --show-prefix] } err]} { - catch {wm withdraw .} - error_popup [strcat [mc "Cannot find the git directory:"] "\n\n$err"] - exit 1 + load_config 1 + apply_config + choose_repository::pick } if {![file isdirectory $_gitdir] && [is_Cygwin]} { catch {set _gitdir [exec cygpath --windows $_gitdir]} diff --git a/lib/choose_repository.tcl b/lib/choose_repository.tcl new file mode 100644 index 0000000000..1bec8bd0a8 --- /dev/null +++ b/lib/choose_repository.tcl @@ -0,0 +1,838 @@ +# git-gui Git repository chooser +# Copyright (C) 2007 Shawn Pearce + +class choose_repository { + +image create photo ::choose_repository::git_logo -data { +R0lGODlh3wA9AMIHAMAAAMIKCsMKCgCAAN/v3/319f///wAAACH5BAEKAAcALAAAAADfAD0AAAP+ +aLrc/jDKSau9OOvNu/9gKI5kaZ5oqq5s675wLM90bd94ru987//AoHBILBqPyKSSFGg6n9BoUwCR +Wq3Ux3X7zC4Xg7B4HN4Bzui0eo2GsN9wN3ye/jLI+IGZzpfz535/b3ZgeWN7goMPiXGLjGyECoaH +Oo+QjpZ1mJlnkQaTYhigZR6cmg6mbZucnqN6F64fqZ2rmYGskbGwo7Kzt7a1lq28u6AfBcjJysvM +yRDN0NHP0dTKniS619pG2dveQd3f4jzh40eu3eh5EOrq5kPtk3fxoQ/0xO9A93jz9+z7hvKBA1hP +0r5/BMkIJIfvU0OE8opFXDjQWCGLEsplfEj+sUc6jg40RhDZMcdHjCNBpkQ5IuAHlx5gtjg5cWVN +CiRjrnu5Uye/FzRlQhQ6IWcHohqQZlCKImhPm0ztqeT506dCqlddOK0K9SnOqVYphS141OuKrVm7 +cv3KUkRUC28rxMXW0KjDthvxgphb1GxSvynQilWblu1Nt4BFJZY4mIVgskMXhwQrN+GryQkj+zvx +mFTew5/5Eo6nmV5p0pzrUr4LejTkv5mlxsZMsKlqvf1an3691PJud7JrpwZFoDgBu3Zzi/6NjrlI +y5cD+74IPbrydowPBgfofPXe6QarW6eOuvLsBtC7424JnnX67djhtr++mTb3s+3Fe0avvexl2g3L +laaPd4QECN9+HBioFYF2KMjff7AVtkNyBUpmnoQRNjYhg184SN94GfI2U38LeUieiIpBOGJ9JVpo +mIYhIggUiQKZGB6GvanoGI0l9ejjj0AGKeSQRBZp5JFIJqnkkkxOkAAAOw== +} + +field top +field w +field w_body ; # Widget holding the center content +field w_next ; # Next button +field o_cons ; # Console object (if active) +field w_types ; # List of type buttons in clone + +field action new ; # What action are we going to perform? +field done 0 ; # Finished picking the repository? +field local_path {} ; # Where this repository is locally +field origin_url {} ; # Where we are cloning from +field origin_name origin ; # What we shall call 'origin' +field clone_type hardlink ; # Type of clone to construct +field readtree_err ; # Error output from read-tree (if any) + +constructor pick {} { + global M1T M1B + + make_toplevel top w + wm title $top [mc "Git Gui"] + + if {$top eq {.}} { + menu $w.mbar -tearoff 0 + $top configure -menu $w.mbar + + $w.mbar add cascade \ + -label [mc Repository] \ + -menu $w.mbar.repository + menu $w.mbar.repository + $w.mbar.repository add command \ + -label [mc Quit] \ + -command exit \ + -accelerator $M1T-Q + + if {[is_MacOSX]} { + $w.mbar add cascade -label [mc Apple] -menu .mbar.apple + menu $w.mbar.apple + $w.mbar.apple add command \ + -label [mc "About %s" [appname]] \ + -command do_about + } else { + $w.mbar add cascade -label [mc Help] -menu $w.mbar.help + menu $w.mbar.help + $w.mbar.help add command \ + -label [mc "About %s" [appname]] \ + -command do_about + } + + _center $top 500 350 + wm protocol $top WM_DELETE_WINDOW exit + bind $top <$M1B-q> exit + bind $top <$M1B-Q> exit + bind $top exit + } else { + wm geometry $top "+[winfo rootx .]+[winfo rooty .]" + bind $top [list destroy $top] + } + + label $w.git_logo \ + -borderwidth 1 \ + -relief sunken \ + -background white \ + -image ::choose_repository::git_logo + pack $w.git_logo -side top -fill x -padx 20 -pady 20 + + set w_body $w.body + frame $w_body + radiobutton $w_body.new \ + -anchor w \ + -text [mc "Create New Repository"] \ + -variable @action \ + -value new + radiobutton $w_body.clone \ + -anchor w \ + -text [mc "Clone Existing Repository"] \ + -variable @action \ + -value clone + radiobutton $w_body.open \ + -anchor w \ + -text [mc "Open Existing Repository"] \ + -variable @action \ + -value open + pack $w_body.new -anchor w -fill x + pack $w_body.clone -anchor w -fill x + pack $w_body.open -anchor w -fill x + pack $w_body -fill x -padx 10 + + frame $w.buttons + set w_next $w.buttons.next + button $w_next \ + -default active \ + -text [mc "Next >"] \ + -command [cb _next] + pack $w_next -side right -padx 5 + button $w.buttons.quit \ + -text [mc "Quit"] \ + -command exit + pack $w.buttons.quit -side right -padx 5 + pack $w.buttons -side bottom -fill x -padx 10 -pady 10 + + bind $top [cb _invoke_next] + bind $top " + grab $top + focus $top + " + tkwait variable @done + + if {$top eq {.}} { + eval destroy [winfo children $top] + _center $top 500 600 + } +} + +proc _home {} { + if {[catch {set h $::env(HOME)}] + || ![file isdirectory $h]} { + set h . + } + return $h +} + +proc _center {top nx ny} { + set rx [expr {([winfo screenwidth $top] - $nx) / 2}] + set ry [expr {([winfo screenheight $top] - $ny) / 2}] + wm geometry $top [format {%dx%d+%d+%d} $nx $ny $rx $ry] +} + +method _invoke_next {} { + if {[winfo exists $w_next]} { + uplevel #0 [$w_next cget -command] + } +} + +method _next {} { + destroy $w_body + _do_$action $this +} + +method _write_local_path {args} { + if {$local_path eq {}} { + $w_next conf -state disabled + } else { + $w_next conf -state normal + } +} + +method _git_init {} { + if {[file exists $local_path]} { + error_popup [mc "Location %s already exists." $local_path] + return 0 + } + + if {[catch {file mkdir $local_path} err]} { + error_popup [strcat \ + [mc "Failed to create repository %s:" $local_path] \ + "\n\n$err"] + return 0 + } + + if {[catch {cd $local_path} err]} { + error_popup [strcat \ + [mc "Failed to create repository %s:" $local_path] \ + "\n\n$err"] + return 0 + } + + if {[catch {git init} err]} { + error_popup [strcat \ + [mc "Failed to create repository %s:" $local_path] \ + "\n\n$err"] + return 0 + } + + set ::_gitdir .git + set ::_prefix {} + return 1 +} + +proc _is_git {path} { + if {[file exists [file join $path HEAD]] + && [file exists [file join $path objects]] + && [file exists [file join $path config]]} { + return 1 + } + return 0 +} + +###################################################################### +## +## Create New Repository + +method _do_new {} { + $w_next conf \ + -state disabled \ + -command [cb _do_new2] \ + -text [mc "Create"] + + frame $w_body + label $w_body.h \ + -font font_uibold \ + -text [mc "Create New Repository"] + pack $w_body.h -side top -fill x -pady 10 + pack $w_body -fill x -padx 10 + + frame $w_body.where + label $w_body.where.l -text [mc "Directory:"] + entry $w_body.where.t \ + -textvariable @local_path \ + -font font_diff \ + -width 50 + button $w_body.where.b \ + -text [mc "Browse"] \ + -command [cb _new_local_path] + + pack $w_body.where.b -side right + pack $w_body.where.l -side left + pack $w_body.where.t -fill x + pack $w_body.where -fill x + + trace add variable @local_path write [cb _write_local_path] + update + focus $w_body.where.t +} + +method _new_local_path {} { + if {$local_path ne {}} { + set p [file dirname $local_path] + } else { + set p [_home] + } + + set p [tk_chooseDirectory \ + -initialdir $p \ + -parent $top \ + -title [mc "Git Repository"] \ + -mustexist false] + if {$p eq {}} return + + set p [file normalize $p] + if {[file isdirectory $p]} { + foreach i [glob \ + -directory $p \ + -tails \ + -nocomplain \ + * .*] { + switch -- $i { + . continue + .. continue + default { + error_popup [mc "Directory %s already exists." $p] + return + } + } + } + if {[catch {file delete $p} err]} { + error_popup [strcat \ + [mc "Directory %s already exists." $p] \ + "\n\n$err"] + return + } + } elseif {[file exists $p]} { + error_popup [mc "File %s already exists." $p] + return + } + set local_path $p +} + +method _do_new2 {} { + if {![_git_init $this]} { + return + } + set done 1 +} + +###################################################################### +## +## Clone Existing Repository + +method _do_clone {} { + $w_next conf \ + -state disabled \ + -command [cb _do_clone2] \ + -text [mc "Clone"] + + frame $w_body + label $w_body.h \ + -font font_uibold \ + -text [mc "Clone Existing Repository"] + pack $w_body.h -side top -fill x -pady 10 + pack $w_body -fill x -padx 10 + + set args $w_body.args + frame $w_body.args + pack $args -fill both + + label $args.origin_l -text [mc "URL:"] + entry $args.origin_t \ + -textvariable @origin_url \ + -font font_diff \ + -width 50 + button $args.origin_b \ + -text [mc "Browse"] \ + -command [cb _open_origin] + grid $args.origin_l $args.origin_t $args.origin_b -sticky ew + + label $args.where_l -text [mc "Directory:"] + entry $args.where_t \ + -textvariable @local_path \ + -font font_diff \ + -width 50 + button $args.where_b \ + -text [mc "Browse"] \ + -command [cb _new_local_path] + grid $args.where_l $args.where_t $args.where_b -sticky ew + + label $args.type_l -text [mc "Clone Type:"] + frame $args.type_f + set w_types [list] + lappend w_types [radiobutton $args.type_f.hardlink \ + -state disabled \ + -anchor w \ + -text [mc "Standard (Fast, Semi-Redundant, Hardlinks)"] \ + -variable @clone_type \ + -value hardlink] + lappend w_types [radiobutton $args.type_f.full \ + -state disabled \ + -anchor w \ + -text [mc "Full Copy (Slower, Redundant Backup)"] \ + -variable @clone_type \ + -value full] + lappend w_types [radiobutton $args.type_f.shared \ + -state disabled \ + -anchor w \ + -text [mc "Shared (Fastest, Not Recommended, No Backup)"] \ + -variable @clone_type \ + -value shared] + foreach r $w_types { + pack $r -anchor w + } + grid $args.type_l $args.type_f -sticky new + + grid columnconfigure $args 1 -weight 1 + + trace add variable @local_path write [cb _update_clone] + trace add variable @origin_url write [cb _update_clone] + update + focus $args.origin_t +} + +method _open_origin {} { + if {$origin_url ne {} && [file isdirectory $origin_url]} { + set p $origin_url + } else { + set p [_home] + } + + set p [tk_chooseDirectory \ + -initialdir $p \ + -parent $top \ + -title [mc "Git Repository"] \ + -mustexist true] + if {$p eq {}} return + + set p [file normalize $p] + if {![_is_git [file join $p .git]] && ![_is_git $p]} { + error_popup [mc "Not a Git repository: %s" [file tail $p]] + return + } + set origin_url $p +} + +method _update_clone {args} { + if {$local_path ne {} && $origin_url ne {}} { + $w_next conf -state normal + } else { + $w_next conf -state disabled + } + + if {$origin_url ne {} && + ( [_is_git [file join $origin_url .git]] + || [_is_git $origin_url])} { + set e normal + if {[[lindex $w_types 0] cget -state] eq {disabled}} { + set clone_type hardlink + } + } else { + set e disabled + set clone_type full + } + + foreach r $w_types { + $r conf -state $e + } +} + +method _do_clone2 {} { + if {[file isdirectory $origin_url]} { + set origin_url [file normalize $origin_url] + } + + if {$clone_type eq {hardlink} && ![file isdirectory $origin_url]} { + error_popup [mc "Standard only available for local repository."] + return + } + if {$clone_type eq {shared} && ![file isdirectory $origin_url]} { + error_popup [mc "Shared only available for local repository."] + return + } + + if {$clone_type eq {hardlink} || $clone_type eq {shared}} { + set objdir [file join $origin_url .git objects] + if {![file isdirectory $objdir]} { + set objdir [file join $origin_url objects] + if {![file isdirectory $objdir]} { + error_popup [mc "Not a Git repository: %s" [file tail $origin_url]] + return + } + } + } + + set giturl $origin_url + if {[is_Cygwin] && [file isdirectory $giturl]} { + set giturl [exec cygpath --unix --absolute $giturl] + if {$clone_type eq {shared}} { + set objdir [exec cygpath --unix --absolute $objdir] + } + } + + if {![_git_init $this]} return + set local_path [pwd] + + if {[catch { + git config remote.$origin_name.url $giturl + git config remote.$origin_name.fetch +refs/heads/*:refs/remotes/$origin_name/* + } err]} { + error_popup [strcat [mc "Failed to configure origin"] "\n\n$err"] + return + } + + destroy $w_body $w_next + + switch -exact -- $clone_type { + hardlink { + set tolink [list] + file mkdir [file join .git objects pack] + foreach i [glob -tails -nocomplain \ + -directory [file join $objdir pack] *] { + lappend tolink [file join pack $i] + } + foreach i [glob -tails -nocomplain \ + -directory [file join $objdir] ??] { + file mkdir [file join .git objects $i] + foreach j [glob -tails -nocomplain \ + -directory [file join $objdir $i] *] { + lappend tolink [file join $i $j] + } + } + + if {$tolink eq {}} { + info_popup [strcat \ + [mc "Nothing to clone from %s." $origin_url] \ + "\n" \ + [mc "The 'master' branch has not been initialized."] \ + ] + set done 1 + return + } + + set o_cons [status_bar::new $w_body] + pack $w_body -fill x -padx 10 + + set i [lindex $tolink 0] + if {[catch { + file link -hard \ + [file join .git objects $i] \ + [file join $objdir $i] + } err]} { + info_popup [strcat \ + [mc "Hardlinks are unavailable. Falling back to copying."] \ + "\n" \ + $err] + set i [_copy_files $this $objdir $tolink] + } else { + set i [_link_files $this $objdir [lrange $tolink 1 end]] + } + if {!$i} return + + destroy $w_body + } + full { + set o_cons [console::embed \ + $w_body \ + [mc "Cloning from %s" $origin_url]] + pack $w_body -fill both -expand 1 -padx 10 + $o_cons exec \ + [list git fetch --no-tags -k $origin_name] \ + [cb _do_clone_tags] + } + shared { + set fd [open [gitdir objects info alternates] w] + fconfigure $fd -translation binary + puts $fd $objdir + close $fd + } + } + + if {$clone_type eq {hardlink} || $clone_type eq {shared}} { + if {![_clone_refs $this]} return + set pwd [pwd] + if {[catch { + cd $origin_url + set HEAD [git rev-parse --verify HEAD^0] + } err]} { + _clone_failed $this [mc "Not a Git repository: %s" [file tail $origin_url]] + return 0 + } + cd $pwd + _do_clone_checkout $this $HEAD + } +} + +method _copy_files {objdir tocopy} { + $o_cons start \ + [mc "Copying objects"] \ + [mc "KiB"] + set tot 0 + set cmp 0 + foreach p $tocopy { + incr tot [file size [file join $objdir $p]] + } + foreach p $tocopy { + if {[catch { + set f_in [open [file join $objdir $p] r] + set f_cp [open [file join .git objects $p] w] + fconfigure $f_in -translation binary -encoding binary + fconfigure $f_cp -translation binary -encoding binary + + while {![eof $f_in]} { + incr cmp [fcopy $f_in $f_cp -size 16384] + $o_cons update \ + [expr {$cmp / 1024}] \ + [expr {$tot / 1024}] + update + } + + close $f_in + close $f_cp + } err]} { + _clone_failed $this [mc "Unable to copy object: %s" $err] + return 0 + } + } + return 1 +} + +method _link_files {objdir tolink} { + set total [llength $tolink] + $o_cons start \ + [mc "Linking objects"] \ + [mc "objects"] + for {set i 0} {$i < $total} {} { + set p [lindex $tolink $i] + if {[catch { + file link -hard \ + [file join .git objects $p] \ + [file join $objdir $p] + } err]} { + _clone_failed $this [mc "Unable to hardlink object: %s" $err] + return 0 + } + + incr i + if {$i % 5 == 0} { + $o_cons update $i $total + update + } + } + return 1 +} + +method _clone_refs {} { + set pwd [pwd] + if {[catch {cd $origin_url} err]} { + error_popup [mc "Not a Git repository: %s" [file tail $origin_url]] + return 0 + } + set fd_in [git_read for-each-ref \ + --tcl \ + {--format=list %(refname) %(objectname) %(*objectname)}] + cd $pwd + + set fd [open [gitdir packed-refs] w] + fconfigure $fd -translation binary + puts $fd "# pack-refs with: peeled" + while {[gets $fd_in line] >= 0} { + set line [eval $line] + set refn [lindex $line 0] + set robj [lindex $line 1] + set tobj [lindex $line 2] + + if {[regsub ^refs/heads/ $refn \ + "refs/remotes/$origin_name/" refn]} { + puts $fd "$robj $refn" + } elseif {[string match refs/tags/* $refn]} { + puts $fd "$robj $refn" + if {$tobj ne {}} { + puts $fd "^$tobj" + } + } + } + close $fd_in + close $fd + return 1 +} + +method _do_clone_tags {ok} { + if {$ok} { + $o_cons exec \ + [list git fetch --tags -k $origin_name] \ + [cb _do_clone_HEAD] + } else { + $o_cons done $ok + _clone_failed $this [mc "Cannot fetch branches and objects. See console output for details."] + } +} + +method _do_clone_HEAD {ok} { + if {$ok} { + $o_cons exec \ + [list git fetch $origin_name HEAD] \ + [cb _do_clone_full_end] + } else { + $o_cons done $ok + _clone_failed $this [mc "Cannot fetch tags. See console output for details."] + } +} + +method _do_clone_full_end {ok} { + $o_cons done $ok + + if {$ok} { + destroy $w_body + + set HEAD {} + if {[file exists [gitdir FETCH_HEAD]]} { + set fd [open [gitdir FETCH_HEAD] r] + while {[gets $fd line] >= 0} { + if {[regexp "^(.{40})\t\t" $line line HEAD]} { + break + } + } + close $fd + } + + catch {git pack-refs} + _do_clone_checkout $this $HEAD + } else { + _clone_failed $this [mc "Cannot determine HEAD. See console output for details."] + } +} + +method _clone_failed {{why {}}} { + if {[catch {file delete -force $local_path} err]} { + set why [strcat \ + $why \ + "\n\n" \ + [mc "Unable to cleanup %s" $local_path] \ + "\n\n" \ + $err] + } + if {$why ne {}} { + update + error_popup [strcat [mc "Clone failed."] "\n" $why] + } +} + +method _do_clone_checkout {HEAD} { + if {$HEAD eq {}} { + info_popup [strcat \ + [mc "No default branch obtained."] \ + "\n" \ + [mc "The 'master' branch has not been initialized."] \ + ] + set done 1 + return + } + if {[catch { + git update-ref HEAD $HEAD^0 + } err]} { + info_popup [strcat \ + [mc "Cannot resolve %s as a commit." $HEAD^0] \ + "\n $err" \ + "\n" \ + [mc "The 'master' branch has not been initialized."] \ + ] + set done 1 + return + } + + set o_cons [status_bar::new $w_body] + pack $w_body -fill x -padx 10 + $o_cons start \ + [mc "Creating working directory"] \ + [mc "files"] + + set readtree_err {} + set fd [git_read --stderr read-tree \ + -m \ + -u \ + -v \ + HEAD \ + HEAD \ + ] + fconfigure $fd -blocking 0 -translation binary + fileevent $fd readable [cb _readtree_wait $fd] +} + +method _readtree_wait {fd} { + set buf [read $fd] + $o_cons update_meter $buf + append readtree_err $buf + + fconfigure $fd -blocking 1 + if {![eof $fd]} { + fconfigure $fd -blocking 0 + return + } + + if {[catch {close $fd}]} { + set err $readtree_err + regsub {^fatal: } $err {} err + error_popup [strcat \ + [mc "Initial file checkout failed."] \ + "\n\n$err"] + return + } + + set done 1 +} + +###################################################################### +## +## Open Existing Repository + +method _do_open {} { + $w_next conf \ + -state disabled \ + -command [cb _do_open2] \ + -text [mc "Open"] + + frame $w_body + label $w_body.h \ + -font font_uibold \ + -text [mc "Open Existing Repository"] + pack $w_body.h -side top -fill x -pady 10 + pack $w_body -fill x -padx 10 + + frame $w_body.where + label $w_body.where.l -text [mc "Repository:"] + entry $w_body.where.t \ + -textvariable @local_path \ + -font font_diff \ + -width 50 + button $w_body.where.b \ + -text [mc "Browse"] \ + -command [cb _open_local_path] + + pack $w_body.where.b -side right + pack $w_body.where.l -side left + pack $w_body.where.t -fill x + pack $w_body.where -fill x + + trace add variable @local_path write [cb _write_local_path] + update + focus $w_body.where.t +} + +method _open_local_path {} { + if {$local_path ne {}} { + set p $local_path + } else { + set p [_home] + } + + set p [tk_chooseDirectory \ + -initialdir $p \ + -parent $top \ + -title [mc "Git Repository"] \ + -mustexist true] + if {$p eq {}} return + + set p [file normalize $p] + if {![_is_git [file join $p .git]]} { + error_popup [mc "Not a Git repository: %s" [file tail $p]] + return + } + set local_path $p +} + +method _do_open2 {} { + if {![_is_git [file join $local_path .git]]} { + error_popup [mc "Not a Git repository: %s" [file tail $local_path]] + return + } + + if {[catch {cd $local_path} err]} { + error_popup [strcat \ + [mc "Failed to open repository %s:" $local_path] \ + "\n\n$err"] + return + } + + set ::_gitdir .git + set ::_prefix {} + set done 1 +} + +} From fbc8a93cd5b03bf15a3ebef6c0a512d2da3df7c4 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Sun, 23 Sep 2007 05:25:13 -0400 Subject: [PATCH 0101/1490] git-gui: Avoid console scrollbars unless they are necessary We shouldn't create scrollbars for the horziontal or vertical sides unless there is enough content to make it worth drawing these widgets on screen. This way users don't loose screen space to objects that won't help them navigate the display. Signed-off-by: Shawn O. Pearce --- lib/console.tcl | 78 ++++++++++++++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 30 deletions(-) diff --git a/lib/console.tcl b/lib/console.tcl index e5f9ba429b..cde9a09268 100644 --- a/lib/console.tcl +++ b/lib/console.tcl @@ -6,6 +6,7 @@ class console { field t_short field t_long field w +field w_t field console_cr field is_toplevel 1; # are we our own window? @@ -36,6 +37,7 @@ method _init {} { } set console_cr 1.0 + set w_t $w.m.t frame $w.m label $w.m.l1 \ @@ -43,38 +45,34 @@ method _init {} { -anchor w \ -justify left \ -font font_uibold - text $w.m.t \ + text $w_t \ -background white -borderwidth 1 \ -relief sunken \ -width 80 -height 10 \ -wrap none \ -font font_diff \ -state disabled \ - -xscrollcommand [list $w.m.sbx set] \ - -yscrollcommand [list $w.m.sby set] + -xscrollcommand [cb _sb_set $w.m.sbx h] \ + -yscrollcommand [cb _sb_set $w.m.sby v] label $w.m.s -text [mc "Working... please wait..."] \ -anchor w \ -justify left \ -font font_uibold - scrollbar $w.m.sbx -command [list $w.m.t xview] -orient h - scrollbar $w.m.sby -command [list $w.m.t yview] pack $w.m.l1 -side top -fill x pack $w.m.s -side bottom -fill x - pack $w.m.sbx -side bottom -fill x - pack $w.m.sby -side right -fill y - pack $w.m.t -side left -fill both -expand 1 + pack $w_t -side left -fill both -expand 1 pack $w.m -side top -fill both -expand 1 -padx 5 -pady 10 menu $w.ctxm -tearoff 0 $w.ctxm add command -label [mc "Copy"] \ - -command "tk_textCopy $w.m.t" + -command "tk_textCopy $w_t" $w.ctxm add command -label [mc "Select All"] \ - -command "focus $w.m.t;$w.m.t tag add sel 0.0 end" + -command "focus $w_t;$w_t tag add sel 0.0 end" $w.ctxm add command -label [mc "Copy All"] \ -command " - $w.m.t tag add sel 0.0 end - tk_textCopy $w.m.t - $w.m.t tag remove sel 0.0 end + $w_t tag add sel 0.0 end + tk_textCopy $w_t + $w_t tag remove sel 0.0 end " if {$is_toplevel} { @@ -85,9 +83,9 @@ method _init {} { bind $w [list focus $w] } - bind_button3 $w.m.t "tk_popup $w.ctxm %X %Y" - bind $w.m.t <$M1B-Key-a> "$w.m.t tag add sel 0.0 end;break" - bind $w.m.t <$M1B-Key-A> "$w.m.t tag add sel 0.0 end;break" + bind_button3 $w_t "tk_popup $w.ctxm %X %Y" + bind $w_t <$M1B-Key-a> "$w_t tag add sel 0.0 end;break" + bind $w_t <$M1B-Key-A> "$w_t tag add sel 0.0 end;break" } method exec {cmd {after {}}} { @@ -104,8 +102,8 @@ method exec {cmd {after {}}} { method _read {fd after} { set buf [read $fd] if {$buf ne {}} { - if {![winfo exists $w.m.t]} {_init $this} - $w.m.t conf -state normal + if {![winfo exists $w_t]} {_init $this} + $w_t conf -state normal set c 0 set n [string length $buf] while {$c < $n} { @@ -115,20 +113,20 @@ method _read {fd after} { if {$lf < 0} {set lf [expr {$n + 1}]} if {$lf < $cr} { - $w.m.t insert end [string range $buf $c $lf] - set console_cr [$w.m.t index {end -1c}] + $w_t insert end [string range $buf $c $lf] + set console_cr [$w_t index {end -1c}] set c $lf incr c } else { - $w.m.t delete $console_cr end - $w.m.t insert end "\n" - $w.m.t insert end [string range $buf $c $cr] + $w_t delete $console_cr end + $w_t insert end "\n" + $w_t insert end [string range $buf $c $cr] set c $cr incr c } } - $w.m.t conf -state disabled - $w.m.t see end + $w_t conf -state disabled + $w_t see end } fconfigure $fd -blocking 1 @@ -171,11 +169,11 @@ method chain {cmdlist {ok 1}} { } method insert {txt} { - if {![winfo exists $w.m.t]} {_init $this} - $w.m.t conf -state normal - $w.m.t insert end "$txt\n" - set console_cr [$w.m.t index {end -1c}] - $w.m.t conf -state disabled + if {![winfo exists $w_t]} {_init $this} + $w_t conf -state normal + $w_t insert end "$txt\n" + set console_cr [$w_t index {end -1c}] + $w_t conf -state disabled } method done {ok} { @@ -200,4 +198,24 @@ method done {ok} { delete_this } +method _sb_set {sb orient first last} { + if {$first == 0 && $last == 1} { + if {[winfo exists $sb]} { + destroy $sb + } + return + } + + if {![winfo exists $sb]} { + if {$orient eq {h}} { + scrollbar $sb -orient h -command [list $w_t xview] + pack $sb -fill x -side bottom -before $w_t + } else { + scrollbar $sb -orient v -command [list $w_t yview] + pack $sb -fill y -side right -before $w_t + } + } + catch {$sb set $first $last} +} + } From 354e114d7461c5f7f6bd4e0fb6d880bdd15a7823 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sun, 23 Sep 2007 22:29:18 -0400 Subject: [PATCH 0102/1490] git-gui: Deiconify startup wizard so it raises to the top Signed-off-by: Shawn O. Pearce --- lib/choose_repository.tcl | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/choose_repository.tcl b/lib/choose_repository.tcl index 1bec8bd0a8..5f2d12fd07 100644 --- a/lib/choose_repository.tcl +++ b/lib/choose_repository.tcl @@ -123,6 +123,7 @@ constructor pick {} { grab $top focus $top " + wm deiconify $top tkwait variable @done if {$top eq {.}} { From 40f86af01b061fbbd1e46d125280073322bf9f33 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Mon, 24 Sep 2007 08:26:07 -0400 Subject: [PATCH 0103/1490] git-gui: Don't bother showing OS error message about hardlinks If we failed to create our test hardlink for the first object we need to link/copy then the only recourse we have is to make a copy of the objects. Users don't really need to know the OS details about why the hardlink failed as its usually because they are crossing filesystem boundaries. Signed-off-by: Shawn O. Pearce --- lib/choose_repository.tcl | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/choose_repository.tcl b/lib/choose_repository.tcl index 5f2d12fd07..9074c1ba5c 100644 --- a/lib/choose_repository.tcl +++ b/lib/choose_repository.tcl @@ -496,10 +496,7 @@ method _do_clone2 {} { [file join .git objects $i] \ [file join $objdir $i] } err]} { - info_popup [strcat \ - [mc "Hardlinks are unavailable. Falling back to copying."] \ - "\n" \ - $err] + info_popup [mc "Hardlinks are unavailable. Falling back to copying."] set i [_copy_files $this $objdir $tolink] } else { set i [_link_files $this $objdir [lrange $tolink 1 end]] From 81d4d3dddc5e96aea45a2623c9b1840491348b92 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Mon, 24 Sep 2007 08:40:44 -0400 Subject: [PATCH 0104/1490] git-gui: Keep the UI responsive while counting objects in clone If we are doing a "standard" clone by way of hardlinking the objects (or copying them if hardlinks are not available) the UI can freeze up for a good few seconds while Tcl scans all of the object directories. This is espeically noticed on a Windows system when you are working off network shares and need to wait for both the NT overheads and the network. We now show a progress bar as we count the objects and build our list of things to copy. This keeps the user amused and also makes sure we run the Tk event loop often enough that the window can still be dragged around the desktop. Signed-off-by: Shawn O. Pearce --- lib/choose_repository.tcl | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/lib/choose_repository.tcl b/lib/choose_repository.tcl index 9074c1ba5c..4ad1f781f7 100644 --- a/lib/choose_repository.tcl +++ b/lib/choose_repository.tcl @@ -462,20 +462,42 @@ method _do_clone2 {} { switch -exact -- $clone_type { hardlink { + set o_cons [status_bar::new $w_body] + pack $w_body -fill x -padx 10 + + $o_cons start \ + [mc "Counting objects"] \ + [mc "buckets"] + update + set tolink [list] + set buckets [glob \ + -tails \ + -nocomplain \ + -directory [file join $objdir] ??] + set bcnt [expr {[llength $buckets] + 2}] + set bcur 1 + $o_cons update $bcur $bcnt + update + file mkdir [file join .git objects pack] foreach i [glob -tails -nocomplain \ -directory [file join $objdir pack] *] { lappend tolink [file join pack $i] } - foreach i [glob -tails -nocomplain \ - -directory [file join $objdir] ??] { + $o_cons update [incr bcur] $bcnt + update + + foreach i $buckets { file mkdir [file join .git objects $i] foreach j [glob -tails -nocomplain \ -directory [file join $objdir $i] *] { lappend tolink [file join $i $j] } + $o_cons update [incr bcur] $bcnt + update } + $o_cons stop if {$tolink eq {}} { info_popup [strcat \ @@ -483,13 +505,11 @@ method _do_clone2 {} { "\n" \ [mc "The 'master' branch has not been initialized."] \ ] + destroy $w_body set done 1 return } - set o_cons [status_bar::new $w_body] - pack $w_body -fill x -padx 10 - set i [lindex $tolink 0] if {[catch { file link -hard \ From 85f77eadcc1d6e5a62079ab86988ffe95e9421d5 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Mon, 24 Sep 2007 08:50:58 -0400 Subject: [PATCH 0105/1490] git-gui: Copy objects/info/alternates during standard clone If the source repository is using an objects/info/alternates file we need to copy the file to our new repository so that it can access any objects that won't be copied/hardlinked as they are stored in the alternate location. We explicitly resolve all paths in the objects/info/alternates as relative to the source repository but then convert them into an absolute path for the new clone. This allows the new clone to access the exact same locaton as the source repository, even if relative paths had been used before. Under Cygwin we assume that Git is Cygwin based and that the paths in objects/info/alternates must be valid Cygwin UNIX paths, so we need to run `cygpath --unix` on each line in the alternate list. Signed-off-by: Shawn O. Pearce --- lib/choose_repository.tcl | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/lib/choose_repository.tcl b/lib/choose_repository.tcl index 4ad1f781f7..f7b8c93095 100644 --- a/lib/choose_repository.tcl +++ b/lib/choose_repository.tcl @@ -470,6 +470,32 @@ method _do_clone2 {} { [mc "buckets"] update + if {[file exists [file join $objdir info alternates]]} { + set pwd [pwd] + if {[catch { + file mkdir [gitdir objects info] + set f_in [open [file join $objdir info alternates] r] + set f_cp [open [gitdir objects info alternates] w] + fconfigure $f_in -translation binary -encoding binary + fconfigure $f_cp -translation binary -encoding binary + cd $objdir + while {[gets $f_in line] >= 0} { + if {[is_Cygwin]} { + puts $f_cp [exec cygpath --unix --absolute $line] + } else { + puts $f_cp [file normalize $line] + } + } + close $f_in + close $f_cp + cd $pwd + } err]} { + catch {cd $pwd} + _clone_failed $this [mc "Unable to copy objects/info/alternates: %s" $err] + return + } + } + set tolink [list] set buckets [glob \ -tails \ From cd38c86fd8e8fbbc1d83b80f7d96cf19d8266196 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Mon, 24 Sep 2007 23:24:12 -0400 Subject: [PATCH 0106/1490] git-gui: add a simple msgfmt replacement The program "msgfmt" was our only dependency on gettext. Since it is more than just a hassle to compile gettext on MinGW, here is a (very simple) drop-in replacement, which Works For Us. [sp: Changed Makefile to enable/disable po2msg.sh by the new NO_MSGFMT variable.] Signed-off-by: Johannes Schindelin Signed-off-by: Shawn O. Pearce --- Makefile | 11 +++++- po/po2msg.sh | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 po/po2msg.sh diff --git a/Makefile b/Makefile index 6236dd6ad3..0ab33517a9 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,10 @@ all:: # Define V=1 to have a more verbose compile. # +# Define NO_MSGFMT if you do not have msgfmt from the GNU gettext +# package and want to use our rough pure Tcl po->msg translator. +# TCL_PATH must be vaild for this to work. +# GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE @$(SHELL_PATH) ./GIT-VERSION-GEN @@ -129,7 +133,12 @@ $(GITGUI_BUILT_INS): git-gui $(QUIET_BUILT_IN)rm -f $@ && ln git-gui $@ XGETTEXT ?= xgettext -MSGFMT ?= msgfmt +ifdef NO_MSGFMT + MSGFMT ?= $(TCL_PATH) po/po2msg.sh +else + MSGFMT ?= msgfmt +endif + msgsdir = $(gg_libdir)/msgs msgsdir_SQ = $(subst ','\'',$(msgsdir)) PO_TEMPLATE = po/git-gui.pot diff --git a/po/po2msg.sh b/po/po2msg.sh new file mode 100644 index 0000000000..da0765dd80 --- /dev/null +++ b/po/po2msg.sh @@ -0,0 +1,103 @@ +#!/bin/sh +# Tcl ignores the next line -*- tcl -*- \ +exec tclsh "$0" -- "$@" + +# This is a really stupid program, which serves as an alternative to +# msgfmt. It _only_ translates to Tcl mode, does _not_ validate the +# input, and does _not_ output any statistics. + +proc u2a {s} { + set res "" + foreach i [split $s ""] { + scan $i %c c + if {$c<128} { + # escape '[', '\' and ']' + if {$c == 0x5b || $c == 0x5d} { + append res "\\" + } + append res $i + } else { + append res \\u[format %04.4x $c] + } + } + return $res +} + +set output_directory "." +set lang "dummy" +set files [list] + +# parse options +for {set i 1} {$i < $argc} {incr i} { + set arg [lindex $argv $i] + if {$arg == "--statistics" || $arg == "--tcl"} { + continue + } + if {$arg == "-l"} { + incr i + set lang [lindex $argv $i] + continue + } + if {$arg == "-d"} { + incr i + set tmp [lindex $argv $i] + regsub "\[^/\]$" $tmp "&/" output_directory + continue + } + lappend files $arg +} + +proc flush_msg {} { + global msgid msgstr mode lang out + + if {![info exists msgid] || $mode == ""} { + return + } + set mode "" + + if {$msgid == ""} { + set prefix "set ::msgcat::header" + } else { + set prefix "::msgcat::mcset $lang \"[u2a $msgid]\"" + } + + puts $out "$prefix \"[u2a $msgstr]\"" +} + +foreach file $files { + regsub "^.*/\(\[^/\]*\)\.po$" $file "$output_directory\\1.msg" outfile + set in [open $file "r"] + fconfigure $in -encoding utf-8 + set out [open $outfile "w"] + + set mode "" + while {[gets $in line] >= 0} { + if {[regexp "^#" $line]} { + flush_msg + continue + } elseif {[regexp "^msgid \"(.*)\"$" $line dummy match]} { + flush_msg + set msgid $match + set mode "msgid" + } elseif {[regexp "^msgstr \"(.*)\"$" $line dummy match]} { + set msgstr $match + set mode "msgstr" + } elseif {$line == ""} { + flush_msg + } elseif {[regexp "^\"(.*)\"$" $line dummy match]} { + if {$mode == "msgid"} { + append msgid $match + } elseif {$mode == "msgstr"} { + append msgstr $match + } else { + puts stderr "I do not know what to do: $match" + } + } else { + puts stderr "Cannot handle $line" + } + } + flush_msg + close $in + close $out +} + From 009c5bcd24da3cd2670962e405585e31d662487d Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Tue, 25 Sep 2007 00:13:14 -0400 Subject: [PATCH 0107/1490] Cleanup style nit of 'x == NULL' in remote.c Git style tends to prefer "!x" over "x == NULL". Make it so in these handful of locations that were not following along. Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- remote.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/remote.c b/remote.c index e3c3df556d..ac354f3795 100644 --- a/remote.c +++ b/remote.c @@ -416,7 +416,7 @@ int remote_find_tracking(struct remote *remote, struct refspec *refspec) int i; if (find_src) { - if (refspec->dst == NULL) + if (!refspec->dst) return error("find_tracking: need either src or dst"); needle = refspec->dst; result = &refspec->src; @@ -613,7 +613,7 @@ static int match_explicit(struct ref *src, struct ref *dst, if (!matched_src) errs = 1; - if (dst_value == NULL) + if (!dst_value) dst_value = matched_src->name; switch (count_refspec_match(dst_value, dst, &matched_dst)) { @@ -633,7 +633,7 @@ static int match_explicit(struct ref *src, struct ref *dst, dst_value); break; } - if (errs || matched_dst == NULL) + if (errs || !matched_dst) return 1; if (matched_dst->peer_ref) { errs = 1; From 7dfee372b08f653c2709c90bea986e4ed608f410 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Tue, 25 Sep 2007 00:13:19 -0400 Subject: [PATCH 0108/1490] Cleanup unnecessary break in remote.c This simple change makes the body of "case 0" easier to read; no matter what the value of matched_src is we want to break out of the switch and not fall through. We only want to display an error if matched_src is NULL, as this indicates there is no local branch matching the input. Also modified the default case's error message so it uses one less line of text. Even at 8 column per tab indentation we still don't break 80 columns with this new formatting. Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- remote.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/remote.c b/remote.c index ac354f3795..2166a2bf15 100644 --- a/remote.c +++ b/remote.c @@ -598,15 +598,12 @@ static int match_explicit(struct ref *src, struct ref *dst, * way to delete 'other' ref at the remote end. */ matched_src = try_explicit_object_name(rs->src); - if (matched_src) - break; - error("src refspec %s does not match any.", - rs->src); + if (!matched_src) + error("src refspec %s does not match any.", rs->src); break; default: matched_src = NULL; - error("src refspec %s matches more than one.", - rs->src); + error("src refspec %s matches more than one.", rs->src); break; } From 4491e62ae932d5774f628d1bd3be663c11058a73 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Tue, 25 Sep 2007 00:13:25 -0400 Subject: [PATCH 0109/1490] Prevent send-pack from segfaulting when a branch doesn't match If `git push url foo` can't find a local branch named foo we can't match it to any remote branch as the local branch is NULL and its name is probably at position 0x34 in memory. On most systems that isn't a valid address for git-send-pack's virtual address space and we segfault. If we can't find a source match and we have no destination we need to abort the match function early before we try to match the destination against the remote. Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- remote.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/remote.c b/remote.c index 2166a2bf15..e7d735b98a 100644 --- a/remote.c +++ b/remote.c @@ -610,8 +610,11 @@ static int match_explicit(struct ref *src, struct ref *dst, if (!matched_src) errs = 1; - if (!dst_value) + if (!dst_value) { + if (!matched_src) + return errs; dst_value = matched_src->name; + } switch (count_refspec_match(dst_value, dst, &matched_dst)) { case 1: From 6f2d73ec0cb6d5937bb4a62a222f942e4f886d6e Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Wed, 26 Sep 2007 14:05:54 -0400 Subject: [PATCH 0110/1490] git-gui: Don't delete console window namespaces too early If the console finishes displaying its output and is "done" but needs to draw a scrollbar to show the final output messages it is possible for Tk to delete the window namespace before it does the text widget updates, which means we are unable to add the horizontal or vertical scrollbar to the window when the text widget decides it cannot draw all glyphs on screen. We need to delay deleting the window namespace until we know the window is not going to ever be used again. This occurs if we are done receiving output, the command is successful and the window is closed, or if the window is open and the user chooses to close the window after the command has completed. Signed-off-by: Shawn O. Pearce --- lib/console.tcl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/console.tcl b/lib/console.tcl index cde9a09268..c0e6fb3cc2 100644 --- a/lib/console.tcl +++ b/lib/console.tcl @@ -179,23 +179,26 @@ method insert {txt} { method done {ok} { if {$ok} { if {[winfo exists $w.m.s]} { + bind $w.m.s [list delete_this $this] $w.m.s conf -background green -text [mc "Success"] if {$is_toplevel} { $w.ok conf -state normal focus $w.ok } + } else { + delete_this } } else { if {![winfo exists $w.m.s]} { _init $this } + bind $w.m.s [list delete_this $this] $w.m.s conf -background red -text [mc "Error: Command Failed"] if {$is_toplevel} { $w.ok conf -state normal focus $w.ok } } - delete_this } method _sb_set {sb orient first last} { From 59213f60b7a3085732f76736e1826869994abf1a Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Wed, 26 Sep 2007 14:16:45 -0400 Subject: [PATCH 0111/1490] git-gui: Don't delete scrollbars in console windows If we have added a scrollbar to the console window because one direction has too much text to fit in the available screen space we should just keep the scrollbars. Its annoying to watch our horizontal scrollbar bounce in and out of the window as additional text is inserted into the widget and the need for the scrollbar comes and goes. Signed-off-by: Shawn O. Pearce --- lib/console.tcl | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/lib/console.tcl b/lib/console.tcl index c0e6fb3cc2..2075374683 100644 --- a/lib/console.tcl +++ b/lib/console.tcl @@ -202,14 +202,8 @@ method done {ok} { } method _sb_set {sb orient first last} { - if {$first == 0 && $last == 1} { - if {[winfo exists $sb]} { - destroy $sb - } - return - } - if {![winfo exists $sb]} { + if {$first == $last || ($first == 0 && $last == 1)} return if {$orient eq {h}} { scrollbar $sb -orient h -command [list $w_t xview] pack $sb -fill x -side bottom -before $w_t @@ -218,7 +212,7 @@ method _sb_set {sb orient first last} { pack $sb -fill y -side right -before $w_t } } - catch {$sb set $first $last} + $sb set $first $last } } From a7cb8f583ff6ef01c23b1694f30e9004271264f9 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Wed, 26 Sep 2007 14:59:09 -0400 Subject: [PATCH 0112/1490] git-gui: Switch the git-gui logo to Henrik Nyh's logo Henrik came up with this alternative logo for gitweb and posted it on his blog: http://henrik.nyh.se/2007/06/alternative-git-logo-and-favicon The msysGit port uses his logo within some of their components, and frankly it looks better here in git-gui for our repository setup wizard screen. The logo fits quite nicely along the left edge of our window, leaving significantly more vertical space for things like the git-fetch console output. Because the logo changes the layout charateristics of the setup window I also needed to adjust some of the padding for our widgets and stop using a fixed width window size. We now let Tk compute the correct size of the main window whenever the layout changes, and drop the window into roughly the upper left 1/3 of the desktop so its not quite centered but is likely to be far enough away from any sort of task bars/menu bars/docks that the user may have along any edge of the screen. Signed-off-by: Shawn O. Pearce --- lib/choose_repository.tcl | 63 +++++++++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 22 deletions(-) diff --git a/lib/choose_repository.tcl b/lib/choose_repository.tcl index f7b8c93095..8d3c81e7c0 100644 --- a/lib/choose_repository.tcl +++ b/lib/choose_repository.tcl @@ -3,19 +3,36 @@ class choose_repository { +# Henrik Nyh's alternative Git logo, from his blog post +# http://henrik.nyh.se/2007/06/alternative-git-logo-and-favicon +# image create photo ::choose_repository::git_logo -data { -R0lGODlh3wA9AMIHAMAAAMIKCsMKCgCAAN/v3/319f///wAAACH5BAEKAAcALAAAAADfAD0AAAP+ -aLrc/jDKSau9OOvNu/9gKI5kaZ5oqq5s675wLM90bd94ru987//AoHBILBqPyKSSFGg6n9BoUwCR -Wq3Ux3X7zC4Xg7B4HN4Bzui0eo2GsN9wN3ye/jLI+IGZzpfz535/b3ZgeWN7goMPiXGLjGyECoaH -Oo+QjpZ1mJlnkQaTYhigZR6cmg6mbZucnqN6F64fqZ2rmYGskbGwo7Kzt7a1lq28u6AfBcjJysvM -yRDN0NHP0dTKniS619pG2dveQd3f4jzh40eu3eh5EOrq5kPtk3fxoQ/0xO9A93jz9+z7hvKBA1hP -0r5/BMkIJIfvU0OE8opFXDjQWCGLEsplfEj+sUc6jg40RhDZMcdHjCNBpkQ5IuAHlx5gtjg5cWVN -CiRjrnu5Uye/FzRlQhQ6IWcHohqQZlCKImhPm0ztqeT506dCqlddOK0K9SnOqVYphS141OuKrVm7 -cv3KUkRUC28rxMXW0KjDthvxgphb1GxSvynQilWblu1Nt4BFJZY4mIVgskMXhwQrN+GryQkj+zvx -mFTew5/5Eo6nmV5p0pzrUr4LejTkv5mlxsZMsKlqvf1an3691PJud7JrpwZFoDgBu3Zzi/6NjrlI -y5cD+74IPbrydowPBgfofPXe6QarW6eOuvLsBtC7424JnnX67djhtr++mTb3s+3Fe0avvexl2g3L -laaPd4QECN9+HBioFYF2KMjff7AVtkNyBUpmnoQRNjYhg184SN94GfI2U38LeUieiIpBOGJ9JVpo -mIYhIggUiQKZGB6GvanoGI0l9ejjj0AGKeSQRBZp5JFIJqnkkkxOkAAAOw== +R0lGODdhYQC8AIQbAGZmZtg4LW9vb3l5eYKCgoyMjEC/TOJpYZWVlZ+fn2/PeKmpqbKysry8vMXF +xZ/fpc/Pz7fnvPXNytnZ2eLi4s/v0vja1+zs7Of36fX19f3z8v///////////////////ywAAAAA +YQC8AAAF/uAmjmRpnmiqrmzrvq4hz3RtGw+s7zx5/7dcb0hUAY8zYXHJRCKVzGjPeYRKry8q0Irt +GrVBr3gFDo/PprKNix6ra+y2902Ly7H05L2dl9n3UX04gGeCf4RFhohiiotdjY5XkJGBfYeUOpOY +iZablXmXURgPpKWmp6ipqYIKqq6vqREjFYK1trUKs7e7vFq5IrS9wsM0vxvBxMm8xsjKzqy6z9J5 +zNPWatXX2k7Z29433d/iMuHj3+Xm2+jp1+vs0+7vz/HyyvT1xPf4wvr7y9H+pBkbBasgLFYGE8ba +o8nTlE4OOYGKKJFOKIopGmLMAnHjDo0eWYAM+WUiSRgj/k+eSKmyBMuWI17C3CATZs2WN1XmPLmT +ZM+QPz0G3VihqNGjSJNWwDCzqdOnUKPu0SChqtWrWLNq3cq1q9evYCVYGCEhgNmzaNOqXcu2rdu3 +cOMGOEBWrt27ePPCpSuirN6/gAO35bvBr+DDiPMSNpy4sWO2ix9Lnmw2MuXLiS1j3gxYM+fPdz2D +Hv1WNOnTak2jXj23LuvXlV3DZq16Nujatjnjzo15N2/Kvn9LDi7cMfHimaUqX868ufPn0KPPpOCA +AQMWCQBo3869u/fv4MNrd3DlQoMC3QlkSJFdvPv38LVDWJLBAYHwE1LE38+/+/UhGTAggHv5odDf +gfv9/seDgPAVeAKCELqnIAwU3BefgyZEqOF3E7rAQH8YlrDhiNt1uEIG6IGoH4kjmpjCBRaqaCCL +G7p4AgUDIhgiCTTW2AKOEe44Qo8a2khCBgNoKKQIREZopAgZxAjhkhs0CeGTG7Sn5IpW9vekAyRS +2eWBRl6Q44ZijhlfAQlQmeKIaarpHZsMTHABCxDQGKec3JH3QpIs7snndn6yAKaeXA7aZwuABppo +fAws0GiEhaKQJ40F3DkjfwVC8CaCAlCgAgIkJjDfCgdiOMGn/Q2w3gkZtPgqC6ma0ECECaBwa4QE +aOpCrSYAqeMJpEKYqw7ABnsmfwQ8aCwPySqLYKUb/kwAYbPQyoiCtQcOUMKHBwrgK7LaogBuuaxC +OkS0KEwa37EiLBufALPuwO4Jh/InwAixkknEvSe4C9+p3PY3rr3lpnDufguIcCmzRQAc7IHYLhxf +w/8mnILA74lg8cARa4xCsZxusMCBomZccgsfv0deuh2HvLKh/sLs3hJSvieuCwUzvIHN4tGXc3ih +vtDzmj8fSNLR8BWQdH9LH+g00OFF3d/UBx4cUcvuOc21eFRiouV+Xvvr0dDvlX21R/2uzTR89TqU +L3+5UoBgAxtRHd5/CHpLkd13i4D2e3hHRLKMY+9Hr0Nvx/fq3Pw57cng7/m9wQVObnIyhAiQwHF8 +/tQS8nDgI2wOYeh3CAvhuIBHiDEgqvdtwudkaz3GBPKaTcKuGgqAJRMZmK6h1hnk3ncDcUvhgPFS +o5B476ZKQcECzCN4qgmYN4lAncmzcAEEkhJp+QlfkyhAAdtbN8H67FvHQAF6b4g6v9UryqfkKkBu +v/0prxD//kR63YnqB8AeqcdoBRxU/1zAuwRaaX4reJ4DSSRAHUhwgrgqwgUx2B94EWGDHISPBzUY +QgSNcAn6K6F4fscDCtBOhdoRwPW6kIHDwZA7vWoDBF44Qd/tIUAEBCACbIeG4AXxfmFrQ4B4OCYE +JBEQELChmgbAACJioj4JOCKCCLCABZ6EAg1IHwDlyLYAB1gRJhSYgHUQAD9WnQ9+CWBAA+wknTpC +JwQAOw== } field top @@ -66,7 +83,6 @@ constructor pick {} { -command do_about } - _center $top 500 350 wm protocol $top WM_DELETE_WINDOW exit bind $top <$M1B-q> exit bind $top <$M1B-Q> exit @@ -81,7 +97,7 @@ constructor pick {} { -relief sunken \ -background white \ -image ::choose_repository::git_logo - pack $w.git_logo -side top -fill x -padx 20 -pady 20 + pack $w.git_logo -side left -fill y -padx 10 -pady 10 set w_body $w.body frame $w_body @@ -103,7 +119,7 @@ constructor pick {} { pack $w_body.new -anchor w -fill x pack $w_body.clone -anchor w -fill x pack $w_body.open -anchor w -fill x - pack $w_body -fill x -padx 10 + pack $w_body -fill x -padx 10 -pady 10 frame $w.buttons set w_next $w.buttons.next @@ -120,15 +136,16 @@ constructor pick {} { bind $top [cb _invoke_next] bind $top " + [cb _center] grab $top focus $top + bind $top {} " wm deiconify $top tkwait variable @done if {$top eq {.}} { eval destroy [winfo children $top] - _center $top 500 600 } } @@ -140,10 +157,12 @@ proc _home {} { return $h } -proc _center {top nx ny} { - set rx [expr {([winfo screenwidth $top] - $nx) / 2}] - set ry [expr {([winfo screenheight $top] - $ny) / 2}] - wm geometry $top [format {%dx%d+%d+%d} $nx $ny $rx $ry] +method _center {} { + set nx [winfo reqwidth $top] + set ny [winfo reqheight $top] + set rx [expr {([winfo screenwidth $top] - $nx) / 3}] + set ry [expr {([winfo screenheight $top] - $ny) / 3}] + wm geometry $top [format {+%d+%d} $rx $ry] } method _invoke_next {} { @@ -463,7 +482,7 @@ method _do_clone2 {} { switch -exact -- $clone_type { hardlink { set o_cons [status_bar::new $w_body] - pack $w_body -fill x -padx 10 + pack $w_body -fill x -padx 10 -pady 10 $o_cons start \ [mc "Counting objects"] \ @@ -762,7 +781,7 @@ method _do_clone_checkout {HEAD} { } set o_cons [status_bar::new $w_body] - pack $w_body -fill x -padx 10 + pack $w_body -fill x -padx 10 -pady 10 $o_cons start \ [mc "Creating working directory"] \ [mc "files"] From 96225dbe966fdbf00ef1a3a1dd801534953c9919 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Wed, 26 Sep 2007 15:31:42 -0400 Subject: [PATCH 0113/1490] git-gui: Make the status bar easier to read in the setup wizard The setup wizard looks better if we layout the progress bar as two lines: the first line holds the message text and our text formatting of the progress while the second line holds the bar itself. Both extend the full width of the window and we try to pad out the message text so the window doesn't expand when the completed progress number jumps to the next order of magnitude. This change required updating the progress meter format string to allow the application to supply the precision. So we also are updating all of the translations at once to use the newer formatting string. Signed-off-by: Shawn O. Pearce --- lib/choose_repository.tcl | 4 ++-- lib/status_bar.tcl | 38 +++++++++++++++++++++++++++++++++----- po/de.po | 4 ++-- po/git-gui.pot | 2 +- po/hu.po | 4 ++-- po/it.po | 4 ++-- po/ja.po | 4 ++-- po/ru.po | 4 ++-- po/zh_cn.po | 2 +- 9 files changed, 47 insertions(+), 19 deletions(-) diff --git a/lib/choose_repository.tcl b/lib/choose_repository.tcl index 8d3c81e7c0..16bf67c34f 100644 --- a/lib/choose_repository.tcl +++ b/lib/choose_repository.tcl @@ -481,7 +481,7 @@ method _do_clone2 {} { switch -exact -- $clone_type { hardlink { - set o_cons [status_bar::new $w_body] + set o_cons [status_bar::two_line $w_body] pack $w_body -fill x -padx 10 -pady 10 $o_cons start \ @@ -780,7 +780,7 @@ method _do_clone_checkout {HEAD} { return } - set o_cons [status_bar::new $w_body] + set o_cons [status_bar::two_line $w_body] pack $w_body -fill x -padx 10 -pady 10 $o_cons start \ [mc "Creating working directory"] \ diff --git a/lib/status_bar.tcl b/lib/status_bar.tcl index 769ef81c4b..5c5bf7c731 100644 --- a/lib/status_bar.tcl +++ b/lib/status_bar.tcl @@ -6,6 +6,7 @@ class status_bar { field w ; # our own window path field w_l ; # text widget we draw messages into field w_c ; # canvas we draw a progress bar into +field c_pack ; # script to pack the canvas with field status {}; # single line of text we show field prefix {}; # text we format into status field units {}; # unit of progress @@ -24,6 +25,29 @@ constructor new {path} { -anchor w \ -justify left pack $w_l -side left + set c_pack [cb _oneline_pack] + + bind $w [cb _delete %W] + return $this +} + +method _oneline_pack {} { + $w_c conf -width 100 + pack $w_c -side right +} + +constructor two_line {path} { + set w $path + set w_l $w.l + set w_c $w.c + + frame $w + label $w_l \ + -textvariable @status \ + -anchor w \ + -justify left + pack $w_l -anchor w -fill x + set c_pack [list pack $w_c -fill x] bind $w [cb _delete %W] return $this @@ -34,13 +58,12 @@ method start {msg uds} { $w_c coords bar 0 0 0 20 } else { canvas $w_c \ - -width 100 \ -height [expr {int([winfo reqheight $w_l] * 0.6)}] \ -borderwidth 1 \ -relief groove \ -highlightt 0 $w_c create rectangle 0 0 0 20 -tags bar -fill navy - pack $w_c -side right + eval $c_pack } set status $msg @@ -53,11 +76,16 @@ method update {have total} { set pdone 0 if {$total > 0} { set pdone [expr {100 * $have / $total}] + set cdone [expr {[winfo width $w_c] * $have / $total}] } - set status [mc "%s ... %i of %i %s (%2i%%)" \ - $prefix $have $total $units $pdone] - $w_c coords bar 0 0 $pdone 20 + set prec [string length [format %i $total]] + set status [mc "%s ... %*i of %*i %s (%3i%%)" \ + $prefix \ + $prec $have \ + $prec $total \ + $units $pdone] + $w_c coords bar 0 0 $cdone 20 } method update_meter {buf} { diff --git a/po/de.po b/po/de.po index 7d57dd15f9..94b7463ca3 100644 --- a/po/de.po +++ b/po/de.po @@ -1350,8 +1350,8 @@ msgstr "Fehler beim Erstellen des Icons:" #: lib/status_bar.tcl:58 #, tcl-format -msgid "%s ... %i of %i %s (%2i%%)" -msgstr "%s ... %i von %i %s (%2i%%)" +msgid "%s ... %*i of %*i %s (%3i%%)" +msgstr "%s ... %*i von %*i %s (%3i%%)" #: lib/transport.tcl:7 #, tcl-format diff --git a/po/git-gui.pot b/po/git-gui.pot index 991efea5f3..b352302572 100644 --- a/po/git-gui.pot +++ b/po/git-gui.pot @@ -1216,7 +1216,7 @@ msgstr "" #: lib/status_bar.tcl:58 #, tcl-format -msgid "%s ... %i of %i %s (%2i%%)" +msgid "%s ... %*i of %*i %s (%3i%%)" msgstr "" #: lib/transport.tcl:7 diff --git a/po/hu.po b/po/hu.po index faac58f810..1e189b6086 100644 --- a/po/hu.po +++ b/po/hu.po @@ -1344,8 +1344,8 @@ msgstr "Nem sikerült írni az ikont:" #: lib/status_bar.tcl:58 #, tcl-format -msgid "%s ... %i of %i %s (%2i%%)" -msgstr "%s ... %i / %i %s (%2i%%)" +msgid "%s ... %*i of %*i %s (%3i%%)" +msgstr "%s ... %*i / %*i %s (%3i%%)" #: lib/transport.tcl:7 #, tcl-format diff --git a/po/it.po b/po/it.po index 17a5c21882..ad5cd9e5da 100644 --- a/po/it.po +++ b/po/it.po @@ -1344,8 +1344,8 @@ msgstr "Impossibile scrivere icona:" #: lib/status_bar.tcl:58 #, tcl-format -msgid "%s ... %i of %i %s (%2i%%)" -msgstr "%s ... %i di %i %s (%2i%%)" +msgid "%s ... %*i of %*i %s (%3i%%)" +msgstr "%s ... %*i di %*i %s (%3i%%)" #: lib/transport.tcl:7 #, tcl-format diff --git a/po/ja.po b/po/ja.po index 17139080ec..cdbc981ca5 100644 --- a/po/ja.po +++ b/po/ja.po @@ -1333,8 +1333,8 @@ msgstr "アイコンが書けません:" #: lib/status_bar.tcl:58 #, tcl-format -msgid "%s ... %i of %i %s (%2i%%)" -msgstr "%1$s ... %3$i %4$s 中の %$2i (%5$2i%%)" +msgid "%s ... %*i of %*i %s (%3i%%)" +msgstr "%1$s ... %3$*i %4$s 中の %$2*i (%5$3i%%)" #: lib/transport.tcl:7 #, tcl-format diff --git a/po/ru.po b/po/ru.po index c44d30af0a..20080338c8 100644 --- a/po/ru.po +++ b/po/ru.po @@ -1434,8 +1434,8 @@ msgstr "Невозможно записать значок:" #: lib/status_bar.tcl:58 #, tcl-format -msgid "%s ... %i of %i %s (%2i%%)" -msgstr "%s ... %i из %i %s (%2i%%)" +msgid "%s ... %*i of %*i %s (%3i%%)" +msgstr "%s ... %*i из %*i %s (%3i%%)" #: lib/transport.tcl:7 #, tcl-format diff --git a/po/zh_cn.po b/po/zh_cn.po index 45eb5b5f98..d1ed94f8a9 100644 --- a/po/zh_cn.po +++ b/po/zh_cn.po @@ -1238,7 +1238,7 @@ msgstr "" #: lib/status_bar.tcl:58 #, tcl-format -msgid "%s ... %i of %i %s (%2i%%)" +msgid "%s ... %*i of %*i %s (%3i%%)" msgstr "" #: lib/transport.tcl:7 From c73adce219ce52a662d90af1e1762c77ea5c4cb0 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Thu, 27 Sep 2007 10:35:05 +1000 Subject: [PATCH 0114/1490] gitk: Fix a couple of bugs insertrow and removerow were trying to adjust rowidlist, rowisopt and rowfinal even if the row where we're inserting/deleting stuff hasn't been laid out yet, which resulted in Tcl errors. This fixes that. Also we weren't deleting the link$linknum tag in appendwithlinks, which resulted in SHA1 IDs in the body of a commit message sometimes getting shown in blue with underlining when they shouldn't. Signed-off-by: Paul Mackerras --- gitk | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/gitk b/gitk index a5d0d66e6c..34fe33771f 100755 --- a/gitk +++ b/gitk @@ -4027,17 +4027,21 @@ proc insertrow {row newcmit} { incr commitidx($curview) set ordertok($curview,$newcmit) $ordertok($curview,$p) - set idlist [lindex $rowidlist $row] - if {[llength $kids] == 1} { - set col [lsearch -exact $idlist $p] - lset idlist $col $newcmit - } else { - set col [llength $idlist] - lappend idlist $newcmit + if {$row < [llength $rowidlist]} { + set idlist [lindex $rowidlist $row] + if {$idlist ne {}} { + if {[llength $kids] == 1} { + set col [lsearch -exact $idlist $p] + lset idlist $col $newcmit + } else { + set col [llength $idlist] + lappend idlist $newcmit + } + } + set rowidlist [linsert $rowidlist $row $idlist] + set rowisopt [linsert $rowisopt $row 0] + set rowfinal [linsert $rowfinal $row [lindex $rowfinal $row]] } - set rowidlist [linsert $rowidlist $row $idlist] - set rowisopt [linsert $rowisopt $row 0] - set rowfinal [linsert $rowfinal $row [lindex $rowfinal $row]] incr numcommits @@ -4077,9 +4081,11 @@ proc removerow {row} { } incr commitidx($curview) -1 - set rowidlist [lreplace $rowidlist $row $row] - set rowisopt [lreplace $rowisopt $row $row] - set rowfinal [lreplace $rowfinal $row $row] + if {$row < [llength $rowidlist]} { + set rowidlist [lreplace $rowidlist $row $row] + set rowisopt [lreplace $rowisopt $row $row] + set rowfinal [lreplace $rowfinal $row $row] + } incr numcommits -1 @@ -4443,6 +4449,7 @@ proc appendwithlinks {text tags} { set e [lindex $l 1] set linkid [string range $text $s $e] incr e + $ctext tag delete link$linknum $ctext tag add link$linknum "$start + $s c" "$start + $e c" setlink $linkid link$linknum incr linknum From bb3edc8b0473192da11bf7f9e961ea0fcc444c63 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Thu, 27 Sep 2007 11:00:25 +1000 Subject: [PATCH 0115/1490] gitk: Add progress bars for reading in stuff and for finding This uses the space formerly occupied by the find string entry field to make a status label (unused for now) and a canvas to display a couple of progress bars. The bar for reading in commits is a short green bar that oscillates back and forth as commits come in. The bar for showing the progress of a Find operation is yellow and advances from left to right. This also arranges to stop a Find operation if the user selects another commit or pops up a context menu, and fixes the "highlight this" popup menu items in the file list window. Signed-off-by: Paul Mackerras --- gitk | 186 ++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 153 insertions(+), 33 deletions(-) diff --git a/gitk b/gitk index 34fe33771f..4e168e98a0 100755 --- a/gitk +++ b/gitk @@ -84,6 +84,7 @@ proc start_rev_list {view} { global commfd leftover tclencoding datemode global viewargs viewfiles commitidx viewcomplete vnextroot global showlocalchanges commitinterest mainheadid + global progressdirn progresscoords proglastnc curview set startmsecs [clock clicks -milliseconds] set commitidx($view) 0 @@ -111,6 +112,11 @@ proc start_rev_list {view} { } filerun $fd [list getcommitlines $fd $view] nowbusy $view + if {$view == $curview} { + set progressdirn 1 + set progresscoords {0 0} + set proglastnc 0 + } } proc stop_rev_list {} { @@ -183,9 +189,11 @@ proc getcommitlines {fd view} { } } set viewcomplete($view) 1 - global viewname + global viewname progresscoords unset commfd($view) notbusy $view + set progresscoords {0 0} + adjustprogress # set it blocking so we wait for the process to terminate fconfigure $fd -blocking 1 if {[catch {close $fd} err]} { @@ -315,6 +323,33 @@ proc getcommitlines {fd view} { } if {$gotsome} { run chewcommits $view + if {$view == $curview} { + # update progress bar + global progressdirn progresscoords proglastnc + set inc [expr {($commitidx($view) - $proglastnc) * 0.0002}] + set proglastnc $commitidx($view) + set l [lindex $progresscoords 0] + set r [lindex $progresscoords 1] + if {$progressdirn} { + set r [expr {$r + $inc}] + if {$r >= 1.0} { + set r 1.0 + set progressdirn 0 + } + if {$r > 0.2} { + set l [expr {$r - 0.2}] + } + } else { + set l [expr {$l - $inc}] + if {$l <= 0.0} { + set l 0.0 + set progressdirn 1 + } + set r [expr {$l + 0.2}] + } + set progresscoords [list $l $r] + adjustprogress + } } return 2 } @@ -589,7 +624,8 @@ proc makewindow {} { global highlight_files gdttype global searchstring sstring global bgcolor fgcolor bglist fglist diffcolors selectbgcolor - global headctxmenu + global headctxmenu progresscanv progressitem progresscoords statusw + global fprogitem fprogcoord lastprogupdate progupdatepending menu .bar .bar add cascade -label "File" -menu .bar.file @@ -706,6 +742,22 @@ proc makewindow {} { -state disabled -width 26 pack .tf.bar.rightbut -side left -fill y + # Status label and progress bar + set statusw .tf.bar.status + label $statusw -width 15 -relief sunken -font $uifont + pack $statusw -side left -padx 5 + set h [expr {[font metrics $uifont -linespace] + 2}] + set progresscanv .tf.bar.progress + canvas $progresscanv -relief sunken -height $h -borderwidth 2 + set progressitem [$progresscanv create rect -1 0 0 $h -fill green] + set fprogitem [$progresscanv create rect -1 0 0 $h -fill yellow] + pack $progresscanv -side right -expand 1 -fill x + set progresscoords {0 0} + set fprogcoord 0 + bind $progresscanv adjustprogress + set lastprogupdate [clock clicks -milliseconds] + set progupdatepending 0 + # build up the bottom bar of upper window label .tf.lbar.flabel -text "Find " -font $uifont button .tf.lbar.fnext -text "next" -command dofind -font $uifont @@ -1051,6 +1103,37 @@ proc click {w} { focus . } +# Adjust the progress bar for a change in requested extent or canvas size +proc adjustprogress {} { + global progresscanv progressitem progresscoords + global fprogitem fprogcoord lastprogupdate progupdatepending + + set w [expr {[winfo width $progresscanv] - 4}] + set x0 [expr {$w * [lindex $progresscoords 0]}] + set x1 [expr {$w * [lindex $progresscoords 1]}] + set h [winfo height $progresscanv] + $progresscanv coords $progressitem $x0 0 $x1 $h + $progresscanv coords $fprogitem 0 0 [expr {$w * $fprogcoord}] $h + set now [clock clicks -milliseconds] + if {$now >= $lastprogupdate + 100} { + set progupdatepending 0 + update + } elseif {!$progupdatepending} { + set progupdatepending 1 + after [expr {$lastprogupdate + 100 - $now}] doprogupdate + } +} + +proc doprogupdate {} { + global lastprogupdate progupdatepending + + if {$progupdatepending} { + set progupdatepending 0 + set lastprogupdate [clock clicks -milliseconds] + update + } +} + proc savestuff {w} { global canv canv2 canv3 ctext cflist mainfont textfont uifont tabstop global stuffsaved findmergefiles maxgraphpct @@ -1626,6 +1709,7 @@ proc pop_flist_menu {w X Y x y} { global ctext cflist cmitmode flist_menu flist_menu_file global treediffs diffids + stopfinding set l [lindex [split [$w index "@$x,$y"] "."] 0] if {$l <= 1} return if {$cmitmode eq "tree"} { @@ -1639,14 +1723,15 @@ proc pop_flist_menu {w X Y x y} { } proc flist_hl {only} { - global flist_menu_file highlight_files + global flist_menu_file findstring gdttype set x [shellquote $flist_menu_file] - if {$only || $highlight_files eq {}} { - set highlight_files $x + if {$only || $findstring eq {} || $gdttype ne "touching paths:"} { + set findstring $x } else { - append highlight_files " " $x + append findstring " " $x } + set gdttype "touching paths:" } # Functions for adding and removing shell-type quoting @@ -2210,6 +2295,7 @@ proc hfiles_change {} { proc gdttype_change {name ix op} { global gdttype highlight_files findstring findpattern + stopfinding if {$findstring ne {}} { if {$gdttype eq "containing:"} { if {$highlight_files ne {}} { @@ -2233,6 +2319,7 @@ proc gdttype_change {name ix op} { proc find_change {name ix op} { global gdttype findstring highlight_files + stopfinding if {$gdttype eq "containing:"} { findcom_change } else { @@ -2248,6 +2335,7 @@ proc findcom_change {} { global nhighlights mainfont boldnamerows global findpattern findtype findstring gdttype + stopfinding # delete previous highlights, if any foreach row $boldnamerows { bolden_name $row $mainfont @@ -4174,6 +4262,18 @@ proc dofind {{rev 0}} { } } +proc stopfinding {} { + global find_dirn findcurline fprogcoord + + if {[info exists find_dirn]} { + unset find_dirn + unset findcurline + notbusy finding + set fprogcoord 0 + adjustprogress + } +} + proc findnext {restart} { global findcurline find_dirn @@ -4207,8 +4307,11 @@ proc findprev {} { proc findmore {} { global commitdata commitinfo numcommits findpattern findloc global findstartline findcurline displayorder - global find_dirn gdttype fhighlights + global find_dirn gdttype fhighlights fprogcoord + if {![info exists find_dirn]} { + return 0 + } set fldtypes {Headline Author Date Committer CDate Comments} set l [expr {$findcurline + 1}] if {$l >= $numcommits} { @@ -4258,32 +4361,41 @@ proc findmore {} { } } } - if {$found} { + if {$found || ($domore && $l == $findstartline + 1)} { + unset findcurline unset find_dirn - findselectline $l notbusy finding + set fprogcoord 0 + adjustprogress + if {$found} { + findselectline $l + } else { + bell + } return 0 } if {!$domore} { flushhighlights - return 0 + } else { + set findcurline [expr {$l - 1}] } - if {$l == $findstartline + 1} { - bell - unset findcurline - unset find_dirn - notbusy finding - return 0 + set n [expr {$findcurline - ($findstartline + 1)}] + if {$n < 0} { + incr n $numcommits } - set findcurline [expr {$l - 1}] - return 1 + set fprogcoord [expr {$n * 1.0 / $numcommits}] + adjustprogress + return $domore } proc findmorerev {} { global commitdata commitinfo numcommits findpattern findloc global findstartline findcurline displayorder - global find_dirn gdttype fhighlights + global find_dirn gdttype fhighlights fprogcoord + if {![info exists find_dirn]} { + return 0 + } set fldtypes {Headline Author Date Committer CDate Comments} set l $findcurline if {$l == 0} { @@ -4333,25 +4445,31 @@ proc findmorerev {} { } } } - if {$found} { + if {$found || ($domore && $l == $findstartline - 1)} { + unset findcurline unset find_dirn - findselectline $l notbusy finding + set fprogcoord 0 + adjustprogress + if {$found} { + findselectline $l + } else { + bell + } return 0 } if {!$domore} { flushhighlights - return 0 + } else { + set findcurline [expr {$l + 1}] } - if {$l == -1} { - bell - unset findcurline - unset find_dirn - notbusy finding - return 0 + set n [expr {($findstartline - 1) - $findcurline}] + if {$n < 0} { + incr n $numcommits } - set findcurline [expr {$l + 1}] - return 1 + set fprogcoord [expr {$n * 1.0 / $numcommits}] + adjustprogress + return $domore } proc findselectline {l} { @@ -4398,12 +4516,11 @@ proc markmatches {canv l str tag matches font row} { } proc unmarkmatches {} { - global findids markingmatches findcurline + global markingmatches allcanvs delete matches - catch {unset findids} set markingmatches 0 - catch {unset findcurline} + stopfinding } proc selcanvline {w x y} { @@ -4626,6 +4743,7 @@ proc selectline {l isnew} { $canv delete hover normalline unsel_reflist + stopfinding if {$l < 0 || $l >= $numcommits} return set y [expr {$canvy0 + $l * $linespc}] set ymax [lindex [$canv cget -scrollregion] 3] @@ -5815,6 +5933,7 @@ proc rowmenu {x y id} { global rowctxmenu commitrow selectedline rowmenuid curview global nullid nullid2 fakerowmenu mainhead + stopfinding set rowmenuid $id if {![info exists selectedline] || $commitrow($curview,$id) eq $selectedline} { @@ -6293,6 +6412,7 @@ proc readresetstat {fd w} { proc headmenu {x y id head} { global headmenuid headmenuhead headctxmenu mainhead + stopfinding set headmenuid $id set headmenuhead $head set state normal From 586801650824f0f7b62c34a206b6a60ffbcd8be0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Mon, 17 Sep 2007 20:06:44 -0400 Subject: [PATCH 0116/1490] Introduce entry point add_interactive and add_files_to_cache MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This refactors builtin-add.c a little to provide a unique entry point for launching git add --interactive, which will be used by builtin-commit too. If we later want to make add --interactive a builtin or change how it is launched, we just start from this function. It also exports the private function update() which is used to add all modified paths to the index as add_files_to_cache(). Signed-off-by: Kristian Høgsberg Signed-off-by: Junio C Hamano --- builtin-add.c | 23 ++++++++++++++--------- commit.h | 4 ++++ 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/builtin-add.c b/builtin-add.c index f9a65803d8..966e145038 100644 --- a/builtin-add.c +++ b/builtin-add.c @@ -12,6 +12,7 @@ #include "diffcore.h" #include "commit.h" #include "revision.h" +#include "run-command.h" static const char builtin_add_usage[] = "git-add [-n] [-v] [-f] [--interactive | -i] [-u] [--refresh] [--] ..."; @@ -106,7 +107,7 @@ static void update_callback(struct diff_queue_struct *q, } } -static void update(int verbose, const char *prefix, const char **files) +void add_files_to_cache(int verbose, const char *prefix, const char **files) { struct rev_info rev; init_revisions(&rev, prefix); @@ -115,8 +116,6 @@ static void update(int verbose, const char *prefix, const char **files) rev.diffopt.output_format = DIFF_FORMAT_CALLBACK; rev.diffopt.format_callback = update_callback; rev.diffopt.format_callback_data = &verbose; - if (read_cache() < 0) - die("index file corrupt"); run_diff_files(&rev, 0); } @@ -149,6 +148,13 @@ static int git_add_config(const char *var, const char *value) return git_default_config(var, value); } +int interactive_add(void) +{ + const char *argv[2] = { "add--interactive", NULL }; + + return run_command_v_opt(argv, RUN_GIT_CMD); +} + static struct lock_file lock_file; static const char ignore_error[] = @@ -168,12 +174,9 @@ int cmd_add(int argc, const char **argv, const char *prefix) add_interactive++; } if (add_interactive) { - const char *args[] = { "add--interactive", NULL }; - - if (add_interactive != 1 || argc != 2) + if (argc != 2) die("add --interactive does not take any parameters"); - execv_git_cmd(args); - exit(1); + exit(interactive_add()); } git_config(git_add_config); @@ -213,7 +216,9 @@ int cmd_add(int argc, const char **argv, const char *prefix) } if (take_worktree_changes) { - update(verbose, prefix, argv + i); + if (read_cache() < 0) + die("index file corrupt"); + add_files_to_cache(verbose, prefix, argv + i); goto finish; } diff --git a/commit.h b/commit.h index b779de8cbc..b50c30e255 100644 --- a/commit.h +++ b/commit.h @@ -128,4 +128,8 @@ extern struct commit_list *get_shallow_commits(struct object_array *heads, int depth, int shallow_flag, int not_shallow_flag); int in_merge_bases(struct commit *, struct commit **, int); + +extern int interactive_add(void); +extern void add_files_to_cache(int verbose, const char *prefix, const char **files); + #endif /* COMMIT_H */ From d8b7db0abfd0c74478964f5a9b08ad141f4f7f82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Mon, 17 Sep 2007 20:06:47 -0400 Subject: [PATCH 0117/1490] Export rerere() and launch_editor(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kristian Høgsberg Signed-off-by: Junio C Hamano --- builtin-rerere.c | 31 ++++++++++++++++++++++++++----- commit.h | 1 + 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/builtin-rerere.c b/builtin-rerere.c index b8206744c1..74493237c9 100644 --- a/builtin-rerere.c +++ b/builtin-rerere.c @@ -389,18 +389,39 @@ static int is_rerere_enabled(void) return 1; } -int cmd_rerere(int argc, const char **argv, const char *prefix) +static int setup_rerere(struct path_list *merge_rr) { - struct path_list merge_rr = { NULL, 0, 0, 1 }; - int i, fd = -1; + int fd; git_config(git_rerere_config); if (!is_rerere_enabled()) - return 0; + return -1; merge_rr_path = xstrdup(git_path("rr-cache/MERGE_RR")); fd = hold_lock_file_for_update(&write_lock, merge_rr_path, 1); - read_rr(&merge_rr); + read_rr(merge_rr); + return fd; +} + +int rerere(void) +{ + struct path_list merge_rr = { NULL, 0, 0, 1 }; + int fd; + + fd = setup_rerere(&merge_rr); + if (fd < 0) + return 0; + return do_plain_rerere(&merge_rr, fd); +} + +int cmd_rerere(int argc, const char **argv, const char *prefix) +{ + struct path_list merge_rr = { NULL, 0, 0, 1 }; + int i, fd; + + fd = setup_rerere(&merge_rr); + if (fd < 0) + return 0; if (argc < 2) return do_plain_rerere(&merge_rr, fd); diff --git a/commit.h b/commit.h index b50c30e255..b661503972 100644 --- a/commit.h +++ b/commit.h @@ -131,5 +131,6 @@ int in_merge_bases(struct commit *, struct commit **, int); extern int interactive_add(void); extern void add_files_to_cache(int verbose, const char *prefix, const char **files); +extern int rerere(void); #endif /* COMMIT_H */ From cbf13d9e0c4fc7ac4f2f52f88cff94f1fc311971 Mon Sep 17 00:00:00 2001 From: Michele Ballabio Date: Thu, 27 Sep 2007 14:53:25 +0200 Subject: [PATCH 0118/1490] git-gui: fix typo in lib/blame.tcl Signed-off-by: Michele Ballabio Signed-off-by: Shawn O. Pearce --- lib/blame.tcl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/blame.tcl b/lib/blame.tcl index a911c3c77d..00ecf21333 100644 --- a/lib/blame.tcl +++ b/lib/blame.tcl @@ -905,7 +905,7 @@ method _open_tooltip {cur_w} { set author_time {} catch {set author_name $header($cmit,author)} catch {set summary $header($cmit,summary)} - catch {set author_time [foramt_date $header($cmit,author-time)]} + catch {set author_time [format_date $header($cmit,author-time)]} $tooltip_t insert end [strcat [mc "Originally By:"] "\n"] section_header $tooltip_t insert end "commit $cmit\n" From 1bdd8a153528b539fdaed23c18e87a374b1f3ff8 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Thu, 27 Sep 2007 00:18:29 -0400 Subject: [PATCH 0119/1490] git-gui: Use Henrik Nyh's git logo icon on Windows systems Rather than displaying the stock red "Tk" icon in our window title bars and on the task bar we now show a Git specific logo. This is Henrik Nyh's logo that we also use in the startup wizard, scaled to a 16x16 image for Windows task bar usage with a proper transparent background. Signed-off-by: Shawn O. Pearce --- Makefile | 2 ++ git-gui.sh | 4 ++++ lib/git-gui.ico | Bin 0 -> 318 bytes 3 files changed, 6 insertions(+) create mode 100644 lib/git-gui.ico diff --git a/Makefile b/Makefile index 0ab33517a9..ea83263406 100644 --- a/Makefile +++ b/Makefile @@ -193,6 +193,7 @@ install: all $(QUIET)$(foreach p,$(GITGUI_BUILT_INS), $(INSTALL_L0)'$(DESTDIR_SQ)$(gitexecdir_SQ)/$p' $(INSTALL_L1)'$(DESTDIR_SQ)$(gitexecdir_SQ)/git-gui' $(INSTALL_L2)'$(DESTDIR_SQ)$(gitexecdir_SQ)/$p' $(INSTALL_L3) &&) true $(QUIET)$(INSTALL_D0)'$(DESTDIR_SQ)$(libdir_SQ)' $(INSTALL_D1) $(QUIET)$(INSTALL_R0)lib/tclIndex $(INSTALL_R1) '$(DESTDIR_SQ)$(libdir_SQ)' + $(QUIET)$(INSTALL_R0)lib/git-gui.ico $(INSTALL_R1) '$(DESTDIR_SQ)$(libdir_SQ)' $(QUIET)$(foreach p,$(ALL_LIBFILES), $(INSTALL_R0)$p $(INSTALL_R1) '$(DESTDIR_SQ)$(libdir_SQ)' &&) true $(QUIET)$(INSTALL_D0)'$(DESTDIR_SQ)$(msgsdir_SQ)' $(INSTALL_D1) $(QUIET)$(foreach p,$(ALL_MSGFILES), $(INSTALL_R0)$p $(INSTALL_R1) '$(DESTDIR_SQ)$(msgsdir_SQ)' &&) true @@ -203,6 +204,7 @@ uninstall: $(QUIET)$(foreach p,$(GITGUI_BUILT_INS), $(REMOVE_F0)'$(DESTDIR_SQ)$(gitexecdir_SQ)'/$p $(REMOVE_F1) &&) true $(QUIET)$(CLEAN_DST) '$(DESTDIR_SQ)$(libdir_SQ)' $(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(libdir_SQ)'/tclIndex $(REMOVE_F1) + $(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(libdir_SQ)'/git-gui.ico $(REMOVE_F1) $(QUIET)$(foreach p,$(ALL_LIBFILES), $(REMOVE_F0)'$(DESTDIR_SQ)$(libdir_SQ)'/$(notdir $p) $(REMOVE_F1) &&) true $(QUIET)$(CLEAN_DST) '$(DESTDIR_SQ)$(msgsdir_SQ)' $(QUIET)$(foreach p,$(ALL_MSGFILES), $(REMOVE_F0)'$(DESTDIR_SQ)$(msgsdir_SQ)'/$(notdir $p) $(REMOVE_F1) &&) true diff --git a/git-gui.sh b/git-gui.sh index 37da8fde3b..843191a896 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -527,6 +527,10 @@ bind . { set root_exists 1 } +if {[is_Windows]} { + wm iconbitmap . -default $oguilib/git-gui.ico +} + ###################################################################### ## ## config defaults diff --git a/lib/git-gui.ico b/lib/git-gui.ico new file mode 100644 index 0000000000000000000000000000000000000000..563dd66238c1a5c169438fdb87ab797f6d19d1bc GIT binary patch literal 318 zcmZ{aI}XAy5JV>uJ$7MQDAOPcghU60DUcAtknN#y8;J{W6>gFv&{A`PAPRmFV(kqb zS!;GYZx%@SDW!O~kS0I}K+00A9xL#s+3xo6-ebNzqCY-kQB0do|8gSInpZISaEic) zJMD~%z0r(_oRhmXtwN+BPw>r1oU&Pn^z+Qx2&}bPyiW4F7RUZ SE~I<%|8o#MxGM)hRp&1`Pe2d= literal 0 HcmV?d00001 From 72a8e81d457a1ee1283817d03d8e28303c2b4e7e Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Thu, 27 Sep 2007 02:30:51 -0400 Subject: [PATCH 0120/1490] git-gui: Support a native Mac OS X application bundle If we are building on Darwin (sometimes known as Mac OS X) and we find the Mac OS X Tk.framework in the expected location we build a proper Mac OS X application bundle with icons and info list. The git-gui and git-citool commands are modified to be very short shell scripts that just execute the application bundle, starting Tk with our own info list and icon set. Although the Makefile change here is rather large it makes for a much more pleasant user experience on Mac OS X as git-gui now has its own icon on the dock, in the standard tk_messageBox dialogs, and the application name now says "Git Gui" instead of "Wish" in locations such as the menu bar and the alt-tab window. Signed-off-by: Shawn O. Pearce --- .gitignore | 4 +- Makefile | 96 +++++++++++++++++++++++++++++++++++--------- macosx/AppMain.tcl | 22 ++++++++++ macosx/Info.plist | 28 +++++++++++++ macosx/git-gui.icns | Bin 0 -> 28866 bytes 5 files changed, 129 insertions(+), 21 deletions(-) create mode 100644 macosx/AppMain.tcl create mode 100644 macosx/Info.plist create mode 100644 macosx/git-gui.icns diff --git a/.gitignore b/.gitignore index 020b86deae..a7cfd6d5a0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ +.DS_Store +Git Gui.app* +git-gui.tcl GIT-VERSION-FILE GIT-GUI-VARS -git-citool git-gui lib/tclIndex diff --git a/Makefile b/Makefile index ea83263406..818a0ab45c 100644 --- a/Makefile +++ b/Makefile @@ -11,11 +11,12 @@ GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE @$(SHELL_PATH) ./GIT-VERSION-GEN -include GIT-VERSION-FILE +uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not') uname_O := $(shell sh -c 'uname -o 2>/dev/null || echo not') SCRIPT_SH = git-gui.sh +GITGUI_MAIN := git-gui GITGUI_BUILT_INS = git-citool -ALL_PROGRAMS = $(GITGUI_BUILT_INS) $(patsubst %.sh,%,$(SCRIPT_SH)) ALL_LIBFILES = $(wildcard lib/*.tcl) PRELOAD_FILES = lib/class.tcl @@ -35,7 +36,7 @@ ifndef INSTALL INSTALL = install endif -RM_F ?= rm -f +RM_RF ?= rm -rf RMDIR ?= rmdir INSTALL_D0 = $(INSTALL) -d -m755 # space is required here @@ -44,6 +45,8 @@ INSTALL_R0 = $(INSTALL) -m644 # space is required here INSTALL_R1 = INSTALL_X0 = $(INSTALL) -m755 # space is required here INSTALL_X1 = +INSTALL_A0 = find # space is required here +INSTALL_A1 = | cpio -pud INSTALL_L0 = rm -f # space is required here INSTALL_L1 = && ln # space is required here INSTALL_L2 = @@ -51,14 +54,13 @@ INSTALL_L3 = REMOVE_D0 = $(RMDIR) # space is required here REMOVE_D1 = || true -REMOVE_F0 = $(RM_F) # space is required here +REMOVE_F0 = $(RM_RF) # space is required here REMOVE_F1 = CLEAN_DST = true ifndef V QUIET = @ - QUIET_GEN = $(QUIET)echo ' ' GEN $@ && - QUIET_BUILT_IN = $(QUIET)echo ' ' BUILTIN $@ && + QUIET_GEN = $(QUIET)echo ' ' GEN '$@' && QUIET_INDEX = $(QUIET)echo ' ' INDEX $(dir $@) && QUIET_MSGFMT0 = $(QUIET)printf ' MSGFMT %12s ' $@ && v=` QUIET_MSGFMT1 = 2>&1` && echo "$$v" | sed -e 's/fuzzy translations/fuzzy/' | sed -e 's/ messages//g' @@ -70,6 +72,8 @@ ifndef V INSTALL_R1 = && echo ' ' INSTALL 644 `basename $$src` && $(INSTALL) -m644 $$src INSTALL_X0 = src= INSTALL_X1 = && echo ' ' INSTALL 755 `basename $$src` && $(INSTALL) -m755 $$src + INSTALL_A0 = src= + INSTALL_A1 = && echo ' ' INSTALL ' ' `basename "$$src"` && find "$$src" | cpio -pud INSTALL_L0 = dst= INSTALL_L1 = && src= @@ -80,15 +84,15 @@ ifndef V REMOVE_D0 = dir= REMOVE_D1 = && echo ' ' REMOVE $$dir && test -d "$$dir" && $(RMDIR) "$$dir" || true REMOVE_F0 = dst= - REMOVE_F1 = && echo ' ' REMOVE `basename "$$dst"` && $(RM_F) "$$dst" + REMOVE_F1 = && echo ' ' REMOVE `basename "$$dst"` && $(RM_RF) "$$dst" endif TCL_PATH ?= tclsh TCLTK_PATH ?= wish +TKFRAMEWORK = /Library/Frameworks/Tk.framework/Resources/Wish.app ifeq ($(findstring $(MAKEFLAGS),s),s) QUIET_GEN = -QUIET_BUILT_IN = endif DESTDIR_SQ = $(subst ','\'',$(DESTDIR)) @@ -105,6 +109,7 @@ exedir = $(dir $(gitexecdir))share/git-gui/lib GITGUI_SCRIPT := $$0 GITGUI_RELATIVE := +GITGUI_MACOSXAPP := ifeq ($(exedir),$(gg_libdir)) GITGUI_RELATIVE := 1 @@ -116,8 +121,51 @@ ifeq ($(uname_O),Cygwin) gg_libdir := $(shell cygpath --windows --absolute "$(gg_libdir)") endif endif +ifeq ($(uname_S),Darwin) + ifeq ($(shell test -d $(TKFRAMEWORK) && echo y),y) + GITGUI_MACOSXAPP := YesPlease + endif +endif -$(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh +ifdef GITGUI_MACOSXAPP +GITGUI_MAIN := git-gui.tcl + +git-gui: GIT-VERSION-FILE GIT-GUI-VARS + $(QUIET_GEN)rm -f $@ $@+ && \ + echo '#!$(SHELL_PATH_SQ)' >$@+ && \ + echo 'if test "z$$*" = zversion ||' >>$@+ && \ + echo ' test "z$$*" = z--version' >>$@+ && \ + echo then >>$@+ && \ + echo ' 'echo \'git-gui version '$(GITGUI_VERSION)'\' >>$@+ && \ + echo else >>$@+ && \ + echo ' 'exec \''$(libdir_SQ)/Git Gui.app/Contents/MacOS/Wish'\' \ + '"$$0" "$$@"' >>$@+ && \ + echo fi >>$@+ && \ + chmod +x $@+ && \ + mv $@+ $@ + +Git\ Gui.app: GIT-VERSION-FILE GIT-GUI-VARS \ + macosx/Info.plist \ + macosx/git-gui.icns \ + macosx/AppMain.tcl \ + $(TKFRAMEWORK)/Contents/MacOS/Wish + $(QUIET_GEN)rm -rf '$@' '$@'+ && \ + mkdir -p '$@'+/Contents/MacOS && \ + mkdir -p '$@'+/Contents/Resources/Scripts && \ + cp '$(subst ','\'',$(TKFRAMEWORK))/Contents/MacOS/Wish' \ + '$@'+/Contents/MacOS && \ + cp macosx/git-gui.icns '$@'+/Contents/Resources && \ + sed -e 's/@@GITGUI_VERSION@@/$(GITGUI_VERSION)/g' \ + macosx/Info.plist \ + >'$@'+/Contents/Info.plist && \ + sed -e 's|@@gitexecdir@@|$(gitexecdir_SQ)|' \ + -e 's|@@GITGUI_LIBDIR@@|$(libdir_SED)|' \ + macosx/AppMain.tcl \ + >'$@'+/Contents/Resources/Scripts/AppMain.tcl && \ + mv '$@'+ '$@' +endif + +$(GITGUI_MAIN): git-gui.sh GIT-VERSION-FILE GIT-GUI-VARS $(QUIET_GEN)rm -f $@ $@+ && \ sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \ -e '1,30s|^ argv0=$$0| argv0=$(GITGUI_SCRIPT)|' \ @@ -125,13 +173,10 @@ $(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh -e 's/@@GITGUI_VERSION@@/$(GITGUI_VERSION)/g' \ -e 's|@@GITGUI_RELATIVE@@|$(GITGUI_RELATIVE)|' \ -e '$(GITGUI_RELATIVE)s|@@GITGUI_LIBDIR@@|$(libdir_SED)|' \ - $@.sh >$@+ && \ + git-gui.sh >$@+ && \ chmod +x $@+ && \ mv $@+ $@ -$(GITGUI_BUILT_INS): git-gui - $(QUIET_BUILT_IN)rm -f $@ && ln git-gui $@ - XGETTEXT ?= xgettext ifdef NO_MSGFMT MSGFMT ?= $(TCL_PATH) po/po2msg.sh @@ -152,7 +197,7 @@ update-po:: $(PO_TEMPLATE) $(ALL_MSGFILES): %.msg : %.po $(QUIET_MSGFMT0)$(MSGFMT) --statistics --tcl $< -l $(basename $(notdir $<)) -d $(dir $@) $(QUIET_MSGFMT1) -lib/tclIndex: $(ALL_LIBFILES) +lib/tclIndex: $(ALL_LIBFILES) GIT-GUI-VARS $(QUIET_INDEX)if echo \ $(foreach p,$(PRELOAD_FILES),source $p\;) \ auto_mkindex lib '*.tcl' \ @@ -166,16 +211,13 @@ lib/tclIndex: $(ALL_LIBFILES) echo >>$@ ; \ fi -# These can record GITGUI_VERSION -$(patsubst %.sh,%,$(SCRIPT_SH)): GIT-VERSION-FILE GIT-GUI-VARS -lib/tclIndex: GIT-GUI-VARS - TRACK_VARS = \ $(subst ','\'',SHELL_PATH='$(SHELL_PATH_SQ)') \ $(subst ','\'',TCL_PATH='$(TCL_PATH_SQ)') \ $(subst ','\'',TCLTK_PATH='$(TCLTK_PATH_SQ)') \ $(subst ','\'',gitexecdir='$(gitexecdir_SQ)') \ $(subst ','\'',gg_libdir='$(libdir_SQ)') \ + GITGUI_MACOSXAPP=$(GITGUI_MACOSXAPP) \ #end TRACK_VARS GIT-GUI-VARS: .FORCE-GIT-GUI-VARS @@ -185,7 +227,10 @@ GIT-GUI-VARS: .FORCE-GIT-GUI-VARS echo 1>$@ "$$VARS"; \ fi -all:: $(ALL_PROGRAMS) lib/tclIndex $(ALL_MSGFILES) +ifdef GITGUI_MACOSXAPP +all:: git-gui Git\ Gui.app +endif +all:: $(GITGUI_MAIN) lib/tclIndex $(ALL_MSGFILES) install: all $(QUIET)$(INSTALL_D0)'$(DESTDIR_SQ)$(gitexecdir_SQ)' $(INSTALL_D1) @@ -194,6 +239,10 @@ install: all $(QUIET)$(INSTALL_D0)'$(DESTDIR_SQ)$(libdir_SQ)' $(INSTALL_D1) $(QUIET)$(INSTALL_R0)lib/tclIndex $(INSTALL_R1) '$(DESTDIR_SQ)$(libdir_SQ)' $(QUIET)$(INSTALL_R0)lib/git-gui.ico $(INSTALL_R1) '$(DESTDIR_SQ)$(libdir_SQ)' +ifdef GITGUI_MACOSXAPP + $(QUIET)$(INSTALL_A0)'Git Gui.app' $(INSTALL_A1) '$(DESTDIR_SQ)$(libdir_SQ)' + $(QUIET)$(INSTALL_X0)git-gui.tcl $(INSTALL_X1) '$(DESTDIR_SQ)$(libdir_SQ)' +endif $(QUIET)$(foreach p,$(ALL_LIBFILES), $(INSTALL_R0)$p $(INSTALL_R1) '$(DESTDIR_SQ)$(libdir_SQ)' &&) true $(QUIET)$(INSTALL_D0)'$(DESTDIR_SQ)$(msgsdir_SQ)' $(INSTALL_D1) $(QUIET)$(foreach p,$(ALL_MSGFILES), $(INSTALL_R0)$p $(INSTALL_R1) '$(DESTDIR_SQ)$(msgsdir_SQ)' &&) true @@ -205,6 +254,10 @@ uninstall: $(QUIET)$(CLEAN_DST) '$(DESTDIR_SQ)$(libdir_SQ)' $(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(libdir_SQ)'/tclIndex $(REMOVE_F1) $(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(libdir_SQ)'/git-gui.ico $(REMOVE_F1) +ifdef GITGUI_MACOSXAPP + $(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(libdir_SQ)/Git Gui.app' $(REMOVE_F1) + $(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(libdir_SQ)'/git-gui.tcl $(REMOVE_F1) +endif $(QUIET)$(foreach p,$(ALL_LIBFILES), $(REMOVE_F0)'$(DESTDIR_SQ)$(libdir_SQ)'/$(notdir $p) $(REMOVE_F1) &&) true $(QUIET)$(CLEAN_DST) '$(DESTDIR_SQ)$(msgsdir_SQ)' $(QUIET)$(foreach p,$(ALL_MSGFILES), $(REMOVE_F0)'$(DESTDIR_SQ)$(msgsdir_SQ)'/$(notdir $p) $(REMOVE_F1) &&) true @@ -218,8 +271,11 @@ dist-version: @echo $(GITGUI_VERSION) > $(TARDIR)/version clean:: - rm -f $(ALL_PROGRAMS) lib/tclIndex po/*.msg - rm -f GIT-VERSION-FILE GIT-GUI-VARS + $(RM_RF) $(GITGUI_MAIN) lib/tclIndex po/*.msg + $(RM_RF) GIT-VERSION-FILE GIT-GUI-VARS +ifdef GITGUI_MACOSXAPP + $(RM_RF) 'Git Gui.app'* git-gui +endif .PHONY: all install uninstall dist-version clean .PHONY: .FORCE-GIT-VERSION-FILE diff --git a/macosx/AppMain.tcl b/macosx/AppMain.tcl new file mode 100644 index 0000000000..41ca08e2b7 --- /dev/null +++ b/macosx/AppMain.tcl @@ -0,0 +1,22 @@ +set gitexecdir {@@gitexecdir@@} +set gitguilib {@@GITGUI_LIBDIR@@} +set env(PATH) "$gitexecdir:$env(PATH)" + +if {[string first -psn [lindex $argv 0]] == 0} { + lset argv 0 [file join $gitexecdir git-gui] +} + +if {[file tail [lindex $argv 0]] eq {gitk}} { + set argv0 [file join $gitexecdir gitk] + set AppMain_source $argv0 +} else { + set argv0 [file join $gitexecdir [file tail [lindex $argv 0]]] + set AppMain_source [file join $gitguilib git-gui.tcl] + if {[pwd] eq {/}} { + cd $env(HOME) + } +} + +unset gitexecdir gitguilib +set argv [lrange $argv 1 end] +source $AppMain_source diff --git a/macosx/Info.plist b/macosx/Info.plist new file mode 100644 index 0000000000..99913ec57a --- /dev/null +++ b/macosx/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + Wish + CFBundleGetInfoString + Git Gui @@GITGUI_VERSION@@ © 2006-2007 Shawn Pearce, et. al. + CFBundleIconFile + git-gui.icns + CFBundleIdentifier + cz.or.repo.git-gui + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + Git Gui + CFBundlePackageType + APPL + CFBundleShortVersionString + @@GITGUI_VERSION@@ + CFBundleSignature + GITg + CFBundleVersion + @@GITGUI_VERSION@@ + + diff --git a/macosx/git-gui.icns b/macosx/git-gui.icns new file mode 100644 index 0000000000000000000000000000000000000000..77d88a77a7669667335cf6fd5767c8b40f3ce6e7 GIT binary patch literal 28866 zcmeHP4O~>^nt#p=2y%5T_jlc}63a@{yjiYES8sx8l*`r3bSS{u2t2L5Yu9oH5|2gx)IfpX?!;ILidHnHy zJYWCk{W$M=&wHGspO!k4D1E1X+RQ#g^f+hajNLADyWq;{LKteUe_;(SzAIPC^)m-Q zNW>k@C5<`e$pSIWqwoQvMm-u6GiuaRW(uD^c5Hl1?AWnW^ISUFlT-7ER+)RyI5W{^ zb3KJvNL%=@*=+1Zi74Kkw)TLL(Oe6K&Cy33U~jWCa1_Dz(LuJgBo*aYcATOkXdOej zA}!+qq93MbLcP0=84OG}XaR*z&reCoOE(chTUC7?p&>NSG2oHX$J+Ul1bn{`y>mRb!5(Q3&e=^FSJcutwL^7{8|b0v*=OXv1`jX*lKw zD3U+mC^%DD{dT*(iN9*M?{W%z*42H;U#hFCXf~1QgWY}8D-z*u2mQs#>diaoh_lZ9 zrpJR1>U6sCE|dHJw`@LC{>LT%@Y0L(`DH(*JL{3Wk>>H;%Fj9LQT$8PIg(cL&bsz& z!|yP>7d~~?>G^BC-Om3s(N(9oZB6I5KPFb6cyuhT5%hz02g&|;o;c?pA(zPnU5Q-K z6R9)uKj3d3{(ibf^v!2PjfaS9+)G?T7*Rtvq6_%D5=E2^x$rmQ3Q@NUUj26jzCJ~` z#zU+HM8l0Sl(f=AzLcoHX$-|dXB6@oR`i55hNepLH6}(=ARmML&(K%(w~CA_h==qp zYau-c>nYZHic`stT6fcwB@~i)D1pk&MfBxj3N@7K7$Xa#l10Q-6y-1yDrJj^F6J;U zld!C08W~qL*h*m|W->N=RRwsVeFy7VVihnNp-^WOSg~}3v87fDS;p8)%t+x$Ot+2d z7)!E}R^a7O=m#G?LR4a8&?;way1_y;U8sfDCNZ`Pi<8#O*i3*I19M|t4#s;W06su$ znR;O8X3U$Hrh_bH+hU@qe8weBUIN){3*%uO! zK_%~R%_jS=Y6NB*`2zIV0BbyDNb;{tb0`J!$;h`uU)2x% zzhbPU0g%U9pQO34f7?2c9#zRFf_K-iX9QBjdsB$>-sD(XX)x{xCC;*1cKzfJ)eF=B z{0m|U7qN_D9Je!fS}v0kwI=VoMxb|KUoV!hnyJwBYo7z`x5>%LF)Fx3eG26?MWNMN z`}~!6>LI6pQs4{K{xA2UlJ^{x+Cm=o+BN=h`q4Q;%JCs>B_z%AwMzSB!Em%-{|O5D zp$d7(NuK|BgjSIEe)>E9%I_8OJ}|lqJjkPH4$r@%kfVQ&3#`lhPq)%tJb&4P{O+Lx ziEe{4h5QegnAlu6D6XZv>;LgQHk2Z9yLkSjv+T~+!^S2=NPX6!h+B}H?!5%=wNnQV ze(@6uO}EOWs6C6Ox#;r0wGb1H{>UZ%_+b?>HXf7K965XXNZG%;8v-@`v?T1!G>>D0 z)F4=SO{35YxVw5tyYal>!m9@X0xF`WCqE9pL(`eg6mYq3g;Xo1VXkxsynQR+cH4DI zNOMmK5#}~Fr#Ur3*~q!mZbmK2-FAp69?^)x#CWtk4{u0~z;et0Ve<&%D?;kMU82-` zi+<7lqfZj{wqcX-Omf5&LnUuI^3~2-7`HBBIdQevy@u*Csw(Jk4$}>vjSE^bKa zgrP$>!CNzTTp@N)qK@EkM*(p|3}Uqr$Z3fSiQ9v?DHCC4&ljEx%7v%=+9bh!G0qZ9 zOp|fef|G;3dy*keT!f}4XPX(N8y9m{gPCzlMxgNh5VQ^SJvHpjQS$Fd>{#wh6xZ>hz67mBW|Gl<&TJ0r2 zX{n_7(9b|V8}?Ehw_gcR{Liutq$zF4D{K>~I=H(1JXg0Q z@hPoyIH^!PFHn+-M4jc(PgEDGa686-z~dR?JPF->OzfW%uIdXaO%zyDMYWd6+_RWWYk5{|ndEz^Prn&7~D|8(o(9Nx>MU7Xdz8(z!(dUn^ z@prjHoo@2bKTftrgQv_}dNxy-H~mh}yz`e3n$YxZGbMY`pM-1uR5;C*Ud5iSUxe}e z_fTxR{zT!?T&aIm?`z4K{7y{rf1 zVteoB{`CwvpZD}&fWr=+uN8aSp-=SO5AcAum#Xxvpr0a&T>269VC_}acCMd}^N2L4 zUA+f-6@rh}^~2*QOc*ApwW|L|nKSNPFaE{&7s&K)`O1ra&#MrA(O+s{5=O-RW=kqT zS@So+*{4D?9i({}XFp!fO%nwv-#|qoUG@udp8xU8rcIkRep1VF=m@o?Z!inZqk{05xD75+W%JVd-I!;#)$_%dU93+>wsNJkP=02{vdLmQp zG*Mx5Q_S3|D*NfGs=U#7d8Z`(Ea7zF=6Hc$Ni?o7hE|-vLHS2iTuO0>;6+<0g;deD z7-E4-ix-Q&6Ksp=%tsyH!mPrnbcQG4-yzzzl=Ns>Jv|rjG?jjEpzySpj0seWSNNs7 z*1XJ_pFBXCNc$O_aM&Ko#c02ZmyY|vy2+f&aJ+{TOM&xO(kzck!wX3_2d{rG=I2Qm zdx-YqG{&v48*eTPB=udS8S!zFoI_`=5{(+t3~toRIh48Bsj-%E%kSJloWbVetYS3G zm`7V{h(0KCYJoSXmN-jRGlMh4?IN<{#3O5((4Ksz-DeoQ5IB~dM21C7^V+2c%%ULl zAkooFI0vD3YlwSaSHQHXIgQa+-e5%sb4ar~Cv_p-h$dGPl@%~9IboqwmP=ehGTOg! zJ8_Frpff!Vht8rIeBTGjyzNAB5Ev%okjE+DVzcq?RG(QTiYOZ|#YBmPxXUvESq4ER zY#Utygt8G9mXd9RD5dO1sKsp~q{s2zR`jxfxQHxx*(2RomspqiROa4{d>t>6bpo~!{OhnTK$$WT^oyvO#TxpE{`4Ag>8Y-&CUIZs ztC+BF!K!H+ag*nuQ1dGOV@V;}j4r}ZXcCVMUQJwN8b&2Cp^CWBLosnNlmyD@P&_54g`ebgxTk&1QtunmFIMec4qWbr6KDV2=lAL!LR~fknM~%5} zGpgN(L&*6X7`NWAA20Z`-(qy2j<~+2b&S>@B2DeG^f#Esc+hZ|xV%lTGmW8s?orYj zEJbN+nIf$&@E*l$%f;bhI~$%t!1kgG3~svGRs+_(%d+0 zDq}^taa3L@tlv$A)wCb$_YKLhe&gLfBDlxaKsRA!tEM4=ON%$q$MD?~r+)8a{qE=% zCKmRh_ucFF06LA9Mbk3@PjTl9uHV7++p(<6mt|F6aQ*%zt>4cV##1HM?;Db1{jQ>k zh+w9zN?f_)=}%bS0+bf7qo?6J&9;uZWBu;v7A`8xpziMVyNPnqvVp>uBEV@j9SW}B z!S!2ptroZHiZwmBe*a?D?^)tIrI>K#8A}`M;_+AWageuT**1FgO)ZGu-1#U4``@?e zb1?Qin2ZGn%^|{PEdi}Lue|Z%$x^DMbj{^`CbVv`} z?;qXnZ;+BTu02J+_n++nmDmLF{hR=jzHCo1*#E))_p1lmGwCEY!TIM`@89_I2gz8r zr|9?iPxg-<^0WJc=D{A2_W;+cSFf&4R=D|)ciQ>Sa$~=15r%YJh8vu}WGZU)lJxuf zlSLfy!cGU`9S-()9g5%M*|RRZ8-br(qS+-M?f*7#)umO{#(z;){pj8!Zx%E|EZB9N2>gW)Atw( zTEMqy{!R29N!6mC@Uv$HwWa^<<5b=G%rq#lQ9brA4lmO6-x&7vR=MWYem-NV8QA4s zdA?NtJExu$e;!dMeVt4fA7%2N76~81Yo;&v_U!C-s=&v`koSJstjb@tb#be)M4WH5w;%XIFf1Pz^uI`MY(| z?z_=aU+pQ&@b@b`sNvI{CnX{Kz5kMJ@%pp{pKKERn%fj6zE&l^c)o4;eWW(>3F9le z{Q37KPGPUw{}k!?lyUbbKLZmKSwrua$_J`&=EZrv_# zzTf*Vd?7{d@uyi{;AicYEAs)se?;N(+K&^RkAKQQqOHOgqoiclD0O_V50^T0l=qaB zM73}y*4v{eOD!rEd82#jYZ+_3d_ zyKIN=M*qhC(y&`RTLw_FaP5D&QJsalwQB=&-rBY>!^eq)y>_LebWhvtT4?=06H+3y literal 0 HcmV?d00001 From 0b2bc460fc69d2aa4f5af743b2b2317088e53949 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Thu, 27 Sep 2007 02:15:29 -0400 Subject: [PATCH 0121/1490] git-gui: Refer to ourselves as "Git Gui" and not "git-gui" When displaying the name of the application in window titles and menu options (e.g. "About [appname]") we would prefer to call ourselves "Git Gui" over "git-gui" as the former name is now being actively used in the Mac OS X UI strings and just plain looks better to the reader. Signed-off-by: Shawn O. Pearce --- git-gui.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/git-gui.sh b/git-gui.sh index 843191a896..82f873bdcd 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -108,7 +108,7 @@ unset oguimsg ## ## read only globals -set _appname [lindex [file split $argv0] end] +set _appname {Git Gui} set _gitdir {} set _gitexec {} set _reponame {} @@ -789,7 +789,7 @@ unset -nocomplain idx fd ## ## feature option selection -if {[regexp {^git-(.+)$} [appname] _junk subcommand]} { +if {[regexp {^git-(.+)$} [file tail $argv0] _junk subcommand]} { unset _junk } else { set subcommand gui @@ -2140,7 +2140,8 @@ citool - gui { if {[llength $argv] != 0} { puts -nonewline stderr "usage: $argv0" - if {$subcommand ne {gui} && [appname] ne "git-$subcommand"} { + if {$subcommand ne {gui} + && [file tail $argv0] ne "git-$subcommand"} { puts -nonewline stderr " $subcommand" } puts stderr {} From 32f1b3e4a4baa3fe3e1acbb75f8134d822a09d58 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Fri, 28 Sep 2007 21:27:39 +1000 Subject: [PATCH 0122/1490] gitk: Fix the tab setting in the diff display window This fixes the bug where we were using the wrong font to calculate the width of the tab stops in the diff display window. If we're running on Tk 8.5 we also use the new -tabstyle wordprocessor option that makes tabs work as expected, i.e. a tab moves the cursor to the right until the next tab stop is reached. On Tk 8.5 we also get fancy and set the first tab stop at column 1 for a normal diff or column N for a merge diff with N parents. On Tk8.4 we can't do that because the tabs work in the "tabular" style, i.e. the nth tab character moves to the location of the nth tab position, *unless* you ask for the default tab setting, which gives 8-column tabs that work in the "wordprocessor" mode. So on Tk8.4 if the tab setting is 8 we ask for default tabs. This means that a tab setting of 7 or 9 can look quite different to 8 in some cases. Signed-off-by: Paul Mackerras --- gitk | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/gitk b/gitk index 4e168e98a0..01f5926916 100755 --- a/gitk +++ b/gitk @@ -626,6 +626,7 @@ proc makewindow {} { global bgcolor fgcolor bglist fglist diffcolors selectbgcolor global headctxmenu progresscanv progressitem progresscoords statusw global fprogitem fprogcoord lastprogupdate progupdatepending + global have_tk85 menu .bar .bar add cascade -label "File" -menu .bar.file @@ -845,9 +846,11 @@ proc makewindow {} { pack .bleft.mid.labeldiffcontext .bleft.mid.diffcontext -side left set ctext .bleft.ctext text $ctext -background $bgcolor -foreground $fgcolor \ - -tabs "[expr {$tabstop * $charspc}]" \ -state disabled -font $textfont \ -yscrollcommand scrolltext -wrap none + if {$have_tk85} { + $ctext conf -tabstyle wordprocessor + } scrollbar .bleft.sb -command "$ctext yview" pack .bleft.top -side top -fill x pack .bleft.mid -side top -fill x @@ -1135,7 +1138,7 @@ proc doprogupdate {} { } proc savestuff {w} { - global canv canv2 canv3 ctext cflist mainfont textfont uifont tabstop + global canv canv2 canv3 mainfont textfont uifont tabstop global stuffsaved findmergefiles maxgraphpct global maxwidth showneartags showlocalchanges global viewname viewfiles viewargs viewperm nextviewnum @@ -5092,6 +5095,7 @@ proc showfile {f} { $ctext insert end "$f\n" filesep $ctext config -state disabled $ctext yview $commentend + settabs 0 } proc getblobline {bf id} { @@ -5133,6 +5137,7 @@ proc mergediff {id l} { fconfigure $mdf -blocking 0 set mdifffd($id) $mdf set np [llength [lindex $parentlist $l]] + settabs $np filerun $mdf [list getmergediffline $mdf $id $np] } @@ -5210,6 +5215,7 @@ proc getmergediffline {mdf id np} { proc startdiff {ids} { global treediffs diffids treepending diffmergeid nullid nullid2 + settabs 1 set diffids $ids catch {unset diffmergeid} if {![info exists treediffs($ids)] || @@ -5515,6 +5521,23 @@ proc clear_ctext {{first 1.0}} { } } +proc settabs {{firstab {}}} { + global firsttabstop tabstop textfont ctext have_tk85 + + if {$firstab ne {} && $have_tk85} { + set firsttabstop $firstab + } + set w [font measure $textfont "0"] + if {$firsttabstop != 0} { + $ctext conf -tabs [list [expr {$firsttabstop * $w}] \ + [expr {($firsttabstop + $tabstop) * $w}]] + } elseif {$have_tk85 || $tabstop != 8} { + $ctext conf -tabs [expr {$tabstop * $w}] + } else { + $ctext conf -tabs {} + } +} + proc incrsearch {name ix op} { global ctext searchstring searchdirn @@ -5666,13 +5689,12 @@ proc redisplay {} { proc incrfont {inc} { global mainfont textfont ctext canv phase cflist showrefstop - global charspc tabstop global stopped entries unmarkmatches set mainfont [lreplace $mainfont 1 1 [expr {[lindex $mainfont 1] + $inc}]] set textfont [lreplace $textfont 1 1 [expr {[lindex $textfont 1] + $inc}]] setcoords - $ctext conf -font $textfont -tabs "[expr {$tabstop * $charspc}]" + settabs $cflist conf -font $textfont $ctext tag conf filesep -font [concat $textfont bold] foreach e $entries { @@ -5876,6 +5898,7 @@ proc lineclick {x y id isnew} { # fill the details pane with info about this line $ctext conf -state normal clear_ctext + settabs 0 $ctext insert end "Parent:\t" $ctext insert end $id link0 setlink $id link0 @@ -7780,6 +7803,7 @@ proc showtag {tag isnew} { } $ctext conf -state normal clear_ctext + settabs 0 set linknum 0 if {![info exists tagcontents($tag)]} { catch { @@ -7951,11 +7975,10 @@ proc prefscan {} { proc prefsok {} { global maxwidth maxgraphpct global oldprefs prefstop showneartags showlocalchanges - global charspc ctext tabstop catch {destroy $prefstop} unset prefstop - $ctext configure -tabs "[expr {$tabstop * $charspc}]" + settabs if {$showlocalchanges != $oldprefs(showlocalchanges)} { if {$showlocalchanges} { doshowlocalchanges @@ -8360,6 +8383,7 @@ if {$i >= [llength $argv] && $revtreeargs ne {}} { set nullid "0000000000000000000000000000000000000000" set nullid2 "0000000000000000000000000000000000000001" +set have_tk85 [expr {[package vcompare $tk_version "8.5"] >= 0}] set runq {} set history {} @@ -8376,6 +8400,7 @@ set markingmatches 0 set linkentercount 0 set need_redisplay 0 set nrows_drawn 0 +set firsttabstop 0 set nextviewnum 1 set curview 0 From 1f088191015968436e7cc6423827b0c26f3427ea Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 29 Sep 2007 20:45:33 -0700 Subject: [PATCH 0123/1490] git-am: make the output quieter. We used to say "Applying ", "Wrote ", and "Committed ". Worse yet, with extra blank lines around them. Make the output more concise. The object names are not so useful nor interesting. Signed-off-by: Junio C Hamano --- git-am.sh | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/git-am.sh b/git-am.sh index 32c46d7ed4..77a0e20996 100755 --- a/git-am.sh +++ b/git-am.sh @@ -394,9 +394,7 @@ do stop_here $this fi - echo printf 'Applying %s\n' "$SUBJECT" - echo case "$resolved" in '') @@ -452,12 +450,10 @@ do fi tree=$(git write-tree) && - echo Wrote tree $tree && parent=$(git rev-parse --verify HEAD) && commit=$(git commit-tree $tree -p $parent <"$dotest/final-commit") && - echo Committed: $commit && git update-ref -m "$GIT_REFLOG_ACTION: $SUBJECT" HEAD $commit $parent || - stop_here $this + stop_here $thisy if test -x "$GIT_DIR"/hooks/post-applypatch then From cfb8f898a883e2fb2fd5ecec0fe83662b64f1373 Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Fri, 28 Sep 2007 19:34:17 -0400 Subject: [PATCH 0124/1490] Allow abbreviations in the first refspec to be merged The config item for a refspec side and the ref name that it matches aren't necessarily character-for-character identical. We actually want to merge a ref by default if: there is no per-branch config, it is the found result of looking for the match for the first refspec, and the first refspec is not a pattern. Beyond that, anything that get_fetch_map() thinks matches is fine. Signed-off-by: Daniel Barkalow Signed-off-by: Junio C Hamano --- builtin-fetch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin-fetch.c b/builtin-fetch.c index 2f639ccef2..ac68ff592e 100644 --- a/builtin-fetch.c +++ b/builtin-fetch.c @@ -102,7 +102,7 @@ static struct ref *get_ref_map(struct transport *transport, remote->fetch[i].dst[0]) *autotags = 1; if (!i && !has_merge && ref_map && - !strcmp(remote->fetch[0].src, ref_map->name)) + !remote->fetch[0].pattern) ref_map->merge = 1; } if (has_merge) From 90446a0009d9c9c0a06c512f0836e0d30f78d2d0 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 28 Sep 2007 01:46:13 -0700 Subject: [PATCH 0125/1490] bundle transport: fix an alloc_ref() call Currently alloc_ref() expects the length of the refname plus 1 as its parameter, prepares that much space and returns a "ref" structure for the caller to fill the refname. One caller in transport.c::get_refs_from_bundle() however allocated one byte less. It may be a good idea to change the calling convention to give alloc_ref() the length of the refname, but that clean-up can be done in a separate patch. This patch only fixes the bug and makes all callers consistent. There was also one overallocation in connect.c, which would not hurt but was wasteful. This patch fixes it as well. Signed-off-by: Junio C Hamano --- connect.c | 4 ++-- transport.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/connect.c b/connect.c index 8b1e9935a8..aee78ff206 100644 --- a/connect.c +++ b/connect.c @@ -72,9 +72,9 @@ struct ref **get_remote_heads(int in, struct ref **list, continue; if (nr_match && !path_match(name, nr_match, match)) continue; - ref = alloc_ref(len - 40); + ref = alloc_ref(name_len + 1); hashcpy(ref->old_sha1, old_sha1); - memcpy(ref->name, buffer + 41, len - 40); + memcpy(ref->name, buffer + 41, name_len + 1); *list = ref; list = &ref->next; } diff --git a/transport.c b/transport.c index 4f9cddc308..3475ccaf5c 100644 --- a/transport.c +++ b/transport.c @@ -215,7 +215,7 @@ static struct ref *get_refs_from_bundle(const struct transport *transport) die ("Could not read bundle '%s'.", transport->url); for (i = 0; i < data->header.references.nr; i++) { struct ref_list_entry *e = data->header.references.list + i; - struct ref *ref = alloc_ref(strlen(e->name)); + struct ref *ref = alloc_ref(strlen(e->name) + 1); hashcpy(ref->old_sha1, e->sha1); strcpy(ref->name, e->name); ref->next = result; From 7155b727c9baae9ef6d7829370aefc09c4ab64e2 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Fri, 28 Sep 2007 16:28:54 +0100 Subject: [PATCH 0126/1490] Introduce remove_dir_recursively() There was a function called remove_empty_dir_recursive() buried in refs.c. Expose a slightly enhanced version in dir.h: it can now optionally remove a non-empty directory. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- dir.c | 41 +++++++++++++++++++++++++++++++++++++++++ dir.h | 2 ++ refs.c | 57 ++++++++++++--------------------------------------------- 3 files changed, 55 insertions(+), 45 deletions(-) diff --git a/dir.c b/dir.c index eb6c3abd30..b18257e65f 100644 --- a/dir.c +++ b/dir.c @@ -685,3 +685,44 @@ int is_inside_dir(const char *dir) char buffer[PATH_MAX]; return get_relative_cwd(buffer, sizeof(buffer), dir) != NULL; } + +int remove_dir_recursively(struct strbuf *path, int only_empty) +{ + DIR *dir = opendir(path->buf); + struct dirent *e; + int ret = 0, original_len = path->len, len; + + if (!dir) + return -1; + if (path->buf[original_len - 1] != '/') + strbuf_addch(path, '/'); + + len = path->len; + while ((e = readdir(dir)) != NULL) { + struct stat st; + if ((e->d_name[0] == '.') && + ((e->d_name[1] == 0) || + ((e->d_name[1] == '.') && e->d_name[2] == 0))) + continue; /* "." and ".." */ + + strbuf_setlen(path, len); + strbuf_addstr(path, e->d_name); + if (lstat(path->buf, &st)) + ; /* fall thru */ + else if (S_ISDIR(st.st_mode)) { + if (!remove_dir_recursively(path, only_empty)) + continue; /* happy */ + } else if (!only_empty && !unlink(path->buf)) + continue; /* happy, too */ + + /* path too long, stat fails, or non-directory still exists */ + ret = -1; + break; + } + closedir(dir); + + strbuf_setlen(path, original_len); + if (!ret) + ret = rmdir(path->buf); + return ret; +} diff --git a/dir.h b/dir.h index f55a87b2cd..a248a23ac4 100644 --- a/dir.h +++ b/dir.h @@ -64,4 +64,6 @@ extern struct dir_entry *dir_add_name(struct dir_struct *dir, const char *pathna extern char *get_relative_cwd(char *buffer, int size, const char *dir); extern int is_inside_dir(const char *dir); +extern int remove_dir_recursively(struct strbuf *path, int only_empty); + #endif diff --git a/refs.c b/refs.c index 7fb3350789..0dc5678079 100644 --- a/refs.c +++ b/refs.c @@ -2,6 +2,7 @@ #include "refs.h" #include "object.h" #include "tag.h" +#include "dir.h" /* ISSYMREF=01 and ISPACKED=02 are public interfaces */ #define REF_KNOWS_PEELED 04 @@ -671,57 +672,23 @@ static struct ref_lock *verify_lock(struct ref_lock *lock, return lock; } -static int remove_empty_dir_recursive(char *path, int len) -{ - DIR *dir = opendir(path); - struct dirent *e; - int ret = 0; - - if (!dir) - return -1; - if (path[len-1] != '/') - path[len++] = '/'; - while ((e = readdir(dir)) != NULL) { - struct stat st; - int namlen; - if ((e->d_name[0] == '.') && - ((e->d_name[1] == 0) || - ((e->d_name[1] == '.') && e->d_name[2] == 0))) - continue; /* "." and ".." */ - - namlen = strlen(e->d_name); - if ((len + namlen < PATH_MAX) && - strcpy(path + len, e->d_name) && - !lstat(path, &st) && - S_ISDIR(st.st_mode) && - !remove_empty_dir_recursive(path, len + namlen)) - continue; /* happy */ - - /* path too long, stat fails, or non-directory still exists */ - ret = -1; - break; - } - closedir(dir); - if (!ret) { - path[len] = 0; - ret = rmdir(path); - } - return ret; -} - -static int remove_empty_directories(char *file) +static int remove_empty_directories(const char *file) { /* we want to create a file but there is a directory there; * if that is an empty directory (or a directory that contains * only empty directories), remove them. */ - char path[PATH_MAX]; - int len = strlen(file); + struct strbuf path; + int result; - if (len >= PATH_MAX) /* path too long ;-) */ - return -1; - strcpy(path, file); - return remove_empty_dir_recursive(path, len); + strbuf_init(&path, 20); + strbuf_addstr(&path, file); + + result = remove_dir_recursively(&path, 1); + + strbuf_release(&path); + + return result; } static int is_refname_available(const char *ref, const char *oldref, From 076d7aa5d406fea1a5dedff5e2c54e2716528222 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 1 Oct 2007 00:27:51 -0700 Subject: [PATCH 0127/1490] git-am: fix typo in the previous one. Caught on #git by Ulrik Sverdrup Signed-off-by: Junio C Hamano --- git-am.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git-am.sh b/git-am.sh index 77a0e20996..cfa6fcf0af 100755 --- a/git-am.sh +++ b/git-am.sh @@ -453,7 +453,7 @@ do parent=$(git rev-parse --verify HEAD) && commit=$(git commit-tree $tree -p $parent <"$dotest/final-commit") && git update-ref -m "$GIT_REFLOG_ACTION: $SUBJECT" HEAD $commit $parent || - stop_here $thisy + stop_here $this if test -x "$GIT_DIR"/hooks/post-applypatch then From cd547b4886c5338a70eb8a674bfc40eac5cab3d9 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Mon, 1 Oct 2007 00:59:39 +0100 Subject: [PATCH 0128/1490] fetch/push: readd rsync support We lost rsync support when transitioning from shell to C. Support it again (even if the transport is technically deprecated, some people just do not have any chance to use anything else). Also, add a test to t5510. Since rsync transport is not configured by default on most machines, and especially not such that you can write to rsync://127.0.0.1$(pwd)/, it is disabled by default; you can enable it by setting the environment variable TEST_RSYNC. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- t/t5510-fetch.sh | 35 +++++ transport.c | 328 ++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 362 insertions(+), 1 deletion(-) diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh index 439430f569..73a4e3cbc3 100755 --- a/t/t5510-fetch.sh +++ b/t/t5510-fetch.sh @@ -153,4 +153,39 @@ test_expect_success 'bundle should be able to create a full history' ' ' +test "$TEST_RSYNC" && { +test_expect_success 'fetch via rsync' ' + git pack-refs && + mkdir rsynced && + cd rsynced && + git init && + git fetch rsync://127.0.0.1$(pwd)/../.git master:refs/heads/master && + git gc --prune && + test $(git rev-parse master) = $(cd .. && git rev-parse master) && + git fsck --full +' + +test_expect_success 'push via rsync' ' + mkdir ../rsynced2 && + (cd ../rsynced2 && + git init) && + git push rsync://127.0.0.1$(pwd)/../rsynced2/.git master && + cd ../rsynced2 && + git gc --prune && + test $(git rev-parse master) = $(cd .. && git rev-parse master) && + git fsck --full +' + +test_expect_success 'push via rsync' ' + cd .. && + mkdir rsynced3 && + (cd rsynced3 && + git init) && + git push --all rsync://127.0.0.1$(pwd)/rsynced3/.git && + cd rsynced3 && + test $(git rev-parse master) = $(cd .. && git rev-parse master) && + git fsck --full +' +} + test_done diff --git a/transport.c b/transport.c index 3475ccaf5c..7266fd3dc7 100644 --- a/transport.c +++ b/transport.c @@ -6,6 +6,330 @@ #include "fetch-pack.h" #include "walker.h" #include "bundle.h" +#include "dir.h" +#include "refs.h" + +/* rsync support */ + +/* + * We copy packed-refs and refs/ into a temporary file, then read the + * loose refs recursively (sorting whenever possible), and then inserting + * those packed refs that are not yet in the list (not validating, but + * assuming that the file is sorted). + * + * Appears refactoring this from refs.c is too cumbersome. + */ + +static int str_cmp(const void *a, const void *b) +{ + const char *s1 = a; + const char *s2 = b; + + return strcmp(s1, s2); +} + +/* path->buf + name_offset is expected to point to "refs/" */ + +static int read_loose_refs(struct strbuf *path, int name_offset, + struct ref **tail) +{ + DIR *dir = opendir(path->buf); + struct dirent *de; + struct { + char **entries; + int nr, alloc; + } list; + int i, pathlen; + + if (!dir) + return -1; + + memset (&list, 0, sizeof(list)); + + while ((de = readdir(dir))) { + if (de->d_name[0] == '.' && (de->d_name[1] == '\0' || + (de->d_name[1] == '.' && + de->d_name[2] == '\0'))) + continue; + ALLOC_GROW(list.entries, list.nr + 1, list.alloc); + list.entries[list.nr++] = xstrdup(de->d_name); + } + closedir(dir); + + /* sort the list */ + + qsort(list.entries, list.nr, sizeof(char *), str_cmp); + + pathlen = path->len; + strbuf_addch(path, '/'); + + for (i = 0; i < list.nr; i++, strbuf_setlen(path, pathlen + 1)) { + strbuf_addstr(path, list.entries[i]); + if (read_loose_refs(path, name_offset, tail)) { + int fd = open(path->buf, O_RDONLY); + char buffer[40]; + struct ref *next; + + if (fd < 0) + continue; + next = alloc_ref(path->len - name_offset + 1); + if (read_in_full(fd, buffer, 40) != 40 || + get_sha1_hex(buffer, next->old_sha1)) { + close(fd); + free(next); + continue; + } + close(fd); + strcpy(next->name, path->buf + name_offset); + (*tail)->next = next; + *tail = next; + } + } + strbuf_setlen(path, pathlen); + + for (i = 0; i < list.nr; i++) + free(list.entries[i]); + free(list.entries); + + return 0; +} + +/* insert the packed refs for which no loose refs were found */ + +static void insert_packed_refs(const char *packed_refs, struct ref **list) +{ + FILE *f = fopen(packed_refs, "r"); + static char buffer[PATH_MAX]; + + if (!f) + return; + + for (;;) { + int cmp, len; + + if (!fgets(buffer, sizeof(buffer), f)) { + fclose(f); + return; + } + + if (hexval(buffer[0]) > 0xf) + continue; + len = strlen(buffer); + if (buffer[len - 1] == '\n') + buffer[--len] = '\0'; + if (len < 41) + continue; + while ((*list)->next && + (cmp = strcmp(buffer + 41, + (*list)->next->name)) > 0) + list = &(*list)->next; + if (!(*list)->next || cmp < 0) { + struct ref *next = alloc_ref(len - 40); + buffer[40] = '\0'; + if (get_sha1_hex(buffer, next->old_sha1)) { + warning ("invalid SHA-1: %s", buffer); + free(next); + continue; + } + strcpy(next->name, buffer + 41); + next->next = (*list)->next; + (*list)->next = next; + list = &(*list)->next; + } + } +} + +static struct ref *get_refs_via_rsync(const struct transport *transport) +{ + struct strbuf buf = STRBUF_INIT, temp_dir = STRBUF_INIT; + struct ref dummy, *tail = &dummy; + struct child_process rsync; + const char *args[5]; + int temp_dir_len; + + /* copy the refs to the temporary directory */ + + strbuf_addstr(&temp_dir, git_path("rsync-refs-XXXXXX")); + if (!mkdtemp(temp_dir.buf)) + die ("Could not make temporary directory"); + temp_dir_len = temp_dir.len; + + strbuf_addstr(&buf, transport->url); + strbuf_addstr(&buf, "/refs"); + + memset(&rsync, 0, sizeof(rsync)); + rsync.argv = args; + rsync.stdout_to_stderr = 1; + args[0] = "rsync"; + args[1] = transport->verbose ? "-rv" : "-r"; + args[2] = buf.buf; + args[3] = temp_dir.buf; + args[4] = NULL; + + if (run_command(&rsync)) + die ("Could not run rsync to get refs"); + + strbuf_reset(&buf); + strbuf_addstr(&buf, transport->url); + strbuf_addstr(&buf, "/packed-refs"); + + args[2] = buf.buf; + + if (run_command(&rsync)) + die ("Could not run rsync to get refs"); + + /* read the copied refs */ + + strbuf_addstr(&temp_dir, "/refs"); + read_loose_refs(&temp_dir, temp_dir_len + 1, &tail); + strbuf_setlen(&temp_dir, temp_dir_len); + + tail = &dummy; + strbuf_addstr(&temp_dir, "/packed-refs"); + insert_packed_refs(temp_dir.buf, &tail); + strbuf_setlen(&temp_dir, temp_dir_len); + + if (remove_dir_recursively(&temp_dir, 0)) + warning ("Error removing temporary directory %s.", + temp_dir.buf); + + strbuf_release(&buf); + strbuf_release(&temp_dir); + + return dummy.next; +} + +static int fetch_objs_via_rsync(struct transport *transport, + int nr_objs, struct ref **to_fetch) +{ + struct strbuf buf = STRBUF_INIT; + struct child_process rsync; + const char *args[8]; + int result; + + strbuf_addstr(&buf, transport->url); + strbuf_addstr(&buf, "/objects/"); + + memset(&rsync, 0, sizeof(rsync)); + rsync.argv = args; + rsync.stdout_to_stderr = 1; + args[0] = "rsync"; + args[1] = transport->verbose ? "-rv" : "-r"; + args[2] = "--ignore-existing"; + args[3] = "--exclude"; + args[4] = "info"; + args[5] = buf.buf; + args[6] = get_object_directory(); + args[7] = NULL; + + /* NEEDSWORK: handle one level of alternates */ + result = run_command(&rsync); + + strbuf_release(&buf); + + return result; +} + +static int write_one_ref(const char *name, const unsigned char *sha1, + int flags, void *data) +{ + struct strbuf *buf = data; + int len = buf->len; + FILE *f; + + /* when called via for_each_ref(), flags is non-zero */ + if (flags && prefixcmp(name, "refs/heads/") && + prefixcmp(name, "refs/tags/")) + return 0; + + strbuf_addstr(buf, name); + if (safe_create_leading_directories(buf->buf) || + !(f = fopen(buf->buf, "w")) || + fprintf(f, "%s\n", sha1_to_hex(sha1)) < 0 || + fclose(f)) + return error("problems writing temporary file %s", buf->buf); + strbuf_setlen(buf, len); + return 0; +} + +static int write_refs_to_temp_dir(struct strbuf *temp_dir, + int refspec_nr, const char **refspec) +{ + int i; + + for (i = 0; i < refspec_nr; i++) { + unsigned char sha1[20]; + char *ref; + + if (dwim_ref(refspec[i], strlen(refspec[i]), sha1, &ref) != 1) + return error("Could not get ref %s", refspec[i]); + + if (write_one_ref(ref, sha1, 0, temp_dir)) { + free(ref); + return -1; + } + free(ref); + } + return 0; +} + +static int rsync_transport_push(struct transport *transport, + int refspec_nr, const char **refspec, int flags) +{ + struct strbuf buf = STRBUF_INIT, temp_dir = STRBUF_INIT; + int result = 0, i; + struct child_process rsync; + const char *args[8]; + + /* first push the objects */ + + strbuf_addstr(&buf, transport->url); + strbuf_addch(&buf, '/'); + + memset(&rsync, 0, sizeof(rsync)); + rsync.argv = args; + rsync.stdout_to_stderr = 1; + args[0] = "rsync"; + args[1] = transport->verbose ? "-av" : "-a"; + args[2] = "--ignore-existing"; + args[3] = "--exclude"; + args[4] = "info"; + args[5] = get_object_directory();; + args[6] = buf.buf; + args[7] = NULL; + + if (run_command(&rsync)) + return error("Could not push objects to %s", transport->url); + + /* copy the refs to the temporary directory; they could be packed. */ + + strbuf_addstr(&temp_dir, git_path("rsync-refs-XXXXXX")); + if (!mkdtemp(temp_dir.buf)) + die ("Could not make temporary directory"); + strbuf_addch(&temp_dir, '/'); + + if (flags & TRANSPORT_PUSH_ALL) { + if (for_each_ref(write_one_ref, &temp_dir)) + return -1; + } else if (write_refs_to_temp_dir(&temp_dir, refspec_nr, refspec)) + return -1; + + i = (flags & TRANSPORT_PUSH_FORCE) ? 2 : 3; + args[i++] = temp_dir.buf; + args[i++] = transport->url; + args[i++] = NULL; + if (run_command(&rsync)) + result = error("Could not push to %s", transport->url); + + if (remove_dir_recursively(&temp_dir, 0)) + warning ("Could not remove temporary directory %s.", + temp_dir.buf); + + strbuf_release(&buf); + strbuf_release(&temp_dir); + + return result; +} /* Generic functions for using commit walkers */ @@ -402,7 +726,9 @@ struct transport *transport_get(struct remote *remote, const char *url) ret->url = url; if (!prefixcmp(url, "rsync://")) { - /* not supported; don't populate any ops */ + ret->get_refs_list = get_refs_via_rsync; + ret->fetch = fetch_objs_via_rsync; + ret->push = rsync_transport_push; } else if (!prefixcmp(url, "http://") || !prefixcmp(url, "https://") From 2b5a06edca8f7237aad6464b349b79772024d2a2 Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Tue, 2 Oct 2007 22:49:15 -0400 Subject: [PATCH 0129/1490] Restore default verbosity for http fetches. This adds a verbosity level below 0 for suppressing default messages with --quiet, and makes the default for http be verbose instead of quiet. This matches the behavior of the shell script version of git-fetch. Signed-off-by: Daniel Barkalow Signed-off-by: Junio C Hamano --- builtin-fetch.c | 2 +- transport.c | 10 +++++----- transport.h | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/builtin-fetch.c b/builtin-fetch.c index ac68ff592e..cf7498b15f 100644 --- a/builtin-fetch.c +++ b/builtin-fetch.c @@ -533,7 +533,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) if (verbose >= 2) transport->verbose = 1; if (quiet) - transport->verbose = 0; + transport->verbose = -1; if (upload_pack) set_option(TRANS_OPT_UPLOADPACK, upload_pack); if (keep) diff --git a/transport.c b/transport.c index 7266fd3dc7..6fe6ec8503 100644 --- a/transport.c +++ b/transport.c @@ -161,7 +161,7 @@ static struct ref *get_refs_via_rsync(const struct transport *transport) rsync.argv = args; rsync.stdout_to_stderr = 1; args[0] = "rsync"; - args[1] = transport->verbose ? "-rv" : "-r"; + args[1] = (transport->verbose > 0) ? "-rv" : "-r"; args[2] = buf.buf; args[3] = temp_dir.buf; args[4] = NULL; @@ -214,7 +214,7 @@ static int fetch_objs_via_rsync(struct transport *transport, rsync.argv = args; rsync.stdout_to_stderr = 1; args[0] = "rsync"; - args[1] = transport->verbose ? "-rv" : "-r"; + args[1] = (transport->verbose > 0) ? "-rv" : "-r"; args[2] = "--ignore-existing"; args[3] = "--exclude"; args[4] = "info"; @@ -290,7 +290,7 @@ static int rsync_transport_push(struct transport *transport, rsync.argv = args; rsync.stdout_to_stderr = 1; args[0] = "rsync"; - args[1] = transport->verbose ? "-av" : "-a"; + args[1] = (transport->verbose > 0) ? "-av" : "-a"; args[2] = "--ignore-existing"; args[3] = "--exclude"; args[4] = "info"; @@ -344,7 +344,7 @@ static int fetch_objs_via_walker(struct transport *transport, walker->get_all = 1; walker->get_tree = 1; walker->get_history = 1; - walker->get_verbosely = transport->verbose; + walker->get_verbosely = transport->verbose >= 0; walker->get_recover = 0; for (i = 0; i < nr_objs; i++) @@ -637,7 +637,7 @@ static int fetch_refs_via_pack(struct transport *transport, args.keep_pack = data->keep; args.lock_pack = 1; args.use_thin_pack = data->thin; - args.verbose = transport->verbose; + args.verbose = transport->verbose > 0; args.depth = data->depth; for (i = 0; i < nr_heads; i++) diff --git a/transport.h b/transport.h index 6e318e4e8c..4bb51d7b7f 100644 --- a/transport.h +++ b/transport.h @@ -24,7 +24,7 @@ struct transport { int (*disconnect)(struct transport *connection); char *pack_lockfile; - unsigned verbose : 1; + signed verbose : 2; }; #define TRANSPORT_PUSH_ALL 1 From 501e4c6f23378aca2ce14ba4bc3eebeccb92e8d7 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Tue, 2 Oct 2007 12:24:44 -0400 Subject: [PATCH 0130/1490] git-gui: Allow gitk to be started on Cygwin with native Tcl/Tk gitk expects $env(GIT_DIR) to be valid as both a path that core Git and Tcl/Tk can resolve to a valid directory, but it has no special handling for Cygwin style UNIX paths and Windows style paths. So we need to do that for gitk and ensure that only relative paths are fed to it, thus allowing both Cygwin style and UNIX style paths to be resolved. Signed-off-by: Shawn O. Pearce --- git-gui.sh | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/git-gui.sh b/git-gui.sh index c8375029dd..9682418e12 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -1468,7 +1468,27 @@ proc do_gitk {revs} { if {! [file exists $exe]} { error_popup "Unable to start gitk:\n\n$exe does not exist" } else { + global env + + if {[info exists env(GIT_DIR)]} { + set old_GIT_DIR $env(GIT_DIR) + } else { + set old_GIT_DIR {} + } + + set pwd [pwd] + cd [file dirname [gitdir]] + set env(GIT_DIR) [file tail [gitdir]] + eval exec $cmd $revs & + + if {$old_GIT_DIR eq {}} { + unset env(GIT_DIR) + } else { + set env(GIT_DIR) $old_GIT_DIR + } + cd $pwd + ui_status $::starting_gitk_msg after 10000 { ui_ready $starting_gitk_msg From 906ab7f6c03764423adef6c0e4d77442405adc23 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Tue, 2 Oct 2007 12:27:32 -0400 Subject: [PATCH 0131/1490] git-gui: Don't crash when starting gitk from a browser session If the user has started git-gui from the command line as a browser we offer the gitk menu options but we didn't create the main status bar widget in the "." toplevel. Trying to access it while starting gitk just results in Tcl errors. Signed-off-by: Shawn O. Pearce --- git-gui.sh | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/git-gui.sh b/git-gui.sh index 9682418e12..cf88a0d824 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -1125,11 +1125,17 @@ proc mapdesc {state path} { } proc ui_status {msg} { - $::main_status show $msg + global main_status + if {[info exists main_status]} { + $main_status show $msg + } } proc ui_ready {{test {}}} { - $::main_status show {Ready.} $test + global main_status + if {[info exists main_status]} { + $main_status show [mc "Ready."] $test + } } proc escape_path {path} { From 1952aa1d5735ccbedd832620e43db3e03fc77088 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Tue, 2 Oct 2007 12:52:22 -0400 Subject: [PATCH 0132/1490] git-gui: Allow forced push into remote repository Some workflows allow the user to forcefully update a remote branch, such as in a "proposed updates" (aka "pu") branch where the branch is rewound and rebuilt on a daily basis against the current master branch. In such a case the "--force" or leading + must be used to make git-push execute anyway, even though it may be discarding one or more commits on the remote side. Signed-off-by: Shawn O. Pearce --- lib/transport.tcl | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/transport.tcl b/lib/transport.tcl index 3b05b8fc2c..8e6a9d0a60 100644 --- a/lib/transport.tcl +++ b/lib/transport.tcl @@ -32,6 +32,7 @@ proc push_to {remote} { proc start_push_anywhere_action {w} { global push_urltype push_remote push_url push_thin push_tags + global push_force set r_url {} switch -- $push_urltype { @@ -45,6 +46,9 @@ proc start_push_anywhere_action {w} { if {$push_thin} { lappend cmd --thin } + if {$push_force} { + lappend cmd --force + } if {$push_tags} { lappend cmd --tags } @@ -76,6 +80,7 @@ trace add variable push_remote write \ proc do_push_anywhere {} { global all_remotes current_branch global push_urltype push_remote push_url push_thin push_tags + global push_force set w .push_setup toplevel $w @@ -151,6 +156,10 @@ proc do_push_anywhere {} { pack $w.dest -anchor nw -fill x -pady 5 -padx 5 labelframe $w.options -text [mc "Transfer Options"] + checkbutton $w.options.force \ + -text [mc "Force overwrite existing branch (may discard changes)"] \ + -variable push_force + grid $w.options.force -columnspan 2 -sticky w checkbutton $w.options.thin \ -text [mc "Use thin pack (for slow network connections)"] \ -variable push_thin @@ -163,6 +172,7 @@ proc do_push_anywhere {} { pack $w.options -anchor nw -fill x -pady 5 -padx 5 set push_url {} + set push_force 0 set push_thin 0 set push_tags 0 From eb4d0e3f4515e5508fa9c0a695f7a45812a76296 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 2 Oct 2007 19:28:19 -0700 Subject: [PATCH 0133/1490] optimize diffcore-delta by sorting hash entries. Here's a test-patch. I don't guarantee anything, except that when I did the timings I also did a "wc" on the result, and they matched.. Before: [torvalds@woody linux]$ time git diff -l0 --stat -C v2.6.22.. | wc 7104 28574 438020 real 0m10.526s user 0m10.401s sys 0m0.136s After: [torvalds@woody linux]$ time ~/git/git diff -l0 --stat -C v2.6.22.. | wc 7104 28574 438020 real 0m8.876s user 0m8.761s sys 0m0.128s but the diff is fairly simple, so if somebody will go over it and say whether it's likely to be *correct* too, that 15% may well be worth it. [ Side note, without rename detection, that diff takes just under three seconds for me, so in that sense the improvement to the rename detection itself is larger than the overall 15% - it brings the cost of just rename detection from 7.5s to 5.9s, which would be on the order of just over a 20% performance improvement. ] Hmm. The patch depends on half-way subtle issues like the fact that the hashtables are guaranteed to not be full => we're guaranteed to have zero counts at the end => we don't need to do any steenking iterator count in the loop. A few comments might in order. Linus --- diffcore-delta.c | 54 +++++++++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/diffcore-delta.c b/diffcore-delta.c index d9729e5ec2..e670f85125 100644 --- a/diffcore-delta.c +++ b/diffcore-delta.c @@ -46,22 +46,6 @@ struct spanhash_top { struct spanhash data[FLEX_ARRAY]; }; -static struct spanhash *spanhash_find(struct spanhash_top *top, - unsigned int hashval) -{ - int sz = 1 << top->alloc_log2; - int bucket = hashval & (sz - 1); - while (1) { - struct spanhash *h = &(top->data[bucket++]); - if (!h->cnt) - return NULL; - if (h->hashval == hashval) - return h; - if (sz <= bucket) - bucket = 0; - } -} - static struct spanhash_top *spanhash_rehash(struct spanhash_top *orig) { struct spanhash_top *new; @@ -122,6 +106,20 @@ static struct spanhash_top *add_spanhash(struct spanhash_top *top, } } +static int spanhash_cmp(const void *a_, const void *b_) +{ + const struct spanhash *a = a_; + const struct spanhash *b = b_; + + /* A count of zero compares at the end.. */ + if (!a->cnt) + return !b->cnt ? 0 : 1; + if (!b->cnt) + return -1; + return a->hashval < b->hashval ? -1 : + a->hashval > b->hashval ? 1 : 0; +} + static struct spanhash_top *hash_chars(struct diff_filespec *one) { int i, n; @@ -158,6 +156,10 @@ static struct spanhash_top *hash_chars(struct diff_filespec *one) n = 0; accum1 = accum2 = 0; } + qsort(hash->data, + 1ul << hash->alloc_log2, + sizeof(hash->data[0]), + spanhash_cmp); return hash; } @@ -169,7 +171,7 @@ int diffcore_count_changes(struct diff_filespec *src, unsigned long *src_copied, unsigned long *literal_added) { - int i, ssz; + struct spanhash *s, *d; struct spanhash_top *src_count, *dst_count; unsigned long sc, la; @@ -190,22 +192,26 @@ int diffcore_count_changes(struct diff_filespec *src, } sc = la = 0; - ssz = 1 << src_count->alloc_log2; - for (i = 0; i < ssz; i++) { - struct spanhash *s = &(src_count->data[i]); - struct spanhash *d; + s = src_count->data; + d = dst_count->data; + for (;;) { unsigned dst_cnt, src_cnt; if (!s->cnt) - continue; + break; /* we checked all in src */ + while (d->cnt) { + if (d->hashval >= s->hashval) + break; + d++; + } src_cnt = s->cnt; - d = spanhash_find(dst_count, s->hashval); - dst_cnt = d ? d->cnt : 0; + dst_cnt = d->hashval == s->hashval ? d->cnt : 0; if (src_cnt < dst_cnt) { la += dst_cnt - src_cnt; sc += src_cnt; } else sc += dst_cnt; + s++; } if (!src_count_p) From 64b5f146fd2252646d23eac925c49ce9cb526de9 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Thu, 4 Oct 2007 22:19:24 +1000 Subject: [PATCH 0134/1490] gitk: Fix bug causing Tcl error when changing find match type When changing the selector for Exact/IgnCase/Regexp, we were getting a Tcl error. This fixes it. It also adds a workaround for a bug in alpha versions of Tk8.5 where wordprocessor-style tabs don't seem to work properly around column 1. Signed-off-by: Paul Mackerras --- gitk | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gitk b/gitk index 01f5926916..35920abc7b 100755 --- a/gitk +++ b/gitk @@ -2334,7 +2334,7 @@ proc find_change {name ix op} { drawvisible } -proc findcom_change {} { +proc findcom_change args { global nhighlights mainfont boldnamerows global findpattern findtype findstring gdttype @@ -5529,8 +5529,8 @@ proc settabs {{firstab {}}} { } set w [font measure $textfont "0"] if {$firsttabstop != 0} { - $ctext conf -tabs [list [expr {$firsttabstop * $w}] \ - [expr {($firsttabstop + $tabstop) * $w}]] + $ctext conf -tabs [list [expr {($firsttabstop + $tabstop) * $w}] \ + [expr {($firsttabstop + 2 * $tabstop) * $w}]] } elseif {$have_tk85 || $tabstop != 8} { $ctext conf -tabs [expr {$tabstop * $w}] } else { From 9c311b3208f25ce70edf0fdbe0f440ecd8e0bda7 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Thu, 4 Oct 2007 22:27:13 +1000 Subject: [PATCH 0135/1490] gitk: Use named fonts instead of the font specification This replaces the use of $mainfont, $textfont and $uifont with named fonts called mainfont, textfont and uifont. We also have variants called mainfontbold and textfontbold. This makes it much easier to make sure font size changes are reflected everywhere they should be, since configuring a named font automatically changes all the widgets that are using that font. Signed-off-by: Paul Mackerras --- gitk | 257 +++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 142 insertions(+), 115 deletions(-) diff --git a/gitk b/gitk index 35920abc7b..c257bb57ac 100755 --- a/gitk +++ b/gitk @@ -133,7 +133,7 @@ proc stop_rev_list {} { } proc getcommits {} { - global phase canv mainfont curview + global phase canv curview set phase getcommits initlayout @@ -615,7 +615,7 @@ proc confirm_popup msg { proc makewindow {} { global canv canv2 canv3 linespc charspc ctext cflist - global textfont mainfont uifont tabstop + global tabstop global findtype findtypemenu findloc findstring fstring geometry global entries sha1entry sha1string sha1but global diffcontextstring diffcontext @@ -630,19 +630,19 @@ proc makewindow {} { menu .bar .bar add cascade -label "File" -menu .bar.file - .bar configure -font $uifont + .bar configure -font uifont menu .bar.file .bar.file add command -label "Update" -command updatecommits .bar.file add command -label "Reread references" -command rereadrefs .bar.file add command -label "List references" -command showrefs .bar.file add command -label "Quit" -command doquit - .bar.file configure -font $uifont + .bar.file configure -font uifont menu .bar.edit .bar add cascade -label "Edit" -menu .bar.edit .bar.edit add command -label "Preferences" -command doprefs - .bar.edit configure -font $uifont + .bar.edit configure -font uifont - menu .bar.view -font $uifont + menu .bar.view -font uifont .bar add cascade -label "View" -menu .bar.view .bar.view add command -label "New view..." -command {newview 0} .bar.view add command -label "Edit view..." -command editview \ @@ -656,7 +656,7 @@ proc makewindow {} { .bar add cascade -label "Help" -menu .bar.help .bar.help add command -label "About gitk" -command about .bar.help add command -label "Key bindings" -command keys - .bar.help configure -font $uifont + .bar.help configure -font uifont . configure -menu .bar # the gui has upper and lower half, parts of a paned window. @@ -713,10 +713,10 @@ proc makewindow {} { set entries $sha1entry set sha1but .tf.bar.sha1label button $sha1but -text "SHA1 ID: " -state disabled -relief flat \ - -command gotocommit -width 8 -font $uifont + -command gotocommit -width 8 -font uifont $sha1but conf -disabledforeground [$sha1but cget -foreground] pack .tf.bar.sha1label -side left - entry $sha1entry -width 40 -font $textfont -textvariable sha1string + entry $sha1entry -width 40 -font textfont -textvariable sha1string trace add variable sha1string write sha1change pack $sha1entry -side left -pady 2 @@ -745,9 +745,9 @@ proc makewindow {} { # Status label and progress bar set statusw .tf.bar.status - label $statusw -width 15 -relief sunken -font $uifont + label $statusw -width 15 -relief sunken -font uifont pack $statusw -side left -padx 5 - set h [expr {[font metrics $uifont -linespace] + 2}] + set h [expr {[font metrics uifont -linespace] + 2}] set progresscanv .tf.bar.progress canvas $progresscanv -relief sunken -height $h -borderwidth 2 set progressitem [$progresscanv create rect -1 0 0 $h -fill green] @@ -760,10 +760,10 @@ proc makewindow {} { set progupdatepending 0 # build up the bottom bar of upper window - label .tf.lbar.flabel -text "Find " -font $uifont - button .tf.lbar.fnext -text "next" -command dofind -font $uifont - button .tf.lbar.fprev -text "prev" -command {dofind 1} -font $uifont - label .tf.lbar.flab2 -text " commit " -font $uifont + label .tf.lbar.flabel -text "Find " -font uifont + button .tf.lbar.fnext -text "next" -command dofind -font uifont + button .tf.lbar.fprev -text "prev" -command {dofind 1} -font uifont + label .tf.lbar.flab2 -text " commit " -font uifont pack .tf.lbar.flabel .tf.lbar.fnext .tf.lbar.fprev .tf.lbar.flab2 \ -side left -fill y set gdttype "containing:" @@ -772,27 +772,27 @@ proc makewindow {} { "touching paths:" \ "adding/removing string:"] trace add variable gdttype write gdttype_change - $gm conf -font $uifont - .tf.lbar.gdttype conf -font $uifont + $gm conf -font uifont + .tf.lbar.gdttype conf -font uifont pack .tf.lbar.gdttype -side left -fill y set findstring {} set fstring .tf.lbar.findstring lappend entries $fstring - entry $fstring -width 30 -font $textfont -textvariable findstring + entry $fstring -width 30 -font textfont -textvariable findstring trace add variable findstring write find_change set findtype Exact set findtypemenu [tk_optionMenu .tf.lbar.findtype \ findtype Exact IgnCase Regexp] trace add variable findtype write findcom_change - .tf.lbar.findtype configure -font $uifont - .tf.lbar.findtype.menu configure -font $uifont + .tf.lbar.findtype configure -font uifont + .tf.lbar.findtype.menu configure -font uifont set findloc "All fields" tk_optionMenu .tf.lbar.findloc findloc "All fields" Headline \ Comments Author Committer trace add variable findloc write find_change - .tf.lbar.findloc configure -font $uifont - .tf.lbar.findloc.menu configure -font $uifont + .tf.lbar.findloc configure -font uifont + .tf.lbar.findloc.menu configure -font uifont pack .tf.lbar.findloc -side right pack .tf.lbar.findtype -side right pack $fstring -side left -expand 1 -fill x @@ -820,10 +820,10 @@ proc makewindow {} { frame .bleft.mid button .bleft.top.search -text "Search" -command dosearch \ - -font $uifont + -font uifont pack .bleft.top.search -side left -padx 5 set sstring .bleft.top.sstring - entry $sstring -width 20 -font $textfont -textvariable searchstring + entry $sstring -width 20 -font textfont -textvariable searchstring lappend entries $sstring trace add variable searchstring write incrsearch pack $sstring -side left -expand 1 -fill x @@ -834,9 +834,9 @@ proc makewindow {} { radiobutton .bleft.mid.new -text "New version" \ -command changediffdisp -variable diffelide -value {1 0} label .bleft.mid.labeldiffcontext -text " Lines of context: " \ - -font $uifont + -font uifont pack .bleft.mid.diff .bleft.mid.old .bleft.mid.new -side left - spinbox .bleft.mid.diffcontext -width 5 -font $textfont \ + spinbox .bleft.mid.diffcontext -width 5 -font textfont \ -from 1 -increment 1 -to 10000000 \ -validate all -validatecommand "diffcontextvalidate %P" \ -textvariable diffcontextstring @@ -846,7 +846,7 @@ proc makewindow {} { pack .bleft.mid.labeldiffcontext .bleft.mid.diffcontext -side left set ctext .bleft.ctext text $ctext -background $bgcolor -foreground $fgcolor \ - -state disabled -font $textfont \ + -state disabled -font textfont \ -yscrollcommand scrolltext -wrap none if {$have_tk85} { $ctext conf -tabstyle wordprocessor @@ -860,7 +860,7 @@ proc makewindow {} { lappend fglist $ctext $ctext tag conf comment -wrap $wrapcomment - $ctext tag conf filesep -font [concat $textfont bold] -back "#aaaaaa" + $ctext tag conf filesep -font textfontbold -back "#aaaaaa" $ctext tag conf hunksep -fore [lindex $diffcolors 2] $ctext tag conf d0 -fore [lindex $diffcolors 0] $ctext tag conf d1 -fore [lindex $diffcolors 1] @@ -882,8 +882,8 @@ proc makewindow {} { $ctext tag conf m15 -fore "#ff70b0" $ctext tag conf mmax -fore darkgrey set mergemax 16 - $ctext tag conf mresult -font [concat $textfont bold] - $ctext tag conf msep -font [concat $textfont bold] + $ctext tag conf mresult -font textfontbold + $ctext tag conf msep -font textfontbold $ctext tag conf found -back yellow .pwbottom add .bleft @@ -894,18 +894,18 @@ proc makewindow {} { frame .bright.mode radiobutton .bright.mode.patch -text "Patch" \ -command reselectline -variable cmitmode -value "patch" - .bright.mode.patch configure -font $uifont + .bright.mode.patch configure -font uifont radiobutton .bright.mode.tree -text "Tree" \ -command reselectline -variable cmitmode -value "tree" - .bright.mode.tree configure -font $uifont + .bright.mode.tree configure -font uifont grid .bright.mode.patch .bright.mode.tree -sticky ew pack .bright.mode -side top -fill x set cflist .bright.cfiles - set indent [font measure $mainfont "nn"] + set indent [font measure mainfont "nn"] text $cflist \ -selectbackground $selectbgcolor \ -background $bgcolor -foreground $fgcolor \ - -font $mainfont \ + -font mainfont \ -tabs [list $indent [expr {2 * $indent}]] \ -yscrollcommand ".bright.sb set" \ -cursor [. cget -cursor] \ @@ -917,7 +917,7 @@ proc makewindow {} { pack $cflist -side left -fill both -expand 1 $cflist tag configure highlight \ -background [$cflist cget -selectbackground] - $cflist tag configure bold -font [concat $mainfont bold] + $cflist tag configure bold -font mainfontbold .pwbottom add .bright .ctop add .pwbottom @@ -1272,10 +1272,10 @@ Copyright Use and redistribute under the terms of the GNU General Public License} \ -justify center -aspect 400 -border 2 -bg white -relief groove pack $w.m -side top -fill x -padx 2 -pady 2 - $w.m configure -font $uifont + $w.m configure -font uifont button $w.ok -text Close -command "destroy $w" -default active pack $w.ok -side bottom - $w.ok configure -font $uifont + $w.ok configure -font uifont bind $w "focus $w.ok" bind $w "destroy $w" bind $w "destroy $w" @@ -1336,10 +1336,10 @@ f Scroll diff view to next file " \ -justify left -bg white -border 2 -relief groove pack $w.m -side top -fill both -padx 2 -pady 2 - $w.m configure -font $uifont + $w.m configure -font uifont button $w.ok -text Close -command "destroy $w" -default active pack $w.ok -side bottom - $w.ok configure -font $uifont + $w.ok configure -font uifont bind $w "focus $w.ok" bind $w "destroy $w" bind $w "destroy $w" @@ -1871,22 +1871,22 @@ proc vieweditor {top n title} { toplevel $top wm title $top $title - label $top.nl -text "Name" -font $uifont - entry $top.name -width 20 -textvariable newviewname($n) -font $uifont + label $top.nl -text "Name" -font uifont + entry $top.name -width 20 -textvariable newviewname($n) -font uifont grid $top.nl $top.name -sticky w -pady 5 checkbutton $top.perm -text "Remember this view" -variable newviewperm($n) \ - -font $uifont + -font uifont grid $top.perm - -pady 5 -sticky w - message $top.al -aspect 1000 -font $uifont \ + message $top.al -aspect 1000 -font uifont \ -text "Commits to include (arguments to git rev-list):" grid $top.al - -sticky w -pady 5 entry $top.args -width 50 -textvariable newviewargs($n) \ - -background white -font $uifont + -background white -font uifont grid $top.args - -sticky ew -padx 5 - message $top.l -aspect 1000 -font $uifont \ + message $top.l -aspect 1000 -font uifont \ -text "Enter files and directories to include, one per line:" grid $top.l - -sticky w - text $top.t -width 40 -height 10 -background white -font $uifont + text $top.t -width 40 -height 10 -background white -font uifont if {[info exists viewfiles($n)]} { foreach f $viewfiles($n) { $top.t insert end $f @@ -1898,9 +1898,9 @@ proc vieweditor {top n title} { grid $top.t - -sticky ew -padx 5 frame $top.buts button $top.buts.ok -text "OK" -command [list newviewok $top $n] \ - -font $uifont + -font uifont button $top.buts.can -text "Cancel" -command [list destroy $top] \ - -font $uifont + -font uifont 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 @@ -2191,12 +2191,12 @@ proc bolden_name {row font} { } proc unbolden {} { - global mainfont boldrows + global boldrows set stillbold {} foreach row $boldrows { if {![ishighlighted $row]} { - bolden $row $mainfont + bolden $row mainfont } else { lappend stillbold $row } @@ -2235,9 +2235,8 @@ proc delvhighlight {} { proc vhighlightmore {} { global hlview vhl_done commitidx vhighlights - global displayorder vdisporder curview mainfont + global displayorder vdisporder curview - set font [concat $mainfont bold] set max $commitidx($hlview) if {$hlview == $curview} { set disp $displayorder @@ -2253,7 +2252,7 @@ proc vhighlightmore {} { set row $commitrow($curview,$id) if {$r0 <= $row && $row <= $r1} { if {![highlighted $row]} { - bolden $row $font + bolden $row mainfontbold } set vhighlights($row) 1 } @@ -2263,11 +2262,11 @@ proc vhighlightmore {} { } proc askvhighlight {row id} { - global hlview vhighlights commitrow iddrawn mainfont + global hlview vhighlights commitrow iddrawn if {[info exists commitrow($hlview,$id)]} { if {[info exists iddrawn($id)] && ![ishighlighted $row]} { - bolden $row [concat $mainfont bold] + bolden $row mainfontbold } set vhighlights($row) 1 } else { @@ -2277,7 +2276,7 @@ proc askvhighlight {row id} { proc hfiles_change {} { global highlight_files filehighlight fhighlights fh_serial - global mainfont highlight_paths gdttype + global highlight_paths gdttype if {[info exists filehighlight]} { # delete previous highlights @@ -2335,13 +2334,13 @@ proc find_change {name ix op} { } proc findcom_change args { - global nhighlights mainfont boldnamerows + global nhighlights boldnamerows global findpattern findtype findstring gdttype stopfinding # delete previous highlights, if any foreach row $boldnamerows { - bolden_name $row $mainfont + bolden_name $row mainfont } set boldnamerows {} catch {unset nhighlights} @@ -2414,7 +2413,7 @@ proc askfilehighlight {row id} { } proc readfhighlight {} { - global filehighlight fhighlights commitrow curview mainfont iddrawn + global filehighlight fhighlights commitrow curview iddrawn global fhl_list find_dirn if {![info exists filehighlight]} { @@ -2436,7 +2435,7 @@ proc readfhighlight {} { if {![info exists commitrow($curview,$line)]} continue set row $commitrow($curview,$line) if {[info exists iddrawn($line)] && ![ishighlighted $row]} { - bolden $row [concat $mainfont bold] + bolden $row mainfontbold } set fhighlights($row) 1 } @@ -2470,7 +2469,7 @@ proc doesmatch {f} { } proc askfindhighlight {row id} { - global nhighlights commitinfo iddrawn mainfont + global nhighlights commitinfo iddrawn global findloc global markingmatches @@ -2491,11 +2490,10 @@ proc askfindhighlight {row id} { } } if {$isbold && [info exists iddrawn($id)]} { - set f [concat $mainfont bold] if {![ishighlighted $row]} { - bolden $row $f + bolden $row mainfontbold if {$isbold > 1} { - bolden_name $row $f + bolden_name $row mainfontbold } } if {$markingmatches} { @@ -2624,7 +2622,7 @@ proc is_ancestor {a} { } proc askrelhighlight {row id} { - global descendent highlight_related iddrawn mainfont rhighlights + global descendent highlight_related iddrawn rhighlights global selectedline ancestor if {![info exists selectedline]} return @@ -2648,7 +2646,7 @@ proc askrelhighlight {row id} { } if {[info exists iddrawn($id)]} { if {$isbold && ![ishighlighted $row]} { - bolden $row [concat $mainfont bold] + bolden $row mainfontbold } } set rhighlights($row) $isbold @@ -3624,7 +3622,7 @@ proc drawcmittext {id row col} { global commitlisted commitinfo rowidlist parentlist global rowtextx idpos idtags idheads idotherrefs global linehtag linentag linedtag selectedline - global mainfont canvxmax boldrows boldnamerows fgcolor nullid nullid2 + global canvxmax boldrows boldnamerows fgcolor nullid nullid2 # listed is 0 for boundary, 1 for normal, 2 for left, 3 for right set listed [lindex $commitlisted $row] @@ -3681,15 +3679,15 @@ proc drawcmittext {id row col} { set name [lindex $commitinfo($id) 1] set date [lindex $commitinfo($id) 2] set date [formatdate $date] - set font $mainfont - set nfont $mainfont + set font mainfont + set nfont mainfont set isbold [ishighlighted $row] if {$isbold > 0} { lappend boldrows $row - lappend font bold + set font mainfontbold if {$isbold > 1} { lappend boldnamerows $row - lappend nfont bold + set nfont mainfontbold } } set linehtag($row) [$canv create text $xt $y -anchor w -fill $fgcolor \ @@ -3698,11 +3696,11 @@ proc drawcmittext {id row col} { set linentag($row) [$canv2 create text 3 $y -anchor w -fill $fgcolor \ -text $name -font $nfont -tags text] set linedtag($row) [$canv3 create text 3 $y -anchor w -fill $fgcolor \ - -text $date -font $mainfont -tags text] + -text $date -font mainfont -tags text] if {[info exists selectedline] && $selectedline == $row} { make_secsel $row } - set xr [expr {$xt + [font measure $mainfont $headline]}] + set xr [expr {$xt + [font measure $font $headline]}] if {$xr > $canvxmax} { set canvxmax $xr setcanvscroll @@ -3985,7 +3983,7 @@ proc bindline {t id} { proc drawtags {id x xt y1} { global idtags idheads idotherrefs mainhead global linespc lthickness - global canv mainfont commitrow rowtextx curview fgcolor bgcolor + global canv commitrow rowtextx curview fgcolor bgcolor set marks {} set ntags 0 @@ -4014,9 +4012,9 @@ proc drawtags {id x xt y1} { foreach tag $marks { incr i if {$i >= $ntags && $i < $ntags + $nheads && $tag eq $mainhead} { - set wid [font measure [concat $mainfont bold] $tag] + set wid [font measure mainfontbold $tag] } else { - set wid [font measure $mainfont $tag] + set wid [font measure mainfont $tag] } lappend xvals $xt lappend wvals $wid @@ -4028,7 +4026,7 @@ proc drawtags {id x xt y1} { foreach tag $marks x $xvals wid $wvals { set xl [expr {$x + $delta}] set xr [expr {$x + $delta + $wid + $lthickness}] - set font $mainfont + set font mainfont if {[incr ntags -1] >= 0} { # draw a tag set t [$canv create polygon $x [expr {$yt + $delta}] $xl $yt \ @@ -4041,7 +4039,7 @@ proc drawtags {id x xt y1} { if {[incr nheads -1] >= 0} { set col green if {$tag eq $mainhead} { - lappend font bold + set font mainfontbold } } else { set col "#ddddff" @@ -4050,7 +4048,7 @@ proc drawtags {id x xt y1} { $canv create polygon $x $yt $xr $yt $xr $yb $x $yb \ -width 1 -outline black -fill $col -tags tag.$id if {[regexp {^(remotes/.*/|remotes/)} $tag match remoteprefix]} { - set rwid [font measure $mainfont $remoteprefix] + set rwid [font measure mainfont $remoteprefix] set xi [expr {$x + 1}] set yti [expr {$yt + 1}] set xri [expr {$x + $rwid}] @@ -4082,10 +4080,10 @@ proc xcoord {i level ln} { } proc show_status {msg} { - global canv mainfont fgcolor + global canv fgcolor clear_display - $canv create text 3 3 -anchor nw -text $msg -font $mainfont \ + $canv create text 3 3 -anchor nw -text $msg -font mainfont \ -tags text -fill $fgcolor } @@ -5522,12 +5520,12 @@ proc clear_ctext {{first 1.0}} { } proc settabs {{firstab {}}} { - global firsttabstop tabstop textfont ctext have_tk85 + global firsttabstop tabstop ctext have_tk85 if {$firstab ne {} && $have_tk85} { set firsttabstop $firstab } - set w [font measure $textfont "0"] + set w [font measure textfont "0"] if {$firsttabstop != 0} { $ctext conf -tabs [list [expr {($firsttabstop + $tabstop) * $w}] \ [expr {($firsttabstop + 2 * $tabstop) * $w}]] @@ -5658,11 +5656,11 @@ proc scrolltext {f0 f1} { } proc setcoords {} { - global linespc charspc canvx0 canvy0 mainfont + global linespc charspc canvx0 canvy0 global xspc1 xspc2 lthickness - set linespc [font metrics $mainfont -linespace] - set charspc [font measure $mainfont "m"] + set linespc [font metrics mainfont -linespace] + set charspc [font measure mainfont "m"] set canvy0 [expr {int(3 + 0.5 * $linespc)}] set canvx0 [expr {int(3 + 0.5 * $linespc)}] set lthickness [expr {int($linespc / 9) + 1}] @@ -5687,25 +5685,45 @@ proc redisplay {} { } } +proc fontdescr {f} { + set d [list [font actual $f -family] [font actual $f -size]] + if {[font actual $f -weight] eq "bold"} { + lappend d "bold" + } + if {[font actual $f -slant] eq "italic"} { + lappend d "italic" + } + if {[font actual $f -underline]} { + lappend d "underline" + } + if {[font actual $f -overstrike]} { + lappend d "overstrike" + } + return $d +} + proc incrfont {inc} { global mainfont textfont ctext canv phase cflist showrefstop global stopped entries unmarkmatches - set mainfont [lreplace $mainfont 1 1 [expr {[lindex $mainfont 1] + $inc}]] - set textfont [lreplace $textfont 1 1 [expr {[lindex $textfont 1] + $inc}]] + set s [font actual mainfont -size] + incr s $inc + if {$s < 1} { + set s 1 + } + font config mainfont -size $s + font config mainfontbold -size $s + set mainfont [fontdescr mainfont] + set s [font actual textfont -size] + incr s $inc + if {$s < 1} { + set s 1 + } + font config textfont -size $s + font config textfontbold -size $s + set textfont [fontdescr textfont] setcoords settabs - $cflist conf -font $textfont - $ctext tag conf filesep -font [concat $textfont bold] - foreach e $entries { - $e conf -font $mainfont - } - if {$phase eq "getcommits"} { - $canv itemconf textitems -font $mainfont - } - if {[info exists showrefstop] && [winfo exists $showrefstop]} { - $showrefstop.list conf -font $mainfont - } redisplay } @@ -5816,7 +5834,7 @@ proc lineleave {id} { proc linehover {} { global hoverx hovery hoverid hovertimer global canv linespc lthickness - global commitinfo mainfont + global commitinfo set text [lindex $commitinfo($hoverid) 0] set ymax [lindex [$canv cget -scrollregion] 3] @@ -5826,13 +5844,13 @@ proc linehover {} { set y [expr {$hovery + $yfrac * $ymax - $linespc / 2}] set x0 [expr {$x - 2 * $lthickness}] set y0 [expr {$y - 2 * $lthickness}] - set x1 [expr {$x + [font measure $mainfont $text] + 2 * $lthickness}] + set x1 [expr {$x + [font measure mainfont $text] + 2 * $lthickness}] set y1 [expr {$y + $linespc + 2 * $lthickness}] set t [$canv create rectangle $x0 $y0 $x1 $y1 \ -fill \#ffff80 -outline black -width 1 -tags hover] $canv raise $t set t [$canv create text $x $y -anchor nw -text $text -tags hover \ - -font $mainfont] + -font mainfont] $canv raise $t } @@ -6168,7 +6186,7 @@ proc domktag {} { proc redrawtags {id} { global canv linehtag commitrow idpos selectedline curview - global mainfont canvxmax iddrawn + global canvxmax iddrawn if {![info exists commitrow($curview,$id)]} return if {![info exists iddrawn($id)]} return @@ -6177,7 +6195,7 @@ proc redrawtags {id} { set xt [eval drawtags $id $idpos($id)] $canv coords $linehtag($commitrow($curview,$id)) $xt [lindex $idpos($id) 2] set text [$canv itemcget $linehtag($commitrow($curview,$id)) -text] - set xr [expr {$xt + [font measure $mainfont $text]}] + set xr [expr {$xt + [font measure mainfont $text]}] if {$xr > $canvxmax} { set canvxmax $xr setcanvscroll @@ -6509,8 +6527,8 @@ proc rmbranch {} { # Display a list of tags and heads proc showrefs {} { - global showrefstop bgcolor fgcolor selectbgcolor mainfont - global bglist fglist uifont reflistfilter reflist maincursor + global showrefstop bgcolor fgcolor selectbgcolor + global bglist fglist reflistfilter reflist maincursor set top .showrefs set showrefstop $top @@ -6522,7 +6540,7 @@ proc showrefs {} { toplevel $top wm title $top "Tags and heads: [file tail [pwd]]" text $top.list -background $bgcolor -foreground $fgcolor \ - -selectbackground $selectbgcolor -font $mainfont \ + -selectbackground $selectbgcolor -font mainfont \ -xscrollcommand "$top.xsb set" -yscrollcommand "$top.ysb set" \ -width 30 -height 20 -cursor $maincursor \ -spacing1 1 -spacing3 1 -state disabled @@ -6534,15 +6552,15 @@ proc showrefs {} { grid $top.list $top.ysb -sticky nsew grid $top.xsb x -sticky ew frame $top.f - label $top.f.l -text "Filter: " -font $uifont - entry $top.f.e -width 20 -textvariable reflistfilter -font $uifont + label $top.f.l -text "Filter: " -font uifont + entry $top.f.e -width 20 -textvariable reflistfilter -font uifont set reflistfilter "*" trace add variable reflistfilter write reflistfilter_change pack $top.f.e -side right -fill x -expand 1 pack $top.f.l -side left grid $top.f - -sticky ew -pady 2 button $top.close -command [list destroy $top] -text "Close" \ - -font $uifont + -font uifont grid $top.close - grid columnconfigure $top 0 -weight 1 grid rowconfigure $top 0 -weight 1 @@ -7845,7 +7863,7 @@ proc doprefs {} { toplevel $top wm title $top "Gitk preferences" label $top.ldisp -text "Commit list display options" - $top.ldisp configure -font $uifont + $top.ldisp configure -font uifont grid $top.ldisp - -sticky w -pady 10 label $top.spacer -text " " label $top.maxwidthl -text "Maximum graph width (lines)" \ @@ -7863,7 +7881,7 @@ proc doprefs {} { grid x $top.showlocal -sticky w label $top.ddisp -text "Diff display options" - $top.ddisp configure -font $uifont + $top.ddisp configure -font uifont grid $top.ddisp - -sticky w -pady 10 label $top.diffoptl -text "Options for diff program" \ -font optionfont @@ -7879,7 +7897,7 @@ proc doprefs {} { grid x $top.tabstopl $top.tabstop -sticky w label $top.cdisp -text "Colors: press to choose" - $top.cdisp configure -font $uifont + $top.cdisp configure -font uifont grid $top.cdisp - -sticky w -pady 10 label $top.bg -padx 40 -relief sunk -background $bgcolor button $top.bgbut -text "Background" -font optionfont \ @@ -7912,9 +7930,9 @@ proc doprefs {} { frame $top.buts button $top.buts.ok -text "OK" -command prefsok -default active - $top.buts.ok configure -font $uifont + $top.buts.ok configure -font uifont button $top.buts.can -text "Cancel" -command prefscan -default normal - $top.buts.can configure -font $uifont + $top.buts.can configure -font uifont 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 @@ -8322,6 +8340,15 @@ set selectbgcolor gray85 catch {source ~/.gitk} font create optionfont -family sans-serif -size -12 +font create mainfont +catch {eval font config mainfont [font actual $mainfont]} +eval font create mainfontbold [font actual mainfont] -weight bold +font create textfont +catch {eval font config textfont [font actual $textfont]} +eval font create textfontbold [font actual textfont] +font config textfontbold -weight bold +font create uifont +catch {eval font config uifont [font actual $uifont]} # check that we can find a .git directory somewhere... if {[catch {set gitdir [gitdir]}]} { From 0ed1dd3c77e606156f0f5d1baa59a47f33711787 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sat, 6 Oct 2007 18:27:37 +1000 Subject: [PATCH 0136/1490] gitk: Keep track of font attributes ourselves instead of using font actual Unfortunately there seems to be a bug in Tk8.5 where font actual -size sometimes gives the wrong answer (e.g. 12 for Bitstream Vera Sans 9), even though the font is actually displayed at the right size. This works around it by parsing and storing the family, size, weight and slant of the mainfont, textfont and uifont explicitly. Signed-off-by: Paul Mackerras --- gitk | 82 ++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 57 insertions(+), 25 deletions(-) diff --git a/gitk b/gitk index c257bb57ac..69b31f037e 100755 --- a/gitk +++ b/gitk @@ -5685,43 +5685,73 @@ proc redisplay {} { } } -proc fontdescr {f} { - set d [list [font actual $f -family] [font actual $f -size]] - if {[font actual $f -weight] eq "bold"} { - lappend d "bold" +proc parsefont {f n} { + global fontattr + + set fontattr($f,family) [lindex $n 0] + set s [lindex $n 1] + if {$s eq {} || $s == 0} { + set s 10 + } elseif {$s < 0} { + set s [expr {int(-$s / [winfo fpixels . 1p] + 0.5)}] } - if {[font actual $f -slant] eq "italic"} { - lappend d "italic" + set fontattr($f,size) $s + set fontattr($f,weight) normal + set fontattr($f,slant) roman + foreach style [lrange $n 2 end] { + switch -- $style { + "normal" - + "bold" {set fontattr($f,weight) $style} + "roman" - + "italic" {set fontattr($f,slant) $style} + } } - if {[font actual $f -underline]} { - lappend d "underline" +} + +proc fontflags {f {isbold 0}} { + global fontattr + + return [list -family $fontattr($f,family) -size $fontattr($f,size) \ + -weight [expr {$isbold? "bold": $fontattr($f,weight)}] \ + -slant $fontattr($f,slant)] +} + +proc fontname {f} { + global fontattr + + set n [list $fontattr($f,family) $fontattr($f,size)] + if {$fontattr($f,weight) eq "bold"} { + lappend n "bold" } - if {[font actual $f -overstrike]} { - lappend d "overstrike" + if {$fontattr($f,slant) eq "italic"} { + lappend n "italic" } - return $d + return $n } proc incrfont {inc} { global mainfont textfont ctext canv phase cflist showrefstop - global stopped entries + global stopped entries fontattr + unmarkmatches - set s [font actual mainfont -size] + set s $fontattr(mainfont,size) incr s $inc if {$s < 1} { set s 1 } + set fontattr(mainfont,size) $s font config mainfont -size $s font config mainfontbold -size $s - set mainfont [fontdescr mainfont] - set s [font actual textfont -size] + set mainfont [fontname mainfont] + set s $fontattr(textfont,size) incr s $inc if {$s < 1} { set s 1 } + set fontattr(textfont,size) $s font config textfont -size $s font config textfontbold -size $s - set textfont [fontdescr textfont] + set textfont [fontname textfont] setcoords settabs redisplay @@ -8340,15 +8370,17 @@ set selectbgcolor gray85 catch {source ~/.gitk} font create optionfont -family sans-serif -size -12 -font create mainfont -catch {eval font config mainfont [font actual $mainfont]} -eval font create mainfontbold [font actual mainfont] -weight bold -font create textfont -catch {eval font config textfont [font actual $textfont]} -eval font create textfontbold [font actual textfont] -font config textfontbold -weight bold -font create uifont -catch {eval font config uifont [font actual $uifont]} + +parsefont mainfont $mainfont +eval font create mainfont [fontflags mainfont] +eval font create mainfontbold [fontflags mainfont 1] + +parsefont textfont $textfont +eval font create textfont [fontflags textfont] +eval font create textfontbold [fontflags textfont 1] + +parsefont uifont $uifont +eval font create uifont [fontflags uifont] # check that we can find a .git directory somewhere... if {[catch {set gitdir [gitdir]}]} { From 9a7558f348772ab3c2fb3d4beda3a3a7af1e843a Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sat, 6 Oct 2007 20:16:06 +1000 Subject: [PATCH 0137/1490] gitk: Add a font chooser This adds buttons to the edit preferences window to allow the user to choose the main font, the text font (used for the diff display window) and the UI font. Pressing those buttons pops up a font chooser window that lets the user pick the font family, size, weight (bold/normal) and slant (roman/italic). Signed-off-by: Paul Mackerras --- gitk | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 155 insertions(+), 1 deletion(-) diff --git a/gitk b/gitk index 69b31f037e..6f0af37342 100755 --- a/gitk +++ b/gitk @@ -7875,6 +7875,130 @@ proc doquit {} { destroy . } +proc mkfontdisp {font top which} { + global fontattr fontpref $font + + set fontpref($font) [set $font] + button $top.${font}but -text $which -font optionfont \ + -command [list choosefont $font $which] + label $top.$font -relief flat -font $font \ + -text $fontattr($font,family) -justify left + grid x $top.${font}but $top.$font -sticky w +} + +proc choosefont {font which} { + global fontparam fontlist fonttop fontattr + + set fontparam(which) $which + set fontparam(font) $font + set fontparam(family) [font actual $font -family] + set fontparam(size) $fontattr($font,size) + set fontparam(weight) $fontattr($font,weight) + set fontparam(slant) $fontattr($font,slant) + set top .gitkfont + set fonttop $top + if {![winfo exists $top]} { + font create sample + eval font config sample [font actual $font] + toplevel $top + wm title $top "Gitk font chooser" + label $top.l -textvariable fontparam(which) -font uifont + pack $top.l -side top + set fontlist [lsort [font families]] + frame $top.f + listbox $top.f.fam -listvariable fontlist \ + -yscrollcommand [list $top.f.sb set] + bind $top.f.fam <> selfontfam + scrollbar $top.f.sb -command [list $top.f.fam yview] + pack $top.f.sb -side right -fill y + pack $top.f.fam -side left -fill both -expand 1 + pack $top.f -side top -fill both -expand 1 + frame $top.g + spinbox $top.g.size -from 4 -to 40 -width 4 \ + -textvariable fontparam(size) \ + -validatecommand {string is integer -strict %s} + checkbutton $top.g.bold -padx 5 \ + -font {{Times New Roman} 12 bold} -text "B" -indicatoron 0 \ + -variable fontparam(weight) -onvalue bold -offvalue normal + checkbutton $top.g.ital -padx 5 \ + -font {{Times New Roman} 12 italic} -text "I" -indicatoron 0 \ + -variable fontparam(slant) -onvalue italic -offvalue roman + pack $top.g.size $top.g.bold $top.g.ital -side left + pack $top.g -side top + canvas $top.c -width 150 -height 50 -border 2 -relief sunk \ + -background white + $top.c create text 100 25 -anchor center -text $which -font sample \ + -fill black -tags text + bind $top.c [list centertext $top.c] + pack $top.c -side top -fill x + frame $top.buts + button $top.buts.ok -text "OK" -command fontok -default active \ + -font uifont + button $top.buts.can -text "Cancel" -command fontcan -default normal \ + -font uifont + 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 + pack $top.buts -side bottom -fill x + trace add variable fontparam write chg_fontparam + } else { + raise $top + $top.c itemconf text -text $which + } + set i [lsearch -exact $fontlist $fontparam(family)] + if {$i >= 0} { + $top.f.fam selection set $i + $top.f.fam see $i + } +} + +proc centertext {w} { + $w coords text [expr {[winfo width $w] / 2}] [expr {[winfo height $w] / 2}] +} + +proc fontok {} { + global fontparam fontpref prefstop + + set f $fontparam(font) + set fontpref($f) [list $fontparam(family) $fontparam(size)] + if {$fontparam(weight) eq "bold"} { + lappend fontpref($f) "bold" + } + if {$fontparam(slant) eq "italic"} { + lappend fontpref($f) "italic" + } + set w $prefstop.$f + $w conf -text $fontparam(family) -font $fontpref($f) + + fontcan +} + +proc fontcan {} { + global fonttop fontparam + + if {[info exists fonttop]} { + catch {destroy $fonttop} + catch {font delete sample} + unset fonttop + unset fontparam + } +} + +proc selfontfam {} { + global fonttop fontparam + + set i [$fonttop.f.fam curselection] + if {$i ne {}} { + set fontparam(family) [$fonttop.f.fam get $i] + } +} + +proc chg_fontparam {v sub op} { + global fontparam + + font config sample -$sub $fontparam($sub) +} + proc doprefs {} { global maxwidth maxgraphpct diffopts global oldprefs prefstop showneartags showlocalchanges @@ -7958,6 +8082,13 @@ proc doprefs {} { -command [list choosecolor selectbgcolor 0 $top.selbgsep background setselbg] grid x $top.selbgbut $top.selbgsep -sticky w + label $top.cfont -text "Fonts: press to choose" + $top.cfont configure -font uifont + grid $top.cfont - -sticky w -pady 10 + mkfontdisp mainfont $top "Main font" + mkfontdisp textfont $top "Diff display font" + mkfontdisp uifont $top "User interface font" + frame $top.buts button $top.buts.ok -text "OK" -command prefsok -default active $top.buts.ok configure -font uifont @@ -8018,14 +8149,37 @@ proc prefscan {} { } catch {destroy $prefstop} unset prefstop + fontcan } proc prefsok {} { global maxwidth maxgraphpct global oldprefs prefstop showneartags showlocalchanges + global fontpref mainfont textfont uifont catch {destroy $prefstop} unset prefstop + fontcan + set fontchanged 0 + if {$mainfont ne $fontpref(mainfont)} { + set mainfont $fontpref(mainfont) + parsefont mainfont $mainfont + eval font configure mainfont [fontflags mainfont] + eval font configure mainfontbold [fontflags mainfont 1] + setcoords + set fontchanged 1 + } + if {$textfont ne $fontpref(textfont)} { + set textfont $fontpref(textfont) + parsefont textfont $textfont + eval font configure textfont [fontflags textfont] + eval font configure textfontbold [fontflags textfont 1] + } + if {$uifont ne $fontpref(uifont)} { + set uifont $fontpref(uifont) + parsefont uifont $uifont + eval font configure uifont [fontflags uifont] + } settabs if {$showlocalchanges != $oldprefs(showlocalchanges)} { if {$showlocalchanges} { @@ -8034,7 +8188,7 @@ proc prefsok {} { dohidelocalchanges } } - if {$maxwidth != $oldprefs(maxwidth) + if {$fontchanged || $maxwidth != $oldprefs(maxwidth) || $maxgraphpct != $oldprefs(maxgraphpct)} { redisplay } elseif {$showneartags != $oldprefs(showneartags)} { From 308ff3d59df853a21d4e218473974311fb7b3320 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sat, 6 Oct 2007 20:17:59 +1000 Subject: [PATCH 0138/1490] gitk: Fix bug where the last few commits would sometimes not be visible We weren't calling showstuff for the last few commits under some circumstances, causing the scrolling region not to be extended right to the end of the graph. This fixes it. Signed-off-by: Paul Mackerras --- gitk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gitk b/gitk index 6f0af37342..3f7f77777d 100755 --- a/gitk +++ b/gitk @@ -2758,7 +2758,7 @@ proc layoutmore {} { global uparrowlen downarrowlen mingaplen curview set show $commitidx($curview) - if {$show > $numcommits} { + if {$show > $numcommits || $viewcomplete($curview)} { showstuff $show $viewcomplete($curview) } } From 8d73b242a53da9ea36800a8ff0f9993e5100ea24 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sat, 6 Oct 2007 20:22:00 +1000 Subject: [PATCH 0139/1490] gitk: Get rid of the diffopts variable The only thing that could be specified with diffopts was the number of lines of context, but there is already a spinbox for that. So this gets rid of it. Signed-off-by: Paul Mackerras --- gitk | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/gitk b/gitk index 3f7f77777d..290deff7b2 100755 --- a/gitk +++ b/gitk @@ -5119,14 +5119,13 @@ proc getblobline {bf id} { } proc mergediff {id l} { - global diffmergeid diffopts mdifffd + global diffmergeid mdifffd global diffids global parentlist set diffmergeid $id set diffids $id # this doesn't seem to actually affect anything... - set env(GIT_DIFF_OPTS) $diffopts set cmd [concat | git diff-tree --no-commit-id --cc $id] if {[catch {set mdf [open $cmd r]} err]} { error_popup "Error getting merge diffs: $err" @@ -5333,11 +5332,10 @@ proc diffcontextchange {n1 n2 op} { } proc getblobdiffs {ids} { - global diffopts blobdifffd diffids env + global blobdifffd diffids env global diffinhdr treediffs global diffcontext - set env(GIT_DIFF_OPTS) $diffopts if {[catch {set bdf [open [diffcmd $ids "-p -C --no-commit-id -U$diffcontext"] r]} err]} { puts "error getting diffs: $err" return @@ -8000,7 +7998,7 @@ proc chg_fontparam {v sub op} { } proc doprefs {} { - global maxwidth maxgraphpct diffopts + global maxwidth maxgraphpct global oldprefs prefstop showneartags showlocalchanges global bgcolor fgcolor ctext diffcolors selectbgcolor global uifont tabstop @@ -8011,7 +8009,7 @@ proc doprefs {} { raise $top return } - foreach v {maxwidth maxgraphpct diffopts showneartags showlocalchanges} { + foreach v {maxwidth maxgraphpct showneartags showlocalchanges} { set oldprefs($v) [set $v] } toplevel $top @@ -8037,10 +8035,6 @@ proc doprefs {} { label $top.ddisp -text "Diff display options" $top.ddisp configure -font uifont grid $top.ddisp - -sticky w -pady 10 - label $top.diffoptl -text "Options for diff program" \ - -font optionfont - entry $top.diffopt -width 20 -textvariable diffopts - grid x $top.diffoptl $top.diffopt -sticky w frame $top.ntag label $top.ntag.l -text "Display nearby tags" -font optionfont checkbutton $top.ntag.b -variable showneartags @@ -8141,10 +8135,10 @@ proc setfg {c} { } proc prefscan {} { - global maxwidth maxgraphpct diffopts + global maxwidth maxgraphpct global oldprefs prefstop showneartags showlocalchanges - foreach v {maxwidth maxgraphpct diffopts showneartags showlocalchanges} { + foreach v {maxwidth maxgraphpct showneartags showlocalchanges} { set $v $oldprefs($v) } catch {destroy $prefstop} @@ -8479,7 +8473,6 @@ proc tcl_encoding {enc} { # defaults... set datemode 0 -set diffopts "-U 5 -p" set wrcomcmd "git diff-tree --stdin -p --pretty" set gitencoding {} From 96f11953c0b0b9b0a0c75fb98bdf239dce5ff582 Mon Sep 17 00:00:00 2001 From: Steffen Prohaska Date: Sat, 6 Oct 2007 15:27:22 +0200 Subject: [PATCH 0140/1490] git-gui: accept versions containing text annotations, like 1.5.3.mingw.1 This commit teaches git-gui to accept versions with annotations that start with text and optionally end with a dot followed by a number. This is needed by the current versioning scheme of msysgit, which uses versions like 1.5.3.mingw.1. However, the changes is not limited to this use case. Any version of the form .. would be parsed and only the starting used for validation. [sp: Minor edit to remove unnecessary group matching] Signed-off-by: Steffen Prohaska Signed-off-by: Shawn O. Pearce --- git-gui.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/git-gui.sh b/git-gui.sh index cf88a0d824..9335a9761b 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -538,6 +538,7 @@ regsub -- {-dirty$} $_git_version {} _git_version regsub {\.[0-9]+\.g[0-9a-f]+$} $_git_version {} _git_version regsub {\.rc[0-9]+$} $_git_version {} _git_version regsub {\.GIT$} $_git_version {} _git_version +regsub {\.[a-zA-Z]+\.[0-9]+$} $_git_version {} _git_version if {![regexp {^[1-9]+(\.[0-9]+)+$} $_git_version]} { catch {wm withdraw .} From 281fdf6921abb11a90a890c09ccce61453050415 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 5 Oct 2007 08:35:41 -0400 Subject: [PATCH 0141/1490] git-gui: Refactor Henrik Nyh's logo into its own procedure By moving the logo into its own procedure we can use it in multiple locations within the UI, but still load it only if the logo is going to be used by the application. Signed-off-by: Shawn O. Pearce --- lib/choose_repository.tcl | 39 +---------------------------------- lib/logo.tcl | 43 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 38 deletions(-) create mode 100644 lib/logo.tcl diff --git a/lib/choose_repository.tcl b/lib/choose_repository.tcl index 16bf67c34f..5d5bc81ad0 100644 --- a/lib/choose_repository.tcl +++ b/lib/choose_repository.tcl @@ -3,38 +3,6 @@ class choose_repository { -# Henrik Nyh's alternative Git logo, from his blog post -# http://henrik.nyh.se/2007/06/alternative-git-logo-and-favicon -# -image create photo ::choose_repository::git_logo -data { -R0lGODdhYQC8AIQbAGZmZtg4LW9vb3l5eYKCgoyMjEC/TOJpYZWVlZ+fn2/PeKmpqbKysry8vMXF -xZ/fpc/Pz7fnvPXNytnZ2eLi4s/v0vja1+zs7Of36fX19f3z8v///////////////////ywAAAAA -YQC8AAAF/uAmjmRpnmiqrmzrvq4hz3RtGw+s7zx5/7dcb0hUAY8zYXHJRCKVzGjPeYRKry8q0Irt -GrVBr3gFDo/PprKNix6ra+y2902Ly7H05L2dl9n3UX04gGeCf4RFhohiiotdjY5XkJGBfYeUOpOY -iZablXmXURgPpKWmp6ipqYIKqq6vqREjFYK1trUKs7e7vFq5IrS9wsM0vxvBxMm8xsjKzqy6z9J5 -zNPWatXX2k7Z29433d/iMuHj3+Xm2+jp1+vs0+7vz/HyyvT1xPf4wvr7y9H+pBkbBasgLFYGE8ba -o8nTlE4OOYGKKJFOKIopGmLMAnHjDo0eWYAM+WUiSRgj/k+eSKmyBMuWI17C3CATZs2WN1XmPLmT -ZM+QPz0G3VihqNGjSJNWwDCzqdOnUKPu0SChqtWrWLNq3cq1q9evYCVYGCEhgNmzaNOqXcu2rdu3 -cOMGOEBWrt27ePPCpSuirN6/gAO35bvBr+DDiPMSNpy4sWO2ix9Lnmw2MuXLiS1j3gxYM+fPdz2D -Hv1WNOnTak2jXj23LuvXlV3DZq16Nujatjnjzo15N2/Kvn9LDi7cMfHimaUqX868ufPn0KPPpOCA -AQMWCQBo3869u/fv4MNrd3DlQoMC3QlkSJFdvPv38LVDWJLBAYHwE1LE38+/+/UhGTAggHv5odDf -gfv9/seDgPAVeAKCELqnIAwU3BefgyZEqOF3E7rAQH8YlrDhiNt1uEIG6IGoH4kjmpjCBRaqaCCL -G7p4AgUDIhgiCTTW2AKOEe44Qo8a2khCBgNoKKQIREZopAgZxAjhkhs0CeGTG7Sn5IpW9vekAyRS -2eWBRl6Q44ZijhlfAQlQmeKIaarpHZsMTHABCxDQGKec3JH3QpIs7snndn6yAKaeXA7aZwuABppo -fAws0GiEhaKQJ40F3DkjfwVC8CaCAlCgAgIkJjDfCgdiOMGn/Q2w3gkZtPgqC6ma0ECECaBwa4QE -aOpCrSYAqeMJpEKYqw7ABnsmfwQ8aCwPySqLYKUb/kwAYbPQyoiCtQcOUMKHBwrgK7LaogBuuaxC -OkS0KEwa37EiLBufALPuwO4Jh/InwAixkknEvSe4C9+p3PY3rr3lpnDufguIcCmzRQAc7IHYLhxf -w/8mnILA74lg8cARa4xCsZxusMCBomZccgsfv0deuh2HvLKh/sLs3hJSvieuCwUzvIHN4tGXc3ih -vtDzmj8fSNLR8BWQdH9LH+g00OFF3d/UBx4cUcvuOc21eFRiouV+Xvvr0dDvlX21R/2uzTR89TqU -L3+5UoBgAxtRHd5/CHpLkd13i4D2e3hHRLKMY+9Hr0Nvx/fq3Pw57cng7/m9wQVObnIyhAiQwHF8 -/tQS8nDgI2wOYeh3CAvhuIBHiDEgqvdtwudkaz3GBPKaTcKuGgqAJRMZmK6h1hnk3ncDcUvhgPFS -o5B476ZKQcECzCN4qgmYN4lAncmzcAEEkhJp+QlfkyhAAdtbN8H67FvHQAF6b4g6v9UryqfkKkBu -v/0prxD//kR63YnqB8AeqcdoBRxU/1zAuwRaaX4reJ4DSSRAHUhwgrgqwgUx2B94EWGDHISPBzUY -QgSNcAn6K6F4fscDCtBOhdoRwPW6kIHDwZA7vWoDBF44Qd/tIUAEBCACbIeG4AXxfmFrQ4B4OCYE -JBEQELChmgbAACJioj4JOCKCCLCABZ6EAg1IHwDlyLYAB1gRJhSYgHUQAD9WnQ9+CWBAA+wknTpC -JwQAOw== -} - field top field w field w_body ; # Widget holding the center content @@ -92,12 +60,7 @@ constructor pick {} { bind $top [list destroy $top] } - label $w.git_logo \ - -borderwidth 1 \ - -relief sunken \ - -background white \ - -image ::choose_repository::git_logo - pack $w.git_logo -side left -fill y -padx 10 -pady 10 + pack [git_logo $w.git_logo] -side left -fill y -padx 10 -pady 10 set w_body $w.body frame $w_body diff --git a/lib/logo.tcl b/lib/logo.tcl new file mode 100644 index 0000000000..5ff76692f5 --- /dev/null +++ b/lib/logo.tcl @@ -0,0 +1,43 @@ +# git-gui Git Gui logo +# Copyright (C) 2007 Shawn Pearce + +# Henrik Nyh's alternative Git logo, from his blog post +# http://henrik.nyh.se/2007/06/alternative-git-logo-and-favicon +# +image create photo ::git_logo_data -data { +R0lGODdhYQC8AIQbAGZmZtg4LW9vb3l5eYKCgoyMjEC/TOJpYZWVlZ+fn2/PeKmpqbKysry8vMXF +xZ/fpc/Pz7fnvPXNytnZ2eLi4s/v0vja1+zs7Of36fX19f3z8v///////////////////ywAAAAA +YQC8AAAF/uAmjmRpnmiqrmzrvq4hz3RtGw+s7zx5/7dcb0hUAY8zYXHJRCKVzGjPeYRKry8q0Irt +GrVBr3gFDo/PprKNix6ra+y2902Ly7H05L2dl9n3UX04gGeCf4RFhohiiotdjY5XkJGBfYeUOpOY +iZablXmXURgPpKWmp6ipqYIKqq6vqREjFYK1trUKs7e7vFq5IrS9wsM0vxvBxMm8xsjKzqy6z9J5 +zNPWatXX2k7Z29433d/iMuHj3+Xm2+jp1+vs0+7vz/HyyvT1xPf4wvr7y9H+pBkbBasgLFYGE8ba +o8nTlE4OOYGKKJFOKIopGmLMAnHjDo0eWYAM+WUiSRgj/k+eSKmyBMuWI17C3CATZs2WN1XmPLmT +ZM+QPz0G3VihqNGjSJNWwDCzqdOnUKPu0SChqtWrWLNq3cq1q9evYCVYGCEhgNmzaNOqXcu2rdu3 +cOMGOEBWrt27ePPCpSuirN6/gAO35bvBr+DDiPMSNpy4sWO2ix9Lnmw2MuXLiS1j3gxYM+fPdz2D +Hv1WNOnTak2jXj23LuvXlV3DZq16Nujatjnjzo15N2/Kvn9LDi7cMfHimaUqX868ufPn0KPPpOCA +AQMWCQBo3869u/fv4MNrd3DlQoMC3QlkSJFdvPv38LVDWJLBAYHwE1LE38+/+/UhGTAggHv5odDf +gfv9/seDgPAVeAKCELqnIAwU3BefgyZEqOF3E7rAQH8YlrDhiNt1uEIG6IGoH4kjmpjCBRaqaCCL +G7p4AgUDIhgiCTTW2AKOEe44Qo8a2khCBgNoKKQIREZopAgZxAjhkhs0CeGTG7Sn5IpW9vekAyRS +2eWBRl6Q44ZijhlfAQlQmeKIaarpHZsMTHABCxDQGKec3JH3QpIs7snndn6yAKaeXA7aZwuABppo +fAws0GiEhaKQJ40F3DkjfwVC8CaCAlCgAgIkJjDfCgdiOMGn/Q2w3gkZtPgqC6ma0ECECaBwa4QE +aOpCrSYAqeMJpEKYqw7ABnsmfwQ8aCwPySqLYKUb/kwAYbPQyoiCtQcOUMKHBwrgK7LaogBuuaxC +OkS0KEwa37EiLBufALPuwO4Jh/InwAixkknEvSe4C9+p3PY3rr3lpnDufguIcCmzRQAc7IHYLhxf +w/8mnILA74lg8cARa4xCsZxusMCBomZccgsfv0deuh2HvLKh/sLs3hJSvieuCwUzvIHN4tGXc3ih +vtDzmj8fSNLR8BWQdH9LH+g00OFF3d/UBx4cUcvuOc21eFRiouV+Xvvr0dDvlX21R/2uzTR89TqU +L3+5UoBgAxtRHd5/CHpLkd13i4D2e3hHRLKMY+9Hr0Nvx/fq3Pw57cng7/m9wQVObnIyhAiQwHF8 +/tQS8nDgI2wOYeh3CAvhuIBHiDEgqvdtwudkaz3GBPKaTcKuGgqAJRMZmK6h1hnk3ncDcUvhgPFS +o5B476ZKQcECzCN4qgmYN4lAncmzcAEEkhJp+QlfkyhAAdtbN8H67FvHQAF6b4g6v9UryqfkKkBu +v/0prxD//kR63YnqB8AeqcdoBRxU/1zAuwRaaX4reJ4DSSRAHUhwgrgqwgUx2B94EWGDHISPBzUY +QgSNcAn6K6F4fscDCtBOhdoRwPW6kIHDwZA7vWoDBF44Qd/tIUAEBCACbIeG4AXxfmFrQ4B4OCYE +JBEQELChmgbAACJioj4JOCKCCLCABZ6EAg1IHwDlyLYAB1gRJhSYgHUQAD9WnQ9+CWBAA+wknTpC +JwQAOw== +} + +proc git_logo {w} { + label $w \ + -borderwidth 1 \ + -relief sunken \ + -background white \ + -image ::git_logo_data + return $w +} From 68099eeeed161fd1adf0822de1dcb388663fc686 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 5 Oct 2007 08:38:35 -0400 Subject: [PATCH 0142/1490] git-gui: Refactor about dialog code into its own module The about dialog is getting somewhat long in size and will probably only get more complex as I try to improve upon its display. As the options dialog is even more complex than the about dialog we move the about dialog into its own module to reduce the complexity of the option dialog module. Signed-off-by: Shawn O. Pearce --- lib/about.tcl | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/option.tcl | 78 ------------------------------------------------ 2 files changed, 80 insertions(+), 78 deletions(-) create mode 100644 lib/about.tcl diff --git a/lib/about.tcl b/lib/about.tcl new file mode 100644 index 0000000000..b19738ecff --- /dev/null +++ b/lib/about.tcl @@ -0,0 +1,80 @@ +# git-gui about git-gui dialog +# Copyright (C) 2006, 2007 Shawn Pearce + +proc do_about {} { + global appvers copyright oguilib + global tcl_patchLevel tk_patchLevel + + set w .about_dialog + toplevel $w + wm geometry $w "+[winfo rootx .]+[winfo rooty .]" + + label $w.header -text [mc "About %s" [appname]] \ + -font font_uibold + pack $w.header -side top -fill x + + frame $w.buttons + button $w.buttons.close -text {Close} \ + -default active \ + -command [list destroy $w] + pack $w.buttons.close -side right + pack $w.buttons -side bottom -fill x -pady 10 -padx 10 + + label $w.desc \ + -text "[mc "git-gui - a graphical user interface for Git."]\n$copyright" \ + -padx 5 -pady 5 \ + -justify left \ + -anchor w \ + -borderwidth 1 \ + -relief solid + pack $w.desc -side top -fill x -padx 5 -pady 5 + + set v {} + append v "git-gui version $appvers\n" + append v "[git version]\n" + append v "\n" + if {$tcl_patchLevel eq $tk_patchLevel} { + append v "Tcl/Tk version $tcl_patchLevel" + } else { + append v "Tcl version $tcl_patchLevel" + append v ", Tk version $tk_patchLevel" + } + + set d {} + append d "git wrapper: $::_git\n" + append d "git exec dir: [gitexec]\n" + append d "git-gui lib: $oguilib" + + label $w.vers \ + -text $v \ + -padx 5 -pady 5 \ + -justify left \ + -anchor w \ + -borderwidth 1 \ + -relief solid + pack $w.vers -side top -fill x -padx 5 -pady 5 + + label $w.dirs \ + -text $d \ + -padx 5 -pady 5 \ + -justify left \ + -anchor w \ + -borderwidth 1 \ + -relief solid + pack $w.dirs -side top -fill x -padx 5 -pady 5 + + menu $w.ctxm -tearoff 0 + $w.ctxm add command \ + -label {Copy} \ + -command " + clipboard clear + clipboard append -format STRING -type STRING -- \[$w.vers cget -text\] + " + + bind $w "grab $w; focus $w.buttons.close" + bind $w "destroy $w" + bind $w "destroy $w" + bind_button3 $w.vers "tk_popup $w.ctxm %X %Y; grab $w; focus $w" + wm title $w "About [appname]" + tkwait window $w +} diff --git a/lib/option.tcl b/lib/option.tcl index 12e297971a..de6bd90edc 100644 --- a/lib/option.tcl +++ b/lib/option.tcl @@ -54,84 +54,6 @@ proc save_config {} { } } -proc do_about {} { - global appvers copyright oguilib - global tcl_patchLevel tk_patchLevel - - set w .about_dialog - toplevel $w - wm geometry $w "+[winfo rootx .]+[winfo rooty .]" - - label $w.header -text [mc "About %s" [appname]] \ - -font font_uibold - pack $w.header -side top -fill x - - frame $w.buttons - button $w.buttons.close -text {Close} \ - -default active \ - -command [list destroy $w] - pack $w.buttons.close -side right - pack $w.buttons -side bottom -fill x -pady 10 -padx 10 - - label $w.desc \ - -text "[mc "git-gui - a graphical user interface for Git."]\n$copyright" \ - -padx 5 -pady 5 \ - -justify left \ - -anchor w \ - -borderwidth 1 \ - -relief solid - pack $w.desc -side top -fill x -padx 5 -pady 5 - - set v {} - append v "git-gui version $appvers\n" - append v "[git version]\n" - append v "\n" - if {$tcl_patchLevel eq $tk_patchLevel} { - append v "Tcl/Tk version $tcl_patchLevel" - } else { - append v "Tcl version $tcl_patchLevel" - append v ", Tk version $tk_patchLevel" - } - - set d {} - append d "git wrapper: $::_git\n" - append d "git exec dir: [gitexec]\n" - append d "git-gui lib: $oguilib" - - label $w.vers \ - -text $v \ - -padx 5 -pady 5 \ - -justify left \ - -anchor w \ - -borderwidth 1 \ - -relief solid - pack $w.vers -side top -fill x -padx 5 -pady 5 - - label $w.dirs \ - -text $d \ - -padx 5 -pady 5 \ - -justify left \ - -anchor w \ - -borderwidth 1 \ - -relief solid - pack $w.dirs -side top -fill x -padx 5 -pady 5 - - menu $w.ctxm -tearoff 0 - $w.ctxm add command \ - -label {Copy} \ - -command " - clipboard clear - clipboard append -format STRING -type STRING -- \[$w.vers cget -text\] - " - - bind $w "grab $w; focus $w.buttons.close" - bind $w "destroy $w" - bind $w "destroy $w" - bind_button3 $w.vers "tk_popup $w.ctxm %X %Y; grab $w; focus $w" - wm title $w "About [appname]" - tkwait window $w -} - proc do_options {} { global repo_config global_config font_descs global repo_config_new global_config_new From 51e1eadb7cd9c8b1943fdc62fe28535bfc032fc6 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 5 Oct 2007 20:15:10 -0400 Subject: [PATCH 0143/1490] git-gui: Include our Git logo in the about dialog Most applications tend to have some sort of pretty image in the about dialog, because it spruces the screen up a little bit and makes the user happy about reading the information shown there. We already have a logo in the repository selection wizard so we can easily reuse this in the about dialog. Signed-off-by: Shawn O. Pearce --- lib/about.tcl | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/about.tcl b/lib/about.tcl index b19738ecff..719fc547b3 100644 --- a/lib/about.tcl +++ b/lib/about.tcl @@ -9,6 +9,7 @@ proc do_about {} { toplevel $w wm geometry $w "+[winfo rootx .]+[winfo rooty .]" + pack [git_logo $w.git_logo] -side left -fill y -padx 10 -pady 10 label $w.header -text [mc "About %s" [appname]] \ -font font_uibold pack $w.header -side top -fill x From 1cad232f92794834c8e70dfc0a1f35431d2c05cd Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Sun, 7 Oct 2007 18:12:31 -0700 Subject: [PATCH 0144/1490] git-gui: Use progress meter in the status bar during index updates If we are updating the index to stage or unstage changes or reverting files in the working directory we can use the progress handling parts of our status bar to perform this display work, reducing the amount of code duplication we have in the index handling module. Unfortunately the status bar is still a strict approximation as it is unable to know when git-update-index has processed the data we fed to it. The progress bar is actually a progress of the pipe buffer filling up in the OS, not of the actual work done. Still, it tells the user we are working and that has some value. Signed-off-by: Shawn O. Pearce --- lib/index.tcl | 54 ++++++++++++--------------------------------------- 1 file changed, 12 insertions(+), 42 deletions(-) diff --git a/lib/index.tcl b/lib/index.tcl index 47255261d2..9e04f2b682 100644 --- a/lib/index.tcl +++ b/lib/index.tcl @@ -12,12 +12,7 @@ proc update_indexinfo {msg pathList after} { set batch [expr {int($totalCnt * .01) + 1}] if {$batch > 25} {set batch 25} - ui_status [format \ - "%s... %i/%i files (%.2f%%)" \ - $msg \ - $update_index_cp \ - $totalCnt \ - 0.0] + $::main_status start $msg [mc "files"] set fd [git_write update-index -z --index-info] fconfigure $fd \ -blocking 0 \ @@ -31,18 +26,18 @@ proc update_indexinfo {msg pathList after} { $pathList \ $totalCnt \ $batch \ - $msg \ $after \ ] } -proc write_update_indexinfo {fd pathList totalCnt batch msg after} { +proc write_update_indexinfo {fd pathList totalCnt batch after} { global update_index_cp global file_states current_diff_path if {$update_index_cp >= $totalCnt} { close $fd unlock_index + $::main_status stop uplevel #0 $after return } @@ -68,12 +63,7 @@ proc write_update_indexinfo {fd pathList totalCnt batch msg after} { display_file $path $new } - ui_status [format \ - "%s... %i/%i files (%.2f%%)" \ - $msg \ - $update_index_cp \ - $totalCnt \ - [expr {100.0 * $update_index_cp / $totalCnt}]] + $::main_status update $update_index_cp $totalCnt } proc update_index {msg pathList after} { @@ -87,12 +77,7 @@ proc update_index {msg pathList after} { set batch [expr {int($totalCnt * .01) + 1}] if {$batch > 25} {set batch 25} - ui_status [format \ - "%s... %i/%i files (%.2f%%)" \ - $msg \ - $update_index_cp \ - $totalCnt \ - 0.0] + $::main_status start $msg [mc "files"] set fd [git_write update-index --add --remove -z --stdin] fconfigure $fd \ -blocking 0 \ @@ -106,18 +91,18 @@ proc update_index {msg pathList after} { $pathList \ $totalCnt \ $batch \ - $msg \ $after \ ] } -proc write_update_index {fd pathList totalCnt batch msg after} { +proc write_update_index {fd pathList totalCnt batch after} { global update_index_cp global file_states current_diff_path if {$update_index_cp >= $totalCnt} { close $fd unlock_index + $::main_status stop uplevel #0 $after return } @@ -147,12 +132,7 @@ proc write_update_index {fd pathList totalCnt batch msg after} { display_file $path $new } - ui_status [format \ - "%s... %i/%i files (%.2f%%)" \ - $msg \ - $update_index_cp \ - $totalCnt \ - [expr {100.0 * $update_index_cp / $totalCnt}]] + $::main_status update $update_index_cp $totalCnt } proc checkout_index {msg pathList after} { @@ -166,12 +146,7 @@ proc checkout_index {msg pathList after} { set batch [expr {int($totalCnt * .01) + 1}] if {$batch > 25} {set batch 25} - ui_status [format \ - "%s... %i/%i files (%.2f%%)" \ - $msg \ - $update_index_cp \ - $totalCnt \ - 0.0] + $::main_status start $msg [mc "files"] set fd [git_write checkout-index \ --index \ --quiet \ @@ -191,18 +166,18 @@ proc checkout_index {msg pathList after} { $pathList \ $totalCnt \ $batch \ - $msg \ $after \ ] } -proc write_checkout_index {fd pathList totalCnt batch msg after} { +proc write_checkout_index {fd pathList totalCnt batch after} { global update_index_cp global file_states current_diff_path if {$update_index_cp >= $totalCnt} { close $fd unlock_index + $::main_status stop uplevel #0 $after return } @@ -222,12 +197,7 @@ proc write_checkout_index {fd pathList totalCnt batch msg after} { } } - ui_status [format \ - "%s... %i/%i files (%.2f%%)" \ - $msg \ - $update_index_cp \ - $totalCnt \ - [expr {100.0 * $update_index_cp / $totalCnt}]] + $::main_status update $update_index_cp $totalCnt } proc unstage_helper {txt paths} { From 6bdf5e5f20c792ad0c5d5ba941d7e637aca86d32 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Sun, 7 Oct 2007 22:23:54 -0700 Subject: [PATCH 0145/1490] git-gui: Consolidate the Fetch and Push menus into a Remote menu Sometimes the Fetch menu looks really odd, such as if you are in a repository that has no remotes configured when you start git-gui. Here we didn't have any items to add to the Fetch menu so it was a tad confusing for the end-user to see an empty menu on the menu bar. We now place all of the commands related to fetching and pushing of changes into a single "Remote" menu. This way we have a better class of bucket that we can drop additional remote related items into such as doing a remote merge or editing the remote configuration specs. The shortcuts to execute fetch/remote prune/push on existing remote specifications are now actually submenus listing the remotes by name. Signed-off-by: Shawn O. Pearce --- git-gui.sh | 20 +++++++++++------- lib/remote.tcl | 55 ++++++++++++++++++++++++++++++-------------------- 2 files changed, 46 insertions(+), 29 deletions(-) diff --git a/git-gui.sh b/git-gui.sh index ca391136c8..c8307a6eef 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -1792,8 +1792,7 @@ if {[is_enabled multicommit] || [is_enabled singlecommit]} { } if {[is_enabled transport]} { .mbar add cascade -label [mc Merge] -menu .mbar.merge - .mbar add cascade -label [mc Fetch] -menu .mbar.fetch - .mbar add cascade -label [mc Push] -menu .mbar.push + .mbar add cascade -label [mc Remote] -menu .mbar.remote } . configure -menu .mbar @@ -2000,13 +1999,14 @@ if {[is_enabled branch]} { # -- Transport Menu # if {[is_enabled transport]} { - menu .mbar.fetch + menu .mbar.remote - menu .mbar.push - .mbar.push add command -label [mc "Push..."] \ + .mbar.remote add command \ + -label [mc "Push..."] \ -command do_push_anywhere \ -accelerator $M1T-P - .mbar.push add command -label [mc "Delete..."] \ + .mbar.remote add command \ + -label [mc "Delete..."] \ -command remote_branch_delete::dialog } @@ -2720,8 +2720,14 @@ user.email settings into your personal if {[is_enabled transport]} { load_all_remotes - populate_fetch_menu + set n [.mbar.remote index end] populate_push_menu + populate_fetch_menu + set n [expr {[.mbar.remote index end] - $n}] + if {$n > 0} { + .mbar.remote insert $n separator + } + unset n } if {[winfo exists $ui_comm]} { diff --git a/lib/remote.tcl b/lib/remote.tcl index aba6eb8343..0e86ddac09 100644 --- a/lib/remote.tcl +++ b/lib/remote.tcl @@ -135,8 +135,10 @@ proc load_all_remotes {} { proc populate_fetch_menu {} { global all_remotes repo_config - set m .mbar.fetch - set prune_list [list] + set remote_m .mbar.remote + set fetch_m $remote_m.fetch + set prune_m $remote_m.prune + foreach r $all_remotes { set enable 0 if {![catch {set a $repo_config(remote.$r.url)}]} { @@ -157,28 +159,34 @@ proc populate_fetch_menu {} { } if {$enable} { - lappend prune_list $r - $m add command \ - -label [mc "Fetch from %s" $r] \ - -command [list fetch_from $r] - } - } + if {![winfo exists $fetch_m]} { + menu $prune_m + $remote_m insert 0 cascade \ + -label [mc "Prune from"] \ + -menu $prune_m - if {$prune_list ne {}} { - $m add separator - } - foreach r $prune_list { - $m add command \ - -label [mc "Prune from %s" $r] \ - -command [list prune_from $r] + menu $fetch_m + $remote_m insert 0 cascade \ + -label [mc "Fetch from"] \ + -menu $fetch_m + } + + $fetch_m add command \ + -label $r \ + -command [list fetch_from $r] + $prune_m add command \ + -label $r \ + -command [list prune_from $r] + } } } proc populate_push_menu {} { global all_remotes repo_config - set m .mbar.push - set fast_count 0 + set remote_m .mbar.remote + set push_m $remote_m.push + foreach r $all_remotes { set enable 0 if {![catch {set a $repo_config(remote.$r.url)}]} { @@ -199,13 +207,16 @@ proc populate_push_menu {} { } if {$enable} { - if {!$fast_count} { - $m add separator + if {![winfo exists $push_m]} { + menu $push_m + $remote_m insert 0 cascade \ + -label [mc "Push to"] \ + -menu $push_m } - $m add command \ - -label [mc "Push to %s" $r] \ + + $push_m add command \ + -label $r \ -command [list push_to $r] - incr fast_count } } } From 13824e2df23c18eab28b2b9a8c112276a84dd419 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Sun, 7 Oct 2007 22:39:08 -0700 Subject: [PATCH 0146/1490] git-gui: Bind Cmd-, to Preferences on Mac OS X A Mac OS X UI convention is to have Cmd-, be the accelerator key for the preferences window, which by convention is located in the apple menu under a separator below the about command. We also now call this "Preferences..." as that is the conventional term used in English. Signed-off-by: Shawn O. Pearce --- git-gui.sh | 8 ++++++-- lib/option.tcl | 12 +++++++----- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/git-gui.sh b/git-gui.sh index c8307a6eef..be506b908c 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -2018,8 +2018,12 @@ if {[is_MacOSX]} { .mbar.apple add command -label [mc "About %s" [appname]] \ -command do_about - .mbar.apple add command -label [mc "Options..."] \ - -command do_options + .mbar.apple add separator + .mbar.apple add command \ + -label [mc "Preferences..."] \ + -command do_options \ + -accelerator $M1T-, + bind . <$M1B-,> do_options } else { # -- Edit Menu # diff --git a/lib/option.tcl b/lib/option.tcl index de6bd90edc..f812e5e89a 100644 --- a/lib/option.tcl +++ b/lib/option.tcl @@ -78,10 +78,6 @@ proc do_options {} { toplevel $w wm geometry $w "+[winfo rootx .]+[winfo rooty .]" - label $w.header -text [mc "Options"] \ - -font font_uibold - pack $w.header -side top -fill x - frame $w.buttons button $w.buttons.restore -text [mc "Restore Defaults"] \ -default normal \ @@ -199,7 +195,13 @@ proc do_options {} { bind $w "grab $w; focus $w.buttons.save" bind $w "destroy $w" bind $w [list do_save_config $w] - wm title $w [append "[appname] ([reponame]): " [mc "Options"]] + + if {[is_MacOSX]} { + set t [mc "Preferences"] + } else { + set t [mc "Options"] + } + wm title $w "[appname] ([reponame]): $t" tkwait window $w } From c73ce762f091688ce6bcd5470239f7c5d1963800 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 5 Oct 2007 08:47:23 -0400 Subject: [PATCH 0147/1490] git-gui: Shorten the staged/unstaged changes title bar text The titles for the staged and unstaged areas were usually opening up too narrow by default, causing the text to be clipped by Tcl as it tried to center the text in the middle of the available area. This meant that users who were new to git-gui did not get to see the entire header and may be unclear about what the different lists are. Signed-off-by: Shawn O. Pearce --- git-gui.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/git-gui.sh b/git-gui.sh index be506b908c..e17efb7d9f 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -2213,7 +2213,7 @@ pack .vpane -anchor n -side top -fill both -expand 1 # -- Index File List # frame .vpane.files.index -height 100 -width 200 -label .vpane.files.index.title -text [mc "Staged Changes (Will Be Committed)"] \ +label .vpane.files.index.title -text [mc "Staged Changes (Will Commit)"] \ -background lightgreen text $ui_index -background white -borderwidth 0 \ -width 20 -height 10 \ @@ -2233,7 +2233,7 @@ pack $ui_index -side left -fill both -expand 1 # -- Working Directory File List # frame .vpane.files.workdir -height 100 -width 200 -label .vpane.files.workdir.title -text [mc "Unstaged Changes (Will Not Be Committed)"] \ +label .vpane.files.workdir.title -text [mc "Unstaged Changes"] \ -background lightsalmon text $ui_workdir -background white -borderwidth 0 \ -width 20 -height 10 \ From 2ce3755a5591354e5aa011254da859889b9be08e Mon Sep 17 00:00:00 2001 From: Christian Stimming Date: Fri, 5 Oct 2007 22:30:32 +0200 Subject: [PATCH 0148/1490] git-gui: Add more words to translation glossary --- po/glossary/git-gui-glossary.pot | 12 ++++++++++-- po/glossary/git-gui-glossary.txt | 2 ++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/po/glossary/git-gui-glossary.pot b/po/glossary/git-gui-glossary.pot index c955b46744..a2e5c73bbd 100644 --- a/po/glossary/git-gui-glossary.pot +++ b/po/glossary/git-gui-glossary.pot @@ -6,12 +6,12 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" -"POT-Creation-Date: 2007-07-27 19:21+0200\n" +"POT-Creation-Date: 2007-10-05 22:30+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" +"Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: ENCODING\n" #. "English Definition (Dear translator: This file will never be visible to the user! It should only serve as a tool for you, the translator. Nothing more.)" @@ -42,6 +42,10 @@ msgstr "" msgid "checkout [verb]" msgstr "" +#. "" +msgid "clone [verb]" +msgstr "" + #. "A single point in the git history." msgid "commit [noun]" msgstr "" @@ -82,6 +86,10 @@ msgstr "" msgid "message" msgstr "" +#. "" +msgid "prune" +msgstr "" + #. "Pulling a branch means to fetch it and merge it." msgid "pull" msgstr "" diff --git a/po/glossary/git-gui-glossary.txt b/po/glossary/git-gui-glossary.txt index bb55aa827d..b53740d48c 100644 --- a/po/glossary/git-gui-glossary.txt +++ b/po/glossary/git-gui-glossary.txt @@ -5,6 +5,7 @@ "branch [verb]" "" "checkout [noun]" "" "checkout [verb]" "The action of updating the working tree to a revision which was stored in the object database." +"clone [verb]" "" "commit [noun]" "A single point in the git history." "commit [verb]" "The action of storing a new snapshot of the project's state in the git history." "diff [noun]" "" @@ -15,6 +16,7 @@ "merge [noun]" "A successful merge results in the creation of a new commit representing the result of the merge." "merge [verb]" "To bring the contents of another branch into the current branch." "message" "" +"prune" "" "pull" "Pulling a branch means to fetch it and merge it." "push" "Pushing a branch means to get the branch's head ref from a remote repository, and ... (well, can someone please explain it for mere mortals?)" "redo" "" From becfb01553ea50c476013d2c31c93eae119fcf64 Mon Sep 17 00:00:00 2001 From: Christian Stimming Date: Fri, 5 Oct 2007 22:32:55 +0200 Subject: [PATCH 0149/1490] git-gui: Update German glossary according to mailing list discussion --- po/glossary/de.po | 45 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/po/glossary/de.po b/po/glossary/de.po index aab3b22f50..054cf4df5a 100644 --- a/po/glossary/de.po +++ b/po/glossary/de.po @@ -6,7 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: git-gui glossary\n" -"PO-Revision-Date: 2007-07-26 14:45+0200\n" +"POT-Creation-Date: 2007-10-05 22:30+0200\n" +"PO-Revision-Date: 2007-10-05 22:32+0200\n" "Last-Translator: Christian Stimming \n" "Language-Team: German \n" "MIME-Version: 1.0\n" @@ -19,11 +20,17 @@ msgid "" msgstr "" "Deutsche Übersetzung.\n" "Andere deutsche SCM:\n" -" http://tortoisesvn.net/docs/release/TortoiseSVN_de/index.html und http://tortoisesvn.tigris.org/svn/tortoisesvn/trunk/Languages/Tortoise_de.po (username=guest, password empty, gut),\n" -" http://msdn.microsoft.com/de-de/library/ms181038(vs.80).aspx (MS Visual Source Safe, kommerziell),\n" -" http://cvsbook.red-bean.com/translations/german/Kap_06.html (mittelmäßig),\n" -" http://tortoisecvs.cvs.sourceforge.net/tortoisecvs/po/TortoiseCVS/de_DE.po?view=markup (mittelmäßig),\n" -" http://rapidsvn.tigris.org/svn/rapidsvn/trunk/src/locale/de/rapidsvn.po (username=guest, password empty, schlecht)" +" http://tortoisesvn.net/docs/release/TortoiseSVN_de/index.html und http://" +"tortoisesvn.tigris.org/svn/tortoisesvn/trunk/Languages/Tortoise_de.po " +"(username=guest, password empty, gut),\n" +" http://msdn.microsoft.com/de-de/library/ms181038(vs.80).aspx (MS Visual " +"Source Safe, kommerziell),\n" +" http://cvsbook.red-bean.com/translations/german/Kap_06.html " +"(mittelmäßig),\n" +" http://tortoisecvs.cvs.sourceforge.net/tortoisecvs/po/TortoiseCVS/de_DE.po?" +"view=markup (mittelmäßig),\n" +" http://rapidsvn.tigris.org/svn/rapidsvn/trunk/src/locale/de/rapidsvn.po " +"(username=guest, password empty, schlecht)" #. "" msgid "amend" @@ -43,19 +50,31 @@ msgstr "verzweigen" #. "" msgid "checkout [noun]" -msgstr "Auscheck? Ausspielung? Abruf? (Source Safe: Auscheckvorgang)" +msgstr "" +"Arbeitskopie (Erstellung einer Arbeitskopie; Auscheck? Ausspielung? Abruf? " +"Source Safe: Auscheckvorgang)" #. "The action of updating the working tree to a revision which was stored in the object database." msgid "checkout [verb]" -msgstr "auschecken? ausspielen? abrufen? (Source Safe: auschecken)" +msgstr "" +"Arbeitskopie erstellen; Zweig umstellen [checkout a branch] (auschecken? " +"ausspielen? abrufen? Source Safe: auschecken)" + +#. "" +msgid "clone [verb]" +msgstr "kopieren" #. "A single point in the git history." msgid "commit [noun]" -msgstr "Übertragung (Sendung?, Übergabe?, Einspielung?, Ablagevorgang?)" +msgstr "" +"Version; Eintragung; Änderung (Buchung?, Eintragung?, Übertragung?, " +"Sendung?, Übergabe?, Einspielung?, Ablagevorgang?)" #. "The action of storing a new snapshot of the project's state in the git history." msgid "commit [verb]" -msgstr "übertragen (TortoiseSVN: übertragen; Source Safe: einchecken; senden?, übergeben?, einspielen?, einpflegen?, ablegen?)" +msgstr "" +"eintragen (TortoiseSVN: übertragen; Source Safe: einchecken; senden?, " +"übergeben?, einspielen?, einpflegen?, ablegen?)" #. "" msgid "diff [noun]" @@ -87,7 +106,11 @@ msgstr "zusammenführen" #. "" msgid "message" -msgstr "Meldung (Nachricht?; Source Safe: Kommentar)" +msgstr "Beschreibung (Meldung?, Nachricht?; Source Safe: Kommentar)" + +#. "" +msgid "prune" +msgstr "löschen" #. "Pulling a branch means to fetch it and merge it." msgid "pull" From aad2dc27636cac9cebd7605a0a57fa50dfb3378e Mon Sep 17 00:00:00 2001 From: Christian Stimming Date: Fri, 5 Oct 2007 22:01:39 +0200 Subject: [PATCH 0150/1490] git-gui: Incorporate glossary changes into existing German translation --- po/de.po | 113 +++++++++++++++++++++++-------------------------------- 1 file changed, 47 insertions(+), 66 deletions(-) diff --git a/po/de.po b/po/de.po index 94b7463ca3..ee69d66b51 100644 --- a/po/de.po +++ b/po/de.po @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: git-gui\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2007-08-11 17:28+0200\n" -"PO-Revision-Date: 2007-08-11 17:37+0200\n" +"PO-Revision-Date: 2007-10-05 22:00+0200\n" "Last-Translator: Christian Stimming \n" "Language-Team: German\n" "MIME-Version: 1.0\n" @@ -80,15 +80,15 @@ msgstr "Verändert, nicht bereitgestellt" #: git-gui.sh:1325 git-gui.sh:1330 msgid "Staged for commit" -msgstr "Bereitgestellt zur Übertragung" +msgstr "Bereitgestellt zum Eintragen" #: git-gui.sh:1326 git-gui.sh:1331 msgid "Portions staged for commit" -msgstr "Teilweise bereitgestellt zur Übertragung" +msgstr "Teilweise bereitgestellt zum Eintragen" #: git-gui.sh:1327 git-gui.sh:1332 msgid "Staged for commit, missing" -msgstr "Bereitgestellt zur Übertragung, fehlend" +msgstr "Bereitgestellt zum Eintragen, fehlend" #: git-gui.sh:1329 msgid "Untracked, not staged" @@ -152,7 +152,7 @@ msgstr "Zweig" #: git-gui.sh:1655 git-gui.sh:1842 git-gui.sh:2152 msgid "Commit" -msgstr "Übertragen" +msgstr "Eintragen" #: git-gui.sh:1658 lib/merge.tcl:121 lib/merge.tcl:150 lib/merge.tcl:168 msgid "Merge" @@ -249,7 +249,7 @@ msgstr "Erstellen..." #: git-gui.sh:1764 msgid "Checkout..." -msgstr "Auschecken..." +msgstr "Arbeitskopie erstellen..." #: git-gui.sh:1770 msgid "Rename..." @@ -265,11 +265,11 @@ msgstr "Zurücksetzen..." #: git-gui.sh:1792 git-gui.sh:2169 msgid "New Commit" -msgstr "Neu übertragen" +msgstr "Neue Version" #: git-gui.sh:1800 git-gui.sh:2176 msgid "Amend Last Commit" -msgstr "Letzte Übertragung nachbessern" +msgstr "Letzte Version nachbessern" #: git-gui.sh:1809 git-gui.sh:2136 lib/remote_branch_delete.tcl:99 msgid "Rescan" @@ -277,11 +277,11 @@ msgstr "Neu laden" #: git-gui.sh:1815 msgid "Stage To Commit" -msgstr "Zur Übertragung bereitstellen" +msgstr "Zum Eintragen bereitstellen" #: git-gui.sh:1820 msgid "Stage Changed Files To Commit" -msgstr "Geänderte Dateien zur Übertragung bereitstellen" +msgstr "Geänderte Dateien zum Eintragen bereitstellen" #: git-gui.sh:1826 msgid "Unstage From Commit" @@ -334,11 +334,11 @@ msgstr "Aktueller Zweig:" #: git-gui.sh:2075 msgid "Staged Changes (Will Be Committed)" -msgstr "Bereitgestellte Änderungen (werden übertragen)" +msgstr "Bereitgestellte Änderungen (werden eingetragen)" #: git-gui.sh:2095 msgid "Unstaged Changes (Will Not Be Committed)" -msgstr "Nicht bereitgestellte Änderungen (werden nicht übertragen)" +msgstr "Nicht bereitgestellte Änderungen (werden nicht eingetragen)" #: git-gui.sh:2142 msgid "Stage Changed" @@ -346,27 +346,27 @@ msgstr "Geänderte bereitstellen" #: git-gui.sh:2188 msgid "Initial Commit Message:" -msgstr "Erstmalige Übertragungsmeldung" +msgstr "Beschreibung der ersten Version:" #: git-gui.sh:2189 msgid "Amended Commit Message:" -msgstr "Übertragungsmeldung mit Nachbesserung:" +msgstr "Beschreibung der nachgebesserten Version:" #: git-gui.sh:2190 msgid "Amended Initial Commit Message:" -msgstr "Erstmalige Übertragungsmeldung mit Nachbesserung:" +msgstr "Beschreibung der nachgebesserten ersten Version:" #: git-gui.sh:2191 msgid "Amended Merge Commit Message:" -msgstr "Zusammenführungs-Übertragungsmeldung mit Nachbesserung" +msgstr "Beschreibung der nachgebesserten Zusammenführungs-Version:" #: git-gui.sh:2192 msgid "Merge Commit Message:" -msgstr "Übertragungsmeldung Zusammenführung:" +msgstr "Beschreibung der Zusammenführungs-Version:" #: git-gui.sh:2193 msgid "Commit Message:" -msgstr "Übertragungsmeldung:" +msgstr "Versionsbeschreibung:" #: git-gui.sh:2238 git-gui.sh:2376 lib/console.tcl:73 msgid "Copy All" @@ -418,11 +418,11 @@ msgstr "Datei-Browser" #: lib/blame.tcl:81 msgid "Commit:" -msgstr "Übertragung:" +msgstr "Version:" #: lib/blame.tcl:249 msgid "Copy Commit" -msgstr "Übertragung kopieren" +msgstr "Version kopieren" #: lib/blame.tcl:369 #, tcl-format @@ -431,11 +431,11 @@ msgstr "%s lesen..." #: lib/branch_checkout.tcl:14 lib/branch_checkout.tcl:19 msgid "Checkout Branch" -msgstr "Zweig auschecken" +msgstr "Zweig umstellen" #: lib/branch_checkout.tcl:23 msgid "Checkout" -msgstr "Auschecken" +msgstr "Umstellen" #: lib/branch_checkout.tcl:27 lib/branch_create.tcl:35 #: lib/branch_delete.tcl:32 lib/branch_rename.tcl:30 lib/browser.tcl:283 @@ -507,7 +507,7 @@ msgstr "Zurücksetzen" #: lib/branch_create.tcl:97 msgid "Checkout After Creation" -msgstr "Auschecken nach Erstellen" +msgstr "Arbeitskopie umstellen nach Erstellen" #: lib/branch_create.tcl:131 msgid "Please select a tracking branch." @@ -686,8 +686,7 @@ msgstr "" #: lib/checkout_op.tcl:353 #, tcl-format msgid "Aborted checkout of '%s' (file level merging is required)." -msgstr "" -"Auschecken von »%s« abgebrochen (Zusammenführen der Dateien ist notwendig)." +msgstr "Zweig umstellen von »%s« abgebrochen (Zusammenführen der Dateien ist notwendig)." #: lib/checkout_op.tcl:354 msgid "File level merge required." @@ -707,8 +706,7 @@ msgid "" msgstr "" "Die Arbeitskopie ist nicht auf einem lokalen Zweig.\n" "\n" -"Wenn Sie auf einem Zwei arbeiten möchten, erstellen Sie bitte jetzt einen " -"Zweig mit der Auswahl »Abgetrennte Auscheck-Version«." +"Wenn Sie auf einem Zweig arbeiten möchten, erstellen Sie bitte jetzt einen Zweig mit der Auswahl »Abgetrennte Arbeitskopie-Version«." #: lib/checkout_op.tcl:478 #, tcl-format @@ -750,7 +748,7 @@ msgstr "" #: lib/choose_rev.tcl:53 msgid "This Detached Checkout" -msgstr "Abgetrennte Auscheck-Version" +msgstr "Abgetrennte Arbeitskopie-Version" #: lib/choose_rev.tcl:60 msgid "Revision Expression:" @@ -831,8 +829,7 @@ msgid "" msgstr "" "Der letzte geladene Status stimmt nicht mehr mit dem Projektarchiv überein.\n" "\n" -"Ein anderes Git-Programm hat das Projektarchiv seit dem letzten Laden " -"geändert. Vor einer neuen Übertragung muss neu geladen werden.\n" +"Ein anderes Git-Programm hat das Projektarchiv seit dem letzten Laden geändert. Vor dem Eintragen einer neuen Version muss neu geladen werden.\n" "\n" "Es wird gleich neu geladen.\n" @@ -844,10 +841,9 @@ msgid "" "File %s has merge conflicts. You must resolve them and stage the file " "before committing.\n" msgstr "" -"Nicht zusammengeführte Dateien können nicht übertragen werden.\n" +"Nicht zusammengeführte Dateien können nicht eingetragen werden.\n" "\n" -"Die Datei %s hat noch nicht aufgelöste Zusammenführungs-Konflikte. Sie " -"müssen diese Konflikte auflösen, bevor Sie übertragen können.\n" +"Die Datei »%s« hat noch nicht aufgelöste Zusammenführungs-Konflikte. Sie müssen diese Konflikte auflösen, bevor Sie eintragen können.\n" #: lib/commit.tcl:162 #, tcl-format @@ -858,7 +854,7 @@ msgid "" msgstr "" "Unbekannter Dateizustand »%s«.\n" "\n" -"Datei »%s« kann nicht übertragen werden.\n" +"Datei »%s« kann nicht eingetragen werden.\n" #: lib/commit.tcl:170 msgid "" @@ -866,10 +862,9 @@ msgid "" "\n" "You must stage at least 1 file before you can commit.\n" msgstr "" -"Keine Änderungen vorhanden, die übertragen werden könnten.\n" +"Keine Änderungen vorhanden, die eingetragen werden könnten.\n" "\n" -"Sie müssen mindestens eine Datei bereitstellen, bevor Sie übertragen " -"können.\n" +"Sie müssen mindestens eine Datei bereitstellen, bevor Sie eintragen können.\n" #: lib/commit.tcl:183 msgid "" @@ -881,16 +876,15 @@ msgid "" "- Second line: Blank\n" "- Remaining lines: Describe why this change is good.\n" msgstr "" -"Bitte geben Sie eine Übertragungsmeldung ein.\n" +"Bitte geben Sie eine Versionsbeschreibung ein.\n" "\n" -"Eine gute Übertragungsmeldung enthält folgende Abschnitte:\n" +"Eine gute Versionsbeschreibung enthält folgende Abschnitte:\n" "\n" "- Erste Zeile: Eine Zusammenfassung, was man gemacht hat.\n" "\n" "- Zweite Zeile: Leerzeile\n" "\n" -"- Rest der Meldung: Eine ausführliche Beschreibung, warum diese Änderung " -"hilfreich ist.\n" +"- Rest: Eine ausführliche Beschreibung, warum diese Änderung hilfreich ist.\n" #: lib/commit.tcl:257 msgid "write-tree failed:" @@ -904,16 +898,15 @@ msgid "" "\n" "A rescan will be automatically started now.\n" msgstr "" -"Keine Änderungen zu übertragen.\n" +"Keine Änderungen einzutragen.\n" "\n" -"Es gibt keine geänderte Datei bei dieser Übertragung und es wurde auch " -"nichts zusammengeführt.\n" +"Es gibt keine geänderte Datei bei dieser Version und es wurde auch nichts zusammengeführt.\n" "\n" "Das Arbeitsverzeichnis wird daher jetzt neu geladen.\n" #: lib/commit.tcl:286 msgid "No changes to commit." -msgstr "Keine Änderungen, die übertragen werden können." +msgstr "Keine Änderungen, die eingetragen werden können." #: lib/commit.tcl:317 msgid "commit-tree failed:" @@ -1024,8 +1017,7 @@ msgstr "Warnung" #: lib/error.tcl:81 msgid "You must correct the above errors before committing." -msgstr "" -"Sie müssen die obigen Fehler zuerst beheben, bevor Sie übertragen können." +msgstr "Sie müssen die obigen Fehler zuerst beheben, bevor Sie eintragen können." #: lib/index.tcl:364 #, tcl-format @@ -1054,8 +1046,7 @@ msgid "" msgstr "" "Zusammenführen kann nicht gleichzeitig mit Nachbessern durchgeführt werden.\n" "\n" -"Sie müssen zuerst die Nachbesserungs-Übertragung abschließen, bevor Sie " -"zusammenführen können.\n" +"Sie müssen zuerst die Nachbesserungs-Version abschließen, bevor Sie zusammenführen können.\n" #: lib/merge.tcl:27 msgid "" @@ -1085,10 +1076,7 @@ msgid "" msgstr "" "Zusammenführung mit Konflikten.\n" "\n" -"Die Datei »%s« enthält Konflikte beim Zusammenführen. Sie müssen diese " -"Konflikte per Hand auflösen. Anschließend müssen Sie die Datei wieder " -"bereitstellen und übertragen, um die Zusammenführung abzuschließen. Erst " -"danach kann eine neue Zusammenführung begonnen werden.\n" +"Die Datei »%s« enthält Konflikte beim Zusammenführen. Sie müssen diese Konflikte per Hand auflösen. Anschließend müssen Sie die Datei wieder bereitstellen und eintragen, um die Zusammenführung abzuschließen. Erst danach kann eine neue Zusammenführung begonnen werden.\n" #: lib/merge.tcl:54 #, tcl-format @@ -1102,10 +1090,7 @@ msgid "" msgstr "" "Es liegen Änderungen vor.\n" "\n" -"Die Datei »%s« wurde geändert. Sie sollten zuerst die bereitgestellte " -"Übertragung abschließen, bevor Sie eine Zusammenführung beginnen. Mit " -"dieser Reihenfolge können Sie mögliche Konflikte beim Zusammenführen " -"wesentlich einfacher beheben oder abbrechen.\n" +"Die Datei »%s« wurde geändert. Sie sollten zuerst die bereitgestellte Version abschließen, bevor Sie eine Zusammenführung beginnen. Mit dieser Reihenfolge können Sie mögliche Konflikte beim Zusammenführen wesentlich einfacher beheben oder abbrechen.\n" #: lib/merge.tcl:106 #, tcl-format @@ -1142,7 +1127,7 @@ msgid "" msgstr "" "Abbruch der Nachbesserung ist nicht möglich.\n" "\n" -"Sie müssen die Nachbesserung der Übertragung abschließen.\n" +"Sie müssen die Nachbesserung der Version abschließen.\n" #: lib/merge.tcl:222 msgid "" @@ -1154,7 +1139,7 @@ msgid "" msgstr "" "Zusammenführen abbrechen?\n" "\n" -"Wenn Sie abbrechen, gehen alle noch nicht übertragenen Änderungen verloren.\n" +"Wenn Sie abbrechen, gehen alle noch nicht eingetragenen Änderungen verloren.\n" "\n" "Zusammenführen jetzt abbrechen?" @@ -1168,8 +1153,7 @@ msgid "" msgstr "" "Änderungen zurücksetzen?\n" "\n" -"Wenn Sie zurücksetzen, gehen alle noch nicht übertragenen Änderungen " -"verloren.\n" +"Wenn Sie zurücksetzen, gehen alle noch nicht eingetragenen Änderungen verloren.\n" "\n" "Änderungen jetzt zurücksetzen?" @@ -1216,7 +1200,7 @@ msgstr "E-Mail-Adresse" #: lib/option.tcl:188 msgid "Summarize Merge Commits" -msgstr "Zusammenführungs-Übertragungen zusammenfassen" +msgstr "Zusammenführungs-Versionen zusammenfassen" #: lib/option.tcl:189 msgid "Merge Verbosity" @@ -1291,10 +1275,7 @@ msgstr "Für »Zusammenführen mit« muss ein Zweig angegeben werden." msgid "" "One or more of the merge tests failed because you have not fetched the " "necessary commits. Try fetching from %s first." -msgstr "" -"Ein oder mehrere Zusammenführungen sind fehlgeschlagen, da Sie nicht die " -"notwendigen Versionen vorher angefordert haben. Sie sollten versuchen, " -"zuerst von »%s« anzufordern." +msgstr "Ein oder mehrere Zusammenführungen sind fehlgeschlagen, da Sie nicht die notwendigen Versionen vorher angefordert haben. Sie sollten versuchen, zuerst von »%s« anzufordern." #: lib/remote_branch_delete.tcl:207 msgid "Please select one or more branches to delete." From 1d6e05f6bda69c4e066f61a85bfdd6d10ca209c0 Mon Sep 17 00:00:00 2001 From: Christian Stimming Date: Mon, 8 Oct 2007 21:34:56 +0200 Subject: [PATCH 0151/1490] git-gui: Update German translation, including latest glossary changes --- po/de.po | 798 +++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 633 insertions(+), 165 deletions(-) diff --git a/po/de.po b/po/de.po index ee69d66b51..60b9ea52dc 100644 --- a/po/de.po +++ b/po/de.po @@ -7,23 +7,41 @@ msgid "" msgstr "" "Project-Id-Version: git-gui\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2007-08-11 17:28+0200\n" -"PO-Revision-Date: 2007-10-05 22:00+0200\n" +"POT-Creation-Date: 2007-10-05 22:01+0200\n" +"PO-Revision-Date: 2007-10-05 22:27+0200\n" "Last-Translator: Christian Stimming \n" "Language-Team: German\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: git-gui.sh:531 +#: git-gui.sh:41 git-gui.sh:631 git-gui.sh:645 git-gui.sh:658 git-gui.sh:740 +#: git-gui.sh:759 +msgid "git-gui: fatal error" +msgstr "git-gui: Programmfehler" + +#: git-gui.sh:592 +#, tcl-format +msgid "Invalid font specified in %s:" +msgstr "Ungültige Zeichensatz-Angabe in %s:" + +#: git-gui.sh:617 +msgid "Main Font" +msgstr "Programmschriftart" + +#: git-gui.sh:618 +msgid "Diff/Console Font" +msgstr "Vergleich-Schriftart" + +#: git-gui.sh:632 msgid "Cannot find git in PATH." msgstr "Git kann im PATH nicht gefunden werden." -#: git-gui.sh:550 +#: git-gui.sh:659 msgid "Cannot parse Git version string:" msgstr "Git Versionsangabe kann nicht erkannt werden:" -#: git-gui.sh:567 +#: git-gui.sh:676 #, tcl-format msgid "" "Git version cannot be determined.\n" @@ -42,79 +60,79 @@ msgstr "" "\n" "Soll angenommen werden, »%s« sei Version 1.5.0?\n" -#: git-gui.sh:689 -msgid "Cannot find the git directory:" -msgstr "Git-Verzeichnis kann nicht gefunden werden:" - -#: git-gui.sh:697 +#: git-gui.sh:849 msgid "Git directory not found:" msgstr "Git-Verzeichnis nicht gefunden:" -#: git-gui.sh:703 +#: git-gui.sh:856 +msgid "Cannot move to top of working directory:" +msgstr "Es konnte nicht in das oberste Verzeichnis der Arbeitskopie gewechselt werden:" + +#: git-gui.sh:863 msgid "Cannot use funny .git directory:" msgstr "Unerwartete Struktur des .git Verzeichnis:" -#: git-gui.sh:708 +#: git-gui.sh:868 msgid "No working directory" msgstr "Kein Arbeitsverzeichnis" -#: git-gui.sh:854 +#: git-gui.sh:1015 msgid "Refreshing file status..." msgstr "Dateistatus aktualisieren..." -#: git-gui.sh:891 +#: git-gui.sh:1080 msgid "Scanning for modified files ..." msgstr "Nach geänderten Dateien suchen..." -#: git-gui.sh:1057 lib/browser.tcl:247 +#: git-gui.sh:1255 lib/browser.tcl:245 msgid "Ready." msgstr "Bereit." -#: git-gui.sh:1322 +#: git-gui.sh:1521 msgid "Unmodified" msgstr "Unverändert" -#: git-gui.sh:1324 +#: git-gui.sh:1523 msgid "Modified, not staged" msgstr "Verändert, nicht bereitgestellt" -#: git-gui.sh:1325 git-gui.sh:1330 +#: git-gui.sh:1524 git-gui.sh:1529 msgid "Staged for commit" msgstr "Bereitgestellt zum Eintragen" -#: git-gui.sh:1326 git-gui.sh:1331 +#: git-gui.sh:1525 git-gui.sh:1530 msgid "Portions staged for commit" msgstr "Teilweise bereitgestellt zum Eintragen" -#: git-gui.sh:1327 git-gui.sh:1332 +#: git-gui.sh:1526 git-gui.sh:1531 msgid "Staged for commit, missing" msgstr "Bereitgestellt zum Eintragen, fehlend" -#: git-gui.sh:1329 +#: git-gui.sh:1528 msgid "Untracked, not staged" msgstr "Nicht unter Versionskontrolle, nicht bereitgestellt" -#: git-gui.sh:1334 +#: git-gui.sh:1533 msgid "Missing" msgstr "Fehlend" -#: git-gui.sh:1335 +#: git-gui.sh:1534 msgid "Staged for removal" msgstr "Bereitgestellt zum Löschen" -#: git-gui.sh:1336 +#: git-gui.sh:1535 msgid "Staged for removal, still present" msgstr "Bereitgestellt zum Löschen, trotzdem vorhanden" -#: git-gui.sh:1338 git-gui.sh:1339 git-gui.sh:1340 git-gui.sh:1341 +#: git-gui.sh:1537 git-gui.sh:1538 git-gui.sh:1539 git-gui.sh:1540 msgid "Requires merge resolution" msgstr "Konfliktauflösung nötig" -#: git-gui.sh:1383 +#: git-gui.sh:1575 msgid "Starting gitk... please wait..." msgstr "Gitk wird gestartet... bitte warten." -#: git-gui.sh:1392 +#: git-gui.sh:1584 #, tcl-format msgid "" "Unable to start gitk:\n" @@ -125,293 +143,319 @@ msgstr "" "\n" "%s existiert nicht" -#: git-gui.sh:1609 -#, tcl-format -msgid "Invalid font specified in gui.%s:" -msgstr "Ungültige Zeichensatz-Angabe in gui.%s:" - -#: git-gui.sh:1634 -msgid "Main Font" -msgstr "Programmschriftart" - -#: git-gui.sh:1635 -msgid "Diff/Console Font" -msgstr "Vergleich-Schriftart" - -#: git-gui.sh:1649 +#: git-gui.sh:1784 lib/choose_repository.tcl:64 msgid "Repository" msgstr "Projektarchiv" -#: git-gui.sh:1650 +#: git-gui.sh:1785 msgid "Edit" msgstr "Bearbeiten" -#: git-gui.sh:1652 +#: git-gui.sh:1787 lib/choose_rev.tcl:560 msgid "Branch" msgstr "Zweig" -#: git-gui.sh:1655 git-gui.sh:1842 git-gui.sh:2152 -msgid "Commit" -msgstr "Eintragen" +#: git-gui.sh:1790 lib/choose_rev.tcl:547 +msgid "Commit@@noun" +msgstr "Version" -#: git-gui.sh:1658 lib/merge.tcl:121 lib/merge.tcl:150 lib/merge.tcl:168 +#: git-gui.sh:1793 lib/merge.tcl:121 lib/merge.tcl:150 lib/merge.tcl:168 msgid "Merge" msgstr "Zusammenführen" -#: git-gui.sh:1659 +#: git-gui.sh:1794 msgid "Fetch" msgstr "Anfordern" -#: git-gui.sh:1660 git-gui.sh:2158 lib/transport.tcl:88 lib/transport.tcl:172 +#: git-gui.sh:1795 git-gui.sh:2294 lib/transport.tcl:93 lib/transport.tcl:182 msgid "Push" msgstr "Ausliefern" -#: git-gui.sh:1669 +#: git-gui.sh:1804 msgid "Browse Current Branch's Files" msgstr "Aktuellen Zweig durchblättern" -#: git-gui.sh:1673 +#: git-gui.sh:1808 msgid "Browse Branch Files..." msgstr "Einen Zweig durchblättern..." -#: git-gui.sh:1678 +#: git-gui.sh:1813 msgid "Visualize Current Branch's History" msgstr "Aktuellen Zweig darstellen" -#: git-gui.sh:1682 +#: git-gui.sh:1817 msgid "Visualize All Branch History" msgstr "Alle Zweige darstellen" -#: git-gui.sh:1689 +#: git-gui.sh:1824 #, tcl-format msgid "Browse %s's Files" msgstr "Zweig »%s« durchblättern" -#: git-gui.sh:1691 +#: git-gui.sh:1826 #, tcl-format msgid "Visualize %s's History" msgstr "Historie von »%s« darstellen" -#: git-gui.sh:1696 lib/database.tcl:27 lib/database.tcl:67 +#: git-gui.sh:1831 lib/database.tcl:27 lib/database.tcl:67 msgid "Database Statistics" msgstr "Datenbankstatistik" -#: git-gui.sh:1699 lib/database.tcl:34 +#: git-gui.sh:1834 lib/database.tcl:34 msgid "Compress Database" msgstr "Datenbank komprimieren" -#: git-gui.sh:1702 +#: git-gui.sh:1837 msgid "Verify Database" msgstr "Datenbank überprüfen" -#: git-gui.sh:1709 git-gui.sh:1713 git-gui.sh:1717 lib/shortcut.tcl:9 +#: git-gui.sh:1844 git-gui.sh:1848 git-gui.sh:1852 lib/shortcut.tcl:9 #: lib/shortcut.tcl:45 lib/shortcut.tcl:84 msgid "Create Desktop Icon" msgstr "Desktop-Icon erstellen" -#: git-gui.sh:1722 +#: git-gui.sh:1857 lib/choose_repository.tcl:68 lib/choose_repository.tcl:132 msgid "Quit" msgstr "Beenden" -#: git-gui.sh:1729 +#: git-gui.sh:1864 msgid "Undo" msgstr "Rückgängig" -#: git-gui.sh:1732 +#: git-gui.sh:1867 msgid "Redo" msgstr "Wiederholen" -#: git-gui.sh:1736 git-gui.sh:2222 +#: git-gui.sh:1871 git-gui.sh:2358 msgid "Cut" msgstr "Ausschneiden" -#: git-gui.sh:1739 git-gui.sh:2225 git-gui.sh:2296 git-gui.sh:2368 -#: lib/console.tcl:69 +#: git-gui.sh:1874 git-gui.sh:2361 git-gui.sh:2432 git-gui.sh:2504 +#: lib/console.tcl:67 msgid "Copy" msgstr "Kopieren" -#: git-gui.sh:1742 git-gui.sh:2228 +#: git-gui.sh:1877 git-gui.sh:2364 msgid "Paste" msgstr "Einfügen" -#: git-gui.sh:1745 git-gui.sh:2231 lib/branch_delete.tcl:26 +#: git-gui.sh:1880 git-gui.sh:2367 lib/branch_delete.tcl:26 #: lib/remote_branch_delete.tcl:38 msgid "Delete" msgstr "Löschen" -#: git-gui.sh:1749 git-gui.sh:2235 git-gui.sh:2372 lib/console.tcl:71 +#: git-gui.sh:1884 git-gui.sh:2371 git-gui.sh:2508 lib/console.tcl:69 msgid "Select All" msgstr "Alle auswählen" -#: git-gui.sh:1758 +#: git-gui.sh:1893 msgid "Create..." msgstr "Erstellen..." -#: git-gui.sh:1764 +#: git-gui.sh:1899 msgid "Checkout..." -msgstr "Arbeitskopie erstellen..." +msgstr "Umstellen..." -#: git-gui.sh:1770 +#: git-gui.sh:1905 msgid "Rename..." msgstr "Umbenennen..." -#: git-gui.sh:1775 git-gui.sh:1873 +#: git-gui.sh:1910 git-gui.sh:2008 msgid "Delete..." msgstr "Löschen..." -#: git-gui.sh:1780 +#: git-gui.sh:1915 msgid "Reset..." msgstr "Zurücksetzen..." -#: git-gui.sh:1792 git-gui.sh:2169 +#: git-gui.sh:1927 git-gui.sh:2305 msgid "New Commit" msgstr "Neue Version" -#: git-gui.sh:1800 git-gui.sh:2176 +#: git-gui.sh:1935 git-gui.sh:2312 msgid "Amend Last Commit" msgstr "Letzte Version nachbessern" -#: git-gui.sh:1809 git-gui.sh:2136 lib/remote_branch_delete.tcl:99 +#: git-gui.sh:1944 git-gui.sh:2272 lib/remote_branch_delete.tcl:99 msgid "Rescan" msgstr "Neu laden" -#: git-gui.sh:1815 +#: git-gui.sh:1950 msgid "Stage To Commit" msgstr "Zum Eintragen bereitstellen" -#: git-gui.sh:1820 +#: git-gui.sh:1955 msgid "Stage Changed Files To Commit" msgstr "Geänderte Dateien zum Eintragen bereitstellen" -#: git-gui.sh:1826 +#: git-gui.sh:1961 msgid "Unstage From Commit" msgstr "Aus der Bereitstellung herausnehmen" -#: git-gui.sh:1831 lib/index.tcl:376 +#: git-gui.sh:1966 lib/index.tcl:382 msgid "Revert Changes" msgstr "Änderungen revidieren" -#: git-gui.sh:1838 git-gui.sh:2148 git-gui.sh:2246 +#: git-gui.sh:1973 git-gui.sh:2284 git-gui.sh:2382 msgid "Sign Off" msgstr "Abzeichnen" -#: git-gui.sh:1853 +#: git-gui.sh:1977 git-gui.sh:2288 +msgid "Commit@@verb" +msgstr "Eintragen" + +#: git-gui.sh:1988 msgid "Local Merge..." msgstr "Lokales Zusammenführen..." -#: git-gui.sh:1858 +#: git-gui.sh:1993 msgid "Abort Merge..." msgstr "Zusammenführen abbrechen..." -#: git-gui.sh:1870 +#: git-gui.sh:2005 msgid "Push..." msgstr "Ausliefern..." -#: git-gui.sh:1880 +#: git-gui.sh:2015 lib/choose_repository.tcl:73 msgid "Apple" msgstr "Apple" -#: git-gui.sh:1883 git-gui.sh:1901 lib/option.tcl:65 +#: git-gui.sh:2018 git-gui.sh:2036 lib/choose_repository.tcl:76 +#: lib/choose_repository.tcl:82 lib/option.tcl:65 #, tcl-format msgid "About %s" msgstr "Über %s" -#: git-gui.sh:1885 git-gui.sh:1891 git-gui.sh:2414 +#: git-gui.sh:2020 git-gui.sh:2026 git-gui.sh:2550 msgid "Options..." msgstr "Optionen..." -#: git-gui.sh:1897 +#: git-gui.sh:2032 lib/choose_repository.tcl:79 msgid "Help" msgstr "Hilfe" -#: git-gui.sh:1938 +#: git-gui.sh:2073 msgid "Online Documentation" msgstr "Online-Dokumentation" -#: git-gui.sh:2054 +#: git-gui.sh:2157 +#, tcl-format +msgid "fatal: cannot stat path %s: No such file or directory" +msgstr "" + +#: git-gui.sh:2190 msgid "Current Branch:" msgstr "Aktueller Zweig:" -#: git-gui.sh:2075 +#: git-gui.sh:2211 msgid "Staged Changes (Will Be Committed)" msgstr "Bereitgestellte Änderungen (werden eingetragen)" -#: git-gui.sh:2095 +#: git-gui.sh:2231 msgid "Unstaged Changes (Will Not Be Committed)" msgstr "Nicht bereitgestellte Änderungen (werden nicht eingetragen)" -#: git-gui.sh:2142 +#: git-gui.sh:2278 msgid "Stage Changed" msgstr "Geänderte bereitstellen" -#: git-gui.sh:2188 +#: git-gui.sh:2324 msgid "Initial Commit Message:" msgstr "Beschreibung der ersten Version:" -#: git-gui.sh:2189 +#: git-gui.sh:2325 msgid "Amended Commit Message:" msgstr "Beschreibung der nachgebesserten Version:" -#: git-gui.sh:2190 +#: git-gui.sh:2326 msgid "Amended Initial Commit Message:" msgstr "Beschreibung der nachgebesserten ersten Version:" -#: git-gui.sh:2191 +#: git-gui.sh:2327 msgid "Amended Merge Commit Message:" msgstr "Beschreibung der nachgebesserten Zusammenführungs-Version:" -#: git-gui.sh:2192 +#: git-gui.sh:2328 msgid "Merge Commit Message:" msgstr "Beschreibung der Zusammenführungs-Version:" -#: git-gui.sh:2193 +#: git-gui.sh:2329 msgid "Commit Message:" msgstr "Versionsbeschreibung:" -#: git-gui.sh:2238 git-gui.sh:2376 lib/console.tcl:73 +#: git-gui.sh:2374 git-gui.sh:2512 lib/console.tcl:71 msgid "Copy All" msgstr "Alle kopieren" -#: git-gui.sh:2262 lib/blame.tcl:104 +#: git-gui.sh:2398 lib/blame.tcl:104 msgid "File:" msgstr "Datei:" -#: git-gui.sh:2364 +#: git-gui.sh:2500 msgid "Refresh" msgstr "Aktualisieren" -#: git-gui.sh:2385 +#: git-gui.sh:2521 msgid "Apply/Reverse Hunk" msgstr "Änderung anwenden/umkehren" -#: git-gui.sh:2391 +#: git-gui.sh:2527 msgid "Decrease Font Size" msgstr "Schriftgröße verkleinern" -#: git-gui.sh:2395 +#: git-gui.sh:2531 msgid "Increase Font Size" msgstr "Schriftgröße vergrößern" -#: git-gui.sh:2400 +#: git-gui.sh:2536 msgid "Show Less Context" msgstr "Weniger Kontext anzeigen" -#: git-gui.sh:2407 +#: git-gui.sh:2543 msgid "Show More Context" msgstr "Mehr Kontext anzeigen" -#: git-gui.sh:2422 +#: git-gui.sh:2557 msgid "Unstage Hunk From Commit" msgstr "Aus der Bereitstellung herausnehmen" -#: git-gui.sh:2426 git-gui.sh:2430 +#: git-gui.sh:2559 msgid "Stage Hunk For Commit" msgstr "In die Bereitstellung hinzufügen" -#: git-gui.sh:2440 +#: git-gui.sh:2578 msgid "Initializing..." msgstr "Initialisieren..." +#: git-gui.sh:2669 +#, tcl-format +msgid "" +"Possible environment issues exist.\n" +"\n" +"The following environment variables are probably\n" +"going to be ignored by any Git subprocess run\n" +"by %s:\n" +"\n" +msgstr "" + +#: git-gui.sh:2699 +msgid "" +"\n" +"This is due to a known issue with the\n" +"Tcl binary distributed by Cygwin." +msgstr "" + +#: git-gui.sh:2704 +#, tcl-format +msgid "" +"\n" +"\n" +"A good replacement for %s\n" +"is placing values for the user.name and\n" +"user.email settings into your personal\n" +"~/.gitconfig file.\n" +msgstr "" + #: lib/blame.tcl:77 msgid "File Viewer" msgstr "Datei-Browser" @@ -429,6 +473,50 @@ msgstr "Version kopieren" msgid "Reading %s..." msgstr "%s lesen..." +#: lib/blame.tcl:473 +msgid "Loading copy/move tracking annotations..." +msgstr "" + +#: lib/blame.tcl:493 +msgid "lines annotated" +msgstr "" + +#: lib/blame.tcl:674 +msgid "Loading original location annotations..." +msgstr "" + +#: lib/blame.tcl:677 +msgid "Annotation complete." +msgstr "" + +#: lib/blame.tcl:731 +msgid "Loading annotation..." +msgstr "Annotierung laden..." + +#: lib/blame.tcl:787 +msgid "Author:" +msgstr "Autor:" + +#: lib/blame.tcl:791 +msgid "Committer:" +msgstr "Eintragender:" + +#: lib/blame.tcl:796 +msgid "Original File:" +msgstr "" + +#: lib/blame.tcl:910 +msgid "Originally By:" +msgstr "" + +#: lib/blame.tcl:916 +msgid "In File:" +msgstr "In Datei:" + +#: lib/blame.tcl:921 +msgid "Copied Or Moved Here By:" +msgstr "" + #: lib/branch_checkout.tcl:14 lib/branch_checkout.tcl:19 msgid "Checkout Branch" msgstr "Zweig umstellen" @@ -438,18 +526,18 @@ msgid "Checkout" msgstr "Umstellen" #: lib/branch_checkout.tcl:27 lib/branch_create.tcl:35 -#: lib/branch_delete.tcl:32 lib/branch_rename.tcl:30 lib/browser.tcl:283 -#: lib/checkout_op.tcl:522 lib/merge.tcl:172 lib/option.tcl:172 -#: lib/remote_branch_delete.tcl:42 lib/transport.tcl:92 +#: lib/branch_delete.tcl:32 lib/branch_rename.tcl:30 lib/browser.tcl:281 +#: lib/checkout_op.tcl:522 lib/choose_font.tcl:43 lib/merge.tcl:172 +#: lib/option.tcl:172 lib/remote_branch_delete.tcl:42 lib/transport.tcl:97 msgid "Cancel" msgstr "Abbrechen" -#: lib/branch_checkout.tcl:32 lib/browser.tcl:288 +#: lib/branch_checkout.tcl:32 lib/browser.tcl:286 msgid "Revision" msgstr "Version" #: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:159 -#: lib/option.tcl:274 +#: lib/option.tcl:280 msgid "Options" msgstr "Optionen" @@ -469,7 +557,7 @@ msgstr "Zweig erstellen" msgid "Create New Branch" msgstr "Neuen Zweig erstellen" -#: lib/branch_create.tcl:31 +#: lib/branch_create.tcl:31 lib/choose_repository.tcl:236 msgid "Create" msgstr "Erstellen" @@ -609,20 +697,22 @@ msgstr "Starten..." msgid "File Browser" msgstr "Datei-Browser" -#: lib/browser.tcl:127 lib/browser.tcl:144 +#: lib/browser.tcl:125 lib/browser.tcl:142 #, tcl-format msgid "Loading %s..." msgstr "%s laden..." -#: lib/browser.tcl:188 +#: lib/browser.tcl:186 msgid "[Up To Parent]" msgstr "[Nach oben]" -#: lib/browser.tcl:268 lib/browser.tcl:274 +#: lib/browser.tcl:266 lib/browser.tcl:272 msgid "Browse Branch Files" msgstr "Dateien des Zweigs durchblättern" -#: lib/browser.tcl:279 +#: lib/browser.tcl:277 lib/choose_repository.tcl:252 +#: lib/choose_repository.tcl:342 lib/choose_repository.tcl:352 +#: lib/choose_repository.tcl:848 msgid "Browse" msgstr "Blättern" @@ -631,7 +721,12 @@ msgstr "Blättern" msgid "Fetching %s from %s" msgstr "Änderungen »%s« von »%s« anfordern" -#: lib/checkout_op.tcl:140 lib/console.tcl:81 lib/database.tcl:31 +#: lib/checkout_op.tcl:127 +#, tcl-format +msgid "fatal: Cannot resolve %s" +msgstr "" + +#: lib/checkout_op.tcl:140 lib/console.tcl:79 lib/database.tcl:31 msgid "Close" msgstr "Schließen" @@ -683,10 +778,17 @@ msgstr "" "\n" "Es wird gleich neu geladen.\n" +#: lib/checkout_op.tcl:322 +#, tcl-format +msgid "Updating working directory to '%s'..." +msgstr "Arbeitskopie umstellen auf »%s«..." + #: lib/checkout_op.tcl:353 #, tcl-format msgid "Aborted checkout of '%s' (file level merging is required)." -msgstr "Zweig umstellen von »%s« abgebrochen (Zusammenführen der Dateien ist notwendig)." +msgstr "" +"Zweig umstellen von »%s« abgebrochen (Zusammenführen der Dateien ist " +"notwendig)." #: lib/checkout_op.tcl:354 msgid "File level merge required." @@ -706,7 +808,13 @@ msgid "" msgstr "" "Die Arbeitskopie ist nicht auf einem lokalen Zweig.\n" "\n" -"Wenn Sie auf einem Zweig arbeiten möchten, erstellen Sie bitte jetzt einen Zweig mit der Auswahl »Abgetrennte Arbeitskopie-Version«." +"Wenn Sie auf einem Zweig arbeiten möchten, erstellen Sie bitte jetzt einen " +"Zweig mit der Auswahl »Abgetrennte Arbeitskopie-Version«." + +#: lib/checkout_op.tcl:446 +#, tcl-format +msgid "Checked out '%s'." +msgstr "Umgestellt auf »%s«." #: lib/checkout_op.tcl:478 #, tcl-format @@ -746,6 +854,236 @@ msgstr "" "\n" "Dies ist ein interner Programmfehler von %s. Programm wird jetzt abgebrochen." +#: lib/choose_font.tcl:39 +msgid "Select" +msgstr "Auswählen" + +#: lib/choose_font.tcl:53 +msgid "Font Family" +msgstr "Schriftfamilie" + +#: lib/choose_font.tcl:73 +msgid "Font Size" +msgstr "Schriftgröße" + +#: lib/choose_font.tcl:90 +msgid "Font Example" +msgstr "Schriftbeispiel" + +#: lib/choose_font.tcl:101 +msgid "" +"This is example text.\n" +"If you like this text, it can be your font." +msgstr "" +"Dies ist ein Beispieltext.\n" +"Wenn Ihnen dieser Text gefällt, sollten Sie diese Schriftart wählen." + +#: lib/choose_repository.tcl:57 +msgid "Git Gui" +msgstr "Git Gui" + +#: lib/choose_repository.tcl:106 lib/choose_repository.tcl:241 +msgid "Create New Repository" +msgstr "Neues Projektarchiv" + +#: lib/choose_repository.tcl:111 lib/choose_repository.tcl:328 +msgid "Clone Existing Repository" +msgstr "Projektarchiv kopieren" + +#: lib/choose_repository.tcl:116 lib/choose_repository.tcl:837 +msgid "Open Existing Repository" +msgstr "Projektarchiv öffnen" + +#: lib/choose_repository.tcl:128 +msgid "Next >" +msgstr "Weiter >" + +#: lib/choose_repository.tcl:189 +#, tcl-format +msgid "Location %s already exists." +msgstr "Projektarchiv »%s« existiert bereits." + +#: lib/choose_repository.tcl:195 lib/choose_repository.tcl:202 +#: lib/choose_repository.tcl:209 +#, tcl-format +msgid "Failed to create repository %s:" +msgstr "Projektarchiv »%s« konnte nicht erstellt werden:" + +#: lib/choose_repository.tcl:246 lib/choose_repository.tcl:346 +msgid "Directory:" +msgstr "Verzeichnis:" + +#: lib/choose_repository.tcl:275 lib/choose_repository.tcl:400 +#: lib/choose_repository.tcl:871 +msgid "Git Repository" +msgstr "Git Projektarchiv" + +#: lib/choose_repository.tcl:290 lib/choose_repository.tcl:297 +#, tcl-format +msgid "Directory %s already exists." +msgstr "Verzeichnis »%s« existiert bereits." + +#: lib/choose_repository.tcl:302 +#, tcl-format +msgid "File %s already exists." +msgstr "Datei »%s« existiert bereits." + +#: lib/choose_repository.tcl:323 +msgid "Clone" +msgstr "Kopieren" + +#: lib/choose_repository.tcl:336 +msgid "URL:" +msgstr "URL:" + +#: lib/choose_repository.tcl:356 +msgid "Clone Type:" +msgstr "Art der Kopie:" + +#: lib/choose_repository.tcl:362 +msgid "Standard (Fast, Semi-Redundant, Hardlinks)" +msgstr "" + +#: lib/choose_repository.tcl:368 +msgid "Full Copy (Slower, Redundant Backup)" +msgstr "" + +#: lib/choose_repository.tcl:374 +msgid "Shared (Fastest, Not Recommended, No Backup)" +msgstr "" + +#: lib/choose_repository.tcl:406 lib/choose_repository.tcl:455 +#: lib/choose_repository.tcl:597 lib/choose_repository.tcl:667 +#: lib/choose_repository.tcl:877 lib/choose_repository.tcl:885 +#, tcl-format +msgid "Not a Git repository: %s" +msgstr "Kein Git-Projektarchiv in »%s« gefunden." + +#: lib/choose_repository.tcl:442 +msgid "Standard only available for local repository." +msgstr "" + +#: lib/choose_repository.tcl:446 +msgid "Shared only available for local repository." +msgstr "" + +#: lib/choose_repository.tcl:476 +msgid "Failed to configure origin" +msgstr "" + +#: lib/choose_repository.tcl:488 +msgid "Counting objects" +msgstr "" + +#: lib/choose_repository.tcl:489 +msgid "buckets" +msgstr "" + +#: lib/choose_repository.tcl:513 +#, tcl-format +msgid "Unable to copy objects/info/alternates: %s" +msgstr "" + +#: lib/choose_repository.tcl:549 +#, tcl-format +msgid "Nothing to clone from %s." +msgstr "Von »%s« konnte nichts kopiert werden." + +#: lib/choose_repository.tcl:551 lib/choose_repository.tcl:765 +#: lib/choose_repository.tcl:777 +msgid "The 'master' branch has not been initialized." +msgstr "" + +#: lib/choose_repository.tcl:564 +msgid "Hardlinks are unavailable. Falling back to copying." +msgstr "" + +#: lib/choose_repository.tcl:576 +#, tcl-format +msgid "Cloning from %s" +msgstr "Kopieren von »%s«" + +#: lib/choose_repository.tcl:607 +msgid "Copying objects" +msgstr "Objektdatenbank kopieren" + +#: lib/choose_repository.tcl:608 +msgid "KiB" +msgstr "KB" + +#: lib/choose_repository.tcl:632 +#, tcl-format +msgid "Unable to copy object: %s" +msgstr "Objekt kann nicht kopiert werden: %s" + +#: lib/choose_repository.tcl:642 +msgid "Linking objects" +msgstr "Objekte verlinken" + +#: lib/choose_repository.tcl:643 +msgid "objects" +msgstr "Objekte" + +#: lib/choose_repository.tcl:651 +#, tcl-format +msgid "Unable to hardlink object: %s" +msgstr "Objekt kann nicht hartverlinkt werden: %s" + +#: lib/choose_repository.tcl:706 +msgid "Cannot fetch branches and objects. See console output for details." +msgstr "" + +#: lib/choose_repository.tcl:717 +msgid "Cannot fetch tags. See console output for details." +msgstr "" + +#: lib/choose_repository.tcl:741 +msgid "Cannot determine HEAD. See console output for details." +msgstr "" + +#: lib/choose_repository.tcl:750 +#, tcl-format +msgid "Unable to cleanup %s" +msgstr "" + +#: lib/choose_repository.tcl:756 +msgid "Clone failed." +msgstr "Kopieren fehlgeschlagen." + +#: lib/choose_repository.tcl:763 +msgid "No default branch obtained." +msgstr "" + +#: lib/choose_repository.tcl:774 +#, tcl-format +msgid "Cannot resolve %s as a commit." +msgstr "" + +#: lib/choose_repository.tcl:786 +msgid "Creating working directory" +msgstr "Arbeitskopie erstellen" + +#: lib/choose_repository.tcl:787 +msgid "files" +msgstr "Dateien" + +#: lib/choose_repository.tcl:816 +msgid "Initial file checkout failed." +msgstr "" + +#: lib/choose_repository.tcl:832 +msgid "Open" +msgstr "Öffnen" + +#: lib/choose_repository.tcl:842 +msgid "Repository:" +msgstr "Projektarchiv:" + +#: lib/choose_repository.tcl:891 +#, tcl-format +msgid "Failed to open repository %s:" +msgstr "Projektarchiv »%s« konnte nicht geöffnet werden." + #: lib/choose_rev.tcl:53 msgid "This Detached Checkout" msgstr "Abgetrennte Arbeitskopie-Version" @@ -762,7 +1100,7 @@ msgstr "Lokaler Zweig" msgid "Tracking Branch" msgstr "Übernahmezweig" -#: lib/choose_rev.tcl:84 +#: lib/choose_rev.tcl:84 lib/choose_rev.tcl:537 msgid "Tag" msgstr "Markierung" @@ -779,6 +1117,18 @@ msgstr "Keine Version ausgewählt." msgid "Revision expression is empty." msgstr "Versions-Ausdruck ist leer." +#: lib/choose_rev.tcl:530 +msgid "Updated" +msgstr "Aktualisiert" + +#: lib/choose_rev.tcl:556 +msgid "Remote" +msgstr "Gegenseite" + +#: lib/choose_rev.tcl:558 +msgid "URL" +msgstr "URL" + #: lib/commit.tcl:9 msgid "" "There is nothing to amend.\n" @@ -829,7 +1179,8 @@ msgid "" msgstr "" "Der letzte geladene Status stimmt nicht mehr mit dem Projektarchiv überein.\n" "\n" -"Ein anderes Git-Programm hat das Projektarchiv seit dem letzten Laden geändert. Vor dem Eintragen einer neuen Version muss neu geladen werden.\n" +"Ein anderes Git-Programm hat das Projektarchiv seit dem letzten Laden " +"geändert. Vor dem Eintragen einer neuen Version muss neu geladen werden.\n" "\n" "Es wird gleich neu geladen.\n" @@ -843,7 +1194,8 @@ msgid "" msgstr "" "Nicht zusammengeführte Dateien können nicht eingetragen werden.\n" "\n" -"Die Datei »%s« hat noch nicht aufgelöste Zusammenführungs-Konflikte. Sie müssen diese Konflikte auflösen, bevor Sie eintragen können.\n" +"Die Datei »%s« hat noch nicht aufgelöste Zusammenführungs-Konflikte. Sie " +"müssen diese Konflikte auflösen, bevor Sie eintragen können.\n" #: lib/commit.tcl:162 #, tcl-format @@ -890,6 +1242,11 @@ msgstr "" msgid "write-tree failed:" msgstr "write-tree fehlgeschlagen:" +#: lib/commit.tcl:275 +#, tcl-format +msgid "Commit %s appears to be corrupt" +msgstr "Version »%s« scheint beschädigt zu sein" + #: lib/commit.tcl:279 msgid "" "No changes to commit.\n" @@ -900,7 +1257,8 @@ msgid "" msgstr "" "Keine Änderungen einzutragen.\n" "\n" -"Es gibt keine geänderte Datei bei dieser Version und es wurde auch nichts zusammengeführt.\n" +"Es gibt keine geänderte Datei bei dieser Version und es wurde auch nichts " +"zusammengeführt.\n" "\n" "Das Arbeitsverzeichnis wird daher jetzt neu geladen.\n" @@ -908,6 +1266,11 @@ msgstr "" msgid "No changes to commit." msgstr "Keine Änderungen, die eingetragen werden können." +#: lib/commit.tcl:303 +#, tcl-format +msgid "warning: Tcl does not support encoding '%s'." +msgstr "" + #: lib/commit.tcl:317 msgid "commit-tree failed:" msgstr "commit-tree fehlgeschlagen:" @@ -921,15 +1284,15 @@ msgstr "update-ref fehlgeschlagen:" msgid "Created commit %s: %s" msgstr "Version %s übertragen: %s" -#: lib/console.tcl:55 +#: lib/console.tcl:57 msgid "Working... please wait..." msgstr "Verarbeitung. Bitte warten..." -#: lib/console.tcl:184 +#: lib/console.tcl:183 msgid "Success" msgstr "Erfolgreich" -#: lib/console.tcl:194 +#: lib/console.tcl:196 msgid "Error: Command Failed" msgstr "Fehler: Kommando fehlgeschlagen" @@ -969,6 +1332,27 @@ msgstr "Objektdatenbank komprimieren" msgid "Verifying the object database with fsck-objects" msgstr "Die Objektdatenbank durch »fsck-objects« überprüfen lassen" +#: lib/database.tcl:108 +#, tcl-format +msgid "" +"This repository currently has approximately %i loose objects.\n" +"\n" +"To maintain optimal performance it is strongly recommended that you compress " +"the database when more than %i loose objects exist.\n" +"\n" +"Compress the database now?" +msgstr "" +"Dieses Projektarchiv enthält ungefähr %i nicht verknüpfte Objekte.\n" +"\n" +"Für eine optimale Performance wird empfohlen, die Datenbank des Projektarchivs zu komprimieren, sobald mehr als %i nicht verknüpfte Objekte vorliegen.\n" +"\n" +"Soll die Datenbank jetzt komprimiert werden?" + +#: lib/date.tcl:25 +#, tcl-format +msgid "Invalid date from Git: %s" +msgstr "Ungültiges Datum von Git: %s" + #: lib/diff.tcl:42 #, tcl-format msgid "" @@ -991,19 +1375,37 @@ msgstr "" "Das Arbeitsverzeichnis wird jetzt neu geladen, um diese Änderung bei allen " "Dateien zu prüfen." -#: lib/diff.tcl:97 +#: lib/diff.tcl:81 +#, tcl-format +msgid "Loading diff of %s..." +msgstr "Vergleich von »%s« laden..." + +#: lib/diff.tcl:114 lib/diff.tcl:184 +#, tcl-format +msgid "Unable to display %s" +msgstr "Datei »%s« kann nicht angezeigt werden" + +#: lib/diff.tcl:115 msgid "Error loading file:" msgstr "Fehler beim Laden der Datei:" -#: lib/diff.tcl:162 +#: lib/diff.tcl:122 +msgid "Git Repository (subproject)" +msgstr "Git-Projektarchiv (Unterprojekt)" + +#: lib/diff.tcl:134 +msgid "* Binary file (not showing content)." +msgstr "* Binärdatei (Inhalt wird nicht angezeigt)" + +#: lib/diff.tcl:185 msgid "Error loading diff:" msgstr "Fehler beim Laden des Vergleichs:" -#: lib/diff.tcl:278 +#: lib/diff.tcl:302 msgid "Failed to unstage selected hunk." msgstr "Fehler beim Herausnehmen der gewählten Dateien aus der Bereitstellung." -#: lib/diff.tcl:285 +#: lib/diff.tcl:309 msgid "Failed to stage selected hunk." msgstr "Fehler beim Bereitstellen der gewählten Dateien." @@ -1017,24 +1419,35 @@ msgstr "Warnung" #: lib/error.tcl:81 msgid "You must correct the above errors before committing." -msgstr "Sie müssen die obigen Fehler zuerst beheben, bevor Sie eintragen können." +msgstr "" +"Sie müssen die obigen Fehler zuerst beheben, bevor Sie eintragen können." -#: lib/index.tcl:364 +#: lib/index.tcl:271 +#, tcl-format +msgid "Unstaging %s from commit" +msgstr "Datei »%s« aus der Bereitstellung herausnehmen" + +#: lib/index.tcl:315 +#, tcl-format +msgid "Adding %s" +msgstr "»%s« hinzufügen..." + +#: lib/index.tcl:370 #, tcl-format msgid "Revert changes in file %s?" msgstr "Änderungen in Datei »%s« revidieren?" -#: lib/index.tcl:366 +#: lib/index.tcl:372 #, tcl-format msgid "Revert changes in these %i files?" msgstr "Änderungen in den gewählten %i Dateien revidieren?" -#: lib/index.tcl:372 +#: lib/index.tcl:378 msgid "Any unstaged changes will be permanently lost by the revert." msgstr "" "Alle nicht bereitgestellten Änderungen werden beim Revidieren verloren gehen." -#: lib/index.tcl:375 +#: lib/index.tcl:381 msgid "Do Nothing" msgstr "Nichts tun" @@ -1046,7 +1459,8 @@ msgid "" msgstr "" "Zusammenführen kann nicht gleichzeitig mit Nachbessern durchgeführt werden.\n" "\n" -"Sie müssen zuerst die Nachbesserungs-Version abschließen, bevor Sie zusammenführen können.\n" +"Sie müssen zuerst die Nachbesserungs-Version abschließen, bevor Sie " +"zusammenführen können.\n" #: lib/merge.tcl:27 msgid "" @@ -1076,7 +1490,10 @@ msgid "" msgstr "" "Zusammenführung mit Konflikten.\n" "\n" -"Die Datei »%s« enthält Konflikte beim Zusammenführen. Sie müssen diese Konflikte per Hand auflösen. Anschließend müssen Sie die Datei wieder bereitstellen und eintragen, um die Zusammenführung abzuschließen. Erst danach kann eine neue Zusammenführung begonnen werden.\n" +"Die Datei »%s« enthält Konflikte beim Zusammenführen. Sie müssen diese " +"Konflikte per Hand auflösen. Anschließend müssen Sie die Datei wieder " +"bereitstellen und eintragen, um die Zusammenführung abzuschließen. Erst " +"danach kann eine neue Zusammenführung begonnen werden.\n" #: lib/merge.tcl:54 #, tcl-format @@ -1090,7 +1507,10 @@ msgid "" msgstr "" "Es liegen Änderungen vor.\n" "\n" -"Die Datei »%s« wurde geändert. Sie sollten zuerst die bereitgestellte Version abschließen, bevor Sie eine Zusammenführung beginnen. Mit dieser Reihenfolge können Sie mögliche Konflikte beim Zusammenführen wesentlich einfacher beheben oder abbrechen.\n" +"Die Datei »%s« wurde geändert. Sie sollten zuerst die bereitgestellte " +"Version abschließen, bevor Sie eine Zusammenführung beginnen. Mit dieser " +"Reihenfolge können Sie mögliche Konflikte beim Zusammenführen wesentlich " +"einfacher beheben oder abbrechen.\n" #: lib/merge.tcl:106 #, tcl-format @@ -1139,7 +1559,8 @@ msgid "" msgstr "" "Zusammenführen abbrechen?\n" "\n" -"Wenn Sie abbrechen, gehen alle noch nicht eingetragenen Änderungen verloren.\n" +"Wenn Sie abbrechen, gehen alle noch nicht eingetragenen Änderungen " +"verloren.\n" "\n" "Zusammenführen jetzt abbrechen?" @@ -1153,7 +1574,8 @@ msgid "" msgstr "" "Änderungen zurücksetzen?\n" "\n" -"Wenn Sie zurücksetzen, gehen alle noch nicht eingetragenen Änderungen verloren.\n" +"Wenn Sie zurücksetzen, gehen alle noch nicht eingetragenen Änderungen " +"verloren.\n" "\n" "Änderungen jetzt zurücksetzen?" @@ -1230,7 +1652,20 @@ msgstr "Anzahl der Kontextzeilen beim Vergleich" msgid "New Branch Name Template" msgstr "Namensvorschlag für neue Zweige" -#: lib/option.tcl:305 +#: lib/option.tcl:258 +msgid "Change Font" +msgstr "Schriftart ändern" + +#: lib/option.tcl:262 +#, tcl-format +msgid "Choose %s" +msgstr "%s wählen" + +#: lib/option.tcl:268 +msgid "pt." +msgstr "pt." + +#: lib/option.tcl:311 msgid "Failed to completely save options:" msgstr "Optionen konnten nicht gespeichert werden:" @@ -1242,11 +1677,11 @@ msgstr "Zweig im Projektarchiv der Gegenseite löschen" msgid "From Repository" msgstr "Von Projektarchiv" -#: lib/remote_branch_delete.tcl:50 lib/transport.tcl:118 +#: lib/remote_branch_delete.tcl:50 lib/transport.tcl:123 msgid "Remote:" msgstr "Gegenseite:" -#: lib/remote_branch_delete.tcl:66 lib/transport.tcl:133 +#: lib/remote_branch_delete.tcl:66 lib/transport.tcl:138 msgid "Arbitrary URL:" msgstr "Kommunikation mit URL:" @@ -1270,12 +1705,26 @@ msgstr "Immer (Keine Zusammenführungsprüfung)" msgid "A branch is required for 'Merged Into'." msgstr "Für »Zusammenführen mit« muss ein Zweig angegeben werden." +#: lib/remote_branch_delete.tcl:184 +#, tcl-format +msgid "" +"The following branches are not completely merged into %s:\n" +"\n" +" - %s" +msgstr "" +"Folgende Zweige sind noch nicht mit »%s« zusammengeführt:\n" +"\n" +" - %s" + #: lib/remote_branch_delete.tcl:189 #, tcl-format msgid "" "One or more of the merge tests failed because you have not fetched the " "necessary commits. Try fetching from %s first." -msgstr "Ein oder mehrere Zusammenführungen sind fehlgeschlagen, da Sie nicht die notwendigen Versionen vorher angefordert haben. Sie sollten versuchen, zuerst von »%s« anzufordern." +msgstr "" +"Ein oder mehrere Zusammenführungen sind fehlgeschlagen, da Sie nicht die " +"notwendigen Versionen vorher angefordert haben. Sie sollten versuchen, " +"zuerst von »%s« anzufordern." #: lib/remote_branch_delete.tcl:207 msgid "Please select one or more branches to delete." @@ -1304,22 +1753,22 @@ msgstr "Kein Projektarchiv ausgewählt." #: lib/remote_branch_delete.tcl:291 #, tcl-format msgid "Scanning %s..." -msgstr "%s laden..." +msgstr "»%s« laden..." #: lib/remote.tcl:162 #, tcl-format -msgid "Fetch from %s..." -msgstr "Von »%s« anfordern..." +msgid "Fetch from %s" +msgstr "Von »%s« anfordern" #: lib/remote.tcl:172 #, tcl-format -msgid "Prune from %s..." -msgstr "Löschen von »%s«..." +msgid "Prune from %s" +msgstr "Löschen von »%s«" #: lib/remote.tcl:206 #, tcl-format -msgid "Push to %s..." -msgstr "Nach %s ausliefern..." +msgid "Push to %s" +msgstr "Nach »%s« ausliefern" #: lib/shortcut.tcl:26 lib/shortcut.tcl:74 msgid "Cannot write script:" @@ -1329,51 +1778,70 @@ msgstr "Fehler beim Schreiben des Scripts:" msgid "Cannot write icon:" msgstr "Fehler beim Erstellen des Icons:" -#: lib/status_bar.tcl:58 +#: lib/status_bar.tcl:83 #, tcl-format msgid "%s ... %*i of %*i %s (%3i%%)" msgstr "%s ... %*i von %*i %s (%3i%%)" +#: lib/transport.tcl:6 +#, tcl-format +msgid "fetch %s" +msgstr "»%s« anfordern" + #: lib/transport.tcl:7 #, tcl-format msgid "Fetching new changes from %s" msgstr "Neue Änderungen von »%s« holen" +#: lib/transport.tcl:18 +#, tcl-format +msgid "remote prune %s" +msgstr "" + #: lib/transport.tcl:19 #, tcl-format msgid "Pruning tracking branches deleted from %s" msgstr "Übernahmezweige löschen, die in »%s« gelöscht wurden" +#: lib/transport.tcl:25 lib/transport.tcl:71 +#, tcl-format +msgid "push %s" +msgstr "»%s« ausliefern..." + #: lib/transport.tcl:26 #, tcl-format msgid "Pushing changes to %s" -msgstr "Änderungen nach %s ausliefern" +msgstr "Änderungen nach »%s« ausliefern" -#: lib/transport.tcl:68 +#: lib/transport.tcl:72 #, tcl-format msgid "Pushing %s %s to %s" msgstr "%s %s nach %s ausliefern" -#: lib/transport.tcl:84 +#: lib/transport.tcl:89 msgid "Push Branches" msgstr "Zweige ausliefern" -#: lib/transport.tcl:98 +#: lib/transport.tcl:103 msgid "Source Branches" msgstr "Herkunftszweige" -#: lib/transport.tcl:115 +#: lib/transport.tcl:120 msgid "Destination Repository" msgstr "Ziel-Projektarchiv" -#: lib/transport.tcl:153 +#: lib/transport.tcl:158 msgid "Transfer Options" msgstr "Netzwerk-Einstellungen" -#: lib/transport.tcl:155 +#: lib/transport.tcl:160 +msgid "Force overwrite existing branch (may discard changes)" +msgstr "Überschreiben von existierenden Zweigen erzwingen (könnte Änderungen löschen)" + +#: lib/transport.tcl:164 msgid "Use thin pack (for slow network connections)" msgstr "Kompaktes Datenformat benutzen (für langsame Netzverbindungen)" -#: lib/transport.tcl:159 +#: lib/transport.tcl:168 msgid "Include tags" msgstr "Mit Markierungen übertragen" From be700fe30fd17b3f9b600de9110c74035091a007 Mon Sep 17 00:00:00 2001 From: Steffen Prohaska Date: Sat, 6 Oct 2007 11:29:02 +0200 Subject: [PATCH 0152/1490] git-gui: add directory git-gui is located in to PATH (on Windows) This commit modifies PATH to include a good guess where git could be found. The first location to search for executable is the directory git-gui is installed in. This is a good guess for a sane installation. Even if git is not available in PATH, git-gui is now able to find it. Hence git-gui can be passed to wish as an absolute path without caring about the environment. We must modify PATH to be able to spawn shell based git commands. For builtins it would be sufficient to located them and execute them with their absolute path. But for shell based git commmands PATH needs to be modified. Signed-off-by: Steffen Prohaska Signed-off-by: Shawn O. Pearce --- git-gui.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/git-gui.sh b/git-gui.sh index e17efb7d9f..6b7bdbca21 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -343,6 +343,9 @@ proc _which {what} { $env(PATH)] {;}] set _search_exe .exe } elseif {[is_Windows]} { + set gitguidir [file dirname [info script]] + regsub -all ";" $gitguidir "\\;" gitguidir + set env(PATH) "$gitguidir;$env(PATH)" set _search_path [split $env(PATH) {;}] set _search_exe .exe } else { From a16b74e72c1dfb6cdef2c17d564d9857ab386d7d Mon Sep 17 00:00:00 2001 From: Steffen Prohaska Date: Wed, 10 Oct 2007 08:58:58 +0200 Subject: [PATCH 0153/1490] git-gui: set NO_MSGFMT to force using pure tcl replacement in msysgit Shawn's git-gui Makefile supports the pure tcl replacement for msgfmt if setting NO_MSGFMT. This patch sets the NO_MSGFMT for msysgit. Signed-off-by: Steffen Prohaska Signed-off-by: Shawn O. Pearce --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index 818a0ab45c..c8054507e9 100644 --- a/Makefile +++ b/Makefile @@ -126,6 +126,9 @@ ifeq ($(uname_S),Darwin) GITGUI_MACOSXAPP := YesPlease endif endif +ifneq (,$(findstring MINGW,$(uname_S))) + NO_MSGFMT=1 +endif ifdef GITGUI_MACOSXAPP GITGUI_MAIN := git-gui.tcl From 99fe594d9677d55d773db3ab180310a3d3bf090b Mon Sep 17 00:00:00 2001 From: Steffen Prohaska Date: Wed, 10 Oct 2007 08:58:59 +0200 Subject: [PATCH 0154/1490] git-gui: add mingw specific startup wrapper The wrapper adds the directory it is installed in to PATH. This is required for the git commands implemented in shell. git-gui fails to launch them if PATH is not modified. The wrapper script also accepts an optional command line switch '--working-dir ' and changes to before launching the actual git-gui. This is required to implement the "Git Gui Here" Explorer shell extension. As a last step the original git-gui script is launched, which is expected to be located in the same directory under the name git-gui.tcl. Signed-off-by: Steffen Prohaska Signed-off-by: Shawn O. Pearce --- Makefile | 20 ++++++++++++++++++++ windows/git-gui.sh | 16 ++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 windows/git-gui.sh diff --git a/Makefile b/Makefile index c8054507e9..2ad8846198 100644 --- a/Makefile +++ b/Makefile @@ -128,6 +128,7 @@ ifeq ($(uname_S),Darwin) endif ifneq (,$(findstring MINGW,$(uname_S))) NO_MSGFMT=1 + GITGUI_WINDOWS_WRAPPER := YesPlease endif ifdef GITGUI_MACOSXAPP @@ -168,6 +169,13 @@ Git\ Gui.app: GIT-VERSION-FILE GIT-GUI-VARS \ mv '$@'+ '$@' endif +ifdef GITGUI_WINDOWS_WRAPPER +GITGUI_MAIN := git-gui.tcl + +git-gui: windows/git-gui.sh + cp $< $@ +endif + $(GITGUI_MAIN): git-gui.sh GIT-VERSION-FILE GIT-GUI-VARS $(QUIET_GEN)rm -f $@ $@+ && \ sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \ @@ -233,12 +241,18 @@ GIT-GUI-VARS: .FORCE-GIT-GUI-VARS ifdef GITGUI_MACOSXAPP all:: git-gui Git\ Gui.app endif +ifdef GITGUI_WINDOWS_WRAPPER +all:: git-gui +endif all:: $(GITGUI_MAIN) lib/tclIndex $(ALL_MSGFILES) install: all $(QUIET)$(INSTALL_D0)'$(DESTDIR_SQ)$(gitexecdir_SQ)' $(INSTALL_D1) $(QUIET)$(INSTALL_X0)git-gui $(INSTALL_X1) '$(DESTDIR_SQ)$(gitexecdir_SQ)' $(QUIET)$(foreach p,$(GITGUI_BUILT_INS), $(INSTALL_L0)'$(DESTDIR_SQ)$(gitexecdir_SQ)/$p' $(INSTALL_L1)'$(DESTDIR_SQ)$(gitexecdir_SQ)/git-gui' $(INSTALL_L2)'$(DESTDIR_SQ)$(gitexecdir_SQ)/$p' $(INSTALL_L3) &&) true +ifdef GITGUI_WINDOWS_WRAPPER + $(QUIET)$(INSTALL_R0)git-gui.tcl $(INSTALL_R1) '$(DESTDIR_SQ)$(gitexecdir_SQ)' +endif $(QUIET)$(INSTALL_D0)'$(DESTDIR_SQ)$(libdir_SQ)' $(INSTALL_D1) $(QUIET)$(INSTALL_R0)lib/tclIndex $(INSTALL_R1) '$(DESTDIR_SQ)$(libdir_SQ)' $(QUIET)$(INSTALL_R0)lib/git-gui.ico $(INSTALL_R1) '$(DESTDIR_SQ)$(libdir_SQ)' @@ -254,6 +268,9 @@ uninstall: $(QUIET)$(CLEAN_DST) '$(DESTDIR_SQ)$(gitexecdir_SQ)' $(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(gitexecdir_SQ)'/git-gui $(REMOVE_F1) $(QUIET)$(foreach p,$(GITGUI_BUILT_INS), $(REMOVE_F0)'$(DESTDIR_SQ)$(gitexecdir_SQ)'/$p $(REMOVE_F1) &&) true +ifdef GITGUI_WINDOWS_WRAPPER + $(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(gitexecdir_SQ)'/git-gui.tcl $(REMOVE_F1) +endif $(QUIET)$(CLEAN_DST) '$(DESTDIR_SQ)$(libdir_SQ)' $(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(libdir_SQ)'/tclIndex $(REMOVE_F1) $(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(libdir_SQ)'/git-gui.ico $(REMOVE_F1) @@ -279,6 +296,9 @@ clean:: ifdef GITGUI_MACOSXAPP $(RM_RF) 'Git Gui.app'* git-gui endif +ifdef GITGUI_WINDOWS_WRAPPER + $(RM_RF) git-gui +endif .PHONY: all install uninstall dist-version clean .PHONY: .FORCE-GIT-VERSION-FILE diff --git a/windows/git-gui.sh b/windows/git-gui.sh new file mode 100644 index 0000000000..98f32c0a07 --- /dev/null +++ b/windows/git-gui.sh @@ -0,0 +1,16 @@ +#!/bin/sh +# Tcl ignores the next line -*- tcl -*- \ +exec wish "$0" -- "$@" + +if { $argc >=2 && [lindex $argv 0] == "--working-dir" } { + cd [lindex $argv 1] + set argv [lrange $argv 2 end] + incr argc -2 +} + +set gitguidir [file dirname [info script]] +regsub -all ";" $gitguidir "\\;" gitguidir +set env(PATH) "$gitguidir;$env(PATH)" +unset gitguidir + +source [file join [file dirname [info script]] git-gui.tcl] From 57364320bf5a15e849ea627423397eda3f34ebb7 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Wed, 10 Oct 2007 04:11:43 -0400 Subject: [PATCH 0155/1490] git-gui: Updated po strings based on current sources --- po/de.po | 453 +++++++++-------- po/git-gui.pot | 804 +++++++++++++++++++++++------- po/hu.po | 843 ++++++++++++++++++++++++------- po/it.po | 872 ++++++++++++++++++++++++-------- po/ja.po | 841 ++++++++++++++++++++++++------- po/ru.po | 1290 +++++++++++++++++++++++++++++++----------------- po/zh_cn.po | 987 ++++++++++++++++++++++++++---------- 7 files changed, 4428 insertions(+), 1662 deletions(-) diff --git a/po/de.po b/po/de.po index 60b9ea52dc..4ba2fbee51 100644 --- a/po/de.po +++ b/po/de.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: git-gui\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2007-10-05 22:01+0200\n" +"POT-Creation-Date: 2007-10-10 04:04-0400\n" "PO-Revision-Date: 2007-10-05 22:27+0200\n" "Last-Translator: Christian Stimming \n" "Language-Team: German\n" @@ -15,33 +15,33 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: git-gui.sh:41 git-gui.sh:631 git-gui.sh:645 git-gui.sh:658 git-gui.sh:740 -#: git-gui.sh:759 +#: git-gui.sh:41 git-gui.sh:634 git-gui.sh:648 git-gui.sh:661 git-gui.sh:744 +#: git-gui.sh:763 msgid "git-gui: fatal error" msgstr "git-gui: Programmfehler" -#: git-gui.sh:592 +#: git-gui.sh:595 #, tcl-format msgid "Invalid font specified in %s:" msgstr "Ungültige Zeichensatz-Angabe in %s:" -#: git-gui.sh:617 +#: git-gui.sh:620 msgid "Main Font" msgstr "Programmschriftart" -#: git-gui.sh:618 +#: git-gui.sh:621 msgid "Diff/Console Font" msgstr "Vergleich-Schriftart" -#: git-gui.sh:632 +#: git-gui.sh:635 msgid "Cannot find git in PATH." msgstr "Git kann im PATH nicht gefunden werden." -#: git-gui.sh:659 +#: git-gui.sh:662 msgid "Cannot parse Git version string:" msgstr "Git Versionsangabe kann nicht erkannt werden:" -#: git-gui.sh:676 +#: git-gui.sh:680 #, tcl-format msgid "" "Git version cannot be determined.\n" @@ -60,79 +60,81 @@ msgstr "" "\n" "Soll angenommen werden, »%s« sei Version 1.5.0?\n" -#: git-gui.sh:849 +#: git-gui.sh:853 msgid "Git directory not found:" msgstr "Git-Verzeichnis nicht gefunden:" -#: git-gui.sh:856 +#: git-gui.sh:860 msgid "Cannot move to top of working directory:" -msgstr "Es konnte nicht in das oberste Verzeichnis der Arbeitskopie gewechselt werden:" +msgstr "" +"Es konnte nicht in das oberste Verzeichnis der Arbeitskopie gewechselt " +"werden:" -#: git-gui.sh:863 +#: git-gui.sh:867 msgid "Cannot use funny .git directory:" msgstr "Unerwartete Struktur des .git Verzeichnis:" -#: git-gui.sh:868 +#: git-gui.sh:872 msgid "No working directory" msgstr "Kein Arbeitsverzeichnis" -#: git-gui.sh:1015 +#: git-gui.sh:1019 msgid "Refreshing file status..." msgstr "Dateistatus aktualisieren..." -#: git-gui.sh:1080 +#: git-gui.sh:1084 msgid "Scanning for modified files ..." msgstr "Nach geänderten Dateien suchen..." -#: git-gui.sh:1255 lib/browser.tcl:245 +#: git-gui.sh:1259 lib/browser.tcl:245 msgid "Ready." msgstr "Bereit." -#: git-gui.sh:1521 +#: git-gui.sh:1525 msgid "Unmodified" msgstr "Unverändert" -#: git-gui.sh:1523 +#: git-gui.sh:1527 msgid "Modified, not staged" msgstr "Verändert, nicht bereitgestellt" -#: git-gui.sh:1524 git-gui.sh:1529 +#: git-gui.sh:1528 git-gui.sh:1533 msgid "Staged for commit" msgstr "Bereitgestellt zum Eintragen" -#: git-gui.sh:1525 git-gui.sh:1530 +#: git-gui.sh:1529 git-gui.sh:1534 msgid "Portions staged for commit" msgstr "Teilweise bereitgestellt zum Eintragen" -#: git-gui.sh:1526 git-gui.sh:1531 +#: git-gui.sh:1530 git-gui.sh:1535 msgid "Staged for commit, missing" msgstr "Bereitgestellt zum Eintragen, fehlend" -#: git-gui.sh:1528 +#: git-gui.sh:1532 msgid "Untracked, not staged" msgstr "Nicht unter Versionskontrolle, nicht bereitgestellt" -#: git-gui.sh:1533 +#: git-gui.sh:1537 msgid "Missing" msgstr "Fehlend" -#: git-gui.sh:1534 +#: git-gui.sh:1538 msgid "Staged for removal" msgstr "Bereitgestellt zum Löschen" -#: git-gui.sh:1535 +#: git-gui.sh:1539 msgid "Staged for removal, still present" msgstr "Bereitgestellt zum Löschen, trotzdem vorhanden" -#: git-gui.sh:1537 git-gui.sh:1538 git-gui.sh:1539 git-gui.sh:1540 +#: git-gui.sh:1541 git-gui.sh:1542 git-gui.sh:1543 git-gui.sh:1544 msgid "Requires merge resolution" msgstr "Konfliktauflösung nötig" -#: git-gui.sh:1575 +#: git-gui.sh:1579 msgid "Starting gitk... please wait..." msgstr "Gitk wird gestartet... bitte warten." -#: git-gui.sh:1584 +#: git-gui.sh:1588 #, tcl-format msgid "" "Unable to start gitk:\n" @@ -143,291 +145,297 @@ msgstr "" "\n" "%s existiert nicht" -#: git-gui.sh:1784 lib/choose_repository.tcl:64 +#: git-gui.sh:1788 lib/choose_repository.tcl:32 msgid "Repository" msgstr "Projektarchiv" -#: git-gui.sh:1785 +#: git-gui.sh:1789 msgid "Edit" msgstr "Bearbeiten" -#: git-gui.sh:1787 lib/choose_rev.tcl:560 +#: git-gui.sh:1791 lib/choose_rev.tcl:560 msgid "Branch" msgstr "Zweig" -#: git-gui.sh:1790 lib/choose_rev.tcl:547 +#: git-gui.sh:1794 lib/choose_rev.tcl:547 msgid "Commit@@noun" msgstr "Version" -#: git-gui.sh:1793 lib/merge.tcl:121 lib/merge.tcl:150 lib/merge.tcl:168 +#: git-gui.sh:1797 lib/merge.tcl:121 lib/merge.tcl:150 lib/merge.tcl:168 msgid "Merge" msgstr "Zusammenführen" -#: git-gui.sh:1794 -msgid "Fetch" -msgstr "Anfordern" +#: git-gui.sh:1798 lib/choose_rev.tcl:556 +msgid "Remote" +msgstr "Gegenseite" -#: git-gui.sh:1795 git-gui.sh:2294 lib/transport.tcl:93 lib/transport.tcl:182 -msgid "Push" -msgstr "Ausliefern" - -#: git-gui.sh:1804 +#: git-gui.sh:1807 msgid "Browse Current Branch's Files" msgstr "Aktuellen Zweig durchblättern" -#: git-gui.sh:1808 +#: git-gui.sh:1811 msgid "Browse Branch Files..." msgstr "Einen Zweig durchblättern..." -#: git-gui.sh:1813 +#: git-gui.sh:1816 msgid "Visualize Current Branch's History" msgstr "Aktuellen Zweig darstellen" -#: git-gui.sh:1817 +#: git-gui.sh:1820 msgid "Visualize All Branch History" msgstr "Alle Zweige darstellen" -#: git-gui.sh:1824 +#: git-gui.sh:1827 #, tcl-format msgid "Browse %s's Files" msgstr "Zweig »%s« durchblättern" -#: git-gui.sh:1826 +#: git-gui.sh:1829 #, tcl-format msgid "Visualize %s's History" msgstr "Historie von »%s« darstellen" -#: git-gui.sh:1831 lib/database.tcl:27 lib/database.tcl:67 +#: git-gui.sh:1834 lib/database.tcl:27 lib/database.tcl:67 msgid "Database Statistics" msgstr "Datenbankstatistik" -#: git-gui.sh:1834 lib/database.tcl:34 +#: git-gui.sh:1837 lib/database.tcl:34 msgid "Compress Database" msgstr "Datenbank komprimieren" -#: git-gui.sh:1837 +#: git-gui.sh:1840 msgid "Verify Database" msgstr "Datenbank überprüfen" -#: git-gui.sh:1844 git-gui.sh:1848 git-gui.sh:1852 lib/shortcut.tcl:9 +#: git-gui.sh:1847 git-gui.sh:1851 git-gui.sh:1855 lib/shortcut.tcl:9 #: lib/shortcut.tcl:45 lib/shortcut.tcl:84 msgid "Create Desktop Icon" msgstr "Desktop-Icon erstellen" -#: git-gui.sh:1857 lib/choose_repository.tcl:68 lib/choose_repository.tcl:132 +#: git-gui.sh:1860 lib/choose_repository.tcl:36 lib/choose_repository.tcl:95 msgid "Quit" msgstr "Beenden" -#: git-gui.sh:1864 +#: git-gui.sh:1867 msgid "Undo" msgstr "Rückgängig" -#: git-gui.sh:1867 +#: git-gui.sh:1870 msgid "Redo" msgstr "Wiederholen" -#: git-gui.sh:1871 git-gui.sh:2358 +#: git-gui.sh:1874 git-gui.sh:2366 msgid "Cut" msgstr "Ausschneiden" -#: git-gui.sh:1874 git-gui.sh:2361 git-gui.sh:2432 git-gui.sh:2504 +#: git-gui.sh:1877 git-gui.sh:2369 git-gui.sh:2440 git-gui.sh:2512 #: lib/console.tcl:67 msgid "Copy" msgstr "Kopieren" -#: git-gui.sh:1877 git-gui.sh:2364 +#: git-gui.sh:1880 git-gui.sh:2372 msgid "Paste" msgstr "Einfügen" -#: git-gui.sh:1880 git-gui.sh:2367 lib/branch_delete.tcl:26 +#: git-gui.sh:1883 git-gui.sh:2375 lib/branch_delete.tcl:26 #: lib/remote_branch_delete.tcl:38 msgid "Delete" msgstr "Löschen" -#: git-gui.sh:1884 git-gui.sh:2371 git-gui.sh:2508 lib/console.tcl:69 +#: git-gui.sh:1887 git-gui.sh:2379 git-gui.sh:2516 lib/console.tcl:69 msgid "Select All" msgstr "Alle auswählen" -#: git-gui.sh:1893 +#: git-gui.sh:1896 msgid "Create..." msgstr "Erstellen..." -#: git-gui.sh:1899 +#: git-gui.sh:1902 msgid "Checkout..." msgstr "Umstellen..." -#: git-gui.sh:1905 +#: git-gui.sh:1908 msgid "Rename..." msgstr "Umbenennen..." -#: git-gui.sh:1910 git-gui.sh:2008 +#: git-gui.sh:1913 git-gui.sh:2012 msgid "Delete..." msgstr "Löschen..." -#: git-gui.sh:1915 +#: git-gui.sh:1918 msgid "Reset..." msgstr "Zurücksetzen..." -#: git-gui.sh:1927 git-gui.sh:2305 +#: git-gui.sh:1930 git-gui.sh:2313 msgid "New Commit" msgstr "Neue Version" -#: git-gui.sh:1935 git-gui.sh:2312 +#: git-gui.sh:1938 git-gui.sh:2320 msgid "Amend Last Commit" msgstr "Letzte Version nachbessern" -#: git-gui.sh:1944 git-gui.sh:2272 lib/remote_branch_delete.tcl:99 +#: git-gui.sh:1947 git-gui.sh:2280 lib/remote_branch_delete.tcl:99 msgid "Rescan" msgstr "Neu laden" -#: git-gui.sh:1950 +#: git-gui.sh:1953 msgid "Stage To Commit" msgstr "Zum Eintragen bereitstellen" -#: git-gui.sh:1955 +#: git-gui.sh:1958 msgid "Stage Changed Files To Commit" msgstr "Geänderte Dateien zum Eintragen bereitstellen" -#: git-gui.sh:1961 +#: git-gui.sh:1964 msgid "Unstage From Commit" msgstr "Aus der Bereitstellung herausnehmen" -#: git-gui.sh:1966 lib/index.tcl:382 +#: git-gui.sh:1969 lib/index.tcl:352 msgid "Revert Changes" msgstr "Änderungen revidieren" -#: git-gui.sh:1973 git-gui.sh:2284 git-gui.sh:2382 +#: git-gui.sh:1976 git-gui.sh:2292 git-gui.sh:2390 msgid "Sign Off" msgstr "Abzeichnen" -#: git-gui.sh:1977 git-gui.sh:2288 +#: git-gui.sh:1980 git-gui.sh:2296 msgid "Commit@@verb" msgstr "Eintragen" -#: git-gui.sh:1988 +#: git-gui.sh:1991 msgid "Local Merge..." msgstr "Lokales Zusammenführen..." -#: git-gui.sh:1993 +#: git-gui.sh:1996 msgid "Abort Merge..." msgstr "Zusammenführen abbrechen..." -#: git-gui.sh:2005 +#: git-gui.sh:2008 msgid "Push..." msgstr "Ausliefern..." -#: git-gui.sh:2015 lib/choose_repository.tcl:73 +#: git-gui.sh:2019 lib/choose_repository.tcl:41 msgid "Apple" msgstr "Apple" -#: git-gui.sh:2018 git-gui.sh:2036 lib/choose_repository.tcl:76 -#: lib/choose_repository.tcl:82 lib/option.tcl:65 +#: git-gui.sh:2022 git-gui.sh:2044 lib/about.tcl:13 +#: lib/choose_repository.tcl:44 lib/choose_repository.tcl:50 #, tcl-format msgid "About %s" msgstr "Über %s" -#: git-gui.sh:2020 git-gui.sh:2026 git-gui.sh:2550 +#: git-gui.sh:2026 +msgid "Preferences..." +msgstr "" + +#: git-gui.sh:2034 git-gui.sh:2558 msgid "Options..." msgstr "Optionen..." -#: git-gui.sh:2032 lib/choose_repository.tcl:79 +#: git-gui.sh:2040 lib/choose_repository.tcl:47 msgid "Help" msgstr "Hilfe" -#: git-gui.sh:2073 +#: git-gui.sh:2081 msgid "Online Documentation" msgstr "Online-Dokumentation" -#: git-gui.sh:2157 +#: git-gui.sh:2165 #, tcl-format msgid "fatal: cannot stat path %s: No such file or directory" msgstr "" -#: git-gui.sh:2190 +#: git-gui.sh:2198 msgid "Current Branch:" msgstr "Aktueller Zweig:" -#: git-gui.sh:2211 -msgid "Staged Changes (Will Be Committed)" +#: git-gui.sh:2219 +#, fuzzy +msgid "Staged Changes (Will Commit)" msgstr "Bereitgestellte Änderungen (werden eingetragen)" -#: git-gui.sh:2231 -msgid "Unstaged Changes (Will Not Be Committed)" -msgstr "Nicht bereitgestellte Änderungen (werden nicht eingetragen)" +#: git-gui.sh:2239 +#, fuzzy +msgid "Unstaged Changes" +msgstr "Geänderte bereitstellen" -#: git-gui.sh:2278 +#: git-gui.sh:2286 msgid "Stage Changed" msgstr "Geänderte bereitstellen" -#: git-gui.sh:2324 +#: git-gui.sh:2302 lib/transport.tcl:93 lib/transport.tcl:182 +msgid "Push" +msgstr "Ausliefern" + +#: git-gui.sh:2332 msgid "Initial Commit Message:" msgstr "Beschreibung der ersten Version:" -#: git-gui.sh:2325 +#: git-gui.sh:2333 msgid "Amended Commit Message:" msgstr "Beschreibung der nachgebesserten Version:" -#: git-gui.sh:2326 +#: git-gui.sh:2334 msgid "Amended Initial Commit Message:" msgstr "Beschreibung der nachgebesserten ersten Version:" -#: git-gui.sh:2327 +#: git-gui.sh:2335 msgid "Amended Merge Commit Message:" msgstr "Beschreibung der nachgebesserten Zusammenführungs-Version:" -#: git-gui.sh:2328 +#: git-gui.sh:2336 msgid "Merge Commit Message:" msgstr "Beschreibung der Zusammenführungs-Version:" -#: git-gui.sh:2329 +#: git-gui.sh:2337 msgid "Commit Message:" msgstr "Versionsbeschreibung:" -#: git-gui.sh:2374 git-gui.sh:2512 lib/console.tcl:71 +#: git-gui.sh:2382 git-gui.sh:2520 lib/console.tcl:71 msgid "Copy All" msgstr "Alle kopieren" -#: git-gui.sh:2398 lib/blame.tcl:104 +#: git-gui.sh:2406 lib/blame.tcl:104 msgid "File:" msgstr "Datei:" -#: git-gui.sh:2500 +#: git-gui.sh:2508 msgid "Refresh" msgstr "Aktualisieren" -#: git-gui.sh:2521 +#: git-gui.sh:2529 msgid "Apply/Reverse Hunk" msgstr "Änderung anwenden/umkehren" -#: git-gui.sh:2527 +#: git-gui.sh:2535 msgid "Decrease Font Size" msgstr "Schriftgröße verkleinern" -#: git-gui.sh:2531 +#: git-gui.sh:2539 msgid "Increase Font Size" msgstr "Schriftgröße vergrößern" -#: git-gui.sh:2536 +#: git-gui.sh:2544 msgid "Show Less Context" msgstr "Weniger Kontext anzeigen" -#: git-gui.sh:2543 +#: git-gui.sh:2551 msgid "Show More Context" msgstr "Mehr Kontext anzeigen" -#: git-gui.sh:2557 +#: git-gui.sh:2565 msgid "Unstage Hunk From Commit" msgstr "Aus der Bereitstellung herausnehmen" -#: git-gui.sh:2559 +#: git-gui.sh:2567 msgid "Stage Hunk For Commit" msgstr "In die Bereitstellung hinzufügen" -#: git-gui.sh:2578 +#: git-gui.sh:2586 msgid "Initializing..." msgstr "Initialisieren..." -#: git-gui.sh:2669 +#: git-gui.sh:2677 #, tcl-format msgid "" "Possible environment issues exist.\n" @@ -438,14 +446,14 @@ msgid "" "\n" msgstr "" -#: git-gui.sh:2699 +#: git-gui.sh:2707 msgid "" "\n" "This is due to a known issue with the\n" "Tcl binary distributed by Cygwin." msgstr "" -#: git-gui.sh:2704 +#: git-gui.sh:2712 #, tcl-format msgid "" "\n" @@ -456,6 +464,10 @@ msgid "" "~/.gitconfig file.\n" msgstr "" +#: lib/about.tcl:25 +msgid "git-gui - a graphical user interface for Git." +msgstr "git-gui - eine grafische Oberfläche für Git." + #: lib/blame.tcl:77 msgid "File Viewer" msgstr "Datei-Browser" @@ -528,7 +540,7 @@ msgstr "Umstellen" #: lib/branch_checkout.tcl:27 lib/branch_create.tcl:35 #: lib/branch_delete.tcl:32 lib/branch_rename.tcl:30 lib/browser.tcl:281 #: lib/checkout_op.tcl:522 lib/choose_font.tcl:43 lib/merge.tcl:172 -#: lib/option.tcl:172 lib/remote_branch_delete.tcl:42 lib/transport.tcl:97 +#: lib/option.tcl:90 lib/remote_branch_delete.tcl:42 lib/transport.tcl:97 msgid "Cancel" msgstr "Abbrechen" @@ -536,8 +548,7 @@ msgstr "Abbrechen" msgid "Revision" msgstr "Version" -#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:159 -#: lib/option.tcl:280 +#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:202 msgid "Options" msgstr "Optionen" @@ -557,7 +568,7 @@ msgstr "Zweig erstellen" msgid "Create New Branch" msgstr "Neuen Zweig erstellen" -#: lib/branch_create.tcl:31 lib/choose_repository.tcl:236 +#: lib/branch_create.tcl:31 lib/choose_repository.tcl:199 msgid "Create" msgstr "Erstellen" @@ -710,9 +721,9 @@ msgstr "[Nach oben]" msgid "Browse Branch Files" msgstr "Dateien des Zweigs durchblättern" -#: lib/browser.tcl:277 lib/choose_repository.tcl:252 -#: lib/choose_repository.tcl:342 lib/choose_repository.tcl:352 -#: lib/choose_repository.tcl:848 +#: lib/browser.tcl:277 lib/choose_repository.tcl:215 +#: lib/choose_repository.tcl:305 lib/choose_repository.tcl:315 +#: lib/choose_repository.tcl:811 msgid "Browse" msgstr "Blättern" @@ -878,208 +889,209 @@ msgstr "" "Dies ist ein Beispieltext.\n" "Wenn Ihnen dieser Text gefällt, sollten Sie diese Schriftart wählen." -#: lib/choose_repository.tcl:57 +#: lib/choose_repository.tcl:25 msgid "Git Gui" msgstr "Git Gui" -#: lib/choose_repository.tcl:106 lib/choose_repository.tcl:241 +#: lib/choose_repository.tcl:69 lib/choose_repository.tcl:204 msgid "Create New Repository" msgstr "Neues Projektarchiv" -#: lib/choose_repository.tcl:111 lib/choose_repository.tcl:328 +#: lib/choose_repository.tcl:74 lib/choose_repository.tcl:291 msgid "Clone Existing Repository" msgstr "Projektarchiv kopieren" -#: lib/choose_repository.tcl:116 lib/choose_repository.tcl:837 +#: lib/choose_repository.tcl:79 lib/choose_repository.tcl:800 msgid "Open Existing Repository" msgstr "Projektarchiv öffnen" -#: lib/choose_repository.tcl:128 +#: lib/choose_repository.tcl:91 msgid "Next >" msgstr "Weiter >" -#: lib/choose_repository.tcl:189 +#: lib/choose_repository.tcl:152 #, tcl-format msgid "Location %s already exists." msgstr "Projektarchiv »%s« existiert bereits." -#: lib/choose_repository.tcl:195 lib/choose_repository.tcl:202 -#: lib/choose_repository.tcl:209 +#: lib/choose_repository.tcl:158 lib/choose_repository.tcl:165 +#: lib/choose_repository.tcl:172 #, tcl-format msgid "Failed to create repository %s:" msgstr "Projektarchiv »%s« konnte nicht erstellt werden:" -#: lib/choose_repository.tcl:246 lib/choose_repository.tcl:346 +#: lib/choose_repository.tcl:209 lib/choose_repository.tcl:309 msgid "Directory:" msgstr "Verzeichnis:" -#: lib/choose_repository.tcl:275 lib/choose_repository.tcl:400 -#: lib/choose_repository.tcl:871 +#: lib/choose_repository.tcl:238 lib/choose_repository.tcl:363 +#: lib/choose_repository.tcl:834 msgid "Git Repository" msgstr "Git Projektarchiv" -#: lib/choose_repository.tcl:290 lib/choose_repository.tcl:297 +#: lib/choose_repository.tcl:253 lib/choose_repository.tcl:260 #, tcl-format msgid "Directory %s already exists." msgstr "Verzeichnis »%s« existiert bereits." -#: lib/choose_repository.tcl:302 +#: lib/choose_repository.tcl:265 #, tcl-format msgid "File %s already exists." msgstr "Datei »%s« existiert bereits." -#: lib/choose_repository.tcl:323 +#: lib/choose_repository.tcl:286 msgid "Clone" msgstr "Kopieren" -#: lib/choose_repository.tcl:336 +#: lib/choose_repository.tcl:299 msgid "URL:" msgstr "URL:" -#: lib/choose_repository.tcl:356 +#: lib/choose_repository.tcl:319 msgid "Clone Type:" msgstr "Art der Kopie:" -#: lib/choose_repository.tcl:362 +#: lib/choose_repository.tcl:325 msgid "Standard (Fast, Semi-Redundant, Hardlinks)" msgstr "" -#: lib/choose_repository.tcl:368 +#: lib/choose_repository.tcl:331 msgid "Full Copy (Slower, Redundant Backup)" msgstr "" -#: lib/choose_repository.tcl:374 +#: lib/choose_repository.tcl:337 msgid "Shared (Fastest, Not Recommended, No Backup)" msgstr "" -#: lib/choose_repository.tcl:406 lib/choose_repository.tcl:455 -#: lib/choose_repository.tcl:597 lib/choose_repository.tcl:667 -#: lib/choose_repository.tcl:877 lib/choose_repository.tcl:885 +#: lib/choose_repository.tcl:369 lib/choose_repository.tcl:418 +#: lib/choose_repository.tcl:560 lib/choose_repository.tcl:630 +#: lib/choose_repository.tcl:840 lib/choose_repository.tcl:848 #, tcl-format msgid "Not a Git repository: %s" msgstr "Kein Git-Projektarchiv in »%s« gefunden." -#: lib/choose_repository.tcl:442 +#: lib/choose_repository.tcl:405 msgid "Standard only available for local repository." msgstr "" -#: lib/choose_repository.tcl:446 +#: lib/choose_repository.tcl:409 msgid "Shared only available for local repository." msgstr "" -#: lib/choose_repository.tcl:476 +#: lib/choose_repository.tcl:439 msgid "Failed to configure origin" msgstr "" -#: lib/choose_repository.tcl:488 +#: lib/choose_repository.tcl:451 msgid "Counting objects" msgstr "" -#: lib/choose_repository.tcl:489 +#: lib/choose_repository.tcl:452 msgid "buckets" msgstr "" -#: lib/choose_repository.tcl:513 +#: lib/choose_repository.tcl:476 #, tcl-format msgid "Unable to copy objects/info/alternates: %s" msgstr "" -#: lib/choose_repository.tcl:549 +#: lib/choose_repository.tcl:512 #, tcl-format msgid "Nothing to clone from %s." msgstr "Von »%s« konnte nichts kopiert werden." -#: lib/choose_repository.tcl:551 lib/choose_repository.tcl:765 -#: lib/choose_repository.tcl:777 +#: lib/choose_repository.tcl:514 lib/choose_repository.tcl:728 +#: lib/choose_repository.tcl:740 msgid "The 'master' branch has not been initialized." msgstr "" -#: lib/choose_repository.tcl:564 +#: lib/choose_repository.tcl:527 msgid "Hardlinks are unavailable. Falling back to copying." msgstr "" -#: lib/choose_repository.tcl:576 +#: lib/choose_repository.tcl:539 #, tcl-format msgid "Cloning from %s" msgstr "Kopieren von »%s«" -#: lib/choose_repository.tcl:607 +#: lib/choose_repository.tcl:570 msgid "Copying objects" msgstr "Objektdatenbank kopieren" -#: lib/choose_repository.tcl:608 +#: lib/choose_repository.tcl:571 msgid "KiB" msgstr "KB" -#: lib/choose_repository.tcl:632 +#: lib/choose_repository.tcl:595 #, tcl-format msgid "Unable to copy object: %s" msgstr "Objekt kann nicht kopiert werden: %s" -#: lib/choose_repository.tcl:642 +#: lib/choose_repository.tcl:605 msgid "Linking objects" msgstr "Objekte verlinken" -#: lib/choose_repository.tcl:643 +#: lib/choose_repository.tcl:606 msgid "objects" msgstr "Objekte" -#: lib/choose_repository.tcl:651 +#: lib/choose_repository.tcl:614 #, tcl-format msgid "Unable to hardlink object: %s" msgstr "Objekt kann nicht hartverlinkt werden: %s" -#: lib/choose_repository.tcl:706 +#: lib/choose_repository.tcl:669 msgid "Cannot fetch branches and objects. See console output for details." msgstr "" -#: lib/choose_repository.tcl:717 +#: lib/choose_repository.tcl:680 msgid "Cannot fetch tags. See console output for details." msgstr "" -#: lib/choose_repository.tcl:741 +#: lib/choose_repository.tcl:704 msgid "Cannot determine HEAD. See console output for details." msgstr "" -#: lib/choose_repository.tcl:750 +#: lib/choose_repository.tcl:713 #, tcl-format msgid "Unable to cleanup %s" msgstr "" -#: lib/choose_repository.tcl:756 +#: lib/choose_repository.tcl:719 msgid "Clone failed." msgstr "Kopieren fehlgeschlagen." -#: lib/choose_repository.tcl:763 +#: lib/choose_repository.tcl:726 msgid "No default branch obtained." msgstr "" -#: lib/choose_repository.tcl:774 +#: lib/choose_repository.tcl:737 #, tcl-format msgid "Cannot resolve %s as a commit." msgstr "" -#: lib/choose_repository.tcl:786 +#: lib/choose_repository.tcl:749 msgid "Creating working directory" msgstr "Arbeitskopie erstellen" -#: lib/choose_repository.tcl:787 +#: lib/choose_repository.tcl:750 lib/index.tcl:15 lib/index.tcl:80 +#: lib/index.tcl:149 msgid "files" msgstr "Dateien" -#: lib/choose_repository.tcl:816 +#: lib/choose_repository.tcl:779 msgid "Initial file checkout failed." msgstr "" -#: lib/choose_repository.tcl:832 +#: lib/choose_repository.tcl:795 msgid "Open" msgstr "Öffnen" -#: lib/choose_repository.tcl:842 +#: lib/choose_repository.tcl:805 msgid "Repository:" msgstr "Projektarchiv:" -#: lib/choose_repository.tcl:891 +#: lib/choose_repository.tcl:854 #, tcl-format msgid "Failed to open repository %s:" msgstr "Projektarchiv »%s« konnte nicht geöffnet werden." @@ -1121,10 +1133,6 @@ msgstr "Versions-Ausdruck ist leer." msgid "Updated" msgstr "Aktualisiert" -#: lib/choose_rev.tcl:556 -msgid "Remote" -msgstr "Gegenseite" - #: lib/choose_rev.tcl:558 msgid "URL" msgstr "URL" @@ -1344,7 +1352,9 @@ msgid "" msgstr "" "Dieses Projektarchiv enthält ungefähr %i nicht verknüpfte Objekte.\n" "\n" -"Für eine optimale Performance wird empfohlen, die Datenbank des Projektarchivs zu komprimieren, sobald mehr als %i nicht verknüpfte Objekte vorliegen.\n" +"Für eine optimale Performance wird empfohlen, die Datenbank des " +"Projektarchivs zu komprimieren, sobald mehr als %i nicht verknüpfte Objekte " +"vorliegen.\n" "\n" "Soll die Datenbank jetzt komprimiert werden?" @@ -1422,32 +1432,32 @@ msgid "You must correct the above errors before committing." msgstr "" "Sie müssen die obigen Fehler zuerst beheben, bevor Sie eintragen können." -#: lib/index.tcl:271 +#: lib/index.tcl:241 #, tcl-format msgid "Unstaging %s from commit" msgstr "Datei »%s« aus der Bereitstellung herausnehmen" -#: lib/index.tcl:315 +#: lib/index.tcl:285 #, tcl-format msgid "Adding %s" msgstr "»%s« hinzufügen..." -#: lib/index.tcl:370 +#: lib/index.tcl:340 #, tcl-format msgid "Revert changes in file %s?" msgstr "Änderungen in Datei »%s« revidieren?" -#: lib/index.tcl:372 +#: lib/index.tcl:342 #, tcl-format msgid "Revert changes in these %i files?" msgstr "Änderungen in den gewählten %i Dateien revidieren?" -#: lib/index.tcl:378 +#: lib/index.tcl:348 msgid "Any unstaged changes will be permanently lost by the revert." msgstr "" "Alle nicht bereitgestellten Änderungen werden beim Revidieren verloren gehen." -#: lib/index.tcl:381 +#: lib/index.tcl:351 msgid "Do Nothing" msgstr "Nichts tun" @@ -1591,84 +1601,99 @@ msgstr "Abbruch fehlgeschlagen." msgid "Abort completed. Ready." msgstr "Abbruch durchgeführt. Bereit." -#: lib/option.tcl:77 -msgid "git-gui - a graphical user interface for Git." -msgstr "git-gui - eine grafische Oberfläche für Git." - -#: lib/option.tcl:164 +#: lib/option.tcl:82 msgid "Restore Defaults" msgstr "Voreinstellungen wiederherstellen" -#: lib/option.tcl:168 +#: lib/option.tcl:86 msgid "Save" msgstr "Speichern" -#: lib/option.tcl:178 +#: lib/option.tcl:96 #, tcl-format msgid "%s Repository" msgstr "Projektarchiv %s" -#: lib/option.tcl:179 +#: lib/option.tcl:97 msgid "Global (All Repositories)" msgstr "Global (Alle Projektarchive)" -#: lib/option.tcl:185 +#: lib/option.tcl:103 msgid "User Name" msgstr "Benutzername" -#: lib/option.tcl:186 +#: lib/option.tcl:104 msgid "Email Address" msgstr "E-Mail-Adresse" -#: lib/option.tcl:188 +#: lib/option.tcl:106 msgid "Summarize Merge Commits" msgstr "Zusammenführungs-Versionen zusammenfassen" -#: lib/option.tcl:189 +#: lib/option.tcl:107 msgid "Merge Verbosity" msgstr "Ausführlichkeit der Zusammenführen-Meldungen" -#: lib/option.tcl:190 +#: lib/option.tcl:108 msgid "Show Diffstat After Merge" msgstr "Vergleichsstatistik nach Zusammenführen anzeigen" -#: lib/option.tcl:192 +#: lib/option.tcl:110 msgid "Trust File Modification Timestamps" msgstr "Auf Dateiänderungsdatum verlassen" -#: lib/option.tcl:193 +#: lib/option.tcl:111 msgid "Prune Tracking Branches During Fetch" msgstr "Übernahmezweige löschen während Anforderung" -#: lib/option.tcl:194 +#: lib/option.tcl:112 msgid "Match Tracking Branches" msgstr "Passend zu Übernahmezweig" -#: lib/option.tcl:195 +#: lib/option.tcl:113 msgid "Number of Diff Context Lines" msgstr "Anzahl der Kontextzeilen beim Vergleich" -#: lib/option.tcl:196 +#: lib/option.tcl:114 msgid "New Branch Name Template" msgstr "Namensvorschlag für neue Zweige" -#: lib/option.tcl:258 +#: lib/option.tcl:176 msgid "Change Font" msgstr "Schriftart ändern" -#: lib/option.tcl:262 +#: lib/option.tcl:180 #, tcl-format msgid "Choose %s" msgstr "%s wählen" -#: lib/option.tcl:268 +#: lib/option.tcl:186 msgid "pt." msgstr "pt." -#: lib/option.tcl:311 +#: lib/option.tcl:200 +msgid "Preferences" +msgstr "" + +#: lib/option.tcl:235 msgid "Failed to completely save options:" msgstr "Optionen konnten nicht gespeichert werden:" +#: lib/remote.tcl:165 +#, fuzzy +msgid "Prune from" +msgstr "Löschen von »%s«" + +#: lib/remote.tcl:170 +#, fuzzy +msgid "Fetch from" +msgstr "Von »%s« anfordern" + +#: lib/remote.tcl:213 +#, fuzzy +msgid "Push to" +msgstr "Nach »%s« ausliefern" + #: lib/remote_branch_delete.tcl:29 lib/remote_branch_delete.tcl:34 msgid "Delete Remote Branch" msgstr "Zweig im Projektarchiv der Gegenseite löschen" @@ -1755,21 +1780,6 @@ msgstr "Kein Projektarchiv ausgewählt." msgid "Scanning %s..." msgstr "»%s« laden..." -#: lib/remote.tcl:162 -#, tcl-format -msgid "Fetch from %s" -msgstr "Von »%s« anfordern" - -#: lib/remote.tcl:172 -#, tcl-format -msgid "Prune from %s" -msgstr "Löschen von »%s«" - -#: lib/remote.tcl:206 -#, tcl-format -msgid "Push to %s" -msgstr "Nach »%s« ausliefern" - #: lib/shortcut.tcl:26 lib/shortcut.tcl:74 msgid "Cannot write script:" msgstr "Fehler beim Schreiben des Scripts:" @@ -1836,7 +1846,8 @@ msgstr "Netzwerk-Einstellungen" #: lib/transport.tcl:160 msgid "Force overwrite existing branch (may discard changes)" -msgstr "Überschreiben von existierenden Zweigen erzwingen (könnte Änderungen löschen)" +msgstr "" +"Überschreiben von existierenden Zweigen erzwingen (könnte Änderungen löschen)" #: lib/transport.tcl:164 msgid "Use thin pack (for slow network connections)" @@ -1845,3 +1856,9 @@ msgstr "Kompaktes Datenformat benutzen (für langsame Netzverbindungen)" #: lib/transport.tcl:168 msgid "Include tags" msgstr "Mit Markierungen übertragen" + +#~ msgid "Fetch" +#~ msgstr "Anfordern" + +#~ msgid "Unstaged Changes (Will Not Be Committed)" +#~ msgstr "Nicht bereitgestellte Änderungen (werden nicht eingetragen)" diff --git a/po/git-gui.pot b/po/git-gui.pot index b352302572..00f0f5922a 100644 --- a/po/git-gui.pot +++ b/po/git-gui.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2007-08-11 17:28+0200\n" +"POT-Creation-Date: 2007-10-10 04:04-0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -16,15 +16,33 @@ msgstr "" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" -#: git-gui.sh:531 +#: git-gui.sh:41 git-gui.sh:634 git-gui.sh:648 git-gui.sh:661 git-gui.sh:744 +#: git-gui.sh:763 +msgid "git-gui: fatal error" +msgstr "" + +#: git-gui.sh:595 +#, tcl-format +msgid "Invalid font specified in %s:" +msgstr "" + +#: git-gui.sh:620 +msgid "Main Font" +msgstr "" + +#: git-gui.sh:621 +msgid "Diff/Console Font" +msgstr "" + +#: git-gui.sh:635 msgid "Cannot find git in PATH." msgstr "" -#: git-gui.sh:550 +#: git-gui.sh:662 msgid "Cannot parse Git version string:" msgstr "" -#: git-gui.sh:567 +#: git-gui.sh:680 #, tcl-format msgid "" "Git version cannot be determined.\n" @@ -36,79 +54,79 @@ msgid "" "Assume '%s' is version 1.5.0?\n" msgstr "" -#: git-gui.sh:689 -msgid "Cannot find the git directory:" -msgstr "" - -#: git-gui.sh:697 +#: git-gui.sh:853 msgid "Git directory not found:" msgstr "" -#: git-gui.sh:703 +#: git-gui.sh:860 +msgid "Cannot move to top of working directory:" +msgstr "" + +#: git-gui.sh:867 msgid "Cannot use funny .git directory:" msgstr "" -#: git-gui.sh:708 +#: git-gui.sh:872 msgid "No working directory" msgstr "" -#: git-gui.sh:854 +#: git-gui.sh:1019 msgid "Refreshing file status..." msgstr "" -#: git-gui.sh:891 +#: git-gui.sh:1084 msgid "Scanning for modified files ..." msgstr "" -#: git-gui.sh:1057 lib/browser.tcl:247 +#: git-gui.sh:1259 lib/browser.tcl:245 msgid "Ready." msgstr "" -#: git-gui.sh:1322 +#: git-gui.sh:1525 msgid "Unmodified" msgstr "" -#: git-gui.sh:1324 +#: git-gui.sh:1527 msgid "Modified, not staged" msgstr "" -#: git-gui.sh:1325 git-gui.sh:1330 +#: git-gui.sh:1528 git-gui.sh:1533 msgid "Staged for commit" msgstr "" -#: git-gui.sh:1326 git-gui.sh:1331 +#: git-gui.sh:1529 git-gui.sh:1534 msgid "Portions staged for commit" msgstr "" -#: git-gui.sh:1327 git-gui.sh:1332 +#: git-gui.sh:1530 git-gui.sh:1535 msgid "Staged for commit, missing" msgstr "" -#: git-gui.sh:1329 +#: git-gui.sh:1532 msgid "Untracked, not staged" msgstr "" -#: git-gui.sh:1334 +#: git-gui.sh:1537 msgid "Missing" msgstr "" -#: git-gui.sh:1335 +#: git-gui.sh:1538 msgid "Staged for removal" msgstr "" -#: git-gui.sh:1336 +#: git-gui.sh:1539 msgid "Staged for removal, still present" msgstr "" -#: git-gui.sh:1338 git-gui.sh:1339 git-gui.sh:1340 git-gui.sh:1341 +#: git-gui.sh:1541 git-gui.sh:1542 git-gui.sh:1543 git-gui.sh:1544 msgid "Requires merge resolution" msgstr "" -#: git-gui.sh:1383 +#: git-gui.sh:1579 msgid "Starting gitk... please wait..." msgstr "" -#: git-gui.sh:1392 +#: git-gui.sh:1588 #, tcl-format msgid "" "Unable to start gitk:\n" @@ -116,293 +134,327 @@ msgid "" "%s does not exist" msgstr "" -#: git-gui.sh:1609 -#, tcl-format -msgid "Invalid font specified in gui.%s:" -msgstr "" - -#: git-gui.sh:1634 -msgid "Main Font" -msgstr "" - -#: git-gui.sh:1635 -msgid "Diff/Console Font" -msgstr "" - -#: git-gui.sh:1649 +#: git-gui.sh:1788 lib/choose_repository.tcl:32 msgid "Repository" msgstr "" -#: git-gui.sh:1650 +#: git-gui.sh:1789 msgid "Edit" msgstr "" -#: git-gui.sh:1652 +#: git-gui.sh:1791 lib/choose_rev.tcl:560 msgid "Branch" msgstr "" -#: git-gui.sh:1655 git-gui.sh:1842 git-gui.sh:2152 -msgid "Commit" +#: git-gui.sh:1794 lib/choose_rev.tcl:547 +msgid "Commit@@noun" msgstr "" -#: git-gui.sh:1658 lib/merge.tcl:121 lib/merge.tcl:150 lib/merge.tcl:168 +#: git-gui.sh:1797 lib/merge.tcl:121 lib/merge.tcl:150 lib/merge.tcl:168 msgid "Merge" msgstr "" -#: git-gui.sh:1659 -msgid "Fetch" +#: git-gui.sh:1798 lib/choose_rev.tcl:556 +msgid "Remote" msgstr "" -#: git-gui.sh:1660 git-gui.sh:2158 lib/transport.tcl:88 lib/transport.tcl:172 -msgid "Push" -msgstr "" - -#: git-gui.sh:1669 +#: git-gui.sh:1807 msgid "Browse Current Branch's Files" msgstr "" -#: git-gui.sh:1673 +#: git-gui.sh:1811 msgid "Browse Branch Files..." msgstr "" -#: git-gui.sh:1678 +#: git-gui.sh:1816 msgid "Visualize Current Branch's History" msgstr "" -#: git-gui.sh:1682 +#: git-gui.sh:1820 msgid "Visualize All Branch History" msgstr "" -#: git-gui.sh:1689 +#: git-gui.sh:1827 #, tcl-format msgid "Browse %s's Files" msgstr "" -#: git-gui.sh:1691 +#: git-gui.sh:1829 #, tcl-format msgid "Visualize %s's History" msgstr "" -#: git-gui.sh:1696 lib/database.tcl:27 lib/database.tcl:67 +#: git-gui.sh:1834 lib/database.tcl:27 lib/database.tcl:67 msgid "Database Statistics" msgstr "" -#: git-gui.sh:1699 lib/database.tcl:34 +#: git-gui.sh:1837 lib/database.tcl:34 msgid "Compress Database" msgstr "" -#: git-gui.sh:1702 +#: git-gui.sh:1840 msgid "Verify Database" msgstr "" -#: git-gui.sh:1709 git-gui.sh:1713 git-gui.sh:1717 lib/shortcut.tcl:9 +#: git-gui.sh:1847 git-gui.sh:1851 git-gui.sh:1855 lib/shortcut.tcl:9 #: lib/shortcut.tcl:45 lib/shortcut.tcl:84 msgid "Create Desktop Icon" msgstr "" -#: git-gui.sh:1722 +#: git-gui.sh:1860 lib/choose_repository.tcl:36 lib/choose_repository.tcl:95 msgid "Quit" msgstr "" -#: git-gui.sh:1729 +#: git-gui.sh:1867 msgid "Undo" msgstr "" -#: git-gui.sh:1732 +#: git-gui.sh:1870 msgid "Redo" msgstr "" -#: git-gui.sh:1736 git-gui.sh:2222 +#: git-gui.sh:1874 git-gui.sh:2366 msgid "Cut" msgstr "" -#: git-gui.sh:1739 git-gui.sh:2225 git-gui.sh:2296 git-gui.sh:2368 -#: lib/console.tcl:69 +#: git-gui.sh:1877 git-gui.sh:2369 git-gui.sh:2440 git-gui.sh:2512 +#: lib/console.tcl:67 msgid "Copy" msgstr "" -#: git-gui.sh:1742 git-gui.sh:2228 +#: git-gui.sh:1880 git-gui.sh:2372 msgid "Paste" msgstr "" -#: git-gui.sh:1745 git-gui.sh:2231 lib/branch_delete.tcl:26 +#: git-gui.sh:1883 git-gui.sh:2375 lib/branch_delete.tcl:26 #: lib/remote_branch_delete.tcl:38 msgid "Delete" msgstr "" -#: git-gui.sh:1749 git-gui.sh:2235 git-gui.sh:2372 lib/console.tcl:71 +#: git-gui.sh:1887 git-gui.sh:2379 git-gui.sh:2516 lib/console.tcl:69 msgid "Select All" msgstr "" -#: git-gui.sh:1758 +#: git-gui.sh:1896 msgid "Create..." msgstr "" -#: git-gui.sh:1764 +#: git-gui.sh:1902 msgid "Checkout..." msgstr "" -#: git-gui.sh:1770 +#: git-gui.sh:1908 msgid "Rename..." msgstr "" -#: git-gui.sh:1775 git-gui.sh:1873 +#: git-gui.sh:1913 git-gui.sh:2012 msgid "Delete..." msgstr "" -#: git-gui.sh:1780 +#: git-gui.sh:1918 msgid "Reset..." msgstr "" -#: git-gui.sh:1792 git-gui.sh:2169 +#: git-gui.sh:1930 git-gui.sh:2313 msgid "New Commit" msgstr "" -#: git-gui.sh:1800 git-gui.sh:2176 +#: git-gui.sh:1938 git-gui.sh:2320 msgid "Amend Last Commit" msgstr "" -#: git-gui.sh:1809 git-gui.sh:2136 lib/remote_branch_delete.tcl:99 +#: git-gui.sh:1947 git-gui.sh:2280 lib/remote_branch_delete.tcl:99 msgid "Rescan" msgstr "" -#: git-gui.sh:1815 +#: git-gui.sh:1953 msgid "Stage To Commit" msgstr "" -#: git-gui.sh:1820 +#: git-gui.sh:1958 msgid "Stage Changed Files To Commit" msgstr "" -#: git-gui.sh:1826 +#: git-gui.sh:1964 msgid "Unstage From Commit" msgstr "" -#: git-gui.sh:1831 lib/index.tcl:376 +#: git-gui.sh:1969 lib/index.tcl:352 msgid "Revert Changes" msgstr "" -#: git-gui.sh:1838 git-gui.sh:2148 git-gui.sh:2246 +#: git-gui.sh:1976 git-gui.sh:2292 git-gui.sh:2390 msgid "Sign Off" msgstr "" -#: git-gui.sh:1853 +#: git-gui.sh:1980 git-gui.sh:2296 +msgid "Commit@@verb" +msgstr "" + +#: git-gui.sh:1991 msgid "Local Merge..." msgstr "" -#: git-gui.sh:1858 +#: git-gui.sh:1996 msgid "Abort Merge..." msgstr "" -#: git-gui.sh:1870 +#: git-gui.sh:2008 msgid "Push..." msgstr "" -#: git-gui.sh:1880 +#: git-gui.sh:2019 lib/choose_repository.tcl:41 msgid "Apple" msgstr "" -#: git-gui.sh:1883 git-gui.sh:1901 lib/option.tcl:65 +#: git-gui.sh:2022 git-gui.sh:2044 lib/about.tcl:13 +#: lib/choose_repository.tcl:44 lib/choose_repository.tcl:50 #, tcl-format msgid "About %s" msgstr "" -#: git-gui.sh:1885 git-gui.sh:1891 git-gui.sh:2414 +#: git-gui.sh:2026 +msgid "Preferences..." +msgstr "" + +#: git-gui.sh:2034 git-gui.sh:2558 msgid "Options..." msgstr "" -#: git-gui.sh:1897 +#: git-gui.sh:2040 lib/choose_repository.tcl:47 msgid "Help" msgstr "" -#: git-gui.sh:1938 +#: git-gui.sh:2081 msgid "Online Documentation" msgstr "" -#: git-gui.sh:2054 +#: git-gui.sh:2165 +#, tcl-format +msgid "fatal: cannot stat path %s: No such file or directory" +msgstr "" + +#: git-gui.sh:2198 msgid "Current Branch:" msgstr "" -#: git-gui.sh:2075 -msgid "Staged Changes (Will Be Committed)" +#: git-gui.sh:2219 +msgid "Staged Changes (Will Commit)" msgstr "" -#: git-gui.sh:2095 -msgid "Unstaged Changes (Will Not Be Committed)" +#: git-gui.sh:2239 +msgid "Unstaged Changes" msgstr "" -#: git-gui.sh:2142 +#: git-gui.sh:2286 msgid "Stage Changed" msgstr "" -#: git-gui.sh:2188 +#: git-gui.sh:2302 lib/transport.tcl:93 lib/transport.tcl:182 +msgid "Push" +msgstr "" + +#: git-gui.sh:2332 msgid "Initial Commit Message:" msgstr "" -#: git-gui.sh:2189 +#: git-gui.sh:2333 msgid "Amended Commit Message:" msgstr "" -#: git-gui.sh:2190 +#: git-gui.sh:2334 msgid "Amended Initial Commit Message:" msgstr "" -#: git-gui.sh:2191 +#: git-gui.sh:2335 msgid "Amended Merge Commit Message:" msgstr "" -#: git-gui.sh:2192 +#: git-gui.sh:2336 msgid "Merge Commit Message:" msgstr "" -#: git-gui.sh:2193 +#: git-gui.sh:2337 msgid "Commit Message:" msgstr "" -#: git-gui.sh:2238 git-gui.sh:2376 lib/console.tcl:73 +#: git-gui.sh:2382 git-gui.sh:2520 lib/console.tcl:71 msgid "Copy All" msgstr "" -#: git-gui.sh:2262 lib/blame.tcl:104 +#: git-gui.sh:2406 lib/blame.tcl:104 msgid "File:" msgstr "" -#: git-gui.sh:2364 +#: git-gui.sh:2508 msgid "Refresh" msgstr "" -#: git-gui.sh:2385 +#: git-gui.sh:2529 msgid "Apply/Reverse Hunk" msgstr "" -#: git-gui.sh:2391 +#: git-gui.sh:2535 msgid "Decrease Font Size" msgstr "" -#: git-gui.sh:2395 +#: git-gui.sh:2539 msgid "Increase Font Size" msgstr "" -#: git-gui.sh:2400 +#: git-gui.sh:2544 msgid "Show Less Context" msgstr "" -#: git-gui.sh:2407 +#: git-gui.sh:2551 msgid "Show More Context" msgstr "" -#: git-gui.sh:2422 +#: git-gui.sh:2565 msgid "Unstage Hunk From Commit" msgstr "" -#: git-gui.sh:2426 git-gui.sh:2430 +#: git-gui.sh:2567 msgid "Stage Hunk For Commit" msgstr "" -#: git-gui.sh:2440 +#: git-gui.sh:2586 msgid "Initializing..." msgstr "" +#: git-gui.sh:2677 +#, tcl-format +msgid "" +"Possible environment issues exist.\n" +"\n" +"The following environment variables are probably\n" +"going to be ignored by any Git subprocess run\n" +"by %s:\n" +"\n" +msgstr "" + +#: git-gui.sh:2707 +msgid "" +"\n" +"This is due to a known issue with the\n" +"Tcl binary distributed by Cygwin." +msgstr "" + +#: git-gui.sh:2712 +#, tcl-format +msgid "" +"\n" +"\n" +"A good replacement for %s\n" +"is placing values for the user.name and\n" +"user.email settings into your personal\n" +"~/.gitconfig file.\n" +msgstr "" + +#: lib/about.tcl:25 +msgid "git-gui - a graphical user interface for Git." +msgstr "" + #: lib/blame.tcl:77 msgid "File Viewer" msgstr "" @@ -420,6 +472,50 @@ msgstr "" msgid "Reading %s..." msgstr "" +#: lib/blame.tcl:473 +msgid "Loading copy/move tracking annotations..." +msgstr "" + +#: lib/blame.tcl:493 +msgid "lines annotated" +msgstr "" + +#: lib/blame.tcl:674 +msgid "Loading original location annotations..." +msgstr "" + +#: lib/blame.tcl:677 +msgid "Annotation complete." +msgstr "" + +#: lib/blame.tcl:731 +msgid "Loading annotation..." +msgstr "" + +#: lib/blame.tcl:787 +msgid "Author:" +msgstr "" + +#: lib/blame.tcl:791 +msgid "Committer:" +msgstr "" + +#: lib/blame.tcl:796 +msgid "Original File:" +msgstr "" + +#: lib/blame.tcl:910 +msgid "Originally By:" +msgstr "" + +#: lib/blame.tcl:916 +msgid "In File:" +msgstr "" + +#: lib/blame.tcl:921 +msgid "Copied Or Moved Here By:" +msgstr "" + #: lib/branch_checkout.tcl:14 lib/branch_checkout.tcl:19 msgid "Checkout Branch" msgstr "" @@ -429,18 +525,17 @@ msgid "Checkout" msgstr "" #: lib/branch_checkout.tcl:27 lib/branch_create.tcl:35 -#: lib/branch_delete.tcl:32 lib/branch_rename.tcl:30 lib/browser.tcl:283 -#: lib/checkout_op.tcl:522 lib/merge.tcl:172 lib/option.tcl:172 -#: lib/remote_branch_delete.tcl:42 lib/transport.tcl:92 +#: lib/branch_delete.tcl:32 lib/branch_rename.tcl:30 lib/browser.tcl:281 +#: lib/checkout_op.tcl:522 lib/choose_font.tcl:43 lib/merge.tcl:172 +#: lib/option.tcl:90 lib/remote_branch_delete.tcl:42 lib/transport.tcl:97 msgid "Cancel" msgstr "" -#: lib/branch_checkout.tcl:32 lib/browser.tcl:288 +#: lib/branch_checkout.tcl:32 lib/browser.tcl:286 msgid "Revision" msgstr "" -#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:159 -#: lib/option.tcl:274 +#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:202 msgid "Options" msgstr "" @@ -460,7 +555,7 @@ msgstr "" msgid "Create New Branch" msgstr "" -#: lib/branch_create.tcl:31 +#: lib/branch_create.tcl:31 lib/choose_repository.tcl:199 msgid "Create" msgstr "" @@ -595,20 +690,22 @@ msgstr "" msgid "File Browser" msgstr "" -#: lib/browser.tcl:127 lib/browser.tcl:144 +#: lib/browser.tcl:125 lib/browser.tcl:142 #, tcl-format msgid "Loading %s..." msgstr "" -#: lib/browser.tcl:188 +#: lib/browser.tcl:186 msgid "[Up To Parent]" msgstr "" -#: lib/browser.tcl:268 lib/browser.tcl:274 +#: lib/browser.tcl:266 lib/browser.tcl:272 msgid "Browse Branch Files" msgstr "" -#: lib/browser.tcl:279 +#: lib/browser.tcl:277 lib/choose_repository.tcl:215 +#: lib/choose_repository.tcl:305 lib/choose_repository.tcl:315 +#: lib/choose_repository.tcl:811 msgid "Browse" msgstr "" @@ -617,7 +714,12 @@ msgstr "" msgid "Fetching %s from %s" msgstr "" -#: lib/checkout_op.tcl:140 lib/console.tcl:81 lib/database.tcl:31 +#: lib/checkout_op.tcl:127 +#, tcl-format +msgid "fatal: Cannot resolve %s" +msgstr "" + +#: lib/checkout_op.tcl:140 lib/console.tcl:79 lib/database.tcl:31 msgid "Close" msgstr "" @@ -659,6 +761,11 @@ msgid "" "The rescan will be automatically started now.\n" msgstr "" +#: lib/checkout_op.tcl:322 +#, tcl-format +msgid "Updating working directory to '%s'..." +msgstr "" + #: lib/checkout_op.tcl:353 #, tcl-format msgid "Aborted checkout of '%s' (file level merging is required)." @@ -681,6 +788,11 @@ msgid "" "Checkout'." msgstr "" +#: lib/checkout_op.tcl:446 +#, tcl-format +msgid "Checked out '%s'." +msgstr "" + #: lib/checkout_op.tcl:478 #, tcl-format msgid "Resetting '%s' to '%s' will lose the following commits:" @@ -710,6 +822,235 @@ msgid "" "This should not have occurred. %s will now close and give up." msgstr "" +#: lib/choose_font.tcl:39 +msgid "Select" +msgstr "" + +#: lib/choose_font.tcl:53 +msgid "Font Family" +msgstr "" + +#: lib/choose_font.tcl:73 +msgid "Font Size" +msgstr "" + +#: lib/choose_font.tcl:90 +msgid "Font Example" +msgstr "" + +#: lib/choose_font.tcl:101 +msgid "" +"This is example text.\n" +"If you like this text, it can be your font." +msgstr "" + +#: lib/choose_repository.tcl:25 +msgid "Git Gui" +msgstr "" + +#: lib/choose_repository.tcl:69 lib/choose_repository.tcl:204 +msgid "Create New Repository" +msgstr "" + +#: lib/choose_repository.tcl:74 lib/choose_repository.tcl:291 +msgid "Clone Existing Repository" +msgstr "" + +#: lib/choose_repository.tcl:79 lib/choose_repository.tcl:800 +msgid "Open Existing Repository" +msgstr "" + +#: lib/choose_repository.tcl:91 +msgid "Next >" +msgstr "" + +#: lib/choose_repository.tcl:152 +#, tcl-format +msgid "Location %s already exists." +msgstr "" + +#: lib/choose_repository.tcl:158 lib/choose_repository.tcl:165 +#: lib/choose_repository.tcl:172 +#, tcl-format +msgid "Failed to create repository %s:" +msgstr "" + +#: lib/choose_repository.tcl:209 lib/choose_repository.tcl:309 +msgid "Directory:" +msgstr "" + +#: lib/choose_repository.tcl:238 lib/choose_repository.tcl:363 +#: lib/choose_repository.tcl:834 +msgid "Git Repository" +msgstr "" + +#: lib/choose_repository.tcl:253 lib/choose_repository.tcl:260 +#, tcl-format +msgid "Directory %s already exists." +msgstr "" + +#: lib/choose_repository.tcl:265 +#, tcl-format +msgid "File %s already exists." +msgstr "" + +#: lib/choose_repository.tcl:286 +msgid "Clone" +msgstr "" + +#: lib/choose_repository.tcl:299 +msgid "URL:" +msgstr "" + +#: lib/choose_repository.tcl:319 +msgid "Clone Type:" +msgstr "" + +#: lib/choose_repository.tcl:325 +msgid "Standard (Fast, Semi-Redundant, Hardlinks)" +msgstr "" + +#: lib/choose_repository.tcl:331 +msgid "Full Copy (Slower, Redundant Backup)" +msgstr "" + +#: lib/choose_repository.tcl:337 +msgid "Shared (Fastest, Not Recommended, No Backup)" +msgstr "" + +#: lib/choose_repository.tcl:369 lib/choose_repository.tcl:418 +#: lib/choose_repository.tcl:560 lib/choose_repository.tcl:630 +#: lib/choose_repository.tcl:840 lib/choose_repository.tcl:848 +#, tcl-format +msgid "Not a Git repository: %s" +msgstr "" + +#: lib/choose_repository.tcl:405 +msgid "Standard only available for local repository." +msgstr "" + +#: lib/choose_repository.tcl:409 +msgid "Shared only available for local repository." +msgstr "" + +#: lib/choose_repository.tcl:439 +msgid "Failed to configure origin" +msgstr "" + +#: lib/choose_repository.tcl:451 +msgid "Counting objects" +msgstr "" + +#: lib/choose_repository.tcl:452 +msgid "buckets" +msgstr "" + +#: lib/choose_repository.tcl:476 +#, tcl-format +msgid "Unable to copy objects/info/alternates: %s" +msgstr "" + +#: lib/choose_repository.tcl:512 +#, tcl-format +msgid "Nothing to clone from %s." +msgstr "" + +#: lib/choose_repository.tcl:514 lib/choose_repository.tcl:728 +#: lib/choose_repository.tcl:740 +msgid "The 'master' branch has not been initialized." +msgstr "" + +#: lib/choose_repository.tcl:527 +msgid "Hardlinks are unavailable. Falling back to copying." +msgstr "" + +#: lib/choose_repository.tcl:539 +#, tcl-format +msgid "Cloning from %s" +msgstr "" + +#: lib/choose_repository.tcl:570 +msgid "Copying objects" +msgstr "" + +#: lib/choose_repository.tcl:571 +msgid "KiB" +msgstr "" + +#: lib/choose_repository.tcl:595 +#, tcl-format +msgid "Unable to copy object: %s" +msgstr "" + +#: lib/choose_repository.tcl:605 +msgid "Linking objects" +msgstr "" + +#: lib/choose_repository.tcl:606 +msgid "objects" +msgstr "" + +#: lib/choose_repository.tcl:614 +#, tcl-format +msgid "Unable to hardlink object: %s" +msgstr "" + +#: lib/choose_repository.tcl:669 +msgid "Cannot fetch branches and objects. See console output for details." +msgstr "" + +#: lib/choose_repository.tcl:680 +msgid "Cannot fetch tags. See console output for details." +msgstr "" + +#: lib/choose_repository.tcl:704 +msgid "Cannot determine HEAD. See console output for details." +msgstr "" + +#: lib/choose_repository.tcl:713 +#, tcl-format +msgid "Unable to cleanup %s" +msgstr "" + +#: lib/choose_repository.tcl:719 +msgid "Clone failed." +msgstr "" + +#: lib/choose_repository.tcl:726 +msgid "No default branch obtained." +msgstr "" + +#: lib/choose_repository.tcl:737 +#, tcl-format +msgid "Cannot resolve %s as a commit." +msgstr "" + +#: lib/choose_repository.tcl:749 +msgid "Creating working directory" +msgstr "" + +#: lib/choose_repository.tcl:750 lib/index.tcl:15 lib/index.tcl:80 +#: lib/index.tcl:149 +msgid "files" +msgstr "" + +#: lib/choose_repository.tcl:779 +msgid "Initial file checkout failed." +msgstr "" + +#: lib/choose_repository.tcl:795 +msgid "Open" +msgstr "" + +#: lib/choose_repository.tcl:805 +msgid "Repository:" +msgstr "" + +#: lib/choose_repository.tcl:854 +#, tcl-format +msgid "Failed to open repository %s:" +msgstr "" + #: lib/choose_rev.tcl:53 msgid "This Detached Checkout" msgstr "" @@ -726,7 +1067,7 @@ msgstr "" msgid "Tracking Branch" msgstr "" -#: lib/choose_rev.tcl:84 +#: lib/choose_rev.tcl:84 lib/choose_rev.tcl:537 msgid "Tag" msgstr "" @@ -743,6 +1084,14 @@ msgstr "" msgid "Revision expression is empty." msgstr "" +#: lib/choose_rev.tcl:530 +msgid "Updated" +msgstr "" + +#: lib/choose_rev.tcl:558 +msgid "URL" +msgstr "" + #: lib/commit.tcl:9 msgid "" "There is nothing to amend.\n" @@ -821,6 +1170,11 @@ msgstr "" msgid "write-tree failed:" msgstr "" +#: lib/commit.tcl:275 +#, tcl-format +msgid "Commit %s appears to be corrupt" +msgstr "" + #: lib/commit.tcl:279 msgid "" "No changes to commit.\n" @@ -834,6 +1188,11 @@ msgstr "" msgid "No changes to commit." msgstr "" +#: lib/commit.tcl:303 +#, tcl-format +msgid "warning: Tcl does not support encoding '%s'." +msgstr "" + #: lib/commit.tcl:317 msgid "commit-tree failed:" msgstr "" @@ -847,15 +1206,15 @@ msgstr "" msgid "Created commit %s: %s" msgstr "" -#: lib/console.tcl:55 +#: lib/console.tcl:57 msgid "Working... please wait..." msgstr "" -#: lib/console.tcl:184 +#: lib/console.tcl:183 msgid "Success" msgstr "" -#: lib/console.tcl:194 +#: lib/console.tcl:196 msgid "Error: Command Failed" msgstr "" @@ -895,6 +1254,22 @@ msgstr "" msgid "Verifying the object database with fsck-objects" msgstr "" +#: lib/database.tcl:108 +#, tcl-format +msgid "" +"This repository currently has approximately %i loose objects.\n" +"\n" +"To maintain optimal performance it is strongly recommended that you compress " +"the database when more than %i loose objects exist.\n" +"\n" +"Compress the database now?" +msgstr "" + +#: lib/date.tcl:25 +#, tcl-format +msgid "Invalid date from Git: %s" +msgstr "" + #: lib/diff.tcl:42 #, tcl-format msgid "" @@ -909,19 +1284,37 @@ msgid "" "the same state." msgstr "" -#: lib/diff.tcl:97 +#: lib/diff.tcl:81 +#, tcl-format +msgid "Loading diff of %s..." +msgstr "" + +#: lib/diff.tcl:114 lib/diff.tcl:184 +#, tcl-format +msgid "Unable to display %s" +msgstr "" + +#: lib/diff.tcl:115 msgid "Error loading file:" msgstr "" -#: lib/diff.tcl:162 +#: lib/diff.tcl:122 +msgid "Git Repository (subproject)" +msgstr "" + +#: lib/diff.tcl:134 +msgid "* Binary file (not showing content)." +msgstr "" + +#: lib/diff.tcl:185 msgid "Error loading diff:" msgstr "" -#: lib/diff.tcl:278 +#: lib/diff.tcl:302 msgid "Failed to unstage selected hunk." msgstr "" -#: lib/diff.tcl:285 +#: lib/diff.tcl:309 msgid "Failed to stage selected hunk." msgstr "" @@ -937,21 +1330,31 @@ msgstr "" msgid "You must correct the above errors before committing." msgstr "" -#: lib/index.tcl:364 +#: lib/index.tcl:241 +#, tcl-format +msgid "Unstaging %s from commit" +msgstr "" + +#: lib/index.tcl:285 +#, tcl-format +msgid "Adding %s" +msgstr "" + +#: lib/index.tcl:340 #, tcl-format msgid "Revert changes in file %s?" msgstr "" -#: lib/index.tcl:366 +#: lib/index.tcl:342 #, tcl-format msgid "Revert changes in these %i files?" msgstr "" -#: lib/index.tcl:372 +#: lib/index.tcl:348 msgid "Any unstaged changes will be permanently lost by the revert." msgstr "" -#: lib/index.tcl:375 +#: lib/index.tcl:351 msgid "Do Nothing" msgstr "" @@ -1058,71 +1461,96 @@ msgstr "" msgid "Abort completed. Ready." msgstr "" -#: lib/option.tcl:77 -msgid "git-gui - a graphical user interface for Git." -msgstr "" - -#: lib/option.tcl:164 +#: lib/option.tcl:82 msgid "Restore Defaults" msgstr "" -#: lib/option.tcl:168 +#: lib/option.tcl:86 msgid "Save" msgstr "" -#: lib/option.tcl:178 +#: lib/option.tcl:96 #, tcl-format msgid "%s Repository" msgstr "" -#: lib/option.tcl:179 +#: lib/option.tcl:97 msgid "Global (All Repositories)" msgstr "" -#: lib/option.tcl:185 +#: lib/option.tcl:103 msgid "User Name" msgstr "" -#: lib/option.tcl:186 +#: lib/option.tcl:104 msgid "Email Address" msgstr "" -#: lib/option.tcl:188 +#: lib/option.tcl:106 msgid "Summarize Merge Commits" msgstr "" -#: lib/option.tcl:189 +#: lib/option.tcl:107 msgid "Merge Verbosity" msgstr "" -#: lib/option.tcl:190 +#: lib/option.tcl:108 msgid "Show Diffstat After Merge" msgstr "" -#: lib/option.tcl:192 +#: lib/option.tcl:110 msgid "Trust File Modification Timestamps" msgstr "" -#: lib/option.tcl:193 +#: lib/option.tcl:111 msgid "Prune Tracking Branches During Fetch" msgstr "" -#: lib/option.tcl:194 +#: lib/option.tcl:112 msgid "Match Tracking Branches" msgstr "" -#: lib/option.tcl:195 +#: lib/option.tcl:113 msgid "Number of Diff Context Lines" msgstr "" -#: lib/option.tcl:196 +#: lib/option.tcl:114 msgid "New Branch Name Template" msgstr "" -#: lib/option.tcl:305 +#: lib/option.tcl:176 +msgid "Change Font" +msgstr "" + +#: lib/option.tcl:180 +#, tcl-format +msgid "Choose %s" +msgstr "" + +#: lib/option.tcl:186 +msgid "pt." +msgstr "" + +#: lib/option.tcl:200 +msgid "Preferences" +msgstr "" + +#: lib/option.tcl:235 msgid "Failed to completely save options:" msgstr "" +#: lib/remote.tcl:165 +msgid "Prune from" +msgstr "" + +#: lib/remote.tcl:170 +msgid "Fetch from" +msgstr "" + +#: lib/remote.tcl:213 +msgid "Push to" +msgstr "" + #: lib/remote_branch_delete.tcl:29 lib/remote_branch_delete.tcl:34 msgid "Delete Remote Branch" msgstr "" @@ -1131,11 +1559,11 @@ msgstr "" msgid "From Repository" msgstr "" -#: lib/remote_branch_delete.tcl:50 lib/transport.tcl:118 +#: lib/remote_branch_delete.tcl:50 lib/transport.tcl:123 msgid "Remote:" msgstr "" -#: lib/remote_branch_delete.tcl:66 lib/transport.tcl:133 +#: lib/remote_branch_delete.tcl:66 lib/transport.tcl:138 msgid "Arbitrary URL:" msgstr "" @@ -1159,6 +1587,14 @@ msgstr "" msgid "A branch is required for 'Merged Into'." msgstr "" +#: lib/remote_branch_delete.tcl:184 +#, tcl-format +msgid "" +"The following branches are not completely merged into %s:\n" +"\n" +" - %s" +msgstr "" + #: lib/remote_branch_delete.tcl:189 #, tcl-format msgid "" @@ -1191,21 +1627,6 @@ msgstr "" msgid "Scanning %s..." msgstr "" -#: lib/remote.tcl:162 -#, tcl-format -msgid "Fetch from %s..." -msgstr "" - -#: lib/remote.tcl:172 -#, tcl-format -msgid "Prune from %s..." -msgstr "" - -#: lib/remote.tcl:206 -#, tcl-format -msgid "Push to %s..." -msgstr "" - #: lib/shortcut.tcl:26 lib/shortcut.tcl:74 msgid "Cannot write script:" msgstr "" @@ -1214,51 +1635,70 @@ msgstr "" msgid "Cannot write icon:" msgstr "" -#: lib/status_bar.tcl:58 +#: lib/status_bar.tcl:83 #, tcl-format msgid "%s ... %*i of %*i %s (%3i%%)" msgstr "" +#: lib/transport.tcl:6 +#, tcl-format +msgid "fetch %s" +msgstr "" + #: lib/transport.tcl:7 #, tcl-format msgid "Fetching new changes from %s" msgstr "" +#: lib/transport.tcl:18 +#, tcl-format +msgid "remote prune %s" +msgstr "" + #: lib/transport.tcl:19 #, tcl-format msgid "Pruning tracking branches deleted from %s" msgstr "" +#: lib/transport.tcl:25 lib/transport.tcl:71 +#, tcl-format +msgid "push %s" +msgstr "" + #: lib/transport.tcl:26 #, tcl-format msgid "Pushing changes to %s" msgstr "" -#: lib/transport.tcl:68 +#: lib/transport.tcl:72 #, tcl-format msgid "Pushing %s %s to %s" msgstr "" -#: lib/transport.tcl:84 +#: lib/transport.tcl:89 msgid "Push Branches" msgstr "" -#: lib/transport.tcl:98 +#: lib/transport.tcl:103 msgid "Source Branches" msgstr "" -#: lib/transport.tcl:115 +#: lib/transport.tcl:120 msgid "Destination Repository" msgstr "" -#: lib/transport.tcl:153 +#: lib/transport.tcl:158 msgid "Transfer Options" msgstr "" -#: lib/transport.tcl:155 +#: lib/transport.tcl:160 +msgid "Force overwrite existing branch (may discard changes)" +msgstr "" + +#: lib/transport.tcl:164 msgid "Use thin pack (for slow network connections)" msgstr "" -#: lib/transport.tcl:159 +#: lib/transport.tcl:168 msgid "Include tags" msgstr "" diff --git a/po/hu.po b/po/hu.po index 1e189b6086..e8c04f7aea 100644 --- a/po/hu.po +++ b/po/hu.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: git-gui-i 18n\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2007-08-11 17:28+0200\n" +"POT-Creation-Date: 2007-10-10 04:04-0400\n" "PO-Revision-Date: 2007-07-27 13:15+0200\n" "Last-Translator: Miklos Vajna \n" "Language-Team: Hungarian\n" @@ -16,15 +16,33 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: git-gui.sh:531 +#: git-gui.sh:41 git-gui.sh:634 git-gui.sh:648 git-gui.sh:661 git-gui.sh:744 +#: git-gui.sh:763 +msgid "git-gui: fatal error" +msgstr "" + +#: git-gui.sh:595 +#, fuzzy, tcl-format +msgid "Invalid font specified in %s:" +msgstr "Érvénytelen font lett megadva a grafikus felületben.%s:" + +#: git-gui.sh:620 +msgid "Main Font" +msgstr "Fő betűtípus" + +#: git-gui.sh:621 +msgid "Diff/Console Font" +msgstr "Diff/konzol betűtípus" + +#: git-gui.sh:635 msgid "Cannot find git in PATH." msgstr "A git nem található a PATH-ban." -#: git-gui.sh:550 +#: git-gui.sh:662 msgid "Cannot parse Git version string:" msgstr "Nem értelmezhető a Git verzió sztring:" -#: git-gui.sh:567 +#: git-gui.sh:680 #, tcl-format msgid "" "Git version cannot be determined.\n" @@ -43,79 +61,80 @@ msgstr "" "\n" "Feltételezhetjük, hogy a(z) '%s' verziója legalább 1.5.0?\n" -#: git-gui.sh:689 -msgid "Cannot find the git directory:" -msgstr "Nem található a git könyvtár:" - -#: git-gui.sh:697 +#: git-gui.sh:853 msgid "Git directory not found:" msgstr "A Git könyvtár nem található:" -#: git-gui.sh:703 +#: git-gui.sh:860 +#, fuzzy +msgid "Cannot move to top of working directory:" +msgstr "Nem használható vicces .git könyvtár:" + +#: git-gui.sh:867 msgid "Cannot use funny .git directory:" msgstr "Nem használható vicces .git könyvtár:" -#: git-gui.sh:708 +#: git-gui.sh:872 msgid "No working directory" msgstr "Nincs munkakönyvtár" -#: git-gui.sh:854 +#: git-gui.sh:1019 msgid "Refreshing file status..." msgstr "A fájlok státuszának frissítése..." -#: git-gui.sh:891 +#: git-gui.sh:1084 msgid "Scanning for modified files ..." msgstr "Módosított fájlok keresése ..." -#: git-gui.sh:1057 lib/browser.tcl:247 +#: git-gui.sh:1259 lib/browser.tcl:245 msgid "Ready." msgstr "Kész." -#: git-gui.sh:1322 +#: git-gui.sh:1525 msgid "Unmodified" msgstr "Nem módosított" -#: git-gui.sh:1324 +#: git-gui.sh:1527 msgid "Modified, not staged" msgstr "Módosított, de nem kiválasztott" -#: git-gui.sh:1325 git-gui.sh:1330 +#: git-gui.sh:1528 git-gui.sh:1533 msgid "Staged for commit" msgstr "Kiválasztva commitolásra" -#: git-gui.sh:1326 git-gui.sh:1331 +#: git-gui.sh:1529 git-gui.sh:1534 msgid "Portions staged for commit" msgstr "Részek kiválasztva commitolásra" -#: git-gui.sh:1327 git-gui.sh:1332 +#: git-gui.sh:1530 git-gui.sh:1535 msgid "Staged for commit, missing" msgstr "Kiválasztva commitolásra, hiányzó" -#: git-gui.sh:1329 +#: git-gui.sh:1532 msgid "Untracked, not staged" msgstr "Nem követett, nem kiválasztott" -#: git-gui.sh:1334 +#: git-gui.sh:1537 msgid "Missing" msgstr "Hiányzó" -#: git-gui.sh:1335 +#: git-gui.sh:1538 msgid "Staged for removal" msgstr "Kiválasztva eltávolításra" -#: git-gui.sh:1336 +#: git-gui.sh:1539 msgid "Staged for removal, still present" msgstr "Kiválasztva eltávolításra, jelenleg is elérhető" -#: git-gui.sh:1338 git-gui.sh:1339 git-gui.sh:1340 git-gui.sh:1341 +#: git-gui.sh:1541 git-gui.sh:1542 git-gui.sh:1543 git-gui.sh:1544 msgid "Requires merge resolution" msgstr "Merge feloldás szükséges" -#: git-gui.sh:1383 +#: git-gui.sh:1579 msgid "Starting gitk... please wait..." msgstr "A gitk indítása... várjunk..." -#: git-gui.sh:1392 +#: git-gui.sh:1588 #, tcl-format msgid "" "Unable to start gitk:\n" @@ -126,293 +145,332 @@ msgstr "" "\n" "A(z) %s nem létezik" -#: git-gui.sh:1609 -#, tcl-format -msgid "Invalid font specified in gui.%s:" -msgstr "Érvénytelen font lett megadva a grafikus felületben.%s:" - -#: git-gui.sh:1634 -msgid "Main Font" -msgstr "Fő betűtípus" - -#: git-gui.sh:1635 -msgid "Diff/Console Font" -msgstr "Diff/konzol betűtípus" - -#: git-gui.sh:1649 +#: git-gui.sh:1788 lib/choose_repository.tcl:32 msgid "Repository" msgstr "Repó" -#: git-gui.sh:1650 +#: git-gui.sh:1789 msgid "Edit" msgstr "Szerkesztés" -#: git-gui.sh:1652 +#: git-gui.sh:1791 lib/choose_rev.tcl:560 msgid "Branch" msgstr "Branch" -#: git-gui.sh:1655 git-gui.sh:1842 git-gui.sh:2152 -msgid "Commit" +#: git-gui.sh:1794 lib/choose_rev.tcl:547 +#, fuzzy +msgid "Commit@@noun" msgstr "Commit" -#: git-gui.sh:1658 lib/merge.tcl:121 lib/merge.tcl:150 lib/merge.tcl:168 +#: git-gui.sh:1797 lib/merge.tcl:121 lib/merge.tcl:150 lib/merge.tcl:168 msgid "Merge" msgstr "Merge" -#: git-gui.sh:1659 -msgid "Fetch" -msgstr "Letöltés" +#: git-gui.sh:1798 lib/choose_rev.tcl:556 +#, fuzzy +msgid "Remote" +msgstr "Távoli:" -#: git-gui.sh:1660 git-gui.sh:2158 lib/transport.tcl:88 lib/transport.tcl:172 -msgid "Push" -msgstr "Push" - -#: git-gui.sh:1669 +#: git-gui.sh:1807 msgid "Browse Current Branch's Files" msgstr "A jelenlegi branch fájljainak böngészése" -#: git-gui.sh:1673 +#: git-gui.sh:1811 msgid "Browse Branch Files..." msgstr "A branch fájljainak böngészése..." -#: git-gui.sh:1678 +#: git-gui.sh:1816 msgid "Visualize Current Branch's History" msgstr "A jelenlegi branch történetének vizualizálása" -#: git-gui.sh:1682 +#: git-gui.sh:1820 msgid "Visualize All Branch History" msgstr "Az összes branch történetének vizualizálása" -#: git-gui.sh:1689 +#: git-gui.sh:1827 #, tcl-format msgid "Browse %s's Files" msgstr "A(z) %s branch fájljainak böngészése" -#: git-gui.sh:1691 +#: git-gui.sh:1829 #, tcl-format msgid "Visualize %s's History" msgstr "A(z) %s branch történetének vizualizálása" -#: git-gui.sh:1696 lib/database.tcl:27 lib/database.tcl:67 +#: git-gui.sh:1834 lib/database.tcl:27 lib/database.tcl:67 msgid "Database Statistics" msgstr "Adatbázis statisztikák" -#: git-gui.sh:1699 lib/database.tcl:34 +#: git-gui.sh:1837 lib/database.tcl:34 msgid "Compress Database" msgstr "Adatbázis tömörítése" -#: git-gui.sh:1702 +#: git-gui.sh:1840 msgid "Verify Database" msgstr "Adatbázis ellenőrzése" -#: git-gui.sh:1709 git-gui.sh:1713 git-gui.sh:1717 lib/shortcut.tcl:9 +#: git-gui.sh:1847 git-gui.sh:1851 git-gui.sh:1855 lib/shortcut.tcl:9 #: lib/shortcut.tcl:45 lib/shortcut.tcl:84 msgid "Create Desktop Icon" msgstr "Asztal ikon létrehozása" -#: git-gui.sh:1722 +#: git-gui.sh:1860 lib/choose_repository.tcl:36 lib/choose_repository.tcl:95 msgid "Quit" msgstr "Kilépés" -#: git-gui.sh:1729 +#: git-gui.sh:1867 msgid "Undo" msgstr "Visszavonás" -#: git-gui.sh:1732 +#: git-gui.sh:1870 msgid "Redo" msgstr "Mégis" -#: git-gui.sh:1736 git-gui.sh:2222 +#: git-gui.sh:1874 git-gui.sh:2366 msgid "Cut" msgstr "Kivágás" -#: git-gui.sh:1739 git-gui.sh:2225 git-gui.sh:2296 git-gui.sh:2368 -#: lib/console.tcl:69 +#: git-gui.sh:1877 git-gui.sh:2369 git-gui.sh:2440 git-gui.sh:2512 +#: lib/console.tcl:67 msgid "Copy" msgstr "Másolás" -#: git-gui.sh:1742 git-gui.sh:2228 +#: git-gui.sh:1880 git-gui.sh:2372 msgid "Paste" msgstr "Beillesztés" -#: git-gui.sh:1745 git-gui.sh:2231 lib/branch_delete.tcl:26 +#: git-gui.sh:1883 git-gui.sh:2375 lib/branch_delete.tcl:26 #: lib/remote_branch_delete.tcl:38 msgid "Delete" msgstr "Törlés" -#: git-gui.sh:1749 git-gui.sh:2235 git-gui.sh:2372 lib/console.tcl:71 +#: git-gui.sh:1887 git-gui.sh:2379 git-gui.sh:2516 lib/console.tcl:69 msgid "Select All" msgstr "Mindent kiválaszt" -#: git-gui.sh:1758 +#: git-gui.sh:1896 msgid "Create..." msgstr "Létrehozás..." -#: git-gui.sh:1764 +#: git-gui.sh:1902 msgid "Checkout..." msgstr "Checkout..." -#: git-gui.sh:1770 +#: git-gui.sh:1908 msgid "Rename..." msgstr "Átnevezés..." -#: git-gui.sh:1775 git-gui.sh:1873 +#: git-gui.sh:1913 git-gui.sh:2012 msgid "Delete..." msgstr "Törlés..." -#: git-gui.sh:1780 +#: git-gui.sh:1918 msgid "Reset..." msgstr "Visszaállítás..." -#: git-gui.sh:1792 git-gui.sh:2169 +#: git-gui.sh:1930 git-gui.sh:2313 msgid "New Commit" msgstr "Új commit" -#: git-gui.sh:1800 git-gui.sh:2176 +#: git-gui.sh:1938 git-gui.sh:2320 msgid "Amend Last Commit" msgstr "Utolsó commit javítása" -#: git-gui.sh:1809 git-gui.sh:2136 lib/remote_branch_delete.tcl:99 +#: git-gui.sh:1947 git-gui.sh:2280 lib/remote_branch_delete.tcl:99 msgid "Rescan" msgstr "Keresés újra" -#: git-gui.sh:1815 +#: git-gui.sh:1953 msgid "Stage To Commit" msgstr "Kiválasztás commitolásra" -#: git-gui.sh:1820 +#: git-gui.sh:1958 msgid "Stage Changed Files To Commit" msgstr "Módosított fájlok kiválasztása commitolásra" -#: git-gui.sh:1826 +#: git-gui.sh:1964 msgid "Unstage From Commit" msgstr "Commitba való kiválasztás visszavonása" -#: git-gui.sh:1831 lib/index.tcl:376 +#: git-gui.sh:1969 lib/index.tcl:352 msgid "Revert Changes" msgstr "Változtatások visszaállítása" -#: git-gui.sh:1838 git-gui.sh:2148 git-gui.sh:2246 +#: git-gui.sh:1976 git-gui.sh:2292 git-gui.sh:2390 msgid "Sign Off" msgstr "Aláír" -#: git-gui.sh:1853 +#: git-gui.sh:1980 git-gui.sh:2296 +#, fuzzy +msgid "Commit@@verb" +msgstr "Commit" + +#: git-gui.sh:1991 msgid "Local Merge..." msgstr "Helyi merge..." -#: git-gui.sh:1858 +#: git-gui.sh:1996 msgid "Abort Merge..." msgstr "Merge megszakítása..." -#: git-gui.sh:1870 +#: git-gui.sh:2008 msgid "Push..." msgstr "Push..." -#: git-gui.sh:1880 +#: git-gui.sh:2019 lib/choose_repository.tcl:41 msgid "Apple" msgstr "Apple" -#: git-gui.sh:1883 git-gui.sh:1901 lib/option.tcl:65 +#: git-gui.sh:2022 git-gui.sh:2044 lib/about.tcl:13 +#: lib/choose_repository.tcl:44 lib/choose_repository.tcl:50 #, tcl-format msgid "About %s" msgstr "Névjegy: %s" -#: git-gui.sh:1885 git-gui.sh:1891 git-gui.sh:2414 +#: git-gui.sh:2026 +msgid "Preferences..." +msgstr "" + +#: git-gui.sh:2034 git-gui.sh:2558 msgid "Options..." msgstr "Opciók..." -#: git-gui.sh:1897 +#: git-gui.sh:2040 lib/choose_repository.tcl:47 msgid "Help" msgstr "Segítség" -#: git-gui.sh:1938 +#: git-gui.sh:2081 msgid "Online Documentation" msgstr "Online dokumentáció" -#: git-gui.sh:2054 +#: git-gui.sh:2165 +#, tcl-format +msgid "fatal: cannot stat path %s: No such file or directory" +msgstr "" + +#: git-gui.sh:2198 msgid "Current Branch:" msgstr "Jelenlegi branch:" -#: git-gui.sh:2075 -msgid "Staged Changes (Will Be Committed)" +#: git-gui.sh:2219 +#, fuzzy +msgid "Staged Changes (Will Commit)" msgstr "Kiválasztott változtatások (commitolva lesz)" -#: git-gui.sh:2095 -msgid "Unstaged Changes (Will Not Be Committed)" -msgstr "Nem kiválasztott változtatások (nem lesz commitolva)" +#: git-gui.sh:2239 +#, fuzzy +msgid "Unstaged Changes" +msgstr "Változtatások kiválasztása" -#: git-gui.sh:2142 +#: git-gui.sh:2286 msgid "Stage Changed" msgstr "Változtatások kiválasztása" -#: git-gui.sh:2188 +#: git-gui.sh:2302 lib/transport.tcl:93 lib/transport.tcl:182 +msgid "Push" +msgstr "Push" + +#: git-gui.sh:2332 msgid "Initial Commit Message:" msgstr "Kezdeti commit üzenet:" -#: git-gui.sh:2189 +#: git-gui.sh:2333 msgid "Amended Commit Message:" msgstr "Javító commit üzenet:" -#: git-gui.sh:2190 +#: git-gui.sh:2334 msgid "Amended Initial Commit Message:" msgstr "Kezdeti javító commit üzenet:" -#: git-gui.sh:2191 +#: git-gui.sh:2335 msgid "Amended Merge Commit Message:" msgstr "Javító merge commit üzenet:" -#: git-gui.sh:2192 +#: git-gui.sh:2336 msgid "Merge Commit Message:" msgstr "Merge commit üzenet:" -#: git-gui.sh:2193 +#: git-gui.sh:2337 msgid "Commit Message:" msgstr "Commit üzenet:" -#: git-gui.sh:2238 git-gui.sh:2376 lib/console.tcl:73 +#: git-gui.sh:2382 git-gui.sh:2520 lib/console.tcl:71 msgid "Copy All" msgstr "Összes másolása" -#: git-gui.sh:2262 lib/blame.tcl:104 +#: git-gui.sh:2406 lib/blame.tcl:104 msgid "File:" msgstr "Fájl:" -#: git-gui.sh:2364 +#: git-gui.sh:2508 msgid "Refresh" msgstr "Frissítés" -#: git-gui.sh:2385 +#: git-gui.sh:2529 msgid "Apply/Reverse Hunk" msgstr "Hunk alkalmazása/visszaállítása" -#: git-gui.sh:2391 +#: git-gui.sh:2535 msgid "Decrease Font Size" msgstr "Font méret csökkentése" -#: git-gui.sh:2395 +#: git-gui.sh:2539 msgid "Increase Font Size" msgstr "Fönt méret növelése" -#: git-gui.sh:2400 +#: git-gui.sh:2544 msgid "Show Less Context" msgstr "Kevesebb környezet mutatása" -#: git-gui.sh:2407 +#: git-gui.sh:2551 msgid "Show More Context" msgstr "Több környezet mutatása" -#: git-gui.sh:2422 +#: git-gui.sh:2565 msgid "Unstage Hunk From Commit" msgstr "Hunk törlése commitból" -#: git-gui.sh:2426 git-gui.sh:2430 +#: git-gui.sh:2567 msgid "Stage Hunk For Commit" msgstr "Hunk kiválasztása commitba" -#: git-gui.sh:2440 +#: git-gui.sh:2586 msgid "Initializing..." msgstr "Inicializálás..." +#: git-gui.sh:2677 +#, tcl-format +msgid "" +"Possible environment issues exist.\n" +"\n" +"The following environment variables are probably\n" +"going to be ignored by any Git subprocess run\n" +"by %s:\n" +"\n" +msgstr "" + +#: git-gui.sh:2707 +msgid "" +"\n" +"This is due to a known issue with the\n" +"Tcl binary distributed by Cygwin." +msgstr "" + +#: git-gui.sh:2712 +#, tcl-format +msgid "" +"\n" +"\n" +"A good replacement for %s\n" +"is placing values for the user.name and\n" +"user.email settings into your personal\n" +"~/.gitconfig file.\n" +msgstr "" + +#: lib/about.tcl:25 +msgid "git-gui - a graphical user interface for Git." +msgstr "git-gui - egy grafikus felület a Githez." + #: lib/blame.tcl:77 msgid "File Viewer" msgstr "Fájl néző" @@ -430,6 +488,53 @@ msgstr "Commit másolása" msgid "Reading %s..." msgstr "A(z) %s olvasása..." +#: lib/blame.tcl:473 +msgid "Loading copy/move tracking annotations..." +msgstr "" + +#: lib/blame.tcl:493 +msgid "lines annotated" +msgstr "" + +#: lib/blame.tcl:674 +msgid "Loading original location annotations..." +msgstr "" + +#: lib/blame.tcl:677 +msgid "Annotation complete." +msgstr "" + +#: lib/blame.tcl:731 +#, fuzzy +msgid "Loading annotation..." +msgstr "A(z) %s betöltése..." + +#: lib/blame.tcl:787 +msgid "Author:" +msgstr "" + +#: lib/blame.tcl:791 +#, fuzzy +msgid "Committer:" +msgstr "Commit:" + +#: lib/blame.tcl:796 +msgid "Original File:" +msgstr "" + +#: lib/blame.tcl:910 +msgid "Originally By:" +msgstr "" + +#: lib/blame.tcl:916 +#, fuzzy +msgid "In File:" +msgstr "Fájl:" + +#: lib/blame.tcl:921 +msgid "Copied Or Moved Here By:" +msgstr "" + #: lib/branch_checkout.tcl:14 lib/branch_checkout.tcl:19 msgid "Checkout Branch" msgstr "Branch checkoutolása" @@ -439,18 +544,17 @@ msgid "Checkout" msgstr "Checkout" #: lib/branch_checkout.tcl:27 lib/branch_create.tcl:35 -#: lib/branch_delete.tcl:32 lib/branch_rename.tcl:30 lib/browser.tcl:283 -#: lib/checkout_op.tcl:522 lib/merge.tcl:172 lib/option.tcl:172 -#: lib/remote_branch_delete.tcl:42 lib/transport.tcl:92 +#: lib/branch_delete.tcl:32 lib/branch_rename.tcl:30 lib/browser.tcl:281 +#: lib/checkout_op.tcl:522 lib/choose_font.tcl:43 lib/merge.tcl:172 +#: lib/option.tcl:90 lib/remote_branch_delete.tcl:42 lib/transport.tcl:97 msgid "Cancel" msgstr "Mégsem" -#: lib/branch_checkout.tcl:32 lib/browser.tcl:288 +#: lib/branch_checkout.tcl:32 lib/browser.tcl:286 msgid "Revision" msgstr "Revízió" -#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:159 -#: lib/option.tcl:274 +#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:202 msgid "Options" msgstr "Opciók" @@ -470,7 +574,7 @@ msgstr "Branch létrehozása" msgid "Create New Branch" msgstr "Új branch létrehozása" -#: lib/branch_create.tcl:31 +#: lib/branch_create.tcl:31 lib/choose_repository.tcl:199 msgid "Create" msgstr "Létrehozás" @@ -610,20 +714,22 @@ msgstr "Indítás..." msgid "File Browser" msgstr "Fájl böngésző" -#: lib/browser.tcl:127 lib/browser.tcl:144 +#: lib/browser.tcl:125 lib/browser.tcl:142 #, tcl-format msgid "Loading %s..." msgstr "A(z) %s betöltése..." -#: lib/browser.tcl:188 +#: lib/browser.tcl:186 msgid "[Up To Parent]" msgstr "[Fel a szülőhöz]" -#: lib/browser.tcl:268 lib/browser.tcl:274 +#: lib/browser.tcl:266 lib/browser.tcl:272 msgid "Browse Branch Files" msgstr "A branch fájljainak böngészése" -#: lib/browser.tcl:279 +#: lib/browser.tcl:277 lib/choose_repository.tcl:215 +#: lib/choose_repository.tcl:305 lib/choose_repository.tcl:315 +#: lib/choose_repository.tcl:811 msgid "Browse" msgstr "Böngészés" @@ -632,7 +738,12 @@ msgstr "Böngészés" msgid "Fetching %s from %s" msgstr "A(z) %s letöltése innen: %s" -#: lib/checkout_op.tcl:140 lib/console.tcl:81 lib/database.tcl:31 +#: lib/checkout_op.tcl:127 +#, tcl-format +msgid "fatal: Cannot resolve %s" +msgstr "" + +#: lib/checkout_op.tcl:140 lib/console.tcl:79 lib/database.tcl:31 msgid "Close" msgstr "Bezárás" @@ -685,6 +796,11 @@ msgstr "" "\n" "Az újrakeresés most automatikusan el fog indulni.\n" +#: lib/checkout_op.tcl:322 +#, fuzzy, tcl-format +msgid "Updating working directory to '%s'..." +msgstr "Nincs munkakönyvtár" + #: lib/checkout_op.tcl:353 #, tcl-format msgid "Aborted checkout of '%s' (file level merging is required)." @@ -711,6 +827,11 @@ msgstr "" "Ha egy branchen szeretnénk lenni, hozzunk létre egyet az 'Ez a leválasztott " "checkout'-ból." +#: lib/checkout_op.tcl:446 +#, fuzzy, tcl-format +msgid "Checked out '%s'." +msgstr "Checkout..." + #: lib/checkout_op.tcl:478 #, tcl-format msgid "Resetting '%s' to '%s' will lose the following commits:" @@ -747,6 +868,246 @@ msgstr "" "\n" "Ennek nem szabad megtörténnie. A(z) %s most kilép és feladja." +#: lib/choose_font.tcl:39 +#, fuzzy +msgid "Select" +msgstr "Mindent kiválaszt" + +#: lib/choose_font.tcl:53 +msgid "Font Family" +msgstr "" + +#: lib/choose_font.tcl:73 +#, fuzzy +msgid "Font Size" +msgstr "Font méret csökkentése" + +#: lib/choose_font.tcl:90 +msgid "Font Example" +msgstr "" + +#: lib/choose_font.tcl:101 +msgid "" +"This is example text.\n" +"If you like this text, it can be your font." +msgstr "" + +#: lib/choose_repository.tcl:25 +msgid "Git Gui" +msgstr "" + +#: lib/choose_repository.tcl:69 lib/choose_repository.tcl:204 +#, fuzzy +msgid "Create New Repository" +msgstr "Forrás repó" + +#: lib/choose_repository.tcl:74 lib/choose_repository.tcl:291 +#, fuzzy +msgid "Clone Existing Repository" +msgstr "Cél repó" + +#: lib/choose_repository.tcl:79 lib/choose_repository.tcl:800 +#, fuzzy +msgid "Open Existing Repository" +msgstr "Cél repó" + +#: lib/choose_repository.tcl:91 +msgid "Next >" +msgstr "" + +#: lib/choose_repository.tcl:152 +#, fuzzy, tcl-format +msgid "Location %s already exists." +msgstr "A(z) '%s' branch már létezik." + +#: lib/choose_repository.tcl:158 lib/choose_repository.tcl:165 +#: lib/choose_repository.tcl:172 +#, fuzzy, tcl-format +msgid "Failed to create repository %s:" +msgstr "Nem sikerült teljesen elmenteni a beállításokat:" + +#: lib/choose_repository.tcl:209 lib/choose_repository.tcl:309 +msgid "Directory:" +msgstr "" + +#: lib/choose_repository.tcl:238 lib/choose_repository.tcl:363 +#: lib/choose_repository.tcl:834 +#, fuzzy +msgid "Git Repository" +msgstr "Repó" + +#: lib/choose_repository.tcl:253 lib/choose_repository.tcl:260 +#, fuzzy, tcl-format +msgid "Directory %s already exists." +msgstr "A(z) '%s' branch már létezik." + +#: lib/choose_repository.tcl:265 +#, fuzzy, tcl-format +msgid "File %s already exists." +msgstr "A(z) '%s' branch már létezik." + +#: lib/choose_repository.tcl:286 +#, fuzzy +msgid "Clone" +msgstr "Bezárás" + +#: lib/choose_repository.tcl:299 +msgid "URL:" +msgstr "" + +#: lib/choose_repository.tcl:319 +msgid "Clone Type:" +msgstr "" + +#: lib/choose_repository.tcl:325 +msgid "Standard (Fast, Semi-Redundant, Hardlinks)" +msgstr "" + +#: lib/choose_repository.tcl:331 +msgid "Full Copy (Slower, Redundant Backup)" +msgstr "" + +#: lib/choose_repository.tcl:337 +msgid "Shared (Fastest, Not Recommended, No Backup)" +msgstr "" + +#: lib/choose_repository.tcl:369 lib/choose_repository.tcl:418 +#: lib/choose_repository.tcl:560 lib/choose_repository.tcl:630 +#: lib/choose_repository.tcl:840 lib/choose_repository.tcl:848 +#, fuzzy, tcl-format +msgid "Not a Git repository: %s" +msgstr "Nincs kiválasztott repó." + +#: lib/choose_repository.tcl:405 +msgid "Standard only available for local repository." +msgstr "" + +#: lib/choose_repository.tcl:409 +msgid "Shared only available for local repository." +msgstr "" + +#: lib/choose_repository.tcl:439 +msgid "Failed to configure origin" +msgstr "" + +#: lib/choose_repository.tcl:451 +msgid "Counting objects" +msgstr "" + +#: lib/choose_repository.tcl:452 +msgid "buckets" +msgstr "" + +#: lib/choose_repository.tcl:476 +#, tcl-format +msgid "Unable to copy objects/info/alternates: %s" +msgstr "" + +#: lib/choose_repository.tcl:512 +#, fuzzy, tcl-format +msgid "Nothing to clone from %s." +msgstr "Új változások letöltése innen: %s" + +#: lib/choose_repository.tcl:514 lib/choose_repository.tcl:728 +#: lib/choose_repository.tcl:740 +msgid "The 'master' branch has not been initialized." +msgstr "" + +#: lib/choose_repository.tcl:527 +msgid "Hardlinks are unavailable. Falling back to copying." +msgstr "" + +#: lib/choose_repository.tcl:539 +#, fuzzy, tcl-format +msgid "Cloning from %s" +msgstr "A(z) %s letöltése innen: %s" + +#: lib/choose_repository.tcl:570 +#, fuzzy +msgid "Copying objects" +msgstr "Az objektum adatbázis tömörítése" + +#: lib/choose_repository.tcl:571 +msgid "KiB" +msgstr "" + +#: lib/choose_repository.tcl:595 +#, tcl-format +msgid "Unable to copy object: %s" +msgstr "" + +#: lib/choose_repository.tcl:605 +msgid "Linking objects" +msgstr "" + +#: lib/choose_repository.tcl:606 +msgid "objects" +msgstr "" + +#: lib/choose_repository.tcl:614 +#, tcl-format +msgid "Unable to hardlink object: %s" +msgstr "" + +#: lib/choose_repository.tcl:669 +msgid "Cannot fetch branches and objects. See console output for details." +msgstr "" + +#: lib/choose_repository.tcl:680 +msgid "Cannot fetch tags. See console output for details." +msgstr "" + +#: lib/choose_repository.tcl:704 +msgid "Cannot determine HEAD. See console output for details." +msgstr "" + +#: lib/choose_repository.tcl:713 +#, tcl-format +msgid "Unable to cleanup %s" +msgstr "" + +#: lib/choose_repository.tcl:719 +#, fuzzy +msgid "Clone failed." +msgstr "A félbeszakítás nem sikerült." + +#: lib/choose_repository.tcl:726 +msgid "No default branch obtained." +msgstr "" + +#: lib/choose_repository.tcl:737 +#, tcl-format +msgid "Cannot resolve %s as a commit." +msgstr "" + +#: lib/choose_repository.tcl:749 +#, fuzzy +msgid "Creating working directory" +msgstr "Nincs munkakönyvtár" + +#: lib/choose_repository.tcl:750 lib/index.tcl:15 lib/index.tcl:80 +#: lib/index.tcl:149 +msgid "files" +msgstr "" + +#: lib/choose_repository.tcl:779 +msgid "Initial file checkout failed." +msgstr "" + +#: lib/choose_repository.tcl:795 +msgid "Open" +msgstr "" + +#: lib/choose_repository.tcl:805 +#, fuzzy +msgid "Repository:" +msgstr "Repó" + +#: lib/choose_repository.tcl:854 +#, fuzzy, tcl-format +msgid "Failed to open repository %s:" +msgstr "Nem sikerült teljesen elmenteni a beállításokat:" + #: lib/choose_rev.tcl:53 msgid "This Detached Checkout" msgstr "Ez a leválasztott checkout" @@ -763,7 +1124,7 @@ msgstr "Helyi branch" msgid "Tracking Branch" msgstr "Követő branch" -#: lib/choose_rev.tcl:84 +#: lib/choose_rev.tcl:84 lib/choose_rev.tcl:537 msgid "Tag" msgstr "Tag" @@ -780,6 +1141,14 @@ msgstr "Nincs kiválasztva revízió." msgid "Revision expression is empty." msgstr "A revízió kifejezés üres." +#: lib/choose_rev.tcl:530 +msgid "Updated" +msgstr "" + +#: lib/choose_rev.tcl:558 +msgid "URL" +msgstr "" + #: lib/commit.tcl:9 msgid "" "There is nothing to amend.\n" @@ -890,6 +1259,11 @@ msgstr "" msgid "write-tree failed:" msgstr "a write-tree sikertelen:" +#: lib/commit.tcl:275 +#, tcl-format +msgid "Commit %s appears to be corrupt" +msgstr "" + #: lib/commit.tcl:279 msgid "" "No changes to commit.\n" @@ -908,6 +1282,11 @@ msgstr "" msgid "No changes to commit." msgstr "Nincs commitolandó változtatás." +#: lib/commit.tcl:303 +#, tcl-format +msgid "warning: Tcl does not support encoding '%s'." +msgstr "" + #: lib/commit.tcl:317 msgid "commit-tree failed:" msgstr "a commit-tree sikertelen:" @@ -921,15 +1300,15 @@ msgstr "az update-ref sikertelen:" msgid "Created commit %s: %s" msgstr "Létrejött a %s commit: %s" -#: lib/console.tcl:55 +#: lib/console.tcl:57 msgid "Working... please wait..." msgstr "Munka folyamatban.. Várjunk..." -#: lib/console.tcl:184 +#: lib/console.tcl:183 msgid "Success" msgstr "Siker" -#: lib/console.tcl:194 +#: lib/console.tcl:196 msgid "Error: Command Failed" msgstr "Hiba: a parancs sikertelen" @@ -969,6 +1348,22 @@ msgstr "Az objektum adatbázis tömörítése" msgid "Verifying the object database with fsck-objects" msgstr "Az objektum adatbázis ellenőrzése az fsck-objects használatával" +#: lib/database.tcl:108 +#, tcl-format +msgid "" +"This repository currently has approximately %i loose objects.\n" +"\n" +"To maintain optimal performance it is strongly recommended that you compress " +"the database when more than %i loose objects exist.\n" +"\n" +"Compress the database now?" +msgstr "" + +#: lib/date.tcl:25 +#, fuzzy, tcl-format +msgid "Invalid date from Git: %s" +msgstr "Érvénytelen revízió: %s" + #: lib/diff.tcl:42 #, tcl-format msgid "" @@ -991,19 +1386,37 @@ msgstr "" "\n" "Egy újrakeresés fog indulni a hasonló állapotú fájlok megtalálása érdekében." -#: lib/diff.tcl:97 +#: lib/diff.tcl:81 +#, fuzzy, tcl-format +msgid "Loading diff of %s..." +msgstr "A(z) %s betöltése..." + +#: lib/diff.tcl:114 lib/diff.tcl:184 +#, tcl-format +msgid "Unable to display %s" +msgstr "" + +#: lib/diff.tcl:115 msgid "Error loading file:" msgstr "Hiba a fájl betöltése közben:" -#: lib/diff.tcl:162 +#: lib/diff.tcl:122 +msgid "Git Repository (subproject)" +msgstr "" + +#: lib/diff.tcl:134 +msgid "* Binary file (not showing content)." +msgstr "" + +#: lib/diff.tcl:185 msgid "Error loading diff:" msgstr "Hiba a diff betöltése közben:" -#: lib/diff.tcl:278 +#: lib/diff.tcl:302 msgid "Failed to unstage selected hunk." msgstr "Nem visszavonni a hunk kiválasztását." -#: lib/diff.tcl:285 +#: lib/diff.tcl:309 msgid "Failed to stage selected hunk." msgstr "Nem sikerült kiválasztani a hunkot." @@ -1019,23 +1432,33 @@ msgstr "figyelmeztetés" msgid "You must correct the above errors before committing." msgstr "Ki kell javítanunk a fenti hibákat commit előtt." -#: lib/index.tcl:364 +#: lib/index.tcl:241 +#, fuzzy, tcl-format +msgid "Unstaging %s from commit" +msgstr "Commitba való kiválasztás visszavonása" + +#: lib/index.tcl:285 +#, fuzzy, tcl-format +msgid "Adding %s" +msgstr "A(z) %s olvasása..." + +#: lib/index.tcl:340 #, tcl-format msgid "Revert changes in file %s?" msgstr "Visszaállítja a változtatásokat a(z) %s fájlban?" -#: lib/index.tcl:366 +#: lib/index.tcl:342 #, tcl-format msgid "Revert changes in these %i files?" msgstr "Visszaállítja a változtatásokat ebben e %i fájlban?" -#: lib/index.tcl:372 +#: lib/index.tcl:348 msgid "Any unstaged changes will be permanently lost by the revert." msgstr "" "Minden nem kiválasztott változtatás el fog veszni ezáltal a visszaállítás " "által." -#: lib/index.tcl:375 +#: lib/index.tcl:351 msgid "Do Nothing" msgstr "Ne csináljunk semmit" @@ -1180,71 +1603,101 @@ msgstr "A félbeszakítás nem sikerült." msgid "Abort completed. Ready." msgstr "A megkeszakítás befejeződött. Kész." -#: lib/option.tcl:77 -msgid "git-gui - a graphical user interface for Git." -msgstr "git-gui - egy grafikus felület a Githez." - -#: lib/option.tcl:164 +#: lib/option.tcl:82 msgid "Restore Defaults" msgstr "Alapértelmezés visszaállítása" -#: lib/option.tcl:168 +#: lib/option.tcl:86 msgid "Save" msgstr "Mentés" -#: lib/option.tcl:178 +#: lib/option.tcl:96 #, tcl-format msgid "%s Repository" msgstr "%s Repó" -#: lib/option.tcl:179 +#: lib/option.tcl:97 msgid "Global (All Repositories)" msgstr "Globális (minden repó)" -#: lib/option.tcl:185 +#: lib/option.tcl:103 msgid "User Name" msgstr "Felhasználónév" -#: lib/option.tcl:186 +#: lib/option.tcl:104 msgid "Email Address" msgstr "Email cím" -#: lib/option.tcl:188 +#: lib/option.tcl:106 msgid "Summarize Merge Commits" msgstr "A merge commitok összegzése" -#: lib/option.tcl:189 +#: lib/option.tcl:107 msgid "Merge Verbosity" msgstr "Merge beszédesség" -#: lib/option.tcl:190 +#: lib/option.tcl:108 msgid "Show Diffstat After Merge" msgstr "Diffstat mutatása merge után" -#: lib/option.tcl:192 +#: lib/option.tcl:110 msgid "Trust File Modification Timestamps" msgstr "A fájl módosítási dátumok megbízhatóak" -#: lib/option.tcl:193 +#: lib/option.tcl:111 msgid "Prune Tracking Branches During Fetch" msgstr "A követő branchek eltávolítása letöltés alatt" -#: lib/option.tcl:194 +#: lib/option.tcl:112 msgid "Match Tracking Branches" msgstr "A követő branchek egyeztetése" -#: lib/option.tcl:195 +#: lib/option.tcl:113 msgid "Number of Diff Context Lines" msgstr "A diff környezeti sorok száma" -#: lib/option.tcl:196 +#: lib/option.tcl:114 msgid "New Branch Name Template" msgstr "Új branch név sablon" -#: lib/option.tcl:305 +#: lib/option.tcl:176 +#, fuzzy +msgid "Change Font" +msgstr "Fő betűtípus" + +#: lib/option.tcl:180 +#, tcl-format +msgid "Choose %s" +msgstr "" + +#: lib/option.tcl:186 +msgid "pt." +msgstr "" + +#: lib/option.tcl:200 +msgid "Preferences" +msgstr "" + +#: lib/option.tcl:235 msgid "Failed to completely save options:" msgstr "Nem sikerült teljesen elmenteni a beállításokat:" +#: lib/remote.tcl:165 +#, fuzzy +msgid "Prune from" +msgstr "Törlés innen: %s..." + +# tcl-format +#: lib/remote.tcl:170 +#, fuzzy +msgid "Fetch from" +msgstr "Letöltés innen: %s..." + +#: lib/remote.tcl:213 +#, fuzzy +msgid "Push to" +msgstr "Push" + #: lib/remote_branch_delete.tcl:29 lib/remote_branch_delete.tcl:34 msgid "Delete Remote Branch" msgstr "Távoli branch törlése" @@ -1253,11 +1706,11 @@ msgstr "Távoli branch törlése" msgid "From Repository" msgstr "Forrás repó" -#: lib/remote_branch_delete.tcl:50 lib/transport.tcl:118 +#: lib/remote_branch_delete.tcl:50 lib/transport.tcl:123 msgid "Remote:" msgstr "Távoli:" -#: lib/remote_branch_delete.tcl:66 lib/transport.tcl:133 +#: lib/remote_branch_delete.tcl:66 lib/transport.tcl:138 msgid "Arbitrary URL:" msgstr "Tetszőleges URL:" @@ -1281,6 +1734,14 @@ msgstr "Mindig (Ne végezzen merge vizsgálatokat)" msgid "A branch is required for 'Merged Into'." msgstr "Egy branch szükséges a 'Merge-ölt a következőbe'-hez." +#: lib/remote_branch_delete.tcl:184 +#, fuzzy, tcl-format +msgid "" +"The following branches are not completely merged into %s:\n" +"\n" +" - %s" +msgstr "A következő branchek nem teljesen lettek merge-ölve ebbe: %s:" + #: lib/remote_branch_delete.tcl:189 #, tcl-format msgid "" @@ -1318,22 +1779,6 @@ msgstr "Nincs kiválasztott repó." msgid "Scanning %s..." msgstr "Keresés itt: %s..." -# tcl-format -#: lib/remote.tcl:162 -#, tcl-format -msgid "Fetch from %s..." -msgstr "Letöltés innen: %s..." - -#: lib/remote.tcl:172 -#, tcl-format -msgid "Prune from %s..." -msgstr "Törlés innen: %s..." - -#: lib/remote.tcl:206 -#, tcl-format -msgid "Push to %s..." -msgstr "Pusholás ide: %s..." - #: lib/shortcut.tcl:26 lib/shortcut.tcl:74 msgid "Cannot write script:" msgstr "Nem sikerült írni a scriptet:" @@ -1342,55 +1787,83 @@ msgstr "Nem sikerült írni a scriptet:" msgid "Cannot write icon:" msgstr "Nem sikerült írni az ikont:" -#: lib/status_bar.tcl:58 +#: lib/status_bar.tcl:83 #, tcl-format msgid "%s ... %*i of %*i %s (%3i%%)" msgstr "%s ... %*i / %*i %s (%3i%%)" +#: lib/transport.tcl:6 +#, fuzzy, tcl-format +msgid "fetch %s" +msgstr "Letöltés" + #: lib/transport.tcl:7 #, tcl-format msgid "Fetching new changes from %s" msgstr "Új változások letöltése innen: %s" +#: lib/transport.tcl:18 +#, tcl-format +msgid "remote prune %s" +msgstr "" + #: lib/transport.tcl:19 #, tcl-format msgid "Pruning tracking branches deleted from %s" msgstr "A %s repóból törölt követő branchek törlése" +#: lib/transport.tcl:25 lib/transport.tcl:71 +#, tcl-format +msgid "push %s" +msgstr "" + #: lib/transport.tcl:26 #, tcl-format msgid "Pushing changes to %s" msgstr "Változások pusholása ide: %s" -#: lib/transport.tcl:68 +#: lib/transport.tcl:72 #, tcl-format msgid "Pushing %s %s to %s" msgstr "Pusholás: %s %s, ide: %s" -#: lib/transport.tcl:84 +#: lib/transport.tcl:89 msgid "Push Branches" msgstr "Branchek pusholása" -#: lib/transport.tcl:98 +#: lib/transport.tcl:103 msgid "Source Branches" msgstr "Forrás branchek" -#: lib/transport.tcl:115 +#: lib/transport.tcl:120 msgid "Destination Repository" msgstr "Cél repó" -#: lib/transport.tcl:153 +#: lib/transport.tcl:158 msgid "Transfer Options" msgstr "Átviteli opciók" -#: lib/transport.tcl:155 +#: lib/transport.tcl:160 +msgid "Force overwrite existing branch (may discard changes)" +msgstr "" + +#: lib/transport.tcl:164 msgid "Use thin pack (for slow network connections)" msgstr "Vékony csomagok használata (lassú hálózati kapcsolatok számára)" -#: lib/transport.tcl:159 +#: lib/transport.tcl:168 msgid "Include tags" msgstr "Tageket is" +#~ msgid "Cannot find the git directory:" +#~ msgstr "Nem található a git könyvtár:" + +#~ msgid "Unstaged Changes (Will Not Be Committed)" +#~ msgstr "Nem kiválasztott változtatások (nem lesz commitolva)" + +#~ msgid "Push to %s..." +#~ msgstr "Pusholás ide: %s..." + #~ msgid "Add To Commit" #~ msgstr "Hozzáadás a commithoz" diff --git a/po/it.po b/po/it.po index ad5cd9e5da..d959019aab 100644 --- a/po/it.po +++ b/po/it.po @@ -9,23 +9,41 @@ msgid "" msgstr "" "Project-Id-Version: git-gui\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2007-08-11 17:28+0200\n" +"POT-Creation-Date: 2007-10-10 04:04-0400\n" "PO-Revision-Date: 2007-08-09 00:27+0200\n" "Last-Translator: Paolo Ciarrocchi \n" "Language-Team: Italian \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit" +"Content-Transfer-Encoding: 8bit\n" -#: git-gui.sh:531 +#: git-gui.sh:41 git-gui.sh:634 git-gui.sh:648 git-gui.sh:661 git-gui.sh:744 +#: git-gui.sh:763 +msgid "git-gui: fatal error" +msgstr "" + +#: git-gui.sh:595 +#, fuzzy, tcl-format +msgid "Invalid font specified in %s:" +msgstr "Caratteri non validi specificati nella gui.%s:" + +#: git-gui.sh:620 +msgid "Main Font" +msgstr "Caratteri principali" + +#: git-gui.sh:621 +msgid "Diff/Console Font" +msgstr "Caratteri per confronti e terminale" + +#: git-gui.sh:635 msgid "Cannot find git in PATH." msgstr "Impossibile trovare git nel PATH" -#: git-gui.sh:550 +#: git-gui.sh:662 msgid "Cannot parse Git version string:" msgstr "Impossibile determinare la versione di Git:" -#: git-gui.sh:567 +#: git-gui.sh:680 #, tcl-format msgid "" "Git version cannot be determined.\n" @@ -44,79 +62,80 @@ msgstr "" "\n" "Assumere che '%s' sia alla versione 1.5.0?\n" -#: git-gui.sh:689 -msgid "Cannot find the git directory:" -msgstr "Non posso trovare la directory di git:" - -#: git-gui.sh:697 +#: git-gui.sh:853 msgid "Git directory not found:" msgstr "Non trovo la directory di git: " -#: git-gui.sh:703 +#: git-gui.sh:860 +#, fuzzy +msgid "Cannot move to top of working directory:" +msgstr "Impossibile usare una .git directory strana:" + +#: git-gui.sh:867 msgid "Cannot use funny .git directory:" msgstr "Impossibile usare una .git directory strana:" -#: git-gui.sh:708 +#: git-gui.sh:872 msgid "No working directory" msgstr "Nessuna directory di lavoro" -#: git-gui.sh:854 +#: git-gui.sh:1019 msgid "Refreshing file status..." msgstr "Controllo dello stato dei file in corso..." -#: git-gui.sh:891 +#: git-gui.sh:1084 msgid "Scanning for modified files ..." msgstr "Ricerca di file modificati in corso..." -#: git-gui.sh:1057 lib/browser.tcl:247 +#: git-gui.sh:1259 lib/browser.tcl:245 msgid "Ready." msgstr "Pronto." -#: git-gui.sh:1322 +#: git-gui.sh:1525 msgid "Unmodified" msgstr "Non modificato" -#: git-gui.sh:1324 +#: git-gui.sh:1527 msgid "Modified, not staged" msgstr "Modificato, non pronto per il commit" -#: git-gui.sh:1325 git-gui.sh:1330 +#: git-gui.sh:1528 git-gui.sh:1533 msgid "Staged for commit" msgstr "Pronto per il commit" -#: git-gui.sh:1326 git-gui.sh:1331 +#: git-gui.sh:1529 git-gui.sh:1534 msgid "Portions staged for commit" msgstr "Parti pronte per il commit" -#: git-gui.sh:1327 git-gui.sh:1332 +#: git-gui.sh:1530 git-gui.sh:1535 msgid "Staged for commit, missing" msgstr "Pronto per il commit, mancante" -#: git-gui.sh:1329 +#: git-gui.sh:1532 msgid "Untracked, not staged" msgstr "Non tracciato, non pronto per il commit" -#: git-gui.sh:1334 +#: git-gui.sh:1537 msgid "Missing" msgstr "Mancante" -#: git-gui.sh:1335 +#: git-gui.sh:1538 msgid "Staged for removal" msgstr "Pronto per la rimozione" -#: git-gui.sh:1336 +#: git-gui.sh:1539 msgid "Staged for removal, still present" msgstr "Pronto alla rimozione, ancora presente" -#: git-gui.sh:1338 git-gui.sh:1339 git-gui.sh:1340 git-gui.sh:1341 +#: git-gui.sh:1541 git-gui.sh:1542 git-gui.sh:1543 git-gui.sh:1544 msgid "Requires merge resolution" msgstr "Richiede risoluzione dei conflitti" -#: git-gui.sh:1383 +#: git-gui.sh:1579 msgid "Starting gitk... please wait..." msgstr "Avvio di gitk... attendere..." -#: git-gui.sh:1392 +#: git-gui.sh:1588 #, tcl-format msgid "" "Unable to start gitk:\n" @@ -127,293 +146,332 @@ msgstr "" "\n" "%s non esiste" -#: git-gui.sh:1609 -#, tcl-format -msgid "Invalid font specified in gui.%s:" -msgstr "Caratteri non validi specificati nella gui.%s:" - -#: git-gui.sh:1634 -msgid "Main Font" -msgstr "Caratteri principali" - -#: git-gui.sh:1635 -msgid "Diff/Console Font" -msgstr "Caratteri per confronti e terminale" - -#: git-gui.sh:1649 +#: git-gui.sh:1788 lib/choose_repository.tcl:32 msgid "Repository" msgstr "Archivio" -#: git-gui.sh:1650 +#: git-gui.sh:1789 msgid "Edit" msgstr "Modifica" -#: git-gui.sh:1652 +#: git-gui.sh:1791 lib/choose_rev.tcl:560 msgid "Branch" msgstr "Ramo" -#: git-gui.sh:1655 git-gui.sh:1842 git-gui.sh:2152 -msgid "Commit" +#: git-gui.sh:1794 lib/choose_rev.tcl:547 +#, fuzzy +msgid "Commit@@noun" msgstr "Commit" -#: git-gui.sh:1658 lib/merge.tcl:121 lib/merge.tcl:150 lib/merge.tcl:168 +#: git-gui.sh:1797 lib/merge.tcl:121 lib/merge.tcl:150 lib/merge.tcl:168 msgid "Merge" msgstr "Fusione (Merge)" -#: git-gui.sh:1659 -msgid "Fetch" -msgstr "Preleva (Fetch)" +#: git-gui.sh:1798 lib/choose_rev.tcl:556 +#, fuzzy +msgid "Remote" +msgstr "Remoto:" -#: git-gui.sh:1660 git-gui.sh:2158 lib/transport.tcl:88 lib/transport.tcl:172 -msgid "Push" -msgstr "Propaga (Push)" - -#: git-gui.sh:1669 +#: git-gui.sh:1807 msgid "Browse Current Branch's Files" msgstr "Esplora i file del ramo corrente" -#: git-gui.sh:1673 +#: git-gui.sh:1811 msgid "Browse Branch Files..." msgstr "Esplora i file del ramo..." -#: git-gui.sh:1678 +#: git-gui.sh:1816 msgid "Visualize Current Branch's History" msgstr "Visualizza la cronologia del ramo corrente" -#: git-gui.sh:1682 +#: git-gui.sh:1820 msgid "Visualize All Branch History" msgstr "Visualizza la cronologia di tutti i rami" -#: git-gui.sh:1689 +#: git-gui.sh:1827 #, tcl-format msgid "Browse %s's Files" msgstr "Esplora i file di %s" -#: git-gui.sh:1691 +#: git-gui.sh:1829 #, tcl-format msgid "Visualize %s's History" msgstr "Visualizza la cronologia di %s" -#: git-gui.sh:1696 lib/database.tcl:27 lib/database.tcl:67 +#: git-gui.sh:1834 lib/database.tcl:27 lib/database.tcl:67 msgid "Database Statistics" msgstr "Statistiche del database" -#: git-gui.sh:1699 lib/database.tcl:34 +#: git-gui.sh:1837 lib/database.tcl:34 msgid "Compress Database" msgstr "Comprimi il database" -#: git-gui.sh:1702 +#: git-gui.sh:1840 msgid "Verify Database" msgstr "Verifica il database" -#: git-gui.sh:1709 git-gui.sh:1713 git-gui.sh:1717 lib/shortcut.tcl:9 +#: git-gui.sh:1847 git-gui.sh:1851 git-gui.sh:1855 lib/shortcut.tcl:9 #: lib/shortcut.tcl:45 lib/shortcut.tcl:84 msgid "Create Desktop Icon" msgstr "Crea icona desktop" -#: git-gui.sh:1722 +#: git-gui.sh:1860 lib/choose_repository.tcl:36 lib/choose_repository.tcl:95 msgid "Quit" msgstr "Esci" -#: git-gui.sh:1729 +#: git-gui.sh:1867 msgid "Undo" msgstr "Annulla" -#: git-gui.sh:1732 +#: git-gui.sh:1870 msgid "Redo" msgstr "Ripeti" -#: git-gui.sh:1736 git-gui.sh:2222 +#: git-gui.sh:1874 git-gui.sh:2366 msgid "Cut" msgstr "Taglia" -#: git-gui.sh:1739 git-gui.sh:2225 git-gui.sh:2296 git-gui.sh:2368 -#: lib/console.tcl:69 +#: git-gui.sh:1877 git-gui.sh:2369 git-gui.sh:2440 git-gui.sh:2512 +#: lib/console.tcl:67 msgid "Copy" msgstr "Copia" -#: git-gui.sh:1742 git-gui.sh:2228 +#: git-gui.sh:1880 git-gui.sh:2372 msgid "Paste" msgstr "Incolla" -#: git-gui.sh:1745 git-gui.sh:2231 lib/branch_delete.tcl:26 +#: git-gui.sh:1883 git-gui.sh:2375 lib/branch_delete.tcl:26 #: lib/remote_branch_delete.tcl:38 msgid "Delete" msgstr "Elimina" -#: git-gui.sh:1749 git-gui.sh:2235 git-gui.sh:2372 lib/console.tcl:71 +#: git-gui.sh:1887 git-gui.sh:2379 git-gui.sh:2516 lib/console.tcl:69 msgid "Select All" msgstr "Seleziona tutto" -#: git-gui.sh:1758 +#: git-gui.sh:1896 msgid "Create..." msgstr "Crea..." -#: git-gui.sh:1764 +#: git-gui.sh:1902 msgid "Checkout..." msgstr "Checkout..." -#: git-gui.sh:1770 +#: git-gui.sh:1908 msgid "Rename..." msgstr "Rinomina" -#: git-gui.sh:1775 git-gui.sh:1873 +#: git-gui.sh:1913 git-gui.sh:2012 msgid "Delete..." msgstr "Elimina..." -#: git-gui.sh:1780 +#: git-gui.sh:1918 msgid "Reset..." msgstr "Ripristina..." -#: git-gui.sh:1792 git-gui.sh:2169 +#: git-gui.sh:1930 git-gui.sh:2313 msgid "New Commit" msgstr "Nuovo commit" -#: git-gui.sh:1800 git-gui.sh:2176 +#: git-gui.sh:1938 git-gui.sh:2320 msgid "Amend Last Commit" msgstr "Correggi l'ultimo commit" -#: git-gui.sh:1809 git-gui.sh:2136 lib/remote_branch_delete.tcl:99 +#: git-gui.sh:1947 git-gui.sh:2280 lib/remote_branch_delete.tcl:99 msgid "Rescan" msgstr "Analizza nuovamente" -#: git-gui.sh:1815 +#: git-gui.sh:1953 msgid "Stage To Commit" msgstr "Prepara per il commit" -#: git-gui.sh:1820 +#: git-gui.sh:1958 msgid "Stage Changed Files To Commit" msgstr "Prepara per il commit i file modificati" -#: git-gui.sh:1826 +#: git-gui.sh:1964 msgid "Unstage From Commit" msgstr "Non pronto per il commit" -#: git-gui.sh:1831 lib/index.tcl:376 +#: git-gui.sh:1969 lib/index.tcl:352 msgid "Revert Changes" msgstr "Annulla modifiche" -#: git-gui.sh:1838 git-gui.sh:2148 git-gui.sh:2246 +#: git-gui.sh:1976 git-gui.sh:2292 git-gui.sh:2390 msgid "Sign Off" msgstr "Sign Off" -#: git-gui.sh:1853 +#: git-gui.sh:1980 git-gui.sh:2296 +#, fuzzy +msgid "Commit@@verb" +msgstr "Commit" + +#: git-gui.sh:1991 msgid "Local Merge..." msgstr "Fusione locale" -#: git-gui.sh:1858 +#: git-gui.sh:1996 msgid "Abort Merge..." msgstr "Interrompi fusione" -#: git-gui.sh:1870 +#: git-gui.sh:2008 msgid "Push..." msgstr "Propaga..." -#: git-gui.sh:1880 +#: git-gui.sh:2019 lib/choose_repository.tcl:41 msgid "Apple" msgstr "Apple" -#: git-gui.sh:1883 git-gui.sh:1901 lib/option.tcl:65 +#: git-gui.sh:2022 git-gui.sh:2044 lib/about.tcl:13 +#: lib/choose_repository.tcl:44 lib/choose_repository.tcl:50 #, tcl-format msgid "About %s" msgstr "Informazioni su %s" -#: git-gui.sh:1885 git-gui.sh:1891 git-gui.sh:2414 +#: git-gui.sh:2026 +msgid "Preferences..." +msgstr "" + +#: git-gui.sh:2034 git-gui.sh:2558 msgid "Options..." msgstr "Opzioni..." -#: git-gui.sh:1897 +#: git-gui.sh:2040 lib/choose_repository.tcl:47 msgid "Help" msgstr "Aiuto" -#: git-gui.sh:1938 +#: git-gui.sh:2081 msgid "Online Documentation" msgstr "Documentazione sul web" -#: git-gui.sh:2054 +#: git-gui.sh:2165 +#, tcl-format +msgid "fatal: cannot stat path %s: No such file or directory" +msgstr "" + +#: git-gui.sh:2198 msgid "Current Branch:" msgstr "Ramo attuale:" -#: git-gui.sh:2075 -msgid "Staged Changes (Will Be Committed)" +#: git-gui.sh:2219 +#, fuzzy +msgid "Staged Changes (Will Commit)" msgstr "Modifiche preparate (ne verrà effettuato il commit)" -#: git-gui.sh:2095 -msgid "Unstaged Changes (Will Not Be Committed)" -msgstr "Modifiche non preparate (non ne verrà effettuato il commit)" +#: git-gui.sh:2239 +#, fuzzy +msgid "Unstaged Changes" +msgstr "Prepara modificati" -#: git-gui.sh:2142 +#: git-gui.sh:2286 msgid "Stage Changed" msgstr "Prepara modificati" -#: git-gui.sh:2188 +#: git-gui.sh:2302 lib/transport.tcl:93 lib/transport.tcl:182 +msgid "Push" +msgstr "Propaga (Push)" + +#: git-gui.sh:2332 msgid "Initial Commit Message:" msgstr "Messaggio di commit iniziale:" -#: git-gui.sh:2189 +#: git-gui.sh:2333 msgid "Amended Commit Message:" msgstr "Messaggio di commit corretto:" -#: git-gui.sh:2190 +#: git-gui.sh:2334 msgid "Amended Initial Commit Message:" msgstr "Messaggio iniziale di commit corretto:" -#: git-gui.sh:2191 +#: git-gui.sh:2335 msgid "Amended Merge Commit Message:" msgstr "Messaggio di fusione corretto:" -#: git-gui.sh:2192 +#: git-gui.sh:2336 msgid "Merge Commit Message:" msgstr "Messaggio di fusione:" -#: git-gui.sh:2193 +#: git-gui.sh:2337 msgid "Commit Message:" msgstr "Messaggio di commit:" -#: git-gui.sh:2238 git-gui.sh:2376 lib/console.tcl:73 +#: git-gui.sh:2382 git-gui.sh:2520 lib/console.tcl:71 msgid "Copy All" msgstr "Copia tutto" -#: git-gui.sh:2262 lib/blame.tcl:104 +#: git-gui.sh:2406 lib/blame.tcl:104 msgid "File:" msgstr "File:" -#: git-gui.sh:2364 +#: git-gui.sh:2508 msgid "Refresh" msgstr "Rinfresca" -#: git-gui.sh:2385 +#: git-gui.sh:2529 msgid "Apply/Reverse Hunk" msgstr "Applica/Inverti sezione" -#: git-gui.sh:2391 +#: git-gui.sh:2535 msgid "Decrease Font Size" msgstr "Diminuisci dimensione caratteri" -#: git-gui.sh:2395 +#: git-gui.sh:2539 msgid "Increase Font Size" msgstr "Aumenta dimensione caratteri" -#: git-gui.sh:2400 +#: git-gui.sh:2544 msgid "Show Less Context" msgstr "Mostra meno contesto" -#: git-gui.sh:2407 +#: git-gui.sh:2551 msgid "Show More Context" msgstr "Mostra più contesto" -#: git-gui.sh:2422 +#: git-gui.sh:2565 msgid "Unstage Hunk From Commit" msgstr "Sezione non pronta per il commit" -#: git-gui.sh:2426 git-gui.sh:2430 +#: git-gui.sh:2567 msgid "Stage Hunk For Commit" msgstr "Prepara sezione per il commit" -#: git-gui.sh:2440 +#: git-gui.sh:2586 msgid "Initializing..." msgstr "Inizializzazione..." +#: git-gui.sh:2677 +#, tcl-format +msgid "" +"Possible environment issues exist.\n" +"\n" +"The following environment variables are probably\n" +"going to be ignored by any Git subprocess run\n" +"by %s:\n" +"\n" +msgstr "" + +#: git-gui.sh:2707 +msgid "" +"\n" +"This is due to a known issue with the\n" +"Tcl binary distributed by Cygwin." +msgstr "" + +#: git-gui.sh:2712 +#, tcl-format +msgid "" +"\n" +"\n" +"A good replacement for %s\n" +"is placing values for the user.name and\n" +"user.email settings into your personal\n" +"~/.gitconfig file.\n" +msgstr "" + +#: lib/about.tcl:25 +msgid "git-gui - a graphical user interface for Git." +msgstr "git-gui - un'interfaccia grafica per Git." + #: lib/blame.tcl:77 msgid "File Viewer" msgstr "Mostra file" @@ -431,6 +489,53 @@ msgstr "Copia commit" msgid "Reading %s..." msgstr "Lettura di %s..." +#: lib/blame.tcl:473 +msgid "Loading copy/move tracking annotations..." +msgstr "" + +#: lib/blame.tcl:493 +msgid "lines annotated" +msgstr "" + +#: lib/blame.tcl:674 +msgid "Loading original location annotations..." +msgstr "" + +#: lib/blame.tcl:677 +msgid "Annotation complete." +msgstr "" + +#: lib/blame.tcl:731 +#, fuzzy +msgid "Loading annotation..." +msgstr "Caricamento %s..." + +#: lib/blame.tcl:787 +msgid "Author:" +msgstr "" + +#: lib/blame.tcl:791 +#, fuzzy +msgid "Committer:" +msgstr "Commit:" + +#: lib/blame.tcl:796 +msgid "Original File:" +msgstr "" + +#: lib/blame.tcl:910 +msgid "Originally By:" +msgstr "" + +#: lib/blame.tcl:916 +#, fuzzy +msgid "In File:" +msgstr "File:" + +#: lib/blame.tcl:921 +msgid "Copied Or Moved Here By:" +msgstr "" + #: lib/branch_checkout.tcl:14 lib/branch_checkout.tcl:19 msgid "Checkout Branch" msgstr "Checkout ramo" @@ -440,18 +545,17 @@ msgid "Checkout" msgstr "Checkout" #: lib/branch_checkout.tcl:27 lib/branch_create.tcl:35 -#: lib/branch_delete.tcl:32 lib/branch_rename.tcl:30 lib/browser.tcl:283 -#: lib/checkout_op.tcl:522 lib/merge.tcl:172 lib/option.tcl:172 -#: lib/remote_branch_delete.tcl:42 lib/transport.tcl:92 +#: lib/branch_delete.tcl:32 lib/branch_rename.tcl:30 lib/browser.tcl:281 +#: lib/checkout_op.tcl:522 lib/choose_font.tcl:43 lib/merge.tcl:172 +#: lib/option.tcl:90 lib/remote_branch_delete.tcl:42 lib/transport.tcl:97 msgid "Cancel" msgstr "Annulla" -#: lib/branch_checkout.tcl:32 lib/browser.tcl:288 +#: lib/branch_checkout.tcl:32 lib/browser.tcl:286 msgid "Revision" msgstr "Revisione" -#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:159 -#: lib/option.tcl:274 +#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:202 msgid "Options" msgstr "Opzioni" @@ -471,7 +575,7 @@ msgstr "Crea ramo" msgid "Create New Branch" msgstr "Crea nuovo ramo" -#: lib/branch_create.tcl:31 +#: lib/branch_create.tcl:31 lib/choose_repository.tcl:199 msgid "Create" msgstr "Crea" @@ -611,20 +715,22 @@ msgstr "Avvio in corso..." msgid "File Browser" msgstr "File browser" -#: lib/browser.tcl:127 lib/browser.tcl:144 +#: lib/browser.tcl:125 lib/browser.tcl:142 #, tcl-format msgid "Loading %s..." msgstr "Caricamento %s..." -#: lib/browser.tcl:188 +#: lib/browser.tcl:186 msgid "[Up To Parent]" msgstr "[Directory superiore]" -#: lib/browser.tcl:268 lib/browser.tcl:274 +#: lib/browser.tcl:266 lib/browser.tcl:272 msgid "Browse Branch Files" msgstr "Esplora i file del ramo" -#: lib/browser.tcl:279 +#: lib/browser.tcl:277 lib/choose_repository.tcl:215 +#: lib/choose_repository.tcl:305 lib/choose_repository.tcl:315 +#: lib/choose_repository.tcl:811 msgid "Browse" msgstr "Sfoglia" @@ -633,7 +739,12 @@ msgstr "Sfoglia" msgid "Fetching %s from %s" msgstr "Recupero %s da %s" -#: lib/checkout_op.tcl:140 lib/console.tcl:81 lib/database.tcl:31 +#: lib/checkout_op.tcl:127 +#, tcl-format +msgid "fatal: Cannot resolve %s" +msgstr "" + +#: lib/checkout_op.tcl:140 lib/console.tcl:79 lib/database.tcl:31 msgid "Close" msgstr "Chiudi" @@ -649,7 +760,8 @@ msgid "" "\n" "It cannot fast-forward to %s.\n" "A merge is required." -msgstr "Il ramo '%s' esiste già.\n" +msgstr "" +"Il ramo '%s' esiste già.\n" "\n" "Non può effettuare un 'fast-forward' a %s.\n" "E' necessaria una fusione." @@ -685,6 +797,11 @@ msgstr "" "\n" "La nuova analisi comincerà ora.\n" +#: lib/checkout_op.tcl:322 +#, fuzzy, tcl-format +msgid "Updating working directory to '%s'..." +msgstr "Nessuna directory di lavoro" + #: lib/checkout_op.tcl:353 #, tcl-format msgid "Aborted checkout of '%s' (file level merging is required)." @@ -708,8 +825,13 @@ msgid "" msgstr "" "Non si è più su un ramo locale\n" "\n" -"Se si vuole rimanere su un ramo, crearne uno ora a partire da 'Questo checkout " -"staccato'." +"Se si vuole rimanere su un ramo, crearne uno ora a partire da 'Questo " +"checkout staccato'." + +#: lib/checkout_op.tcl:446 +#, fuzzy, tcl-format +msgid "Checked out '%s'." +msgstr "Checkout..." #: lib/checkout_op.tcl:478 #, tcl-format @@ -741,12 +863,252 @@ msgid "" msgstr "" "Preparazione ramo corrente fallita.\n" "\n" -"Questa directory di lavoro è stata convertita solo parzialmente. I file " -"sono stati aggiornati correttamente, ma l'aggiornamento di un file di Git ha " +"Questa directory di lavoro è stata convertita solo parzialmente. I file sono " +"stati aggiornati correttamente, ma l'aggiornamento di un file di Git ha " "prodotto degli errori.\n" "\n" "Questo non sarebbe dovuto succedere. %s ora terminerà senza altre azioni." +#: lib/choose_font.tcl:39 +#, fuzzy +msgid "Select" +msgstr "Seleziona tutto" + +#: lib/choose_font.tcl:53 +msgid "Font Family" +msgstr "" + +#: lib/choose_font.tcl:73 +#, fuzzy +msgid "Font Size" +msgstr "Diminuisci dimensione caratteri" + +#: lib/choose_font.tcl:90 +msgid "Font Example" +msgstr "" + +#: lib/choose_font.tcl:101 +msgid "" +"This is example text.\n" +"If you like this text, it can be your font." +msgstr "" + +#: lib/choose_repository.tcl:25 +msgid "Git Gui" +msgstr "" + +#: lib/choose_repository.tcl:69 lib/choose_repository.tcl:204 +#, fuzzy +msgid "Create New Repository" +msgstr "Da archivio" + +#: lib/choose_repository.tcl:74 lib/choose_repository.tcl:291 +#, fuzzy +msgid "Clone Existing Repository" +msgstr "Archivio di destinazione" + +#: lib/choose_repository.tcl:79 lib/choose_repository.tcl:800 +#, fuzzy +msgid "Open Existing Repository" +msgstr "Archivio di destinazione" + +#: lib/choose_repository.tcl:91 +msgid "Next >" +msgstr "" + +#: lib/choose_repository.tcl:152 +#, fuzzy, tcl-format +msgid "Location %s already exists." +msgstr "Il ramo '%s' esiste già" + +#: lib/choose_repository.tcl:158 lib/choose_repository.tcl:165 +#: lib/choose_repository.tcl:172 +#, fuzzy, tcl-format +msgid "Failed to create repository %s:" +msgstr "Fallimento nel salvataggio completo delle opzioni:" + +#: lib/choose_repository.tcl:209 lib/choose_repository.tcl:309 +msgid "Directory:" +msgstr "" + +#: lib/choose_repository.tcl:238 lib/choose_repository.tcl:363 +#: lib/choose_repository.tcl:834 +#, fuzzy +msgid "Git Repository" +msgstr "Archivio" + +#: lib/choose_repository.tcl:253 lib/choose_repository.tcl:260 +#, fuzzy, tcl-format +msgid "Directory %s already exists." +msgstr "Il ramo '%s' esiste già" + +#: lib/choose_repository.tcl:265 +#, fuzzy, tcl-format +msgid "File %s already exists." +msgstr "Il ramo '%s' esiste già" + +#: lib/choose_repository.tcl:286 +#, fuzzy +msgid "Clone" +msgstr "Chiudi" + +#: lib/choose_repository.tcl:299 +msgid "URL:" +msgstr "" + +#: lib/choose_repository.tcl:319 +msgid "Clone Type:" +msgstr "" + +#: lib/choose_repository.tcl:325 +msgid "Standard (Fast, Semi-Redundant, Hardlinks)" +msgstr "" + +#: lib/choose_repository.tcl:331 +msgid "Full Copy (Slower, Redundant Backup)" +msgstr "" + +#: lib/choose_repository.tcl:337 +msgid "Shared (Fastest, Not Recommended, No Backup)" +msgstr "" + +#: lib/choose_repository.tcl:369 lib/choose_repository.tcl:418 +#: lib/choose_repository.tcl:560 lib/choose_repository.tcl:630 +#: lib/choose_repository.tcl:840 lib/choose_repository.tcl:848 +#, fuzzy, tcl-format +msgid "Not a Git repository: %s" +msgstr "Nessun archivio selezionato." + +#: lib/choose_repository.tcl:405 +msgid "Standard only available for local repository." +msgstr "" + +#: lib/choose_repository.tcl:409 +msgid "Shared only available for local repository." +msgstr "" + +#: lib/choose_repository.tcl:439 +msgid "Failed to configure origin" +msgstr "" + +#: lib/choose_repository.tcl:451 +msgid "Counting objects" +msgstr "" + +#: lib/choose_repository.tcl:452 +msgid "buckets" +msgstr "" + +#: lib/choose_repository.tcl:476 +#, tcl-format +msgid "Unable to copy objects/info/alternates: %s" +msgstr "" + +#: lib/choose_repository.tcl:512 +#, fuzzy, tcl-format +msgid "Nothing to clone from %s." +msgstr "Recupero nuove modifiche da %s" + +#: lib/choose_repository.tcl:514 lib/choose_repository.tcl:728 +#: lib/choose_repository.tcl:740 +msgid "The 'master' branch has not been initialized." +msgstr "" + +#: lib/choose_repository.tcl:527 +msgid "Hardlinks are unavailable. Falling back to copying." +msgstr "" + +#: lib/choose_repository.tcl:539 +#, fuzzy, tcl-format +msgid "Cloning from %s" +msgstr "Recupero %s da %s" + +#: lib/choose_repository.tcl:570 +#, fuzzy +msgid "Copying objects" +msgstr "Compressione del database in corso" + +#: lib/choose_repository.tcl:571 +msgid "KiB" +msgstr "" + +#: lib/choose_repository.tcl:595 +#, tcl-format +msgid "Unable to copy object: %s" +msgstr "" + +#: lib/choose_repository.tcl:605 +msgid "Linking objects" +msgstr "" + +#: lib/choose_repository.tcl:606 +msgid "objects" +msgstr "" + +#: lib/choose_repository.tcl:614 +#, tcl-format +msgid "Unable to hardlink object: %s" +msgstr "" + +#: lib/choose_repository.tcl:669 +msgid "Cannot fetch branches and objects. See console output for details." +msgstr "" + +#: lib/choose_repository.tcl:680 +msgid "Cannot fetch tags. See console output for details." +msgstr "" + +#: lib/choose_repository.tcl:704 +msgid "Cannot determine HEAD. See console output for details." +msgstr "" + +#: lib/choose_repository.tcl:713 +#, tcl-format +msgid "Unable to cleanup %s" +msgstr "" + +#: lib/choose_repository.tcl:719 +#, fuzzy +msgid "Clone failed." +msgstr "Interruzione fallita." + +#: lib/choose_repository.tcl:726 +msgid "No default branch obtained." +msgstr "" + +#: lib/choose_repository.tcl:737 +#, tcl-format +msgid "Cannot resolve %s as a commit." +msgstr "" + +#: lib/choose_repository.tcl:749 +#, fuzzy +msgid "Creating working directory" +msgstr "Nessuna directory di lavoro" + +#: lib/choose_repository.tcl:750 lib/index.tcl:15 lib/index.tcl:80 +#: lib/index.tcl:149 +msgid "files" +msgstr "" + +#: lib/choose_repository.tcl:779 +msgid "Initial file checkout failed." +msgstr "" + +#: lib/choose_repository.tcl:795 +msgid "Open" +msgstr "" + +#: lib/choose_repository.tcl:805 +#, fuzzy +msgid "Repository:" +msgstr "Archivio" + +#: lib/choose_repository.tcl:854 +#, fuzzy, tcl-format +msgid "Failed to open repository %s:" +msgstr "Fallimento nel salvataggio completo delle opzioni:" + #: lib/choose_rev.tcl:53 msgid "This Detached Checkout" msgstr "Questo checkout staccato" @@ -763,7 +1125,7 @@ msgstr "Ramo locale" msgid "Tracking Branch" msgstr "Ramo in 'tracking'" -#: lib/choose_rev.tcl:84 +#: lib/choose_rev.tcl:84 lib/choose_rev.tcl:537 msgid "Tag" msgstr "Etichetta" @@ -780,6 +1142,14 @@ msgstr "Nessuna revisione selezionata." msgid "Revision expression is empty." msgstr "L'espressione di revisione è vuota." +#: lib/choose_rev.tcl:530 +msgid "Updated" +msgstr "" + +#: lib/choose_rev.tcl:558 +msgid "URL" +msgstr "" + #: lib/commit.tcl:9 msgid "" "There is nothing to amend.\n" @@ -844,8 +1214,8 @@ msgid "" msgstr "" "Non è possibile effettuare il commit di file non sottoposti a fusione.\n" "\n" -"Il file %s presenta dei conflitti. Devi risolverli e preparare il file " -"per il commit prima di effettuare questa azione.\n" +"Il file %s presenta dei conflitti. Devi risolverli e preparare il file per " +"il commit prima di effettuare questa azione.\n" #: lib/commit.tcl:162 #, tcl-format @@ -866,7 +1236,8 @@ msgid "" msgstr "" "Nessuna modifica per la quale effettuare il commit.\n" "\n" -"Devi preparare per il commit almeno 1 file prima di effettuare questa operazione.\n" +"Devi preparare per il commit almeno 1 file prima di effettuare questa " +"operazione.\n" #: lib/commit.tcl:183 msgid "" @@ -890,6 +1261,11 @@ msgstr "" msgid "write-tree failed:" msgstr "write-tree fallito:" +#: lib/commit.tcl:275 +#, tcl-format +msgid "Commit %s appears to be corrupt" +msgstr "" + #: lib/commit.tcl:279 msgid "" "No changes to commit.\n" @@ -908,6 +1284,11 @@ msgstr "" msgid "No changes to commit." msgstr "Nessuna modifica pronta per il commit." +#: lib/commit.tcl:303 +#, tcl-format +msgid "warning: Tcl does not support encoding '%s'." +msgstr "" + #: lib/commit.tcl:317 msgid "commit-tree failed:" msgstr "commit-tree fallito:" @@ -921,15 +1302,15 @@ msgstr "update-ref fallito:" msgid "Created commit %s: %s" msgstr "Creato commit %s: %s" -#: lib/console.tcl:55 +#: lib/console.tcl:57 msgid "Working... please wait..." msgstr "Elaborazione in corso... attendere..." -#: lib/console.tcl:184 +#: lib/console.tcl:183 msgid "Success" msgstr "Successo" -#: lib/console.tcl:194 +#: lib/console.tcl:196 msgid "Error: Command Failed" msgstr "Errore: comando fallito" @@ -969,6 +1350,22 @@ msgstr "Compressione del database in corso" msgid "Verifying the object database with fsck-objects" msgstr "Verifica dell'archivio con fsck-objects in corso" +#: lib/database.tcl:108 +#, tcl-format +msgid "" +"This repository currently has approximately %i loose objects.\n" +"\n" +"To maintain optimal performance it is strongly recommended that you compress " +"the database when more than %i loose objects exist.\n" +"\n" +"Compress the database now?" +msgstr "" + +#: lib/date.tcl:25 +#, fuzzy, tcl-format +msgid "Invalid date from Git: %s" +msgstr "Revisione non valida: %s" + #: lib/diff.tcl:42 #, tcl-format msgid "" @@ -992,19 +1389,37 @@ msgstr "" "Si procederà automaticamente ad una nuova analisi per trovare altri file che " "potrebbero avere lo stesso stato." -#: lib/diff.tcl:97 +#: lib/diff.tcl:81 +#, fuzzy, tcl-format +msgid "Loading diff of %s..." +msgstr "Caricamento %s..." + +#: lib/diff.tcl:114 lib/diff.tcl:184 +#, tcl-format +msgid "Unable to display %s" +msgstr "" + +#: lib/diff.tcl:115 msgid "Error loading file:" msgstr "Errore nel caricamento del file:" -#: lib/diff.tcl:162 +#: lib/diff.tcl:122 +msgid "Git Repository (subproject)" +msgstr "" + +#: lib/diff.tcl:134 +msgid "* Binary file (not showing content)." +msgstr "" + +#: lib/diff.tcl:185 msgid "Error loading diff:" msgstr "Errore nel caricamento delle differenze:" -#: lib/diff.tcl:278 +#: lib/diff.tcl:302 msgid "Failed to unstage selected hunk." msgstr "La sezione scelta è ancora pronta per il commit." -#: lib/diff.tcl:285 +#: lib/diff.tcl:309 msgid "Failed to stage selected hunk." msgstr "La sezione scelta non è ancora pronta per il commit." @@ -1020,21 +1435,32 @@ msgstr "avviso" msgid "You must correct the above errors before committing." msgstr "Bisogna correggere gli errori suddetti prima di effettuare un commit." -#: lib/index.tcl:364 +#: lib/index.tcl:241 +#, fuzzy, tcl-format +msgid "Unstaging %s from commit" +msgstr "Non pronto per il commit" + +#: lib/index.tcl:285 +#, fuzzy, tcl-format +msgid "Adding %s" +msgstr "Lettura di %s..." + +#: lib/index.tcl:340 #, tcl-format msgid "Revert changes in file %s?" msgstr "Annullare le modifiche nel file %s?" -#: lib/index.tcl:366 +#: lib/index.tcl:342 #, tcl-format msgid "Revert changes in these %i files?" msgstr "Annullare le modifiche in questi %i file?" -#: lib/index.tcl:372 +#: lib/index.tcl:348 msgid "Any unstaged changes will be permanently lost by the revert." -msgstr "Tutte le modifiche non preparate per il commit saranno perse per sempre." +msgstr "" +"Tutte le modifiche non preparate per il commit saranno perse per sempre." -#: lib/index.tcl:375 +#: lib/index.tcl:351 msgid "Do Nothing" msgstr "Non fare niente" @@ -1080,9 +1506,8 @@ msgstr "" "Il file %s ha dei conflitti.\n" "\n" "Bisogna risolvere i conflitti, preparare il file per il commit ed infine " -"effettuare un commit " -"per completare la fusione corrente. Solo a questo punto potrai iniziare " -"un'altra fusione.\n" +"effettuare un commit per completare la fusione corrente. Solo a questo punto " +"potrai iniziare un'altra fusione.\n" #: lib/merge.tcl:54 #, tcl-format @@ -1164,8 +1589,8 @@ msgid "" msgstr "" "Annullare le modifiche?\n" "\n" -"L'annullamento delle modifiche causerà la perdita di *TUTTE* le " -"modifiche non ancora presenti nei commit.\n" +"L'annullamento delle modifiche causerà la perdita di *TUTTE* le modifiche " +"non ancora presenti nei commit.\n" "\n" "Continuare con l'annullamento delle modifiche correnti?" @@ -1181,71 +1606,100 @@ msgstr "Interruzione fallita." msgid "Abort completed. Ready." msgstr "Interruzione completata. Pronto." -#: lib/option.tcl:77 -msgid "git-gui - a graphical user interface for Git." -msgstr "git-gui - un'interfaccia grafica per Git." - -#: lib/option.tcl:164 +#: lib/option.tcl:82 msgid "Restore Defaults" msgstr "Ripristina predefiniti" -#: lib/option.tcl:168 +#: lib/option.tcl:86 msgid "Save" msgstr "Salva" -#: lib/option.tcl:178 +#: lib/option.tcl:96 #, tcl-format msgid "%s Repository" msgstr "%s archivio" -#: lib/option.tcl:179 +#: lib/option.tcl:97 msgid "Global (All Repositories)" msgstr "Globale (Tutti i repository)" -#: lib/option.tcl:185 +#: lib/option.tcl:103 msgid "User Name" msgstr "Nome utente" -#: lib/option.tcl:186 +#: lib/option.tcl:104 msgid "Email Address" msgstr "Indirizzo Email" -#: lib/option.tcl:188 +#: lib/option.tcl:106 msgid "Summarize Merge Commits" msgstr "Riepilogo nei commit di fusione" -#: lib/option.tcl:189 +#: lib/option.tcl:107 msgid "Merge Verbosity" msgstr "Verbosità della fusione" -#: lib/option.tcl:190 +#: lib/option.tcl:108 msgid "Show Diffstat After Merge" msgstr "Mostra statistiche delle differenze dopo la fusione" -#: lib/option.tcl:192 +#: lib/option.tcl:110 msgid "Trust File Modification Timestamps" msgstr "Fidati delle date di modifica dei file" -#: lib/option.tcl:193 +#: lib/option.tcl:111 msgid "Prune Tracking Branches During Fetch" msgstr "Effettua potatura dei rami in 'tracking' durante il recupero" -#: lib/option.tcl:194 +#: lib/option.tcl:112 msgid "Match Tracking Branches" msgstr "Appaia rami in 'tracking'" -#: lib/option.tcl:195 +#: lib/option.tcl:113 msgid "Number of Diff Context Lines" msgstr "Numero di linee di contesto nelle differenze" -#: lib/option.tcl:196 +#: lib/option.tcl:114 msgid "New Branch Name Template" msgstr "Modello per il nome di un nuovo ramo" -#: lib/option.tcl:305 +#: lib/option.tcl:176 +#, fuzzy +msgid "Change Font" +msgstr "Caratteri principali" + +#: lib/option.tcl:180 +#, tcl-format +msgid "Choose %s" +msgstr "" + +#: lib/option.tcl:186 +msgid "pt." +msgstr "" + +#: lib/option.tcl:200 +msgid "Preferences" +msgstr "" + +#: lib/option.tcl:235 msgid "Failed to completely save options:" msgstr "Fallimento nel salvataggio completo delle opzioni:" +#: lib/remote.tcl:165 +#, fuzzy +msgid "Prune from" +msgstr "Effettua potatura da %s..." + +#: lib/remote.tcl:170 +#, fuzzy +msgid "Fetch from" +msgstr "Preleva da %s..." + +#: lib/remote.tcl:213 +#, fuzzy +msgid "Push to" +msgstr "Propaga (Push)" + #: lib/remote_branch_delete.tcl:29 lib/remote_branch_delete.tcl:34 msgid "Delete Remote Branch" msgstr "Cancella ramo remoto" @@ -1254,11 +1708,11 @@ msgstr "Cancella ramo remoto" msgid "From Repository" msgstr "Da archivio" -#: lib/remote_branch_delete.tcl:50 lib/transport.tcl:118 +#: lib/remote_branch_delete.tcl:50 lib/transport.tcl:123 msgid "Remote:" msgstr "Remoto:" -#: lib/remote_branch_delete.tcl:66 lib/transport.tcl:133 +#: lib/remote_branch_delete.tcl:66 lib/transport.tcl:138 msgid "Arbitrary URL:" msgstr "URL arbitrario:" @@ -1282,6 +1736,14 @@ msgstr "Sempre (Non effettuare controlli durante la fusione)" msgid "A branch is required for 'Merged Into'." msgstr "Si richiede un ramo per 'Fuso in'." +#: lib/remote_branch_delete.tcl:184 +#, fuzzy, tcl-format +msgid "" +"The following branches are not completely merged into %s:\n" +"\n" +" - %s" +msgstr "I rami seguenti non sono stati fusi completamente in %s:" + #: lib/remote_branch_delete.tcl:189 #, tcl-format msgid "" @@ -1319,21 +1781,6 @@ msgstr "Nessun archivio selezionato." msgid "Scanning %s..." msgstr "Analisi in corso %s..." -#: lib/remote.tcl:162 -#, tcl-format -msgid "Fetch from %s..." -msgstr "Preleva da %s..." - -#: lib/remote.tcl:172 -#, tcl-format -msgid "Prune from %s..." -msgstr "Effettua potatura da %s..." - -#: lib/remote.tcl:206 -#, tcl-format -msgid "Push to %s..." -msgstr "Propaga verso %s..." - #: lib/shortcut.tcl:26 lib/shortcut.tcl:74 msgid "Cannot write script:" msgstr "Impossibile scrivere script:" @@ -1342,52 +1789,79 @@ msgstr "Impossibile scrivere script:" msgid "Cannot write icon:" msgstr "Impossibile scrivere icona:" -#: lib/status_bar.tcl:58 +#: lib/status_bar.tcl:83 #, tcl-format msgid "%s ... %*i of %*i %s (%3i%%)" msgstr "%s ... %*i di %*i %s (%3i%%)" +#: lib/transport.tcl:6 +#, fuzzy, tcl-format +msgid "fetch %s" +msgstr "Preleva (Fetch)" + #: lib/transport.tcl:7 #, tcl-format msgid "Fetching new changes from %s" msgstr "Recupero nuove modifiche da %s" +#: lib/transport.tcl:18 +#, tcl-format +msgid "remote prune %s" +msgstr "" + #: lib/transport.tcl:19 #, tcl-format msgid "Pruning tracking branches deleted from %s" msgstr "Effettua potatura dei rami in 'tracking' cancellati da %s" +#: lib/transport.tcl:25 lib/transport.tcl:71 +#, tcl-format +msgid "push %s" +msgstr "" + #: lib/transport.tcl:26 #, tcl-format msgid "Pushing changes to %s" msgstr "Propagazione modifiche a %s" -#: lib/transport.tcl:68 +#: lib/transport.tcl:72 #, tcl-format msgid "Pushing %s %s to %s" msgstr "Propagazione %s %s a %s" -#: lib/transport.tcl:84 +#: lib/transport.tcl:89 msgid "Push Branches" msgstr "Propaga rami" -#: lib/transport.tcl:98 +#: lib/transport.tcl:103 msgid "Source Branches" msgstr "Rami di origine" -#: lib/transport.tcl:115 +#: lib/transport.tcl:120 msgid "Destination Repository" msgstr "Archivio di destinazione" -#: lib/transport.tcl:153 +#: lib/transport.tcl:158 msgid "Transfer Options" msgstr "Opzioni di trasferimento" -#: lib/transport.tcl:155 +#: lib/transport.tcl:160 +msgid "Force overwrite existing branch (may discard changes)" +msgstr "" + +#: lib/transport.tcl:164 msgid "Use thin pack (for slow network connections)" msgstr "Utilizza 'thin pack' (per connessioni lente)" -#: lib/transport.tcl:159 +#: lib/transport.tcl:168 msgid "Include tags" msgstr "Includi etichette" +#~ msgid "Cannot find the git directory:" +#~ msgstr "Non posso trovare la directory di git:" + +#~ msgid "Unstaged Changes (Will Not Be Committed)" +#~ msgstr "Modifiche non preparate (non ne verrà effettuato il commit)" + +#~ msgid "Push to %s..." +#~ msgstr "Propaga verso %s..." diff --git a/po/ja.po b/po/ja.po index cdbc981ca5..f65e460686 100644 --- a/po/ja.po +++ b/po/ja.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: git-gui\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2007-08-11 17:28+0200\n" +"POT-Creation-Date: 2007-10-10 04:04-0400\n" "PO-Revision-Date: 2007-08-14 18:49+0900\n" "Last-Translator: しらいし ななこ \n" "Language-Team: Japanese\n" @@ -16,15 +16,33 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: git-gui.sh:531 +#: git-gui.sh:41 git-gui.sh:634 git-gui.sh:648 git-gui.sh:661 git-gui.sh:744 +#: git-gui.sh:763 +msgid "git-gui: fatal error" +msgstr "" + +#: git-gui.sh:595 +#, fuzzy, tcl-format +msgid "Invalid font specified in %s:" +msgstr "gui.%s に無効なフォントが指定されています:" + +#: git-gui.sh:620 +msgid "Main Font" +msgstr "主フォント" + +#: git-gui.sh:621 +msgid "Diff/Console Font" +msgstr "diff/コンソール・フォント" + +#: git-gui.sh:635 msgid "Cannot find git in PATH." msgstr "PATH 中に git が見つかりません" -#: git-gui.sh:550 +#: git-gui.sh:662 msgid "Cannot parse Git version string:" msgstr "Git バージョン名が理解できません:" -#: git-gui.sh:567 +#: git-gui.sh:680 #, tcl-format msgid "" "Git version cannot be determined.\n" @@ -43,79 +61,80 @@ msgstr "" "\n" "'%s' はバージョン 1.5.0 と思って良いですか?\n" -#: git-gui.sh:689 -msgid "Cannot find the git directory:" -msgstr "git ディレクトリが見つかりません:" - -#: git-gui.sh:697 +#: git-gui.sh:853 msgid "Git directory not found:" msgstr "Git ディレクトリが見つかりません:" -#: git-gui.sh:703 +#: git-gui.sh:860 +#, fuzzy +msgid "Cannot move to top of working directory:" +msgstr "変な .git ディレクトリは使えません" + +#: git-gui.sh:867 msgid "Cannot use funny .git directory:" msgstr "変な .git ディレクトリは使えません" -#: git-gui.sh:708 +#: git-gui.sh:872 msgid "No working directory" msgstr "作業ディレクトリがありません" -#: git-gui.sh:854 +#: git-gui.sh:1019 msgid "Refreshing file status..." msgstr "ファイル状態を更新しています…" -#: git-gui.sh:891 +#: git-gui.sh:1084 msgid "Scanning for modified files ..." msgstr "変更されたファイルをスキャンしています…" -#: git-gui.sh:1057 lib/browser.tcl:247 +#: git-gui.sh:1259 lib/browser.tcl:245 msgid "Ready." msgstr "準備完了" -#: git-gui.sh:1322 +#: git-gui.sh:1525 msgid "Unmodified" msgstr "変更無し" -#: git-gui.sh:1324 +#: git-gui.sh:1527 msgid "Modified, not staged" msgstr "変更あり、コミット未予定" -#: git-gui.sh:1325 git-gui.sh:1330 +#: git-gui.sh:1528 git-gui.sh:1533 msgid "Staged for commit" msgstr "コミット予定済" -#: git-gui.sh:1326 git-gui.sh:1331 +#: git-gui.sh:1529 git-gui.sh:1534 msgid "Portions staged for commit" msgstr "部分的にコミット予定済" -#: git-gui.sh:1327 git-gui.sh:1332 +#: git-gui.sh:1530 git-gui.sh:1535 msgid "Staged for commit, missing" msgstr "コミット予定済、ファイル無し" -#: git-gui.sh:1329 +#: git-gui.sh:1532 msgid "Untracked, not staged" msgstr "管理外、コミット未予定" -#: git-gui.sh:1334 +#: git-gui.sh:1537 msgid "Missing" msgstr "ファイル無し" -#: git-gui.sh:1335 +#: git-gui.sh:1538 msgid "Staged for removal" msgstr "削除予定済" -#: git-gui.sh:1336 +#: git-gui.sh:1539 msgid "Staged for removal, still present" msgstr "削除予定済、ファイル未削除" -#: git-gui.sh:1338 git-gui.sh:1339 git-gui.sh:1340 git-gui.sh:1341 +#: git-gui.sh:1541 git-gui.sh:1542 git-gui.sh:1543 git-gui.sh:1544 msgid "Requires merge resolution" msgstr "要マージ解決" -#: git-gui.sh:1383 +#: git-gui.sh:1579 msgid "Starting gitk... please wait..." msgstr "gitk を起動中…お待ち下さい…" -#: git-gui.sh:1392 +#: git-gui.sh:1588 #, tcl-format msgid "" "Unable to start gitk:\n" @@ -126,293 +145,332 @@ msgstr "" "\n" "%s がありません" -#: git-gui.sh:1609 -#, tcl-format -msgid "Invalid font specified in gui.%s:" -msgstr "gui.%s に無効なフォントが指定されています:" - -#: git-gui.sh:1634 -msgid "Main Font" -msgstr "主フォント" - -#: git-gui.sh:1635 -msgid "Diff/Console Font" -msgstr "diff/コンソール・フォント" - -#: git-gui.sh:1649 +#: git-gui.sh:1788 lib/choose_repository.tcl:32 msgid "Repository" msgstr "リポジトリ" -#: git-gui.sh:1650 +#: git-gui.sh:1789 msgid "Edit" msgstr "編集" -#: git-gui.sh:1652 +#: git-gui.sh:1791 lib/choose_rev.tcl:560 msgid "Branch" msgstr "ブランチ" -#: git-gui.sh:1655 git-gui.sh:1842 git-gui.sh:2152 -msgid "Commit" +#: git-gui.sh:1794 lib/choose_rev.tcl:547 +#, fuzzy +msgid "Commit@@noun" msgstr "コミット" -#: git-gui.sh:1658 lib/merge.tcl:121 lib/merge.tcl:150 lib/merge.tcl:168 +#: git-gui.sh:1797 lib/merge.tcl:121 lib/merge.tcl:150 lib/merge.tcl:168 msgid "Merge" msgstr "マージ" -#: git-gui.sh:1659 -msgid "Fetch" -msgstr "フェッチ" +#: git-gui.sh:1798 lib/choose_rev.tcl:556 +#, fuzzy +msgid "Remote" +msgstr "リモート:" -#: git-gui.sh:1660 git-gui.sh:2158 lib/transport.tcl:88 lib/transport.tcl:172 -msgid "Push" -msgstr "プッシュ" - -#: git-gui.sh:1669 +#: git-gui.sh:1807 msgid "Browse Current Branch's Files" msgstr "現在のブランチのファイルを見る" -#: git-gui.sh:1673 +#: git-gui.sh:1811 msgid "Browse Branch Files..." msgstr "ブランチのファイルを見る…" -#: git-gui.sh:1678 +#: git-gui.sh:1816 msgid "Visualize Current Branch's History" msgstr "現在のブランチの履歴を見る" -#: git-gui.sh:1682 +#: git-gui.sh:1820 msgid "Visualize All Branch History" msgstr "全てのブランチの履歴を見る" -#: git-gui.sh:1689 +#: git-gui.sh:1827 #, tcl-format msgid "Browse %s's Files" msgstr "ブランチ %s のファイルを見る" -#: git-gui.sh:1691 +#: git-gui.sh:1829 #, tcl-format msgid "Visualize %s's History" msgstr "ブランチ %s の履歴を見る" -#: git-gui.sh:1696 lib/database.tcl:27 lib/database.tcl:67 +#: git-gui.sh:1834 lib/database.tcl:27 lib/database.tcl:67 msgid "Database Statistics" msgstr "データベース統計" -#: git-gui.sh:1699 lib/database.tcl:34 +#: git-gui.sh:1837 lib/database.tcl:34 msgid "Compress Database" msgstr "データベース圧縮" -#: git-gui.sh:1702 +#: git-gui.sh:1840 msgid "Verify Database" msgstr "データベース検証" -#: git-gui.sh:1709 git-gui.sh:1713 git-gui.sh:1717 lib/shortcut.tcl:9 +#: git-gui.sh:1847 git-gui.sh:1851 git-gui.sh:1855 lib/shortcut.tcl:9 #: lib/shortcut.tcl:45 lib/shortcut.tcl:84 msgid "Create Desktop Icon" msgstr "デスクトップ・アイコンを作る" -#: git-gui.sh:1722 +#: git-gui.sh:1860 lib/choose_repository.tcl:36 lib/choose_repository.tcl:95 msgid "Quit" msgstr "終了" -#: git-gui.sh:1729 +#: git-gui.sh:1867 msgid "Undo" msgstr "元に戻す" -#: git-gui.sh:1732 +#: git-gui.sh:1870 msgid "Redo" msgstr "やり直し" -#: git-gui.sh:1736 git-gui.sh:2222 +#: git-gui.sh:1874 git-gui.sh:2366 msgid "Cut" msgstr "切り取り" -#: git-gui.sh:1739 git-gui.sh:2225 git-gui.sh:2296 git-gui.sh:2368 -#: lib/console.tcl:69 +#: git-gui.sh:1877 git-gui.sh:2369 git-gui.sh:2440 git-gui.sh:2512 +#: lib/console.tcl:67 msgid "Copy" msgstr "コピー" -#: git-gui.sh:1742 git-gui.sh:2228 +#: git-gui.sh:1880 git-gui.sh:2372 msgid "Paste" msgstr "貼り付け" -#: git-gui.sh:1745 git-gui.sh:2231 lib/branch_delete.tcl:26 +#: git-gui.sh:1883 git-gui.sh:2375 lib/branch_delete.tcl:26 #: lib/remote_branch_delete.tcl:38 msgid "Delete" msgstr "削除" -#: git-gui.sh:1749 git-gui.sh:2235 git-gui.sh:2372 lib/console.tcl:71 +#: git-gui.sh:1887 git-gui.sh:2379 git-gui.sh:2516 lib/console.tcl:69 msgid "Select All" msgstr "全て選択" -#: git-gui.sh:1758 +#: git-gui.sh:1896 msgid "Create..." msgstr "作成…" -#: git-gui.sh:1764 +#: git-gui.sh:1902 msgid "Checkout..." msgstr "チェックアウト" -#: git-gui.sh:1770 +#: git-gui.sh:1908 msgid "Rename..." msgstr "名前変更…" -#: git-gui.sh:1775 git-gui.sh:1873 +#: git-gui.sh:1913 git-gui.sh:2012 msgid "Delete..." msgstr "削除…" -#: git-gui.sh:1780 +#: git-gui.sh:1918 msgid "Reset..." msgstr "リセット…" -#: git-gui.sh:1792 git-gui.sh:2169 +#: git-gui.sh:1930 git-gui.sh:2313 msgid "New Commit" msgstr "新規コミット" -#: git-gui.sh:1800 git-gui.sh:2176 +#: git-gui.sh:1938 git-gui.sh:2320 msgid "Amend Last Commit" msgstr "最新コミットを訂正" -#: git-gui.sh:1809 git-gui.sh:2136 lib/remote_branch_delete.tcl:99 +#: git-gui.sh:1947 git-gui.sh:2280 lib/remote_branch_delete.tcl:99 msgid "Rescan" msgstr "再スキャン" -#: git-gui.sh:1815 +#: git-gui.sh:1953 msgid "Stage To Commit" msgstr "コミット予定する" -#: git-gui.sh:1820 +#: git-gui.sh:1958 msgid "Stage Changed Files To Commit" msgstr "変更されたファイルをコミット予定" -#: git-gui.sh:1826 +#: git-gui.sh:1964 msgid "Unstage From Commit" msgstr "コミットから降ろす" -#: git-gui.sh:1831 lib/index.tcl:376 +#: git-gui.sh:1969 lib/index.tcl:352 msgid "Revert Changes" msgstr "変更を元に戻す" -#: git-gui.sh:1838 git-gui.sh:2148 git-gui.sh:2246 +#: git-gui.sh:1976 git-gui.sh:2292 git-gui.sh:2390 msgid "Sign Off" msgstr "署名" -#: git-gui.sh:1853 +#: git-gui.sh:1980 git-gui.sh:2296 +#, fuzzy +msgid "Commit@@verb" +msgstr "コミット" + +#: git-gui.sh:1991 msgid "Local Merge..." msgstr "ローカル・マージ…" -#: git-gui.sh:1858 +#: git-gui.sh:1996 msgid "Abort Merge..." msgstr "マージ中止…" -#: git-gui.sh:1870 +#: git-gui.sh:2008 msgid "Push..." msgstr "プッシュ…" -#: git-gui.sh:1880 +#: git-gui.sh:2019 lib/choose_repository.tcl:41 msgid "Apple" msgstr "りんご" -#: git-gui.sh:1883 git-gui.sh:1901 lib/option.tcl:65 +#: git-gui.sh:2022 git-gui.sh:2044 lib/about.tcl:13 +#: lib/choose_repository.tcl:44 lib/choose_repository.tcl:50 #, tcl-format msgid "About %s" msgstr "%s について" -#: git-gui.sh:1885 git-gui.sh:1891 git-gui.sh:2414 +#: git-gui.sh:2026 +msgid "Preferences..." +msgstr "" + +#: git-gui.sh:2034 git-gui.sh:2558 msgid "Options..." msgstr "オプション…" -#: git-gui.sh:1897 +#: git-gui.sh:2040 lib/choose_repository.tcl:47 msgid "Help" msgstr "ヘルプ" -#: git-gui.sh:1938 +#: git-gui.sh:2081 msgid "Online Documentation" msgstr "オンライン・ドキュメント" -#: git-gui.sh:2054 +#: git-gui.sh:2165 +#, tcl-format +msgid "fatal: cannot stat path %s: No such file or directory" +msgstr "" + +#: git-gui.sh:2198 msgid "Current Branch:" msgstr "現在のブランチ" -#: git-gui.sh:2075 -msgid "Staged Changes (Will Be Committed)" +#: git-gui.sh:2219 +#, fuzzy +msgid "Staged Changes (Will Commit)" msgstr "ステージングされた(コミット予定済の)変更" -#: git-gui.sh:2095 -msgid "Unstaged Changes (Will Not Be Committed)" -msgstr "ステージングされていない(コミット未予定の)変更" +#: git-gui.sh:2239 +#, fuzzy +msgid "Unstaged Changes" +msgstr "変更をコミット予定に入れる" -#: git-gui.sh:2142 +#: git-gui.sh:2286 msgid "Stage Changed" msgstr "変更をコミット予定に入れる" -#: git-gui.sh:2188 +#: git-gui.sh:2302 lib/transport.tcl:93 lib/transport.tcl:182 +msgid "Push" +msgstr "プッシュ" + +#: git-gui.sh:2332 msgid "Initial Commit Message:" msgstr "最初のコミットメッセージ:" -#: git-gui.sh:2189 +#: git-gui.sh:2333 msgid "Amended Commit Message:" msgstr "訂正したコミットメッセージ:" -#: git-gui.sh:2190 +#: git-gui.sh:2334 msgid "Amended Initial Commit Message:" msgstr "訂正した最初のコミットメッセージ:" -#: git-gui.sh:2191 +#: git-gui.sh:2335 msgid "Amended Merge Commit Message:" msgstr "訂正したマージコミットメッセージ:" -#: git-gui.sh:2192 +#: git-gui.sh:2336 msgid "Merge Commit Message:" msgstr "マージコミットメッセージ:" -#: git-gui.sh:2193 +#: git-gui.sh:2337 msgid "Commit Message:" msgstr "コミットメッセージ:" -#: git-gui.sh:2238 git-gui.sh:2376 lib/console.tcl:73 +#: git-gui.sh:2382 git-gui.sh:2520 lib/console.tcl:71 msgid "Copy All" msgstr "全てコピー" -#: git-gui.sh:2262 lib/blame.tcl:104 +#: git-gui.sh:2406 lib/blame.tcl:104 msgid "File:" msgstr "ファイル:" -#: git-gui.sh:2364 +#: git-gui.sh:2508 msgid "Refresh" msgstr "再読み込み" -#: git-gui.sh:2385 +#: git-gui.sh:2529 msgid "Apply/Reverse Hunk" msgstr "パッチを適用/取り消す" -#: git-gui.sh:2391 +#: git-gui.sh:2535 msgid "Decrease Font Size" msgstr "フォントを小さく" -#: git-gui.sh:2395 +#: git-gui.sh:2539 msgid "Increase Font Size" msgstr "フォントを大きく" -#: git-gui.sh:2400 +#: git-gui.sh:2544 msgid "Show Less Context" msgstr "文脈を少なく" -#: git-gui.sh:2407 +#: git-gui.sh:2551 msgid "Show More Context" msgstr "文脈を多く" -#: git-gui.sh:2422 +#: git-gui.sh:2565 msgid "Unstage Hunk From Commit" msgstr "パッチをコミット予定から外す" -#: git-gui.sh:2426 git-gui.sh:2430 +#: git-gui.sh:2567 msgid "Stage Hunk For Commit" msgstr "パッチをコミット予定に加える" -#: git-gui.sh:2440 +#: git-gui.sh:2586 msgid "Initializing..." msgstr "初期化しています…" +#: git-gui.sh:2677 +#, tcl-format +msgid "" +"Possible environment issues exist.\n" +"\n" +"The following environment variables are probably\n" +"going to be ignored by any Git subprocess run\n" +"by %s:\n" +"\n" +msgstr "" + +#: git-gui.sh:2707 +msgid "" +"\n" +"This is due to a known issue with the\n" +"Tcl binary distributed by Cygwin." +msgstr "" + +#: git-gui.sh:2712 +#, tcl-format +msgid "" +"\n" +"\n" +"A good replacement for %s\n" +"is placing values for the user.name and\n" +"user.email settings into your personal\n" +"~/.gitconfig file.\n" +msgstr "" + +#: lib/about.tcl:25 +msgid "git-gui - a graphical user interface for Git." +msgstr "Git のグラフィカルUI git-gui" + #: lib/blame.tcl:77 msgid "File Viewer" msgstr "ファイルピューワ" @@ -430,6 +488,53 @@ msgstr "コミットをコピー" msgid "Reading %s..." msgstr "%s を読んでいます…" +#: lib/blame.tcl:473 +msgid "Loading copy/move tracking annotations..." +msgstr "" + +#: lib/blame.tcl:493 +msgid "lines annotated" +msgstr "" + +#: lib/blame.tcl:674 +msgid "Loading original location annotations..." +msgstr "" + +#: lib/blame.tcl:677 +msgid "Annotation complete." +msgstr "" + +#: lib/blame.tcl:731 +#, fuzzy +msgid "Loading annotation..." +msgstr "%s をロード中…" + +#: lib/blame.tcl:787 +msgid "Author:" +msgstr "" + +#: lib/blame.tcl:791 +#, fuzzy +msgid "Committer:" +msgstr "コミット:" + +#: lib/blame.tcl:796 +msgid "Original File:" +msgstr "" + +#: lib/blame.tcl:910 +msgid "Originally By:" +msgstr "" + +#: lib/blame.tcl:916 +#, fuzzy +msgid "In File:" +msgstr "ファイル:" + +#: lib/blame.tcl:921 +msgid "Copied Or Moved Here By:" +msgstr "" + #: lib/branch_checkout.tcl:14 lib/branch_checkout.tcl:19 msgid "Checkout Branch" msgstr "ブランチをチェックアウト" @@ -439,18 +544,17 @@ msgid "Checkout" msgstr "チェックアウト" #: lib/branch_checkout.tcl:27 lib/branch_create.tcl:35 -#: lib/branch_delete.tcl:32 lib/branch_rename.tcl:30 lib/browser.tcl:283 -#: lib/checkout_op.tcl:522 lib/merge.tcl:172 lib/option.tcl:172 -#: lib/remote_branch_delete.tcl:42 lib/transport.tcl:92 +#: lib/branch_delete.tcl:32 lib/branch_rename.tcl:30 lib/browser.tcl:281 +#: lib/checkout_op.tcl:522 lib/choose_font.tcl:43 lib/merge.tcl:172 +#: lib/option.tcl:90 lib/remote_branch_delete.tcl:42 lib/transport.tcl:97 msgid "Cancel" msgstr "中止" -#: lib/branch_checkout.tcl:32 lib/browser.tcl:288 +#: lib/branch_checkout.tcl:32 lib/browser.tcl:286 msgid "Revision" msgstr "リビジョン" -#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:159 -#: lib/option.tcl:274 +#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:202 msgid "Options" msgstr "オプション" @@ -470,7 +574,7 @@ msgstr "ブランチを作成" msgid "Create New Branch" msgstr "ブランチを新規作成" -#: lib/branch_create.tcl:31 +#: lib/branch_create.tcl:31 lib/choose_repository.tcl:199 msgid "Create" msgstr "作成" @@ -610,20 +714,22 @@ msgstr "起動中…" msgid "File Browser" msgstr "ファイル・ブラウザ" -#: lib/browser.tcl:127 lib/browser.tcl:144 +#: lib/browser.tcl:125 lib/browser.tcl:142 #, tcl-format msgid "Loading %s..." msgstr "%s をロード中…" -#: lib/browser.tcl:188 +#: lib/browser.tcl:186 msgid "[Up To Parent]" msgstr "[上位フォルダへ]" -#: lib/browser.tcl:268 lib/browser.tcl:274 +#: lib/browser.tcl:266 lib/browser.tcl:272 msgid "Browse Branch Files" msgstr "現在のブランチのファイルを見る" -#: lib/browser.tcl:279 +#: lib/browser.tcl:277 lib/choose_repository.tcl:215 +#: lib/choose_repository.tcl:305 lib/choose_repository.tcl:315 +#: lib/choose_repository.tcl:811 msgid "Browse" msgstr "ブラウズ" @@ -632,7 +738,12 @@ msgstr "ブラウズ" msgid "Fetching %s from %s" msgstr "%s から %s をフェッチしています" -#: lib/checkout_op.tcl:140 lib/console.tcl:81 lib/database.tcl:31 +#: lib/checkout_op.tcl:127 +#, tcl-format +msgid "fatal: Cannot resolve %s" +msgstr "" + +#: lib/checkout_op.tcl:140 lib/console.tcl:79 lib/database.tcl:31 msgid "Close" msgstr "閉じる" @@ -684,6 +795,11 @@ msgstr "" "\n" "自動的に再スキャンを開始します。\n" +#: lib/checkout_op.tcl:322 +#, fuzzy, tcl-format +msgid "Updating working directory to '%s'..." +msgstr "作業ディレクトリがありません" + #: lib/checkout_op.tcl:353 #, tcl-format msgid "Aborted checkout of '%s' (file level merging is required)." @@ -710,6 +826,11 @@ msgstr "" "ブランチ上に滞まりたいときは、この「分離されたチェックアウト」から新規ブラン" "チを開始してください。" +#: lib/checkout_op.tcl:446 +#, fuzzy, tcl-format +msgid "Checked out '%s'." +msgstr "チェックアウト" + #: lib/checkout_op.tcl:478 #, tcl-format msgid "Resetting '%s' to '%s' will lose the following commits:" @@ -744,6 +865,246 @@ msgstr "" "ましたが、 Git の内部データを更新できませんでした。\n" "起こるはずのないエラーです。あきらめて %s を終了します。" +#: lib/choose_font.tcl:39 +#, fuzzy +msgid "Select" +msgstr "全て選択" + +#: lib/choose_font.tcl:53 +msgid "Font Family" +msgstr "" + +#: lib/choose_font.tcl:73 +#, fuzzy +msgid "Font Size" +msgstr "フォントを小さく" + +#: lib/choose_font.tcl:90 +msgid "Font Example" +msgstr "" + +#: lib/choose_font.tcl:101 +msgid "" +"This is example text.\n" +"If you like this text, it can be your font." +msgstr "" + +#: lib/choose_repository.tcl:25 +msgid "Git Gui" +msgstr "" + +#: lib/choose_repository.tcl:69 lib/choose_repository.tcl:204 +#, fuzzy +msgid "Create New Repository" +msgstr "元のリポジトリ" + +#: lib/choose_repository.tcl:74 lib/choose_repository.tcl:291 +#, fuzzy +msgid "Clone Existing Repository" +msgstr "送り先リポジトリ" + +#: lib/choose_repository.tcl:79 lib/choose_repository.tcl:800 +#, fuzzy +msgid "Open Existing Repository" +msgstr "送り先リポジトリ" + +#: lib/choose_repository.tcl:91 +msgid "Next >" +msgstr "" + +#: lib/choose_repository.tcl:152 +#, fuzzy, tcl-format +msgid "Location %s already exists." +msgstr "'%s'というブランチは既に存在します。" + +#: lib/choose_repository.tcl:158 lib/choose_repository.tcl:165 +#: lib/choose_repository.tcl:172 +#, fuzzy, tcl-format +msgid "Failed to create repository %s:" +msgstr "完全にオプションを保存できません:" + +#: lib/choose_repository.tcl:209 lib/choose_repository.tcl:309 +msgid "Directory:" +msgstr "" + +#: lib/choose_repository.tcl:238 lib/choose_repository.tcl:363 +#: lib/choose_repository.tcl:834 +#, fuzzy +msgid "Git Repository" +msgstr "リポジトリ" + +#: lib/choose_repository.tcl:253 lib/choose_repository.tcl:260 +#, fuzzy, tcl-format +msgid "Directory %s already exists." +msgstr "'%s'というブランチは既に存在します。" + +#: lib/choose_repository.tcl:265 +#, fuzzy, tcl-format +msgid "File %s already exists." +msgstr "'%s'というブランチは既に存在します。" + +#: lib/choose_repository.tcl:286 +#, fuzzy +msgid "Clone" +msgstr "閉じる" + +#: lib/choose_repository.tcl:299 +msgid "URL:" +msgstr "" + +#: lib/choose_repository.tcl:319 +msgid "Clone Type:" +msgstr "" + +#: lib/choose_repository.tcl:325 +msgid "Standard (Fast, Semi-Redundant, Hardlinks)" +msgstr "" + +#: lib/choose_repository.tcl:331 +msgid "Full Copy (Slower, Redundant Backup)" +msgstr "" + +#: lib/choose_repository.tcl:337 +msgid "Shared (Fastest, Not Recommended, No Backup)" +msgstr "" + +#: lib/choose_repository.tcl:369 lib/choose_repository.tcl:418 +#: lib/choose_repository.tcl:560 lib/choose_repository.tcl:630 +#: lib/choose_repository.tcl:840 lib/choose_repository.tcl:848 +#, fuzzy, tcl-format +msgid "Not a Git repository: %s" +msgstr "リポジトリが選択されていません。" + +#: lib/choose_repository.tcl:405 +msgid "Standard only available for local repository." +msgstr "" + +#: lib/choose_repository.tcl:409 +msgid "Shared only available for local repository." +msgstr "" + +#: lib/choose_repository.tcl:439 +msgid "Failed to configure origin" +msgstr "" + +#: lib/choose_repository.tcl:451 +msgid "Counting objects" +msgstr "" + +#: lib/choose_repository.tcl:452 +msgid "buckets" +msgstr "" + +#: lib/choose_repository.tcl:476 +#, tcl-format +msgid "Unable to copy objects/info/alternates: %s" +msgstr "" + +#: lib/choose_repository.tcl:512 +#, fuzzy, tcl-format +msgid "Nothing to clone from %s." +msgstr "%s から新しい変更をフェッチしています" + +#: lib/choose_repository.tcl:514 lib/choose_repository.tcl:728 +#: lib/choose_repository.tcl:740 +msgid "The 'master' branch has not been initialized." +msgstr "" + +#: lib/choose_repository.tcl:527 +msgid "Hardlinks are unavailable. Falling back to copying." +msgstr "" + +#: lib/choose_repository.tcl:539 +#, fuzzy, tcl-format +msgid "Cloning from %s" +msgstr "%s から %s をフェッチしています" + +#: lib/choose_repository.tcl:570 +#, fuzzy +msgid "Copying objects" +msgstr "データベース圧縮" + +#: lib/choose_repository.tcl:571 +msgid "KiB" +msgstr "" + +#: lib/choose_repository.tcl:595 +#, tcl-format +msgid "Unable to copy object: %s" +msgstr "" + +#: lib/choose_repository.tcl:605 +msgid "Linking objects" +msgstr "" + +#: lib/choose_repository.tcl:606 +msgid "objects" +msgstr "" + +#: lib/choose_repository.tcl:614 +#, tcl-format +msgid "Unable to hardlink object: %s" +msgstr "" + +#: lib/choose_repository.tcl:669 +msgid "Cannot fetch branches and objects. See console output for details." +msgstr "" + +#: lib/choose_repository.tcl:680 +msgid "Cannot fetch tags. See console output for details." +msgstr "" + +#: lib/choose_repository.tcl:704 +msgid "Cannot determine HEAD. See console output for details." +msgstr "" + +#: lib/choose_repository.tcl:713 +#, tcl-format +msgid "Unable to cleanup %s" +msgstr "" + +#: lib/choose_repository.tcl:719 +#, fuzzy +msgid "Clone failed." +msgstr "中断に失敗しました。" + +#: lib/choose_repository.tcl:726 +msgid "No default branch obtained." +msgstr "" + +#: lib/choose_repository.tcl:737 +#, tcl-format +msgid "Cannot resolve %s as a commit." +msgstr "" + +#: lib/choose_repository.tcl:749 +#, fuzzy +msgid "Creating working directory" +msgstr "作業ディレクトリがありません" + +#: lib/choose_repository.tcl:750 lib/index.tcl:15 lib/index.tcl:80 +#: lib/index.tcl:149 +msgid "files" +msgstr "" + +#: lib/choose_repository.tcl:779 +msgid "Initial file checkout failed." +msgstr "" + +#: lib/choose_repository.tcl:795 +msgid "Open" +msgstr "" + +#: lib/choose_repository.tcl:805 +#, fuzzy +msgid "Repository:" +msgstr "リポジトリ" + +#: lib/choose_repository.tcl:854 +#, fuzzy, tcl-format +msgid "Failed to open repository %s:" +msgstr "完全にオプションを保存できません:" + #: lib/choose_rev.tcl:53 msgid "This Detached Checkout" msgstr "分離されたチェックアウト" @@ -760,7 +1121,7 @@ msgstr "ローカル・ブランチ" msgid "Tracking Branch" msgstr "トラッキング・ブランチ" -#: lib/choose_rev.tcl:84 +#: lib/choose_rev.tcl:84 lib/choose_rev.tcl:537 msgid "Tag" msgstr "タグ" @@ -777,6 +1138,14 @@ msgstr "リビジョンが未選択です。" msgid "Revision expression is empty." msgstr "リビジョン式が空です。" +#: lib/choose_rev.tcl:530 +msgid "Updated" +msgstr "" + +#: lib/choose_rev.tcl:558 +msgid "URL" +msgstr "" + #: lib/commit.tcl:9 msgid "" "There is nothing to amend.\n" @@ -886,6 +1255,11 @@ msgstr "" msgid "write-tree failed:" msgstr "write-tree が失敗しました:" +#: lib/commit.tcl:275 +#, tcl-format +msgid "Commit %s appears to be corrupt" +msgstr "" + #: lib/commit.tcl:279 msgid "" "No changes to commit.\n" @@ -904,6 +1278,11 @@ msgstr "" msgid "No changes to commit." msgstr "コミットする変更がありません。" +#: lib/commit.tcl:303 +#, tcl-format +msgid "warning: Tcl does not support encoding '%s'." +msgstr "" + #: lib/commit.tcl:317 msgid "commit-tree failed:" msgstr "commit-tree が失敗しました:" @@ -917,15 +1296,15 @@ msgstr "update-ref が失敗しました:" msgid "Created commit %s: %s" msgstr "コミット %s を作成しました: %s" -#: lib/console.tcl:55 +#: lib/console.tcl:57 msgid "Working... please wait..." msgstr "実行中…お待ち下さい…" -#: lib/console.tcl:184 +#: lib/console.tcl:183 msgid "Success" msgstr "成功" -#: lib/console.tcl:194 +#: lib/console.tcl:196 msgid "Error: Command Failed" msgstr "エラー: コマンドが失敗しました" @@ -965,6 +1344,22 @@ msgstr "データベース圧縮" msgid "Verifying the object database with fsck-objects" msgstr "fsck-objects でオブジェクト・データベースを検証しています" +#: lib/database.tcl:108 +#, tcl-format +msgid "" +"This repository currently has approximately %i loose objects.\n" +"\n" +"To maintain optimal performance it is strongly recommended that you compress " +"the database when more than %i loose objects exist.\n" +"\n" +"Compress the database now?" +msgstr "" + +#: lib/date.tcl:25 +#, fuzzy, tcl-format +msgid "Invalid date from Git: %s" +msgstr "無効なリビジョン: %s" + #: lib/diff.tcl:42 #, tcl-format msgid "" @@ -987,19 +1382,37 @@ msgstr "" "\n" "同様な状態のファイルを探すために、自動的に再スキャンを開始します。" -#: lib/diff.tcl:97 +#: lib/diff.tcl:81 +#, fuzzy, tcl-format +msgid "Loading diff of %s..." +msgstr "%s をロード中…" + +#: lib/diff.tcl:114 lib/diff.tcl:184 +#, tcl-format +msgid "Unable to display %s" +msgstr "" + +#: lib/diff.tcl:115 msgid "Error loading file:" msgstr "ファイルを読む際のエラーです:" -#: lib/diff.tcl:162 +#: lib/diff.tcl:122 +msgid "Git Repository (subproject)" +msgstr "" + +#: lib/diff.tcl:134 +msgid "* Binary file (not showing content)." +msgstr "" + +#: lib/diff.tcl:185 msgid "Error loading diff:" msgstr "diff を読む際のエラーです:" -#: lib/diff.tcl:278 +#: lib/diff.tcl:302 msgid "Failed to unstage selected hunk." msgstr "選択されたパッチをコミット予定から外せません。" -#: lib/diff.tcl:285 +#: lib/diff.tcl:309 msgid "Failed to stage selected hunk." msgstr "選択されたパッチをコミット予定に加えられません。" @@ -1015,21 +1428,31 @@ msgstr "警告" msgid "You must correct the above errors before committing." msgstr "コミットする前に、以上のエラーを修正して下さい" -#: lib/index.tcl:364 +#: lib/index.tcl:241 +#, fuzzy, tcl-format +msgid "Unstaging %s from commit" +msgstr "コミットから降ろす" + +#: lib/index.tcl:285 +#, fuzzy, tcl-format +msgid "Adding %s" +msgstr "%s を読んでいます…" + +#: lib/index.tcl:340 #, tcl-format msgid "Revert changes in file %s?" msgstr "ファイル %s にした変更を元に戻しますか?" -#: lib/index.tcl:366 +#: lib/index.tcl:342 #, tcl-format msgid "Revert changes in these %i files?" msgstr "これら %i 個のファイルにした変更を元に戻しますか?" -#: lib/index.tcl:372 +#: lib/index.tcl:348 msgid "Any unstaged changes will be permanently lost by the revert." msgstr "変更を元に戻すとコミット予定していない変更は全て失われます。" -#: lib/index.tcl:375 +#: lib/index.tcl:351 msgid "Do Nothing" msgstr "何もしない" @@ -1170,71 +1593,100 @@ msgstr "中断に失敗しました。" msgid "Abort completed. Ready." msgstr "中断完了。" -#: lib/option.tcl:77 -msgid "git-gui - a graphical user interface for Git." -msgstr "Git のグラフィカルUI git-gui" - -#: lib/option.tcl:164 +#: lib/option.tcl:82 msgid "Restore Defaults" msgstr "既定値に戻す" -#: lib/option.tcl:168 +#: lib/option.tcl:86 msgid "Save" msgstr "保存" -#: lib/option.tcl:178 +#: lib/option.tcl:96 #, tcl-format msgid "%s Repository" msgstr "%s リポジトリ" -#: lib/option.tcl:179 +#: lib/option.tcl:97 msgid "Global (All Repositories)" msgstr "大域(全てのリポジトリ)" -#: lib/option.tcl:185 +#: lib/option.tcl:103 msgid "User Name" msgstr "ユーザ名" -#: lib/option.tcl:186 +#: lib/option.tcl:104 msgid "Email Address" msgstr "電子メールアドレス" -#: lib/option.tcl:188 +#: lib/option.tcl:106 msgid "Summarize Merge Commits" msgstr "マージコミットの要約" -#: lib/option.tcl:189 +#: lib/option.tcl:107 msgid "Merge Verbosity" msgstr "マージの冗長度" -#: lib/option.tcl:190 +#: lib/option.tcl:108 msgid "Show Diffstat After Merge" msgstr "マージ後に diffstat を表示" -#: lib/option.tcl:192 +#: lib/option.tcl:110 msgid "Trust File Modification Timestamps" msgstr "ファイル変更時刻を信頼する" -#: lib/option.tcl:193 +#: lib/option.tcl:111 msgid "Prune Tracking Branches During Fetch" msgstr "フェッチ中にトラッキングブランチを刈る" -#: lib/option.tcl:194 +#: lib/option.tcl:112 msgid "Match Tracking Branches" msgstr "トラッキングブランチを合わせる" -#: lib/option.tcl:195 +#: lib/option.tcl:113 msgid "Number of Diff Context Lines" msgstr "diff の文脈行数" -#: lib/option.tcl:196 +#: lib/option.tcl:114 msgid "New Branch Name Template" msgstr "新しいブランチ名のテンプレート" -#: lib/option.tcl:305 +#: lib/option.tcl:176 +#, fuzzy +msgid "Change Font" +msgstr "主フォント" + +#: lib/option.tcl:180 +#, tcl-format +msgid "Choose %s" +msgstr "" + +#: lib/option.tcl:186 +msgid "pt." +msgstr "" + +#: lib/option.tcl:200 +msgid "Preferences" +msgstr "" + +#: lib/option.tcl:235 msgid "Failed to completely save options:" msgstr "完全にオプションを保存できません:" +#: lib/remote.tcl:165 +#, fuzzy +msgid "Prune from" +msgstr "%s から刈る…" + +#: lib/remote.tcl:170 +#, fuzzy +msgid "Fetch from" +msgstr "%s からフェッチ…" + +#: lib/remote.tcl:213 +#, fuzzy +msgid "Push to" +msgstr "プッシュ" + #: lib/remote_branch_delete.tcl:29 lib/remote_branch_delete.tcl:34 msgid "Delete Remote Branch" msgstr "リモート・ブランチを削除" @@ -1243,11 +1695,11 @@ msgstr "リモート・ブランチを削除" msgid "From Repository" msgstr "元のリポジトリ" -#: lib/remote_branch_delete.tcl:50 lib/transport.tcl:118 +#: lib/remote_branch_delete.tcl:50 lib/transport.tcl:123 msgid "Remote:" msgstr "リモート:" -#: lib/remote_branch_delete.tcl:66 lib/transport.tcl:133 +#: lib/remote_branch_delete.tcl:66 lib/transport.tcl:138 msgid "Arbitrary URL:" msgstr "任意の URL:" @@ -1271,6 +1723,14 @@ msgstr "無条件(マージ検査をしない)" msgid "A branch is required for 'Merged Into'." msgstr "'マージ先' にはブランチが必要です。" +#: lib/remote_branch_delete.tcl:184 +#, fuzzy, tcl-format +msgid "" +"The following branches are not completely merged into %s:\n" +"\n" +" - %s" +msgstr "以下のブランチは %s に完全にマージされていません:" + #: lib/remote_branch_delete.tcl:189 #, tcl-format msgid "" @@ -1308,21 +1768,6 @@ msgstr "リポジトリが選択されていません。" msgid "Scanning %s..." msgstr "%s をスキャンしています…" -#: lib/remote.tcl:162 -#, tcl-format -msgid "Fetch from %s..." -msgstr "%s からフェッチ…" - -#: lib/remote.tcl:172 -#, tcl-format -msgid "Prune from %s..." -msgstr "%s から刈る…" - -#: lib/remote.tcl:206 -#, tcl-format -msgid "Push to %s..." -msgstr "%s へプッシュ…" - #: lib/shortcut.tcl:26 lib/shortcut.tcl:74 msgid "Cannot write script:" msgstr "スクリプトが書けません:" @@ -1331,51 +1776,79 @@ msgstr "スクリプトが書けません:" msgid "Cannot write icon:" msgstr "アイコンが書けません:" -#: lib/status_bar.tcl:58 +#: lib/status_bar.tcl:83 #, tcl-format msgid "%s ... %*i of %*i %s (%3i%%)" msgstr "%1$s ... %3$*i %4$s 中の %$2*i (%5$3i%%)" +#: lib/transport.tcl:6 +#, fuzzy, tcl-format +msgid "fetch %s" +msgstr "フェッチ" + #: lib/transport.tcl:7 #, tcl-format msgid "Fetching new changes from %s" msgstr "%s から新しい変更をフェッチしています" +#: lib/transport.tcl:18 +#, tcl-format +msgid "remote prune %s" +msgstr "" + #: lib/transport.tcl:19 #, tcl-format msgid "Pruning tracking branches deleted from %s" msgstr "%s から削除されたトラッキング・ブランチを刈っています" +#: lib/transport.tcl:25 lib/transport.tcl:71 +#, tcl-format +msgid "push %s" +msgstr "" + #: lib/transport.tcl:26 #, tcl-format msgid "Pushing changes to %s" msgstr "%s へ変更をプッシュしています" -#: lib/transport.tcl:68 +#: lib/transport.tcl:72 #, tcl-format msgid "Pushing %s %s to %s" msgstr "%3$s へ %1$s %2$s をプッシュしています" -#: lib/transport.tcl:84 +#: lib/transport.tcl:89 msgid "Push Branches" msgstr "ブランチをプッシュ" -#: lib/transport.tcl:98 +#: lib/transport.tcl:103 msgid "Source Branches" msgstr "元のブランチ" -#: lib/transport.tcl:115 +#: lib/transport.tcl:120 msgid "Destination Repository" msgstr "送り先リポジトリ" -#: lib/transport.tcl:153 +#: lib/transport.tcl:158 msgid "Transfer Options" msgstr "通信オプション" -#: lib/transport.tcl:155 +#: lib/transport.tcl:160 +msgid "Force overwrite existing branch (may discard changes)" +msgstr "" + +#: lib/transport.tcl:164 msgid "Use thin pack (for slow network connections)" msgstr "Thin Pack を使う(遅いネットワーク接続)" -#: lib/transport.tcl:159 +#: lib/transport.tcl:168 msgid "Include tags" msgstr "タグを含める" + +#~ msgid "Cannot find the git directory:" +#~ msgstr "git ディレクトリが見つかりません:" + +#~ msgid "Unstaged Changes (Will Not Be Committed)" +#~ msgstr "ステージングされていない(コミット未予定の)変更" + +#~ msgid "Push to %s..." +#~ msgstr "%s へプッシュ…" diff --git a/po/ru.po b/po/ru.po index 20080338c8..3beaf9d52e 100644 --- a/po/ru.po +++ b/po/ru.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: git-gui\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2007-07-27 19:33+0200\n" +"POT-Creation-Date: 2007-10-10 04:04-0400\n" "PO-Revision-Date: 2007-07-28 18:30+0200\n" "Last-Translator: Irina Riesen \n" "Language-Team: Russian Translation \n" @@ -15,16 +15,33 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: git-gui.sh:531 +#: git-gui.sh:41 git-gui.sh:634 git-gui.sh:648 git-gui.sh:661 git-gui.sh:744 +#: git-gui.sh:763 +msgid "git-gui: fatal error" +msgstr "" + +#: git-gui.sh:595 +#, fuzzy, tcl-format +msgid "Invalid font specified in %s:" +msgstr "В оболочке установлен неверный шрифт.%s:" + +#: git-gui.sh:620 +msgid "Main Font" +msgstr "Шрифт интерфейса" + +#: git-gui.sh:621 +msgid "Diff/Console Font" +msgstr "Шрифт в консоли diff" + +#: git-gui.sh:635 msgid "Cannot find git in PATH." msgstr "git не найден в PATH." -#: git-gui.sh:550 +#: git-gui.sh:662 msgid "Cannot parse Git version string:" -msgstr "" -"Невозможно распознать строку версии Git: " +msgstr "Невозможно распознать строку версии Git: " -#: git-gui.sh:567 +#: git-gui.sh:680 #, tcl-format msgid "" "Git version cannot be determined.\n" @@ -36,85 +53,81 @@ msgid "" "Assume '%s' is version 1.5.0?\n" msgstr "" -#: git-gui.sh:689 -msgid "Cannot find the git directory:" -msgstr "Каталог Git не найден:" - -#: git-gui.sh:697 +#: git-gui.sh:853 msgid "Git directory not found:" msgstr "Каталог Git не найден:" -#: git-gui.sh:703 +#: git-gui.sh:860 +#, fuzzy +msgid "Cannot move to top of working directory:" +msgstr "Каталог.git испорчен: " + +#: git-gui.sh:867 msgid "Cannot use funny .git directory:" msgstr "Каталог.git испорчен: " -#: git-gui.sh:708 +#: git-gui.sh:872 msgid "No working directory" msgstr "Отсутствует рабочий каталог" -#: git-gui.sh:853 +#: git-gui.sh:1019 msgid "Refreshing file status..." msgstr "Обновление состояния файлов проекта..." -#: git-gui.sh:886 +#: git-gui.sh:1084 msgid "Scanning for modified files ..." msgstr "Поиск измененных файлов..." -#: git-gui.sh:1052 lib/browser.tcl:233 +#: git-gui.sh:1259 lib/browser.tcl:245 msgid "Ready." msgstr "Готово." -#: git-gui.sh:1343 +#: git-gui.sh:1525 msgid "Unmodified" msgstr "Не изменено" -#: git-gui.sh:1345 +#: git-gui.sh:1527 msgid "Modified, not staged" msgstr "Изменено, но не включено" -#: git-gui.sh:1346 git-gui.sh:1351 +#: git-gui.sh:1528 git-gui.sh:1533 msgid "Staged for commit" msgstr "Подготовлено для сохранения" -#: git-gui.sh:1347 git-gui.sh:1352 +#: git-gui.sh:1529 git-gui.sh:1534 msgid "Portions staged for commit" msgstr "Части, подготовленные для сохранения" -#: git-gui.sh:1348 git-gui.sh:1353 +#: git-gui.sh:1530 git-gui.sh:1535 #, fuzzy msgid "Staged for commit, missing" -msgstr "" -"Подготовлено для сохранения, отсутствует" +msgstr "Подготовлено для сохранения, отсутствует" -#: git-gui.sh:1350 +#: git-gui.sh:1532 msgid "Untracked, not staged" msgstr "Не отслеживается, не подготовлено" -#: git-gui.sh:1355 +#: git-gui.sh:1537 msgid "Missing" msgstr "Отсутствует" -#: git-gui.sh:1356 +#: git-gui.sh:1538 msgid "Staged for removal" msgstr "Подготовлено для удаления" -#: git-gui.sh:1357 +#: git-gui.sh:1539 msgid "Staged for removal, still present" -msgstr "" -"Подготовлено для удаления, но еще не " -"удалено" +msgstr "Подготовлено для удаления, но еще не удалено" -#: git-gui.sh:1359 git-gui.sh:1360 git-gui.sh:1361 git-gui.sh:1362 +#: git-gui.sh:1541 git-gui.sh:1542 git-gui.sh:1543 git-gui.sh:1544 msgid "Requires merge resolution" -msgstr "" -"Требуется разрешение конфликта при " -"объединении" +msgstr "Требуется разрешение конфликта при объединении" -#: git-gui.sh:1404 +#: git-gui.sh:1579 msgid "Starting gitk... please wait..." msgstr "Запускается gitk... пожалуйста, ждите..." -#: git-gui.sh:1413 +#: git-gui.sh:1588 #, tcl-format msgid "" "Unable to start gitk:\n" @@ -125,308 +138,338 @@ msgstr "" "\n" "%s не существует" -#: git-gui.sh:1630 -#, tcl-format -msgid "Invalid font specified in gui.%s:" -msgstr "" -"В оболочке установлен неверный шрифт.%s:" - -#: git-gui.sh:1655 -msgid "Main Font" -msgstr "Шрифт интерфейса" - -#: git-gui.sh:1656 -msgid "Diff/Console Font" -msgstr "Шрифт в консоли diff" - -#: git-gui.sh:1670 +#: git-gui.sh:1788 lib/choose_repository.tcl:32 msgid "Repository" msgstr "Репозиторий" -#: git-gui.sh:1671 +#: git-gui.sh:1789 msgid "Edit" msgstr "Редактировать" -#: git-gui.sh:1673 +#: git-gui.sh:1791 lib/choose_rev.tcl:560 msgid "Branch" msgstr "Ветвь" -#: git-gui.sh:1676 git-gui.sh:1854 git-gui.sh:2193 -msgid "Commit" +#: git-gui.sh:1794 lib/choose_rev.tcl:547 +#, fuzzy +msgid "Commit@@noun" msgstr "Сохранить" -#: git-gui.sh:1679 lib/merge.tcl:96 lib/merge.tcl:157 lib/merge.tcl:173 +#: git-gui.sh:1797 lib/merge.tcl:121 lib/merge.tcl:150 lib/merge.tcl:168 msgid "Merge" msgstr "Объединить" -#: git-gui.sh:1680 -msgid "Fetch" -msgstr "Получить" +#: git-gui.sh:1798 lib/choose_rev.tcl:556 +#, fuzzy +msgid "Remote" +msgstr "внешний:" -#: git-gui.sh:1681 git-gui.sh:2199 lib/transport.tcl:88 lib/transport.tcl:172 -msgid "Push" -msgstr "Отправить" - -#: git-gui.sh:1690 +#: git-gui.sh:1807 msgid "Browse Current Branch's Files" msgstr "Просмотреть файлы текущей ветви" -#: git-gui.sh:1692 -#, fuzzy, tcl-format -msgid "Browse %s's Files" -msgstr "Показать файлы ветви" - -#: git-gui.sh:1694 +#: git-gui.sh:1811 #, fuzzy msgid "Browse Branch Files..." msgstr "Показать файлы ветви" -#: git-gui.sh:1699 +#: git-gui.sh:1816 msgid "Visualize Current Branch's History" msgstr "История текущей ветви наглядно" -#: git-gui.sh:1701 +#: git-gui.sh:1820 +msgid "Visualize All Branch History" +msgstr "История всех ветвей наглядно" + +#: git-gui.sh:1827 +#, fuzzy, tcl-format +msgid "Browse %s's Files" +msgstr "Показать файлы ветви" + +#: git-gui.sh:1829 #, fuzzy, tcl-format msgid "Visualize %s's History" msgstr "История всех ветвей наглядно" -#: git-gui.sh:1703 -msgid "Visualize All Branch History" -msgstr "История всех ветвей наглядно" - -#: git-gui.sh:1708 lib/database.tcl:27 lib/database.tcl:67 +#: git-gui.sh:1834 lib/database.tcl:27 lib/database.tcl:67 msgid "Database Statistics" msgstr "Статистика базы данных" -#: git-gui.sh:1711 lib/database.tcl:34 +#: git-gui.sh:1837 lib/database.tcl:34 msgid "Compress Database" msgstr "Сжать базу данных" -#: git-gui.sh:1714 +#: git-gui.sh:1840 msgid "Verify Database" msgstr "Проверить базу данных" -#: git-gui.sh:1721 git-gui.sh:1725 git-gui.sh:1729 lib/shortcut.tcl:9 +#: git-gui.sh:1847 git-gui.sh:1851 git-gui.sh:1855 lib/shortcut.tcl:9 #: lib/shortcut.tcl:45 lib/shortcut.tcl:84 msgid "Create Desktop Icon" msgstr "Создать ярлык на рабочем столе" -#: git-gui.sh:1734 +#: git-gui.sh:1860 lib/choose_repository.tcl:36 lib/choose_repository.tcl:95 msgid "Quit" msgstr "Выход" -#: git-gui.sh:1741 +#: git-gui.sh:1867 msgid "Undo" msgstr "Отменить" -#: git-gui.sh:1744 +#: git-gui.sh:1870 msgid "Redo" msgstr "Повторить" -#: git-gui.sh:1748 git-gui.sh:2263 +#: git-gui.sh:1874 git-gui.sh:2366 msgid "Cut" msgstr "Вырезать" -#: git-gui.sh:1751 git-gui.sh:2266 git-gui.sh:2337 git-gui.sh:2409 -#: lib/console.tcl:69 +#: git-gui.sh:1877 git-gui.sh:2369 git-gui.sh:2440 git-gui.sh:2512 +#: lib/console.tcl:67 msgid "Copy" msgstr "Копировать" -#: git-gui.sh:1754 git-gui.sh:2269 +#: git-gui.sh:1880 git-gui.sh:2372 msgid "Paste" msgstr "Вставить" -#: git-gui.sh:1757 git-gui.sh:2272 lib/branch_delete.tcl:26 +#: git-gui.sh:1883 git-gui.sh:2375 lib/branch_delete.tcl:26 #: lib/remote_branch_delete.tcl:38 msgid "Delete" msgstr "Удалить" -#: git-gui.sh:1761 git-gui.sh:2276 git-gui.sh:2413 lib/console.tcl:71 +#: git-gui.sh:1887 git-gui.sh:2379 git-gui.sh:2516 lib/console.tcl:69 msgid "Select All" msgstr "Выделить все" -#: git-gui.sh:1770 +#: git-gui.sh:1896 msgid "Create..." msgstr "Создать..." -#: git-gui.sh:1776 +#: git-gui.sh:1902 msgid "Checkout..." msgstr "Перейти..." -#: git-gui.sh:1782 +#: git-gui.sh:1908 msgid "Rename..." msgstr "Переименовать..." -#: git-gui.sh:1787 git-gui.sh:1885 +#: git-gui.sh:1913 git-gui.sh:2012 msgid "Delete..." msgstr "Удалить..." -#: git-gui.sh:1792 +#: git-gui.sh:1918 msgid "Reset..." msgstr "Сбросить..." -#: git-gui.sh:1804 git-gui.sh:2210 +#: git-gui.sh:1930 git-gui.sh:2313 msgid "New Commit" msgstr "Новое состояние" -#: git-gui.sh:1812 git-gui.sh:2217 +#: git-gui.sh:1938 git-gui.sh:2320 msgid "Amend Last Commit" msgstr "Исправить последнее состояние" -#: git-gui.sh:1821 git-gui.sh:2177 lib/remote_branch_delete.tcl:99 +#: git-gui.sh:1947 git-gui.sh:2280 lib/remote_branch_delete.tcl:99 msgid "Rescan" msgstr "Перечитать" -#: git-gui.sh:1827 -msgid "Add To Commit" -msgstr "Подготовить к сохранению" +#: git-gui.sh:1953 +#, fuzzy +msgid "Stage To Commit" +msgstr "Подготовлено для сохранения" -#: git-gui.sh:1832 -msgid "Add Existing To Commit" -msgstr "" -"Подготовить имеющиеся файлы к сохранению" +#: git-gui.sh:1958 +#, fuzzy +msgid "Stage Changed Files To Commit" +msgstr "Подготовлено (будет сохранено)" -#: git-gui.sh:1838 +#: git-gui.sh:1964 msgid "Unstage From Commit" msgstr "Убрать из подготовленного" -#: git-gui.sh:1843 lib/index.tcl:376 +#: git-gui.sh:1969 lib/index.tcl:352 msgid "Revert Changes" msgstr "Отменить изменения" -#: git-gui.sh:1850 git-gui.sh:2189 git-gui.sh:2287 +#: git-gui.sh:1976 git-gui.sh:2292 git-gui.sh:2390 msgid "Sign Off" msgstr "Подписать" -#: git-gui.sh:1865 +#: git-gui.sh:1980 git-gui.sh:2296 +#, fuzzy +msgid "Commit@@verb" +msgstr "Сохранить" + +#: git-gui.sh:1991 msgid "Local Merge..." msgstr "Локальное объединение..." -#: git-gui.sh:1870 +#: git-gui.sh:1996 msgid "Abort Merge..." msgstr "Прервать объединение..." -#: git-gui.sh:1882 +#: git-gui.sh:2008 msgid "Push..." msgstr "Отправить..." -#: git-gui.sh:1892 +#: git-gui.sh:2019 lib/choose_repository.tcl:41 msgid "Apple" msgstr "" -#: git-gui.sh:1895 git-gui.sh:1942 lib/option.tcl:65 +#: git-gui.sh:2022 git-gui.sh:2044 lib/about.tcl:13 +#: lib/choose_repository.tcl:44 lib/choose_repository.tcl:50 #, tcl-format msgid "About %s" msgstr "О %s" -#: git-gui.sh:1897 git-gui.sh:1903 git-gui.sh:2455 +#: git-gui.sh:2026 +msgid "Preferences..." +msgstr "" + +#: git-gui.sh:2034 git-gui.sh:2558 msgid "Options..." msgstr "Настройки..." -#: git-gui.sh:1917 -msgid "Running miga..." -msgstr "" - -#: git-gui.sh:1938 +#: git-gui.sh:2040 lib/choose_repository.tcl:47 msgid "Help" msgstr "Помощь" -#: git-gui.sh:1979 +#: git-gui.sh:2081 msgid "Online Documentation" msgstr "Документация в интернете" -#: git-gui.sh:2095 +#: git-gui.sh:2165 +#, tcl-format +msgid "fatal: cannot stat path %s: No such file or directory" +msgstr "" + +#: git-gui.sh:2198 msgid "Current Branch:" msgstr "Текущая ветвь:" -#: git-gui.sh:2116 -msgid "Staged Changes (Will Be Committed)" +#: git-gui.sh:2219 +#, fuzzy +msgid "Staged Changes (Will Commit)" msgstr "Подготовлено (будет сохранено)" -#: git-gui.sh:2136 -msgid "Unstaged Changes (Will Not Be Committed)" -msgstr "Изменено (не будет сохранено)" +#: git-gui.sh:2239 +msgid "Unstaged Changes" +msgstr "" -#: git-gui.sh:2183 -msgid "Add Existing" -msgstr "Добавить имеющиеся файлы" +#: git-gui.sh:2286 +msgid "Stage Changed" +msgstr "" -#: git-gui.sh:2229 +#: git-gui.sh:2302 lib/transport.tcl:93 lib/transport.tcl:182 +msgid "Push" +msgstr "Отправить" + +#: git-gui.sh:2332 #, fuzzy msgid "Initial Commit Message:" -msgstr "" -"Первоначальный комментарий к состоянию:" +msgstr "Первоначальный комментарий к состоянию:" -#: git-gui.sh:2230 +#: git-gui.sh:2333 #, fuzzy msgid "Amended Commit Message:" msgstr "Исправленный комментарий к состоянию:" -#: git-gui.sh:2231 +#: git-gui.sh:2334 #, fuzzy msgid "Amended Initial Commit Message:" -msgstr "" -"Первоначальный комментарий к " -"исправленному состоянию:" +msgstr "Первоначальный комментарий к исправленному состоянию:" -#: git-gui.sh:2232 +#: git-gui.sh:2335 #, fuzzy msgid "Amended Merge Commit Message:" -msgstr "" -"Комментарий к исправленному объединению:" +msgstr "Комментарий к исправленному объединению:" -#: git-gui.sh:2233 +#: git-gui.sh:2336 msgid "Merge Commit Message:" msgstr "Комментарий к объединению:" -#: git-gui.sh:2234 +#: git-gui.sh:2337 msgid "Commit Message:" msgstr "Комментарий к состоянию:" -#: git-gui.sh:2279 git-gui.sh:2417 lib/console.tcl:73 +#: git-gui.sh:2382 git-gui.sh:2520 lib/console.tcl:71 msgid "Copy All" msgstr "Копировать все" -#: git-gui.sh:2303 lib/blame.tcl:104 +#: git-gui.sh:2406 lib/blame.tcl:104 msgid "File:" msgstr "Файл:" -#: git-gui.sh:2405 +#: git-gui.sh:2508 msgid "Refresh" msgstr "Обновить" -#: git-gui.sh:2426 +#: git-gui.sh:2529 msgid "Apply/Reverse Hunk" msgstr "Применить/Убрать изменение" -#: git-gui.sh:2432 +#: git-gui.sh:2535 msgid "Decrease Font Size" msgstr "Уменьшить размер шрифта" -#: git-gui.sh:2436 +#: git-gui.sh:2539 msgid "Increase Font Size" msgstr "Увеличить размер шрифта" -#: git-gui.sh:2441 +#: git-gui.sh:2544 msgid "Show Less Context" msgstr "Меньше контекста" -#: git-gui.sh:2448 +#: git-gui.sh:2551 msgid "Show More Context" msgstr "Больше контекста" -#: git-gui.sh:2461 +#: git-gui.sh:2565 msgid "Unstage Hunk From Commit" msgstr "Не сохранять часть" -#: git-gui.sh:2463 +#: git-gui.sh:2567 msgid "Stage Hunk For Commit" msgstr "Подготовить часть для сохранения" -#: git-gui.sh:2473 +#: git-gui.sh:2586 msgid "Initializing..." msgstr "Инициализация..." +#: git-gui.sh:2677 +#, tcl-format +msgid "" +"Possible environment issues exist.\n" +"\n" +"The following environment variables are probably\n" +"going to be ignored by any Git subprocess run\n" +"by %s:\n" +"\n" +msgstr "" + +#: git-gui.sh:2707 +msgid "" +"\n" +"This is due to a known issue with the\n" +"Tcl binary distributed by Cygwin." +msgstr "" + +#: git-gui.sh:2712 +#, tcl-format +msgid "" +"\n" +"\n" +"A good replacement for %s\n" +"is placing values for the user.name and\n" +"user.email settings into your personal\n" +"~/.gitconfig file.\n" +msgstr "" + +#: lib/about.tcl:25 +msgid "git-gui - a graphical user interface for Git." +msgstr "git-gui - графический пользовательский интерфейс к Git." + #: lib/blame.tcl:77 msgid "File Viewer" msgstr "Просмотр файла" @@ -444,6 +487,53 @@ msgstr "Копировать сохраненное состояние" msgid "Reading %s..." msgstr "Чтение %s..." +#: lib/blame.tcl:473 +msgid "Loading copy/move tracking annotations..." +msgstr "" + +#: lib/blame.tcl:493 +msgid "lines annotated" +msgstr "" + +#: lib/blame.tcl:674 +msgid "Loading original location annotations..." +msgstr "" + +#: lib/blame.tcl:677 +msgid "Annotation complete." +msgstr "" + +#: lib/blame.tcl:731 +#, fuzzy +msgid "Loading annotation..." +msgstr "Загрузка %s..." + +#: lib/blame.tcl:787 +msgid "Author:" +msgstr "" + +#: lib/blame.tcl:791 +#, fuzzy +msgid "Committer:" +msgstr "Сохраненное состояние:" + +#: lib/blame.tcl:796 +msgid "Original File:" +msgstr "" + +#: lib/blame.tcl:910 +msgid "Originally By:" +msgstr "" + +#: lib/blame.tcl:916 +#, fuzzy +msgid "In File:" +msgstr "Файл:" + +#: lib/blame.tcl:921 +msgid "Copied Or Moved Here By:" +msgstr "" + #: lib/branch_checkout.tcl:14 lib/branch_checkout.tcl:19 msgid "Checkout Branch" msgstr "Перейти на ветвь" @@ -453,18 +543,17 @@ msgid "Checkout" msgstr "Перейти" #: lib/branch_checkout.tcl:27 lib/branch_create.tcl:35 -#: lib/branch_delete.tcl:32 lib/branch_rename.tcl:30 lib/browser.tcl:269 -#: lib/checkout_op.tcl:519 lib/merge.tcl:176 lib/option.tcl:172 -#: lib/remote_branch_delete.tcl:42 lib/transport.tcl:92 +#: lib/branch_delete.tcl:32 lib/branch_rename.tcl:30 lib/browser.tcl:281 +#: lib/checkout_op.tcl:522 lib/choose_font.tcl:43 lib/merge.tcl:172 +#: lib/option.tcl:90 lib/remote_branch_delete.tcl:42 lib/transport.tcl:97 msgid "Cancel" msgstr "Отменить" -#: lib/branch_checkout.tcl:32 lib/browser.tcl:274 +#: lib/branch_checkout.tcl:32 lib/browser.tcl:286 msgid "Revision" msgstr "Версия" -#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:159 -#: lib/option.tcl:274 +#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:202 msgid "Options" msgstr "Настройки" @@ -484,7 +573,7 @@ msgstr "Создание ветви" msgid "Create New Branch" msgstr "Создать новую ветвь" -#: lib/branch_create.tcl:31 +#: lib/branch_create.tcl:31 lib/choose_repository.tcl:199 msgid "Create" msgstr "Создать" @@ -516,7 +605,7 @@ msgstr "Нет" msgid "Fast Forward Only" msgstr "Только Fast Forward" -#: lib/branch_create.tcl:85 lib/checkout_op.tcl:511 +#: lib/branch_create.tcl:85 lib/checkout_op.tcl:514 msgid "Reset" msgstr "Сброс" @@ -531,9 +620,7 @@ msgstr "Укажите ветвь слежения." #: lib/branch_create.tcl:140 #, tcl-format msgid "Tracking branch %s is not a branch in the remote repository." -msgstr "" -"Ветвь слежения %s не является ветвью во " -"внешнем репозитории." +msgstr "Ветвь слежения %s не является ветвью во внешнем репозитории." #: lib/branch_create.tcl:153 lib/branch_rename.tcl:86 msgid "Please supply a branch name." @@ -558,22 +645,16 @@ msgstr "Локальные ветви" #: lib/branch_delete.tcl:52 msgid "Delete Only If Merged Into" -msgstr "" -"Удалить только в случае, если было " -"объединение с" +msgstr "Удалить только в случае, если было объединение с" #: lib/branch_delete.tcl:54 msgid "Always (Do not perform merge test.)" -msgstr "" -"Всегда (не выполнять проверку на " -"объединение)" +msgstr "Всегда (не выполнять проверку на объединение)" #: lib/branch_delete.tcl:103 #, tcl-format msgid "The following branches are not completely merged into %s:" -msgstr "" -"Следующие ветви объединены с %s не " -"полностью:" +msgstr "Следующие ветви объединены с %s не полностью:" #: lib/branch_delete.tcl:115 msgid "" @@ -624,24 +705,30 @@ msgstr "Ветвь '%s' уже существует." msgid "Failed to rename '%s'." msgstr "Не удалось переименовать '%s'. " -#: lib/browser.tcl:10 +#: lib/browser.tcl:17 msgid "Starting..." msgstr "Запуск..." -#: lib/browser.tcl:19 +#: lib/browser.tcl:26 msgid "File Browser" msgstr "Просмотр списка файлов" -#: lib/browser.tcl:120 lib/browser.tcl:137 +#: lib/browser.tcl:125 lib/browser.tcl:142 #, tcl-format msgid "Loading %s..." msgstr "Загрузка %s..." -#: lib/browser.tcl:254 lib/browser.tcl:260 +#: lib/browser.tcl:186 +msgid "[Up To Parent]" +msgstr "" + +#: lib/browser.tcl:266 lib/browser.tcl:272 msgid "Browse Branch Files" msgstr "Показать файлы ветви" -#: lib/browser.tcl:265 +#: lib/browser.tcl:277 lib/choose_repository.tcl:215 +#: lib/choose_repository.tcl:305 lib/choose_repository.tcl:315 +#: lib/choose_repository.tcl:811 msgid "Browse" msgstr "Показать" @@ -650,7 +737,12 @@ msgstr "Показать" msgid "Fetching %s from %s" msgstr "Получение изменений из %s " -#: lib/checkout_op.tcl:140 lib/console.tcl:81 lib/database.tcl:31 +#: lib/checkout_op.tcl:127 +#, tcl-format +msgid "fatal: Cannot resolve %s" +msgstr "" + +#: lib/checkout_op.tcl:140 lib/console.tcl:79 lib/database.tcl:31 msgid "Close" msgstr "Закрыть" @@ -659,7 +751,7 @@ msgstr "Закрыть" msgid "Branch '%s' does not exist." msgstr "Ветвь '%s' не существует " -#: lib/checkout_op.tcl:205 +#: lib/checkout_op.tcl:206 #, tcl-format msgid "" "Branch '%s' already exists.\n" @@ -672,23 +764,22 @@ msgstr "" "Она не может быть прокручена(fast-forward) к %s.\n" "Требуется объединение." -#: lib/checkout_op.tcl:219 +#: lib/checkout_op.tcl:220 #, tcl-format msgid "Merge strategy '%s' not supported." -msgstr "" -"Операция объединения '%s' не " -"поддерживается." +msgstr "Операция объединения '%s' не поддерживается." -#: lib/checkout_op.tcl:238 +#: lib/checkout_op.tcl:239 #, tcl-format msgid "Failed to update '%s'." msgstr "Не удалось обновить '%s'." -#: lib/checkout_op.tcl:250 -msgid "Index is already locked." +#: lib/checkout_op.tcl:251 +#, fuzzy +msgid "Staging area (index) is already locked." msgstr "Индекс заблокирован." -#: lib/checkout_op.tcl:265 +#: lib/checkout_op.tcl:266 msgid "" "Last scanned state does not match repository state.\n" "\n" @@ -697,34 +788,33 @@ msgid "" "\n" "The rescan will be automatically started now.\n" msgstr "" -"Последнее прочитанное состояние " -"репозитория не соответствует текущему.\n" +"Последнее прочитанное состояние репозитория не соответствует текущему.\n" "\n" -"С момента последней проверки репозиторий " -"был изменен другой программой " -"Git.Необходимо перечитать репозиторий, " -"прежде чем изменять текущую ветвь. \n" +"С момента последней проверки репозиторий был изменен другой программой Git." +"Необходимо перечитать репозиторий, прежде чем изменять текущую ветвь. \n" "\n" "Это будет сделано сейчас автоматически.\n" -#: lib/checkout_op.tcl:352 -#, tcl-format -msgid "Aborted checkout of '%s' (file level merging is required)." -msgstr "" -"Прерван переход на '%s' (требуется " -"объединение на уровне файлов)" +#: lib/checkout_op.tcl:322 +#, fuzzy, tcl-format +msgid "Updating working directory to '%s'..." +msgstr "Отсутствует рабочий каталог" #: lib/checkout_op.tcl:353 -msgid "File level merge required." -msgstr "" -"Требуется объединение на уровне файлов." +#, tcl-format +msgid "Aborted checkout of '%s' (file level merging is required)." +msgstr "Прерван переход на '%s' (требуется объединение на уровне файлов)" -#: lib/checkout_op.tcl:357 +#: lib/checkout_op.tcl:354 +msgid "File level merge required." +msgstr "Требуется объединение на уровне файлов." + +#: lib/checkout_op.tcl:358 #, tcl-format msgid "Staying on branch '%s'." msgstr "Ветвь '%s' остается текущей." -#: lib/checkout_op.tcl:426 +#: lib/checkout_op.tcl:429 msgid "" "You are no longer on a local branch.\n" "\n" @@ -733,34 +823,33 @@ msgid "" msgstr "" "Вы находитесь не в локальной ветви.\n" "\n" -"Если вы хотите снова вернуться к " -"какой-нибудь ветви, создайте ее сейчас, " -"начиная с 'Текущего отсоединенного " -"состояния'." +"Если вы хотите снова вернуться к какой-нибудь ветви, создайте ее сейчас, " +"начиная с 'Текущего отсоединенного состояния'." -#: lib/checkout_op.tcl:475 +#: lib/checkout_op.tcl:446 +#, fuzzy, tcl-format +msgid "Checked out '%s'." +msgstr "Перейти..." + +#: lib/checkout_op.tcl:478 #, tcl-format msgid "Resetting '%s' to '%s' will lose the following commits:" -msgstr "" -"Сброс '%s' в '%s' приведет к потере следующих " -"сохраненных состояний: " +msgstr "Сброс '%s' в '%s' приведет к потере следующих сохраненных состояний: " -#: lib/checkout_op.tcl:497 +#: lib/checkout_op.tcl:500 msgid "Recovering lost commits may not be easy." -msgstr "" -"Восстановить потерянные сохраненные " -"состояния будет сложно." +msgstr "Восстановить потерянные сохраненные состояния будет сложно." -#: lib/checkout_op.tcl:502 +#: lib/checkout_op.tcl:505 #, tcl-format msgid "Reset '%s'?" msgstr "Сбросить '%s'?" -#: lib/checkout_op.tcl:507 lib/merge.tcl:171 +#: lib/checkout_op.tcl:510 lib/merge.tcl:164 msgid "Visualize" msgstr "Наглядно" -#: lib/checkout_op.tcl:575 +#: lib/checkout_op.tcl:578 #, tcl-format msgid "" "Failed to set current branch.\n" @@ -772,46 +861,290 @@ msgid "" msgstr "" "Не удалось установить текущую ветвь.\n" "\n" -"Ваш рабочий каталог обновлен только " -"частично. Были обновлены все файлы кроме " +"Ваш рабочий каталог обновлен только частично. Были обновлены все файлы кроме " "служебных файлов Git. \n" "\n" -"Этого не должно было произойти. %s " -"завершается." +"Этого не должно было произойти. %s завершается." -#: lib/choose_rev.tcl:35 +#: lib/choose_font.tcl:39 +#, fuzzy +msgid "Select" +msgstr "Выделить все" + +#: lib/choose_font.tcl:53 +msgid "Font Family" +msgstr "" + +#: lib/choose_font.tcl:73 +#, fuzzy +msgid "Font Size" +msgstr "Уменьшить размер шрифта" + +#: lib/choose_font.tcl:90 +msgid "Font Example" +msgstr "" + +#: lib/choose_font.tcl:101 +msgid "" +"This is example text.\n" +"If you like this text, it can be your font." +msgstr "" + +#: lib/choose_repository.tcl:25 +msgid "Git Gui" +msgstr "" + +#: lib/choose_repository.tcl:69 lib/choose_repository.tcl:204 +#, fuzzy +msgid "Create New Repository" +msgstr "Из репозитория" + +#: lib/choose_repository.tcl:74 lib/choose_repository.tcl:291 +#, fuzzy +msgid "Clone Existing Repository" +msgstr "Репозиторий назначения" + +#: lib/choose_repository.tcl:79 lib/choose_repository.tcl:800 +#, fuzzy +msgid "Open Existing Repository" +msgstr "Репозиторий назначения" + +#: lib/choose_repository.tcl:91 +msgid "Next >" +msgstr "" + +#: lib/choose_repository.tcl:152 +#, fuzzy, tcl-format +msgid "Location %s already exists." +msgstr "Ветвь '%s' уже существует." + +#: lib/choose_repository.tcl:158 lib/choose_repository.tcl:165 +#: lib/choose_repository.tcl:172 +#, fuzzy, tcl-format +msgid "Failed to create repository %s:" +msgstr "Не удалось полностью сохранить настройки:" + +#: lib/choose_repository.tcl:209 lib/choose_repository.tcl:309 +msgid "Directory:" +msgstr "" + +#: lib/choose_repository.tcl:238 lib/choose_repository.tcl:363 +#: lib/choose_repository.tcl:834 +#, fuzzy +msgid "Git Repository" +msgstr "Репозиторий" + +#: lib/choose_repository.tcl:253 lib/choose_repository.tcl:260 +#, fuzzy, tcl-format +msgid "Directory %s already exists." +msgstr "Ветвь '%s' уже существует." + +#: lib/choose_repository.tcl:265 +#, fuzzy, tcl-format +msgid "File %s already exists." +msgstr "Ветвь '%s' уже существует." + +#: lib/choose_repository.tcl:286 +#, fuzzy +msgid "Clone" +msgstr "Закрыть" + +#: lib/choose_repository.tcl:299 +msgid "URL:" +msgstr "" + +#: lib/choose_repository.tcl:319 +msgid "Clone Type:" +msgstr "" + +#: lib/choose_repository.tcl:325 +msgid "Standard (Fast, Semi-Redundant, Hardlinks)" +msgstr "" + +#: lib/choose_repository.tcl:331 +msgid "Full Copy (Slower, Redundant Backup)" +msgstr "" + +#: lib/choose_repository.tcl:337 +msgid "Shared (Fastest, Not Recommended, No Backup)" +msgstr "" + +#: lib/choose_repository.tcl:369 lib/choose_repository.tcl:418 +#: lib/choose_repository.tcl:560 lib/choose_repository.tcl:630 +#: lib/choose_repository.tcl:840 lib/choose_repository.tcl:848 +#, fuzzy, tcl-format +msgid "Not a Git repository: %s" +msgstr "Не указан репозиторий" + +#: lib/choose_repository.tcl:405 +msgid "Standard only available for local repository." +msgstr "" + +#: lib/choose_repository.tcl:409 +msgid "Shared only available for local repository." +msgstr "" + +#: lib/choose_repository.tcl:439 +msgid "Failed to configure origin" +msgstr "" + +#: lib/choose_repository.tcl:451 +msgid "Counting objects" +msgstr "" + +#: lib/choose_repository.tcl:452 +msgid "buckets" +msgstr "" + +#: lib/choose_repository.tcl:476 +#, tcl-format +msgid "Unable to copy objects/info/alternates: %s" +msgstr "" + +#: lib/choose_repository.tcl:512 +#, fuzzy, tcl-format +msgid "Nothing to clone from %s." +msgstr "Получение изменений из %s " + +#: lib/choose_repository.tcl:514 lib/choose_repository.tcl:728 +#: lib/choose_repository.tcl:740 +msgid "The 'master' branch has not been initialized." +msgstr "" + +#: lib/choose_repository.tcl:527 +msgid "Hardlinks are unavailable. Falling back to copying." +msgstr "" + +#: lib/choose_repository.tcl:539 +#, fuzzy, tcl-format +msgid "Cloning from %s" +msgstr "Получение изменений из %s " + +#: lib/choose_repository.tcl:570 +#, fuzzy +msgid "Copying objects" +msgstr "Сжатие базы объектов" + +#: lib/choose_repository.tcl:571 +msgid "KiB" +msgstr "" + +#: lib/choose_repository.tcl:595 +#, tcl-format +msgid "Unable to copy object: %s" +msgstr "" + +#: lib/choose_repository.tcl:605 +msgid "Linking objects" +msgstr "" + +#: lib/choose_repository.tcl:606 +msgid "objects" +msgstr "" + +#: lib/choose_repository.tcl:614 +#, tcl-format +msgid "Unable to hardlink object: %s" +msgstr "" + +#: lib/choose_repository.tcl:669 +msgid "Cannot fetch branches and objects. See console output for details." +msgstr "" + +#: lib/choose_repository.tcl:680 +msgid "Cannot fetch tags. See console output for details." +msgstr "" + +#: lib/choose_repository.tcl:704 +msgid "Cannot determine HEAD. See console output for details." +msgstr "" + +#: lib/choose_repository.tcl:713 +#, tcl-format +msgid "Unable to cleanup %s" +msgstr "" + +#: lib/choose_repository.tcl:719 +msgid "Clone failed." +msgstr "" + +#: lib/choose_repository.tcl:726 +msgid "No default branch obtained." +msgstr "" + +#: lib/choose_repository.tcl:737 +#, tcl-format +msgid "Cannot resolve %s as a commit." +msgstr "" + +#: lib/choose_repository.tcl:749 +#, fuzzy +msgid "Creating working directory" +msgstr "Отсутствует рабочий каталог" + +#: lib/choose_repository.tcl:750 lib/index.tcl:15 lib/index.tcl:80 +#: lib/index.tcl:149 +msgid "files" +msgstr "" + +#: lib/choose_repository.tcl:779 +msgid "Initial file checkout failed." +msgstr "" + +#: lib/choose_repository.tcl:795 +msgid "Open" +msgstr "" + +#: lib/choose_repository.tcl:805 +#, fuzzy +msgid "Repository:" +msgstr "Репозиторий" + +#: lib/choose_repository.tcl:854 +#, fuzzy, tcl-format +msgid "Failed to open repository %s:" +msgstr "Не удалось полностью сохранить настройки:" + +#: lib/choose_rev.tcl:53 msgid "This Detached Checkout" msgstr "Текущее отсоединенное состояние" -#: lib/choose_rev.tcl:42 +#: lib/choose_rev.tcl:60 msgid "Revision Expression:" msgstr "Выражение для определения версии:" -#: lib/choose_rev.tcl:56 +#: lib/choose_rev.tcl:74 msgid "Local Branch" msgstr "Локальная ветвь:" -#: lib/choose_rev.tcl:61 +#: lib/choose_rev.tcl:79 msgid "Tracking Branch" msgstr "Ветвь слежения" -#: lib/choose_rev.tcl:66 +#: lib/choose_rev.tcl:84 lib/choose_rev.tcl:537 msgid "Tag" msgstr "Метка" -#: lib/choose_rev.tcl:227 +#: lib/choose_rev.tcl:317 #, tcl-format msgid "Invalid revision: %s" msgstr "Неверная версия: %s" -#: lib/choose_rev.tcl:248 +#: lib/choose_rev.tcl:338 msgid "No revision selected." msgstr "Версия не указана." -#: lib/choose_rev.tcl:256 +#: lib/choose_rev.tcl:346 msgid "Revision expression is empty." +msgstr "Пустое выражения для определения версии." + +#: lib/choose_rev.tcl:530 +msgid "Updated" +msgstr "" + +#: lib/choose_rev.tcl:558 +msgid "URL" msgstr "" -"Пустое выражения для определения версии." #: lib/commit.tcl:9 msgid "" @@ -822,8 +1155,7 @@ msgid "" msgstr "" "Отсутствует состояние для исправления.\n" "\n" -"Вы можете создать начальное сохраненное " -"состояние. Других состояний для " +"Вы можете создать начальное сохраненное состояние. Других состояний для " "исправления нет.\n" #: lib/commit.tcl:18 @@ -834,25 +1166,18 @@ msgid "" "completed. You cannot amend the prior commit unless you first abort the " "current merge activity.\n" msgstr "" -"Невозможно исправить состояние во время " -"объединения.\n" +"Невозможно исправить состояние во время объединения.\n" "\n" -"Текущее объединение не завершено. " -"Невозможно исправить предыдущее " -"сохраненное состояние не прерывая " -"текущее объединение.\n" +"Текущее объединение не завершено. Невозможно исправить предыдущее " +"сохраненное состояние не прерывая текущее объединение.\n" #: lib/commit.tcl:49 msgid "Error loading commit data for amend:" -msgstr "" -"Ошибка при загрузке данных для " -"исправления сохраненного состояния:" +msgstr "Ошибка при загрузке данных для исправления сохраненного состояния:" #: lib/commit.tcl:76 msgid "Unable to obtain your identity:" -msgstr "" -"Невозможно получить информацию об " -"авторстве:" +msgstr "Невозможно получить информацию об авторстве:" #: lib/commit.tcl:81 msgid "Invalid GIT_COMMITTER_IDENT:" @@ -867,30 +1192,25 @@ msgid "" "\n" "The rescan will be automatically started now.\n" msgstr "" -"Последнее прочитанное состояние " -"репозитория не соответствует текущему.\n" +"Последнее прочитанное состояние репозитория не соответствует текущему.\n" "\n" -"С момента последней проверки репозиторий " -"был изменен другой программой " -"Git.Необходимо перечитать репозиторий, " -"прежде чем изменять текущую ветвь. \n" +"С момента последней проверки репозиторий был изменен другой программой Git." +"Необходимо перечитать репозиторий, прежде чем изменять текущую ветвь. \n" "\n" "Это будет сделано сейчас автоматически.\n" #: lib/commit.tcl:154 -#, tcl-format +#, fuzzy, tcl-format msgid "" "Unmerged files cannot be committed.\n" "\n" -"File %s has merge conflicts. You must resolve them and add the file before " -"committing.\n" +"File %s has merge conflicts. You must resolve them and stage the file " +"before committing.\n" msgstr "" "Нельзя сохранить необъединенные файлы.\n" "\n" -"Для файла %s возник конфликт объединения. " -"Разрешите конфликт и добавьте к " -"подготовленным файлам перед " -"сохранением.\n" +"Для файла %s возник конфликт объединения. Разрешите конфликт и добавьте к " +"подготовленным файлам перед сохранением.\n" #: lib/commit.tcl:162 #, tcl-format @@ -899,22 +1219,20 @@ msgid "" "\n" "File %s cannot be committed by this program.\n" msgstr "" -"Обнаружено неизвестное состояние файла " -"%s.\n" +"Обнаружено неизвестное состояние файла %s.\n" "\n" -"Файл %s не может быть сохранен данной " -"программой.\n" +"Файл %s не может быть сохранен данной программой.\n" #: lib/commit.tcl:170 +#, fuzzy msgid "" "No changes to commit.\n" "\n" -"You must add at least 1 file before you can commit.\n" +"You must stage at least 1 file before you can commit.\n" msgstr "" "Отсутствуют изменения для сохранения.\n" "\n" -"Подготовьте хотя бы один файл до создания " -"сохраненного состояния.\n" +"Подготовьте хотя бы один файл до создания сохраненного состояния.\n" #: lib/commit.tcl:183 msgid "" @@ -926,22 +1244,22 @@ msgid "" "- Second line: Blank\n" "- Remaining lines: Describe why this change is good.\n" msgstr "" -"Напишите комментарий к сохраненному " -"состоянию.\n" +"Напишите комментарий к сохраненному состоянию.\n" "\n" -"Рекомендуется следующий формат " -"комментария:\n" +"Рекомендуется следующий формат комментария:\n" "\n" -"- первая строка: краткое описание " -"сделанных изменений.\n" +"- первая строка: краткое описание сделанных изменений.\n" "- вторая строка пустая\n" -"- оставшиеся строки: опишите, что дают " -"ваши изменения.\n" +"- оставшиеся строки: опишите, что дают ваши изменения.\n" #: lib/commit.tcl:257 msgid "write-tree failed:" +msgstr "Программа write-tree завершилась с ошибкой:" + +#: lib/commit.tcl:275 +#, tcl-format +msgid "Commit %s appears to be corrupt" msgstr "" -"Программа write-tree завершилась с ошибкой:" #: lib/commit.tcl:279 msgid "" @@ -953,40 +1271,41 @@ msgid "" msgstr "" "Отсутствуют изменения для сохранения.\n" "\n" -"Ни один файл не был изменен и не было " -"объединения.\n" +"Ни один файл не был изменен и не было объединения.\n" "\n" -"Сейчас автоматически запустится " -"перечитывание репозитория.\n" +"Сейчас автоматически запустится перечитывание репозитория.\n" #: lib/commit.tcl:286 msgid "No changes to commit." msgstr "Отуствуют измения для сохранения." +#: lib/commit.tcl:303 +#, tcl-format +msgid "warning: Tcl does not support encoding '%s'." +msgstr "" + #: lib/commit.tcl:317 msgid "commit-tree failed:" -msgstr "" -"Программа commit-tree завершилась с ошибкой:" +msgstr "Программа commit-tree завершилась с ошибкой:" #: lib/commit.tcl:339 msgid "update-ref failed:" -msgstr "" -"Программа update-ref завершилась с ошибкой:" +msgstr "Программа update-ref завершилась с ошибкой:" #: lib/commit.tcl:430 #, tcl-format msgid "Created commit %s: %s" msgstr "Создано состояние %s: %s " -#: lib/console.tcl:55 +#: lib/console.tcl:57 msgid "Working... please wait..." msgstr "В процессе... пожалуйста, ждите..." -#: lib/console.tcl:184 +#: lib/console.tcl:183 msgid "Success" msgstr "Процесс успешно завершен" -#: lib/console.tcl:194 +#: lib/console.tcl:196 msgid "Error: Command Failed" msgstr "Ошибка: не удалось выполнить команду" @@ -996,9 +1315,7 @@ msgstr "Количество несвязанных объектов" #: lib/database.tcl:44 msgid "Disk space used by loose objects" -msgstr "" -"Объем дискового пространства, занятый " -"несвязанными объектами" +msgstr "Объем дискового пространства, занятый несвязанными объектами" #: lib/database.tcl:45 msgid "Number of packed objects" @@ -1010,15 +1327,11 @@ msgstr "Количество pack-файлов" #: lib/database.tcl:47 msgid "Disk space used by packed objects" -msgstr "" -"Объем дискового пространства, занятый " -"упакованными объектами" +msgstr "Объем дискового пространства, занятый упакованными объектами" #: lib/database.tcl:48 msgid "Packed objects waiting for pruning" -msgstr "" -"Несвязанные объекты, которые можно " -"удалить" +msgstr "Несвязанные объекты, которые можно удалить" #: lib/database.tcl:49 msgid "Garbage files" @@ -1032,6 +1345,22 @@ msgstr "Сжатие базы объектов" msgid "Verifying the object database with fsck-objects" msgstr "Проверка базы объектов при помощи fsck" +#: lib/database.tcl:108 +#, tcl-format +msgid "" +"This repository currently has approximately %i loose objects.\n" +"\n" +"To maintain optimal performance it is strongly recommended that you compress " +"the database when more than %i loose objects exist.\n" +"\n" +"Compress the database now?" +msgstr "" + +#: lib/date.tcl:25 +#, fuzzy, tcl-format +msgid "Invalid date from Git: %s" +msgstr "Неверная версия: %s" + #: lib/diff.tcl:42 #, tcl-format msgid "" @@ -1049,30 +1378,44 @@ msgstr "" "\n" "в %s отутствуют изменения.\n" "\n" -"Дата изменения файла была обновлена " -"другой программой, но содержимое файла " +"Дата изменения файла была обновлена другой программой, но содержимое файла " "осталось прежним.\n" "\n" -"Сейчас будет запущено перечитывание " -"репозитория, чтобы найти подобные файлы." +"Сейчас будет запущено перечитывание репозитория, чтобы найти подобные файлы." -#: lib/diff.tcl:97 +#: lib/diff.tcl:81 +#, fuzzy, tcl-format +msgid "Loading diff of %s..." +msgstr "Загрузка %s..." + +#: lib/diff.tcl:114 lib/diff.tcl:184 +#, tcl-format +msgid "Unable to display %s" +msgstr "" + +#: lib/diff.tcl:115 msgid "Error loading file:" msgstr "Ошибка загрузки файла:" -#: lib/diff.tcl:162 +#: lib/diff.tcl:122 +msgid "Git Repository (subproject)" +msgstr "" + +#: lib/diff.tcl:134 +msgid "* Binary file (not showing content)." +msgstr "" + +#: lib/diff.tcl:185 msgid "Error loading diff:" msgstr "Ошибка загрузки diff:" -#: lib/diff.tcl:278 +#: lib/diff.tcl:302 msgid "Failed to unstage selected hunk." msgstr "Не удалось исключить выбранную часть" -#: lib/diff.tcl:285 +#: lib/diff.tcl:309 msgid "Failed to stage selected hunk." -msgstr "" -"Не удалось подготовить к сохранению " -"выбранную часть" +msgstr "Не удалось подготовить к сохранению выбранную часть" #: lib/error.tcl:12 lib/error.tcl:102 msgid "error" @@ -1084,47 +1427,53 @@ msgstr "предупреждение" #: lib/error.tcl:81 msgid "You must correct the above errors before committing." -msgstr "" -"Прежде чем сохранить, исправьте " -"вышеуказанные ошибки." +msgstr "Прежде чем сохранить, исправьте вышеуказанные ошибки." -#: lib/index.tcl:364 +#: lib/index.tcl:241 +#, fuzzy, tcl-format +msgid "Unstaging %s from commit" +msgstr "Убрать из подготовленного" + +#: lib/index.tcl:285 +#, fuzzy, tcl-format +msgid "Adding %s" +msgstr "Чтение %s..." + +#: lib/index.tcl:340 #, fuzzy, tcl-format msgid "Revert changes in file %s?" msgstr "Отменить изменения" -#: lib/index.tcl:366 +#: lib/index.tcl:342 #, tcl-format msgid "Revert changes in these %i files?" msgstr "Отменить изменения в %i файле(-ах)?" -#: lib/index.tcl:372 +#: lib/index.tcl:348 #, fuzzy -msgid "Any unadded changes will be permanently lost by the revert." +msgid "Any unstaged changes will be permanently lost by the revert." msgstr "" "Отменить изменения в %s?\n" "\n" -"Любые изменения, не подготовленные к " -"сохранению, будут потеряны при данной " +"Любые изменения, не подготовленные к сохранению, будут потеряны при данной " "операции." -#: lib/index.tcl:375 +#: lib/index.tcl:351 msgid "Do Nothing" msgstr "Ничего не делать" -#: lib/merge.tcl:14 +#: lib/merge.tcl:13 msgid "" "Cannot merge while amending.\n" "\n" "You must finish amending this commit before starting any type of merge.\n" msgstr "" -"Невозможно выполнить объединение во " -"время исправления.\n" +"Невозможно выполнить объединение во время исправления.\n" "\n" -"Завершите исправление данного состояния " -"перед выполнением операции объединения.\n" +"Завершите исправление данного состояния перед выполнением операции " +"объединения.\n" -#: lib/merge.tcl:28 +#: lib/merge.tcl:27 msgid "" "Last scanned state does not match repository state.\n" "\n" @@ -1133,35 +1482,30 @@ msgid "" "\n" "The rescan will be automatically started now.\n" msgstr "" -"Последнее прочитанное состояние " -"репозитория не соответствует текущему.\n" +"Последнее прочитанное состояние репозитория не соответствует текущему.\n" "\n" -"С момента последней проверки репозиторий " -"был изменен другой программой " -"Git.Необходимо перечитать репозиторий, " -"прежде чем изменять текущую ветвь. \n" +"С момента последней проверки репозиторий был изменен другой программой Git." +"Необходимо перечитать репозиторий, прежде чем изменять текущую ветвь. \n" "\n" "Это будет сделано сейчас автоматически.\n" -#: lib/merge.tcl:45 -#, tcl-format +#: lib/merge.tcl:44 +#, fuzzy, tcl-format msgid "" "You are in the middle of a conflicted merge.\n" "\n" "File %s has merge conflicts.\n" "\n" -"You must resolve them, add the file, and commit to complete the current " +"You must resolve them, stage the file, and commit to complete the current " "merge. Only then can you begin another merge.\n" msgstr "" -"Предыдущее объединение не завершено " -"из-за конфликта.\n" +"Предыдущее объединение не завершено из-за конфликта.\n" "\n" "Для файла %s возник конфликт объединения.\n" -"Разрешите конфликт, подготовьте файл и " -"сохраните. Только после этого можно " +"Разрешите конфликт, подготовьте файл и сохраните. Только после этого можно " "начать следующее объединение.\n" -#: lib/merge.tcl:55 +#: lib/merge.tcl:54 #, tcl-format msgid "" "You are in the middle of a change.\n" @@ -1175,36 +1519,38 @@ msgstr "" "\n" "Файл %s изменен.\n" "\n" -"Подготовьте и сохраните измения перед " -"началом объединения. В случае " -"необходимости это позволит прервать " -"операцию объединения.\n" +"Подготовьте и сохраните измения перед началом объединения. В случае " +"необходимости это позволит прервать операцию объединения.\n" -#: lib/merge.tcl:94 +#: lib/merge.tcl:106 +#, tcl-format +msgid "%s of %s" +msgstr "" + +#: lib/merge.tcl:119 #, tcl-format msgid "Merging %s and %s" msgstr "Объединение %s и %s" -#: lib/merge.tcl:106 +#: lib/merge.tcl:131 msgid "Merge completed successfully." msgstr "Объединение успешно завершено." -#: lib/merge.tcl:108 +#: lib/merge.tcl:133 msgid "Merge failed. Conflict resolution is required." -msgstr "" -"Не удалось завершить объединение. " -"Требуется разрешение конфликта." +msgstr "Не удалось завершить объединение. Требуется разрешение конфликта." -#: lib/merge.tcl:166 +#: lib/merge.tcl:158 #, tcl-format msgid "Merge Into %s" msgstr "Объединить с %s" -#: lib/merge.tcl:181 lib/transport.tcl:98 -msgid "Source Branches" -msgstr "Исходные ветви" +#: lib/merge.tcl:177 +#, fuzzy +msgid "Revision To Merge" +msgstr "Версия" -#: lib/merge.tcl:240 +#: lib/merge.tcl:212 msgid "" "Cannot abort while amending.\n" "\n" @@ -1212,10 +1558,9 @@ msgid "" msgstr "" "Невозможно прервать исправление.\n" "\n" -"Завершите текущее исправление " -"сохраненного состояния.\n" +"Завершите текущее исправление сохраненного состояния.\n" -#: lib/merge.tcl:250 +#: lib/merge.tcl:222 msgid "" "Abort merge?\n" "\n" @@ -1224,113 +1569,129 @@ msgid "" "Continue with aborting the current merge?" msgstr "" "Прервать объединение?\n" -"Прерывание объединения приведет к потере " -"*ВСЕХ* несохраненных изменений.\n" +"Прерывание объединения приведет к потере *ВСЕХ* несохраненных изменений.\n" "\n" "Продолжить?" -#: lib/merge.tcl:256 +#: lib/merge.tcl:228 +#, fuzzy msgid "" -"Abort commit?\n" +"Reset changes?\n" "\n" -"Aborting the current commit will cause *ALL* uncommitted changes to be " -"lost.\n" +"Resetting the changes will cause *ALL* uncommitted changes to be lost.\n" "\n" -"Continue with aborting the current commit?" +"Continue with resetting the current changes?" msgstr "" -"Отменить изменения?\n" -"\n" -"Вызванная операция приведет к потере " -"*ВСЕХ* несохраненных изменений.\n" +"Прервать объединение?\n" +"Прерывание объединения приведет к потере *ВСЕХ* несохраненных изменений.\n" "\n" "Продолжить?" -#: lib/merge.tcl:267 -msgid "Aborting... please wait..." +#: lib/merge.tcl:239 +msgid "Aborting" msgstr "" -"Прерывание выполнения... Пожалуйста, " -"ждите..." -#: lib/merge.tcl:290 +#: lib/merge.tcl:266 +msgid "Abort failed." +msgstr "" + +#: lib/merge.tcl:268 msgid "Abort completed. Ready." msgstr "Прервано." -#: lib/option.tcl:77 -msgid "git-gui - a graphical user interface for Git." -msgstr "" -"git-gui - графический пользовательский " -"интерфейс к Git." - -#: lib/option.tcl:164 +#: lib/option.tcl:82 msgid "Restore Defaults" msgstr "Восстановить настройки по умолчанию" -#: lib/option.tcl:168 +#: lib/option.tcl:86 msgid "Save" msgstr "Сохранить" -#: lib/option.tcl:178 +#: lib/option.tcl:96 #, tcl-format msgid "%s Repository" msgstr "для репозитория %s " -#: lib/option.tcl:179 +#: lib/option.tcl:97 msgid "Global (All Repositories)" msgstr "Общие (для всех репозиториев)" -#: lib/option.tcl:185 +#: lib/option.tcl:103 msgid "User Name" msgstr "Имя пользователя" -#: lib/option.tcl:186 +#: lib/option.tcl:104 msgid "Email Address" msgstr "Адес электронной почты" -#: lib/option.tcl:188 +#: lib/option.tcl:106 msgid "Summarize Merge Commits" -msgstr "" -"Суммарный комментарий при объединении" +msgstr "Суммарный комментарий при объединении" -#: lib/option.tcl:189 +#: lib/option.tcl:107 msgid "Merge Verbosity" -msgstr "" -"Уровень детальности сообщений при " -"объединении" +msgstr "Уровень детальности сообщений при объединении" -#: lib/option.tcl:190 +#: lib/option.tcl:108 msgid "Show Diffstat After Merge" -msgstr "" -"Показать отчет об изменениях после " -"объединения" +msgstr "Показать отчет об изменениях после объединения" -#: lib/option.tcl:192 +#: lib/option.tcl:110 msgid "Trust File Modification Timestamps" msgstr "Доверять времени модификации файла" -#: lib/option.tcl:193 +#: lib/option.tcl:111 msgid "Prune Tracking Branches During Fetch" -msgstr "" -"Чистка ветвей слежения при получении " -"изменений" +msgstr "Чистка ветвей слежения при получении изменений" -#: lib/option.tcl:194 +#: lib/option.tcl:112 msgid "Match Tracking Branches" -msgstr "" -"Имя новой ветви взять из имен ветвей " -"слежения" +msgstr "Имя новой ветви взять из имен ветвей слежения" -#: lib/option.tcl:195 +#: lib/option.tcl:113 msgid "Number of Diff Context Lines" msgstr "Число строк в контексте diff" -#: lib/option.tcl:196 +#: lib/option.tcl:114 msgid "New Branch Name Template" msgstr "Шаблон для имени новой ветви" -#: lib/option.tcl:305 -msgid "Failed to completely save options:" +#: lib/option.tcl:176 +#, fuzzy +msgid "Change Font" +msgstr "Шрифт интерфейса" + +#: lib/option.tcl:180 +#, tcl-format +msgid "Choose %s" msgstr "" -"Не удалось полностью сохранить настройки:" + +#: lib/option.tcl:186 +msgid "pt." +msgstr "" + +#: lib/option.tcl:200 +msgid "Preferences" +msgstr "" + +#: lib/option.tcl:235 +msgid "Failed to completely save options:" +msgstr "Не удалось полностью сохранить настройки:" + +#: lib/remote.tcl:165 +#, fuzzy +msgid "Prune from" +msgstr "Чистка %s... " + +#: lib/remote.tcl:170 +#, fuzzy +msgid "Fetch from" +msgstr "Чистка %s... " + +#: lib/remote.tcl:213 +#, fuzzy +msgid "Push to" +msgstr "Отправить" #: lib/remote_branch_delete.tcl:29 lib/remote_branch_delete.tcl:34 msgid "Delete Remote Branch" @@ -1340,11 +1701,11 @@ msgstr "Удалить внешнюю ветвь" msgid "From Repository" msgstr "Из репозитория" -#: lib/remote_branch_delete.tcl:50 lib/transport.tcl:118 +#: lib/remote_branch_delete.tcl:50 lib/transport.tcl:123 msgid "Remote:" msgstr "внешний:" -#: lib/remote_branch_delete.tcl:66 lib/transport.tcl:133 +#: lib/remote_branch_delete.tcl:66 lib/transport.tcl:138 msgid "Arbitrary URL:" msgstr "по указанному URL:" @@ -1362,15 +1723,19 @@ msgstr "Объединено с:" #: lib/remote_branch_delete.tcl:119 msgid "Always (Do not perform merge checks)" -msgstr "" -"Всегда (не выполнять проверку " -"объединений)" +msgstr "Всегда (не выполнять проверку объединений)" #: lib/remote_branch_delete.tcl:152 msgid "A branch is required for 'Merged Into'." -msgstr "" -"Для опции 'Объединено с' требуется " -"указать ветвь." +msgstr "Для опции 'Объединено с' требуется указать ветвь." + +#: lib/remote_branch_delete.tcl:184 +#, fuzzy, tcl-format +msgid "" +"The following branches are not completely merged into %s:\n" +"\n" +" - %s" +msgstr "Следующие ветви объединены с %s не полностью:" #: lib/remote_branch_delete.tcl:189 #, tcl-format @@ -1381,9 +1746,7 @@ msgstr "" #: lib/remote_branch_delete.tcl:207 msgid "Please select one or more branches to delete." -msgstr "" -"Укажите одну или несколько ветвей для " -"удаления." +msgstr "Укажите одну или несколько ветвей для удаления." #: lib/remote_branch_delete.tcl:216 msgid "" @@ -1409,21 +1772,6 @@ msgstr "Не указан репозиторий" msgid "Scanning %s..." msgstr "Перечитывание %s... " -#: lib/remote.tcl:156 -#, fuzzy, tcl-format -msgid "Fetch from %s..." -msgstr "Чистка %s... " - -#: lib/remote.tcl:166 -#, tcl-format -msgid "Prune from %s..." -msgstr "Чистка %s... " - -#: lib/remote.tcl:200 -#, tcl-format -msgid "Push to %s..." -msgstr "Отправка в %s..." - #: lib/shortcut.tcl:26 lib/shortcut.tcl:74 msgid "Cannot write script:" msgstr "Невозможно записать скрипт:" @@ -1432,49 +1780,105 @@ msgstr "Невозможно записать скрипт:" msgid "Cannot write icon:" msgstr "Невозможно записать значок:" -#: lib/status_bar.tcl:58 +#: lib/status_bar.tcl:83 #, tcl-format msgid "%s ... %*i of %*i %s (%3i%%)" msgstr "%s ... %*i из %*i %s (%3i%%)" +#: lib/transport.tcl:6 +#, fuzzy, tcl-format +msgid "fetch %s" +msgstr "Получить" + #: lib/transport.tcl:7 #, tcl-format msgid "Fetching new changes from %s" msgstr "Получение изменений из %s " +#: lib/transport.tcl:18 +#, tcl-format +msgid "remote prune %s" +msgstr "" + #: lib/transport.tcl:19 #, tcl-format msgid "Pruning tracking branches deleted from %s" msgstr "Чистка ветвей слежения, удаленных из %s" +#: lib/transport.tcl:25 lib/transport.tcl:71 +#, tcl-format +msgid "push %s" +msgstr "" + #: lib/transport.tcl:26 #, tcl-format msgid "Pushing changes to %s" msgstr "Отправка изменений в %s " -#: lib/transport.tcl:68 +#: lib/transport.tcl:72 #, tcl-format msgid "Pushing %s %s to %s" msgstr "Отправка %s %s в %s" -#: lib/transport.tcl:84 +#: lib/transport.tcl:89 msgid "Push Branches" msgstr "Отправить изменения" -#: lib/transport.tcl:115 +#: lib/transport.tcl:103 +msgid "Source Branches" +msgstr "Исходные ветви" + +#: lib/transport.tcl:120 msgid "Destination Repository" msgstr "Репозиторий назначения" -#: lib/transport.tcl:153 +#: lib/transport.tcl:158 msgid "Transfer Options" msgstr "Настройки передачи" -#: lib/transport.tcl:155 -msgid "Use thin pack (for slow network connections)" +#: lib/transport.tcl:160 +msgid "Force overwrite existing branch (may discard changes)" msgstr "" -"Использовать thin pack (для медленных сетевых " -"подключений)" -#: lib/transport.tcl:159 +#: lib/transport.tcl:164 +msgid "Use thin pack (for slow network connections)" +msgstr "Использовать thin pack (для медленных сетевых подключений)" + +#: lib/transport.tcl:168 msgid "Include tags" msgstr "Включить метки" + +#~ msgid "Cannot find the git directory:" +#~ msgstr "Каталог Git не найден:" + +#~ msgid "Add To Commit" +#~ msgstr "Подготовить к сохранению" + +#~ msgid "Add Existing To Commit" +#~ msgstr "Подготовить имеющиеся файлы к сохранению" + +#~ msgid "Unstaged Changes (Will Not Be Committed)" +#~ msgstr "Изменено (не будет сохранено)" + +#~ msgid "Add Existing" +#~ msgstr "Добавить имеющиеся файлы" + +#~ msgid "" +#~ "Abort commit?\n" +#~ "\n" +#~ "Aborting the current commit will cause *ALL* uncommitted changes to be " +#~ "lost.\n" +#~ "\n" +#~ "Continue with aborting the current commit?" +#~ msgstr "" +#~ "Отменить изменения?\n" +#~ "\n" +#~ "Вызванная операция приведет к потере *ВСЕХ* несохраненных изменений.\n" +#~ "\n" +#~ "Продолжить?" + +#~ msgid "Aborting... please wait..." +#~ msgstr "Прерывание выполнения... Пожалуйста, ждите..." + +#~ msgid "Push to %s..." +#~ msgstr "Отправка в %s..." diff --git a/po/zh_cn.po b/po/zh_cn.po index d1ed94f8a9..621c9479b2 100644 --- a/po/zh_cn.po +++ b/po/zh_cn.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: git-gui\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2007-07-27 19:33+0200\n" +"POT-Creation-Date: 2007-10-10 04:04-0400\n" "PO-Revision-Date: 2007-07-21 01:23-0700\n" "Last-Translator: Xudong Guan \n" "Language-Team: Chinese\n" @@ -16,15 +16,33 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: git-gui.sh:531 +#: git-gui.sh:41 git-gui.sh:634 git-gui.sh:648 git-gui.sh:661 git-gui.sh:744 +#: git-gui.sh:763 +msgid "git-gui: fatal error" +msgstr "" + +#: git-gui.sh:595 +#, tcl-format +msgid "Invalid font specified in %s:" +msgstr "" + +#: git-gui.sh:620 +msgid "Main Font" +msgstr "" + +#: git-gui.sh:621 +msgid "Diff/Console Font" +msgstr "" + +#: git-gui.sh:635 msgid "Cannot find git in PATH." msgstr "" -#: git-gui.sh:550 +#: git-gui.sh:662 msgid "Cannot parse Git version string:" msgstr "" -#: git-gui.sh:567 +#: git-gui.sh:680 #, tcl-format msgid "" "Git version cannot be determined.\n" @@ -36,82 +54,82 @@ msgid "" "Assume '%s' is version 1.5.0?\n" msgstr "" -#: git-gui.sh:689 -msgid "Cannot find the git directory:" -msgstr "" - -#: git-gui.sh:697 +#: git-gui.sh:853 msgid "Git directory not found:" msgstr "" -#: git-gui.sh:703 +#: git-gui.sh:860 +msgid "Cannot move to top of working directory:" +msgstr "" + +#: git-gui.sh:867 msgid "Cannot use funny .git directory:" msgstr "" -#: git-gui.sh:708 +#: git-gui.sh:872 msgid "No working directory" msgstr "" -#: git-gui.sh:853 +#: git-gui.sh:1019 msgid "Refreshing file status..." msgstr "" -#: git-gui.sh:886 +#: git-gui.sh:1084 msgid "Scanning for modified files ..." msgstr "" -#: git-gui.sh:1052 lib/browser.tcl:233 +#: git-gui.sh:1259 lib/browser.tcl:245 #, fuzzy msgid "Ready." msgstr "重做" -#: git-gui.sh:1343 +#: git-gui.sh:1525 msgid "Unmodified" msgstr "" -#: git-gui.sh:1345 +#: git-gui.sh:1527 msgid "Modified, not staged" msgstr "" -#: git-gui.sh:1346 git-gui.sh:1351 +#: git-gui.sh:1528 git-gui.sh:1533 #, fuzzy msgid "Staged for commit" msgstr "从本次提交移除" -#: git-gui.sh:1347 git-gui.sh:1352 +#: git-gui.sh:1529 git-gui.sh:1534 #, fuzzy msgid "Portions staged for commit" msgstr "从本次提交移除" -#: git-gui.sh:1348 git-gui.sh:1353 +#: git-gui.sh:1530 git-gui.sh:1535 msgid "Staged for commit, missing" msgstr "" -#: git-gui.sh:1350 +#: git-gui.sh:1532 msgid "Untracked, not staged" msgstr "" -#: git-gui.sh:1355 +#: git-gui.sh:1537 msgid "Missing" msgstr "" -#: git-gui.sh:1356 +#: git-gui.sh:1538 msgid "Staged for removal" msgstr "" -#: git-gui.sh:1357 +#: git-gui.sh:1539 msgid "Staged for removal, still present" msgstr "" -#: git-gui.sh:1359 git-gui.sh:1360 git-gui.sh:1361 git-gui.sh:1362 +#: git-gui.sh:1541 git-gui.sh:1542 git-gui.sh:1543 git-gui.sh:1544 msgid "Requires merge resolution" msgstr "" -#: git-gui.sh:1404 +#: git-gui.sh:1579 msgid "Starting gitk... please wait..." msgstr "" -#: git-gui.sh:1413 +#: git-gui.sh:1588 #, tcl-format msgid "" "Unable to start gitk:\n" @@ -119,300 +137,336 @@ msgid "" "%s does not exist" msgstr "" -#: git-gui.sh:1630 -#, tcl-format -msgid "Invalid font specified in gui.%s:" -msgstr "" - -#: git-gui.sh:1655 -msgid "Main Font" -msgstr "" - -#: git-gui.sh:1656 -msgid "Diff/Console Font" -msgstr "" - -#: git-gui.sh:1670 +#: git-gui.sh:1788 lib/choose_repository.tcl:32 msgid "Repository" msgstr "版本树" -#: git-gui.sh:1671 +#: git-gui.sh:1789 msgid "Edit" msgstr "编辑" -#: git-gui.sh:1673 +#: git-gui.sh:1791 lib/choose_rev.tcl:560 msgid "Branch" msgstr "分支" -#: git-gui.sh:1676 git-gui.sh:1854 git-gui.sh:2193 -msgid "Commit" +#: git-gui.sh:1794 lib/choose_rev.tcl:547 +#, fuzzy +msgid "Commit@@noun" msgstr "提交" -#: git-gui.sh:1679 lib/merge.tcl:96 lib/merge.tcl:157 lib/merge.tcl:173 +#: git-gui.sh:1797 lib/merge.tcl:121 lib/merge.tcl:150 lib/merge.tcl:168 msgid "Merge" msgstr "合并" -#: git-gui.sh:1680 -msgid "Fetch" -msgstr "导入" +#: git-gui.sh:1798 lib/choose_rev.tcl:556 +#, fuzzy +msgid "Remote" +msgstr "改名..." -#: git-gui.sh:1681 git-gui.sh:2199 lib/transport.tcl:88 lib/transport.tcl:172 -msgid "Push" -msgstr "上传" - -#: git-gui.sh:1690 +#: git-gui.sh:1807 msgid "Browse Current Branch's Files" msgstr "浏览当前分支文件" -#: git-gui.sh:1692 -#, fuzzy, tcl-format -msgid "Browse %s's Files" -msgstr "浏览当前分支文件" - -#: git-gui.sh:1694 +#: git-gui.sh:1811 #, fuzzy msgid "Browse Branch Files..." msgstr "浏览当前分支文件" -#: git-gui.sh:1699 +#: git-gui.sh:1816 msgid "Visualize Current Branch's History" msgstr "调用gitk显示当前分支" -#: git-gui.sh:1701 +#: git-gui.sh:1820 +msgid "Visualize All Branch History" +msgstr "调用gitk显示所有分支" + +#: git-gui.sh:1827 +#, fuzzy, tcl-format +msgid "Browse %s's Files" +msgstr "浏览当前分支文件" + +#: git-gui.sh:1829 #, fuzzy, tcl-format msgid "Visualize %s's History" msgstr "调用gitk显示所有分支" -#: git-gui.sh:1703 -msgid "Visualize All Branch History" -msgstr "调用gitk显示所有分支" - -#: git-gui.sh:1708 lib/database.tcl:27 lib/database.tcl:67 +#: git-gui.sh:1834 lib/database.tcl:27 lib/database.tcl:67 msgid "Database Statistics" msgstr "数据库统计数据" -#: git-gui.sh:1711 lib/database.tcl:34 +#: git-gui.sh:1837 lib/database.tcl:34 msgid "Compress Database" msgstr "压缩数据库" -#: git-gui.sh:1714 +#: git-gui.sh:1840 msgid "Verify Database" msgstr "验证数据库" -#: git-gui.sh:1721 git-gui.sh:1725 git-gui.sh:1729 lib/shortcut.tcl:9 +#: git-gui.sh:1847 git-gui.sh:1851 git-gui.sh:1855 lib/shortcut.tcl:9 #: lib/shortcut.tcl:45 lib/shortcut.tcl:84 msgid "Create Desktop Icon" msgstr "创建桌面图标" -#: git-gui.sh:1734 +#: git-gui.sh:1860 lib/choose_repository.tcl:36 lib/choose_repository.tcl:95 msgid "Quit" msgstr "退出" -#: git-gui.sh:1741 +#: git-gui.sh:1867 msgid "Undo" msgstr "撤销" -#: git-gui.sh:1744 +#: git-gui.sh:1870 msgid "Redo" msgstr "重做" -#: git-gui.sh:1748 git-gui.sh:2263 +#: git-gui.sh:1874 git-gui.sh:2366 msgid "Cut" msgstr "剪切" -#: git-gui.sh:1751 git-gui.sh:2266 git-gui.sh:2337 git-gui.sh:2409 -#: lib/console.tcl:69 +#: git-gui.sh:1877 git-gui.sh:2369 git-gui.sh:2440 git-gui.sh:2512 +#: lib/console.tcl:67 msgid "Copy" msgstr "复制" -#: git-gui.sh:1754 git-gui.sh:2269 +#: git-gui.sh:1880 git-gui.sh:2372 msgid "Paste" msgstr "粘贴" -#: git-gui.sh:1757 git-gui.sh:2272 lib/branch_delete.tcl:26 +#: git-gui.sh:1883 git-gui.sh:2375 lib/branch_delete.tcl:26 #: lib/remote_branch_delete.tcl:38 msgid "Delete" msgstr "删除" -#: git-gui.sh:1761 git-gui.sh:2276 git-gui.sh:2413 lib/console.tcl:71 +#: git-gui.sh:1887 git-gui.sh:2379 git-gui.sh:2516 lib/console.tcl:69 msgid "Select All" msgstr "全选" -#: git-gui.sh:1770 +#: git-gui.sh:1896 msgid "Create..." msgstr "新建..." -#: git-gui.sh:1776 +#: git-gui.sh:1902 msgid "Checkout..." msgstr "切换..." -#: git-gui.sh:1782 +#: git-gui.sh:1908 msgid "Rename..." msgstr "改名..." -#: git-gui.sh:1787 git-gui.sh:1885 +#: git-gui.sh:1913 git-gui.sh:2012 msgid "Delete..." msgstr "删除..." -#: git-gui.sh:1792 +#: git-gui.sh:1918 msgid "Reset..." msgstr "重置所有修动..." -#: git-gui.sh:1804 git-gui.sh:2210 +#: git-gui.sh:1930 git-gui.sh:2313 msgid "New Commit" msgstr "新提交" -#: git-gui.sh:1812 git-gui.sh:2217 +#: git-gui.sh:1938 git-gui.sh:2320 msgid "Amend Last Commit" msgstr "修订上次提交" -#: git-gui.sh:1821 git-gui.sh:2177 lib/remote_branch_delete.tcl:99 +#: git-gui.sh:1947 git-gui.sh:2280 lib/remote_branch_delete.tcl:99 msgid "Rescan" msgstr "重新扫描" -#: git-gui.sh:1827 -msgid "Add To Commit" -msgstr "添加到本次提交" +#: git-gui.sh:1953 +#, fuzzy +msgid "Stage To Commit" +msgstr "从本次提交移除" -#: git-gui.sh:1832 -msgid "Add Existing To Commit" -msgstr "添加默认修改文件" +#: git-gui.sh:1958 +#, fuzzy +msgid "Stage Changed Files To Commit" +msgstr "将被提交的修改" -#: git-gui.sh:1838 +#: git-gui.sh:1964 msgid "Unstage From Commit" msgstr "从本次提交移除" -#: git-gui.sh:1843 lib/index.tcl:376 +#: git-gui.sh:1969 lib/index.tcl:352 msgid "Revert Changes" msgstr "恢复修改" -#: git-gui.sh:1850 git-gui.sh:2189 git-gui.sh:2287 +#: git-gui.sh:1976 git-gui.sh:2292 git-gui.sh:2390 msgid "Sign Off" msgstr "签名" -#: git-gui.sh:1865 +#: git-gui.sh:1980 git-gui.sh:2296 +#, fuzzy +msgid "Commit@@verb" +msgstr "提交" + +#: git-gui.sh:1991 msgid "Local Merge..." msgstr "本地合并..." -#: git-gui.sh:1870 +#: git-gui.sh:1996 msgid "Abort Merge..." msgstr "取消合并..." -#: git-gui.sh:1882 +#: git-gui.sh:2008 msgid "Push..." msgstr "上传..." -#: git-gui.sh:1892 +#: git-gui.sh:2019 lib/choose_repository.tcl:41 msgid "Apple" msgstr "苹果" -#: git-gui.sh:1895 git-gui.sh:1942 lib/option.tcl:65 +#: git-gui.sh:2022 git-gui.sh:2044 lib/about.tcl:13 +#: lib/choose_repository.tcl:44 lib/choose_repository.tcl:50 #, tcl-format msgid "About %s" msgstr "关于%s" -#: git-gui.sh:1897 git-gui.sh:1903 git-gui.sh:2455 +#: git-gui.sh:2026 +msgid "Preferences..." +msgstr "" + +#: git-gui.sh:2034 git-gui.sh:2558 msgid "Options..." msgstr "选项..." -#: git-gui.sh:1917 -msgid "Running miga..." -msgstr "" - -#: git-gui.sh:1938 +#: git-gui.sh:2040 lib/choose_repository.tcl:47 msgid "Help" msgstr "帮助" -#: git-gui.sh:1979 +#: git-gui.sh:2081 msgid "Online Documentation" msgstr "在线文档" -#: git-gui.sh:2095 +#: git-gui.sh:2165 +#, tcl-format +msgid "fatal: cannot stat path %s: No such file or directory" +msgstr "" + +#: git-gui.sh:2198 msgid "Current Branch:" msgstr "当前分支:" -#: git-gui.sh:2116 -msgid "Staged Changes (Will Be Committed)" +#: git-gui.sh:2219 +#, fuzzy +msgid "Staged Changes (Will Commit)" msgstr "将被提交的修改" -#: git-gui.sh:2136 -msgid "Unstaged Changes (Will Not Be Committed)" -msgstr "不被提交的修改" +#: git-gui.sh:2239 +msgid "Unstaged Changes" +msgstr "" -#: git-gui.sh:2183 -msgid "Add Existing" -msgstr "添加默认修改文件" +#: git-gui.sh:2286 +msgid "Stage Changed" +msgstr "" -#: git-gui.sh:2229 +#: git-gui.sh:2302 lib/transport.tcl:93 lib/transport.tcl:182 +msgid "Push" +msgstr "上传" + +#: git-gui.sh:2332 msgid "Initial Commit Message:" msgstr "初始提交描述:" -#: git-gui.sh:2230 +#: git-gui.sh:2333 msgid "Amended Commit Message:" msgstr "修订提交描述:" -#: git-gui.sh:2231 +#: git-gui.sh:2334 msgid "Amended Initial Commit Message:" msgstr "修订初始提交描述:" -#: git-gui.sh:2232 +#: git-gui.sh:2335 msgid "Amended Merge Commit Message:" msgstr "修订合并提交描述:" -#: git-gui.sh:2233 +#: git-gui.sh:2336 msgid "Merge Commit Message:" msgstr "合并提交描述:" -#: git-gui.sh:2234 +#: git-gui.sh:2337 msgid "Commit Message:" msgstr "提交描述:" -#: git-gui.sh:2279 git-gui.sh:2417 lib/console.tcl:73 +#: git-gui.sh:2382 git-gui.sh:2520 lib/console.tcl:71 msgid "Copy All" msgstr "全部复制" -#: git-gui.sh:2303 lib/blame.tcl:104 +#: git-gui.sh:2406 lib/blame.tcl:104 msgid "File:" msgstr "" -#: git-gui.sh:2405 +#: git-gui.sh:2508 msgid "Refresh" msgstr "刷新" -#: git-gui.sh:2426 +#: git-gui.sh:2529 msgid "Apply/Reverse Hunk" msgstr "应用/撤消此修改块" -#: git-gui.sh:2432 +#: git-gui.sh:2535 msgid "Decrease Font Size" msgstr "缩小字体" -#: git-gui.sh:2436 +#: git-gui.sh:2539 msgid "Increase Font Size" msgstr "放大字体" -#: git-gui.sh:2441 +#: git-gui.sh:2544 msgid "Show Less Context" msgstr "显示更多diff上下文" -#: git-gui.sh:2448 +#: git-gui.sh:2551 msgid "Show More Context" msgstr "显示更少diff上下文" -#: git-gui.sh:2461 +#: git-gui.sh:2565 #, fuzzy msgid "Unstage Hunk From Commit" msgstr "从本次提交移除" -#: git-gui.sh:2463 +#: git-gui.sh:2567 #, fuzzy msgid "Stage Hunk For Commit" msgstr "从本次提交移除" -#: git-gui.sh:2473 +#: git-gui.sh:2586 msgid "Initializing..." msgstr "" +#: git-gui.sh:2677 +#, tcl-format +msgid "" +"Possible environment issues exist.\n" +"\n" +"The following environment variables are probably\n" +"going to be ignored by any Git subprocess run\n" +"by %s:\n" +"\n" +msgstr "" + +#: git-gui.sh:2707 +msgid "" +"\n" +"This is due to a known issue with the\n" +"Tcl binary distributed by Cygwin." +msgstr "" + +#: git-gui.sh:2712 +#, tcl-format +msgid "" +"\n" +"\n" +"A good replacement for %s\n" +"is placing values for the user.name and\n" +"user.email settings into your personal\n" +"~/.gitconfig file.\n" +msgstr "" + +#: lib/about.tcl:25 +msgid "git-gui - a graphical user interface for Git." +msgstr "" + #: lib/blame.tcl:77 msgid "File Viewer" msgstr "" @@ -432,6 +486,51 @@ msgstr "提交" msgid "Reading %s..." msgstr "" +#: lib/blame.tcl:473 +msgid "Loading copy/move tracking annotations..." +msgstr "" + +#: lib/blame.tcl:493 +msgid "lines annotated" +msgstr "" + +#: lib/blame.tcl:674 +msgid "Loading original location annotations..." +msgstr "" + +#: lib/blame.tcl:677 +msgid "Annotation complete." +msgstr "" + +#: lib/blame.tcl:731 +msgid "Loading annotation..." +msgstr "" + +#: lib/blame.tcl:787 +msgid "Author:" +msgstr "" + +#: lib/blame.tcl:791 +#, fuzzy +msgid "Committer:" +msgstr "提交" + +#: lib/blame.tcl:796 +msgid "Original File:" +msgstr "" + +#: lib/blame.tcl:910 +msgid "Originally By:" +msgstr "" + +#: lib/blame.tcl:916 +msgid "In File:" +msgstr "" + +#: lib/blame.tcl:921 +msgid "Copied Or Moved Here By:" +msgstr "" + #: lib/branch_checkout.tcl:14 lib/branch_checkout.tcl:19 #, fuzzy msgid "Checkout Branch" @@ -443,18 +542,17 @@ msgid "Checkout" msgstr "切换..." #: lib/branch_checkout.tcl:27 lib/branch_create.tcl:35 -#: lib/branch_delete.tcl:32 lib/branch_rename.tcl:30 lib/browser.tcl:269 -#: lib/checkout_op.tcl:519 lib/merge.tcl:176 lib/option.tcl:172 -#: lib/remote_branch_delete.tcl:42 lib/transport.tcl:92 +#: lib/branch_delete.tcl:32 lib/branch_rename.tcl:30 lib/browser.tcl:281 +#: lib/checkout_op.tcl:522 lib/choose_font.tcl:43 lib/merge.tcl:172 +#: lib/option.tcl:90 lib/remote_branch_delete.tcl:42 lib/transport.tcl:97 msgid "Cancel" msgstr "" -#: lib/branch_checkout.tcl:32 lib/browser.tcl:274 +#: lib/branch_checkout.tcl:32 lib/browser.tcl:286 msgid "Revision" msgstr "" -#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:159 -#: lib/option.tcl:274 +#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:202 #, fuzzy msgid "Options" msgstr "选项..." @@ -477,7 +575,7 @@ msgstr "当前分支:" msgid "Create New Branch" msgstr "当前分支:" -#: lib/branch_create.tcl:31 +#: lib/branch_create.tcl:31 lib/choose_repository.tcl:199 #, fuzzy msgid "Create" msgstr "新建..." @@ -511,7 +609,7 @@ msgstr "" msgid "Fast Forward Only" msgstr "" -#: lib/branch_create.tcl:85 lib/checkout_op.tcl:511 +#: lib/branch_create.tcl:85 lib/checkout_op.tcl:514 #, fuzzy msgid "Reset" msgstr "重置所有修动..." @@ -612,25 +710,31 @@ msgstr "" msgid "Failed to rename '%s'." msgstr "" -#: lib/browser.tcl:10 +#: lib/browser.tcl:17 msgid "Starting..." msgstr "" -#: lib/browser.tcl:19 +#: lib/browser.tcl:26 msgid "File Browser" msgstr "" -#: lib/browser.tcl:120 lib/browser.tcl:137 +#: lib/browser.tcl:125 lib/browser.tcl:142 #, tcl-format msgid "Loading %s..." msgstr "" -#: lib/browser.tcl:254 lib/browser.tcl:260 +#: lib/browser.tcl:186 +msgid "[Up To Parent]" +msgstr "" + +#: lib/browser.tcl:266 lib/browser.tcl:272 #, fuzzy msgid "Browse Branch Files" msgstr "浏览当前分支文件" -#: lib/browser.tcl:265 +#: lib/browser.tcl:277 lib/choose_repository.tcl:215 +#: lib/choose_repository.tcl:305 lib/choose_repository.tcl:315 +#: lib/choose_repository.tcl:811 msgid "Browse" msgstr "" @@ -639,7 +743,12 @@ msgstr "" msgid "Fetching %s from %s" msgstr "" -#: lib/checkout_op.tcl:140 lib/console.tcl:81 lib/database.tcl:31 +#: lib/checkout_op.tcl:127 +#, tcl-format +msgid "fatal: Cannot resolve %s" +msgstr "" + +#: lib/checkout_op.tcl:140 lib/console.tcl:79 lib/database.tcl:31 msgid "Close" msgstr "" @@ -648,7 +757,7 @@ msgstr "" msgid "Branch '%s' does not exist." msgstr "" -#: lib/checkout_op.tcl:205 +#: lib/checkout_op.tcl:206 #, tcl-format msgid "" "Branch '%s' already exists.\n" @@ -657,21 +766,21 @@ msgid "" "A merge is required." msgstr "" -#: lib/checkout_op.tcl:219 +#: lib/checkout_op.tcl:220 #, tcl-format msgid "Merge strategy '%s' not supported." msgstr "" -#: lib/checkout_op.tcl:238 +#: lib/checkout_op.tcl:239 #, tcl-format msgid "Failed to update '%s'." msgstr "" -#: lib/checkout_op.tcl:250 -msgid "Index is already locked." +#: lib/checkout_op.tcl:251 +msgid "Staging area (index) is already locked." msgstr "" -#: lib/checkout_op.tcl:265 +#: lib/checkout_op.tcl:266 msgid "" "Last scanned state does not match repository state.\n" "\n" @@ -681,21 +790,26 @@ msgid "" "The rescan will be automatically started now.\n" msgstr "" -#: lib/checkout_op.tcl:352 +#: lib/checkout_op.tcl:322 +#, tcl-format +msgid "Updating working directory to '%s'..." +msgstr "" + +#: lib/checkout_op.tcl:353 #, tcl-format msgid "Aborted checkout of '%s' (file level merging is required)." msgstr "" -#: lib/checkout_op.tcl:353 +#: lib/checkout_op.tcl:354 msgid "File level merge required." msgstr "" -#: lib/checkout_op.tcl:357 +#: lib/checkout_op.tcl:358 #, tcl-format msgid "Staying on branch '%s'." msgstr "" -#: lib/checkout_op.tcl:426 +#: lib/checkout_op.tcl:429 msgid "" "You are no longer on a local branch.\n" "\n" @@ -703,25 +817,30 @@ msgid "" "Checkout'." msgstr "" -#: lib/checkout_op.tcl:475 +#: lib/checkout_op.tcl:446 +#, fuzzy, tcl-format +msgid "Checked out '%s'." +msgstr "切换..." + +#: lib/checkout_op.tcl:478 #, tcl-format msgid "Resetting '%s' to '%s' will lose the following commits:" msgstr "" -#: lib/checkout_op.tcl:497 +#: lib/checkout_op.tcl:500 msgid "Recovering lost commits may not be easy." msgstr "" -#: lib/checkout_op.tcl:502 +#: lib/checkout_op.tcl:505 #, tcl-format msgid "Reset '%s'?" msgstr "" -#: lib/checkout_op.tcl:507 lib/merge.tcl:171 +#: lib/checkout_op.tcl:510 lib/merge.tcl:164 msgid "Visualize" msgstr "" -#: lib/checkout_op.tcl:575 +#: lib/checkout_op.tcl:578 #, tcl-format msgid "" "Failed to set current branch.\n" @@ -732,41 +851,286 @@ msgid "" "This should not have occurred. %s will now close and give up." msgstr "" -#: lib/choose_rev.tcl:35 +#: lib/choose_font.tcl:39 +#, fuzzy +msgid "Select" +msgstr "全选" + +#: lib/choose_font.tcl:53 +msgid "Font Family" +msgstr "" + +#: lib/choose_font.tcl:73 +#, fuzzy +msgid "Font Size" +msgstr "缩小字体" + +#: lib/choose_font.tcl:90 +msgid "Font Example" +msgstr "" + +#: lib/choose_font.tcl:101 +msgid "" +"This is example text.\n" +"If you like this text, it can be your font." +msgstr "" + +#: lib/choose_repository.tcl:25 +msgid "Git Gui" +msgstr "" + +#: lib/choose_repository.tcl:69 lib/choose_repository.tcl:204 +#, fuzzy +msgid "Create New Repository" +msgstr "版本树" + +#: lib/choose_repository.tcl:74 lib/choose_repository.tcl:291 +#, fuzzy +msgid "Clone Existing Repository" +msgstr "版本树" + +#: lib/choose_repository.tcl:79 lib/choose_repository.tcl:800 +#, fuzzy +msgid "Open Existing Repository" +msgstr "版本树" + +#: lib/choose_repository.tcl:91 +msgid "Next >" +msgstr "" + +#: lib/choose_repository.tcl:152 +#, tcl-format +msgid "Location %s already exists." +msgstr "" + +#: lib/choose_repository.tcl:158 lib/choose_repository.tcl:165 +#: lib/choose_repository.tcl:172 +#, tcl-format +msgid "Failed to create repository %s:" +msgstr "" + +#: lib/choose_repository.tcl:209 lib/choose_repository.tcl:309 +msgid "Directory:" +msgstr "" + +#: lib/choose_repository.tcl:238 lib/choose_repository.tcl:363 +#: lib/choose_repository.tcl:834 +#, fuzzy +msgid "Git Repository" +msgstr "版本树" + +#: lib/choose_repository.tcl:253 lib/choose_repository.tcl:260 +#, tcl-format +msgid "Directory %s already exists." +msgstr "" + +#: lib/choose_repository.tcl:265 +#, tcl-format +msgid "File %s already exists." +msgstr "" + +#: lib/choose_repository.tcl:286 +msgid "Clone" +msgstr "" + +#: lib/choose_repository.tcl:299 +msgid "URL:" +msgstr "" + +#: lib/choose_repository.tcl:319 +msgid "Clone Type:" +msgstr "" + +#: lib/choose_repository.tcl:325 +msgid "Standard (Fast, Semi-Redundant, Hardlinks)" +msgstr "" + +#: lib/choose_repository.tcl:331 +msgid "Full Copy (Slower, Redundant Backup)" +msgstr "" + +#: lib/choose_repository.tcl:337 +msgid "Shared (Fastest, Not Recommended, No Backup)" +msgstr "" + +#: lib/choose_repository.tcl:369 lib/choose_repository.tcl:418 +#: lib/choose_repository.tcl:560 lib/choose_repository.tcl:630 +#: lib/choose_repository.tcl:840 lib/choose_repository.tcl:848 +#, tcl-format +msgid "Not a Git repository: %s" +msgstr "" + +#: lib/choose_repository.tcl:405 +msgid "Standard only available for local repository." +msgstr "" + +#: lib/choose_repository.tcl:409 +msgid "Shared only available for local repository." +msgstr "" + +#: lib/choose_repository.tcl:439 +msgid "Failed to configure origin" +msgstr "" + +#: lib/choose_repository.tcl:451 +msgid "Counting objects" +msgstr "" + +#: lib/choose_repository.tcl:452 +msgid "buckets" +msgstr "" + +#: lib/choose_repository.tcl:476 +#, tcl-format +msgid "Unable to copy objects/info/alternates: %s" +msgstr "" + +#: lib/choose_repository.tcl:512 +#, tcl-format +msgid "Nothing to clone from %s." +msgstr "" + +#: lib/choose_repository.tcl:514 lib/choose_repository.tcl:728 +#: lib/choose_repository.tcl:740 +msgid "The 'master' branch has not been initialized." +msgstr "" + +#: lib/choose_repository.tcl:527 +msgid "Hardlinks are unavailable. Falling back to copying." +msgstr "" + +#: lib/choose_repository.tcl:539 +#, tcl-format +msgid "Cloning from %s" +msgstr "" + +#: lib/choose_repository.tcl:570 +#, fuzzy +msgid "Copying objects" +msgstr "压缩数据库" + +#: lib/choose_repository.tcl:571 +msgid "KiB" +msgstr "" + +#: lib/choose_repository.tcl:595 +#, tcl-format +msgid "Unable to copy object: %s" +msgstr "" + +#: lib/choose_repository.tcl:605 +msgid "Linking objects" +msgstr "" + +#: lib/choose_repository.tcl:606 +msgid "objects" +msgstr "" + +#: lib/choose_repository.tcl:614 +#, tcl-format +msgid "Unable to hardlink object: %s" +msgstr "" + +#: lib/choose_repository.tcl:669 +msgid "Cannot fetch branches and objects. See console output for details." +msgstr "" + +#: lib/choose_repository.tcl:680 +msgid "Cannot fetch tags. See console output for details." +msgstr "" + +#: lib/choose_repository.tcl:704 +msgid "Cannot determine HEAD. See console output for details." +msgstr "" + +#: lib/choose_repository.tcl:713 +#, tcl-format +msgid "Unable to cleanup %s" +msgstr "" + +#: lib/choose_repository.tcl:719 +msgid "Clone failed." +msgstr "" + +#: lib/choose_repository.tcl:726 +msgid "No default branch obtained." +msgstr "" + +#: lib/choose_repository.tcl:737 +#, tcl-format +msgid "Cannot resolve %s as a commit." +msgstr "" + +#: lib/choose_repository.tcl:749 +msgid "Creating working directory" +msgstr "" + +#: lib/choose_repository.tcl:750 lib/index.tcl:15 lib/index.tcl:80 +#: lib/index.tcl:149 +msgid "files" +msgstr "" + +#: lib/choose_repository.tcl:779 +msgid "Initial file checkout failed." +msgstr "" + +#: lib/choose_repository.tcl:795 +msgid "Open" +msgstr "" + +#: lib/choose_repository.tcl:805 +#, fuzzy +msgid "Repository:" +msgstr "版本树" + +#: lib/choose_repository.tcl:854 +#, tcl-format +msgid "Failed to open repository %s:" +msgstr "" + +#: lib/choose_rev.tcl:53 msgid "This Detached Checkout" msgstr "" -#: lib/choose_rev.tcl:42 +#: lib/choose_rev.tcl:60 msgid "Revision Expression:" msgstr "" -#: lib/choose_rev.tcl:56 +#: lib/choose_rev.tcl:74 #, fuzzy msgid "Local Branch" msgstr "分支" -#: lib/choose_rev.tcl:61 +#: lib/choose_rev.tcl:79 #, fuzzy msgid "Tracking Branch" msgstr "当前分支:" -#: lib/choose_rev.tcl:66 +#: lib/choose_rev.tcl:84 lib/choose_rev.tcl:537 msgid "Tag" msgstr "" -#: lib/choose_rev.tcl:227 +#: lib/choose_rev.tcl:317 #, tcl-format msgid "Invalid revision: %s" msgstr "" -#: lib/choose_rev.tcl:248 +#: lib/choose_rev.tcl:338 msgid "No revision selected." msgstr "" -#: lib/choose_rev.tcl:256 +#: lib/choose_rev.tcl:346 msgid "Revision expression is empty." msgstr "" +#: lib/choose_rev.tcl:530 +msgid "Updated" +msgstr "" + +#: lib/choose_rev.tcl:558 +msgid "URL" +msgstr "" + #: lib/commit.tcl:9 msgid "" "There is nothing to amend.\n" @@ -811,8 +1175,8 @@ msgstr "" msgid "" "Unmerged files cannot be committed.\n" "\n" -"File %s has merge conflicts. You must resolve them and add the file before " -"committing.\n" +"File %s has merge conflicts. You must resolve them and stage the file " +"before committing.\n" msgstr "" #: lib/commit.tcl:162 @@ -827,7 +1191,7 @@ msgstr "" msgid "" "No changes to commit.\n" "\n" -"You must add at least 1 file before you can commit.\n" +"You must stage at least 1 file before you can commit.\n" msgstr "" #: lib/commit.tcl:183 @@ -845,6 +1209,11 @@ msgstr "" msgid "write-tree failed:" msgstr "" +#: lib/commit.tcl:275 +#, tcl-format +msgid "Commit %s appears to be corrupt" +msgstr "" + #: lib/commit.tcl:279 msgid "" "No changes to commit.\n" @@ -858,6 +1227,11 @@ msgstr "" msgid "No changes to commit." msgstr "" +#: lib/commit.tcl:303 +#, tcl-format +msgid "warning: Tcl does not support encoding '%s'." +msgstr "" + #: lib/commit.tcl:317 msgid "commit-tree failed:" msgstr "" @@ -871,15 +1245,15 @@ msgstr "" msgid "Created commit %s: %s" msgstr "" -#: lib/console.tcl:55 +#: lib/console.tcl:57 msgid "Working... please wait..." msgstr "" -#: lib/console.tcl:184 +#: lib/console.tcl:183 msgid "Success" msgstr "" -#: lib/console.tcl:194 +#: lib/console.tcl:196 msgid "Error: Command Failed" msgstr "" @@ -920,6 +1294,22 @@ msgstr "压缩数据库" msgid "Verifying the object database with fsck-objects" msgstr "" +#: lib/database.tcl:108 +#, tcl-format +msgid "" +"This repository currently has approximately %i loose objects.\n" +"\n" +"To maintain optimal performance it is strongly recommended that you compress " +"the database when more than %i loose objects exist.\n" +"\n" +"Compress the database now?" +msgstr "" + +#: lib/date.tcl:25 +#, tcl-format +msgid "Invalid date from Git: %s" +msgstr "" + #: lib/diff.tcl:42 #, tcl-format msgid "" @@ -934,19 +1324,37 @@ msgid "" "the same state." msgstr "" -#: lib/diff.tcl:97 +#: lib/diff.tcl:81 +#, tcl-format +msgid "Loading diff of %s..." +msgstr "" + +#: lib/diff.tcl:114 lib/diff.tcl:184 +#, tcl-format +msgid "Unable to display %s" +msgstr "" + +#: lib/diff.tcl:115 msgid "Error loading file:" msgstr "" -#: lib/diff.tcl:162 +#: lib/diff.tcl:122 +msgid "Git Repository (subproject)" +msgstr "" + +#: lib/diff.tcl:134 +msgid "* Binary file (not showing content)." +msgstr "" + +#: lib/diff.tcl:185 msgid "Error loading diff:" msgstr "" -#: lib/diff.tcl:278 +#: lib/diff.tcl:302 msgid "Failed to unstage selected hunk." msgstr "" -#: lib/diff.tcl:285 +#: lib/diff.tcl:309 msgid "Failed to stage selected hunk." msgstr "" @@ -962,32 +1370,42 @@ msgstr "" msgid "You must correct the above errors before committing." msgstr "" -#: lib/index.tcl:364 +#: lib/index.tcl:241 +#, fuzzy, tcl-format +msgid "Unstaging %s from commit" +msgstr "从本次提交移除" + +#: lib/index.tcl:285 +#, tcl-format +msgid "Adding %s" +msgstr "" + +#: lib/index.tcl:340 #, fuzzy, tcl-format msgid "Revert changes in file %s?" msgstr "恢复修改" -#: lib/index.tcl:366 +#: lib/index.tcl:342 #, tcl-format msgid "Revert changes in these %i files?" msgstr "" -#: lib/index.tcl:372 -msgid "Any unadded changes will be permanently lost by the revert." +#: lib/index.tcl:348 +msgid "Any unstaged changes will be permanently lost by the revert." msgstr "" -#: lib/index.tcl:375 +#: lib/index.tcl:351 msgid "Do Nothing" msgstr "" -#: lib/merge.tcl:14 +#: lib/merge.tcl:13 msgid "" "Cannot merge while amending.\n" "\n" "You must finish amending this commit before starting any type of merge.\n" msgstr "" -#: lib/merge.tcl:28 +#: lib/merge.tcl:27 msgid "" "Last scanned state does not match repository state.\n" "\n" @@ -997,18 +1415,18 @@ msgid "" "The rescan will be automatically started now.\n" msgstr "" -#: lib/merge.tcl:45 +#: lib/merge.tcl:44 #, tcl-format msgid "" "You are in the middle of a conflicted merge.\n" "\n" "File %s has merge conflicts.\n" "\n" -"You must resolve them, add the file, and commit to complete the current " +"You must resolve them, stage the file, and commit to complete the current " "merge. Only then can you begin another merge.\n" msgstr "" -#: lib/merge.tcl:55 +#: lib/merge.tcl:54 #, tcl-format msgid "" "You are in the middle of a change.\n" @@ -1019,37 +1437,41 @@ msgid "" "will help you abort a failed merge, should the need arise.\n" msgstr "" -#: lib/merge.tcl:94 +#: lib/merge.tcl:106 +#, tcl-format +msgid "%s of %s" +msgstr "" + +#: lib/merge.tcl:119 #, tcl-format msgid "Merging %s and %s" msgstr "" -#: lib/merge.tcl:106 +#: lib/merge.tcl:131 msgid "Merge completed successfully." msgstr "" -#: lib/merge.tcl:108 +#: lib/merge.tcl:133 msgid "Merge failed. Conflict resolution is required." msgstr "" -#: lib/merge.tcl:166 +#: lib/merge.tcl:158 #, tcl-format msgid "Merge Into %s" msgstr "" -#: lib/merge.tcl:181 lib/transport.tcl:98 -#, fuzzy -msgid "Source Branches" -msgstr "当前分支:" +#: lib/merge.tcl:177 +msgid "Revision To Merge" +msgstr "" -#: lib/merge.tcl:240 +#: lib/merge.tcl:212 msgid "" "Cannot abort while amending.\n" "\n" "You must finish amending this commit.\n" msgstr "" -#: lib/merge.tcl:250 +#: lib/merge.tcl:222 msgid "" "Abort merge?\n" "\n" @@ -1058,90 +1480,120 @@ msgid "" "Continue with aborting the current merge?" msgstr "" -#: lib/merge.tcl:256 +#: lib/merge.tcl:228 msgid "" -"Abort commit?\n" +"Reset changes?\n" "\n" -"Aborting the current commit will cause *ALL* uncommitted changes to be " -"lost.\n" +"Resetting the changes will cause *ALL* uncommitted changes to be lost.\n" "\n" -"Continue with aborting the current commit?" +"Continue with resetting the current changes?" msgstr "" -#: lib/merge.tcl:267 -msgid "Aborting... please wait..." +#: lib/merge.tcl:239 +msgid "Aborting" msgstr "" -#: lib/merge.tcl:290 +#: lib/merge.tcl:266 +msgid "Abort failed." +msgstr "" + +#: lib/merge.tcl:268 msgid "Abort completed. Ready." msgstr "" -#: lib/option.tcl:77 -msgid "git-gui - a graphical user interface for Git." -msgstr "" - -#: lib/option.tcl:164 +#: lib/option.tcl:82 msgid "Restore Defaults" msgstr "" -#: lib/option.tcl:168 +#: lib/option.tcl:86 msgid "Save" msgstr "" -#: lib/option.tcl:178 +#: lib/option.tcl:96 #, fuzzy, tcl-format msgid "%s Repository" msgstr "版本树" -#: lib/option.tcl:179 +#: lib/option.tcl:97 msgid "Global (All Repositories)" msgstr "" -#: lib/option.tcl:185 +#: lib/option.tcl:103 msgid "User Name" msgstr "" -#: lib/option.tcl:186 +#: lib/option.tcl:104 msgid "Email Address" msgstr "" -#: lib/option.tcl:188 +#: lib/option.tcl:106 #, fuzzy msgid "Summarize Merge Commits" msgstr "修订合并提交描述:" -#: lib/option.tcl:189 +#: lib/option.tcl:107 msgid "Merge Verbosity" msgstr "" -#: lib/option.tcl:190 +#: lib/option.tcl:108 msgid "Show Diffstat After Merge" msgstr "" -#: lib/option.tcl:192 +#: lib/option.tcl:110 msgid "Trust File Modification Timestamps" msgstr "" -#: lib/option.tcl:193 +#: lib/option.tcl:111 msgid "Prune Tracking Branches During Fetch" msgstr "" -#: lib/option.tcl:194 +#: lib/option.tcl:112 msgid "Match Tracking Branches" msgstr "" -#: lib/option.tcl:195 +#: lib/option.tcl:113 msgid "Number of Diff Context Lines" msgstr "" -#: lib/option.tcl:196 +#: lib/option.tcl:114 msgid "New Branch Name Template" msgstr "" -#: lib/option.tcl:305 +#: lib/option.tcl:176 +msgid "Change Font" +msgstr "" + +#: lib/option.tcl:180 +#, tcl-format +msgid "Choose %s" +msgstr "" + +#: lib/option.tcl:186 +msgid "pt." +msgstr "" + +#: lib/option.tcl:200 +msgid "Preferences" +msgstr "" + +#: lib/option.tcl:235 msgid "Failed to completely save options:" msgstr "" +#: lib/remote.tcl:165 +msgid "Prune from" +msgstr "" + +#: lib/remote.tcl:170 +#, fuzzy +msgid "Fetch from" +msgstr "导入" + +#: lib/remote.tcl:213 +#, fuzzy +msgid "Push to" +msgstr "上传" + #: lib/remote_branch_delete.tcl:29 lib/remote_branch_delete.tcl:34 msgid "Delete Remote Branch" msgstr "" @@ -1151,11 +1603,11 @@ msgstr "" msgid "From Repository" msgstr "版本树" -#: lib/remote_branch_delete.tcl:50 lib/transport.tcl:118 +#: lib/remote_branch_delete.tcl:50 lib/transport.tcl:123 msgid "Remote:" msgstr "" -#: lib/remote_branch_delete.tcl:66 lib/transport.tcl:133 +#: lib/remote_branch_delete.tcl:66 lib/transport.tcl:138 msgid "Arbitrary URL:" msgstr "" @@ -1181,6 +1633,14 @@ msgstr "" msgid "A branch is required for 'Merged Into'." msgstr "" +#: lib/remote_branch_delete.tcl:184 +#, tcl-format +msgid "" +"The following branches are not completely merged into %s:\n" +"\n" +" - %s" +msgstr "" + #: lib/remote_branch_delete.tcl:189 #, tcl-format msgid "" @@ -1213,21 +1673,6 @@ msgstr "" msgid "Scanning %s..." msgstr "" -#: lib/remote.tcl:156 -#, tcl-format -msgid "Fetch from %s..." -msgstr "" - -#: lib/remote.tcl:166 -#, tcl-format -msgid "Prune from %s..." -msgstr "" - -#: lib/remote.tcl:200 -#, fuzzy, tcl-format -msgid "Push to %s..." -msgstr "上传..." - #: lib/shortcut.tcl:26 lib/shortcut.tcl:74 msgid "Cannot write script:" msgstr "" @@ -1236,49 +1681,89 @@ msgstr "" msgid "Cannot write icon:" msgstr "" -#: lib/status_bar.tcl:58 +#: lib/status_bar.tcl:83 #, tcl-format msgid "%s ... %*i of %*i %s (%3i%%)" msgstr "" +#: lib/transport.tcl:6 +#, fuzzy, tcl-format +msgid "fetch %s" +msgstr "导入" + #: lib/transport.tcl:7 #, tcl-format msgid "Fetching new changes from %s" msgstr "" +#: lib/transport.tcl:18 +#, tcl-format +msgid "remote prune %s" +msgstr "" + #: lib/transport.tcl:19 #, tcl-format msgid "Pruning tracking branches deleted from %s" msgstr "" +#: lib/transport.tcl:25 lib/transport.tcl:71 +#, tcl-format +msgid "push %s" +msgstr "" + #: lib/transport.tcl:26 #, tcl-format msgid "Pushing changes to %s" msgstr "" -#: lib/transport.tcl:68 +#: lib/transport.tcl:72 #, tcl-format msgid "Pushing %s %s to %s" msgstr "" -#: lib/transport.tcl:84 +#: lib/transport.tcl:89 #, fuzzy msgid "Push Branches" msgstr "分支" -#: lib/transport.tcl:115 +#: lib/transport.tcl:103 +#, fuzzy +msgid "Source Branches" +msgstr "当前分支:" + +#: lib/transport.tcl:120 #, fuzzy msgid "Destination Repository" msgstr "版本树" -#: lib/transport.tcl:153 +#: lib/transport.tcl:158 msgid "Transfer Options" msgstr "" -#: lib/transport.tcl:155 +#: lib/transport.tcl:160 +msgid "Force overwrite existing branch (may discard changes)" +msgstr "" + +#: lib/transport.tcl:164 msgid "Use thin pack (for slow network connections)" msgstr "" -#: lib/transport.tcl:159 +#: lib/transport.tcl:168 msgid "Include tags" msgstr "" + +#~ msgid "Add To Commit" +#~ msgstr "添加到本次提交" + +#~ msgid "Add Existing To Commit" +#~ msgstr "添加默认修改文件" + +#~ msgid "Unstaged Changes (Will Not Be Committed)" +#~ msgstr "不被提交的修改" + +#~ msgid "Add Existing" +#~ msgstr "添加默认修改文件" + +#, fuzzy +#~ msgid "Push to %s..." +#~ msgstr "上传..." From 4dcf4e0ed44183f846878a3845e8a71b61c34edb Mon Sep 17 00:00:00 2001 From: Michele Ballabio Date: Wed, 10 Oct 2007 15:04:16 +0200 Subject: [PATCH 0156/1490] git-gui: update Italian translation An Italian glossary was also added. Some changes: * commit (verb): (creare una) nuova revisione * commit (noun): revisione * checkout: attivazione * tracking branch: duplicato locale di ramo remoto * repository: archivio * some terms are used with more consistency Signed-off-by: Michele Ballabio Signed-off-by: Shawn O. Pearce --- po/glossary/it.po | 180 +++++++++++++++++ po/it.po | 493 +++++++++++++++++++++++----------------------- 2 files changed, 429 insertions(+), 244 deletions(-) create mode 100644 po/glossary/it.po diff --git a/po/glossary/it.po b/po/glossary/it.po new file mode 100644 index 0000000000..8e3d9a2f07 --- /dev/null +++ b/po/glossary/it.po @@ -0,0 +1,180 @@ +# Translation of git-gui glossary to Italian +# Copyright (C) 2007 Shawn Pearce, et al. +# This file is distributed under the same license as the git package. +# Christian Stimming , 2007 +# +msgid "" +msgstr "" +"Project-Id-Version: git-gui glossary\n" +"POT-Creation-Date: 2007-10-05 22:30+0200\n" +"PO-Revision-Date: 2007-10-10 15:24+0200\n" +"Last-Translator: Michele Ballabio \n" +"Language-Team: Italian \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. "English Definition (Dear translator: This file will never be visible to the user! It should only serve as a tool for you, the translator. Nothing more.)" +msgid "" +"English Term (Dear translator: This file will never be visible to the user!)" +msgstr "" +"Traduzione italiana.\n" +"Altri SCM in italiano:\n" +" http://tortoisesvn.tigris.org/svn/tortoisesvn/trunk/Languages/Tortoise_it." +"po (username=guest, password empty),\n" +" http://tortoisecvs.cvs.sourceforge.net/tortoisecvs/po/TortoiseCVS/it_IT.po?" +"view=markup ,\n" +" http://rapidsvn.tigris.org/svn/rapidsvn/trunk/src/locale/it_IT/rapidsvn.po " +"(username=guest, password empty)" + +#. "" +msgid "amend" +msgstr "correggere, correzione" + +#. "" +msgid "annotate" +msgstr "annotare, annotazione" + +#. "A 'branch' is an active line of development." +msgid "branch [noun]" +msgstr "ramo, diramazione, ramificazione" + +#. "" +msgid "branch [verb]" +msgstr "creare ramo, ramificare, diramare" + +#. "" +msgid "checkout [noun]" +msgstr "attivazione, checkout, revisione attiva, prelievo (TortoiseCVS)?" + +#. "The action of updating the working tree to a revision which was stored in the object database." +msgid "checkout [verb]" +msgstr "" +"attivare, effettuare un checkout, attivare revisione, prelevare (TortoiseCVS), " +"ritirare (TSVN)?" + +#. "" +msgid "clone [verb]" +msgstr "clonare" + +#. "A single point in the git history." +msgid "commit [noun]" +msgstr "revisione, commit, deposito (TortoiseCVS), invio (TSVN)?" + +#. "The action of storing a new snapshot of the project's state in the git history." +msgid "commit [verb]" +msgstr "" +"creare una nuova revisione, archiviare, effettuare un commit, depositare " +"(nel server), fare un deposito (TortoiseCVS), inviare (TSVN)?" + +#. "" +msgid "diff [noun]" +msgstr "differenza, confronto, comparazione, raffronto" + +#. "" +msgid "diff [verb]" +msgstr "confronta, mostra le differenze" + +#. "A fast-forward is a special type of merge where you have a revision and you are merging another branch's changes that happen to be a descendant of what you have." +msgid "fast forward merge" +msgstr "fusione in 'fast-forward', fusione in avanti veloce" + +#. "Fetching a branch means to get the branch's head from a remote repository, to find out which objects are missing from the local object database, and to get them, too." +msgid "fetch" +msgstr "recuperare, prelevare, prendere da, recuperare (TSVN)" + +#. "A collection of files. The index is a stored version of your working tree." +msgid "index (in git-gui: staging area)" +msgstr "indice" + +#. "A successful merge results in the creation of a new commit representing the result of the merge." +msgid "merge [noun]" +msgstr "fusione, unione" + +#. "To bring the contents of another branch into the current branch." +msgid "merge [verb]" +msgstr "effettuare la fusione, unire, fondere, eseguire la fusione" + +#. "" +msgid "message" +msgstr "messaggio, commento" + +#. "" +msgid "prune" +msgstr "potatura" + +#. "Pulling a branch means to fetch it and merge it." +msgid "pull" +msgstr "" +"prendi (recupera) e fondi (unisci)? (in pratica una traduzione di fetch + " +"merge)" + +#. "Pushing a branch means to get the branch's head ref from a remote repository, and ... (well, can someone please explain it for mere mortals?)" +msgid "push" +msgstr "propaga" + +#. "" +msgid "redo" +msgstr "ripeti, rifai" + +#. "A collection of refs (?) together with an object database containing all objects which are reachable from the refs... (oops, you've lost me here. Again, please an explanation for mere mortals?)" +msgid "repository" +msgstr "archivio, repository, database? deposito (rapidsvn)?" + +#. "" +msgid "reset" +msgstr "ripristinare, annullare, azzerare, ripristinare" + +#. "" +msgid "revert" +msgstr "" +"annullare, inverti (rapidsvn), ritorna allo stato precedente, annulla le " +"modifiche della revisione" + +#. "A particular state of files and directories which was stored in the object database." +msgid "revision" +msgstr "revisione (TortoiseSVN)" + +#. "" +msgid "sign off" +msgstr "sign off, firma" + +#. "" +msgid "staging area" +msgstr "" +"area di preparazione, zona di preparazione, modifiche in preparazione? " +"modifiche in allestimento?" + +#. "" +msgid "status" +msgstr "stato" + +#. "A ref pointing to a tag or commit object" +msgid "tag [noun]" +msgstr "etichetta, etichettatura (TortoiseCVS)" + +#. "" +msgid "tag [verb]" +msgstr "etichettare" + +#. "A regular git branch that is used to follow changes from another repository." +msgid "tracking branch" +msgstr "" +"duplicato locale di ramo remoto, ramo in 'tracking', ramo inseguitore? ramo di {inseguimento,allineamento," +"rilevamento,puntamento}?" + +#. "" +msgid "undo" +msgstr "annulla" + +#. "" +msgid "update" +msgstr "aggiornamento, aggiornare" + +#. "" +msgid "verify" +msgstr "verifica, verificare" + +#. "The tree of actual checked out files." +msgid "working copy, working tree" +msgstr "directory di lavoro, copia di lavoro" diff --git a/po/it.po b/po/it.po index d959019aab..7668414104 100644 --- a/po/it.po +++ b/po/it.po @@ -9,8 +9,8 @@ msgid "" msgstr "" "Project-Id-Version: git-gui\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2007-10-10 04:04-0400\n" -"PO-Revision-Date: 2007-08-09 00:27+0200\n" +"POT-Creation-Date: 2007-10-10 14:42+0200\n" +"PO-Revision-Date: 2007-10-10 15:27+0200\n" "Last-Translator: Paolo Ciarrocchi \n" "Language-Team: Italian \n" "MIME-Version: 1.0\n" @@ -20,12 +20,12 @@ msgstr "" #: git-gui.sh:41 git-gui.sh:634 git-gui.sh:648 git-gui.sh:661 git-gui.sh:744 #: git-gui.sh:763 msgid "git-gui: fatal error" -msgstr "" +msgstr "git-gui: errore grave" #: git-gui.sh:595 -#, fuzzy, tcl-format +#, tcl-format msgid "Invalid font specified in %s:" -msgstr "Caratteri non validi specificati nella gui.%s:" +msgstr "Caratteri non validi specificati in %s:" #: git-gui.sh:620 msgid "Main Font" @@ -56,7 +56,7 @@ msgid "" msgstr "" "La versione di GIT non può essere determinata.\n" "\n" -"%s sostiene che la versione è '%s'.\n" +"%s riporta che la versione è '%s'.\n" "\n" "%s richiede almeno Git 1.5.0 o superiore.\n" "\n" @@ -67,9 +67,8 @@ msgid "Git directory not found:" msgstr "Non trovo la directory di git: " #: git-gui.sh:860 -#, fuzzy msgid "Cannot move to top of working directory:" -msgstr "Impossibile usare una .git directory strana:" +msgstr "Impossibile spostarsi sulla directory principale del progetto:" #: git-gui.sh:867 msgid "Cannot use funny .git directory:" @@ -97,23 +96,23 @@ msgstr "Non modificato" #: git-gui.sh:1527 msgid "Modified, not staged" -msgstr "Modificato, non pronto per il commit" +msgstr "Modificato, non preparato per una nuova revisione" #: git-gui.sh:1528 git-gui.sh:1533 msgid "Staged for commit" -msgstr "Pronto per il commit" +msgstr "Preparato per una nuova revisione" #: git-gui.sh:1529 git-gui.sh:1534 msgid "Portions staged for commit" -msgstr "Parti pronte per il commit" +msgstr "Parti preparate per una nuova revisione" #: git-gui.sh:1530 git-gui.sh:1535 msgid "Staged for commit, missing" -msgstr "Pronto per il commit, mancante" +msgstr "Preparato per una nuova revisione, mancante" #: git-gui.sh:1532 msgid "Untracked, not staged" -msgstr "Non tracciato, non pronto per il commit" +msgstr "Non tracciato, non preparato per una nuova revisione" #: git-gui.sh:1537 msgid "Missing" @@ -121,11 +120,11 @@ msgstr "Mancante" #: git-gui.sh:1538 msgid "Staged for removal" -msgstr "Pronto per la rimozione" +msgstr "Preparato per la rimozione" #: git-gui.sh:1539 msgid "Staged for removal, still present" -msgstr "Pronto alla rimozione, ancora presente" +msgstr "Preparato alla rimozione, ancora presente" #: git-gui.sh:1541 git-gui.sh:1542 git-gui.sh:1543 git-gui.sh:1544 msgid "Requires merge resolution" @@ -159,18 +158,16 @@ msgid "Branch" msgstr "Ramo" #: git-gui.sh:1794 lib/choose_rev.tcl:547 -#, fuzzy msgid "Commit@@noun" -msgstr "Commit" +msgstr "Revisione" #: git-gui.sh:1797 lib/merge.tcl:121 lib/merge.tcl:150 lib/merge.tcl:168 msgid "Merge" msgstr "Fusione (Merge)" #: git-gui.sh:1798 lib/choose_rev.tcl:556 -#, fuzzy msgid "Remote" -msgstr "Remoto:" +msgstr "Remoto" #: git-gui.sh:1807 msgid "Browse Current Branch's Files" @@ -200,15 +197,15 @@ msgstr "Visualizza la cronologia di %s" #: git-gui.sh:1834 lib/database.tcl:27 lib/database.tcl:67 msgid "Database Statistics" -msgstr "Statistiche del database" +msgstr "Statistiche dell'archivio" #: git-gui.sh:1837 lib/database.tcl:34 msgid "Compress Database" -msgstr "Comprimi il database" +msgstr "Comprimi l'archivio" #: git-gui.sh:1840 msgid "Verify Database" -msgstr "Verifica il database" +msgstr "Verifica l'archivio" #: git-gui.sh:1847 git-gui.sh:1851 git-gui.sh:1855 lib/shortcut.tcl:9 #: lib/shortcut.tcl:45 lib/shortcut.tcl:84 @@ -255,7 +252,7 @@ msgstr "Crea..." #: git-gui.sh:1902 msgid "Checkout..." -msgstr "Checkout..." +msgstr "Attiva..." #: git-gui.sh:1908 msgid "Rename..." @@ -271,11 +268,11 @@ msgstr "Ripristina..." #: git-gui.sh:1930 git-gui.sh:2313 msgid "New Commit" -msgstr "Nuovo commit" +msgstr "Nuova revisione" #: git-gui.sh:1938 git-gui.sh:2320 msgid "Amend Last Commit" -msgstr "Correggi l'ultimo commit" +msgstr "Correggi l'ultima revisione" #: git-gui.sh:1947 git-gui.sh:2280 lib/remote_branch_delete.tcl:99 msgid "Rescan" @@ -283,15 +280,15 @@ msgstr "Analizza nuovamente" #: git-gui.sh:1953 msgid "Stage To Commit" -msgstr "Prepara per il commit" +msgstr "Prepara per una nuova revisione" #: git-gui.sh:1958 msgid "Stage Changed Files To Commit" -msgstr "Prepara per il commit i file modificati" +msgstr "Prepara i file modificati per una nuova revisione" #: git-gui.sh:1964 msgid "Unstage From Commit" -msgstr "Non pronto per il commit" +msgstr "Annulla preparazione" #: git-gui.sh:1969 lib/index.tcl:352 msgid "Revert Changes" @@ -302,17 +299,16 @@ msgid "Sign Off" msgstr "Sign Off" #: git-gui.sh:1980 git-gui.sh:2296 -#, fuzzy msgid "Commit@@verb" -msgstr "Commit" +msgstr "Nuova revisione" #: git-gui.sh:1991 msgid "Local Merge..." -msgstr "Fusione locale" +msgstr "Fusione locale..." #: git-gui.sh:1996 msgid "Abort Merge..." -msgstr "Interrompi fusione" +msgstr "Interrompi fusione..." #: git-gui.sh:2008 msgid "Push..." @@ -330,7 +326,7 @@ msgstr "Informazioni su %s" #: git-gui.sh:2026 msgid "Preferences..." -msgstr "" +msgstr "Preferenze..." #: git-gui.sh:2034 git-gui.sh:2558 msgid "Options..." @@ -348,20 +344,20 @@ msgstr "Documentazione sul web" #, tcl-format msgid "fatal: cannot stat path %s: No such file or directory" msgstr "" +"errore grave: impossibile effettuare lo stat del path %s: file o directory " +"non trovata" #: git-gui.sh:2198 msgid "Current Branch:" msgstr "Ramo attuale:" #: git-gui.sh:2219 -#, fuzzy msgid "Staged Changes (Will Commit)" -msgstr "Modifiche preparate (ne verrà effettuato il commit)" +msgstr "Modifiche preparate (saranno nella nuova revisione)" #: git-gui.sh:2239 -#, fuzzy msgid "Unstaged Changes" -msgstr "Prepara modificati" +msgstr "Modifiche non preparate" #: git-gui.sh:2286 msgid "Stage Changed" @@ -373,15 +369,15 @@ msgstr "Propaga (Push)" #: git-gui.sh:2332 msgid "Initial Commit Message:" -msgstr "Messaggio di commit iniziale:" +msgstr "Messaggio di revisione iniziale:" #: git-gui.sh:2333 msgid "Amended Commit Message:" -msgstr "Messaggio di commit corretto:" +msgstr "Messaggio di revisione corretto:" #: git-gui.sh:2334 msgid "Amended Initial Commit Message:" -msgstr "Messaggio iniziale di commit corretto:" +msgstr "Messaggio iniziale di revisione corretto:" #: git-gui.sh:2335 msgid "Amended Merge Commit Message:" @@ -393,7 +389,7 @@ msgstr "Messaggio di fusione:" #: git-gui.sh:2337 msgid "Commit Message:" -msgstr "Messaggio di commit:" +msgstr "Messaggio di revisione:" #: git-gui.sh:2382 git-gui.sh:2520 lib/console.tcl:71 msgid "Copy All" @@ -429,11 +425,11 @@ msgstr "Mostra più contesto" #: git-gui.sh:2565 msgid "Unstage Hunk From Commit" -msgstr "Sezione non pronta per il commit" +msgstr "Sezione non preparata per una nuova revisione" #: git-gui.sh:2567 msgid "Stage Hunk For Commit" -msgstr "Prepara sezione per il commit" +msgstr "Prepara sezione per una nuova revisione" #: git-gui.sh:2586 msgid "Initializing..." @@ -449,6 +445,12 @@ msgid "" "by %s:\n" "\n" msgstr "" +"Possibili problemi con le variabili d'ambiente.\n" +"\n" +"Le seguenti variabili d'ambiente saranno probabilmente\n" +"ignorate da tutti i sottoprocessi di Git avviati\n" +"da %s:\n" +"\n" #: git-gui.sh:2707 msgid "" @@ -456,6 +458,9 @@ msgid "" "This is due to a known issue with the\n" "Tcl binary distributed by Cygwin." msgstr "" +"\n" +"Ciò è dovuto a un problema conosciuto\n" +"causato dall'eseguibile Tcl distribuito da Cygwin." #: git-gui.sh:2712 #, tcl-format @@ -467,6 +472,11 @@ msgid "" "user.email settings into your personal\n" "~/.gitconfig file.\n" msgstr "" +"\n" +"\n" +"Una buona alternativa a %s\n" +"consiste nell'assegnare valori alle variabili di configurazione\n" +"user.name e user.email nel tuo file ~/.gitconfig personale.\n" #: lib/about.tcl:25 msgid "git-gui - a graphical user interface for Git." @@ -478,11 +488,11 @@ msgstr "Mostra file" #: lib/blame.tcl:81 msgid "Commit:" -msgstr "Commit:" +msgstr "Revisione:" #: lib/blame.tcl:249 msgid "Copy Commit" -msgstr "Copia commit" +msgstr "Copia revisione" #: lib/blame.tcl:369 #, tcl-format @@ -491,58 +501,55 @@ msgstr "Lettura di %s..." #: lib/blame.tcl:473 msgid "Loading copy/move tracking annotations..." -msgstr "" +msgstr "Caricamento annotazioni per copie/spostamenti..." #: lib/blame.tcl:493 msgid "lines annotated" -msgstr "" +msgstr "linee annotate" #: lib/blame.tcl:674 msgid "Loading original location annotations..." -msgstr "" +msgstr "Caricamento annotazioni per posizione originaria..." #: lib/blame.tcl:677 msgid "Annotation complete." -msgstr "" +msgstr "Annotazione completata." #: lib/blame.tcl:731 -#, fuzzy msgid "Loading annotation..." -msgstr "Caricamento %s..." +msgstr "Caricamento annotazioni..." #: lib/blame.tcl:787 msgid "Author:" -msgstr "" +msgstr "Autore:" #: lib/blame.tcl:791 -#, fuzzy msgid "Committer:" -msgstr "Commit:" +msgstr "Revisione creata da:" #: lib/blame.tcl:796 msgid "Original File:" -msgstr "" +msgstr "File originario:" #: lib/blame.tcl:910 msgid "Originally By:" -msgstr "" +msgstr "In origine da:" #: lib/blame.tcl:916 -#, fuzzy msgid "In File:" -msgstr "File:" +msgstr "Nel file:" #: lib/blame.tcl:921 msgid "Copied Or Moved Here By:" -msgstr "" +msgstr "Copiato o spostato qui da:" #: lib/branch_checkout.tcl:14 lib/branch_checkout.tcl:19 msgid "Checkout Branch" -msgstr "Checkout ramo" +msgstr "Attiva ramo" #: lib/branch_checkout.tcl:23 msgid "Checkout" -msgstr "Checkout" +msgstr "Attiva" #: lib/branch_checkout.tcl:27 lib/branch_create.tcl:35 #: lib/branch_delete.tcl:32 lib/branch_rename.tcl:30 lib/browser.tcl:281 @@ -561,7 +568,7 @@ msgstr "Opzioni" #: lib/branch_checkout.tcl:39 lib/branch_create.tcl:92 msgid "Fetch Tracking Branch" -msgstr "Preleva ramo in 'tracking'" +msgstr "Recupera duplicato locale di ramo remoto" #: lib/branch_checkout.tcl:44 msgid "Detach From Local Branch" @@ -589,7 +596,7 @@ msgstr "Nome:" #: lib/branch_create.tcl:58 msgid "Match Tracking Branch Name" -msgstr "Appaia nome del ramo in 'tracking'" +msgstr "Appaia nome del duplicato locale di ramo remoto" #: lib/branch_create.tcl:66 msgid "Starting Revision" @@ -613,16 +620,17 @@ msgstr "Ripristina" #: lib/branch_create.tcl:97 msgid "Checkout After Creation" -msgstr "Checkout dopo la creazione" +msgstr "Attiva dopo la creazione" #: lib/branch_create.tcl:131 msgid "Please select a tracking branch." -msgstr "Scegliere un ramo in 'tracking'" +msgstr "Scegliere un duplicato locale di ramo remoto" #: lib/branch_create.tcl:140 #, tcl-format msgid "Tracking branch %s is not a branch in the remote repository." -msgstr "Il ramo in 'tracking' %s non è un ramo nell'archivio remoto." +msgstr "" +"Il duplicato locale del ramo remoto %s non è un ramo nell'archivio remoto." #: lib/branch_create.tcl:153 lib/branch_rename.tcl:86 msgid "Please supply a branch name." @@ -651,7 +659,7 @@ msgstr "Cancella solo se fuso con un altro ramo" #: lib/branch_delete.tcl:54 msgid "Always (Do not perform merge test.)" -msgstr "Sempre (Non effettuare controlli durante la fusione)." +msgstr "Sempre (Non effettuare verifiche di fusione)." #: lib/branch_delete.tcl:103 #, tcl-format @@ -664,7 +672,7 @@ msgid "" "\n" " Delete the selected branches?" msgstr "" -"Prelevare rami cancellati può essere complicato. \n" +"Ricomporre rami cancellati può essere complicato. \n" "\n" " Eliminare i rami selezionati?" @@ -700,12 +708,12 @@ msgstr "Scegliere un ramo da rinominare." #: lib/branch_rename.tcl:96 lib/checkout_op.tcl:179 #, tcl-format msgid "Branch '%s' already exists." -msgstr "Il ramo '%s' esiste già" +msgstr "Il ramo '%s' esiste già." #: lib/branch_rename.tcl:117 #, tcl-format msgid "Failed to rename '%s'." -msgstr "Cambiamento nome '%s' fallito." +msgstr "Impossibile rinominare '%s'." #: lib/browser.tcl:17 msgid "Starting..." @@ -742,7 +750,7 @@ msgstr "Recupero %s da %s" #: lib/checkout_op.tcl:127 #, tcl-format msgid "fatal: Cannot resolve %s" -msgstr "" +msgstr "errore grave: impossibile risolvere %s" #: lib/checkout_op.tcl:140 lib/console.tcl:79 lib/database.tcl:31 msgid "Close" @@ -778,7 +786,7 @@ msgstr "Aggiornamento di '%s' fallito." #: lib/checkout_op.tcl:251 msgid "Staging area (index) is already locked." -msgstr "L'area di preparazione per il commit (indice) è già bloccata." +msgstr "L'area di preparazione per una nuova revisione (indice) è già bloccata." #: lib/checkout_op.tcl:266 msgid "" @@ -789,23 +797,23 @@ msgid "" "\n" "The rescan will be automatically started now.\n" msgstr "" -"L'ultimo stato analizzato non corrisponde allo stato del repository.\n" +"L'ultimo stato analizzato non corrisponde allo stato dell'archivio.\n" "\n" -"Un altro programma Git ha modificato questo repository dall'ultima analisi. " +"Un altro programma Git ha modificato questo archivio dall'ultima analisi. " "Bisogna effettuare una nuova analisi prima di poter cambiare il ramo " "corrente.\n" "\n" "La nuova analisi comincerà ora.\n" #: lib/checkout_op.tcl:322 -#, fuzzy, tcl-format +#, tcl-format msgid "Updating working directory to '%s'..." -msgstr "Nessuna directory di lavoro" +msgstr "Aggiornamento della directory di lavoro a '%s' in corso..." #: lib/checkout_op.tcl:353 #, tcl-format msgid "Aborted checkout of '%s' (file level merging is required)." -msgstr "Checkout di '%s' fallito (richiesta una fusione a livello file)." +msgstr "Attivazione di '%s' fallita (richiesta una fusione a livello file)." #: lib/checkout_op.tcl:354 msgid "File level merge required." @@ -825,22 +833,23 @@ msgid "" msgstr "" "Non si è più su un ramo locale\n" "\n" -"Se si vuole rimanere su un ramo, crearne uno ora a partire da 'Questo " -"checkout staccato'." +"Se si vuole rimanere su un ramo, crearne uno ora a partire da 'Questa " +"revisione attiva staccata'." #: lib/checkout_op.tcl:446 -#, fuzzy, tcl-format +#, tcl-format msgid "Checked out '%s'." -msgstr "Checkout..." +msgstr "Attivazione di '%s' completata." #: lib/checkout_op.tcl:478 #, tcl-format msgid "Resetting '%s' to '%s' will lose the following commits:" -msgstr "Ripristinare '%s' a '%s' comporterà la perdita dei seguenti commit:" +msgstr "" +"Ripristinare '%s' a '%s' comporterà la perdita delle seguenti revisioni:" #: lib/checkout_op.tcl:500 msgid "Recovering lost commits may not be easy." -msgstr "Prelevare i commit perduti potrebbe non essere semplice." +msgstr "Ricomporre le revisioni perdute potrebbe non essere semplice." #: lib/checkout_op.tcl:505 #, tcl-format @@ -870,130 +879,125 @@ msgstr "" "Questo non sarebbe dovuto succedere. %s ora terminerà senza altre azioni." #: lib/choose_font.tcl:39 -#, fuzzy msgid "Select" -msgstr "Seleziona tutto" +msgstr "Seleziona" #: lib/choose_font.tcl:53 msgid "Font Family" -msgstr "" +msgstr "Famiglia di caratteri" #: lib/choose_font.tcl:73 -#, fuzzy msgid "Font Size" -msgstr "Diminuisci dimensione caratteri" +msgstr "Dimensione caratteri" #: lib/choose_font.tcl:90 msgid "Font Example" -msgstr "" +msgstr "Esempio caratteri" #: lib/choose_font.tcl:101 msgid "" "This is example text.\n" "If you like this text, it can be your font." msgstr "" +"Questo è un testo d'esempio.\n" +"Se ti piace questo testo, può essere il carattere giusto." #: lib/choose_repository.tcl:25 msgid "Git Gui" -msgstr "" +msgstr "Git Gui" #: lib/choose_repository.tcl:69 lib/choose_repository.tcl:204 -#, fuzzy msgid "Create New Repository" -msgstr "Da archivio" +msgstr "Crea nuovo archivio" #: lib/choose_repository.tcl:74 lib/choose_repository.tcl:291 -#, fuzzy msgid "Clone Existing Repository" -msgstr "Archivio di destinazione" +msgstr "Clona archivio esistente" #: lib/choose_repository.tcl:79 lib/choose_repository.tcl:800 -#, fuzzy msgid "Open Existing Repository" -msgstr "Archivio di destinazione" +msgstr "Apri archivio esistente" #: lib/choose_repository.tcl:91 msgid "Next >" -msgstr "" +msgstr "Successivo >" #: lib/choose_repository.tcl:152 -#, fuzzy, tcl-format +#, tcl-format msgid "Location %s already exists." -msgstr "Il ramo '%s' esiste già" +msgstr "La posizione %s esiste già." #: lib/choose_repository.tcl:158 lib/choose_repository.tcl:165 #: lib/choose_repository.tcl:172 -#, fuzzy, tcl-format +#, tcl-format msgid "Failed to create repository %s:" -msgstr "Fallimento nel salvataggio completo delle opzioni:" +msgstr "Impossibile creare l'archivio %s:" #: lib/choose_repository.tcl:209 lib/choose_repository.tcl:309 msgid "Directory:" -msgstr "" +msgstr "Directory:" #: lib/choose_repository.tcl:238 lib/choose_repository.tcl:363 #: lib/choose_repository.tcl:834 -#, fuzzy msgid "Git Repository" -msgstr "Archivio" +msgstr "Archivio Git" #: lib/choose_repository.tcl:253 lib/choose_repository.tcl:260 -#, fuzzy, tcl-format +#, tcl-format msgid "Directory %s already exists." -msgstr "Il ramo '%s' esiste già" +msgstr "La directory %s esiste già." #: lib/choose_repository.tcl:265 -#, fuzzy, tcl-format +#, tcl-format msgid "File %s already exists." -msgstr "Il ramo '%s' esiste già" +msgstr "Il file %s esiste già." #: lib/choose_repository.tcl:286 -#, fuzzy msgid "Clone" -msgstr "Chiudi" +msgstr "Clona" #: lib/choose_repository.tcl:299 msgid "URL:" -msgstr "" +msgstr "URL:" #: lib/choose_repository.tcl:319 msgid "Clone Type:" -msgstr "" +msgstr "Tipo di clone:" #: lib/choose_repository.tcl:325 msgid "Standard (Fast, Semi-Redundant, Hardlinks)" -msgstr "" +msgstr "Standard (veloce, semi-ridondante, con hardlink)" #: lib/choose_repository.tcl:331 msgid "Full Copy (Slower, Redundant Backup)" -msgstr "" +msgstr "Copia completa (più lento, backup ridondante)" #: lib/choose_repository.tcl:337 msgid "Shared (Fastest, Not Recommended, No Backup)" -msgstr "" +msgstr "Shared (il più veloce, non raccomandato, nessun backup)" #: lib/choose_repository.tcl:369 lib/choose_repository.tcl:418 #: lib/choose_repository.tcl:560 lib/choose_repository.tcl:630 #: lib/choose_repository.tcl:840 lib/choose_repository.tcl:848 -#, fuzzy, tcl-format +#, tcl-format msgid "Not a Git repository: %s" -msgstr "Nessun archivio selezionato." +msgstr "%s non è un archivio Git." #: lib/choose_repository.tcl:405 msgid "Standard only available for local repository." -msgstr "" +msgstr "Standard è disponibile solo per archivi locali." #: lib/choose_repository.tcl:409 msgid "Shared only available for local repository." -msgstr "" +msgstr "Shared è disponibile solo per archivi locali." #: lib/choose_repository.tcl:439 msgid "Failed to configure origin" -msgstr "" +msgstr "Impossibile configurare origin" #: lib/choose_repository.tcl:451 msgid "Counting objects" -msgstr "" +msgstr "Calcolo oggetti" #: lib/choose_repository.tcl:452 msgid "buckets" @@ -1002,116 +1006,117 @@ msgstr "" #: lib/choose_repository.tcl:476 #, tcl-format msgid "Unable to copy objects/info/alternates: %s" -msgstr "" +msgstr "Impossibile copiare oggetti/info/alternate: %s" #: lib/choose_repository.tcl:512 -#, fuzzy, tcl-format +#, tcl-format msgid "Nothing to clone from %s." -msgstr "Recupero nuove modifiche da %s" +msgstr "Niente da clonare da %s." #: lib/choose_repository.tcl:514 lib/choose_repository.tcl:728 #: lib/choose_repository.tcl:740 msgid "The 'master' branch has not been initialized." -msgstr "" +msgstr "Il ramo 'master' non è stato inizializzato." #: lib/choose_repository.tcl:527 msgid "Hardlinks are unavailable. Falling back to copying." -msgstr "" +msgstr "Impossibile utilizzare gli hardlink. Si ricorrerà alla copia." #: lib/choose_repository.tcl:539 -#, fuzzy, tcl-format +#, tcl-format msgid "Cloning from %s" -msgstr "Recupero %s da %s" +msgstr "Clonazione da %s" #: lib/choose_repository.tcl:570 -#, fuzzy msgid "Copying objects" -msgstr "Compressione del database in corso" +msgstr "Copia degli oggetti" #: lib/choose_repository.tcl:571 msgid "KiB" -msgstr "" +msgstr "KiB" #: lib/choose_repository.tcl:595 #, tcl-format msgid "Unable to copy object: %s" -msgstr "" +msgstr "Impossibile copiare oggetto: %s" #: lib/choose_repository.tcl:605 msgid "Linking objects" -msgstr "" +msgstr "Collegamento oggetti" #: lib/choose_repository.tcl:606 msgid "objects" -msgstr "" +msgstr "oggetti" #: lib/choose_repository.tcl:614 #, tcl-format msgid "Unable to hardlink object: %s" -msgstr "" +msgstr "Hardlink impossibile sull'oggetto: %s" #: lib/choose_repository.tcl:669 msgid "Cannot fetch branches and objects. See console output for details." msgstr "" +"Impossibile recuperare rami e oggetti. Controllare i dettagli forniti dalla " +"console." #: lib/choose_repository.tcl:680 msgid "Cannot fetch tags. See console output for details." msgstr "" +"Impossibile recuperare le etichette. Controllare i dettagli forniti dalla " +"console." #: lib/choose_repository.tcl:704 msgid "Cannot determine HEAD. See console output for details." msgstr "" +"Impossibile determinare HEAD. Controllare i dettagli forniti dalla console." #: lib/choose_repository.tcl:713 #, tcl-format msgid "Unable to cleanup %s" -msgstr "" +msgstr "Impossibile ripulire %s" #: lib/choose_repository.tcl:719 -#, fuzzy msgid "Clone failed." -msgstr "Interruzione fallita." +msgstr "Clonazione fallita." #: lib/choose_repository.tcl:726 msgid "No default branch obtained." -msgstr "" +msgstr "Non è stato trovato un ramo predefinito." #: lib/choose_repository.tcl:737 #, tcl-format msgid "Cannot resolve %s as a commit." -msgstr "" +msgstr "Impossibile risolvere %s come una revisione." #: lib/choose_repository.tcl:749 -#, fuzzy msgid "Creating working directory" -msgstr "Nessuna directory di lavoro" +msgstr "Creazione directory di lavoro" #: lib/choose_repository.tcl:750 lib/index.tcl:15 lib/index.tcl:80 #: lib/index.tcl:149 msgid "files" -msgstr "" +msgstr "file" #: lib/choose_repository.tcl:779 msgid "Initial file checkout failed." -msgstr "" +msgstr "Attivazione iniziale impossibile." #: lib/choose_repository.tcl:795 msgid "Open" -msgstr "" +msgstr "Apri" #: lib/choose_repository.tcl:805 -#, fuzzy msgid "Repository:" -msgstr "Archivio" +msgstr "Archivio:" #: lib/choose_repository.tcl:854 -#, fuzzy, tcl-format +#, tcl-format msgid "Failed to open repository %s:" -msgstr "Fallimento nel salvataggio completo delle opzioni:" +msgstr "Impossibile accedere all'archivio %s:" #: lib/choose_rev.tcl:53 msgid "This Detached Checkout" -msgstr "Questo checkout staccato" +msgstr "Questa revisione attiva staccata" #: lib/choose_rev.tcl:60 msgid "Revision Expression:" @@ -1123,7 +1128,7 @@ msgstr "Ramo locale" #: lib/choose_rev.tcl:79 msgid "Tracking Branch" -msgstr "Ramo in 'tracking'" +msgstr "Duplicato locale di ramo remoto" #: lib/choose_rev.tcl:84 lib/choose_rev.tcl:537 msgid "Tag" @@ -1144,11 +1149,11 @@ msgstr "L'espressione di revisione è vuota." #: lib/choose_rev.tcl:530 msgid "Updated" -msgstr "" +msgstr "Aggiornato" #: lib/choose_rev.tcl:558 msgid "URL" -msgstr "" +msgstr "URL" #: lib/commit.tcl:9 msgid "" @@ -1159,8 +1164,8 @@ msgid "" msgstr "" "Non c'è niente da correggere.\n" "\n" -"Stai per creare il commit iniziale. Non esiste un commit precedente da " -"correggere.\n" +"Stai per creare la revisione iniziale. Non esiste una revisione " +"precedente da correggere.\n" #: lib/commit.tcl:18 msgid "" @@ -1173,12 +1178,12 @@ msgstr "" "Non è possibile effettuare una correzione durante una fusione.\n" "\n" "In questo momento si sta effettuando una fusione che non è stata del tutto " -"completata. Non puoi correggere il commit precedente a meno che prima tu non " -"interrompa l'operazione di fusione in corso.\n" +"completata. Non puoi correggere la revisione precedente a meno che prima tu " +"non interrompa l'operazione di fusione in corso.\n" #: lib/commit.tcl:49 msgid "Error loading commit data for amend:" -msgstr "Errore durante il caricamento dei dati da correggere:" +msgstr "Errore durante il caricamento dei dati della revisione da correggere:" #: lib/commit.tcl:76 msgid "Unable to obtain your identity:" @@ -1197,10 +1202,11 @@ msgid "" "\n" "The rescan will be automatically started now.\n" msgstr "" -"L'ultimo stato analizzato non corrisponde allo stato del repository.\n" +"L'ultimo stato analizzato non corrisponde allo stato dell'archivio.\n" "\n" -"Un altro programma Git ha modificato questo repository dall'ultima analisi. " -"Bisogna effettuare una nuova analisi prima di poter creare un nuovo commit.\n" +"Un altro programma Git ha modificato questo archivio dall'ultima analisi. " +"Bisogna effettuare una nuova analisi prima di poter creare una nuova " +"revisione.\n" "\n" "La nuova analisi comincerà ora.\n" @@ -1212,10 +1218,10 @@ msgid "" "File %s has merge conflicts. You must resolve them and stage the file " "before committing.\n" msgstr "" -"Non è possibile effettuare il commit di file non sottoposti a fusione.\n" +"Non è possibile creare una revisione con file non sottoposti a fusione.\n" "\n" "Il file %s presenta dei conflitti. Devi risolverli e preparare il file per " -"il commit prima di effettuare questa azione.\n" +"creare una nuova revisione prima di effettuare questa azione.\n" #: lib/commit.tcl:162 #, tcl-format @@ -1226,7 +1232,7 @@ msgid "" msgstr "" "Stato di file %s sconosciuto.\n" "\n" -"Non si può effettuare il commit del file %s con questo programma.\n" +"Questo programma non può creare una revisione contenente il file %s.\n" #: lib/commit.tcl:170 msgid "" @@ -1234,9 +1240,9 @@ msgid "" "\n" "You must stage at least 1 file before you can commit.\n" msgstr "" -"Nessuna modifica per la quale effettuare il commit.\n" +"Nessuna modifica per la nuova revisione.\n" "\n" -"Devi preparare per il commit almeno 1 file prima di effettuare questa " +"Devi preparare per una nuova revisione almeno 1 file prima di effettuare questa " "operazione.\n" #: lib/commit.tcl:183 @@ -1249,13 +1255,13 @@ msgid "" "- Second line: Blank\n" "- Remaining lines: Describe why this change is good.\n" msgstr "" -"Bisogna fornire un messaggio di commit.\n" +"Bisogna fornire un messaggio di revisione.\n" "\n" -"Un buon messaggio di commit ha il seguente formato:\n" +"Un buon messaggio di revisione ha il seguente formato:\n" "\n" "- Prima linea: descrivi in una frase ciò che hai fatto.\n" "- Seconda linea: vuota.\n" -"- Terza linea: spiga a cosa serve la tua modifica.\n" +"- Terza linea: spiega a cosa serve la tua modifica.\n" #: lib/commit.tcl:257 msgid "write-tree failed:" @@ -1264,7 +1270,7 @@ msgstr "write-tree fallito:" #: lib/commit.tcl:275 #, tcl-format msgid "Commit %s appears to be corrupt" -msgstr "" +msgstr "La revisione %s sembra essere corrotta" #: lib/commit.tcl:279 msgid "" @@ -1274,20 +1280,20 @@ msgid "" "\n" "A rescan will be automatically started now.\n" msgstr "" -"Nessuna modifica pronta per il commit.\n" +"Nessuna modifica per la nuova revisione.\n" "\n" -"Questo commit non modifica alcun file e non effettua alcuna fusione.\n" +"Questa revisione non modifica alcun file e non effettua alcuna fusione.\n" "\n" "Si procederà subito ad una nuova analisi.\n" #: lib/commit.tcl:286 msgid "No changes to commit." -msgstr "Nessuna modifica pronta per il commit." +msgstr "Nessuna modifica per la nuova revisione." #: lib/commit.tcl:303 #, tcl-format msgid "warning: Tcl does not support encoding '%s'." -msgstr "" +msgstr "attenzione: Tcl non supporta la codifica '%s'." #: lib/commit.tcl:317 msgid "commit-tree failed:" @@ -1300,7 +1306,7 @@ msgstr "update-ref fallito:" #: lib/commit.tcl:430 #, tcl-format msgid "Created commit %s: %s" -msgstr "Creato commit %s: %s" +msgstr "Creata revisione %s: %s" #: lib/console.tcl:57 msgid "Working... please wait..." @@ -1344,7 +1350,7 @@ msgstr "File inutili" #: lib/database.tcl:72 msgid "Compressing the object database" -msgstr "Compressione del database in corso" +msgstr "Compressione dell'archivio in corso" #: lib/database.tcl:83 msgid "Verifying the object database with fsck-objects" @@ -1360,11 +1366,17 @@ msgid "" "\n" "Compress the database now?" msgstr "" +"Questo archivio attualmente ha circa %i oggetti slegati.\n" +"\n" +"Per mantenere buone prestazioni si raccomanda di comprimere l'archivio " +"quando sono presenti più di %i oggetti slegati.\n" +"\n" +"Comprimere l'archivio ora?" #: lib/date.tcl:25 -#, fuzzy, tcl-format +#, tcl-format msgid "Invalid date from Git: %s" -msgstr "Revisione non valida: %s" +msgstr "Git ha restituito una data non valida: %s" #: lib/diff.tcl:42 #, tcl-format @@ -1390,14 +1402,14 @@ msgstr "" "potrebbero avere lo stesso stato." #: lib/diff.tcl:81 -#, fuzzy, tcl-format +#, tcl-format msgid "Loading diff of %s..." -msgstr "Caricamento %s..." +msgstr "Caricamento delle differenze di %s..." #: lib/diff.tcl:114 lib/diff.tcl:184 #, tcl-format msgid "Unable to display %s" -msgstr "" +msgstr "Impossibile visualizzare %s" #: lib/diff.tcl:115 msgid "Error loading file:" @@ -1405,11 +1417,11 @@ msgstr "Errore nel caricamento del file:" #: lib/diff.tcl:122 msgid "Git Repository (subproject)" -msgstr "" +msgstr "Archivio Git (sottoprogetto)" #: lib/diff.tcl:134 msgid "* Binary file (not showing content)." -msgstr "" +msgstr "* File binario (il contenuto non sarà mostrato)." #: lib/diff.tcl:185 msgid "Error loading diff:" @@ -1417,11 +1429,11 @@ msgstr "Errore nel caricamento delle differenze:" #: lib/diff.tcl:302 msgid "Failed to unstage selected hunk." -msgstr "La sezione scelta è ancora pronta per il commit." +msgstr "La sezione scelta è ancora pronta per una nuova revisione." #: lib/diff.tcl:309 msgid "Failed to stage selected hunk." -msgstr "La sezione scelta non è ancora pronta per il commit." +msgstr "Impossibile preparare la sezione scelta per una nuova revisione." #: lib/error.tcl:12 lib/error.tcl:102 msgid "error" @@ -1429,21 +1441,21 @@ msgstr "errore" #: lib/error.tcl:28 msgid "warning" -msgstr "avviso" +msgstr "attenzione" #: lib/error.tcl:81 msgid "You must correct the above errors before committing." -msgstr "Bisogna correggere gli errori suddetti prima di effettuare un commit." +msgstr "Bisogna correggere gli errori suddetti prima di creare una nuova revisione." #: lib/index.tcl:241 -#, fuzzy, tcl-format +#, tcl-format msgid "Unstaging %s from commit" -msgstr "Non pronto per il commit" +msgstr "%s non farà parte della prossima revisione" #: lib/index.tcl:285 -#, fuzzy, tcl-format +#, tcl-format msgid "Adding %s" -msgstr "Lettura di %s..." +msgstr "Aggiunta di %s in corso" #: lib/index.tcl:340 #, tcl-format @@ -1458,7 +1470,8 @@ msgstr "Annullare le modifiche in questi %i file?" #: lib/index.tcl:348 msgid "Any unstaged changes will be permanently lost by the revert." msgstr "" -"Tutte le modifiche non preparate per il commit saranno perse per sempre." +"Tutte le modifiche non preparate per una nuova revisione saranno perse per " +"sempre." #: lib/index.tcl:351 msgid "Do Nothing" @@ -1472,8 +1485,8 @@ msgid "" msgstr "" "Non posso effettuare fusioni durante una correzione.\n" "\n" -"Bisogna finire di correggere questo commit prima di iniziare una qualunque " -"fusione.\n" +"Bisogna finire di correggere questa revisione prima di iniziare una " +"qualunque fusione.\n" #: lib/merge.tcl:27 msgid "" @@ -1484,9 +1497,9 @@ msgid "" "\n" "The rescan will be automatically started now.\n" msgstr "" -"L'ultimo stato analizzato non corrisponde allo stato del repository.\n" +"L'ultimo stato analizzato non corrisponde allo stato dell'archivio.\n" "\n" -"Un altro programma Git ha modificato questo repository dall'ultima analisi." +"Un altro programma Git ha modificato questo archivio dall'ultima analisi." "Bisogna effettuare una nuova analisi prima di poter effettuare una fusione.\n" "\n" "La nuova analisi comincerà ora.\n" @@ -1505,8 +1518,8 @@ msgstr "" "\n" "Il file %s ha dei conflitti.\n" "\n" -"Bisogna risolvere i conflitti, preparare il file per il commit ed infine " -"effettuare un commit per completare la fusione corrente. Solo a questo punto " +"Bisogna risolvere i conflitti, preparare il file per una nuova revisione ed " +"infine crearla per completare la fusione corrente. Solo a questo punto " "potrai iniziare un'altra fusione.\n" #: lib/merge.tcl:54 @@ -1523,9 +1536,9 @@ msgstr "" "\n" "Il file %s è stato modificato.\n" "\n" -"Bisogna completare il commit corrente prima di iniziare una fusione. In " -"questo modo sarà più facile interrompere una fusione non riuscita, nel caso " -"ce ne fosse bisogno.\n" +"Bisogna completare la creazione della revisione corrente prima di iniziare una fusione. " +"In questo modo sarà più facile interrompere una fusione non riuscita, nel " +"caso ce ne fosse bisogno.\n" #: lib/merge.tcl:106 #, tcl-format @@ -1562,7 +1575,7 @@ msgid "" msgstr "" "Interruzione impossibile durante una correzione.\n" "\n" -"Bisogna finire di correggere questo commit.\n" +"Bisogna finire di correggere questa revisione.\n" #: lib/merge.tcl:222 msgid "" @@ -1575,7 +1588,7 @@ msgstr "" "Interrompere fusione?\n" "\n" "L'interruzione della fusione corrente causerà la perdita di *TUTTE* le " -"modifiche non ancora presenti nei commit.\n" +"modifiche non ancora presenti nell'archivio.\n" "\n" "Continuare con l'interruzione della fusione corrente?" @@ -1587,10 +1600,10 @@ msgid "" "\n" "Continue with resetting the current changes?" msgstr "" -"Annullare le modifiche?\n" +"Ripristinare la revisione corrente e annullare le modifiche?\n" "\n" "L'annullamento delle modifiche causerà la perdita di *TUTTE* le modifiche " -"non ancora presenti nei commit.\n" +"non ancora presenti nell'archivio.\n" "\n" "Continuare con l'annullamento delle modifiche correnti?" @@ -1617,11 +1630,11 @@ msgstr "Salva" #: lib/option.tcl:96 #, tcl-format msgid "%s Repository" -msgstr "%s archivio" +msgstr "Archivio di %s" #: lib/option.tcl:97 msgid "Global (All Repositories)" -msgstr "Globale (Tutti i repository)" +msgstr "Tutti gli archivi" #: lib/option.tcl:103 msgid "User Name" @@ -1633,11 +1646,11 @@ msgstr "Indirizzo Email" #: lib/option.tcl:106 msgid "Summarize Merge Commits" -msgstr "Riepilogo nei commit di fusione" +msgstr "Riepilogo nelle revisioni di fusione" #: lib/option.tcl:107 msgid "Merge Verbosity" -msgstr "Verbosità della fusione" +msgstr "Prolissità della fusione" #: lib/option.tcl:108 msgid "Show Diffstat After Merge" @@ -1649,11 +1662,12 @@ msgstr "Fidati delle date di modifica dei file" #: lib/option.tcl:111 msgid "Prune Tracking Branches During Fetch" -msgstr "Effettua potatura dei rami in 'tracking' durante il recupero" +msgstr "" +"Effettua potatura dei duplicati locali di rami remoti durante il recupero" #: lib/option.tcl:112 msgid "Match Tracking Branches" -msgstr "Appaia rami in 'tracking'" +msgstr "Appaia duplicati locali di rami remoti" #: lib/option.tcl:113 msgid "Number of Diff Context Lines" @@ -1664,41 +1678,37 @@ msgid "New Branch Name Template" msgstr "Modello per il nome di un nuovo ramo" #: lib/option.tcl:176 -#, fuzzy msgid "Change Font" -msgstr "Caratteri principali" +msgstr "Cambia caratteri" #: lib/option.tcl:180 #, tcl-format msgid "Choose %s" -msgstr "" +msgstr "Scegli %s" #: lib/option.tcl:186 msgid "pt." -msgstr "" +msgstr "pt." #: lib/option.tcl:200 msgid "Preferences" -msgstr "" +msgstr "Preferenze" #: lib/option.tcl:235 msgid "Failed to completely save options:" -msgstr "Fallimento nel salvataggio completo delle opzioni:" +msgstr "Impossibile salvare completamente le opzioni:" #: lib/remote.tcl:165 -#, fuzzy msgid "Prune from" -msgstr "Effettua potatura da %s..." +msgstr "Effettua potatura da" #: lib/remote.tcl:170 -#, fuzzy msgid "Fetch from" -msgstr "Preleva da %s..." +msgstr "Recupera da" #: lib/remote.tcl:213 -#, fuzzy msgid "Push to" -msgstr "Propaga (Push)" +msgstr "Propaga verso" #: lib/remote_branch_delete.tcl:29 lib/remote_branch_delete.tcl:34 msgid "Delete Remote Branch" @@ -1714,7 +1724,7 @@ msgstr "Remoto:" #: lib/remote_branch_delete.tcl:66 lib/transport.tcl:138 msgid "Arbitrary URL:" -msgstr "URL arbitrario:" +msgstr "URL specifico:" #: lib/remote_branch_delete.tcl:84 msgid "Branches" @@ -1730,19 +1740,22 @@ msgstr "Fuso in:" #: lib/remote_branch_delete.tcl:119 msgid "Always (Do not perform merge checks)" -msgstr "Sempre (Non effettuare controlli durante la fusione)" +msgstr "Sempre (non verificare le fusioni)" #: lib/remote_branch_delete.tcl:152 msgid "A branch is required for 'Merged Into'." msgstr "Si richiede un ramo per 'Fuso in'." #: lib/remote_branch_delete.tcl:184 -#, fuzzy, tcl-format +#, tcl-format msgid "" "The following branches are not completely merged into %s:\n" "\n" " - %s" -msgstr "I rami seguenti non sono stati fusi completamente in %s:" +msgstr "" +"I rami seguenti non sono stati fusi completamente in %s:\n" +"\n" +" - %s" #: lib/remote_branch_delete.tcl:189 #, tcl-format @@ -1750,8 +1763,8 @@ msgid "" "One or more of the merge tests failed because you have not fetched the " "necessary commits. Try fetching from %s first." msgstr "" -"Una o più verifiche di fusione sono fallite perché mancano i commit " -"necessari. Prova prima a prelevarli da %s." +"Una o più verifiche di fusione sono fallite perché mancano le revisioni " +"necessarie. Prova prima a recuperarle da %s." #: lib/remote_branch_delete.tcl:207 msgid "Please select one or more branches to delete." @@ -1763,7 +1776,7 @@ msgid "" "\n" "Delete the selected branches?" msgstr "" -"Prelevare rami cancellati è difficile.\n" +"Ricomporre rami cancellati è difficile.\n" "\n" "Cancellare i rami selezionati?" @@ -1795,9 +1808,9 @@ msgid "%s ... %*i of %*i %s (%3i%%)" msgstr "%s ... %*i di %*i %s (%3i%%)" #: lib/transport.tcl:6 -#, fuzzy, tcl-format +#, tcl-format msgid "fetch %s" -msgstr "Preleva (Fetch)" +msgstr "recupera da %s" #: lib/transport.tcl:7 #, tcl-format @@ -1807,17 +1820,17 @@ msgstr "Recupero nuove modifiche da %s" #: lib/transport.tcl:18 #, tcl-format msgid "remote prune %s" -msgstr "" +msgstr "potatura remota di %s" #: lib/transport.tcl:19 #, tcl-format msgid "Pruning tracking branches deleted from %s" -msgstr "Effettua potatura dei rami in 'tracking' cancellati da %s" +msgstr "Effettua potatura dei duplicati locali di rami remoti cancellati da %s" #: lib/transport.tcl:25 lib/transport.tcl:71 #, tcl-format msgid "push %s" -msgstr "" +msgstr "propaga verso %s" #: lib/transport.tcl:26 #, tcl-format @@ -1847,7 +1860,7 @@ msgstr "Opzioni di trasferimento" #: lib/transport.tcl:160 msgid "Force overwrite existing branch (may discard changes)" -msgstr "" +msgstr "Sovrascrivi ramo esistente (alcune modifiche potrebbero essere perse)" #: lib/transport.tcl:164 msgid "Use thin pack (for slow network connections)" @@ -1857,11 +1870,3 @@ msgstr "Utilizza 'thin pack' (per connessioni lente)" msgid "Include tags" msgstr "Includi etichette" -#~ msgid "Cannot find the git directory:" -#~ msgstr "Non posso trovare la directory di git:" - -#~ msgid "Unstaged Changes (Will Not Be Committed)" -#~ msgstr "Modifiche non preparate (non ne verrà effettuato il commit)" - -#~ msgid "Push to %s..." -#~ msgstr "Propaga verso %s..." From a0592d3f5746b41c60fee71dd8d2d27b5c813907 Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Wed, 10 Oct 2007 20:50:40 -0400 Subject: [PATCH 0157/1490] git-gui: Change main window layout to support wider screens The layout is changed to have the file lists at the left (Unstaged Changes at the top, Staged Changes below it) and the diff window at the right (with the commit area below it). +----------+---------------------+ | Unstaged | Diff area | | | | | | | | | | +----------+ | | Staged | | | +---------------------+ | | Commit area | | | | +----------+---------------------+ The advantages are: - The height of the file lists can be adjusted independently to fit the files that they contain. - The diff viewer is higher. On wide screens it is ok that the main window is now generally wider, too. Signed-off-by: Johannes Sixt Signed-off-by: Shawn O. Pearce --- git-gui.sh | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/git-gui.sh b/git-gui.sh index 6b7bdbca21..07be97dd5c 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -1658,8 +1658,8 @@ proc do_quit {} { # set cfg_geometry [list] lappend cfg_geometry [wm geometry .] - lappend cfg_geometry [lindex [.vpane sash coord 0] 1] - lappend cfg_geometry [lindex [.vpane.files sash coord 0] 0] + lappend cfg_geometry [lindex [.vpane sash coord 0] 0] + lappend cfg_geometry [lindex [.vpane.files sash coord 0] 1] if {[catch {set rc_geometry $repo_config(gui.geometry)}]} { set rc_geometry {} } @@ -2208,8 +2208,8 @@ pack .branch -side top -fill x # -- Main Window Layout # -panedwindow .vpane -orient vertical -panedwindow .vpane.files -orient horizontal +panedwindow .vpane -orient horizontal +panedwindow .vpane.files -orient vertical .vpane add .vpane.files -sticky nsew -height 100 -width 200 pack .vpane -anchor n -side top -fill both -expand 1 @@ -2231,7 +2231,6 @@ pack .vpane.files.index.title -side top -fill x pack .vpane.files.index.sx -side bottom -fill x pack .vpane.files.index.sy -side right -fill y pack $ui_index -side left -fill both -expand 1 -.vpane.files add .vpane.files.index -sticky nsew # -- Working Directory File List # @@ -2251,7 +2250,9 @@ pack .vpane.files.workdir.title -side top -fill x pack .vpane.files.workdir.sx -side bottom -fill x pack .vpane.files.workdir.sy -side right -fill y pack $ui_workdir -side left -fill both -expand 1 + .vpane.files add .vpane.files.workdir -sticky nsew +.vpane.files add .vpane.files.index -sticky nsew foreach i [list $ui_index $ui_workdir] { rmsel_tag $i @@ -2264,8 +2265,8 @@ unset i frame .vpane.lower -height 300 -width 400 frame .vpane.lower.commarea frame .vpane.lower.diff -relief sunken -borderwidth 1 -pack .vpane.lower.commarea -side top -fill x -pack .vpane.lower.diff -side bottom -fill both -expand 1 +pack .vpane.lower.diff -fill both -expand 1 +pack .vpane.lower.commarea -side bottom -fill x .vpane add .vpane.lower -sticky nsew # -- Commit Area Buttons @@ -2591,11 +2592,11 @@ catch { set gm $repo_config(gui.geometry) wm geometry . [lindex $gm 0] .vpane sash place 0 \ - [lindex [.vpane sash coord 0] 0] \ - [lindex $gm 1] + [lindex $gm 1] \ + [lindex [.vpane sash coord 0] 1] .vpane.files sash place 0 \ - [lindex $gm 2] \ - [lindex [.vpane.files sash coord 0] 1] + [lindex [.vpane.files sash coord 0] 0] \ + [lindex $gm 2] unset gm } From 69f85ffaa22c3357cbb5c3c97a621eccbdfa2bb3 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 12 Oct 2007 00:34:04 -0400 Subject: [PATCH 0158/1490] git-gui: Move load_config procedure below git-version selection To better handle configuration options that contain LFs in their values we want to use the new -z option available in git-config version 1.5.3 and later. To configure load_config based upon the git version we need to move thos below the git-version computation. No logic changes yet, just a minor reordering of the code. Signed-off-by: Shawn O. Pearce --- git-gui.sh | 94 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 49 insertions(+), 45 deletions(-) diff --git a/git-gui.sh b/git-gui.sh index 07be97dd5c..530fee866f 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -233,51 +233,6 @@ proc get_config {name} { } } -proc load_config {include_global} { - global repo_config global_config default_config - - array unset global_config - if {$include_global} { - catch { - set fd_rc [git_read config --global --list] - while {[gets $fd_rc line] >= 0} { - if {[regexp {^([^=]+)=(.*)$} $line line name value]} { - if {[is_many_config $name]} { - lappend global_config($name) $value - } else { - set global_config($name) $value - } - } - } - close $fd_rc - } - } - - array unset repo_config - catch { - set fd_rc [git_read config --list] - while {[gets $fd_rc line] >= 0} { - if {[regexp {^([^=]+)=(.*)$} $line line name value]} { - if {[is_many_config $name]} { - lappend repo_config($name) $value - } else { - set repo_config($name) $value - } - } - } - close $fd_rc - } - - foreach name [array names default_config] { - if {[catch {set v $global_config($name)}]} { - set global_config($name) $default_config($name) - } - if {[catch {set v $repo_config($name)}]} { - set repo_config($name) $default_config($name) - } - } -} - ###################################################################### ## ## handy utils @@ -789,6 +744,55 @@ if {$idx ne {}} { } unset -nocomplain idx fd +###################################################################### +## +## config file parsing + +proc load_config {include_global} { + global repo_config global_config default_config + + array unset global_config + if {$include_global} { + catch { + set fd_rc [git_read config --global --list] + while {[gets $fd_rc line] >= 0} { + if {[regexp {^([^=]+)=(.*)$} $line line name value]} { + if {[is_many_config $name]} { + lappend global_config($name) $value + } else { + set global_config($name) $value + } + } + } + close $fd_rc + } + } + + array unset repo_config + catch { + set fd_rc [git_read config --list] + while {[gets $fd_rc line] >= 0} { + if {[regexp {^([^=]+)=(.*)$} $line line name value]} { + if {[is_many_config $name]} { + lappend repo_config($name) $value + } else { + set repo_config($name) $value + } + } + } + close $fd_rc + } + + foreach name [array names default_config] { + if {[catch {set v $global_config($name)}]} { + set global_config($name) $default_config($name) + } + if {[catch {set v $repo_config($name)}]} { + set repo_config($name) $default_config($name) + } + } +} + ###################################################################### ## ## feature option selection From f00d504a6fcf29944311a497d0eb76f0fe5ef8f0 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 12 Oct 2007 00:42:17 -0400 Subject: [PATCH 0159/1490] git-gui: Refactor git-config --list parsing The parsing for the output of `git config --list` is the same for both the global options and the current repository's options so we can really just use the same parser between them. I'm currently just refactoring the parser so we can use a different one depending on the version of git available to us at runtime. My next change will add support for 1.5.3's --null option. Signed-off-by: Shawn O. Pearce --- git-gui.sh | 35 ++++++++++++++--------------------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/git-gui.sh b/git-gui.sh index 530fee866f..cfed62da44 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -748,40 +748,33 @@ unset -nocomplain idx fd ## ## config file parsing -proc load_config {include_global} { - global repo_config global_config default_config - - array unset global_config - if {$include_global} { +git-version proc _parse_config {arr_name args} { + default { + upvar $arr_name arr + array unset arr catch { - set fd_rc [git_read config --global --list] + set fd_rc [eval [list git_read config --list] $args] while {[gets $fd_rc line] >= 0} { if {[regexp {^([^=]+)=(.*)$} $line line name value]} { if {[is_many_config $name]} { - lappend global_config($name) $value + lappend arr($name) $value } else { - set global_config($name) $value + set arr($name) $value } } } close $fd_rc } } +} - array unset repo_config - catch { - set fd_rc [git_read config --list] - while {[gets $fd_rc line] >= 0} { - if {[regexp {^([^=]+)=(.*)$} $line line name value]} { - if {[is_many_config $name]} { - lappend repo_config($name) $value - } else { - set repo_config($name) $value - } - } - } - close $fd_rc +proc load_config {include_global} { + global repo_config global_config default_config + + if {$include_global} { + _parse_config global_config --global } + _parse_config repo_config foreach name [array names default_config] { if {[catch {set v $global_config($name)}]} { From 85f7a94b3c1e4289827f2529d2e8447f3678c619 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 12 Oct 2007 00:54:15 -0400 Subject: [PATCH 0160/1490] git-gui: Support LFs embedded in config file values Using the new --null option added to git-config in git 1.5.3 we can safely accept LFs that are embedded in configuration options. This does require a completely different configuration file parser then the pre 1.5.3 version as we are splitting on very different values. Signed-off-by: Shawn O. Pearce --- git-gui.sh | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/git-gui.sh b/git-gui.sh index cfed62da44..a6e2d57a2f 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -749,6 +749,26 @@ unset -nocomplain idx fd ## config file parsing git-version proc _parse_config {arr_name args} { + >= 1.5.3 { + upvar $arr_name arr + array unset arr + set buf {} + catch { + set fd_rc [eval [list git_read config --null --list] $args] + fconfigure $fd_rc -translation binary + set buf [read $fd_rc] + close $fd_rc + } + foreach line [split $buf "\0"] { + if {[regexp {^([^\n]+)\n(.*)$} $line line name value]} { + if {[is_many_config $name]} { + lappend arr($name) $value + } else { + set arr($name) $value + } + } + } + } default { upvar $arr_name arr array unset arr From 24f7c64b21bb26aab5b8525c0bac8452e7a7a4c8 Mon Sep 17 00:00:00 2001 From: Steffen Prohaska Date: Mon, 8 Oct 2007 08:25:47 +0200 Subject: [PATCH 0161/1490] git-gui: offer a list of recent repositories on startup If git-gui is started outside a work tree the repository chooser will offer a list of recently opened repositories. Clicking on any list entry directly opens the repository. The list of recently opened repositories is stored in the config as the multi-valued option gui.recentrepo. If the list grows beyond 10 entries it will be truncated by removing one of the older entries. Only repositories that are opened through the repository chooser will get added to the recent list. Repositories opened from the shell will not yet be added to the recent list, as users are likely to have a way to easily return to the same directory via their shell. [sp: This is actually a combined work from both Steffen and myself. Most of the ideas are Steffen's, as is the basic outline of the code, but any outstanding bugs are entirely my fault.] Signed-off-by: Steffen Prohaska Signed-off-by: Shawn O. Pearce --- git-gui.sh | 1 + lib/choose_repository.tcl | 82 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) diff --git a/git-gui.sh b/git-gui.sh index a6e2d57a2f..dd320fb075 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -205,6 +205,7 @@ proc disable_option {option} { proc is_many_config {name} { switch -glob -- $name { + gui.recentrepo - remote.*.fetch - remote.*.push {return 1} diff --git a/lib/choose_repository.tcl b/lib/choose_repository.tcl index 5d5bc81ad0..8dc8506544 100644 --- a/lib/choose_repository.tcl +++ b/lib/choose_repository.tcl @@ -9,6 +9,7 @@ field w_body ; # Widget holding the center content field w_next ; # Next button field o_cons ; # Console object (if active) field w_types ; # List of type buttons in clone +field w_recentlist ; # Listbox containing recent repositories field action new ; # What action are we going to perform? field done 0 ; # Finished picking the repository? @@ -17,6 +18,7 @@ field origin_url {} ; # Where we are cloning from field origin_name origin ; # What we shall call 'origin' field clone_type hardlink ; # Type of clone to construct field readtree_err ; # Error output from read-tree (if any) +field sorted_recent ; # recent repositories (sorted) constructor pick {} { global M1T M1B @@ -82,6 +84,40 @@ constructor pick {} { pack $w_body.new -anchor w -fill x pack $w_body.clone -anchor w -fill x pack $w_body.open -anchor w -fill x + + set sorted_recent [_get_recentrepos] + if {[llength $sorted_recent] > 0} { + label $w_body.space + label $w_body.recentlabel \ + -anchor w \ + -text [mc "Open Recent Repository:"] + set w_recentlist $w_body.recentlist + text $w_recentlist \ + -cursor $::cursor_ptr \ + -relief flat \ + -background [$w_body.recentlabel cget -background] \ + -wrap none \ + -width 50 \ + -height 10 + $w_recentlist tag conf link \ + -foreground blue \ + -underline 1 + set home "[file normalize $::env(HOME)][file separator]" + set hlen [string length $home] + foreach p $sorted_recent { + if {[string equal -length $hlen $home $p]} { + set p "~[file separator][string range $p $hlen end]" + } + regsub -all "\n" $p "\\n" p + $w_recentlist insert end $p link + $w_recentlist insert end "\n" + } + $w_recentlist conf -state disabled + $w_recentlist tag bind link <1> [cb _open_recent %x,%y] + pack $w_body.space -anchor w -fill x + pack $w_body.recentlabel -anchor w -fill x + pack $w_recentlist -anchor w -fill x + } pack $w_body -fill x -padx 10 -pady 10 frame $w.buttons @@ -134,6 +170,50 @@ method _invoke_next {} { } } +proc _get_recentrepos {} { + set recent [list] + foreach p [get_config gui.recentrepo] { + if {[_is_git [file join $p .git]]} { + lappend recent $p + } + } + return [lsort $recent] +} + +proc _unset_recentrepo {p} { + regsub -all -- {([()\[\]{}\.^$+*?\\])} $p {\\\1} p + git config --global --unset gui.recentrepo "^$p\$" +} + +proc _append_recentrepos {path} { + set path [file normalize $path] + set recent [get_config gui.recentrepo] + + if {[lindex $recent end] eq $path} { + return + } + + set i [lsearch $recent $path] + if {$i >= 0} { + _unset_recentrepo $path + set recent [lreplace $recent $i $i] + } + + lappend recent $path + git config --global --add gui.recentrepo $path + + while {[llength $recent] > 10} { + _unset_recentrepo [lindex $recent 0] + set recent [lrange $recent 1 end] + } +} + +method _open_recent {xy} { + set id [lindex [split [$w_recentlist index @$xy] .] 0] + set local_path [lindex $sorted_recent [expr {$id - 1}]] + _do_open2 $this +} + method _next {} { destroy $w_body _do_$action $this @@ -174,6 +254,7 @@ method _git_init {} { return 0 } + _append_recentrepos [pwd] set ::_gitdir .git set ::_prefix {} return 1 @@ -856,6 +937,7 @@ method _do_open2 {} { return } + _append_recentrepos [pwd] set ::_gitdir .git set ::_prefix {} set done 1 From 28e86952dd0802315d79f57f666fa2c283d0fbe8 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 12 Oct 2007 01:34:36 -0400 Subject: [PATCH 0162/1490] git-gui: Change repository browser radio buttons to hyperlinks Making a user click twice to select which action they want to perform when starting git-gui is just wasting their time. Clicking once on a radio button and then clicking again on the "Next >" button is quite unnecessary. Since the recent repository list is shown as a list of hyperlinks we now offer the 3 basic startup actions as hyperlinks. Clicking on a link will immediately jump to the next UI panel, saving the user time as they don't need to click an additional button. Signed-off-by: Shawn O. Pearce --- lib/choose_repository.tcl | 61 ++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/lib/choose_repository.tcl b/lib/choose_repository.tcl index 8dc8506544..eb4a6d2851 100644 --- a/lib/choose_repository.tcl +++ b/lib/choose_repository.tcl @@ -7,11 +7,11 @@ field top field w field w_body ; # Widget holding the center content field w_next ; # Next button +field w_quit ; # Quit button field o_cons ; # Console object (if active) field w_types ; # List of type buttons in clone field w_recentlist ; # Listbox containing recent repositories -field action new ; # What action are we going to perform? field done 0 ; # Finished picking the repository? field local_path {} ; # Where this repository is locally field origin_url {} ; # Where we are cloning from @@ -65,25 +65,32 @@ constructor pick {} { pack [git_logo $w.git_logo] -side left -fill y -padx 10 -pady 10 set w_body $w.body + set opts $w_body.options frame $w_body - radiobutton $w_body.new \ - -anchor w \ - -text [mc "Create New Repository"] \ - -variable @action \ - -value new - radiobutton $w_body.clone \ - -anchor w \ - -text [mc "Clone Existing Repository"] \ - -variable @action \ - -value clone - radiobutton $w_body.open \ - -anchor w \ - -text [mc "Open Existing Repository"] \ - -variable @action \ - -value open - pack $w_body.new -anchor w -fill x - pack $w_body.clone -anchor w -fill x - pack $w_body.open -anchor w -fill x + text $opts \ + -cursor $::cursor_ptr \ + -relief flat \ + -background [$w_body cget -background] \ + -wrap none \ + -spacing1 5 \ + -width 50 \ + -height 3 + pack $opts -anchor w -fill x + + $opts tag conf link_new -foreground blue -underline 1 + $opts tag bind link_new <1> [cb _next new] + $opts insert end [mc "Create New Repository"] link_new + $opts insert end "\n" + + $opts tag conf link_clone -foreground blue -underline 1 + $opts tag bind link_clone <1> [cb _next clone] + $opts insert end [mc "Clone Existing Repository"] link_clone + $opts insert end "\n" + + $opts tag conf link_open -foreground blue -underline 1 + $opts tag bind link_open <1> [cb _next open] + $opts insert end [mc "Open Existing Repository"] link_open + $opts insert end "\n" set sorted_recent [_get_recentrepos] if {[llength $sorted_recent] > 0} { @@ -122,15 +129,11 @@ constructor pick {} { frame $w.buttons set w_next $w.buttons.next - button $w_next \ - -default active \ - -text [mc "Next >"] \ - -command [cb _next] - pack $w_next -side right -padx 5 - button $w.buttons.quit \ + set w_quit $w.buttons.quit + button $w_quit \ -text [mc "Quit"] \ -command exit - pack $w.buttons.quit -side right -padx 5 + pack $w_quit -side right -padx 5 pack $w.buttons -side bottom -fill x -padx 10 -pady 10 bind $top [cb _invoke_next] @@ -214,8 +217,12 @@ method _open_recent {xy} { _do_open2 $this } -method _next {} { +method _next {action} { destroy $w_body + if {![winfo exists $w_next]} { + button $w_next -default active + pack $w_next -side right -padx 5 -before $w_quit + } _do_$action $this } From 9c1b1b1e45926e6eed57f5bfbb5c3f69e063e5ab Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 12 Oct 2007 01:56:06 -0400 Subject: [PATCH 0163/1490] git-gui: Offer repository management features in menu bar When we show the repository chooser as the primary toplevel (".") we now offer the major choices not just on the window as hyperlinks but they also now are shown in the Repository menu, including the recent repository list. Signed-off-by: Shawn O. Pearce --- lib/choose_repository.tcl | 55 ++++++++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 6 deletions(-) diff --git a/lib/choose_repository.tcl b/lib/choose_repository.tcl index eb4a6d2851..46d5b77c00 100644 --- a/lib/choose_repository.tcl +++ b/lib/choose_repository.tcl @@ -30,14 +30,11 @@ constructor pick {} { menu $w.mbar -tearoff 0 $top configure -menu $w.mbar + set m_repo $w.mbar.repository $w.mbar add cascade \ -label [mc Repository] \ - -menu $w.mbar.repository - menu $w.mbar.repository - $w.mbar.repository add command \ - -label [mc Quit] \ - -command exit \ - -accelerator $M1T-Q + -menu $m_repo + menu $m_repo if {[is_MacOSX]} { $w.mbar add cascade -label [mc Apple] -menu .mbar.apple @@ -60,6 +57,7 @@ constructor pick {} { } else { wm geometry $top "+[winfo rootx .]+[winfo rooty .]" bind $top [list destroy $top] + set m_repo {} } pack [git_logo $w.git_logo] -side left -fill y -padx 10 -pady 10 @@ -81,19 +79,44 @@ constructor pick {} { $opts tag bind link_new <1> [cb _next new] $opts insert end [mc "Create New Repository"] link_new $opts insert end "\n" + if {$m_repo ne {}} { + $m_repo add command \ + -command [cb _next new] \ + -accelerator $M1T-N \ + -label [mc "New..."] + } $opts tag conf link_clone -foreground blue -underline 1 $opts tag bind link_clone <1> [cb _next clone] $opts insert end [mc "Clone Existing Repository"] link_clone $opts insert end "\n" + if {$m_repo ne {}} { + $m_repo add command \ + -command [cb _next clone] \ + -accelerator $M1T-C \ + -label [mc "Clone..."] + } $opts tag conf link_open -foreground blue -underline 1 $opts tag bind link_open <1> [cb _next open] $opts insert end [mc "Open Existing Repository"] link_open $opts insert end "\n" + if {$m_repo ne {}} { + $m_repo add command \ + -command [cb _next open] \ + -accelerator $M1T-O \ + -label [mc "Open..."] + } set sorted_recent [_get_recentrepos] if {[llength $sorted_recent] > 0} { + if {$m_repo ne {}} { + $m_repo add separator + $m_repo add command \ + -state disabled \ + -label [mc "Recent Repositories"] + } + label $w_body.space label $w_body.recentlabel \ -anchor w \ @@ -112,12 +135,19 @@ constructor pick {} { set home "[file normalize $::env(HOME)][file separator]" set hlen [string length $home] foreach p $sorted_recent { + set path $p if {[string equal -length $hlen $home $p]} { set p "~[file separator][string range $p $hlen end]" } regsub -all "\n" $p "\\n" p $w_recentlist insert end $p link $w_recentlist insert end "\n" + + if {$m_repo ne {}} { + $m_repo add command \ + -command [cb _open_recent_path $path] \ + -label " $p" + } } $w_recentlist conf -state disabled $w_recentlist tag bind link <1> [cb _open_recent %x,%y] @@ -136,6 +166,14 @@ constructor pick {} { pack $w_quit -side right -padx 5 pack $w.buttons -side bottom -fill x -padx 10 -pady 10 + if {$m_repo ne {}} { + $m_repo add separator + $m_repo add command \ + -label [mc Quit] \ + -command exit \ + -accelerator $M1T-Q + } + bind $top [cb _invoke_next] bind $top " [cb _center] @@ -217,6 +255,11 @@ method _open_recent {xy} { _do_open2 $this } +method _open_recent_path {p} { + set local_path $p + _do_open2 $this +} + method _next {action} { destroy $w_body if {![winfo exists $w_next]} { From 580b73de258635ca392d917cda4341ac5f1a2535 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 12 Oct 2007 11:15:02 -0400 Subject: [PATCH 0164/1490] git-gui: Fix bind errors when switching repository chooser panels We need to remove any variable traces we may have installed when the panel is destroyed as the trace may attempt to use a widget that no longer exists on this panel. Signed-off-by: Shawn O. Pearce --- lib/choose_repository.tcl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/choose_repository.tcl b/lib/choose_repository.tcl index 46d5b77c00..ab8e620c70 100644 --- a/lib/choose_repository.tcl +++ b/lib/choose_repository.tcl @@ -352,6 +352,7 @@ method _do_new {} { pack $w_body.where -fill x trace add variable @local_path write [cb _write_local_path] + bind $w_body.h [list trace remove variable @local_path write [cb _write_local_path]] update focus $w_body.where.t } @@ -477,6 +478,10 @@ method _do_clone {} { trace add variable @local_path write [cb _update_clone] trace add variable @origin_url write [cb _update_clone] + bind $w_body.h " + [list trace remove variable @local_path write [cb _update_clone]] + [list trace remove variable @origin_url write [cb _update_clone]] + " update focus $args.origin_t } @@ -948,6 +953,7 @@ method _do_open {} { pack $w_body.where -fill x trace add variable @local_path write [cb _write_local_path] + bind $w_body.h [list trace remove variable @local_path write [cb _write_local_path]] update focus $w_body.where.t } From 28d1b11a1172ef047a97a901819aac75a8cf75c9 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 12 Oct 2007 11:04:20 -0400 Subject: [PATCH 0165/1490] git-gui: Disable the text widget in the repository chooser Although we are using a text widget here we really do not want the end-user to be able to modify the text it displays. So we need to disable it. Signed-off-by: Shawn O. Pearce --- lib/choose_repository.tcl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/choose_repository.tcl b/lib/choose_repository.tcl index ab8e620c70..1e55aec90a 100644 --- a/lib/choose_repository.tcl +++ b/lib/choose_repository.tcl @@ -108,6 +108,8 @@ constructor pick {} { -label [mc "Open..."] } + $opts conf -state disabled + set sorted_recent [_get_recentrepos] if {[llength $sorted_recent] > 0} { if {$m_repo ne {}} { From 914c4d4dcd96218d33f5fefc9c175ea785972f06 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 12 Oct 2007 11:13:58 -0400 Subject: [PATCH 0166/1490] git-gui: Bind n/c/o accelerators in repository chooser On Windows we need to actually setup binds for the accelerator keys, otherwise the OS doesn't respond to them when the user presses the key combinations. Apparently we automatically get these on Mac OS X when we configure the menu commands, but not on Windows. Signed-off-by: Shawn O. Pearce --- lib/choose_repository.tcl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/choose_repository.tcl b/lib/choose_repository.tcl index 1e55aec90a..e66df85964 100644 --- a/lib/choose_repository.tcl +++ b/lib/choose_repository.tcl @@ -84,6 +84,8 @@ constructor pick {} { -command [cb _next new] \ -accelerator $M1T-N \ -label [mc "New..."] + bind $top <$M1B-n> [cb _next new] + bind $top <$M1B-N> [cb _next new] } $opts tag conf link_clone -foreground blue -underline 1 @@ -95,6 +97,8 @@ constructor pick {} { -command [cb _next clone] \ -accelerator $M1T-C \ -label [mc "Clone..."] + bind $top <$M1B-c> [cb _next clone] + bind $top <$M1B-C> [cb _next clone] } $opts tag conf link_open -foreground blue -underline 1 @@ -106,6 +110,8 @@ constructor pick {} { -command [cb _next open] \ -accelerator $M1T-O \ -label [mc "Open..."] + bind $top <$M1B-o> [cb _next open] + bind $top <$M1B-O> [cb _next open] } $opts conf -state disabled From d6db1ad51a5ac8154fcc2413f1eb6142c1a0639a Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 12 Oct 2007 12:18:02 -0400 Subject: [PATCH 0167/1490] git-gui: Ensure copyright message is correctly read as UTF-8 On Windows using the native Tcl/Tk the copyright header is being read from the script using the system encoding, which may not be utf-8. This causes the multi-byte copyright symbol (which is actually encoded as utf-8) to read as two characters and not as a proper copyright symbol. Explicitly asking Tcl to read this sequence of bytes as utf-8 corrects the issue. Signed-off-by: Shawn O. Pearce --- git-gui.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/git-gui.sh b/git-gui.sh index dd320fb075..9bc5626286 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -10,7 +10,7 @@ exec wish "$argv0" -- "$@" set appvers {@@GITGUI_VERSION@@} -set copyright { +set copyright [encoding convertfrom utf-8 { Copyright © 2006, 2007 Shawn Pearce, et. al. This program is free software; you can redistribute it and/or modify @@ -25,7 +25,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA} +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA}] ###################################################################### ## From 51a41ac4efd8bcbcf2aa6e738c42ae4d46d10947 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 12 Oct 2007 16:11:35 -0400 Subject: [PATCH 0168/1490] git-gui: Use proper Windows shortcuts instead of bat files On Windows its better to use a shortcut (.lnk file) over a batch script (.bat) as we can specify the icon file for the .lnk and thus have these git specific objects appear on the desktop with that git specific icon file. Unfortunately the authors of Tcl did not bless us with the APIs needed to create shortcuts from within Tcl. But Microsoft did give us Windows Scripting Host which allows us to execute some JavaScript that calls some sort of COM object that can operate on a .lnk file. We now build both Cygwin and non-Cygwin "desktop icons" as proper Windows .lnk files, using the "Start in" property of these files to indicate the working directory of the repository the user wants to launch. Signed-off-by: Shawn O. Pearce --- Makefile | 10 +++++---- lib/shortcut.tcl | 49 ++++++++++++++++--------------------------- lib/win32.tcl | 26 +++++++++++++++++++++++ lib/win32_shortcut.js | 34 ++++++++++++++++++++++++++++++ 4 files changed, 84 insertions(+), 35 deletions(-) create mode 100644 lib/win32.tcl create mode 100644 lib/win32_shortcut.js diff --git a/Makefile b/Makefile index 2ad8846198..ef9cd91262 100644 --- a/Makefile +++ b/Makefile @@ -19,6 +19,10 @@ GITGUI_MAIN := git-gui GITGUI_BUILT_INS = git-citool ALL_LIBFILES = $(wildcard lib/*.tcl) PRELOAD_FILES = lib/class.tcl +NONTCL_LIBFILES = \ + lib/git-gui.ico \ + $(wildcard lib/win32_*.js) \ +#end NONTCL_LIBFILES ifndef SHELL_PATH SHELL_PATH = /bin/sh @@ -255,12 +259,11 @@ ifdef GITGUI_WINDOWS_WRAPPER endif $(QUIET)$(INSTALL_D0)'$(DESTDIR_SQ)$(libdir_SQ)' $(INSTALL_D1) $(QUIET)$(INSTALL_R0)lib/tclIndex $(INSTALL_R1) '$(DESTDIR_SQ)$(libdir_SQ)' - $(QUIET)$(INSTALL_R0)lib/git-gui.ico $(INSTALL_R1) '$(DESTDIR_SQ)$(libdir_SQ)' ifdef GITGUI_MACOSXAPP $(QUIET)$(INSTALL_A0)'Git Gui.app' $(INSTALL_A1) '$(DESTDIR_SQ)$(libdir_SQ)' $(QUIET)$(INSTALL_X0)git-gui.tcl $(INSTALL_X1) '$(DESTDIR_SQ)$(libdir_SQ)' endif - $(QUIET)$(foreach p,$(ALL_LIBFILES), $(INSTALL_R0)$p $(INSTALL_R1) '$(DESTDIR_SQ)$(libdir_SQ)' &&) true + $(QUIET)$(foreach p,$(ALL_LIBFILES) $(NONTCL_LIBFILES), $(INSTALL_R0)$p $(INSTALL_R1) '$(DESTDIR_SQ)$(libdir_SQ)' &&) true $(QUIET)$(INSTALL_D0)'$(DESTDIR_SQ)$(msgsdir_SQ)' $(INSTALL_D1) $(QUIET)$(foreach p,$(ALL_MSGFILES), $(INSTALL_R0)$p $(INSTALL_R1) '$(DESTDIR_SQ)$(msgsdir_SQ)' &&) true @@ -273,12 +276,11 @@ ifdef GITGUI_WINDOWS_WRAPPER endif $(QUIET)$(CLEAN_DST) '$(DESTDIR_SQ)$(libdir_SQ)' $(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(libdir_SQ)'/tclIndex $(REMOVE_F1) - $(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(libdir_SQ)'/git-gui.ico $(REMOVE_F1) ifdef GITGUI_MACOSXAPP $(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(libdir_SQ)/Git Gui.app' $(REMOVE_F1) $(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(libdir_SQ)'/git-gui.tcl $(REMOVE_F1) endif - $(QUIET)$(foreach p,$(ALL_LIBFILES), $(REMOVE_F0)'$(DESTDIR_SQ)$(libdir_SQ)'/$(notdir $p) $(REMOVE_F1) &&) true + $(QUIET)$(foreach p,$(ALL_LIBFILES) $(NONTCL_LIBFILES), $(REMOVE_F0)'$(DESTDIR_SQ)$(libdir_SQ)'/$(notdir $p) $(REMOVE_F1) &&) true $(QUIET)$(CLEAN_DST) '$(DESTDIR_SQ)$(msgsdir_SQ)' $(QUIET)$(foreach p,$(ALL_MSGFILES), $(REMOVE_F0)'$(DESTDIR_SQ)$(msgsdir_SQ)'/$(notdir $p) $(REMOVE_F1) &&) true $(QUIET)$(REMOVE_D0)'$(DESTDIR_SQ)$(gitexecdir_SQ)' $(REMOVE_D1) diff --git a/lib/shortcut.tcl b/lib/shortcut.tcl index a7674a7aee..38c3151b05 100644 --- a/lib/shortcut.tcl +++ b/lib/shortcut.tcl @@ -2,28 +2,22 @@ # Copyright (C) 2006, 2007 Shawn Pearce proc do_windows_shortcut {} { - global argv0 - set fn [tk_getSaveFile \ -parent . \ -title [append "[appname] ([reponame]): " [mc "Create Desktop Icon"]] \ - -initialfile "Git [reponame].bat"] + -initialfile "Git [reponame].lnk"] if {$fn != {}} { - if {[file extension $fn] ne {.bat}} { - set fn ${fn}.bat + if {[file extension $fn] ne {.lnk}} { + set fn ${fn}.lnk } if {[catch { - set ge [file normalize [file dirname $::_git]] - set fd [open $fn w] - puts $fd "@ECHO Entering [reponame]" - puts $fd "@ECHO Starting git-gui... please wait..." - puts $fd "@SET PATH=$ge;%PATH%" - puts $fd "@SET GIT_DIR=[file normalize [gitdir]]" - puts -nonewline $fd "@\"[info nameofexecutable]\"" - puts $fd " \"[file normalize $argv0]\"" - close $fd + win32_create_lnk $fn [list \ + [info nameofexecutable] \ + [file normalize $::argv0] \ + ] \ + [file dirname [file normalize [gitdir]]] } err]} { - error_popup [strcat [mc "Cannot write script:"] "\n\n$err"] + error_popup [strcat [mc "Cannot write shortcut:"] "\n\n$err"] } } } @@ -44,13 +38,12 @@ proc do_cygwin_shortcut {} { -parent . \ -title [append "[appname] ([reponame]): " [mc "Create Desktop Icon"]] \ -initialdir $desktop \ - -initialfile "Git [reponame].bat"] + -initialfile "Git [reponame].lnk"] if {$fn != {}} { - if {[file extension $fn] ne {.bat}} { - set fn ${fn}.bat + if {[file extension $fn] ne {.lnk}} { + set fn ${fn}.lnk } if {[catch { - set fd [open $fn w] set sh [exec cygpath \ --windows \ --absolute \ @@ -59,19 +52,13 @@ proc do_cygwin_shortcut {} { --unix \ --absolute \ $argv0] - set gd [exec cygpath \ - --unix \ - --absolute \ - [gitdir]] - puts $fd "@ECHO Entering [reponame]" - puts $fd "@ECHO Starting git-gui... please wait..." - puts -nonewline $fd "@\"$sh\" --login -c \"" - puts -nonewline $fd "GIT_DIR=[sq $gd]" - puts -nonewline $fd " [sq $me]" - puts $fd " &\"" - close $fd + win32_create_lnk $fn [list \ + $sh -c \ + "CHERE_INVOKING=1 source /etc/profile;[sq $me]" \ + ] \ + [file dirname [file normalize [gitdir]]] } err]} { - error_popup [strcat [mc "Cannot write script:"] "\n\n$err"] + error_popup [strcat [mc "Cannot write shortcut:"] "\n\n$err"] } } } diff --git a/lib/win32.tcl b/lib/win32.tcl new file mode 100644 index 0000000000..d7f93d045d --- /dev/null +++ b/lib/win32.tcl @@ -0,0 +1,26 @@ +# git-gui Misc. native Windows 32 support +# Copyright (C) 2007 Shawn Pearce + +proc win32_read_lnk {lnk_path} { + return [exec cscript.exe \ + /E:jscript \ + /nologo \ + [file join $::oguilib win32_shortcut.js] \ + $lnk_path] +} + +proc win32_create_lnk {lnk_path lnk_exec lnk_dir} { + global oguilib + + set lnk_args [lrange $lnk_exec 1 end] + set lnk_exec [lindex $lnk_exec 0] + + eval [list exec wscript.exe \ + /E:jscript \ + /nologo \ + [file join $oguilib win32_shortcut.js] \ + $lnk_path \ + [file join $oguilib git-gui.ico] \ + $lnk_dir \ + $lnk_exec] $lnk_args +} diff --git a/lib/win32_shortcut.js b/lib/win32_shortcut.js new file mode 100644 index 0000000000..117923f886 --- /dev/null +++ b/lib/win32_shortcut.js @@ -0,0 +1,34 @@ +// git-gui Windows shortcut support +// Copyright (C) 2007 Shawn Pearce + +var WshShell = WScript.CreateObject("WScript.Shell"); +var argv = WScript.Arguments; +var argi = 0; +var lnk_path = argv.item(argi++); +var ico_path = argi < argv.length ? argv.item(argi++) : undefined; +var dir_path = argi < argv.length ? argv.item(argi++) : undefined; +var lnk_exec = argi < argv.length ? argv.item(argi++) : undefined; +var lnk_args = ''; +while (argi < argv.length) { + var s = argv.item(argi++); + if (lnk_args != '') + lnk_args += ' '; + if (s.indexOf(' ') >= 0) { + lnk_args += '"'; + lnk_args += s; + lnk_args += '"'; + } else { + lnk_args += s; + } +} + +var lnk = WshShell.CreateShortcut(lnk_path); +if (argv.length == 1) { + WScript.echo(lnk.TargetPath); +} else { + lnk.TargetPath = lnk_exec; + lnk.Arguments = lnk_args; + lnk.IconLocation = ico_path + ", 0"; + lnk.WorkingDirectory = dir_path; + lnk.Save(); +} From ba6c761e6287f9987d70ed4d2a609a7ed415a6a5 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 12 Oct 2007 16:24:20 -0400 Subject: [PATCH 0169/1490] git-gui: Support cloning Cygwin based work-dirs If the user tries to clone a Git repository that is actually a workdir of another repository (by way of contrib git-new-workdir) then the contents of .git is a series of Windows .lnk files which Tcl can't read if this is a native Tcl process. To read the real objects directory we need to resolve the link to that location. Signed-off-by: Shawn O. Pearce --- lib/choose_repository.tcl | 44 ++++++++++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/lib/choose_repository.tcl b/lib/choose_repository.tcl index e66df85964..bf04361464 100644 --- a/lib/choose_repository.tcl +++ b/lib/choose_repository.tcl @@ -324,9 +324,42 @@ proc _is_git {path} { && [file exists [file join $path config]]} { return 1 } + if {[is_Cygwin]} { + if {[file exists [file join $path HEAD]] + && [file exists [file join $path objects.lnk]] + && [file exists [file join $path config.lnk]]} { + return 1 + } + } return 0 } +proc _objdir {path} { + set objdir [file join $path .git objects] + if {[file isdirectory $objdir]} { + return $objdir + } + + set objdir [file join $path objects] + if {[file isdirectory $objdir]} { + return $objdir + } + + if {[is_Cygwin]} { + set objdir [file join $path .git objects.lnk] + if {[file isfile $objdir]} { + return [win32_read_lnk $objdir] + } + + set objdir [file join $path objects.lnk] + if {[file isfile $objdir]} { + return [win32_read_lnk $objdir] + } + } + + return {} +} + ###################################################################### ## ## Create New Repository @@ -555,13 +588,10 @@ method _do_clone2 {} { } if {$clone_type eq {hardlink} || $clone_type eq {shared}} { - set objdir [file join $origin_url .git objects] - if {![file isdirectory $objdir]} { - set objdir [file join $origin_url objects] - if {![file isdirectory $objdir]} { - error_popup [mc "Not a Git repository: %s" [file tail $origin_url]] - return - } + set objdir [_objdir $origin_url] + if {$objdir eq {}} { + error_popup [mc "Not a Git repository: %s" [file tail $origin_url]] + return } } From 82dd4e0465282e39962ba8fdb01c42aa665b1999 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 12 Oct 2007 16:33:45 -0400 Subject: [PATCH 0170/1490] git-gui: Collapse $env(HOME) to ~/ in recent repositories on Windows Apparently native Tcl/Tk on Windows is using \ as the return value from [file separator] but [file normalize] on that same system is using / rather than \ to represent a directory separator. I really think that is nuts, but its what is happening. So we can actually just hardcode our separator to / as all systems we support (Windows, Mac OS X, UNIX) use /. Signed-off-by: Shawn O. Pearce --- lib/choose_repository.tcl | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/choose_repository.tcl b/lib/choose_repository.tcl index bf04361464..2bac50e149 100644 --- a/lib/choose_repository.tcl +++ b/lib/choose_repository.tcl @@ -140,12 +140,16 @@ constructor pick {} { $w_recentlist tag conf link \ -foreground blue \ -underline 1 - set home "[file normalize $::env(HOME)][file separator]" + set home $::env(HOME) + if {[is_Cygwin]} { + set home [exec cygpath --windows --absolute $home] + } + set home "[file normalize $home]/" set hlen [string length $home] foreach p $sorted_recent { set path $p if {[string equal -length $hlen $home $p]} { - set p "~[file separator][string range $p $hlen end]" + set p "~/[string range $p $hlen end]" } regsub -all "\n" $p "\\n" p $w_recentlist insert end $p link From 86215812487930c69e197ef03be31e0b396a04cc Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Sat, 13 Oct 2007 15:41:31 -0400 Subject: [PATCH 0171/1490] git-gui: Honor a config.mak in git-gui's top level I keep forgetting to include TCLTK_PATH when I build git-gui on some systems. Placing that rule (among others) into a config.mak makes it easier to compile the application the same way every time. Signed-off-by: Shawn O. Pearce --- .gitignore | 1 + Makefile | 2 ++ 2 files changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index a7cfd6d5a0..6483b21cbf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .DS_Store +config.mak Git Gui.app* git-gui.tcl GIT-VERSION-FILE diff --git a/Makefile b/Makefile index ef9cd91262..e860319278 100644 --- a/Makefile +++ b/Makefile @@ -99,6 +99,8 @@ ifeq ($(findstring $(MAKEFLAGS),s),s) QUIET_GEN = endif +-include config.mak + DESTDIR_SQ = $(subst ','\'',$(DESTDIR)) gitexecdir_SQ = $(subst ','\'',$(gitexecdir)) SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH)) From 2467a4fa03ff849fcf2f6a93b89057aebd49c62b Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Mon, 8 Oct 2007 00:25:07 -0400 Subject: [PATCH 0172/1490] Remove duplicate ref matches in fetch If multiple refspecs matched the same ref, the update would be processed multiple times. Now having the same destination for the same source has no additional effect, and having the same destination for different sources is an error. Signed-off-by: Daniel Barkalow Signed-off-by: Lars Hjemli Signed-off-by: Shawn O. Pearce --- builtin-fetch.c | 1 + remote.c | 27 +++++++++++++++++++++++++++ remote.h | 5 +++++ 3 files changed, 33 insertions(+) diff --git a/builtin-fetch.c b/builtin-fetch.c index cf7498b15f..caaca63644 100644 --- a/builtin-fetch.c +++ b/builtin-fetch.c @@ -112,6 +112,7 @@ static struct ref *get_ref_map(struct transport *transport, ref_map->merge = 1; } } + ref_remove_duplicates(ref_map); return ref_map; } diff --git a/remote.c b/remote.c index e7d735b98a..e2ca4d32ba 100644 --- a/remote.c +++ b/remote.c @@ -380,6 +380,33 @@ int for_each_remote(each_remote_fn fn, void *priv) return result; } +void ref_remove_duplicates(struct ref *ref_map) +{ + struct ref **posn; + struct ref *next; + for (; ref_map; ref_map = ref_map->next) { + if (!ref_map->peer_ref) + continue; + posn = &ref_map->next; + while (*posn) { + if ((*posn)->peer_ref && + !strcmp((*posn)->peer_ref->name, + ref_map->peer_ref->name)) { + if (strcmp((*posn)->name, ref_map->name)) + die("%s tracks both %s and %s", + ref_map->peer_ref->name, + (*posn)->name, ref_map->name); + next = (*posn)->next; + free((*posn)->peer_ref); + free(*posn); + *posn = next; + } else { + posn = &(*posn)->next; + } + } + } +} + int remote_has_url(struct remote *remote, const char *url) { int i; diff --git a/remote.h b/remote.h index 05add06e48..c62636d78e 100644 --- a/remote.h +++ b/remote.h @@ -49,6 +49,11 @@ struct ref *alloc_ref(unsigned namelen); */ void free_refs(struct ref *ref); +/* + * Removes and frees any duplicate refs in the map. + */ +void ref_remove_duplicates(struct ref *ref_map); + struct refspec *parse_ref_spec(int nr_refspec, const char **refspec); int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail, From 8f70a7657a9b459d6a4a3bcb1628c0fa6a6c22e0 Mon Sep 17 00:00:00 2001 From: Alex Riesen Date: Fri, 12 Oct 2007 22:40:04 +0200 Subject: [PATCH 0173/1490] Fix a crash in ls-remote when refspec expands into nothing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Originally-by: Väinö Järvelä Signed-off-by: Alex Riesen Signed-off-by: Lars Hjemli Signed-off-by: Shawn O. Pearce --- remote.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/remote.c b/remote.c index e2ca4d32ba..b20e2be433 100644 --- a/remote.c +++ b/remote.c @@ -909,7 +909,8 @@ int get_fetch_map(struct ref *remote_refs, rm->peer_ref->name); } - tail_link_ref(ref_map, tail); + if (ref_map) + tail_link_ref(ref_map, tail); return 0; } From f539d0d6c1f0b4431c0711e290d1f5a7205ed6e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A4in=C3=B6=20J=C3=A4rvel=C3=A4?= Date: Tue, 9 Oct 2007 11:51:07 +0300 Subject: [PATCH 0174/1490] Added a test for fetching remote tags when there is not tags. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a user runs "git fetch -t", git crashes when it doesn't find any tags on the remote repository. Signed-off-by: Väinö Järvelä Signed-off-by: Lars Hjemli Signed-off-by: Shawn O. Pearce --- t/t5510-fetch.sh | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh index 73a4e3cbc3..40ebf2e2bf 100755 --- a/t/t5510-fetch.sh +++ b/t/t5510-fetch.sh @@ -67,6 +67,18 @@ test_expect_success "fetch test for-merge" ' cut -f -2 .git/FETCH_HEAD >actual && diff expected actual' +test_expect_success 'fetch tags when there is no tags' ' + + cd "$D" && + + mkdir notags && + cd notags && + git init && + + git fetch -t .. + +' + test_expect_success 'fetch following tags' ' cd "$D" && From ccfc02a30057a5fa7376e1fc8e8c3fe5478556f4 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Mon, 15 Oct 2007 14:52:25 +0100 Subject: [PATCH 0175/1490] Fix compilation when NO_CURL is defined There were a few places which did not cope well without curl. This fixes all of them. We still need to link against the walker.o part of the library as some parts of transport.o still call into there even though we don't have HTTP support enabled. If compiled with NO_CURL=1 we now get the following useful error message: $ git-fetch http://www.example.com/git error: git was compiled without libcurl support. fatal: Don't know how to fetch from http://www.example.com/git Signed-off-by: Johannes Schindelin Signed-off-by: Shawn O. Pearce --- Makefile | 6 +++--- transport.c | 23 +++++++---------------- 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/Makefile b/Makefile index 23dc52c1d9..7dd212a19e 100644 --- a/Makefile +++ b/Makefile @@ -310,7 +310,7 @@ LIB_OBJS = \ alloc.o merge-file.o path-list.o help.o unpack-trees.o $(DIFF_OBJS) \ color.o wt-status.o archive-zip.o archive-tar.o shallow.o utf8.o \ convert.o attr.o decorate.o progress.o mailmap.o symlinks.o remote.o \ - transport.o bundle.o + transport.o bundle.o walker.o BUILTIN_OBJS = \ builtin-add.o \ @@ -528,7 +528,7 @@ else endif BUILTIN_OBJS += builtin-http-fetch.o EXTLIBS += $(CURL_LIBCURL) - LIB_OBJS += http.o walker.o http-walker.o + LIB_OBJS += http.o http-walker.o curl_check := $(shell (echo 070908; curl-config --vernum) | sort -r | sed -ne 2p) ifeq "$(curl_check)" "070908" ifndef NO_EXPAT @@ -905,7 +905,7 @@ git-http-push$X: revision.o http.o http-push.o $(GITLIBS) $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \ $(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT) -$(LIB_OBJS) $(BUILTIN_OBJS) walker.o: $(LIB_H) +$(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H) $(patsubst git-%$X,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h) $(DIFF_OBJS): diffcore.h diff --git a/transport.c b/transport.c index 6fe6ec8503..46da754078 100644 --- a/transport.c +++ b/transport.c @@ -1,7 +1,9 @@ #include "cache.h" #include "transport.h" #include "run-command.h" +#ifndef NO_CURL #include "http.h" +#endif #include "pkt-line.h" #include "fetch-pack.h" #include "walker.h" @@ -368,6 +370,7 @@ static int disconnect_walker(struct transport *transport) return 0; } +#ifndef NO_CURL static int curl_transport_push(struct transport *transport, int refspec_nr, const char **refspec, int flags) { const char **argv; int argc; @@ -400,7 +403,6 @@ static int curl_transport_push(struct transport *transport, int refspec_nr, cons return !!err; } -#ifndef NO_CURL static int missing__target(int code, int result) { return /* file:// URL -- do we ever use one??? */ @@ -504,21 +506,6 @@ static int fetch_objs_via_curl(struct transport *transport, return fetch_objs_via_walker(transport, nr_objs, to_fetch); } -#else - -static struct ref *get_refs_via_curl(const struct transport *transport) -{ - die("Cannot fetch from '%s' without curl ...", transport->url); - return NULL; -} - -static int fetch_objs_via_curl(struct transport *transport, - int nr_objs, struct ref **to_fetch) -{ - die("Cannot fetch from '%s' without curl ...", transport->url); - return -1; -} - #endif struct bundle_transport_data { @@ -733,9 +720,13 @@ struct transport *transport_get(struct remote *remote, const char *url) } else if (!prefixcmp(url, "http://") || !prefixcmp(url, "https://") || !prefixcmp(url, "ftp://")) { +#ifdef NO_CURL + error("git was compiled without libcurl support."); +#else ret->get_refs_list = get_refs_via_curl; ret->fetch = fetch_objs_via_curl; ret->push = curl_transport_push; +#endif ret->disconnect = disconnect_walker; } else if (is_local(url) && is_file(url)) { From 18184f79dbf70e157399ba2288f7045582fd61c6 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Tue, 16 Oct 2007 00:25:34 -0400 Subject: [PATCH 0176/1490] Fix 'push --all branch...' error handling The builtin-fetch topic changed push's handling of --all to setting the new TRANSPORT_PUSH_ALL flag before starting the push subroutine for the given transport. Unfortunately not all references within builtin-push were changed to test this flag therefore allowing push to incorrectly accept refspecs and --all. Signed-off-by: Shawn O. Pearce --- builtin-push.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/builtin-push.c b/builtin-push.c index a552f0dac6..4b39ef3852 100644 --- a/builtin-push.c +++ b/builtin-push.c @@ -10,7 +10,7 @@ static const char push_usage[] = "git-push [--all] [--dry-run] [--tags] [--receive-pack=] [--repo=all] [-f | --force] [-v] [ ...]"; -static int all, thin, verbose; +static int thin, verbose; static const char *receivepack; static const char **refspec; @@ -52,7 +52,9 @@ static int do_push(const char *repo, int flags) if (!remote) die("bad repository '%s'", repo); - if (!refspec && !all && remote->push_refspec_nr) { + if (!refspec + && !(flags & TRANSPORT_PUSH_ALL) + && remote->push_refspec_nr) { refspec = remote->push_refspec; refspec_nr = remote->push_refspec_nr; } @@ -138,7 +140,7 @@ int cmd_push(int argc, const char **argv, const char *prefix) usage(push_usage); } set_refspecs(argv + i, argc - i); - if (all && refspec) + if ((flags & TRANSPORT_PUSH_ALL) && refspec) usage(push_usage); return do_push(repo, flags); From ee020f3598f0dc86a939fb8597845594bf664898 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Tue, 16 Oct 2007 00:28:32 -0400 Subject: [PATCH 0177/1490] Support 'push --dry-run' for rsync transport If the end-user requested a dry-run push we should pass that flag though to rsync so that the rsync command can show what it would do (or not do) if push was to be executed without the --dry-run flag. Signed-off-by: Shawn O. Pearce --- transport.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/transport.c b/transport.c index e363c11c05..f34d19750f 100644 --- a/transport.c +++ b/transport.c @@ -281,7 +281,7 @@ static int rsync_transport_push(struct transport *transport, struct strbuf buf = STRBUF_INIT, temp_dir = STRBUF_INIT; int result = 0, i; struct child_process rsync; - const char *args[8]; + const char *args[10]; /* first push the objects */ @@ -291,14 +291,19 @@ static int rsync_transport_push(struct transport *transport, memset(&rsync, 0, sizeof(rsync)); rsync.argv = args; rsync.stdout_to_stderr = 1; - args[0] = "rsync"; - args[1] = (transport->verbose > 0) ? "-av" : "-a"; - args[2] = "--ignore-existing"; - args[3] = "--exclude"; - args[4] = "info"; - args[5] = get_object_directory();; - args[6] = buf.buf; - args[7] = NULL; + i = 0; + args[i++] = "rsync"; + args[i++] = "-a"; + if (flags & TRANSPORT_PUSH_DRY_RUN) + args[i++] = "--dry-run"; + if (transport->verbose > 0) + args[i++] = "-v"; + args[i++] = "--ignore-existing"; + args[i++] = "--exclude"; + args[i++] = "info"; + args[i++] = get_object_directory(); + args[i++] = buf.buf; + args[i++] = NULL; if (run_command(&rsync)) return error("Could not push objects to %s", transport->url); @@ -316,7 +321,11 @@ static int rsync_transport_push(struct transport *transport, } else if (write_refs_to_temp_dir(&temp_dir, refspec_nr, refspec)) return -1; - i = (flags & TRANSPORT_PUSH_FORCE) ? 2 : 3; + i = 2; + if (flags & TRANSPORT_PUSH_DRY_RUN) + args[i++] = "--dry-run"; + if (!(flags & TRANSPORT_PUSH_FORCE)) + args[i++] = "--ignore-existing"; args[i++] = temp_dir.buf; args[i++] = transport->url; args[i++] = NULL; From fe5d1d3eb42e6cf3dca93b2277be9464b026fcf2 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Tue, 16 Oct 2007 00:35:22 -0400 Subject: [PATCH 0178/1490] Support 'push --dry-run' for http transport If the end-user requested a dry-run push we need to pass that flag over to http-push and additionally make sure it does not actually upload any changes to the remote server. Signed-off-by: Shawn O. Pearce --- Documentation/git-http-push.txt | 5 ++++- http-push.c | 13 ++++++++++--- transport.c | 2 ++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/Documentation/git-http-push.txt b/Documentation/git-http-push.txt index 9afb860381..3a69b719b5 100644 --- a/Documentation/git-http-push.txt +++ b/Documentation/git-http-push.txt @@ -8,7 +8,7 @@ git-http-push - Push objects over HTTP/DAV to another repository SYNOPSIS -------- -'git-http-push' [--all] [--force] [--verbose] [...] +'git-http-push' [--all] [--dry-run] [--force] [--verbose] [...] DESCRIPTION ----------- @@ -30,6 +30,9 @@ OPTIONS the remote repository can lose commits; use it with care. +--dry-run:: + Do everything except actually send the updates. + --verbose:: Report the list of objects being walked locally and the list of objects successfully sent to the remote repository. diff --git a/http-push.c b/http-push.c index a035919764..c02a3af634 100644 --- a/http-push.c +++ b/http-push.c @@ -13,7 +13,7 @@ #include static const char http_push_usage[] = -"git-http-push [--all] [--force] [--verbose] [...]\n"; +"git-http-push [--all] [--dry-run] [--force] [--verbose] [...]\n"; #ifndef XML_STATUS_OK enum XML_Status { @@ -80,6 +80,7 @@ static struct curl_slist *default_headers; static int push_verbosely; static int push_all; static int force_all; +static int dry_run; static struct object_list *objects; @@ -2302,6 +2303,10 @@ int main(int argc, char **argv) force_all = 1; continue; } + if (!strcmp(arg, "--dry-run")) { + dry_run = 1; + continue; + } if (!strcmp(arg, "--verbose")) { push_verbosely = 1; continue; @@ -2443,7 +2448,8 @@ int main(int argc, char **argv) if (strcmp(ref->name, ref->peer_ref->name)) fprintf(stderr, " using '%s'", ref->peer_ref->name); fprintf(stderr, "\n from %s\n to %s\n", old_hex, new_hex); - + if (dry_run) + continue; /* Lock remote branch ref */ ref_lock = lock_remote(ref->name, LOCK_TIME); @@ -2511,7 +2517,8 @@ int main(int argc, char **argv) if (remote->has_info_refs && new_refs) { if (info_ref_lock && remote->can_update_info_refs) { fprintf(stderr, "Updating remote server info\n"); - update_remote_info_refs(info_ref_lock); + if (!dry_run) + update_remote_info_refs(info_ref_lock); } else { fprintf(stderr, "Unable to update server info\n"); } diff --git a/transport.c b/transport.c index f34d19750f..400af71c76 100644 --- a/transport.c +++ b/transport.c @@ -392,6 +392,8 @@ static int curl_transport_push(struct transport *transport, int refspec_nr, cons argv[argc++] = "--all"; if (flags & TRANSPORT_PUSH_FORCE) argv[argc++] = "--force"; + if (flags & TRANSPORT_PUSH_DRY_RUN) + argv[argc++] = "--dry-run"; argv[argc++] = transport->url; while (refspec_nr--) argv[argc++] = *refspec++; From da0204df587ae76cd291bc7e495fc60d873c2f20 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Thu, 11 Oct 2007 01:47:55 +0100 Subject: [PATCH 0179/1490] fetch: if not fetching from default remote, ignore default merge When doing "git fetch " on a remote that does not have the branch referenced in branch..merge, git fetch failed. It failed because it tried to add the "merge" ref to the refs to be fetched. Fix that. And add a test case. Incidentally, this unconvered a bug in our own test suite, where "git pull " was expected to merge the ref given in the defaults, even if not pulling from the default remote. Signed-off-by: Johannes Schindelin Signed-off-by: Lars Hjemli Signed-off-by: Shawn O. Pearce --- builtin-fetch.c | 8 +++++++- t/t5510-fetch.sh | 8 ++++++++ t/t5700-clone-reference.sh | 4 ++-- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/builtin-fetch.c b/builtin-fetch.c index caaca63644..3442f3d09e 100644 --- a/builtin-fetch.c +++ b/builtin-fetch.c @@ -105,7 +105,13 @@ static struct ref *get_ref_map(struct transport *transport, !remote->fetch[0].pattern) ref_map->merge = 1; } - if (has_merge) + /* + * if the remote we're fetching from is the same + * as given in branch..remote, we add the + * ref given in branch..merge, too. + */ + if (has_merge && !strcmp(branch->remote_name, + remote->name)) add_merge_config(&ref_map, remote_refs, branch, &tail); } else { ref_map = get_remote_ref(remote_refs, "HEAD"); diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh index 40ebf2e2bf..d217657146 100755 --- a/t/t5510-fetch.sh +++ b/t/t5510-fetch.sh @@ -200,4 +200,12 @@ test_expect_success 'push via rsync' ' ' } +test_expect_success 'fetch with a non-applying branch..merge' ' + git config branch.master.remote yeti && + git config branch.master.merge refs/heads/bigfoot && + git config remote.blub.url one && + git config remote.blub.fetch "refs/heads/*:refs/remotes/one/*" && + git fetch blub +' + test_done diff --git a/t/t5700-clone-reference.sh b/t/t5700-clone-reference.sh index 4e93aaab02..b6a54867b4 100755 --- a/t/t5700-clone-reference.sh +++ b/t/t5700-clone-reference.sh @@ -38,7 +38,7 @@ cd "$base_dir" test_expect_success 'pulling from reference' \ 'cd C && -git pull ../B' +git pull ../B master' cd "$base_dir" @@ -61,7 +61,7 @@ test_expect_success 'existence of info/alternates' \ cd "$base_dir" test_expect_success 'pulling from reference' \ -'cd D && git pull ../B' +'cd D && git pull ../B master' cd "$base_dir" From 42e18fbf5f94dd6bd303bf702e030a29fa39d6c4 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 16 Oct 2007 21:55:45 -0400 Subject: [PATCH 0180/1490] more compact progress display Each progress can be on a single line instead of two. [sp: Changed "Checking files out" to "Checking out files" at Johannes Sixt's suggestion as it better explains the action that is taking place] Signed-off-by: Nicolas Pitre Signed-off-by: Shawn O. Pearce --- builtin-pack-objects.c | 16 ++++-------- builtin-unpack-objects.c | 2 +- index-pack.c | 4 +-- progress.c | 53 +++++++++++++++++++--------------------- progress.h | 10 +++----- unpack-trees.c | 4 +-- 6 files changed, 39 insertions(+), 50 deletions(-) diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index 0be539ed7f..df69abd514 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -606,7 +606,7 @@ static void write_pack_file(void) uint32_t nr_remaining = nr_result; if (do_progress) - start_progress(&progress_state, "Writing %u objects...", "", nr_result); + start_progress(&progress_state, "Writing objects", nr_result); written_list = xmalloc(nr_objects * sizeof(struct object_entry *)); do { @@ -1717,9 +1717,8 @@ static void prepare_pack(int window, int depth) if (nr_deltas) { unsigned nr_done = 0; if (progress) - start_progress(&progress_state, - "Deltifying %u objects...", "", - nr_deltas); + start_progress(&progress_state, "Deltifying objects", + nr_deltas); qsort(delta_list, n, sizeof(*delta_list), type_size_sort); ll_find_deltas(delta_list, n, window+1, depth, &nr_done); if (progress) @@ -2135,23 +2134,18 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) prepare_packed_git(); if (progress) - start_progress(&progress_state, "Generating pack...", - "Counting objects: ", 0); + start_progress(&progress_state, "Counting objects", 0); if (!use_internal_rev_list) read_object_list_from_stdin(); else { rp_av[rp_ac] = NULL; get_object_list(rp_ac, rp_av); } - if (progress) { + if (progress) stop_progress(&progress_state); - fprintf(stderr, "Done counting %u objects.\n", nr_objects); - } if (non_empty && !nr_result) return 0; - if (progress && (nr_objects != nr_result)) - fprintf(stderr, "Result has %u objects.\n", nr_result); if (nr_result) prepare_pack(window, depth); write_pack_file(); diff --git a/builtin-unpack-objects.c b/builtin-unpack-objects.c index a6ff62fd8c..2317b8f411 100644 --- a/builtin-unpack-objects.c +++ b/builtin-unpack-objects.c @@ -322,7 +322,7 @@ static void unpack_all(void) use(sizeof(struct pack_header)); if (!quiet) - start_progress(&progress, "Unpacking %u objects...", "", nr_objects); + start_progress(&progress, "Unpacking objects", nr_objects); obj_list = xmalloc(nr_objects * sizeof(*obj_list)); for (i = 0; i < nr_objects; i++) { unpack_one(i); diff --git a/index-pack.c b/index-pack.c index db58e05041..c784decd24 100644 --- a/index-pack.c +++ b/index-pack.c @@ -406,7 +406,7 @@ static void parse_pack_objects(unsigned char *sha1) * - remember base (SHA1 or offset) for all deltas. */ if (verbose) - start_progress(&progress, "Indexing %u objects...", "", nr_objects); + start_progress(&progress, "Indexing objects", nr_objects); for (i = 0; i < nr_objects; i++) { struct object_entry *obj = &objects[i]; data = unpack_raw_entry(obj, &delta->base); @@ -455,7 +455,7 @@ static void parse_pack_objects(unsigned char *sha1) * for some more deltas. */ if (verbose) - start_progress(&progress, "Resolving %u deltas...", "", nr_deltas); + start_progress(&progress, "Resolving deltas", nr_deltas); for (i = 0; i < nr_objects; i++) { struct object_entry *obj = &objects[i]; union delta_base base; diff --git a/progress.c b/progress.c index 4344f4eed5..7629e0572b 100644 --- a/progress.c +++ b/progress.c @@ -35,10 +35,11 @@ static void clear_progress_signal(void) progress_update = 0; } -int display_progress(struct progress *progress, unsigned n) +static int display(struct progress *progress, unsigned n, int done) { + char *eol; + if (progress->delay) { - char buf[80]; if (!progress_update || --progress->delay) return 0; if (progress->total) { @@ -51,60 +52,56 @@ int display_progress(struct progress *progress, unsigned n) return 0; } } - if (snprintf(buf, sizeof(buf), - progress->delayed_title, progress->total)) - fprintf(stderr, "%s\n", buf); } + + progress->last_value = n; + eol = done ? ", done. \n" : " \r"; if (progress->total) { unsigned percent = n * 100 / progress->total; if (percent != progress->last_percent || progress_update) { progress->last_percent = percent; - fprintf(stderr, "%s%4u%% (%u/%u) done\r", - progress->prefix, percent, n, progress->total); + fprintf(stderr, "%s: %3u%% (%u/%u)%s", progress->title, + percent, n, progress->total, eol); progress_update = 0; - progress->need_lf = 1; return 1; } } else if (progress_update) { - fprintf(stderr, "%s%u\r", progress->prefix, n); + fprintf(stderr, "%s: %u%s", progress->title, n, eol); progress_update = 0; - progress->need_lf = 1; return 1; } + return 0; } -void start_progress(struct progress *progress, const char *title, - const char *prefix, unsigned total) +int display_progress(struct progress *progress, unsigned n) { - char buf[80]; - progress->prefix = prefix; - progress->total = total; - progress->last_percent = -1; - progress->delay = 0; - progress->need_lf = 0; - if (snprintf(buf, sizeof(buf), title, total)) - fprintf(stderr, "%s\n", buf); - set_progress_signal(); + return display(progress, n, 0); } void start_progress_delay(struct progress *progress, const char *title, - const char *prefix, unsigned total, - unsigned percent_treshold, unsigned delay) + unsigned total, unsigned percent_treshold, unsigned delay) { - progress->prefix = prefix; + progress->title = title; progress->total = total; + progress->last_value = -1; progress->last_percent = -1; progress->delayed_percent_treshold = percent_treshold; - progress->delayed_title = title; progress->delay = delay; - progress->need_lf = 0; set_progress_signal(); } +void start_progress(struct progress *progress, const char *title, unsigned total) +{ + start_progress_delay(progress, title, total, 0, 0); +} + void stop_progress(struct progress *progress) { + if (progress->last_value != -1) { + /* Force the last update */ + progress_update = 1; + display(progress, progress->last_value, 1); + } clear_progress_signal(); - if (progress->need_lf) - fputc('\n', stderr); } diff --git a/progress.h b/progress.h index a7c17ca7c4..07b56bdbb5 100644 --- a/progress.h +++ b/progress.h @@ -2,21 +2,19 @@ #define PROGRESS_H struct progress { - const char *prefix; + const char *title; + int last_value; unsigned total; unsigned last_percent; unsigned delay; unsigned delayed_percent_treshold; - const char *delayed_title; - int need_lf; }; int display_progress(struct progress *progress, unsigned n); void start_progress(struct progress *progress, const char *title, - const char *prefix, unsigned total); + unsigned total); void start_progress_delay(struct progress *progress, const char *title, - const char *prefix, unsigned total, - unsigned percent_treshold, unsigned delay); + unsigned total, unsigned percent_treshold, unsigned delay); void stop_progress(struct progress *progress); #endif diff --git a/unpack-trees.c b/unpack-trees.c index ccfeb6e245..32251018b2 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -307,8 +307,8 @@ static void check_updates(struct cache_entry **src, int nr, total++; } - start_progress_delay(&progress, "Checking %u files out...", - "", total, 50, 2); + start_progress_delay(&progress, "Checking out files", + total, 50, 2); cnt = 0; } From ed1902ef5c6a30942def50809b52e41fbdcdf13f Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 16 Oct 2007 21:55:46 -0400 Subject: [PATCH 0181/1490] cope with multiple line breaks within sideband progress messages A single sideband packet may sometimes contain multiple lines of progress messages, but we prepend "remote: " only to the whole buffer which creates a messed up display in that case. Make sure that the "remote: " prefix is applied to every remote lines. Signed-off-by: Nicolas Pitre Signed-off-by: Shawn O. Pearce --- sideband.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/sideband.c b/sideband.c index 277fa3c10d..ab8a1e990d 100644 --- a/sideband.c +++ b/sideband.c @@ -17,7 +17,7 @@ int recv_sideband(const char *me, int in_stream, int out, int err) strcpy(buf, "remote:"); while (1) { int band, len; - len = packet_read_line(in_stream, buf+7, LARGE_PACKET_MAX); + len = packet_read_line(in_stream, buf+7, LARGE_PACKET_MAX); if (len == 0) break; if (len < 1) { @@ -35,7 +35,22 @@ int recv_sideband(const char *me, int in_stream, int out, int err) return SIDEBAND_REMOTE_ERROR; case 2: buf[7] = ' '; - safe_write(err, buf, 8+len); + len += 8; + while (1) { + int brk = 8; + while (brk < len) { + brk++; + if (buf[brk-1] == '\n' || + buf[brk-1] == '\r') + break; + } + safe_write(err, buf, brk); + if (brk < len) { + memmove(buf + 8, buf + brk, len - brk); + len = len - brk + 8; + } else + break; + } continue; case 1: safe_write(out, buf+8, len); From 2f8b89472cec19a530cb697c4ee20e0ddfd747f6 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 16 Oct 2007 21:55:47 -0400 Subject: [PATCH 0182/1490] pack-objects: no delta possible with only one object in the list ... so don't even try in that case, and save another useless line of progress display. Signed-off-by: Nicolas Pitre Signed-off-by: Shawn O. Pearce --- builtin-pack-objects.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index df69abd514..d729cb7237 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -1714,7 +1714,7 @@ static void prepare_pack(int window, int depth) delta_list[n++] = entry; } - if (nr_deltas) { + if (nr_deltas && n > 1) { unsigned nr_done = 0; if (progress) start_progress(&progress_state, "Deltifying objects", From 7ba502c47bda21d060844863991083f4c319d436 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 16 Oct 2007 21:55:48 -0400 Subject: [PATCH 0183/1490] pack-objects.c: fix some global variable abuse and memory leaks To keep things well layered, sha1close() now returns the file descriptor when it doesn't close the file. An ugly cast was added to the return of write_idx_file() to avoid a warning. A proper fix will come separately. Signed-off-by: Nicolas Pitre Signed-off-by: Shawn O. Pearce --- builtin-pack-objects.c | 29 +++++++++++++++-------------- csum-file.c | 23 ++++++++++++++--------- 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index d729cb7237..933c2526f8 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -65,8 +65,6 @@ static int no_reuse_delta, no_reuse_object, keep_unreachable; static int local; static int incremental; static int allow_ofs_delta; -static const char *pack_tmp_name, *idx_tmp_name; -static char tmpname[PATH_MAX]; static const char *base_name; static int progress = 1; static int window = 10; @@ -587,12 +585,6 @@ static off_t write_one(struct sha1file *f, return offset + size; } -static int open_object_dir_tmp(const char *path) -{ - snprintf(tmpname, sizeof(tmpname), "%s/%s", get_object_directory(), path); - return xmkstemp(tmpname); -} - /* forward declaration for write_pack_file */ static int adjust_perm(const char *path, mode_t mode); @@ -611,11 +603,16 @@ static void write_pack_file(void) do { unsigned char sha1[20]; + char *pack_tmp_name = NULL; if (pack_to_stdout) { f = sha1fd(1, ""); } else { - int fd = open_object_dir_tmp("tmp_pack_XXXXXX"); + char tmpname[PATH_MAX]; + int fd; + snprintf(tmpname, sizeof(tmpname), + "%s/tmp_pack_XXXXXX", get_object_directory()); + fd = xmkstemp(tmpname); pack_tmp_name = xstrdup(tmpname); f = sha1fd(fd, pack_tmp_name); } @@ -643,19 +640,21 @@ static void write_pack_file(void) if (pack_to_stdout || nr_written == nr_remaining) { sha1close(f, sha1, 1); } else { - sha1close(f, sha1, 0); - fixup_pack_header_footer(f->fd, sha1, pack_tmp_name, nr_written); - close(f->fd); + int fd = sha1close(f, NULL, 0); + fixup_pack_header_footer(fd, sha1, pack_tmp_name, nr_written); + close(fd); } if (!pack_to_stdout) { mode_t mode = umask(0); + char *idx_tmp_name, tmpname[PATH_MAX]; umask(mode); mode = 0444 & ~mode; - idx_tmp_name = write_idx_file(NULL, - (struct pack_idx_entry **) written_list, nr_written, sha1); + idx_tmp_name = (char *) write_idx_file(NULL, + (struct pack_idx_entry **) written_list, + nr_written, sha1); snprintf(tmpname, sizeof(tmpname), "%s-%s.pack", base_name, sha1_to_hex(sha1)); if (adjust_perm(pack_tmp_name, mode)) @@ -672,6 +671,8 @@ static void write_pack_file(void) if (rename(idx_tmp_name, tmpname)) die("unable to rename temporary index file: %s", strerror(errno)); + free(idx_tmp_name); + free(pack_tmp_name); puts(sha1_to_hex(sha1)); } diff --git a/csum-file.c b/csum-file.c index 9ab997120d..9929991dea 100644 --- a/csum-file.c +++ b/csum-file.c @@ -31,22 +31,27 @@ static void sha1flush(struct sha1file *f, unsigned int count) int sha1close(struct sha1file *f, unsigned char *result, int final) { + int fd; unsigned offset = f->offset; if (offset) { SHA1_Update(&f->ctx, f->buffer, offset); sha1flush(f, offset); f->offset = 0; } - if (!final) - return 0; /* only want to flush (no checksum write, no close) */ - SHA1_Final(f->buffer, &f->ctx); - if (result) - hashcpy(result, f->buffer); - sha1flush(f, 20); - if (close(f->fd)) - die("%s: sha1 file error on close (%s)", f->name, strerror(errno)); + if (final) { + /* write checksum and close fd */ + SHA1_Final(f->buffer, &f->ctx); + if (result) + hashcpy(result, f->buffer); + sha1flush(f, 20); + if (close(f->fd)) + die("%s: sha1 file error on close (%s)", + f->name, strerror(errno)); + fd = 0; + } else + fd = f->fd; free(f); - return 0; + return fd; } int sha1write(struct sha1file *f, void *buf, unsigned int count) From 4049b9cfc082affc6365539138f6f5c546bb5685 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 16 Oct 2007 21:55:49 -0400 Subject: [PATCH 0184/1490] fix const issues with some functions Two functions, namely write_idx_file() and open_pack_file(), currently return a const pointer. However that pointer is either a copy of the first argument, or set to a malloc'd buffer when that first argument is null. In the later case it is wrong to qualify that pointer as const since ownership of the buffer is transferred to the caller to dispose of, and obviously the free() function is not meant to be passed const pointers. Making the return pointer not const causes a warning when the first argument is returned since that argument is also marked const. The correct thing to do is therefore to remove the const qualifiers, avoiding the need for ugly casts only to silence some warnings. Signed-off-by: Nicolas Pitre Signed-off-by: Shawn O. Pearce --- builtin-pack-objects.c | 2 +- index-pack.c | 8 ++++---- pack-write.c | 3 ++- pack.h | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index 933c2526f8..15d3750616 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -652,7 +652,7 @@ static void write_pack_file(void) umask(mode); mode = 0444 & ~mode; - idx_tmp_name = (char *) write_idx_file(NULL, + idx_tmp_name = write_idx_file(NULL, (struct pack_idx_entry **) written_list, nr_written, sha1); snprintf(tmpname, sizeof(tmpname), "%s-%s.pack", diff --git a/index-pack.c b/index-pack.c index c784decd24..60173d5192 100644 --- a/index-pack.c +++ b/index-pack.c @@ -106,7 +106,7 @@ static void use(int bytes) consumed_bytes += bytes; } -static const char *open_pack_file(const char *pack_name) +static char *open_pack_file(char *pack_name) { if (from_stdin) { input_fd = 0; @@ -686,15 +686,15 @@ static void final(const char *final_pack_name, const char *curr_pack_name, int main(int argc, char **argv) { int i, fix_thin_pack = 0; - const char *curr_pack, *pack_name = NULL; - const char *curr_index, *index_name = NULL; + char *curr_pack, *pack_name = NULL; + char *curr_index, *index_name = NULL; const char *keep_name = NULL, *keep_msg = NULL; char *index_name_buf = NULL, *keep_name_buf = NULL; struct pack_idx_entry **idx_objects; unsigned char sha1[20]; for (i = 1; i < argc; i++) { - const char *arg = argv[i]; + char *arg = argv[i]; if (*arg == '-') { if (!strcmp(arg, "--stdin")) { diff --git a/pack-write.c b/pack-write.c index e59b197e5e..d1ed3abe21 100644 --- a/pack-write.c +++ b/pack-write.c @@ -17,7 +17,8 @@ static int sha1_compare(const void *_a, const void *_b) * the SHA1 hash of sorted object names. The objects array passed in * will be sorted by SHA1 on exit. */ -const char *write_idx_file(const char *index_name, struct pack_idx_entry **objects, int nr_objects, unsigned char *sha1) +char *write_idx_file(char *index_name, struct pack_idx_entry **objects, + int nr_objects, unsigned char *sha1) { struct sha1file *f; struct pack_idx_entry **sorted_by_sha, **list, **last; diff --git a/pack.h b/pack.h index f357c9f428..cab4aa8381 100644 --- a/pack.h +++ b/pack.h @@ -55,7 +55,7 @@ struct pack_idx_entry { off_t offset; }; -extern const char *write_idx_file(const char *index_name, struct pack_idx_entry **objects, int nr_objects, unsigned char *sha1); +extern char *write_idx_file(char *index_name, struct pack_idx_entry **objects, int nr_objects, unsigned char *sha1); extern int verify_pack(struct packed_git *, int); extern void fixup_pack_header_footer(int, unsigned char *, const char *, uint32_t); From c85228ed8f31eb739e19cf8abcff84fad44c1258 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 16 Oct 2007 21:55:50 -0400 Subject: [PATCH 0185/1490] fix for more minor memory leaks Now that some pointers have lost their const attribute, we can free their associated memory when done with them. This is more a correctness issue about the rule for freeing those pointers which isn't completely trivial more than the leak itself which didn't matter as the program is exiting anyway. Signed-off-by: Nicolas Pitre Signed-off-by: Shawn O. Pearce --- index-pack.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/index-pack.c b/index-pack.c index 60173d5192..2f149a40fd 100644 --- a/index-pack.c +++ b/index-pack.c @@ -815,6 +815,10 @@ int main(int argc, char **argv) free(objects); free(index_name_buf); free(keep_name_buf); + if (pack_name == NULL) + free(curr_pack); + if (index_name == NULL) + free(curr_index); return 0; } From a5bb31fb6323b53559b0d15ce2d02a7ba6d74bed Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Tue, 16 Oct 2007 12:55:34 -0400 Subject: [PATCH 0186/1490] git-gui: Paper bag fix the global config parsing git-config won't honor any options after --list. We must supply the --global option in front of --list if we really want to load the global configuration options. Signed-off-by: Shawn O. Pearce --- git-gui.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/git-gui.sh b/git-gui.sh index 9bc5626286..38c6e595d8 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -755,7 +755,10 @@ git-version proc _parse_config {arr_name args} { array unset arr set buf {} catch { - set fd_rc [eval [list git_read config --null --list] $args] + set fd_rc [eval \ + [list git_read config] \ + $args \ + [list --null --list]] fconfigure $fd_rc -translation binary set buf [read $fd_rc] close $fd_rc From 0166419a197cea0ceef3aed8c72023deb015ecf4 Mon Sep 17 00:00:00 2001 From: Sam Vilain Date: Wed, 17 Oct 2007 11:33:04 +1300 Subject: [PATCH 0187/1490] gitk: disable colours when calling git log If the user specifies 'diff.color = 1' in their configuration file, then gitk will not start. Disable colours when calling git log. Signed-off-by: Sam Vilain Signed-off-by: Shawn O. Pearce --- gitk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gitk b/gitk index 300fdceb35..999e3c2188 100755 --- a/gitk +++ b/gitk @@ -92,7 +92,7 @@ proc start_rev_list {view} { set order "--date-order" } if {[catch { - set fd [open [concat | git log -z --pretty=raw $order --parents \ + set fd [open [concat | git log --no-color -z --pretty=raw $order --parents \ --boundary $viewargs($view) "--" $viewfiles($view)] r] } err]} { error_popup "Error executing git rev-list: $err" From a2d6b872dbf4e65525c9ba55e820e2ea26011ce1 Mon Sep 17 00:00:00 2001 From: Robert Schiele Date: Thu, 18 Oct 2007 00:27:51 +0200 Subject: [PATCH 0188/1490] fixing output of non-fast-forward output of post-receive-email post-receive-email has one place where the variable fast_forward is not spelled correctly. At the same place the logic was reversed. The combination of both bugs made the script work correctly for fast-forward commits but not for non-fast-forward ones. This change fixes this to be correct in both cases. Signed-off-by: Robert Schiele Signed-off-by: Shawn O. Pearce --- contrib/hooks/post-receive-email | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/hooks/post-receive-email b/contrib/hooks/post-receive-email index cbbd02fadd..28a06c7f38 100644 --- a/contrib/hooks/post-receive-email +++ b/contrib/hooks/post-receive-email @@ -323,7 +323,7 @@ generate_update_branch_email() echo " via $rev ($revtype)" done - if [ -z "$fastforward" ]; then + if [ "$fast_forward" ]; then echo " from $oldrev ($oldrev_type)" else # 1. Existing revisions were removed. In this case newrev is a From 130faabe48fd988c1eb078ef467a44e124a00a40 Mon Sep 17 00:00:00 2001 From: "koreth@midwinter.com" Date: Wed, 17 Oct 2007 21:41:43 -0700 Subject: [PATCH 0189/1490] Add a message explaining that automatic GC is about to start Signed-off-by: Steven Grimm Signed-off-by: Shawn O. Pearce --- builtin-gc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/builtin-gc.c b/builtin-gc.c index 956c32d1af..f99b212ca4 100644 --- a/builtin-gc.c +++ b/builtin-gc.c @@ -205,6 +205,10 @@ int cmd_gc(int argc, const char **argv, const char *prefix) prune = 0; if (!need_to_gc()) return 0; + fprintf(stderr, "Packing your repository for optimum " + "performance. If you would rather run\n" + "\"git gc\" by hand, run \"git config gc.auto 0\" " + "to disable automatic cleanup.\n"); } else { /* * Use safer (for shared repos) "-A" option to From 93a56c2cf7c8b29ca4c5e0740fe1e487324ffc73 Mon Sep 17 00:00:00 2001 From: Gerrit Pape Date: Fri, 12 Oct 2007 11:40:57 +0000 Subject: [PATCH 0190/1490] git-config: print error message if the config file cannot be read Instead of simply exiting with 255, print an error message including the reason why a config file specified through --file cannot be opened or read. The problem was noticed by Joey Hess, reported through http://bugs.debian.org/445208 Signed-off-by: Shawn O. Pearce --- builtin-config.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/builtin-config.c b/builtin-config.c index d98b6c2c4c..e5e243f27c 100644 --- a/builtin-config.c +++ b/builtin-config.c @@ -175,7 +175,10 @@ int cmd_config(int argc, const char **argv, const char *prefix) else if (!strcmp(argv[1], "--list") || !strcmp(argv[1], "-l")) { if (argc != 2) usage(git_config_set_usage); - return git_config(show_all_config); + if (git_config(show_all_config) < 0 && file && errno) + die("unable to read config file %s: %s", file, + strerror(errno)); + return 0; } else if (!strcmp(argv[1], "--global")) { char *home = getenv("HOME"); From 8f353ee57a2f79697f8dea80ad3174998586bc75 Mon Sep 17 00:00:00 2001 From: Marius Storm-Olsen Date: Wed, 17 Oct 2007 12:57:47 +0200 Subject: [PATCH 0191/1490] Teach core.autocrlf to 'git blame' Pass the fake commit through convert_to_git, so that the file is adjusted for local line-ending convention. Signed-off-by: Marius Storm-Olsen Signed-off-by: Shawn O. Pearce --- builtin-blame.c | 1 + 1 file changed, 1 insertion(+) diff --git a/builtin-blame.c b/builtin-blame.c index e3112a2d5b..8432b823e6 100644 --- a/builtin-blame.c +++ b/builtin-blame.c @@ -2059,6 +2059,7 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con if (strbuf_read(&buf, 0, 0) < 0) die("read error %s from stdin", strerror(errno)); } + convert_to_git(path, buf.buf, buf.len, &buf); origin->file.ptr = buf.buf; origin->file.size = buf.len; pretend_sha1_file(buf.buf, buf.len, OBJ_BLOB, origin->blob_sha1); From cd8ae20195ae09c06d0854f1ebf92d1f1164c927 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 18 Oct 2007 02:31:30 -0400 Subject: [PATCH 0192/1490] git-blame shouldn't crash if run in an unmerged tree MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we are in the middle of resolving a merge conflict there may be one or more files whose entries in the index represent an unmerged state (index entries in the higher-order stages). Attempting to run git-blame on any file in such a working directory resulted in "fatal: internal error: ce_mode is 0" as we use the magic marker for an unmerged entry is 0 (set up by things like diff-lib.c's do_diff_cache() and builtin-read-tree.c's read_tree_unmerged()) and the ce_match_stat_basic() function gets upset about this. I'm not entirely sure that the whole "ce_mode = 0" case is a good idea to begin with, and maybe the right thing to do is to remove that horrid freakish special case, but removing the internal error seems to be the simplest fix for now. Linus [sp: Thanks to Björn Steinbrink for the test case] Signed-off-by: Shawn O. Pearce --- read-cache.c | 2 ++ t/t8004-blame.sh | 73 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100755 t/t8004-blame.sh diff --git a/read-cache.c b/read-cache.c index 536f4d0875..928e8fa1ae 100644 --- a/read-cache.c +++ b/read-cache.c @@ -149,6 +149,8 @@ static int ce_match_stat_basic(struct cache_entry *ce, struct stat *st) else if (ce_compare_gitlink(ce)) changed |= DATA_CHANGED; return changed; + case 0: /* Special case: unmerged file in index */ + return MODE_CHANGED | DATA_CHANGED | TYPE_CHANGED; default: die("internal error: ce_mode is %o", ntohl(ce->ce_mode)); } diff --git a/t/t8004-blame.sh b/t/t8004-blame.sh new file mode 100755 index 0000000000..ba19ac127e --- /dev/null +++ b/t/t8004-blame.sh @@ -0,0 +1,73 @@ +#!/bin/sh + +# Based on a test case submitted by Björn Steinbrink. + +test_description='git blame on conflicted files' +. ./test-lib.sh + +test_expect_success 'setup first case' ' + # Create the old file + echo "Old line" > file1 && + git add file1 && + git commit --author "Old Line " -m file1.a && + + # Branch + git checkout -b foo && + + # Do an ugly move and change + git rm file1 && + echo "New line ..." > file2 && + echo "... and more" >> file2 && + git add file2 && + git commit --author "U Gly " -m ugly && + + # Back to master and change something + git checkout master && + echo " + +bla" >> file1 && + git commit --author "Old Line " -a -m file1.b && + + # Back to foo and merge master + git checkout foo && + if git merge master; then + echo needed conflict here + exit 1 + else + echo merge failed - resolving automatically + fi && + echo "New line ... +... and more + +bla +Even more" > file2 && + git rm file1 && + git commit --author "M Result " -a -m merged && + + # Back to master and change file1 again + git checkout master && + sed s/bla/foo/ X && + rm file1 && + mv X file1 && + git commit --author "No Bla " -a -m replace && + + # Try to merge into foo again + git checkout foo && + if git merge master; then + echo needed conflict here + exit 1 + else + echo merge failed - test is setup + fi +' + +test_expect_success \ + 'blame runs on unconflicted file while other file has conflicts' ' + git blame file2 +' + +test_expect_success 'blame runs on conflicted file in stages 1,3' ' + git blame file1 +' + +test_done From 2a4b5d5a0701a5f9a953883e21a6e3dc71cd5cc7 Mon Sep 17 00:00:00 2001 From: Brian Gernhardt Date: Wed, 17 Oct 2007 10:05:47 -0400 Subject: [PATCH 0193/1490] cvsserver: Use exit 1 instead of die when req_Root fails. This was causing test failures because die was exiting 255. Signed-off-by: Brian Gernhardt Signed-off-by: Shawn O. Pearce --- git-cvsserver.perl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/git-cvsserver.perl b/git-cvsserver.perl index 13dbd27a80..0d55fec04f 100755 --- a/git-cvsserver.perl +++ b/git-cvsserver.perl @@ -145,8 +145,10 @@ } my $request = $1; $line = ; chomp $line; - req_Root('root', $line) # reuse Root - or die "E Invalid root $line \n"; + unless (req_Root('root', $line)) { # reuse Root + print "E Invalid root $line \n"; + exit 1; + } $line = ; chomp $line; unless ($line eq 'anonymous') { print "E Only anonymous user allowed via pserver\n"; From 1aa3d01f870a68dc46a872c83f9cd051f172f9b3 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Thu, 18 Oct 2007 03:11:03 -0400 Subject: [PATCH 0194/1490] Yet more 1.5.3.5 fixes mentioned in release notes Signed-off-by: Shawn O. Pearce --- Documentation/RelNotes-1.5.3.5.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Documentation/RelNotes-1.5.3.5.txt b/Documentation/RelNotes-1.5.3.5.txt index de38a84ad6..78df418257 100644 --- a/Documentation/RelNotes-1.5.3.5.txt +++ b/Documentation/RelNotes-1.5.3.5.txt @@ -10,9 +10,14 @@ Fixes since v1.5.3.4 * "git-config --file" failed if the argument used a relative path as it changed directories before opening the file. + * "git-config --file" now displays a proper error message if it + cannot read the file specified on the command line. + * "git-config", "git-diff", "git-apply" failed if run from a subdirectory with relative GIT_DIR and GIT_WORK_TREE set. + * "git-blame" crashed if run during a merge conflict. + * "git-add -i" did not handle single line hunks correctly. * "git-rebase -i" failed if external diff drivers were used for one @@ -33,6 +38,9 @@ Fixes since v1.5.3.4 * "git-instaweb" no longer fails on Mac OS X. + * post-receive-email example hook fixed was fixed for + non-fast-forward updates. + * Documentation updates for supported (but previously undocumented) options of "git-archive" and "git-reflog". From 334f4831e5a779d42e521b770a26eae1ecb27e86 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Thu, 18 Oct 2007 02:19:15 -0400 Subject: [PATCH 0195/1490] send-pack: don't update tracking refs on error Previously, we updated the tracking refs (which match refs we are pushing) while generating the list of refs to send. However, at that point we don't know whether the refs were accepted. Instead, we now wait until we get a response code from the server. If an error was indicated, we don't update any local tracking refs. Technically some refs could have been updated on the remote, but since the local ref update is just an optimization to avoid an extra fetch, we are better off erring on the side of correctness. The user-visible message is now generated much later in the program, and has been tweaked to make more sense. Signed-off-by: Jeff King Signed-off-by: Shawn O. Pearce --- send-pack.c | 50 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/send-pack.c b/send-pack.c index c1807f0794..1a7397f3a6 100644 --- a/send-pack.c +++ b/send-pack.c @@ -178,6 +178,35 @@ static int receive_status(int in) return ret; } +static void update_tracking_ref(struct remote *remote, struct ref *ref) +{ + struct refspec rs; + int will_delete_ref; + + rs.src = ref->name; + rs.dst = NULL; + + if (!ref->peer_ref) + return; + + will_delete_ref = is_null_sha1(ref->peer_ref->new_sha1); + + if (!will_delete_ref && + !hashcmp(ref->old_sha1, ref->peer_ref->new_sha1)) + return; + + if (!remote_find_tracking(remote, &rs)) { + fprintf(stderr, "updating local tracking ref '%s'\n", rs.dst); + if (is_null_sha1(ref->peer_ref->new_sha1)) { + if (delete_ref(rs.dst, NULL)) + error("Failed to delete"); + } else + update_ref("update by push", rs.dst, + ref->new_sha1, NULL, 0, 0); + free(rs.dst); + } +} + static int send_pack(int in, int out, struct remote *remote, int nr_refspec, char **refspec) { struct ref *ref; @@ -306,22 +335,6 @@ static int send_pack(int in, int out, struct remote *remote, int nr_refspec, cha fprintf(stderr, "\n from %s\n to %s\n", old_hex, new_hex); } - if (remote && !dry_run) { - struct refspec rs; - rs.src = ref->name; - rs.dst = NULL; - if (!remote_find_tracking(remote, &rs)) { - fprintf(stderr, " Also local %s\n", rs.dst); - if (will_delete_ref) { - if (delete_ref(rs.dst, NULL)) { - error("Failed to delete"); - } - } else - update_ref("update by push", rs.dst, - ref->new_sha1, NULL, 0, 0); - free(rs.dst); - } - } } packet_flush(out); @@ -334,6 +347,11 @@ static int send_pack(int in, int out, struct remote *remote, int nr_refspec, cha ret = -4; } + if (!dry_run && remote && ret == 0) { + for (ref = remote_refs; ref; ref = ref->next) + update_tracking_ref(remote, ref); + } + if (!new_refs && ret == 0) fprintf(stderr, "Everything up-to-date\n"); return ret; From 09fba7a59d38d1cafaf33eadaf1d409c4113b30c Mon Sep 17 00:00:00 2001 From: Jeff King Date: Thu, 18 Oct 2007 02:17:46 -0400 Subject: [PATCH 0196/1490] t5516: test update of local refs on push The first test (updating local refs) should succeed without the prior commit, but the second one (not updating on error) used to fail before the prior commit was written. Signed-off-by: Jeff King Signed-off-by: Shawn O. Pearce --- t/t5516-fetch-push.sh | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh index 4fbd5b1f47..86f9b5346a 100755 --- a/t/t5516-fetch-push.sh +++ b/t/t5516-fetch-push.sh @@ -254,4 +254,32 @@ test_expect_success 'push with dry-run' ' check_push_result $old_commit heads/master ' +test_expect_success 'push updates local refs' ' + + rm -rf parent child && + mkdir parent && cd parent && git init && + echo one >foo && git add foo && git commit -m one && + cd .. && + git clone parent child && cd child && + echo two >foo && git commit -a -m two && + git push && + test $(git rev-parse master) = $(git rev-parse remotes/origin/master) + +' + +test_expect_success 'push does not update local refs on failure' ' + + rm -rf parent child && + mkdir parent && cd parent && git init && + echo one >foo && git add foo && git commit -m one && + echo exit 1 >.git/hooks/pre-receive && + chmod +x .git/hooks/pre-receive && + cd .. && + git clone parent child && cd child && + echo two >foo && git commit -a -m two || exit 1 + git push && exit 1 + test $(git rev-parse master) != $(git rev-parse remotes/origin/master) + +' + test_done From 889a50e909dba5f4416049afc5eeae601fe133bc Mon Sep 17 00:00:00 2001 From: Jonathan del Strother Date: Wed, 17 Oct 2007 10:31:35 +0100 Subject: [PATCH 0197/1490] Fixing path quoting in git-rebase git-rebase used to fail when run from a path containing a space. Signed-off-by: Jonathan del Strother Signed-off-by: Shawn O. Pearce --- git-rebase.sh | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/git-rebase.sh b/git-rebase.sh index 1583402a06..224cca98ee 100755 --- a/git-rebase.sh +++ b/git-rebase.sh @@ -59,7 +59,7 @@ continue_merge () { die "$RESOLVEMSG" fi - cmt=`cat $dotest/current` + cmt=`cat "$dotest/current"` if ! git diff-index --quiet HEAD then if ! git-commit -C "$cmt" @@ -84,14 +84,14 @@ continue_merge () { } call_merge () { - cmt="$(cat $dotest/cmt.$1)" + cmt="$(cat "$dotest/cmt.$1")" echo "$cmt" > "$dotest/current" hd=$(git rev-parse --verify HEAD) cmt_name=$(git symbolic-ref HEAD) - msgnum=$(cat $dotest/msgnum) - end=$(cat $dotest/end) + msgnum=$(cat "$dotest/msgnum") + end=$(cat "$dotest/end") eval GITHEAD_$cmt='"${cmt_name##refs/heads/}~$(($end - $msgnum))"' - eval GITHEAD_$hd='"$(cat $dotest/onto_name)"' + eval GITHEAD_$hd='$(cat "$dotest/onto_name")' export GITHEAD_$cmt GITHEAD_$hd git-merge-$strategy "$cmt^" -- "$hd" "$cmt" rv=$? @@ -140,10 +140,10 @@ do } if test -d "$dotest" then - prev_head="`cat $dotest/prev_head`" - end="`cat $dotest/end`" - msgnum="`cat $dotest/msgnum`" - onto="`cat $dotest/onto`" + prev_head=$(cat "$dotest/prev_head") + end=$(cat "$dotest/end") + msgnum=$(cat "$dotest/msgnum") + onto=$(cat "$dotest/onto") continue_merge while test "$msgnum" -le "$end" do @@ -160,11 +160,11 @@ do if test -d "$dotest" then git rerere clear - prev_head="`cat $dotest/prev_head`" - end="`cat $dotest/end`" - msgnum="`cat $dotest/msgnum`" + prev_head=$(cat "$dotest/prev_head") + end=$(cat "$dotest/end") + msgnum=$(cat "$dotest/msgnum") msgnum=$(($msgnum + 1)) - onto="`cat $dotest/onto`" + onto=$(cat "$dotest/onto") while test "$msgnum" -le "$end" do call_merge "$msgnum" From e3fa2c761fdc490494e8e0855bcee4d7e58ada6a Mon Sep 17 00:00:00 2001 From: Steffen Prohaska Date: Wed, 17 Oct 2007 19:16:11 +0200 Subject: [PATCH 0198/1490] mergetool: use path to mergetool in config var mergetool..path This commit adds a mechanism to provide absolute paths to the external programs called by 'git mergetool'. A path can be specified in the configuation variable mergetool..path. The configuration variable is similar to how we name branches and remotes. It is extensible if we need to specify more details about a tool. The mechanism is especially useful on Windows, where external programs are unlikely to be in PATH. [sp: Fixed a few minor issues prior to applying] Signed-off-by: Steffen Prohaska Signed-off-by: Shawn O. Pearce --- Documentation/git-mergetool.txt | 6 ++ git-mergetool.sh | 97 ++++++++++++++++++--------------- 2 files changed, 60 insertions(+), 43 deletions(-) diff --git a/Documentation/git-mergetool.txt b/Documentation/git-mergetool.txt index 6c32c6d18e..78b2f433b0 100644 --- a/Documentation/git-mergetool.txt +++ b/Documentation/git-mergetool.txt @@ -31,6 +31,12 @@ If a merge resolution program is not specified, 'git mergetool' will use the configuration variable merge.tool. If the configuration variable merge.tool is not set, 'git mergetool' will pick a suitable default. ++ +You can explicitly provide a full path to the tool by setting the +configuration variable mergetool..path. For example, you +can configure the absolute path to kdiff3 by setting +mergetool.kdiff3.path. Otherwise, 'git mergetool' assumes the tool +is available in PATH. Author ------ diff --git a/git-mergetool.sh b/git-mergetool.sh index 9f4f3134b6..4f89cbe8e6 100755 --- a/git-mergetool.sh +++ b/git-mergetool.sh @@ -192,10 +192,10 @@ merge_file () { case "$merge_tool" in kdiff3) if base_present ; then - (kdiff3 --auto --L1 "$path (Base)" --L2 "$path (Local)" --L3 "$path (Remote)" \ + ("$merge_tool_path" --auto --L1 "$path (Base)" --L2 "$path (Local)" --L3 "$path (Remote)" \ -o "$path" -- "$BASE" "$LOCAL" "$REMOTE" > /dev/null 2>&1) else - (kdiff3 --auto --L1 "$path (Local)" --L2 "$path (Remote)" \ + ("$merge_tool_path" --auto --L1 "$path (Local)" --L2 "$path (Remote)" \ -o "$path" -- "$LOCAL" "$REMOTE" > /dev/null 2>&1) fi status=$? @@ -203,35 +203,35 @@ merge_file () { ;; tkdiff) if base_present ; then - tkdiff -a "$BASE" -o "$path" -- "$LOCAL" "$REMOTE" + "$merge_tool_path" -a "$BASE" -o "$path" -- "$LOCAL" "$REMOTE" else - tkdiff -o "$path" -- "$LOCAL" "$REMOTE" + "$merge_tool_path" -o "$path" -- "$LOCAL" "$REMOTE" fi status=$? save_backup ;; meld|vimdiff) touch "$BACKUP" - $merge_tool -- "$LOCAL" "$path" "$REMOTE" + "$merge_tool_path" -- "$LOCAL" "$path" "$REMOTE" check_unchanged save_backup ;; gvimdiff) touch "$BACKUP" - gvimdiff -f -- "$LOCAL" "$path" "$REMOTE" + "$merge_tool_path" -f -- "$LOCAL" "$path" "$REMOTE" check_unchanged save_backup ;; xxdiff) touch "$BACKUP" if base_present ; then - xxdiff -X --show-merged-pane \ + "$merge_tool_path" -X --show-merged-pane \ -R 'Accel.SaveAsMerged: "Ctrl-S"' \ -R 'Accel.Search: "Ctrl+F"' \ -R 'Accel.SearchForward: "Ctrl-G"' \ --merged-file "$path" -- "$LOCAL" "$BASE" "$REMOTE" else - xxdiff -X --show-merged-pane \ + "$merge_tool_path" -X --show-merged-pane \ -R 'Accel.SaveAsMerged: "Ctrl-S"' \ -R 'Accel.Search: "Ctrl+F"' \ -R 'Accel.SearchForward: "Ctrl-G"' \ @@ -243,18 +243,18 @@ merge_file () { opendiff) touch "$BACKUP" if base_present; then - opendiff "$LOCAL" "$REMOTE" -ancestor "$BASE" -merge "$path" | cat + "$merge_tool_path" "$LOCAL" "$REMOTE" -ancestor "$BASE" -merge "$path" | cat else - opendiff "$LOCAL" "$REMOTE" -merge "$path" | cat + "$merge_tool_path" "$LOCAL" "$REMOTE" -merge "$path" | cat fi check_unchanged save_backup ;; emerge) if base_present ; then - emacs -f emerge-files-with-ancestor-command "$LOCAL" "$REMOTE" "$BASE" "$(basename "$path")" + "$merge_tool_path" -f emerge-files-with-ancestor-command "$LOCAL" "$REMOTE" "$BASE" "$(basename "$path")" else - emacs -f emerge-files-command "$LOCAL" "$REMOTE" "$(basename "$path")" + "$merge_tool_path" -f emerge-files-command "$LOCAL" "$REMOTE" "$(basename "$path")" fi status=$? save_backup @@ -297,17 +297,38 @@ do shift done +valid_tool() { + case "$1" in + kdiff3 | tkdiff | xxdiff | meld | opendiff | emerge | vimdiff | gvimdiff) + ;; # happy + *) + return 1 + ;; + esac +} + +init_merge_tool_path() { + merge_tool_path=`git config mergetool.$1.path` + if test -z "$merge_tool_path" ; then + case "$1" in + emerge) + merge_tool_path=emacs + ;; + *) + merge_tool_path=$1 + ;; + esac + fi +} + + if test -z "$merge_tool"; then merge_tool=`git config merge.tool` - case "$merge_tool" in - kdiff3 | tkdiff | xxdiff | meld | opendiff | emerge | vimdiff | gvimdiff | "") - ;; # happy - *) + if ! valid_tool "$merge_tool"; then echo >&2 "git config option merge.tool set to unknown tool: $merge_tool" echo >&2 "Resetting to default..." unset merge_tool - ;; - esac + fi fi if test -z "$merge_tool" ; then @@ -329,40 +350,30 @@ if test -z "$merge_tool" ; then merge_tool_candidates="$merge_tool_candidates opendiff emerge vimdiff" echo "merge tool candidates: $merge_tool_candidates" for i in $merge_tool_candidates; do - if test $i = emerge ; then - cmd=emacs - else - cmd=$i - fi - if type $cmd > /dev/null 2>&1; then + init_merge_tool_path $i + if type "$merge_tool_path" > /dev/null 2>&1; then merge_tool=$i break fi done if test -z "$merge_tool" ; then - echo "No available merge resolution programs available." + echo "No known merge resolution program available." exit 1 fi +else + if ! valid_tool "$merge_tool"; then + echo >&2 "Unknown merge_tool $merge_tool" + exit 1 + fi + + init_merge_tool_path "$merge_tool" + + if ! type "$merge_tool_path" > /dev/null 2>&1; then + echo "The merge tool $merge_tool is not available as '$merge_tool_path'" + exit 1 + fi fi -case "$merge_tool" in - kdiff3|tkdiff|meld|xxdiff|vimdiff|gvimdiff|opendiff) - if ! type "$merge_tool" > /dev/null 2>&1; then - echo "The merge tool $merge_tool is not available" - exit 1 - fi - ;; - emerge) - if ! type "emacs" > /dev/null 2>&1; then - echo "Emacs is not available" - exit 1 - fi - ;; - *) - echo "Unknown merge tool: $merge_tool" - exit 1 - ;; -esac if test $# -eq 0 ; then files=`git ls-files -u | sed -e 's/^[^ ]* //' | sort -u` From ca8e6b7a55bfeccbd08182205102d44874f787b6 Mon Sep 17 00:00:00 2001 From: Steffen Prohaska Date: Wed, 17 Oct 2007 19:16:12 +0200 Subject: [PATCH 0199/1490] mergetool: add support for ECMerge Add support to mergetool for ECMerge available from http://www.elliecomputing.com/Products/merge_overview.asp Signed-off-by: Steffen Prohaska Signed-off-by: Shawn O. Pearce --- Documentation/git-mergetool.txt | 2 +- git-mergetool.sh | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Documentation/git-mergetool.txt b/Documentation/git-mergetool.txt index 78b2f433b0..a26c260162 100644 --- a/Documentation/git-mergetool.txt +++ b/Documentation/git-mergetool.txt @@ -25,7 +25,7 @@ OPTIONS -t or --tool=:: Use the merge resolution program specified by . Valid merge tools are: - kdiff3, tkdiff, meld, xxdiff, emerge, vimdiff, gvimdiff, and opendiff + kdiff3, tkdiff, meld, xxdiff, emerge, vimdiff, gvimdiff, ecmerge, and opendiff + If a merge resolution program is not specified, 'git mergetool' will use the configuration variable merge.tool. If the diff --git a/git-mergetool.sh b/git-mergetool.sh index 4f89cbe8e6..94511f9d1a 100755 --- a/git-mergetool.sh +++ b/git-mergetool.sh @@ -250,6 +250,16 @@ merge_file () { check_unchanged save_backup ;; + ecmerge) + touch "$BACKUP" + if base_present; then + "$merge_tool_path" "$BASE" "$LOCAL" "$REMOTE" --mode=merge3 --to="$path" + else + "$merge_tool_path" "$LOCAL" "$REMOTE" --mode=merge2 --to="$path" + fi + check_unchanged + save_backup + ;; emerge) if base_present ; then "$merge_tool_path" -f emerge-files-with-ancestor-command "$LOCAL" "$REMOTE" "$BASE" "$(basename "$path")" @@ -299,7 +309,7 @@ done valid_tool() { case "$1" in - kdiff3 | tkdiff | xxdiff | meld | opendiff | emerge | vimdiff | gvimdiff) + kdiff3 | tkdiff | xxdiff | meld | opendiff | emerge | vimdiff | gvimdiff | ecmerge) ;; # happy *) return 1 From d279fc1a76bf9bfeedded1a1c8ebcfc8779f5b10 Mon Sep 17 00:00:00 2001 From: Steffen Prohaska Date: Thu, 18 Oct 2007 12:25:34 +0200 Subject: [PATCH 0200/1490] mergetool: avoid misleading message "Resetting to default..." If no mergetool is configured in the configuration variable merge.tool the resetting message should not be printed. This is fixed. The message is only printed if a tool is configured but the entry in merge.tool is invalid. Signed-off-by: Steffen Prohaska Signed-off-by: Shawn O. Pearce --- git-mergetool.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git-mergetool.sh b/git-mergetool.sh index 94511f9d1a..a68b40386b 100755 --- a/git-mergetool.sh +++ b/git-mergetool.sh @@ -334,7 +334,7 @@ init_merge_tool_path() { if test -z "$merge_tool"; then merge_tool=`git config merge.tool` - if ! valid_tool "$merge_tool"; then + if test -n "$merge_tool" && ! valid_tool "$merge_tool"; then echo >&2 "git config option merge.tool set to unknown tool: $merge_tool" echo >&2 "Resetting to default..." unset merge_tool From 42a32174b600f139b489341b1281fb1bfa14c252 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 18 Oct 2007 16:24:47 -0700 Subject: [PATCH 0201/1490] Avoid scary errors about tagged trees/blobs during git-fetch Ok, what is going on is: - append_fetch_head() looks up the SHA1 for all heads (including tags): if (get_sha1(head, sha1)) return error("Not a valid object name: %s", head); - it then wants to check if it's a candidate for merging (because fetching also does the whole "list which heads to merge" in case it is going to be part of a "pull"): commit = lookup_commit_reference(sha1); if (!commit) not_for_merge = 1; - and that "lookup_commit_reference()" is just very vocal about the case where it fails. It really shouldn't be, and it shouldn't affect the actual end result, but that basically explains why you get that scary warning. In short, the warning is just bogus, and should be harmless, but I agree that it's ugly. I think the appended patch should fix it. Signed-off-by: Linus Torvalds Signed-off-by: Shawn O. Pearce --- builtin-fetch--tool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin-fetch--tool.c b/builtin-fetch--tool.c index e2f8ede9ae..db133348a8 100644 --- a/builtin-fetch--tool.c +++ b/builtin-fetch--tool.c @@ -148,7 +148,7 @@ static int append_fetch_head(FILE *fp, if (get_sha1(head, sha1)) return error("Not a valid object name: %s", head); - commit = lookup_commit_reference(sha1); + commit = lookup_commit_reference_gently(sha1, 1); if (!commit) not_for_merge = 1; From fd0b9594d0c2bb50469bfc1481ea4395b7a76548 Mon Sep 17 00:00:00 2001 From: Alex Bennee Date: Thu, 18 Oct 2007 17:15:44 +0100 Subject: [PATCH 0202/1490] Ensure we add directories in the correct order CVS gets understandably upset if you try and add a subdirectory before it's parent directory. This patch fixes that. Signed-off-by: Shawn O. Pearce --- git-cvsexportcommit.perl | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/git-cvsexportcommit.perl b/git-cvsexportcommit.perl index a33fa8d4c8..7b19a33ad1 100755 --- a/git-cvsexportcommit.perl +++ b/git-cvsexportcommit.perl @@ -224,6 +224,17 @@ print "Patch applied successfully. Adding new files and directories to CVS\n"; my $dirtypatch = 0; + +# +# We have to add the directories in order otherwise we will have +# problems when we try and add the sub-directory of a directory we +# have not added yet. +# +# Luckily this is easy to deal with by sorting the directories and +# dealing with the shortest ones first. +# +@dirs = sort { length $a <=> length $b} @dirs; + foreach my $d (@dirs) { if (system(@cvs,'add',$d)) { $dirtypatch = 1; From 415e7b877c54440bf92137a7021416efdf0a29b5 Mon Sep 17 00:00:00 2001 From: Patrick Welche Date: Thu, 18 Oct 2007 18:17:39 +0100 Subject: [PATCH 0203/1490] Define NI_MAXSERV if not defined by operating system I found I needed NI_MAXSERV as it is defined in netdb.h, which is not included by daemon.c. Rather than including the whole header we can define a reasonable fallback value. Signed-off-by: Shawn O. Pearce --- daemon.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/daemon.c b/daemon.c index 9cf22fef41..660e1552d4 100644 --- a/daemon.c +++ b/daemon.c @@ -9,6 +9,10 @@ #define HOST_NAME_MAX 256 #endif +#ifndef NI_MAXSERV +#define NI_MAXSERV 32 +#endif + static int log_syslog; static int verbose; static int reuseaddr; From d7b0a09316fe8dcb62ad247dbbb45c3c777667ad Mon Sep 17 00:00:00 2001 From: Steffen Prohaska Date: Thu, 18 Oct 2007 22:02:35 +0200 Subject: [PATCH 0204/1490] attr: fix segfault in gitattributes parsing code git may segfault if gitattributes contains an invalid entry. A test is added to t0020 that triggers the segfault. The parsing code is fixed to avoid the crash. Signed-off-by: Steffen Prohaska Signed-off-by: Shawn O. Pearce --- attr.c | 5 ++++- t/t0020-crlf.sh | 7 +++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/attr.c b/attr.c index 129399310a..6e82507be7 100644 --- a/attr.c +++ b/attr.c @@ -214,8 +214,11 @@ static struct match_attr *parse_attr_line(const char *line, const char *src, num_attr = 0; cp = name + namelen; cp = cp + strspn(cp, blank); - while (*cp) + while (*cp) { cp = parse_attr(src, lineno, cp, &num_attr, res); + if (!cp) + return NULL; + } if (pass) break; res = xcalloc(1, diff --git a/t/t0020-crlf.sh b/t/t0020-crlf.sh index 0807d9f01a..62bc4bb077 100755 --- a/t/t0020-crlf.sh +++ b/t/t0020-crlf.sh @@ -371,4 +371,11 @@ test_expect_success 'in-tree .gitattributes (4)' ' } ' +test_expect_success 'invalid .gitattributes (must not crash)' ' + + echo "three +crlf" >>.gitattributes && + git diff + +' + test_done From 89d750bf6fa025edeb31ad258cdd09a27a5c02fa Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Thu, 18 Oct 2007 21:28:43 -0400 Subject: [PATCH 0205/1490] Avoid invoking diff drivers during git-stash git-stash needs to restrict itself to plumbing when running automated diffs as part of its operation as the user may have configured a custom diff driver that opens an interactive UI for certain/all files. Doing that during scripted actions is very unfriendly to the end-user and may cause git-stash to fail to work. Reported by Johannes Sixt Acked-by: Johannes Schindelin Signed-off-by: Shawn O. Pearce --- git-stash.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/git-stash.sh b/git-stash.sh index 7ba61625ba..def3163ebb 100755 --- a/git-stash.sh +++ b/git-stash.sh @@ -110,7 +110,7 @@ show_stash () { w_commit=$(git rev-parse --verify "$s") && b_commit=$(git rev-parse --verify "$s^") && - git diff $flags $b_commit $w_commit + git diff-tree $flags $b_commit $w_commit } apply_stash () { @@ -139,7 +139,7 @@ apply_stash () { unstashed_index_tree= if test -n "$unstash_index" && test "$b_tree" != "$i_tree" then - git diff --binary $s^2^..$s^2 | git apply --cached + git diff-tree --binary $s^2^..$s^2 | git apply --cached test $? -ne 0 && die 'Conflicts in index. Try without --index.' unstashed_index_tree=$(git-write-tree) || @@ -162,7 +162,7 @@ apply_stash () { git read-tree "$unstashed_index_tree" else a="$TMP-added" && - git diff --cached --name-only --diff-filter=A $c_tree >"$a" && + git diff-index --cached --name-only --diff-filter=A $c_tree >"$a" && git read-tree --reset $c_tree && git update-index --add --stdin <"$a" || die "Cannot unstage modified files" From dd8b883ab9d9a18c5ec8157765244316b2490618 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Thu, 18 Oct 2007 21:12:11 -0400 Subject: [PATCH 0206/1490] git-gc: improve wording of --auto notification The previous message had too much of a "boy, you should really turn off this annoying gc" flair to it. Instead, let's make sure the user understands what is happening, that they can run it themselves, and where to find more info. Suggested by Brian Gernhardt. Signed-off-by: Jeff King Signed-off-by: Shawn O. Pearce --- builtin-gc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/builtin-gc.c b/builtin-gc.c index f99b212ca4..3a2ca4f901 100644 --- a/builtin-gc.c +++ b/builtin-gc.c @@ -206,9 +206,9 @@ int cmd_gc(int argc, const char **argv, const char *prefix) if (!need_to_gc()) return 0; fprintf(stderr, "Packing your repository for optimum " - "performance. If you would rather run\n" - "\"git gc\" by hand, run \"git config gc.auto 0\" " - "to disable automatic cleanup.\n"); + "performance. You may also\n" + "run \"git gc\" manually. See " + "\"git help gc\" for more information.\n"); } else { /* * Use safer (for shared repos) "-A" option to From 08fbb136f7440eac96f4e4396316aff36526f299 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Thu, 18 Oct 2007 22:01:11 -0400 Subject: [PATCH 0207/1490] Documentation/git-gc: explain --auto in description Now that git-gc --auto tells the user to look at the man page, it makes sense to mention the auto behavior near the top (since this is likely to be most users' first exposure to git-gc). Signed-off-by: Jeff King Signed-off-by: Shawn O. Pearce --- Documentation/git-gc.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/git-gc.txt b/Documentation/git-gc.txt index b9d5660eac..83843a549c 100644 --- a/Documentation/git-gc.txt +++ b/Documentation/git-gc.txt @@ -19,7 +19,8 @@ created from prior invocations of gitlink:git-add[1]. Users are encouraged to run this task on a regular basis within each repository to maintain good disk space utilization and good -operating performance. +operating performance. Some git commands may automatically run +`git-gc`; see the `--auto` flag below for details. OPTIONS ------- From d7e56dbc4f60f6bd238e8612783541d89f006fb7 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Thu, 18 Oct 2007 22:05:10 -0400 Subject: [PATCH 0208/1490] Documentation/git-gc: improve description of --auto This patch tries to make the description of --auto a little more clear for new users, especially those referred by the "git-gc --auto" notification message. It also cleans up some grammatical errors and typos in the original description, as well as rewording for clarity. Signed-off-by: Jeff King Signed-off-by: Shawn O. Pearce --- Documentation/git-gc.txt | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/Documentation/git-gc.txt b/Documentation/git-gc.txt index 83843a549c..872056ea04 100644 --- a/Documentation/git-gc.txt +++ b/Documentation/git-gc.txt @@ -45,18 +45,23 @@ OPTIONS few hundred changesets or so. --auto:: - With this option, `git gc` checks if there are too many - loose objects in the repository and runs - gitlink:git-repack[1] with `-d -l` option to pack them. - The threshold for loose objects is set with `gc.auto` configuration - variable, and can be disabled by setting it to 0. Some - Porcelain commands use this after they perform operation - that could create many loose objects automatically. - Additionally, when there are too many packs are present, - they are consolidated into one larger pack by running - the `git-repack` command with `-A` option. The - threshold for number of packs is set with - `gc.autopacklimit` configuration variable. + With this option, `git gc` checks whether any housekeeping is + required; if not, it exits without performing any work. + Some git commands run `git gc --auto` after performing + operations that could create many loose objects. ++ +Housekeeping is required if there are too many loose objects or +too many packs in the repository. If the number of loose objects +exceeds the value of the `gc.auto` configuration variable, then +all loose objects are combined into a single pack using +`git-repack -d -l`. Setting the value of `gc.auto` to 0 +disables automatic packing of loose objects. ++ +If the number of packs exceeds the value of `gc.autopacklimit`, +then existing packs (except those marked with a `.keep` file) +are consolidated into a single pack by using the `-A` option of +`git-repack`. Setting `gc.autopacklimit` to 0 disables +automatic consolidation of packs. Configuration ------------- From 9c60a966f2c3784cdff31aa6ad9f2086df64d5ba Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Thu, 18 Oct 2007 20:42:20 -0400 Subject: [PATCH 0209/1490] Change 'Deltifying objects' to 'Compressing objects' Recently I was referred to the Grammar Police as the git-pack-objects progress message 'Deltifying %u objects' is considered to be not proper English to at least some small but vocal segment of the English speaking population. Techncially we are applying delta compression to these objects at this stage, so the new term is slightly more acceptable to the Grammar Police but is also just as correct. Signed-off-by: Shawn O. Pearce --- builtin-pack-objects.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index 15d3750616..21ba977df3 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -1718,7 +1718,7 @@ static void prepare_pack(int window, int depth) if (nr_deltas && n > 1) { unsigned nr_done = 0; if (progress) - start_progress(&progress_state, "Deltifying objects", + start_progress(&progress_state, "Compressing objects", nr_deltas); qsort(delta_list, n, sizeof(*delta_list), type_size_sort); ll_find_deltas(delta_list, n, window+1, depth, &nr_done); From b5d72f0a4cd3cce945ca0d37e4fa0ebbfcdcdb52 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 19 Oct 2007 00:08:37 -0400 Subject: [PATCH 0210/1490] Teach prune-packed to use the standard progress meter Rather than reimplementing the progress meter logic and always showing 100 lines of output while pruning already packed objects we now use a delayed progress meter and only show it if there are enough objects to make us take a little while. Most users won't see the message anymore as it usually doesn't take very long to delete the already packed loose objects. This neatens the output of a git-gc or git-repack execution, which is especially important for a `git gc --auto` triggered from within another command. We perform the display_progress() call from within the very innermost loop in case we spend more than 1 second within any single object directory. This ensures that a progress_update event from the timer will still trigger in a timely fashion and allow the user to see the progress meter. While I'm in here I changed the message to be more descriptive of its actual task. "Removing unused objects" is a little scary for new users as they wonder where these unused objects came from and how they should avoid them. Truth is these objects aren't unused in the sense of what git-prune would call a dangling object, these are used but are just duplicates of things we have already stored in a packfile. Signed-off-by: Shawn O. Pearce --- builtin-prune-packed.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/builtin-prune-packed.c b/builtin-prune-packed.c index 977730064b..015c8bb7cc 100644 --- a/builtin-prune-packed.c +++ b/builtin-prune-packed.c @@ -1,5 +1,6 @@ #include "builtin.h" #include "cache.h" +#include "progress.h" static const char prune_packed_usage[] = "git-prune-packed [-n] [-q]"; @@ -7,6 +8,8 @@ static const char prune_packed_usage[] = #define DRY_RUN 01 #define VERBOSE 02 +static struct progress progress; + static void prune_dir(int i, DIR *dir, char *pathname, int len, int opts) { struct dirent *de; @@ -23,6 +26,8 @@ static void prune_dir(int i, DIR *dir, char *pathname, int len, int opts) if (!has_sha1_pack(sha1, NULL)) continue; memcpy(pathname + len, de->d_name, 38); + if (opts == VERBOSE) + display_progress(&progress, i + 1); if (opts & DRY_RUN) printf("rm -f %s\n", pathname); else if (unlink(pathname) < 0) @@ -39,6 +44,11 @@ void prune_packed_objects(int opts) const char *dir = get_object_directory(); int len = strlen(dir); + if (opts == VERBOSE) + start_progress_delay(&progress, + "Removing duplicate objects", + 256, 95, 2); + if (len > PATH_MAX - 42) die("impossible object directory"); memcpy(pathname, dir, len); @@ -49,16 +59,13 @@ void prune_packed_objects(int opts) sprintf(pathname + len, "%02x/", i); d = opendir(pathname); - if (opts == VERBOSE && (d || i == 255)) - fprintf(stderr, "Removing unused objects %d%%...\015", - ((i+1) * 100) / 256); if (!d) continue; prune_dir(i, d, pathname, len + 3, opts); closedir(d); } if (opts == VERBOSE) - fprintf(stderr, "\nDone.\n"); + stop_progress(&progress); } int cmd_prune_packed(int argc, const char **argv, const char *prefix) From 0e30404370c24047c5fa54b2a6c43e53629c916b Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 19 Oct 2007 01:01:40 -0400 Subject: [PATCH 0211/1490] Stop displaying "Pack pack-$ID created." during git-gc Discussion on the list tonight came to the conclusion that showing the name of the packfile we just created during git-repack is not a very useful message for any end-user. For the really technical folk who need to have the name of the newest packfile they can use something such as `ls -t .git/objects/pack | head -2` to find the most recently created packfile. Signed-off-by: Shawn O. Pearce --- git-repack.sh | 3 --- 1 file changed, 3 deletions(-) diff --git a/git-repack.sh b/git-repack.sh index e72adc4d91..7220635c96 100755 --- a/git-repack.sh +++ b/git-repack.sh @@ -83,9 +83,6 @@ for name in $names ; do fullbases="$fullbases pack-$name" chmod a-w "$PACKTMP-$name.pack" chmod a-w "$PACKTMP-$name.idx" - if test "$quiet" != '-q'; then - echo "Pack pack-$name created." - fi mkdir -p "$PACKDIR" || exit for sfx in pack idx From bbaf63f2f18242484868d6c03d5df9bd071d6deb Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 19 Oct 2007 01:18:29 -0400 Subject: [PATCH 0212/1490] Further 1.5.3.5 fixes described in release notes Signed-off-by: Shawn O. Pearce --- Documentation/RelNotes-1.5.3.5.txt | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/Documentation/RelNotes-1.5.3.5.txt b/Documentation/RelNotes-1.5.3.5.txt index 78df418257..49e52264ba 100644 --- a/Documentation/RelNotes-1.5.3.5.txt +++ b/Documentation/RelNotes-1.5.3.5.txt @@ -20,9 +20,9 @@ Fixes since v1.5.3.4 * "git-add -i" did not handle single line hunks correctly. - * "git-rebase -i" failed if external diff drivers were used for one - or more files in a commit. It now avoids calling the external - diff drivers. + * "git-rebase -i" and "git-stash apply" failed if external diff + drivers were used for one or more files in a commit. They now + avoid calling the external diff drivers. * "git-log --follow" did not work unless diff generation (e.g. -p) was also requested. @@ -38,6 +38,16 @@ Fixes since v1.5.3.4 * "git-instaweb" no longer fails on Mac OS X. + * "git-cvsexportcommit" didn't always create new parent directories + before trying to create new child directories. Fixed. + + * "git-fetch" printed a scary (but bogus) error message while + fetching a tag that pointed to a tree or blob. The error did + not impact correctness, only user perception. The bogus error + is no longer printed. + + * Git segfaulted when reading an invalid .gitattributes file. Fixed. + * post-receive-email example hook fixed was fixed for non-fast-forward updates. From e7187e4e0fece6c2947fbceff251f3ce69ae0aa8 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 19 Oct 2007 02:18:14 -0400 Subject: [PATCH 0213/1490] Paper bag fix diff invocation in 'git stash show' In 89d750bf6fa025edeb31ad258cdd09a27a5c02fa I got a little too aggressive with changing "git diff" to "git diff-tree". This is shown to the user, who expects to see a full diff on their console, and will want to see the output of their custom diff drivers (if any) as the whole point of this call site is to show the diff to the end-user. Noticed by Johannes Sixt . Signed-off-by: Shawn O. Pearce --- git-stash.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git-stash.sh b/git-stash.sh index def3163ebb..5bbda47b7b 100755 --- a/git-stash.sh +++ b/git-stash.sh @@ -110,7 +110,7 @@ show_stash () { w_commit=$(git rev-parse --verify "$s") && b_commit=$(git rev-parse --verify "$s^") && - git diff-tree $flags $b_commit $w_commit + git diff $flags $b_commit $w_commit } apply_stash () { From cfa5b2b7faa1a620ec6599a63fa5b9b45bd62b57 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 19 Oct 2007 00:54:59 -0400 Subject: [PATCH 0214/1490] Avoid scary errors about tagged trees/blobs during git-fetch This is the same bug as 42a32174b600f139b489341b1281fb1bfa14c252. The warning "Object $X is a tree, not a commit" is bogus and is not relevant here. If its not a commit we just need to make sure we don't mark it for merge as we fill out FETCH_HEAD. Signed-off-by: Shawn O. Pearce --- builtin-fetch.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/builtin-fetch.c b/builtin-fetch.c index 3442f3d09e..b9d2b0c27e 100644 --- a/builtin-fetch.c +++ b/builtin-fetch.c @@ -202,8 +202,8 @@ static int update_local_ref(struct ref *ref, return s_update_ref("updating tag", ref, 0); } - current = lookup_commit_reference(ref->old_sha1); - updated = lookup_commit_reference(ref->new_sha1); + current = lookup_commit_reference_gently(ref->old_sha1, 1); + updated = lookup_commit_reference_gently(ref->new_sha1, 1); if (!current || !updated) { char *msg; if (!strncmp(ref->name, "refs/tags/", 10)) @@ -261,7 +261,7 @@ static void store_updated_refs(const char *url, struct ref *ref_map) ref->force = rm->peer_ref->force; } - commit = lookup_commit_reference(rm->old_sha1); + commit = lookup_commit_reference_gently(rm->old_sha1, 1); if (!commit) rm->merge = 0; From eb33a67f218b612f6fb1456e19b40a1f97ff02c0 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Fri, 19 Oct 2007 19:09:43 +1000 Subject: [PATCH 0215/1490] gitk: Fix Tcl error: can't unset findcurline The logic in stopfinding assumes that findcurline will be set if find_dirn is, but findnext and findprev can set find_dirn without setting findcurline. This makes sure we only set find_dirn in those places if findcurline is already set. Signed-off-by: Paul Mackerras --- gitk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gitk b/gitk index 290deff7b2..3b3cc4bd93 100755 --- a/gitk +++ b/gitk @@ -4279,7 +4279,6 @@ proc findnext {restart} { global findcurline find_dirn if {[info exists find_dirn]} return - set find_dirn 1 if {![info exists findcurline]} { if {$restart} { dofind @@ -4287,6 +4286,7 @@ proc findnext {restart} { bell } } else { + set find_dirn 1 run findmore nowbusy finding } @@ -4296,10 +4296,10 @@ proc findprev {} { global findcurline find_dirn if {[info exists find_dirn]} return - set find_dirn -1 if {![info exists findcurline]} { dofind 1 } else { + set find_dirn -1 run findmorerev nowbusy finding } From 5eb73581679abb41dcdf9ad7fa63fa156e078790 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Fri, 19 Oct 2007 05:04:00 -0400 Subject: [PATCH 0216/1490] send-pack: respect '+' on wildcard refspecs When matching source and destination refs, we were failing to pull the 'force' parameter from wildcard refspecs (but not explicit ones) and attach it to the ref struct. This adds a test for explicit and wildcard refspecs; the latter fails without this patch. Signed-off-by: Jeff King Signed-off-by: Shawn O. Pearce --- remote.c | 2 ++ t/t5400-send-pack.sh | 48 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/remote.c b/remote.c index bb774d0bcc..cdbbdcb00d 100644 --- a/remote.c +++ b/remote.c @@ -626,6 +626,8 @@ int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail, hashcpy(dst_peer->new_sha1, src->new_sha1); } dst_peer->peer_ref = src; + if (pat) + dst_peer->force = pat->force; free_name: free(dst_name); } diff --git a/t/t5400-send-pack.sh b/t/t5400-send-pack.sh index 57c6397be1..2d0c07fd6a 100755 --- a/t/t5400-send-pack.sh +++ b/t/t5400-send-pack.sh @@ -123,4 +123,52 @@ test_expect_success \ git-branch -a >branches && ! grep -q origin/master branches ' +rewound_push_setup() { + rm -rf parent child && + mkdir parent && cd parent && + git-init && echo one >file && git-add file && git-commit -m one && + echo two >file && git-commit -a -m two && + cd .. && + git-clone parent child && cd child && git-reset --hard HEAD^ +} + +rewound_push_succeeded() { + cmp ../parent/.git/refs/heads/master .git/refs/heads/master +} + +rewound_push_failed() { + if rewound_push_succeeded + then + false + else + true + fi +} + +test_expect_success \ + 'pushing explicit refspecs respects forcing' ' + rewound_push_setup && + if git-send-pack ../parent/.git refs/heads/master:refs/heads/master + then + false + else + true + fi && rewound_push_failed && + git-send-pack ../parent/.git +refs/heads/master:refs/heads/master && + rewound_push_succeeded +' + +test_expect_success \ + 'pushing wildcard refspecs respects forcing' ' + rewound_push_setup && + if git-send-pack ../parent/.git refs/heads/*:refs/heads/* + then + false + else + true + fi && rewound_push_failed && + git-send-pack ../parent/.git +refs/heads/*:refs/heads/* && + rewound_push_succeeded +' + test_done From 5dd57d512225bb82aa0010b39aaec0085d471eac Mon Sep 17 00:00:00 2001 From: Jonathan del Strother Date: Mon, 15 Oct 2007 10:33:07 +0100 Subject: [PATCH 0217/1490] gitk: Add support for OS X mouse wheel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (Väinö Järvelä supplied this patch a while ago for 1.5.2. It no longer applied cleanly, so I'm reposting it.) MacBook doesn't seem to recognize MouseRelease-4 and -5 events, at all. So i added a support for the MouseWheel event, which i limited to Tcl/tk aqua, as i couldn't test it neither on Linux or Windows. Tcl/tk needs to be updated from the version that is shipped with OS X 10.4 Tiger, for this patch to work. Signed-off-by: Jonathan del Strother Signed-off-by: Shawn O. Pearce --- gitk | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/gitk b/gitk index 999e3c2188..46673e3b9c 100755 --- a/gitk +++ b/gitk @@ -843,6 +843,12 @@ proc makewindow {} { } else { bindall "allcanvs yview scroll -5 units" bindall "allcanvs yview scroll 5 units" + if {[tk windowingsystem] eq "aqua"} { + bindall { + set delta [expr {- (%D)}] + allcanvs yview scroll $delta units + } + } } bindall <2> "canvscan mark %W %x %y" bindall "canvscan dragto %W %x %y" From 5e85ec4cd0658232fa8ee13e8cd9da21e0e4973e Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Tue, 2 Oct 2007 16:16:54 +0200 Subject: [PATCH 0218/1490] gitk: Do not pick up file names of "copy from" lines A file copy would be detected only if the original file was modified in the same commit. This implies that there will be a patch listed under the original file name, and we would expect that clicking the original file name in the file list warps the patch window to that file's patch. (If the original file was not modified, the copy would not be detected in the first place, the copied file would be listed as "new file", and this whole matter would not apply.) However, if the name of the copy is sorted after the original file's patch, then the logic introduced by commit d1cb298b0b (which picks up the link information from the "copy from" line) would overwrite the link information that is already present for the original file name, which was parsed earlier. Hence, this patch reverts part of said commit. Signed-off-by: Johannes Sixt Signed-off-by: Shawn O. Pearce --- gitk | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gitk b/gitk index 46673e3b9c..516e14a8fc 100755 --- a/gitk +++ b/gitk @@ -5221,8 +5221,7 @@ proc getblobdiffline {bdf ids} { set diffinhdr 0 } elseif {$diffinhdr} { - if {![string compare -length 12 "rename from " $line] || - ![string compare -length 10 "copy from " $line]} { + if {![string compare -length 12 "rename from " $line]} { set fname [string range $line [expr 6 + [string first " from " $line] ] end] if {[string index $fname 0] eq "\""} { set fname [lindex $fname 0] From 1d5bf7fcee6122931bd04c97269d64f8f282ec55 Mon Sep 17 00:00:00 2001 From: Ralf Wildenhues Date: Fri, 19 Oct 2007 19:24:43 +0200 Subject: [PATCH 0219/1490] gitk.txt: Fix markup. For the manpage, avoid generating an em dash in code. Signed-off-by: Ralf Wildenhues Signed-off-by: Shawn O. Pearce --- Documentation/gitk.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/gitk.txt b/Documentation/gitk.txt index e9f82b97b9..8dbfb0d5a3 100644 --- a/Documentation/gitk.txt +++ b/Documentation/gitk.txt @@ -69,7 +69,7 @@ gitk --since="2 weeks ago" \-- gitk:: The "--" is necessary to avoid confusion with the *branch* named 'gitk' -gitk --max-count=100 --all -- Makefile:: +gitk --max-count=100 --all \-- Makefile:: Show at most 100 changes made to the file 'Makefile'. Instead of only looking for changes in the current branch look in all branches. From 8af52d7a83a78c5f3a60d5bd5099a5073655339a Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Sat, 20 Oct 2007 01:42:01 -0400 Subject: [PATCH 0220/1490] git-gui: Correctly report failures from git-write-tree If git-write-tree fails (such as if the index file is currently locked and it wants to write to it) we were not getting the error message as $tree_id was always the empty string so we shortcut through the catch and never got the output from stderr. Signed-off-by: Shawn O. Pearce --- lib/commit.tcl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/commit.tcl b/lib/commit.tcl index f857a2ff5b..57238129e4 100644 --- a/lib/commit.tcl +++ b/lib/commit.tcl @@ -253,7 +253,7 @@ proc commit_committree {fd_wt curHEAD msg} { global repo_config gets $fd_wt tree_id - if {$tree_id eq {} || [catch {close $fd_wt} err]} { + if {[catch {close $fd_wt} err]} { error_popup "write-tree failed:\n\n$err" ui_status {Commit failed.} unlock_index From 5d7589d4c43e941563dfa2d096e6d6c184191702 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sat, 20 Oct 2007 21:21:03 +1000 Subject: [PATCH 0221/1490] gitk: Check that we are running on at least Tcl/Tk 8.4 This checks that we have Tcl/Tk 8.4 or later, and puts up an error message in a window and quits if not. This was prompted by a patch submitted by Steffen Prohaska, but is done a bit differently (this uses package require rather than looking at [info tclversion], and uses show_error to display the error rather than printing it to stderr). Signed-off-by: Paul Mackerras --- gitk | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/gitk b/gitk index 516e14a8fc..06172a434b 100755 --- a/gitk +++ b/gitk @@ -7838,6 +7838,13 @@ proc tcl_encoding {enc} { return {} } +# First check that Tcl/Tk is recent enough +if {[catch {package require Tk 8.4} err]} { + show_error {} . "Sorry, gitk cannot run with this version of Tcl/Tk.\n\ + Gitk requires at least Tcl/Tk 8.4." + exit 1 +} + # defaults... set datemode 0 set diffopts "-U 5 -p" From 3ebba3c724f77d149061c62f4414166649c2e56e Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sat, 20 Oct 2007 22:10:52 +1000 Subject: [PATCH 0222/1490] gitk: Avoid an error when cherry-picking if HEAD has moved on MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes an error reported by Adam Piątyszek: if the current HEAD is not in the graph that gitk knows about when we do a cherry-pick using gitk, then gitk hits an error when trying to update its internal representation of the topology. This avoids the error by not doing that update if the HEAD before the cherry-pick was a commit that gitk doesn't know about. Signed-off-by: Paul Mackerras --- gitk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gitk b/gitk index 06172a434b..f910cba8bf 100755 --- a/gitk +++ b/gitk @@ -6648,7 +6648,7 @@ proc addnewchild {id p} { global arcnos arcids arctags arcout arcend arcstart archeads growing global seeds allcommits - if {![info exists allcommits]} return + if {![info exists allcommits] || ![info exists arcnos($p)]} return lappend allids $id set allparents($id) [list $p] set allchildren($id) {} From 209471493afbf30d5c1fc80feadfc4836b86dc42 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 13 Sep 2007 22:10:18 +0200 Subject: [PATCH 0223/1490] git-p4: When skipping a patch as part of "git-p4 submit" make sure we correctly revert to the previous state of the files using "p4 revert". Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index 52cd2a46ba..e1dc263013 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -529,6 +529,10 @@ class P4Submit(Command): "and with .rej files / [w]rite the patch to a file (patch.txt) ") if response == "s": print "Skipping! Good luck with the next patches..." + for f in editedFiles: + system("p4 revert \"%s\"" % f); + for f in filesToAdd: + system("rm %s" %f) return elif response == "a": os.system(applyPatchCmd) From d9a5f25b67951eb68e80d872611542b58ce5aa33 Mon Sep 17 00:00:00 2001 From: Chris Pettitt Date: Mon, 15 Oct 2007 22:15:06 -0700 Subject: [PATCH 0224/1490] git-p4 support for perforce renames. The current git-p4 implementation does support file renames. However, because it does not use the "p4 integrate" command, the history for the renamed file is not linked to the new file. This changeset adds support for perforce renames with the integrate command. Currently this feature is only enabled when calling git-p4 submit with the -M option. This is intended to look and behave similar to the "detect renames" feature of other git commands. The following sequence is used for renamed files: p4 integrate -Dt x x' p4 edit x' rm x' git apply p4 delete x By default, perforce will not allow an integration with a target file that has been deleted. That is, if x' in the example above is the name of a previously deleted file then perforce will fail the integrate. The -Dt option tells perforce to allow the target of integrate to be a previously deleted file. Signed-off-by: Chris Pettitt Signed-off-by: Simon Hausmann --- contrib/fast-import/git-p4 | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index e1dc263013..bf33f74b70 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -399,6 +399,7 @@ class P4Submit(Command): optparse.make_option("--dry-run", action="store_true"), optparse.make_option("--direct", dest="directSubmit", action="store_true"), optparse.make_option("--trust-me-like-a-fool", dest="trustMeLikeAFool", action="store_true"), + optparse.make_option("-M", dest="detectRename", action="store_true"), ] self.description = "Submit changes from git to the perforce depot." self.usage += " [name of git branch to submit into perforce depot]" @@ -411,6 +412,7 @@ class P4Submit(Command): self.origin = "" self.directSubmit = False self.trustMeLikeAFool = False + self.detectRename = False self.verbose = False self.isWindows = (platform.system() == "Windows") @@ -491,7 +493,8 @@ class P4Submit(Command): diff = self.diffStatus else: print "Applying %s" % (read_pipe("git log --max-count=1 --pretty=oneline %s" % id)) - diff = read_pipe_lines("git diff-tree -r --name-status \"%s^\" \"%s\"" % (id, id)) + diffOpts = ("", "-M")[self.detectRename] + diff = read_pipe_lines("git diff-tree -r --name-status %s \"%s^\" \"%s\"" % (diffOpts, id, id)) filesToAdd = set() filesToDelete = set() editedFiles = set() @@ -509,6 +512,13 @@ class P4Submit(Command): filesToDelete.add(path) if path in filesToAdd: filesToAdd.remove(path) + elif modifier == "R": + src, dest = line.strip().split("\t")[1:3] + system("p4 integrate -Dt \"%s\" \"%s\"" % (src, dest)) + system("p4 edit \"%s\"" % (dest)) + os.unlink(dest) + editedFiles.add(dest) + filesToDelete.add(src) else: die("unknown modifier %s for %s" % (modifier, path)) From bea6878be2fb73e50407f93f2bcd71b961510c19 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Sat, 20 Oct 2007 14:16:15 -0400 Subject: [PATCH 0225/1490] git-gui: Handle progress bars from newer gits Post Git 1.5.3 a new style progress bar has been introduced that uses only one line rather than two. The formatting of the completed and total section is also slightly different so we must adjust our regexp to match. Unfortunately both styles are in active use by different versions of Git so we need to look for both. Signed-off-by: Shawn O. Pearce --- lib/status_bar.tcl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/status_bar.tcl b/lib/status_bar.tcl index 72a8fe1fd3..3bf79eb6e0 100644 --- a/lib/status_bar.tcl +++ b/lib/status_bar.tcl @@ -69,7 +69,10 @@ method update_meter {buf} { set prior [string range $meter 0 $r] set meter [string range $meter [expr {$r + 1}] end] - if {[regexp "\\((\\d+)/(\\d+)\\)\\s+done\r\$" $prior _j a b]} { + set p "\\((\\d+)/(\\d+)\\)" + if {[regexp ":\\s*\\d+% $p\(?:, done.\\s*\n|\\s*\r)\$" $prior _j a b]} { + update $this $a $b + } elseif {[regexp "$p\\s+done\r\$" $prior _j a b]} { update $this $a $b } } From bbbadf6e58f72ac6bf739d2a1109cbd872eb1083 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Sat, 20 Oct 2007 20:42:01 -0400 Subject: [PATCH 0226/1490] git-gui: Don't display CR within console windows Git progress bars from tools like git-push and git-fetch use CR to skip back to the start of the current line and redraw it with an updated progress. We were doing this in our Tk widget but had failed to skip the CR, which Tk doesn't draw well. Signed-off-by: Shawn O. Pearce --- lib/console.tcl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/console.tcl b/lib/console.tcl index 6f718fbac3..b038a78358 100644 --- a/lib/console.tcl +++ b/lib/console.tcl @@ -122,7 +122,7 @@ method _read {fd after} { } else { $w.m.t delete $console_cr end $w.m.t insert end "\n" - $w.m.t insert end [string range $buf $c $cr] + $w.m.t insert end [string range $buf $c [expr {$cr - 1}]] set c $cr incr c } From fb6cf213a3929744fc89e6a444dcd7d4b2fa3c66 Mon Sep 17 00:00:00 2001 From: Christian Stimming Date: Sat, 20 Oct 2007 15:30:53 +0200 Subject: [PATCH 0227/1490] git-gui: Add more terms to glossary. Signed-off-by: Shawn O. Pearce --- po/glossary/git-gui-glossary.pot | 8 ++++++-- po/glossary/git-gui-glossary.txt | 3 ++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/po/glossary/git-gui-glossary.pot b/po/glossary/git-gui-glossary.pot index a2e5c73bbd..48af803314 100644 --- a/po/glossary/git-gui-glossary.pot +++ b/po/glossary/git-gui-glossary.pot @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" -"POT-Creation-Date: 2007-10-05 22:30+0200\n" +"POT-Creation-Date: 2007-10-19 21:43+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -86,7 +86,7 @@ msgstr "" msgid "message" msgstr "" -#. "" +#. "Deletes all stale tracking branches under . These stale branches have already been removed from the remote repository referenced by , but are still locally available in 'remotes/'." msgid "prune" msgstr "" @@ -102,6 +102,10 @@ msgstr "" msgid "redo" msgstr "" +#. "An other repository ('remote'). One might have a set of remotes whose branches one tracks." +msgid "remote" +msgstr "" + #. "A collection of refs (?) together with an object database containing all objects which are reachable from the refs... (oops, you've lost me here. Again, please an explanation for mere mortals?)" msgid "repository" msgstr "" diff --git a/po/glossary/git-gui-glossary.txt b/po/glossary/git-gui-glossary.txt index b53740d48c..500d0a0ea7 100644 --- a/po/glossary/git-gui-glossary.txt +++ b/po/glossary/git-gui-glossary.txt @@ -16,10 +16,11 @@ "merge [noun]" "A successful merge results in the creation of a new commit representing the result of the merge." "merge [verb]" "To bring the contents of another branch into the current branch." "message" "" -"prune" "" +"prune" "Deletes all stale tracking branches under . These stale branches have already been removed from the remote repository referenced by , but are still locally available in 'remotes/'." "pull" "Pulling a branch means to fetch it and merge it." "push" "Pushing a branch means to get the branch's head ref from a remote repository, and ... (well, can someone please explain it for mere mortals?)" "redo" "" +"remote" "An other repository ('remote'). One might have a set of remotes whose branches one tracks." "repository" "A collection of refs (?) together with an object database containing all objects which are reachable from the refs... (oops, you've lost me here. Again, please an explanation for mere mortals?)" "reset" "" "revert" "" From 9d434d50262b00243c6249697ebfa8512042b158 Mon Sep 17 00:00:00 2001 From: Christian Stimming Date: Sat, 20 Oct 2007 15:31:43 +0200 Subject: [PATCH 0228/1490] git-gui: Update German translation Signed-off-by: Shawn O. Pearce --- po/de.po | 444 ++++++++++++++++++++++++---------------------- po/glossary/de.po | 14 +- 2 files changed, 238 insertions(+), 220 deletions(-) diff --git a/po/de.po b/po/de.po index 4ba2fbee51..3df30edb87 100644 --- a/po/de.po +++ b/po/de.po @@ -7,41 +7,41 @@ msgid "" msgstr "" "Project-Id-Version: git-gui\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2007-10-10 04:04-0400\n" -"PO-Revision-Date: 2007-10-05 22:27+0200\n" +"POT-Creation-Date: 2007-10-19 21:10+0200\n" +"PO-Revision-Date: 2007-10-20 15:28+0200\n" "Last-Translator: Christian Stimming \n" "Language-Team: German\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: git-gui.sh:41 git-gui.sh:634 git-gui.sh:648 git-gui.sh:661 git-gui.sh:744 -#: git-gui.sh:763 +#: git-gui.sh:41 git-gui.sh:590 git-gui.sh:604 git-gui.sh:617 git-gui.sh:700 +#: git-gui.sh:719 msgid "git-gui: fatal error" msgstr "git-gui: Programmfehler" -#: git-gui.sh:595 +#: git-gui.sh:551 #, tcl-format msgid "Invalid font specified in %s:" msgstr "Ungültige Zeichensatz-Angabe in %s:" -#: git-gui.sh:620 +#: git-gui.sh:576 msgid "Main Font" msgstr "Programmschriftart" -#: git-gui.sh:621 +#: git-gui.sh:577 msgid "Diff/Console Font" msgstr "Vergleich-Schriftart" -#: git-gui.sh:635 +#: git-gui.sh:591 msgid "Cannot find git in PATH." msgstr "Git kann im PATH nicht gefunden werden." -#: git-gui.sh:662 +#: git-gui.sh:618 msgid "Cannot parse Git version string:" msgstr "Git Versionsangabe kann nicht erkannt werden:" -#: git-gui.sh:680 +#: git-gui.sh:636 #, tcl-format msgid "" "Git version cannot be determined.\n" @@ -60,81 +60,81 @@ msgstr "" "\n" "Soll angenommen werden, »%s« sei Version 1.5.0?\n" -#: git-gui.sh:853 +#: git-gui.sh:874 msgid "Git directory not found:" msgstr "Git-Verzeichnis nicht gefunden:" -#: git-gui.sh:860 +#: git-gui.sh:881 msgid "Cannot move to top of working directory:" msgstr "" "Es konnte nicht in das oberste Verzeichnis der Arbeitskopie gewechselt " "werden:" -#: git-gui.sh:867 +#: git-gui.sh:888 msgid "Cannot use funny .git directory:" msgstr "Unerwartete Struktur des .git Verzeichnis:" -#: git-gui.sh:872 +#: git-gui.sh:893 msgid "No working directory" msgstr "Kein Arbeitsverzeichnis" -#: git-gui.sh:1019 +#: git-gui.sh:1040 msgid "Refreshing file status..." msgstr "Dateistatus aktualisieren..." -#: git-gui.sh:1084 +#: git-gui.sh:1105 msgid "Scanning for modified files ..." msgstr "Nach geänderten Dateien suchen..." -#: git-gui.sh:1259 lib/browser.tcl:245 +#: git-gui.sh:1280 lib/browser.tcl:245 msgid "Ready." msgstr "Bereit." -#: git-gui.sh:1525 +#: git-gui.sh:1546 msgid "Unmodified" msgstr "Unverändert" -#: git-gui.sh:1527 +#: git-gui.sh:1548 msgid "Modified, not staged" msgstr "Verändert, nicht bereitgestellt" -#: git-gui.sh:1528 git-gui.sh:1533 +#: git-gui.sh:1549 git-gui.sh:1554 msgid "Staged for commit" msgstr "Bereitgestellt zum Eintragen" -#: git-gui.sh:1529 git-gui.sh:1534 +#: git-gui.sh:1550 git-gui.sh:1555 msgid "Portions staged for commit" msgstr "Teilweise bereitgestellt zum Eintragen" -#: git-gui.sh:1530 git-gui.sh:1535 +#: git-gui.sh:1551 git-gui.sh:1556 msgid "Staged for commit, missing" msgstr "Bereitgestellt zum Eintragen, fehlend" -#: git-gui.sh:1532 +#: git-gui.sh:1553 msgid "Untracked, not staged" msgstr "Nicht unter Versionskontrolle, nicht bereitgestellt" -#: git-gui.sh:1537 +#: git-gui.sh:1558 msgid "Missing" msgstr "Fehlend" -#: git-gui.sh:1538 +#: git-gui.sh:1559 msgid "Staged for removal" msgstr "Bereitgestellt zum Löschen" -#: git-gui.sh:1539 +#: git-gui.sh:1560 msgid "Staged for removal, still present" msgstr "Bereitgestellt zum Löschen, trotzdem vorhanden" -#: git-gui.sh:1541 git-gui.sh:1542 git-gui.sh:1543 git-gui.sh:1544 +#: git-gui.sh:1562 git-gui.sh:1563 git-gui.sh:1564 git-gui.sh:1565 msgid "Requires merge resolution" msgstr "Konfliktauflösung nötig" -#: git-gui.sh:1579 +#: git-gui.sh:1600 msgid "Starting gitk... please wait..." msgstr "Gitk wird gestartet... bitte warten." -#: git-gui.sh:1588 +#: git-gui.sh:1609 #, tcl-format msgid "" "Unable to start gitk:\n" @@ -145,297 +145,295 @@ msgstr "" "\n" "%s existiert nicht" -#: git-gui.sh:1788 lib/choose_repository.tcl:32 +#: git-gui.sh:1809 lib/choose_repository.tcl:35 msgid "Repository" msgstr "Projektarchiv" -#: git-gui.sh:1789 +#: git-gui.sh:1810 msgid "Edit" msgstr "Bearbeiten" -#: git-gui.sh:1791 lib/choose_rev.tcl:560 +#: git-gui.sh:1812 lib/choose_rev.tcl:560 msgid "Branch" msgstr "Zweig" -#: git-gui.sh:1794 lib/choose_rev.tcl:547 +#: git-gui.sh:1815 lib/choose_rev.tcl:547 msgid "Commit@@noun" msgstr "Version" -#: git-gui.sh:1797 lib/merge.tcl:121 lib/merge.tcl:150 lib/merge.tcl:168 +#: git-gui.sh:1818 lib/merge.tcl:121 lib/merge.tcl:150 lib/merge.tcl:168 msgid "Merge" msgstr "Zusammenführen" -#: git-gui.sh:1798 lib/choose_rev.tcl:556 +#: git-gui.sh:1819 lib/choose_rev.tcl:556 msgid "Remote" -msgstr "Gegenseite" +msgstr "Andere Archive" -#: git-gui.sh:1807 +#: git-gui.sh:1828 msgid "Browse Current Branch's Files" msgstr "Aktuellen Zweig durchblättern" -#: git-gui.sh:1811 +#: git-gui.sh:1832 msgid "Browse Branch Files..." msgstr "Einen Zweig durchblättern..." -#: git-gui.sh:1816 +#: git-gui.sh:1837 msgid "Visualize Current Branch's History" msgstr "Aktuellen Zweig darstellen" -#: git-gui.sh:1820 +#: git-gui.sh:1841 msgid "Visualize All Branch History" msgstr "Alle Zweige darstellen" -#: git-gui.sh:1827 +#: git-gui.sh:1848 #, tcl-format msgid "Browse %s's Files" msgstr "Zweig »%s« durchblättern" -#: git-gui.sh:1829 +#: git-gui.sh:1850 #, tcl-format msgid "Visualize %s's History" msgstr "Historie von »%s« darstellen" -#: git-gui.sh:1834 lib/database.tcl:27 lib/database.tcl:67 +#: git-gui.sh:1855 lib/database.tcl:27 lib/database.tcl:67 msgid "Database Statistics" msgstr "Datenbankstatistik" -#: git-gui.sh:1837 lib/database.tcl:34 +#: git-gui.sh:1858 lib/database.tcl:34 msgid "Compress Database" msgstr "Datenbank komprimieren" -#: git-gui.sh:1840 +#: git-gui.sh:1861 msgid "Verify Database" msgstr "Datenbank überprüfen" -#: git-gui.sh:1847 git-gui.sh:1851 git-gui.sh:1855 lib/shortcut.tcl:9 -#: lib/shortcut.tcl:45 lib/shortcut.tcl:84 +#: git-gui.sh:1868 git-gui.sh:1872 git-gui.sh:1876 lib/shortcut.tcl:7 +#: lib/shortcut.tcl:39 lib/shortcut.tcl:71 msgid "Create Desktop Icon" msgstr "Desktop-Icon erstellen" -#: git-gui.sh:1860 lib/choose_repository.tcl:36 lib/choose_repository.tcl:95 +#: git-gui.sh:1881 lib/choose_repository.tcl:176 lib/choose_repository.tcl:184 msgid "Quit" msgstr "Beenden" -#: git-gui.sh:1867 +#: git-gui.sh:1888 msgid "Undo" msgstr "Rückgängig" -#: git-gui.sh:1870 +#: git-gui.sh:1891 msgid "Redo" msgstr "Wiederholen" -#: git-gui.sh:1874 git-gui.sh:2366 +#: git-gui.sh:1895 git-gui.sh:2388 msgid "Cut" msgstr "Ausschneiden" -#: git-gui.sh:1877 git-gui.sh:2369 git-gui.sh:2440 git-gui.sh:2512 +#: git-gui.sh:1898 git-gui.sh:2391 git-gui.sh:2462 git-gui.sh:2534 #: lib/console.tcl:67 msgid "Copy" msgstr "Kopieren" -#: git-gui.sh:1880 git-gui.sh:2372 +#: git-gui.sh:1901 git-gui.sh:2394 msgid "Paste" msgstr "Einfügen" -#: git-gui.sh:1883 git-gui.sh:2375 lib/branch_delete.tcl:26 +#: git-gui.sh:1904 git-gui.sh:2397 lib/branch_delete.tcl:26 #: lib/remote_branch_delete.tcl:38 msgid "Delete" msgstr "Löschen" -#: git-gui.sh:1887 git-gui.sh:2379 git-gui.sh:2516 lib/console.tcl:69 +#: git-gui.sh:1908 git-gui.sh:2401 git-gui.sh:2538 lib/console.tcl:69 msgid "Select All" msgstr "Alle auswählen" -#: git-gui.sh:1896 +#: git-gui.sh:1917 msgid "Create..." msgstr "Erstellen..." -#: git-gui.sh:1902 +#: git-gui.sh:1923 msgid "Checkout..." msgstr "Umstellen..." -#: git-gui.sh:1908 +#: git-gui.sh:1929 msgid "Rename..." msgstr "Umbenennen..." -#: git-gui.sh:1913 git-gui.sh:2012 +#: git-gui.sh:1934 git-gui.sh:2033 msgid "Delete..." msgstr "Löschen..." -#: git-gui.sh:1918 +#: git-gui.sh:1939 msgid "Reset..." msgstr "Zurücksetzen..." -#: git-gui.sh:1930 git-gui.sh:2313 +#: git-gui.sh:1951 git-gui.sh:2335 msgid "New Commit" msgstr "Neue Version" -#: git-gui.sh:1938 git-gui.sh:2320 +#: git-gui.sh:1959 git-gui.sh:2342 msgid "Amend Last Commit" msgstr "Letzte Version nachbessern" -#: git-gui.sh:1947 git-gui.sh:2280 lib/remote_branch_delete.tcl:99 +#: git-gui.sh:1968 git-gui.sh:2302 lib/remote_branch_delete.tcl:99 msgid "Rescan" msgstr "Neu laden" -#: git-gui.sh:1953 +#: git-gui.sh:1974 msgid "Stage To Commit" msgstr "Zum Eintragen bereitstellen" -#: git-gui.sh:1958 +#: git-gui.sh:1979 msgid "Stage Changed Files To Commit" msgstr "Geänderte Dateien zum Eintragen bereitstellen" -#: git-gui.sh:1964 +#: git-gui.sh:1985 msgid "Unstage From Commit" msgstr "Aus der Bereitstellung herausnehmen" -#: git-gui.sh:1969 lib/index.tcl:352 +#: git-gui.sh:1990 lib/index.tcl:352 msgid "Revert Changes" msgstr "Änderungen revidieren" -#: git-gui.sh:1976 git-gui.sh:2292 git-gui.sh:2390 +#: git-gui.sh:1997 git-gui.sh:2314 git-gui.sh:2412 msgid "Sign Off" msgstr "Abzeichnen" -#: git-gui.sh:1980 git-gui.sh:2296 +#: git-gui.sh:2001 git-gui.sh:2318 msgid "Commit@@verb" msgstr "Eintragen" -#: git-gui.sh:1991 +#: git-gui.sh:2012 msgid "Local Merge..." msgstr "Lokales Zusammenführen..." -#: git-gui.sh:1996 +#: git-gui.sh:2017 msgid "Abort Merge..." msgstr "Zusammenführen abbrechen..." -#: git-gui.sh:2008 +#: git-gui.sh:2029 msgid "Push..." -msgstr "Ausliefern..." +msgstr "Versenden..." -#: git-gui.sh:2019 lib/choose_repository.tcl:41 +#: git-gui.sh:2040 lib/choose_repository.tcl:40 msgid "Apple" msgstr "Apple" -#: git-gui.sh:2022 git-gui.sh:2044 lib/about.tcl:13 -#: lib/choose_repository.tcl:44 lib/choose_repository.tcl:50 +#: git-gui.sh:2043 git-gui.sh:2065 lib/about.tcl:13 +#: lib/choose_repository.tcl:43 lib/choose_repository.tcl:49 #, tcl-format msgid "About %s" msgstr "Über %s" -#: git-gui.sh:2026 +#: git-gui.sh:2047 msgid "Preferences..." -msgstr "" +msgstr "Einstellungen..." -#: git-gui.sh:2034 git-gui.sh:2558 +#: git-gui.sh:2055 git-gui.sh:2580 msgid "Options..." msgstr "Optionen..." -#: git-gui.sh:2040 lib/choose_repository.tcl:47 +#: git-gui.sh:2061 lib/choose_repository.tcl:46 msgid "Help" msgstr "Hilfe" -#: git-gui.sh:2081 +#: git-gui.sh:2102 msgid "Online Documentation" msgstr "Online-Dokumentation" -#: git-gui.sh:2165 +#: git-gui.sh:2186 #, tcl-format msgid "fatal: cannot stat path %s: No such file or directory" msgstr "" -#: git-gui.sh:2198 +#: git-gui.sh:2219 msgid "Current Branch:" msgstr "Aktueller Zweig:" -#: git-gui.sh:2219 -#, fuzzy +#: git-gui.sh:2240 msgid "Staged Changes (Will Commit)" -msgstr "Bereitgestellte Änderungen (werden eingetragen)" +msgstr "Bereitgestellte Änderungen (zum Eintragen)" -#: git-gui.sh:2239 -#, fuzzy +#: git-gui.sh:2259 msgid "Unstaged Changes" -msgstr "Geänderte bereitstellen" +msgstr "Nicht bereitgestellte Änderungen" -#: git-gui.sh:2286 +#: git-gui.sh:2308 msgid "Stage Changed" -msgstr "Geänderte bereitstellen" +msgstr "Alles bereitstellen" -#: git-gui.sh:2302 lib/transport.tcl:93 lib/transport.tcl:182 +#: git-gui.sh:2324 lib/transport.tcl:93 lib/transport.tcl:182 msgid "Push" -msgstr "Ausliefern" +msgstr "Versenden" -#: git-gui.sh:2332 +#: git-gui.sh:2354 msgid "Initial Commit Message:" -msgstr "Beschreibung der ersten Version:" +msgstr "Erste Versionsbeschreibung:" -#: git-gui.sh:2333 +#: git-gui.sh:2355 msgid "Amended Commit Message:" -msgstr "Beschreibung der nachgebesserten Version:" +msgstr "Nachgebesserte Versionsbeschreibung:" -#: git-gui.sh:2334 +#: git-gui.sh:2356 msgid "Amended Initial Commit Message:" -msgstr "Beschreibung der nachgebesserten ersten Version:" +msgstr "Nachgebesserte erste Versionsbeschreibung:" -#: git-gui.sh:2335 +#: git-gui.sh:2357 msgid "Amended Merge Commit Message:" -msgstr "Beschreibung der nachgebesserten Zusammenführungs-Version:" +msgstr "Nachgebesserte Zusammenführungs-Versionsbeschreibung:" -#: git-gui.sh:2336 +#: git-gui.sh:2358 msgid "Merge Commit Message:" -msgstr "Beschreibung der Zusammenführungs-Version:" +msgstr "Zusammenführungs-Versionsbeschreibung:" -#: git-gui.sh:2337 +#: git-gui.sh:2359 msgid "Commit Message:" msgstr "Versionsbeschreibung:" -#: git-gui.sh:2382 git-gui.sh:2520 lib/console.tcl:71 +#: git-gui.sh:2404 git-gui.sh:2542 lib/console.tcl:71 msgid "Copy All" msgstr "Alle kopieren" -#: git-gui.sh:2406 lib/blame.tcl:104 +#: git-gui.sh:2428 lib/blame.tcl:104 msgid "File:" msgstr "Datei:" -#: git-gui.sh:2508 +#: git-gui.sh:2530 msgid "Refresh" msgstr "Aktualisieren" -#: git-gui.sh:2529 +#: git-gui.sh:2551 msgid "Apply/Reverse Hunk" msgstr "Änderung anwenden/umkehren" -#: git-gui.sh:2535 +#: git-gui.sh:2557 msgid "Decrease Font Size" msgstr "Schriftgröße verkleinern" -#: git-gui.sh:2539 +#: git-gui.sh:2561 msgid "Increase Font Size" msgstr "Schriftgröße vergrößern" -#: git-gui.sh:2544 +#: git-gui.sh:2566 msgid "Show Less Context" msgstr "Weniger Kontext anzeigen" -#: git-gui.sh:2551 +#: git-gui.sh:2573 msgid "Show More Context" msgstr "Mehr Kontext anzeigen" -#: git-gui.sh:2565 +#: git-gui.sh:2587 msgid "Unstage Hunk From Commit" msgstr "Aus der Bereitstellung herausnehmen" -#: git-gui.sh:2567 +#: git-gui.sh:2589 msgid "Stage Hunk For Commit" msgstr "In die Bereitstellung hinzufügen" -#: git-gui.sh:2586 +#: git-gui.sh:2608 msgid "Initializing..." msgstr "Initialisieren..." -#: git-gui.sh:2677 +#: git-gui.sh:2699 #, tcl-format msgid "" "Possible environment issues exist.\n" @@ -446,14 +444,14 @@ msgid "" "\n" msgstr "" -#: git-gui.sh:2707 +#: git-gui.sh:2729 msgid "" "\n" "This is due to a known issue with the\n" "Tcl binary distributed by Cygwin." msgstr "" -#: git-gui.sh:2712 +#: git-gui.sh:2734 #, tcl-format msgid "" "\n" @@ -515,11 +513,11 @@ msgstr "Eintragender:" #: lib/blame.tcl:796 msgid "Original File:" -msgstr "" +msgstr "Ursprüngliche Datei:" #: lib/blame.tcl:910 msgid "Originally By:" -msgstr "" +msgstr "Ursprünglich von:" #: lib/blame.tcl:916 msgid "In File:" @@ -527,7 +525,7 @@ msgstr "In Datei:" #: lib/blame.tcl:921 msgid "Copied Or Moved Here By:" -msgstr "" +msgstr "Kopiert oder verschoben durch:" #: lib/branch_checkout.tcl:14 lib/branch_checkout.tcl:19 msgid "Checkout Branch" @@ -568,7 +566,7 @@ msgstr "Zweig erstellen" msgid "Create New Branch" msgstr "Neuen Zweig erstellen" -#: lib/branch_create.tcl:31 lib/choose_repository.tcl:199 +#: lib/branch_create.tcl:31 lib/choose_repository.tcl:375 msgid "Create" msgstr "Erstellen" @@ -615,7 +613,7 @@ msgstr "Bitte wählen Sie einen Übernahmezweig." #: lib/branch_create.tcl:140 #, tcl-format msgid "Tracking branch %s is not a branch in the remote repository." -msgstr "Übernahmezweig »%s« ist kein Zweig im Projektarchiv der Gegenseite." +msgstr "Übernahmezweig »%s« ist kein Zweig im anderen Projektarchiv." #: lib/branch_create.tcl:153 lib/branch_rename.tcl:86 msgid "Please supply a branch name." @@ -721,9 +719,9 @@ msgstr "[Nach oben]" msgid "Browse Branch Files" msgstr "Dateien des Zweigs durchblättern" -#: lib/browser.tcl:277 lib/choose_repository.tcl:215 -#: lib/choose_repository.tcl:305 lib/choose_repository.tcl:315 -#: lib/choose_repository.tcl:811 +#: lib/browser.tcl:277 lib/choose_repository.tcl:391 +#: lib/choose_repository.tcl:482 lib/choose_repository.tcl:492 +#: lib/choose_repository.tcl:989 msgid "Browse" msgstr "Blättern" @@ -889,209 +887,225 @@ msgstr "" "Dies ist ein Beispieltext.\n" "Wenn Ihnen dieser Text gefällt, sollten Sie diese Schriftart wählen." -#: lib/choose_repository.tcl:25 +#: lib/choose_repository.tcl:27 msgid "Git Gui" msgstr "Git Gui" -#: lib/choose_repository.tcl:69 lib/choose_repository.tcl:204 +#: lib/choose_repository.tcl:80 lib/choose_repository.tcl:380 msgid "Create New Repository" msgstr "Neues Projektarchiv" -#: lib/choose_repository.tcl:74 lib/choose_repository.tcl:291 +#: lib/choose_repository.tcl:86 +msgid "New..." +msgstr "Neu..." + +#: lib/choose_repository.tcl:93 lib/choose_repository.tcl:468 msgid "Clone Existing Repository" msgstr "Projektarchiv kopieren" -#: lib/choose_repository.tcl:79 lib/choose_repository.tcl:800 +#: lib/choose_repository.tcl:99 +msgid "Clone..." +msgstr "Kopieren..." + +#: lib/choose_repository.tcl:106 lib/choose_repository.tcl:978 msgid "Open Existing Repository" msgstr "Projektarchiv öffnen" -#: lib/choose_repository.tcl:91 -msgid "Next >" -msgstr "Weiter >" +#: lib/choose_repository.tcl:112 +msgid "Open..." +msgstr "Öffnen..." -#: lib/choose_repository.tcl:152 +#: lib/choose_repository.tcl:125 +msgid "Recent Repositories" +msgstr "Zuletzt benutzte Projektarchive" + +#: lib/choose_repository.tcl:131 +msgid "Open Recent Repository:" +msgstr "Zuletzt benutztes Projektarchiv öffnen:" + +#: lib/choose_repository.tcl:294 #, tcl-format msgid "Location %s already exists." msgstr "Projektarchiv »%s« existiert bereits." -#: lib/choose_repository.tcl:158 lib/choose_repository.tcl:165 -#: lib/choose_repository.tcl:172 +#: lib/choose_repository.tcl:300 lib/choose_repository.tcl:307 +#: lib/choose_repository.tcl:314 #, tcl-format msgid "Failed to create repository %s:" msgstr "Projektarchiv »%s« konnte nicht erstellt werden:" -#: lib/choose_repository.tcl:209 lib/choose_repository.tcl:309 +#: lib/choose_repository.tcl:385 lib/choose_repository.tcl:486 msgid "Directory:" msgstr "Verzeichnis:" -#: lib/choose_repository.tcl:238 lib/choose_repository.tcl:363 -#: lib/choose_repository.tcl:834 +#: lib/choose_repository.tcl:415 lib/choose_repository.tcl:544 +#: lib/choose_repository.tcl:1013 msgid "Git Repository" msgstr "Git Projektarchiv" -#: lib/choose_repository.tcl:253 lib/choose_repository.tcl:260 +#: lib/choose_repository.tcl:430 lib/choose_repository.tcl:437 #, tcl-format msgid "Directory %s already exists." msgstr "Verzeichnis »%s« existiert bereits." -#: lib/choose_repository.tcl:265 +#: lib/choose_repository.tcl:442 #, tcl-format msgid "File %s already exists." msgstr "Datei »%s« existiert bereits." -#: lib/choose_repository.tcl:286 +#: lib/choose_repository.tcl:463 msgid "Clone" msgstr "Kopieren" -#: lib/choose_repository.tcl:299 +#: lib/choose_repository.tcl:476 msgid "URL:" msgstr "URL:" -#: lib/choose_repository.tcl:319 +#: lib/choose_repository.tcl:496 msgid "Clone Type:" msgstr "Art der Kopie:" -#: lib/choose_repository.tcl:325 +#: lib/choose_repository.tcl:502 msgid "Standard (Fast, Semi-Redundant, Hardlinks)" -msgstr "" +msgstr "Standard (schnell, teilweise redundant, Hardlinks)" -#: lib/choose_repository.tcl:331 +#: lib/choose_repository.tcl:508 msgid "Full Copy (Slower, Redundant Backup)" -msgstr "" +msgstr "Alles kopieren (langsamer, volle Redundanz)" -#: lib/choose_repository.tcl:337 +#: lib/choose_repository.tcl:514 msgid "Shared (Fastest, Not Recommended, No Backup)" -msgstr "" +msgstr "Verknüpft (schnell, nicht empfohlen, kein Backup)" -#: lib/choose_repository.tcl:369 lib/choose_repository.tcl:418 -#: lib/choose_repository.tcl:560 lib/choose_repository.tcl:630 -#: lib/choose_repository.tcl:840 lib/choose_repository.tcl:848 +#: lib/choose_repository.tcl:550 lib/choose_repository.tcl:597 +#: lib/choose_repository.tcl:738 lib/choose_repository.tcl:808 +#: lib/choose_repository.tcl:1019 lib/choose_repository.tcl:1027 #, tcl-format msgid "Not a Git repository: %s" msgstr "Kein Git-Projektarchiv in »%s« gefunden." -#: lib/choose_repository.tcl:405 +#: lib/choose_repository.tcl:586 msgid "Standard only available for local repository." -msgstr "" +msgstr "Standard ist nur für lokale Projektarchive verfügbar." -#: lib/choose_repository.tcl:409 +#: lib/choose_repository.tcl:590 msgid "Shared only available for local repository." -msgstr "" +msgstr "Verknüpft ist nur für lokale Projektarchive verfügbar." -#: lib/choose_repository.tcl:439 +#: lib/choose_repository.tcl:617 msgid "Failed to configure origin" msgstr "" -#: lib/choose_repository.tcl:451 +#: lib/choose_repository.tcl:629 msgid "Counting objects" msgstr "" -#: lib/choose_repository.tcl:452 +#: lib/choose_repository.tcl:630 msgid "buckets" msgstr "" -#: lib/choose_repository.tcl:476 +#: lib/choose_repository.tcl:654 #, tcl-format msgid "Unable to copy objects/info/alternates: %s" msgstr "" -#: lib/choose_repository.tcl:512 +#: lib/choose_repository.tcl:690 #, tcl-format msgid "Nothing to clone from %s." msgstr "Von »%s« konnte nichts kopiert werden." -#: lib/choose_repository.tcl:514 lib/choose_repository.tcl:728 -#: lib/choose_repository.tcl:740 +#: lib/choose_repository.tcl:692 lib/choose_repository.tcl:906 +#: lib/choose_repository.tcl:918 msgid "The 'master' branch has not been initialized." msgstr "" -#: lib/choose_repository.tcl:527 +#: lib/choose_repository.tcl:705 msgid "Hardlinks are unavailable. Falling back to copying." msgstr "" -#: lib/choose_repository.tcl:539 +#: lib/choose_repository.tcl:717 #, tcl-format msgid "Cloning from %s" msgstr "Kopieren von »%s«" -#: lib/choose_repository.tcl:570 +#: lib/choose_repository.tcl:748 msgid "Copying objects" msgstr "Objektdatenbank kopieren" -#: lib/choose_repository.tcl:571 +#: lib/choose_repository.tcl:749 msgid "KiB" msgstr "KB" -#: lib/choose_repository.tcl:595 +#: lib/choose_repository.tcl:773 #, tcl-format msgid "Unable to copy object: %s" msgstr "Objekt kann nicht kopiert werden: %s" -#: lib/choose_repository.tcl:605 +#: lib/choose_repository.tcl:783 msgid "Linking objects" msgstr "Objekte verlinken" -#: lib/choose_repository.tcl:606 +#: lib/choose_repository.tcl:784 msgid "objects" msgstr "Objekte" -#: lib/choose_repository.tcl:614 +#: lib/choose_repository.tcl:792 #, tcl-format msgid "Unable to hardlink object: %s" msgstr "Objekt kann nicht hartverlinkt werden: %s" -#: lib/choose_repository.tcl:669 +#: lib/choose_repository.tcl:847 msgid "Cannot fetch branches and objects. See console output for details." msgstr "" -#: lib/choose_repository.tcl:680 +#: lib/choose_repository.tcl:858 msgid "Cannot fetch tags. See console output for details." msgstr "" -#: lib/choose_repository.tcl:704 +#: lib/choose_repository.tcl:882 msgid "Cannot determine HEAD. See console output for details." msgstr "" -#: lib/choose_repository.tcl:713 +#: lib/choose_repository.tcl:891 #, tcl-format msgid "Unable to cleanup %s" msgstr "" -#: lib/choose_repository.tcl:719 +#: lib/choose_repository.tcl:897 msgid "Clone failed." msgstr "Kopieren fehlgeschlagen." -#: lib/choose_repository.tcl:726 +#: lib/choose_repository.tcl:904 msgid "No default branch obtained." msgstr "" -#: lib/choose_repository.tcl:737 +#: lib/choose_repository.tcl:915 #, tcl-format msgid "Cannot resolve %s as a commit." msgstr "" -#: lib/choose_repository.tcl:749 +#: lib/choose_repository.tcl:927 msgid "Creating working directory" msgstr "Arbeitskopie erstellen" -#: lib/choose_repository.tcl:750 lib/index.tcl:15 lib/index.tcl:80 +#: lib/choose_repository.tcl:928 lib/index.tcl:15 lib/index.tcl:80 #: lib/index.tcl:149 msgid "files" msgstr "Dateien" -#: lib/choose_repository.tcl:779 +#: lib/choose_repository.tcl:957 msgid "Initial file checkout failed." msgstr "" -#: lib/choose_repository.tcl:795 +#: lib/choose_repository.tcl:973 msgid "Open" msgstr "Öffnen" -#: lib/choose_repository.tcl:805 +#: lib/choose_repository.tcl:983 msgid "Repository:" msgstr "Projektarchiv:" -#: lib/choose_repository.tcl:854 +#: lib/choose_repository.tcl:1033 #, tcl-format msgid "Failed to open repository %s:" msgstr "Projektarchiv »%s« konnte nicht geöffnet werden." @@ -1326,7 +1340,7 @@ msgstr "Festplattenplatz von komprimierten Objekten" #: lib/database.tcl:48 msgid "Packed objects waiting for pruning" -msgstr "Komprimierte Objekte, die zum Löschen vorgesehen sind" +msgstr "Komprimierte Objekte, die zum Entfernen vorgesehen sind" #: lib/database.tcl:49 msgid "Garbage files" @@ -1644,7 +1658,7 @@ msgstr "Auf Dateiänderungsdatum verlassen" #: lib/option.tcl:111 msgid "Prune Tracking Branches During Fetch" -msgstr "Übernahmezweige löschen während Anforderung" +msgstr "Übernahmezweige entfernen während Anforderung" #: lib/option.tcl:112 msgid "Match Tracking Branches" @@ -1673,30 +1687,15 @@ msgstr "pt." #: lib/option.tcl:200 msgid "Preferences" -msgstr "" +msgstr "Einstellungen" #: lib/option.tcl:235 msgid "Failed to completely save options:" msgstr "Optionen konnten nicht gespeichert werden:" -#: lib/remote.tcl:165 -#, fuzzy -msgid "Prune from" -msgstr "Löschen von »%s«" - -#: lib/remote.tcl:170 -#, fuzzy -msgid "Fetch from" -msgstr "Von »%s« anfordern" - -#: lib/remote.tcl:213 -#, fuzzy -msgid "Push to" -msgstr "Nach »%s« ausliefern" - #: lib/remote_branch_delete.tcl:29 lib/remote_branch_delete.tcl:34 msgid "Delete Remote Branch" -msgstr "Zweig im Projektarchiv der Gegenseite löschen" +msgstr "Zweig im anderen Projektarchiv löschen" #: lib/remote_branch_delete.tcl:47 msgid "From Repository" @@ -1704,7 +1703,7 @@ msgstr "Von Projektarchiv" #: lib/remote_branch_delete.tcl:50 lib/transport.tcl:123 msgid "Remote:" -msgstr "Gegenseite:" +msgstr "Anderes Archiv:" #: lib/remote_branch_delete.tcl:66 lib/transport.tcl:138 msgid "Arbitrary URL:" @@ -1780,11 +1779,23 @@ msgstr "Kein Projektarchiv ausgewählt." msgid "Scanning %s..." msgstr "»%s« laden..." -#: lib/shortcut.tcl:26 lib/shortcut.tcl:74 -msgid "Cannot write script:" -msgstr "Fehler beim Schreiben des Scripts:" +#: lib/remote.tcl:165 +msgid "Prune from" +msgstr "Entfernen von" -#: lib/shortcut.tcl:149 +#: lib/remote.tcl:170 +msgid "Fetch from" +msgstr "Anfordern von" + +#: lib/remote.tcl:213 +msgid "Push to" +msgstr "Versenden nach" + +#: lib/shortcut.tcl:20 lib/shortcut.tcl:61 +msgid "Cannot write shortcut:" +msgstr "Fehler beim Schreiben der Verknüpfung:" + +#: lib/shortcut.tcl:136 msgid "Cannot write icon:" msgstr "Fehler beim Erstellen des Icons:" @@ -1806,31 +1817,31 @@ msgstr "Neue Änderungen von »%s« holen" #: lib/transport.tcl:18 #, tcl-format msgid "remote prune %s" -msgstr "" +msgstr "Entfernen von »%s« im anderen Archiv" #: lib/transport.tcl:19 #, tcl-format msgid "Pruning tracking branches deleted from %s" -msgstr "Übernahmezweige löschen, die in »%s« gelöscht wurden" +msgstr "Übernahmezweige entfernen, die in »%s« gelöscht wurden" #: lib/transport.tcl:25 lib/transport.tcl:71 #, tcl-format msgid "push %s" -msgstr "»%s« ausliefern..." +msgstr "»%s« versenden..." #: lib/transport.tcl:26 #, tcl-format msgid "Pushing changes to %s" -msgstr "Änderungen nach »%s« ausliefern" +msgstr "Änderungen nach »%s« versenden" #: lib/transport.tcl:72 #, tcl-format msgid "Pushing %s %s to %s" -msgstr "%s %s nach %s ausliefern" +msgstr "%s %s nach %s versenden" #: lib/transport.tcl:89 msgid "Push Branches" -msgstr "Zweige ausliefern" +msgstr "Zweige versenden" #: lib/transport.tcl:103 msgid "Source Branches" @@ -1857,6 +1868,9 @@ msgstr "Kompaktes Datenformat benutzen (für langsame Netzverbindungen)" msgid "Include tags" msgstr "Mit Markierungen übertragen" +#~ msgid "Next >" +#~ msgstr "Weiter >" + #~ msgid "Fetch" #~ msgstr "Anfordern" diff --git a/po/glossary/de.po b/po/glossary/de.po index 054cf4df5a..c94786c6ab 100644 --- a/po/glossary/de.po +++ b/po/glossary/de.po @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: git-gui glossary\n" -"POT-Creation-Date: 2007-10-05 22:30+0200\n" -"PO-Revision-Date: 2007-10-05 22:32+0200\n" +"POT-Creation-Date: 2007-10-19 21:43+0200\n" +"PO-Revision-Date: 2007-10-20 15:24+0200\n" "Last-Translator: Christian Stimming \n" "Language-Team: German \n" "MIME-Version: 1.0\n" @@ -108,9 +108,9 @@ msgstr "zusammenführen" msgid "message" msgstr "Beschreibung (Meldung?, Nachricht?; Source Safe: Kommentar)" -#. "" +#. "Deletes all stale tracking branches under . These stale branches have already been removed from the remote repository referenced by , but are still locally available in 'remotes/'." msgid "prune" -msgstr "löschen" +msgstr "entfernen" #. "Pulling a branch means to fetch it and merge it." msgid "pull" @@ -118,12 +118,16 @@ msgstr "übernehmen (ziehen?)" #. "Pushing a branch means to get the branch's head ref from a remote repository, and ... (well, can someone please explain it for mere mortals?)" msgid "push" -msgstr "ausliefern (hochladen? verschicken? schieben?)" +msgstr "versenden (ausliefern? hochladen? verschicken? schieben?)" #. "" msgid "redo" msgstr "wiederholen" +#. "An other repository ('remote'). One might have a set of remotes whose branches one tracks." +msgid "remote" +msgstr "Andere Archive (Gegenseite?, Entfernte?, Server?)" + #. "A collection of refs (?) together with an object database containing all objects which are reachable from the refs... (oops, you've lost me here. Again, please an explanation for mere mortals?)" msgid "repository" msgstr "Projektarchiv" From 2005dbe2a4e3eba5ecddb7d3c46339d2bc1241d4 Mon Sep 17 00:00:00 2001 From: Julian Phillips Date: Sat, 20 Oct 2007 17:15:38 +0100 Subject: [PATCH 0229/1490] fast-import: Fix argument order to die in file_change_m The arguments to the "Not a blob" die call in file_change_m were transposed, so that the command was printed as the type, and the type as the command. Switch them around so that the error message comes out correctly. Signed-off-by: Julian Phillips Signed-off-by: Shawn O. Pearce --- fast-import.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fast-import.c b/fast-import.c index 078079d404..c07e3d8ef0 100644 --- a/fast-import.c +++ b/fast-import.c @@ -1859,7 +1859,7 @@ static void file_change_m(struct branch *b) } else if (oe) { if (oe->type != OBJ_BLOB) die("Not a blob (actually a %s): %s", - command_buf.buf, typename(oe->type)); + typename(oe->type), command_buf.buf); } else { enum object_type type = sha1_object_info(sha1, NULL); if (type < 0) From 0b8293f6776a7fc600c924ca71e4bba81d396409 Mon Sep 17 00:00:00 2001 From: Joakim Tjernlund Date: Sat, 20 Oct 2007 21:31:46 +0200 Subject: [PATCH 0230/1490] Improve receive-pack error message about funny ref creation receive-pack is only executed remotely so when reporting errors, say so. Signed-off-by: Joakim Tjernlund Signed-off-by: Shawn O. Pearce --- receive-pack.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/receive-pack.c b/receive-pack.c index d3c422be58..1521d0b2de 100644 --- a/receive-pack.c +++ b/receive-pack.c @@ -166,7 +166,7 @@ static const char *update(struct command *cmd) struct ref_lock *lock; if (!prefixcmp(name, "refs/") && check_ref_format(name + 5)) { - error("refusing to create funny ref '%s' locally", name); + error("refusing to create funny ref '%s' remotely", name); return "funny refname"; } From 43db492a8eb701dd157f88ae9ca38d366c280761 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sat, 20 Oct 2007 08:21:34 +0100 Subject: [PATCH 0231/1490] Deduce exec_path also from calls to git with a relative path There is already logic in the git wrapper to deduce the exec_path from argv[0], when the git wrapper was called with an absolute path. Extend that logic to handle relative paths as well. For example, when you call "../../hello/world/git", it will not turn "../../hello/world" into an absolute path, and use that. Initial implementation by Scott R Parish. Signed-off-by: Johannes Schindelin Signed-off-by: Shawn O. Pearce --- git.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/git.c b/git.c index 9eaca1d671..853e66cddb 100644 --- a/git.c +++ b/git.c @@ -409,13 +409,14 @@ int main(int argc, const char **argv) /* * Take the basename of argv[0] as the command * name, and the dirname as the default exec_path - * if it's an absolute path and we don't have - * anything better. + * if we don't have anything better. */ if (slash) { *slash++ = 0; if (*cmd == '/') exec_path = cmd; + else + exec_path = xstrdup(make_absolute_path(cmd)); cmd = slash; } From ca5bb5d5390e4ec709ca3e11c451c58a836d4ee6 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Sat, 20 Oct 2007 16:03:49 -0400 Subject: [PATCH 0232/1490] Define compat version of mkdtemp for systems lacking it Solaris 9 doesn't have mkdtemp() so we need to emulate it for the rsync transport implementation. Since Solaris 9 is lacking this function we can also reasonably assume it is not available on Solaris 8 either. The new Makfile definition NO_MKDTEMP can be set to enable the git compat version. Signed-off-by: Shawn O. Pearce --- Makefile | 8 ++++++++ compat/mkdtemp.c | 8 ++++++++ git-compat-util.h | 5 +++++ 3 files changed, 21 insertions(+) create mode 100644 compat/mkdtemp.c diff --git a/Makefile b/Makefile index bb4873d754..6287418df3 100644 --- a/Makefile +++ b/Makefile @@ -38,6 +38,8 @@ all:: # # Define NO_SETENV if you don't have setenv in the C library. # +# Define NO_MKDTEMP if you don't have mkdtemp in the C library. +# # Define NO_SYMLINK_HEAD if you never want .git/HEAD to be a symbolic link. # Enable it on Windows. By default, symrefs are still used. # @@ -414,12 +416,14 @@ ifeq ($(uname_S),SunOS) NEEDS_LIBICONV = YesPlease NO_UNSETENV = YesPlease NO_SETENV = YesPlease + NO_MKDTEMP = YesPlease NO_C99_FORMAT = YesPlease NO_STRTOUMAX = YesPlease endif ifeq ($(uname_R),5.9) NO_UNSETENV = YesPlease NO_SETENV = YesPlease + NO_MKDTEMP = YesPlease NO_C99_FORMAT = YesPlease NO_STRTOUMAX = YesPlease endif @@ -610,6 +614,10 @@ ifdef NO_SETENV COMPAT_CFLAGS += -DNO_SETENV COMPAT_OBJS += compat/setenv.o endif +ifdef NO_MKDTEMP + COMPAT_CFLAGS += -DNO_MKDTEMP + COMPAT_OBJS += compat/mkdtemp.o +endif ifdef NO_UNSETENV COMPAT_CFLAGS += -DNO_UNSETENV COMPAT_OBJS += compat/unsetenv.o diff --git a/compat/mkdtemp.c b/compat/mkdtemp.c new file mode 100644 index 0000000000..34d4b49818 --- /dev/null +++ b/compat/mkdtemp.c @@ -0,0 +1,8 @@ +#include "../git-compat-util.h" + +char *gitmkdtemp(char *template) +{ + if (!mktemp(template) || mkdir(template, 0700)) + return NULL; + return template; +} diff --git a/git-compat-util.h b/git-compat-util.h index f23d934f66..474f1d1ffb 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -147,6 +147,11 @@ extern ssize_t git_pread(int fd, void *buf, size_t count, off_t offset); extern int gitsetenv(const char *, const char *, int); #endif +#ifdef NO_MKDTEMP +#define mkdtemp gitmkdtemp +extern char *gitmkdtemp(char *); +#endif + #ifdef NO_UNSETENV #define unsetenv gitunsetenv extern void gitunsetenv(const char *); From e5ef6f952a13342065d44bab53999e8d8529cc3b Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sun, 21 Oct 2007 12:58:42 +1000 Subject: [PATCH 0233/1490] gitk: Fix "can't unset prevlines(...)" Tcl error This fixes the error reported by Michele Ballabio, where gitk will throw a Tcl error "can't unset prevlines(...)" when displaying a commit that has a parent commit listed more than once, and the commit is the first child of that parent. The problem was basically that we had two variables, prevlines and lineends, and were relying on the invariant that prevlines($id) was set iff $id was in the lineends($r) list for some $r. But having a duplicate parent breaks that invariant since we end up with the parent listed twice in lineends. This fixes it by simplifying the logic to use only a single variable, lineend. It also rearranges things a little so that we don't try to draw the line for the duplicated parent twice. Signed-off-by: Paul Mackerras --- gitk | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/gitk b/gitk index f910cba8bf..41a1c69e19 100755 --- a/gitk +++ b/gitk @@ -3695,34 +3695,23 @@ proc drawcommits {row {endrow {}}} { drawcmitrow $r if {$r == $er} break set nextid [lindex $displayorder [expr {$r + 1}]] - if {$wasdrawn && [info exists iddrawn($nextid)]} { - catch {unset prevlines} - continue - } + if {$wasdrawn && [info exists iddrawn($nextid)]} continue drawparentlinks $id $r - if {[info exists lineends($r)]} { - foreach lid $lineends($r) { - unset prevlines($lid) - } - } set rowids [lindex $rowidlist $r] foreach lid $rowids { if {$lid eq {}} continue + if {[info exists lineend($lid)] && $lineend($lid) > $r} continue if {$lid eq $id} { # see if this is the first child of any of its parents foreach p [lindex $parentlist $r] { if {[lsearch -exact $rowids $p] < 0} { # make this line extend up to the child - set le [drawlineseg $p $r $er 0] - lappend lineends($le) $p - set prevlines($p) 1 + set lineend($p) [drawlineseg $p $r $er 0] } } - } elseif {![info exists prevlines($lid)]} { - set le [drawlineseg $lid $r $er 1] - lappend lineends($le) $lid - set prevlines($lid) 1 + } else { + set lineend($lid) [drawlineseg $lid $r $er 1] } } } From 98158e9cfd2808613f305bf587ce697762c884bb Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Fri, 19 Oct 2007 21:47:53 +0200 Subject: [PATCH 0234/1490] Change git_connect() to return a struct child_process instead of a pid_t. This prepares the API of git_connect() and finish_connect() to operate on a struct child_process. Currently, we just use that object as a placeholder for the pid that we used to return. A follow-up patch will change the implementation of git_connect() and finish_connect() to make full use of the object. Old code had early-return-on-error checks at the calling sites of git_connect(), but since git_connect() dies on errors anyway, these checks were removed. [sp: Corrected style nit of "conn == NULL" to "!conn"] Signed-off-by: Johannes Sixt Signed-off-by: Shawn O. Pearce --- builtin-archive.c | 8 +++----- builtin-fetch-pack.c | 8 +++----- cache.h | 4 ++-- connect.c | 31 +++++++++++++++++-------------- peek-remote.c | 8 +++----- send-pack.c | 8 +++----- transport.c | 9 ++------- 7 files changed, 33 insertions(+), 43 deletions(-) diff --git a/builtin-archive.c b/builtin-archive.c index 04385dea05..76f8d3d83d 100644 --- a/builtin-archive.c +++ b/builtin-archive.c @@ -30,7 +30,7 @@ static int run_remote_archiver(const char *remote, int argc, { char *url, buf[LARGE_PACKET_MAX]; int fd[2], i, len, rv; - pid_t pid; + struct child_process *conn; const char *exec = "git-upload-archive"; int exec_at = 0; @@ -46,9 +46,7 @@ static int run_remote_archiver(const char *remote, int argc, } url = xstrdup(remote); - pid = git_connect(fd, url, exec, 0); - if (pid < 0) - return pid; + conn = git_connect(fd, url, exec, 0); for (i = 1; i < argc; i++) { if (i == exec_at) @@ -76,7 +74,7 @@ static int run_remote_archiver(const char *remote, int argc, rv = recv_sideband("archive", fd[0], 1, 2); close(fd[0]); close(fd[1]); - rv |= finish_connect(pid); + rv |= finish_connect(conn); return !!rv; } diff --git a/builtin-fetch-pack.c b/builtin-fetch-pack.c index 8f25d509a0..f56592fea7 100644 --- a/builtin-fetch-pack.c +++ b/builtin-fetch-pack.c @@ -762,7 +762,7 @@ struct ref *fetch_pack(struct fetch_pack_args *my_args, { int i, ret; int fd[2]; - pid_t pid; + struct child_process *conn; struct ref *ref; struct stat st; @@ -773,16 +773,14 @@ struct ref *fetch_pack(struct fetch_pack_args *my_args, st.st_mtime = 0; } - pid = git_connect(fd, (char *)dest, uploadpack, + conn = git_connect(fd, (char *)dest, uploadpack, args.verbose ? CONNECT_VERBOSE : 0); - if (pid < 0) - return NULL; if (heads && nr_heads) nr_heads = remove_duplicates(nr_heads, heads); ref = do_fetch_pack(fd, nr_heads, heads, pack_lockfile); close(fd[0]); close(fd[1]); - ret = finish_connect(pid); + ret = finish_connect(conn); if (!ret && nr_heads) { /* If the heads to pull were given, we should have diff --git a/cache.h b/cache.h index 27485d36c2..bfffa05dff 100644 --- a/cache.h +++ b/cache.h @@ -503,8 +503,8 @@ struct ref { #define REF_TAGS (1u << 2) #define CONNECT_VERBOSE (1u << 0) -extern pid_t git_connect(int fd[2], char *url, const char *prog, int flags); -extern int finish_connect(pid_t pid); +extern struct child_process *git_connect(int fd[2], char *url, const char *prog, int flags); +extern int finish_connect(struct child_process *conn); extern int path_match(const char *path, int nr, char **match); extern int get_ack(int fd, unsigned char *result_sha1); extern struct ref **get_remote_heads(int in, struct ref **list, int nr_match, char **match, unsigned int flags); diff --git a/connect.c b/connect.c index 3d5c4ab755..a6d7b13759 100644 --- a/connect.c +++ b/connect.c @@ -468,21 +468,22 @@ char *get_port(char *host) } /* - * This returns 0 if the transport protocol does not need fork(2), - * or a process id if it does. Once done, finish the connection + * This returns NULL if the transport protocol does not need fork(2), or a + * struct child_process object if it does. Once done, finish the connection * with finish_connect() with the value returned from this function - * (it is safe to call finish_connect() with 0 to support the former + * (it is safe to call finish_connect() with NULL to support the former * case). * - * Does not return a negative value on error; it just dies. + * If it returns, the connect is successful; it just dies on errors. */ -pid_t git_connect(int fd[2], char *url, const char *prog, int flags) +struct child_process *git_connect(int fd[2], char *url, + const char *prog, int flags) { char *host, *path = url; char *end; int c; int pipefd[2][2]; - pid_t pid; + struct child_process *conn; enum protocol protocol = PROTO_LOCAL; int free_path = 0; char *port = NULL; @@ -568,15 +569,16 @@ pid_t git_connect(int fd[2], char *url, const char *prog, int flags) free(target_host); if (free_path) free(path); - return 0; + return NULL; } if (pipe(pipefd[0]) < 0 || pipe(pipefd[1]) < 0) die("unable to create pipe pair for communication"); - pid = fork(); - if (pid < 0) + conn = xcalloc(1, sizeof(*conn)); + conn->pid = fork(); + if (conn->pid < 0) die("unable to fork"); - if (!pid) { + if (!conn->pid) { struct strbuf cmd; strbuf_init(&cmd, MAX_CMD_LEN); @@ -625,17 +627,18 @@ pid_t git_connect(int fd[2], char *url, const char *prog, int flags) close(pipefd[1][0]); if (free_path) free(path); - return pid; + return conn; } -int finish_connect(pid_t pid) +int finish_connect(struct child_process *conn) { - if (pid == 0) + if (!conn) return 0; - while (waitpid(pid, NULL, 0) < 0) { + while (waitpid(conn->pid, NULL, 0) < 0) { if (errno != EINTR) return -1; } + free(conn); return 0; } diff --git a/peek-remote.c b/peek-remote.c index ceb787170e..8d20f7c9c6 100644 --- a/peek-remote.c +++ b/peek-remote.c @@ -25,7 +25,7 @@ int main(int argc, char **argv) int i, ret; char *dest = NULL; int fd[2]; - pid_t pid; + struct child_process *conn; int nongit = 0; unsigned flags = 0; @@ -64,12 +64,10 @@ int main(int argc, char **argv) if (!dest || i != argc - 1) usage(peek_remote_usage); - pid = git_connect(fd, dest, uploadpack, 0); - if (pid < 0) - return 1; + conn = git_connect(fd, dest, uploadpack, 0); ret = peek_remote(fd, flags); close(fd[0]); close(fd[1]); - ret |= finish_connect(pid); + ret |= finish_connect(conn); return !!ret; } diff --git a/send-pack.c b/send-pack.c index 7b776243e6..147f44b01d 100644 --- a/send-pack.c +++ b/send-pack.c @@ -365,7 +365,7 @@ int main(int argc, char **argv) char *dest = NULL; char **heads = NULL; int fd[2], ret; - pid_t pid; + struct child_process *conn; char *remote_name = NULL; struct remote *remote = NULL; @@ -433,12 +433,10 @@ int main(int argc, char **argv) } } - pid = git_connect(fd, dest, receivepack, verbose ? CONNECT_VERBOSE : 0); - if (pid < 0) - return 1; + conn = git_connect(fd, dest, receivepack, verbose ? CONNECT_VERBOSE : 0); ret = send_pack(fd[0], fd[1], remote, nr_heads, heads); close(fd[0]); close(fd[1]); - ret |= finish_connect(pid); + ret |= finish_connect(conn); return !!ret; } diff --git a/transport.c b/transport.c index 400af71c76..5132d289da 100644 --- a/transport.c +++ b/transport.c @@ -601,18 +601,13 @@ static struct ref *get_refs_via_connect(const struct transport *transport) struct git_transport_data *data = transport->data; struct ref *refs; int fd[2]; - pid_t pid; char *dest = xstrdup(transport->url); - - pid = git_connect(fd, dest, data->uploadpack, 0); - - if (pid < 0) - die("Failed to connect to \"%s\"", transport->url); + struct child_process *conn = git_connect(fd, dest, data->uploadpack, 0); get_remote_heads(fd[0], &refs, 0, NULL, 0); packet_flush(fd[1]); - finish_connect(pid); + finish_connect(conn); free(dest); From f364cb88238bbb468b0e076c53a055bcb8603b60 Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Fri, 19 Oct 2007 21:47:54 +0200 Subject: [PATCH 0235/1490] Use start_command() in git_connect() instead of explicit fork/exec. The child process handling is delegated to start_command() and finish_command(). Signed-off-by: Johannes Sixt Signed-off-by: Shawn O. Pearce --- connect.c | 99 ++++++++++++++++++++++++++----------------------------- 1 file changed, 46 insertions(+), 53 deletions(-) diff --git a/connect.c b/connect.c index a6d7b13759..44e423dafd 100644 --- a/connect.c +++ b/connect.c @@ -482,11 +482,12 @@ struct child_process *git_connect(int fd[2], char *url, char *host, *path = url; char *end; int c; - int pipefd[2][2]; struct child_process *conn; enum protocol protocol = PROTO_LOCAL; int free_path = 0; char *port = NULL; + const char **arg; + struct strbuf cmd; /* Without this we cannot rely on waitpid() to tell * what happened to our children. @@ -572,59 +573,52 @@ struct child_process *git_connect(int fd[2], char *url, return NULL; } - if (pipe(pipefd[0]) < 0 || pipe(pipefd[1]) < 0) - die("unable to create pipe pair for communication"); conn = xcalloc(1, sizeof(*conn)); - conn->pid = fork(); - if (conn->pid < 0) - die("unable to fork"); - if (!conn->pid) { - struct strbuf cmd; - strbuf_init(&cmd, MAX_CMD_LEN); - strbuf_addstr(&cmd, prog); - strbuf_addch(&cmd, ' '); - sq_quote_buf(&cmd, path); - if (cmd.len >= MAX_CMD_LEN) - die("command line too long"); + strbuf_init(&cmd, MAX_CMD_LEN); + strbuf_addstr(&cmd, prog); + strbuf_addch(&cmd, ' '); + sq_quote_buf(&cmd, path); + if (cmd.len >= MAX_CMD_LEN) + die("command line too long"); - dup2(pipefd[1][0], 0); - dup2(pipefd[0][1], 1); - close(pipefd[0][0]); - close(pipefd[0][1]); - close(pipefd[1][0]); - close(pipefd[1][1]); - if (protocol == PROTO_SSH) { - const char *ssh, *ssh_basename; - ssh = getenv("GIT_SSH"); - if (!ssh) ssh = "ssh"; - ssh_basename = strrchr(ssh, '/'); - if (!ssh_basename) - ssh_basename = ssh; - else - ssh_basename++; + conn->in = conn->out = -1; + conn->argv = arg = xcalloc(6, sizeof(*arg)); + if (protocol == PROTO_SSH) { + const char *ssh = getenv("GIT_SSH"); + if (!ssh) ssh = "ssh"; - if (!port) - execlp(ssh, ssh_basename, host, cmd.buf, NULL); - else - execlp(ssh, ssh_basename, "-p", port, host, - cmd.buf, NULL); + *arg++ = ssh; + if (port) { + *arg++ = "-p"; + *arg++ = port; } - else { - unsetenv(ALTERNATE_DB_ENVIRONMENT); - unsetenv(DB_ENVIRONMENT); - unsetenv(GIT_DIR_ENVIRONMENT); - unsetenv(GIT_WORK_TREE_ENVIRONMENT); - unsetenv(GRAFT_ENVIRONMENT); - unsetenv(INDEX_ENVIRONMENT); - execlp("sh", "sh", "-c", cmd.buf, NULL); - } - die("exec failed"); + *arg++ = host; } - fd[0] = pipefd[0][0]; - fd[1] = pipefd[1][1]; - close(pipefd[0][1]); - close(pipefd[1][0]); + else { + /* remove these from the environment */ + const char *env[] = { + ALTERNATE_DB_ENVIRONMENT, + DB_ENVIRONMENT, + GIT_DIR_ENVIRONMENT, + GIT_WORK_TREE_ENVIRONMENT, + GRAFT_ENVIRONMENT, + INDEX_ENVIRONMENT, + NULL + }; + conn->env = env; + *arg++ = "sh"; + *arg++ = "-c"; + } + *arg++ = cmd.buf; + *arg = NULL; + + if (start_command(conn)) + die("unable to fork"); + + fd[0] = conn->out; /* read from child's stdout */ + fd[1] = conn->in; /* write to child's stdin */ + strbuf_release(&cmd); if (free_path) free(path); return conn; @@ -632,13 +626,12 @@ struct child_process *git_connect(int fd[2], char *url, int finish_connect(struct child_process *conn) { + int code; if (!conn) return 0; - while (waitpid(conn->pid, NULL, 0) < 0) { - if (errno != EINTR) - return -1; - } + code = finish_command(conn); + free(conn->argv); free(conn); - return 0; + return code; } From dc1bfdcd1a8af81885f1831c5e6dcfe5cf61372e Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Fri, 19 Oct 2007 21:47:55 +0200 Subject: [PATCH 0236/1490] Use start_command() to run content filters instead of explicit fork/exec. The previous code already used finish_command() to wait for the process to terminate, but did not use start_command() to run it. Signed-off-by: Johannes Sixt Signed-off-by: Shawn O. Pearce --- convert.c | 30 +++++++----------------------- 1 file changed, 7 insertions(+), 23 deletions(-) diff --git a/convert.c b/convert.c index aa95834eb3..d83c2fcc5e 100644 --- a/convert.c +++ b/convert.c @@ -199,34 +199,18 @@ static int filter_buffer(const char *path, const char *src, * Spawn cmd and feed the buffer contents through its stdin. */ struct child_process child_process; - int pipe_feed[2]; int write_err, status; + const char *argv[] = { "sh", "-c", cmd, NULL }; memset(&child_process, 0, sizeof(child_process)); + child_process.argv = argv; + child_process.in = -1; - if (pipe(pipe_feed) < 0) { - error("cannot create pipe to run external filter %s", cmd); - return 1; - } + if (start_command(&child_process)) + return error("cannot fork to run external filter %s", cmd); - child_process.pid = fork(); - if (child_process.pid < 0) { - error("cannot fork to run external filter %s", cmd); - close(pipe_feed[0]); - close(pipe_feed[1]); - return 1; - } - if (!child_process.pid) { - dup2(pipe_feed[0], 0); - close(pipe_feed[0]); - close(pipe_feed[1]); - execlp("sh", "sh", "-c", cmd, NULL); - return 1; - } - close(pipe_feed[0]); - - write_err = (write_in_full(pipe_feed[1], src, size) < 0); - if (close(pipe_feed[1])) + write_err = (write_in_full(child_process.in, src, size) < 0); + if (close(child_process.in)) write_err = 1; if (write_err) error("cannot feed the input to external filter %s", cmd); From d5535ec75ce1cdf57ef52b57c58c548121ce99ba Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Fri, 19 Oct 2007 21:47:56 +0200 Subject: [PATCH 0237/1490] Use run_command() to spawn external diff programs instead of fork/exec. Signed-off-by: Johannes Sixt Signed-off-by: Shawn O. Pearce --- diff.c | 38 +++----------------------------------- 1 file changed, 3 insertions(+), 35 deletions(-) diff --git a/diff.c b/diff.c index 6648e01521..30b7544171 100644 --- a/diff.c +++ b/diff.c @@ -9,6 +9,7 @@ #include "xdiff-interface.h" #include "color.h" #include "attr.h" +#include "run-command.h" #ifdef NO_FAST_WORKING_DIRECTORY #define FAST_WORKING_DIRECTORY 0 @@ -1748,40 +1749,6 @@ static void remove_tempfile_on_signal(int signo) raise(signo); } -static int spawn_prog(const char *pgm, const char **arg) -{ - pid_t pid; - int status; - - fflush(NULL); - pid = fork(); - if (pid < 0) - die("unable to fork"); - if (!pid) { - execvp(pgm, (char *const*) arg); - exit(255); - } - - while (waitpid(pid, &status, 0) < 0) { - if (errno == EINTR) - continue; - return -1; - } - - /* Earlier we did not check the exit status because - * diff exits non-zero if files are different, and - * we are not interested in knowing that. It was a - * mistake which made it harder to quit a diff-* - * session that uses the git-apply-patch-script as - * the GIT_EXTERNAL_DIFF. A custom GIT_EXTERNAL_DIFF - * should also exit non-zero only when it wants to - * abort the entire diff-* session. - */ - if (WIFEXITED(status) && !WEXITSTATUS(status)) - return 0; - return -1; -} - /* An external diff command takes: * * diff-cmd name infile1 infile1-sha1 infile1-mode \ @@ -1834,7 +1801,8 @@ static void run_external_diff(const char *pgm, *arg++ = name; } *arg = NULL; - retval = spawn_prog(pgm, spawn_arg); + fflush(NULL); + retval = run_command_v_opt(spawn_arg, 0); remove_tempfile(); if (retval) { fprintf(stderr, "external diff died, stopping at %s.\n", name); From 477822c35dbf3d5f16fce1425638e761e60ede3d Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Fri, 19 Oct 2007 21:47:57 +0200 Subject: [PATCH 0238/1490] Use start_comand() in builtin-fetch-pack.c instead of explicit fork/exec. Signed-off-by: Johannes Sixt Signed-off-by: Shawn O. Pearce --- builtin-fetch-pack.c | 56 +++++++++++++------------------------------- 1 file changed, 16 insertions(+), 40 deletions(-) diff --git a/builtin-fetch-pack.c b/builtin-fetch-pack.c index f56592fea7..871b7042e7 100644 --- a/builtin-fetch-pack.c +++ b/builtin-fetch-pack.c @@ -7,6 +7,7 @@ #include "pack.h" #include "sideband.h" #include "fetch-pack.h" +#include "run-command.h" static int transfer_unpack_limit = -1; static int fetch_unpack_limit = -1; @@ -491,18 +492,19 @@ static pid_t setup_sideband(int fd[2], int xd[2]) static int get_pack(int xd[2], char **pack_lockfile) { - int status; - pid_t pid, side_pid; + pid_t side_pid; int fd[2]; const char *argv[20]; char keep_arg[256]; char hdr_arg[256]; const char **av; int do_keep = args.keep_pack; - int keep_pipe[2]; + struct child_process cmd; side_pid = setup_sideband(fd, xd); + memset(&cmd, 0, sizeof(cmd)); + cmd.argv = argv; av = argv; *hdr_arg = 0; if (!args.keep_pack && unpack_limit) { @@ -519,8 +521,8 @@ static int get_pack(int xd[2], char **pack_lockfile) } if (do_keep) { - if (pack_lockfile && pipe(keep_pipe)) - die("fetch-pack: pipe setup failure: %s", strerror(errno)); + if (pack_lockfile) + cmd.out = -1; *av++ = "index-pack"; *av++ = "--stdin"; if (!args.quiet && !args.no_progress) @@ -544,43 +546,17 @@ static int get_pack(int xd[2], char **pack_lockfile) *av++ = hdr_arg; *av++ = NULL; - pid = fork(); - if (pid < 0) + cmd.in = fd[0]; + cmd.git_cmd = 1; + if (start_command(&cmd)) die("fetch-pack: unable to fork off %s", argv[0]); - if (!pid) { - dup2(fd[0], 0); - if (do_keep && pack_lockfile) { - dup2(keep_pipe[1], 1); - close(keep_pipe[0]); - close(keep_pipe[1]); - } - close(fd[0]); - close(fd[1]); - execv_git_cmd(argv); - die("%s exec failed", argv[0]); - } - close(fd[0]); close(fd[1]); - if (do_keep && pack_lockfile) { - close(keep_pipe[1]); - *pack_lockfile = index_pack_lockfile(keep_pipe[0]); - close(keep_pipe[0]); - } - while (waitpid(pid, &status, 0) < 0) { - if (errno != EINTR) - die("waiting for %s: %s", argv[0], strerror(errno)); - } - if (WIFEXITED(status)) { - int code = WEXITSTATUS(status); - if (code) - die("%s died with error code %d", argv[0], code); - return 0; - } - if (WIFSIGNALED(status)) { - int sig = WTERMSIG(status); - die("%s died of signal %d", argv[0], sig); - } - die("%s died of unnatural causes %d", argv[0], status); + if (do_keep && pack_lockfile) + *pack_lockfile = index_pack_lockfile(cmd.out); + + if (finish_command(&cmd)) + die("%s failed", argv[0]); + return 0; } static struct ref *do_fetch_pack(int fd[2], From f3b33f1d220056243d3c1da154d3859410630189 Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Fri, 19 Oct 2007 21:47:58 +0200 Subject: [PATCH 0239/1490] Have start_command() create a pipe to read the stderr of the child. This adds another stanza that allocates a pipe that is connected to the child's stderr and that the caller can read from. In order to request this pipe, the caller sets cmd->err to -1. The implementation is not exactly modeled after the stdout case: For stdout the caller can supply an existing file descriptor, but this facility is nowhere needed in the stderr case. Additionally, the caller is required to close cmd->err. Signed-off-by: Johannes Sixt Signed-off-by: Shawn O. Pearce --- run-command.c | 26 ++++++++++++++++++++++++-- run-command.h | 1 + 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/run-command.c b/run-command.c index 7e779d33ee..d00c03bbdf 100644 --- a/run-command.c +++ b/run-command.c @@ -17,8 +17,8 @@ static inline void dup_devnull(int to) int start_command(struct child_process *cmd) { - int need_in, need_out; - int fdin[2], fdout[2]; + int need_in, need_out, need_err; + int fdin[2], fdout[2], fderr[2]; need_in = !cmd->no_stdin && cmd->in < 0; if (need_in) { @@ -41,12 +41,26 @@ int start_command(struct child_process *cmd) cmd->close_out = 1; } + need_err = cmd->err < 0; + if (need_err) { + if (pipe(fderr) < 0) { + if (need_in) + close_pair(fdin); + if (need_out) + close_pair(fdout); + return -ERR_RUN_COMMAND_PIPE; + } + cmd->err = fderr[0]; + } + cmd->pid = fork(); if (cmd->pid < 0) { if (need_in) close_pair(fdin); if (need_out) close_pair(fdout); + if (need_err) + close_pair(fderr); return -ERR_RUN_COMMAND_FORK; } @@ -73,6 +87,11 @@ int start_command(struct child_process *cmd) close(cmd->out); } + if (need_err) { + dup2(fderr[1], 2); + close_pair(fderr); + } + if (cmd->dir && chdir(cmd->dir)) die("exec %s: cd to %s failed (%s)", cmd->argv[0], cmd->dir, strerror(errno)); @@ -102,6 +121,9 @@ int start_command(struct child_process *cmd) else if (cmd->out > 1) close(cmd->out); + if (need_err) + close(fderr[1]); + return 0; } diff --git a/run-command.h b/run-command.h index 7958eb1e0b..35b9fb61f1 100644 --- a/run-command.h +++ b/run-command.h @@ -16,6 +16,7 @@ struct child_process { pid_t pid; int in; int out; + int err; const char *dir; const char *const *env; unsigned close_in:1; From cc41fa8da9b9e9d23221d3be47a80409a89732d4 Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Fri, 19 Oct 2007 21:47:59 +0200 Subject: [PATCH 0240/1490] upload-pack: Use start_command() to run pack-objects in create_pack_file(). This gets rid of an explicit fork/exec. Since upload-pack has to coordinate two processes (rev-list and pack-objects), we cannot use the normal finish_command(), but have to monitor the processes explicitly. Hence, the waitpid() call remains. Signed-off-by: Johannes Sixt Signed-off-by: Shawn O. Pearce --- upload-pack.c | 105 +++++++++++++++++++++----------------------------- 1 file changed, 44 insertions(+), 61 deletions(-) diff --git a/upload-pack.c b/upload-pack.c index fe96ef15c4..5c0c0cc8e5 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -9,6 +9,7 @@ #include "diff.h" #include "revision.h" #include "list-objects.h" +#include "run-command.h" static const char upload_pack_usage[] = "git-upload-pack [--strict] [--timeout=nn] "; @@ -98,16 +99,18 @@ static void show_edge(struct commit *commit) static void create_pack_file(void) { - /* Pipes between rev-list to pack-objects, pack-objects to us - * and pack-objects error stream for progress bar. + /* Pipe from rev-list to pack-objects */ - int lp_pipe[2], pu_pipe[2], pe_pipe[2]; - pid_t pid_rev_list, pid_pack_objects; + int lp_pipe[2]; + pid_t pid_rev_list; + struct child_process pack_objects; int create_full_pack = (nr_our_refs == want_obj.nr && !have_obj.nr); char data[8193], progress[128]; char abort_msg[] = "aborting due to possible repository " "corruption on the remote side."; int buffered = -1; + const char *argv[10]; + int arg = 0; if (pipe(lp_pipe) < 0) die("git-upload-pack: unable to create pipe"); @@ -154,52 +157,32 @@ static void create_pack_file(void) exit(0); } - if (pipe(pu_pipe) < 0) - die("git-upload-pack: unable to create pipe"); - if (pipe(pe_pipe) < 0) - die("git-upload-pack: unable to create pipe"); - pid_pack_objects = fork(); - if (pid_pack_objects < 0) { + /* writable pipe end must not be inherited by pack_objects */ + close(lp_pipe[1]); + + argv[arg++] = "pack-objects"; + argv[arg++] = "--stdout"; + if (!no_progress) + argv[arg++] = "--progress"; + if (use_ofs_delta) + argv[arg++] = "--delta-base-offset"; + argv[arg++] = NULL; + + memset(&pack_objects, 0, sizeof(pack_objects)); + pack_objects.in = lp_pipe[0]; /* start_command closes it */ + pack_objects.out = -1; + pack_objects.err = -1; + pack_objects.git_cmd = 1; + pack_objects.argv = argv; + if (start_command(&pack_objects)) { /* daemon sets things up to ignore TERM */ kill(pid_rev_list, SIGKILL); die("git-upload-pack: unable to fork git-pack-objects"); } - if (!pid_pack_objects) { - const char *argv[10]; - int i = 0; - dup2(lp_pipe[0], 0); - dup2(pu_pipe[1], 1); - dup2(pe_pipe[1], 2); - - close(lp_pipe[0]); - close(lp_pipe[1]); - close(pu_pipe[0]); - close(pu_pipe[1]); - close(pe_pipe[0]); - close(pe_pipe[1]); - - argv[i++] = "pack-objects"; - argv[i++] = "--stdout"; - if (!no_progress) - argv[i++] = "--progress"; - if (use_ofs_delta) - argv[i++] = "--delta-base-offset"; - argv[i++] = NULL; - - execv_git_cmd(argv); - kill(pid_rev_list, SIGKILL); - die("git-upload-pack: unable to exec git-pack-objects"); - } - - close(lp_pipe[0]); - close(lp_pipe[1]); - - /* We read from pe_pipe[0] to capture stderr output for - * progress bar, and pu_pipe[0] to capture the pack data. + /* We read from pack_objects.err to capture stderr output for + * progress bar, and pack_objects.out to capture the pack data. */ - close(pe_pipe[1]); - close(pu_pipe[1]); while (1) { const char *who; @@ -214,14 +197,14 @@ static void create_pack_file(void) pollsize = 0; pe = pu = -1; - if (0 <= pu_pipe[0]) { - pfd[pollsize].fd = pu_pipe[0]; + if (0 <= pack_objects.out) { + pfd[pollsize].fd = pack_objects.out; pfd[pollsize].events = POLLIN; pu = pollsize; pollsize++; } - if (0 <= pe_pipe[0]) { - pfd[pollsize].fd = pe_pipe[0]; + if (0 <= pack_objects.err) { + pfd[pollsize].fd = pack_objects.err; pfd[pollsize].events = POLLIN; pe = pollsize; pollsize++; @@ -254,13 +237,13 @@ static void create_pack_file(void) *cp++ = buffered; outsz++; } - sz = xread(pu_pipe[0], cp, + sz = xread(pack_objects.out, cp, sizeof(data) - outsz); if (0 < sz) ; else if (sz == 0) { - close(pu_pipe[0]); - pu_pipe[0] = -1; + close(pack_objects.out); + pack_objects.out = -1; } else goto fail; @@ -279,13 +262,13 @@ static void create_pack_file(void) /* Status ready; we ship that in the side-band * or dump to the standard error. */ - sz = xread(pe_pipe[0], progress, + sz = xread(pack_objects.err, progress, sizeof(progress)); if (0 < sz) send_client_data(2, progress, sz); else if (sz == 0) { - close(pe_pipe[0]); - pe_pipe[0] = -1; + close(pack_objects.err); + pack_objects.err = -1; } else goto fail; @@ -293,12 +276,12 @@ static void create_pack_file(void) } /* See if the children are still there */ - if (pid_rev_list || pid_pack_objects) { + if (pid_rev_list || pack_objects.pid) { pid = waitpid(-1, &status, WNOHANG); if (!pid) continue; who = ((pid == pid_rev_list) ? "git-rev-list" : - (pid == pid_pack_objects) ? "git-pack-objects" : + (pid == pack_objects.pid) ? "git-pack-objects" : NULL); if (!who) { if (pid < 0) { @@ -317,9 +300,9 @@ static void create_pack_file(void) } if (pid == pid_rev_list) pid_rev_list = 0; - if (pid == pid_pack_objects) - pid_pack_objects = 0; - if (pid_rev_list || pid_pack_objects) + if (pid == pack_objects.pid) + pack_objects.pid = 0; + if (pid_rev_list || pack_objects.pid) continue; } @@ -340,8 +323,8 @@ static void create_pack_file(void) return; } fail: - if (pid_pack_objects) - kill(pid_pack_objects, SIGKILL); + if (pack_objects.pid) + kill(pack_objects.pid, SIGKILL); if (pid_rev_list) kill(pid_rev_list, SIGKILL); send_client_data(3, abort_msg, sizeof(abort_msg)); From 2d22c208304156892fd6674e0055a3212c1e2d2e Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Fri, 19 Oct 2007 21:48:00 +0200 Subject: [PATCH 0241/1490] Add infrastructure to run a function asynchronously. This adds start_async() and finish_async(), which runs a function asynchronously. Communication with the caller happens only via pipes. For this reason, this implementation forks off a child process that runs the function. [sp: Style nit fixed by removing unnecessary block on if condition inside of start_async()] Signed-off-by: Johannes Sixt Signed-off-by: Shawn O. Pearce --- run-command.c | 51 +++++++++++++++++++++++++++++++++++++++++++-------- run-command.h | 22 ++++++++++++++++++++++ 2 files changed, 65 insertions(+), 8 deletions(-) diff --git a/run-command.c b/run-command.c index d00c03bbdf..d99a6c4ea7 100644 --- a/run-command.c +++ b/run-command.c @@ -127,16 +127,11 @@ int start_command(struct child_process *cmd) return 0; } -int finish_command(struct child_process *cmd) +static int wait_or_whine(pid_t pid) { - if (cmd->close_in) - close(cmd->in); - if (cmd->close_out) - close(cmd->out); - for (;;) { int status, code; - pid_t waiting = waitpid(cmd->pid, &status, 0); + pid_t waiting = waitpid(pid, &status, 0); if (waiting < 0) { if (errno == EINTR) @@ -144,7 +139,7 @@ int finish_command(struct child_process *cmd) error("waitpid failed (%s)", strerror(errno)); return -ERR_RUN_COMMAND_WAITPID; } - if (waiting != cmd->pid) + if (waiting != pid) return -ERR_RUN_COMMAND_WAITPID_WRONG_PID; if (WIFSIGNALED(status)) return -ERR_RUN_COMMAND_WAITPID_SIGNAL; @@ -158,6 +153,15 @@ int finish_command(struct child_process *cmd) } } +int finish_command(struct child_process *cmd) +{ + if (cmd->close_in) + close(cmd->in); + if (cmd->close_out) + close(cmd->out); + return wait_or_whine(cmd->pid); +} + int run_command(struct child_process *cmd) { int code = start_command(cmd); @@ -200,3 +204,34 @@ int run_command_v_opt_cd_env(const char **argv, int opt, const char *dir, const cmd.env = env; return run_command(&cmd); } + +int start_async(struct async *async) +{ + int pipe_out[2]; + + if (pipe(pipe_out) < 0) + return error("cannot create pipe: %s", strerror(errno)); + + async->pid = fork(); + if (async->pid < 0) { + error("fork (async) failed: %s", strerror(errno)); + close_pair(pipe_out); + return -1; + } + if (!async->pid) { + close(pipe_out[0]); + exit(!!async->proc(pipe_out[1], async->data)); + } + async->out = pipe_out[0]; + close(pipe_out[1]); + return 0; +} + +int finish_async(struct async *async) +{ + int ret = 0; + + if (wait_or_whine(async->pid)) + ret = error("waitpid (async) failed"); + return ret; +} diff --git a/run-command.h b/run-command.h index 35b9fb61f1..94e1e9d516 100644 --- a/run-command.h +++ b/run-command.h @@ -43,4 +43,26 @@ int run_command_v_opt_cd(const char **argv, int opt, const char *dir); */ int run_command_v_opt_cd_env(const char **argv, int opt, const char *dir, const char *const *env); +/* + * The purpose of the following functions is to feed a pipe by running + * a function asynchronously and providing output that the caller reads. + * + * It is expected that no synchronization and mutual exclusion between + * the caller and the feed function is necessary so that the function + * can run in a thread without interfering with the caller. + */ +struct async { + /* + * proc writes to fd and closes it; + * returns 0 on success, non-zero on failure + */ + int (*proc)(int fd, void *data); + void *data; + int out; /* caller reads from here and closes it */ + pid_t pid; +}; + +int start_async(struct async *async); +int finish_async(struct async *async); + #endif From 088fab5fc48ebb8b476c3b32dd25df3aa4236f94 Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Fri, 19 Oct 2007 21:48:01 +0200 Subject: [PATCH 0242/1490] Use the asyncronous function infrastructure in builtin-fetch-pack.c. We run the sideband demultiplexer in an asynchronous function. Note that earlier there was a check in the child process that closed xd[1] only if it was different from xd[0]; this test is no longer needed because git_connect() always returns two different file descriptors (see ec587fde0a76780931c7ac32474c8c000aa45134). Signed-off-by: Johannes Sixt Signed-off-by: Shawn O. Pearce --- builtin-fetch-pack.c | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/builtin-fetch-pack.c b/builtin-fetch-pack.c index 871b7042e7..51d8a32791 100644 --- a/builtin-fetch-pack.c +++ b/builtin-fetch-pack.c @@ -457,42 +457,37 @@ static int everything_local(struct ref **refs, int nr_match, char **match) return retval; } -static pid_t setup_sideband(int fd[2], int xd[2]) +static int sideband_demux(int fd, void *data) { - pid_t side_pid; + int *xd = data; + close(xd[1]); + return recv_sideband("fetch-pack", xd[0], fd, 2); +} + +static void setup_sideband(int fd[2], int xd[2], struct async *demux) +{ if (!use_sideband) { fd[0] = xd[0]; fd[1] = xd[1]; - return 0; + return; } /* xd[] is talking with upload-pack; subprocess reads from * xd[0], spits out band#2 to stderr, and feeds us band#1 - * through our fd[0]. + * through demux->out. */ - if (pipe(fd) < 0) - die("fetch-pack: unable to set up pipe"); - side_pid = fork(); - if (side_pid < 0) + demux->proc = sideband_demux; + demux->data = xd; + if (start_async(demux)) die("fetch-pack: unable to fork off sideband demultiplexer"); - if (!side_pid) { - /* subprocess */ - close(fd[0]); - if (xd[0] != xd[1]) - close(xd[1]); - if (recv_sideband("fetch-pack", xd[0], fd[1], 2)) - exit(1); - exit(0); - } close(xd[0]); - close(fd[1]); + fd[0] = demux->out; fd[1] = xd[1]; - return side_pid; } static int get_pack(int xd[2], char **pack_lockfile) { - pid_t side_pid; + struct async demux; int fd[2]; const char *argv[20]; char keep_arg[256]; @@ -501,7 +496,7 @@ static int get_pack(int xd[2], char **pack_lockfile) int do_keep = args.keep_pack; struct child_process cmd; - side_pid = setup_sideband(fd, xd); + setup_sideband(fd, xd, &demux); memset(&cmd, 0, sizeof(cmd)); cmd.argv = argv; @@ -556,6 +551,8 @@ static int get_pack(int xd[2], char **pack_lockfile) if (finish_command(&cmd)) die("%s failed", argv[0]); + if (use_sideband && finish_async(&demux)) + die("error in sideband demultiplexer"); return 0; } From 80ccaa78a8b95ad3b4f6e24dc35a9aa3cae5fd86 Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Fri, 19 Oct 2007 21:48:02 +0200 Subject: [PATCH 0243/1490] upload-pack: Move the revision walker into a separate function. This allows us later to use start_async() with this function, and at the same time is a nice cleanup that makes a long function (create_pack_file()) shorter. Signed-off-by: Johannes Sixt Signed-off-by: Shawn O. Pearce --- upload-pack.c | 70 +++++++++++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 33 deletions(-) diff --git a/upload-pack.c b/upload-pack.c index 5c0c0cc8e5..ccdc30653b 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -97,6 +97,42 @@ static void show_edge(struct commit *commit) fprintf(pack_pipe, "-%s\n", sha1_to_hex(commit->object.sha1)); } +static void do_rev_list(int create_full_pack) +{ + int i; + struct rev_info revs; + + if (create_full_pack) + use_thin_pack = 0; /* no point doing it */ + init_revisions(&revs, NULL); + revs.tag_objects = 1; + revs.tree_objects = 1; + revs.blob_objects = 1; + if (use_thin_pack) + revs.edge_hint = 1; + + if (create_full_pack) { + const char *args[] = {"rev-list", "--all", NULL}; + setup_revisions(2, args, &revs, NULL); + } else { + for (i = 0; i < want_obj.nr; i++) { + struct object *o = want_obj.objects[i].item; + /* why??? */ + o->flags &= ~UNINTERESTING; + add_pending_object(&revs, o, NULL); + } + for (i = 0; i < have_obj.nr; i++) { + struct object *o = have_obj.objects[i].item; + o->flags |= UNINTERESTING; + add_pending_object(&revs, o, NULL); + } + setup_revisions(0, NULL, &revs, NULL); + } + prepare_revision_walk(&revs); + mark_edges_uninteresting(revs.commits, &revs, show_edge); + traverse_commit_list(&revs, show_commit, show_object); +} + static void create_pack_file(void) { /* Pipe from rev-list to pack-objects @@ -119,41 +155,9 @@ static void create_pack_file(void) die("git-upload-pack: unable to fork git-rev-list"); if (!pid_rev_list) { - int i; - struct rev_info revs; - close(lp_pipe[0]); pack_pipe = fdopen(lp_pipe[1], "w"); - - if (create_full_pack) - use_thin_pack = 0; /* no point doing it */ - init_revisions(&revs, NULL); - revs.tag_objects = 1; - revs.tree_objects = 1; - revs.blob_objects = 1; - if (use_thin_pack) - revs.edge_hint = 1; - - if (create_full_pack) { - const char *args[] = {"rev-list", "--all", NULL}; - setup_revisions(2, args, &revs, NULL); - } else { - for (i = 0; i < want_obj.nr; i++) { - struct object *o = want_obj.objects[i].item; - /* why??? */ - o->flags &= ~UNINTERESTING; - add_pending_object(&revs, o, NULL); - } - for (i = 0; i < have_obj.nr; i++) { - struct object *o = have_obj.objects[i].item; - o->flags |= UNINTERESTING; - add_pending_object(&revs, o, NULL); - } - setup_revisions(0, NULL, &revs, NULL); - } - prepare_revision_walk(&revs); - mark_edges_uninteresting(revs.commits, &revs, show_edge); - traverse_commit_list(&revs, show_commit, show_object); + do_rev_list(create_full_pack); exit(0); } From 21edd3f197df80e9493233a3b9849b61764ebf46 Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Fri, 19 Oct 2007 21:48:03 +0200 Subject: [PATCH 0244/1490] upload-pack: Run rev-list in an asynchronous function. This gets rid of an explicit fork(). Since upload-pack has to coordinate two processes (rev-list and pack-objects), we cannot use the normal finish_async(), but have to monitor the process explicitly. Hence, there are no changes at this front. Signed-off-by: Johannes Sixt Signed-off-by: Shawn O. Pearce --- upload-pack.c | 46 ++++++++++++++++++---------------------------- 1 file changed, 18 insertions(+), 28 deletions(-) diff --git a/upload-pack.c b/upload-pack.c index ccdc30653b..67994680f2 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -97,11 +97,12 @@ static void show_edge(struct commit *commit) fprintf(pack_pipe, "-%s\n", sha1_to_hex(commit->object.sha1)); } -static void do_rev_list(int create_full_pack) +static int do_rev_list(int fd, void *create_full_pack) { int i; struct rev_info revs; + pack_pipe = fdopen(fd, "w"); if (create_full_pack) use_thin_pack = 0; /* no point doing it */ init_revisions(&revs, NULL); @@ -131,14 +132,12 @@ static void do_rev_list(int create_full_pack) prepare_revision_walk(&revs); mark_edges_uninteresting(revs.commits, &revs, show_edge); traverse_commit_list(&revs, show_commit, show_object); + return 0; } static void create_pack_file(void) { - /* Pipe from rev-list to pack-objects - */ - int lp_pipe[2]; - pid_t pid_rev_list; + struct async rev_list; struct child_process pack_objects; int create_full_pack = (nr_our_refs == want_obj.nr && !have_obj.nr); char data[8193], progress[128]; @@ -148,22 +147,12 @@ static void create_pack_file(void) const char *argv[10]; int arg = 0; - if (pipe(lp_pipe) < 0) - die("git-upload-pack: unable to create pipe"); - pid_rev_list = fork(); - if (pid_rev_list < 0) + rev_list.proc = do_rev_list; + /* .data is just a boolean: any non-NULL value will do */ + rev_list.data = create_full_pack ? &rev_list : NULL; + if (start_async(&rev_list)) die("git-upload-pack: unable to fork git-rev-list"); - if (!pid_rev_list) { - close(lp_pipe[0]); - pack_pipe = fdopen(lp_pipe[1], "w"); - do_rev_list(create_full_pack); - exit(0); - } - - /* writable pipe end must not be inherited by pack_objects */ - close(lp_pipe[1]); - argv[arg++] = "pack-objects"; argv[arg++] = "--stdout"; if (!no_progress) @@ -173,14 +162,15 @@ static void create_pack_file(void) argv[arg++] = NULL; memset(&pack_objects, 0, sizeof(pack_objects)); - pack_objects.in = lp_pipe[0]; /* start_command closes it */ + pack_objects.in = rev_list.out; /* start_command closes it */ pack_objects.out = -1; pack_objects.err = -1; pack_objects.git_cmd = 1; pack_objects.argv = argv; + if (start_command(&pack_objects)) { /* daemon sets things up to ignore TERM */ - kill(pid_rev_list, SIGKILL); + kill(rev_list.pid, SIGKILL); die("git-upload-pack: unable to fork git-pack-objects"); } @@ -280,11 +270,11 @@ static void create_pack_file(void) } /* See if the children are still there */ - if (pid_rev_list || pack_objects.pid) { + if (rev_list.pid || pack_objects.pid) { pid = waitpid(-1, &status, WNOHANG); if (!pid) continue; - who = ((pid == pid_rev_list) ? "git-rev-list" : + who = ((pid == rev_list.pid) ? "git-rev-list" : (pid == pack_objects.pid) ? "git-pack-objects" : NULL); if (!who) { @@ -302,11 +292,11 @@ static void create_pack_file(void) who); goto fail; } - if (pid == pid_rev_list) - pid_rev_list = 0; + if (pid == rev_list.pid) + rev_list.pid = 0; if (pid == pack_objects.pid) pack_objects.pid = 0; - if (pid_rev_list || pack_objects.pid) + if (rev_list.pid || pack_objects.pid) continue; } @@ -329,8 +319,8 @@ static void create_pack_file(void) fail: if (pack_objects.pid) kill(pack_objects.pid, SIGKILL); - if (pid_rev_list) - kill(pid_rev_list, SIGKILL); + if (rev_list.pid) + kill(rev_list.pid, SIGKILL); send_client_data(3, abort_msg, sizeof(abort_msg)); die("git-upload-pack: %s", abort_msg); } From a0ae35ae2d92cc706f902227cb0f34e2a2f0fd50 Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Fri, 19 Oct 2007 21:48:04 +0200 Subject: [PATCH 0245/1490] t0021-conversion.sh: Test that the clean filter really cleans content. This test uses a rot13 filter, which is its own inverse. It tested only that the content was the same as the original after both the 'clean' and the 'smudge' filter were applied. This way it would not detect whether any filter was run at all. Hence, here we add another test that checks that the repository contained content that was processed by the 'clean' filter. Signed-off-by: Johannes Sixt Signed-off-by: Shawn O. Pearce --- t/t0021-conversion.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh index a839f4e074..cb860296ed 100755 --- a/t/t0021-conversion.sh +++ b/t/t0021-conversion.sh @@ -42,7 +42,12 @@ test_expect_success check ' git diff --raw --exit-code :test :test.i && id=$(git rev-parse --verify :test) && embedded=$(sed -ne "$script" test.i) && - test "z$id" = "z$embedded" + test "z$id" = "z$embedded" && + + git cat-file blob :test.t > test.r && + + ./rot13.sh < test.o > test.t && + cmp test.r test.t ' # If an expanded ident ever gets into the repository, we want to make sure that From 7683b6e81fa0f1f55d4974d69fb87c7c7b6b394e Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Fri, 19 Oct 2007 21:48:05 +0200 Subject: [PATCH 0246/1490] Avoid a dup2(2) in apply_filter() - start_command() can do it for us. When apply_filter() runs the external (clean or smudge) filter program, it needs to pass the writable end of a pipe as its stdout. For this purpose, it used to dup2(2) the file descriptor explicitly to stdout. Now we use the facilities of start_command() to do it for us. Furthermore, the path argument of a subordinate function, filter_buffer(), was not used, so here we replace it to pass the fd instead. Signed-off-by: Johannes Sixt Signed-off-by: Shawn O. Pearce --- convert.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/convert.c b/convert.c index d83c2fcc5e..8dc9965081 100644 --- a/convert.c +++ b/convert.c @@ -192,7 +192,7 @@ static int crlf_to_worktree(const char *path, const char *src, size_t len, return 1; } -static int filter_buffer(const char *path, const char *src, +static int filter_buffer(int fd, const char *src, unsigned long size, const char *cmd) { /* @@ -205,6 +205,7 @@ static int filter_buffer(const char *path, const char *src, memset(&child_process, 0, sizeof(child_process)); child_process.argv = argv; child_process.in = -1; + child_process.out = fd; if (start_command(&child_process)) return error("cannot fork to run external filter %s", cmd); @@ -254,10 +255,8 @@ static int apply_filter(const char *path, const char *src, size_t len, return 0; } if (!child_process.pid) { - dup2(pipe_feed[1], 1); close(pipe_feed[0]); - close(pipe_feed[1]); - exit(filter_buffer(path, src, len, cmd)); + exit(filter_buffer(pipe_feed[1], src, len, cmd)); } close(pipe_feed[1]); From 546bb5823249678bc6ad11e65661d896ed83448a Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Fri, 19 Oct 2007 21:48:06 +0200 Subject: [PATCH 0247/1490] Use the asyncronous function infrastructure to run the content filter. Signed-off-by: Johannes Sixt Signed-off-by: Shawn O. Pearce --- convert.c | 61 +++++++++++++++++++++++++------------------------------ 1 file changed, 28 insertions(+), 33 deletions(-) diff --git a/convert.c b/convert.c index 8dc9965081..4df75595b1 100644 --- a/convert.c +++ b/convert.c @@ -192,15 +192,21 @@ static int crlf_to_worktree(const char *path, const char *src, size_t len, return 1; } -static int filter_buffer(int fd, const char *src, - unsigned long size, const char *cmd) +struct filter_params { + const char *src; + unsigned long size; + const char *cmd; +}; + +static int filter_buffer(int fd, void *data) { /* * Spawn cmd and feed the buffer contents through its stdin. */ struct child_process child_process; + struct filter_params *params = (struct filter_params *)data; int write_err, status; - const char *argv[] = { "sh", "-c", cmd, NULL }; + const char *argv[] = { "sh", "-c", params->cmd, NULL }; memset(&child_process, 0, sizeof(child_process)); child_process.argv = argv; @@ -208,17 +214,17 @@ static int filter_buffer(int fd, const char *src, child_process.out = fd; if (start_command(&child_process)) - return error("cannot fork to run external filter %s", cmd); + return error("cannot fork to run external filter %s", params->cmd); - write_err = (write_in_full(child_process.in, src, size) < 0); + write_err = (write_in_full(child_process.in, params->src, params->size) < 0); if (close(child_process.in)) write_err = 1; if (write_err) - error("cannot feed the input to external filter %s", cmd); + error("cannot feed the input to external filter %s", params->cmd); status = finish_command(&child_process); if (status) - error("external filter %s failed %d", cmd, -status); + error("external filter %s failed %d", params->cmd, -status); return (write_err || status); } @@ -231,47 +237,36 @@ static int apply_filter(const char *path, const char *src, size_t len, * * (child --> cmd) --> us */ - int pipe_feed[2]; - int status, ret = 1; - struct child_process child_process; + int ret = 1; struct strbuf nbuf; + struct async async; + struct filter_params params; if (!cmd) return 0; - memset(&child_process, 0, sizeof(child_process)); - - if (pipe(pipe_feed) < 0) { - error("cannot create pipe to run external filter %s", cmd); - return 0; - } + memset(&async, 0, sizeof(async)); + async.proc = filter_buffer; + async.data = ¶ms; + params.src = src; + params.size = len; + params.cmd = cmd; fflush(NULL); - child_process.pid = fork(); - if (child_process.pid < 0) { - error("cannot fork to run external filter %s", cmd); - close(pipe_feed[0]); - close(pipe_feed[1]); - return 0; - } - if (!child_process.pid) { - close(pipe_feed[0]); - exit(filter_buffer(pipe_feed[1], src, len, cmd)); - } - close(pipe_feed[1]); + if (start_async(&async)) + return 0; /* error was already reported */ strbuf_init(&nbuf, 0); - if (strbuf_read(&nbuf, pipe_feed[0], len) < 0) { + if (strbuf_read(&nbuf, async.out, len) < 0) { error("read from external filter %s failed", cmd); ret = 0; } - if (close(pipe_feed[0])) { + if (close(async.out)) { error("read from external filter %s failed", cmd); ret = 0; } - status = finish_command(&child_process); - if (status) { - error("external filter %s failed %d", cmd, -status); + if (finish_async(&async)) { + error("external filter %s failed", cmd); ret = 0; } From 538dfe7397db62e5c7e8861c272380140969a8b8 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Sun, 21 Oct 2007 00:12:12 -0400 Subject: [PATCH 0248/1490] Improved const correctness for strings Signed-off-by: Shawn O. Pearce --- builtin-fetch--tool.c | 4 ++-- builtin-mailinfo.c | 2 +- builtin-reset.c | 2 +- match-trees.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/builtin-fetch--tool.c b/builtin-fetch--tool.c index e26817de21..6a78517958 100644 --- a/builtin-fetch--tool.c +++ b/builtin-fetch--tool.c @@ -25,7 +25,7 @@ static int update_ref_env(const char *action, unsigned char *oldval) { char msg[1024]; - char *rla = getenv("GIT_REFLOG_ACTION"); + const char *rla = getenv("GIT_REFLOG_ACTION"); if (!rla) rla = "(reflog update)"; @@ -61,7 +61,7 @@ static int update_local_ref(const char *name, } if (get_sha1(name, sha1_old)) { - char *msg; + const char *msg; just_store: /* new ref */ if (!strncmp(name, "refs/tags/", 10)) diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c index d7cb11dc0d..fb12248f82 100644 --- a/builtin-mailinfo.c +++ b/builtin-mailinfo.c @@ -288,7 +288,7 @@ static void cleanup_space(char *buf) } static void decode_header(char *it, unsigned itsize); -static char *header[MAX_HDR_PARSED] = { +static const char *header[MAX_HDR_PARSED] = { "From","Subject","Date", }; diff --git a/builtin-reset.c b/builtin-reset.c index 99d5c082a6..e1dc31e0eb 100644 --- a/builtin-reset.c +++ b/builtin-reset.c @@ -169,7 +169,7 @@ static void prepend_reflog_action(const char *action, char *buf, size_t size) } enum reset_type { MIXED, SOFT, HARD, NONE }; -static char *reset_type_names[] = { "mixed", "soft", "hard", NULL }; +static const char *reset_type_names[] = { "mixed", "soft", "hard", NULL }; int cmd_reset(int argc, const char **argv, const char *prefix) { diff --git a/match-trees.c b/match-trees.c index d7e29c4d1d..0fd6df7d6e 100644 --- a/match-trees.c +++ b/match-trees.c @@ -132,7 +132,7 @@ static void match_trees(const unsigned char *hash1, const unsigned char *hash2, int *best_score, char **best_match, - char *base, + const char *base, int recurse_limit) { struct tree_desc one; From 07134421fc5765d6c96c548e70e461c290143762 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 19 Oct 2007 10:59:22 -0700 Subject: [PATCH 0249/1490] Fix directory scanner to correctly ignore files without d_type On Fri, 19 Oct 2007, Todd T. Fries wrote: > If DT_UNKNOWN exists, then we have to do a stat() of some form to > find out the right type. That happened in the case of a pathname that was ignored, and we did not ask for "dir->show_ignored". That test used to be *together* with the "DTYPE(de) != DT_DIR", but splitting the two tests up means that we can do that (common) test before we even bother to calculate the real dtype. Of course, that optimization only matters for systems that don't have, or don't fill in DTYPE properly. I also clarified the real relationship between "exclude" and "dir->show_ignored". It used to do if (exclude != dir->show_ignored) { .. which wasn't exactly obvious, because it triggers for two different cases: - the path is marked excluded, but we are not interested in ignored files: ignore it - the path is *not* excluded, but we *are* interested in ignored files: ignore it unless it's a directory, in which case we might have ignored files inside the directory and need to recurse into it). so this splits them into those two cases, since the first case doesn't even care about the type. I also made a the DT_UNKNOWN case a separate helper function, and added some commentary to the cases. Linus Signed-off-by: Shawn O. Pearce --- dir.c | 52 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 14 deletions(-) diff --git a/dir.c b/dir.c index eb6c3abd30..f843c4dd20 100644 --- a/dir.c +++ b/dir.c @@ -443,6 +443,24 @@ static int in_pathspec(const char *path, int len, const struct path_simplify *si return 0; } +static int get_dtype(struct dirent *de, const char *path) +{ + int dtype = DTYPE(de); + struct stat st; + + if (dtype != DT_UNKNOWN) + return dtype; + if (lstat(path, &st)) + return dtype; + if (S_ISREG(st.st_mode)) + return DT_REG; + if (S_ISDIR(st.st_mode)) + return DT_DIR; + if (S_ISLNK(st.st_mode)) + return DT_LNK; + return dtype; +} + /* * Read a directory tree. We currently ignore anything but * directories, regular files and symlinks. That's because git @@ -466,7 +484,7 @@ static int read_directory_recursive(struct dir_struct *dir, const char *path, co exclude_stk = push_exclude_per_directory(dir, base, baselen); while ((de = readdir(fdir)) != NULL) { - int len; + int len, dtype; int exclude; if ((de->d_name[0] == '.') && @@ -486,24 +504,30 @@ static int read_directory_recursive(struct dir_struct *dir, const char *path, co if (exclude && dir->collect_ignored && in_pathspec(fullname, baselen + len, simplify)) dir_add_ignored(dir, fullname, baselen + len); - if (exclude != dir->show_ignored) { - if (!dir->show_ignored || DTYPE(de) != DT_DIR) { + + /* + * Excluded? If we don't explicitly want to show + * ignored files, ignore it + */ + if (exclude && !dir->show_ignored) + continue; + + dtype = get_dtype(de, fullname); + + /* + * Do we want to see just the ignored files? + * We still need to recurse into directories, + * even if we don't ignore them, since the + * directory may contain files that we do.. + */ + if (!exclude && dir->show_ignored) { + if (dtype != DT_DIR) continue; - } } - switch (DTYPE(de)) { - struct stat st; + switch (dtype) { default: continue; - case DT_UNKNOWN: - if (lstat(fullname, &st)) - continue; - if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) - break; - if (!S_ISDIR(st.st_mode)) - continue; - /* fallthrough */ case DT_DIR: memcpy(fullname + baselen + len, "/", 2); len++; From 6dd4b66fdecc2ffdc68758b6c4e059fcaaca512b Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 20 Oct 2007 12:31:31 -0700 Subject: [PATCH 0250/1490] Fix diffcore-break total breakage Ok, so on the kernel list, some people noticed that "git log --follow" doesn't work too well with some files in the x86 merge, because a lot of files got renamed in very special ways. In particular, there was a pattern of doing single commits with renames that looked basically like - rename "filename.h" -> "filename_64.h" - create new "filename.c" that includes "filename_32.h" or "filename_64.h" depending on whether we're 32-bit or 64-bit. which was preparatory for smushing the two trees together. Now, there's two issues here: - "filename.c" *remained*. Yes, it was a rename, but there was a new file created with the old name in the same commit. This was important, because we wanted each commit to compile properly, so that it was bisectable, so splitting the rename into one commit and the "create helper file" into another was *not* an option. So we need to break associations where the contents change too much. Fine. We have the -B flag for that. When we break things up, then the rename detection will be able to figure out whether there are better alternatives. - "git log --follow" didn't with with -B. Now, the second case was really simple: we use a different "diffopt" structure for the rename detection than the basic one (which we use for showing the diffs). So that second case is trivially fixed by a trivial one-liner that just copies the break_opt values from the "real" diffopts to the one used for rename following. So now "git log -B --follow" works fine: diff --git a/tree-diff.c b/tree-diff.c index 26bdbdd..7c261fd 100644 --- a/tree-diff.c +++ b/tree-diff.c @@ -319,6 +319,7 @@ static void try_to_follow_renames(struct tree_desc *t1, struct tree_desc *t2, co diff_opts.detect_rename = DIFF_DETECT_RENAME; diff_opts.output_format = DIFF_FORMAT_NO_OUTPUT; diff_opts.single_follow = opt->paths[0]; + diff_opts.break_opt = opt->break_opt; paths[0] = NULL; diff_tree_setup_paths(paths, &diff_opts); if (diff_setup_done(&diff_opts) < 0) however, the end result does *not* work. Because our diffcore-break.c logic is totally bogus! In particular: - it used to do if (base_size < MINIMUM_BREAK_SIZE) return 0; /* we do not break too small filepair */ which basically says "don't bother to break small files". But that "base_size" is the *smaller* of the two sizes, which means that if some large file was rewritten into one that just includes another file, we would look at the (small) result, and decide that it's smaller than the break size, so it cannot be worth it to break it up! Even if the other side was ten times bigger and looked *nothing* like the samell file! That's clearly bogus. I replaced "base_size" with "max_size", so that we compare the *bigger* of the filepair with the break size. - It calculated a "merge_score", which was the score needed to merge it back together if nothing else wanted it. But even if it was *so* different that we would never want to merge it back, we wouldn't consider it a break! That makes no sense. So I added if (*merge_score_p > break_score) return 1; to make it clear that if we wouldn't want to merge it at the end, it was *definitely* a break. - It compared the whole "extent of damage", counting all inserts and deletes, but it based this score on the "base_size", and generated the damage score with delta_size = src_removed + literal_added; damage_score = delta_size * MAX_SCORE / base_size; but that makes no sense either, since quite often, this will result in a number that is *bigger* than MAX_SCORE! Why? Because base_size is (again) the smaller of the two files we compare, and when you start out from a small file and add a lot (or start out from a large file and remove a lot), the base_size is going to be much smaller than the damage! Again, the fix was to replace "base_size" with "max_size", at which point the damage actually becomes a sane percentage of the whole. With these changes in place, not only does "git log -B --follow" work for the case that triggered this in the first place, ie now git log -B --follow arch/x86/kernel/vmlinux_64.lds.S actually gives reasonable results. But I also wanted to verify it in general, by doing a full-history git log --stat -B -C on my kernel tree with the old code and the new code. There's some tweaking to be done, but generally, the new code generates much better results wrt breaking up files (and then finding better rename candidates). Here's a few examples of the "--stat" output: - This: include/asm-x86/Kbuild | 2 - include/asm-x86/debugreg.h | 79 +++++++++++++++++++++++++++++++++++------ include/asm-x86/debugreg_32.h | 64 --------------------------------- include/asm-x86/debugreg_64.h | 65 --------------------------------- 4 files changed, 68 insertions(+), 142 deletions(-) Becomes: include/asm-x86/Kbuild | 2 - include/asm-x86/{debugreg_64.h => debugreg.h} | 9 +++- include/asm-x86/debugreg_32.h | 64 ------------------------- 3 files changed, 7 insertions(+), 68 deletions(-) - This: include/asm-x86/bug.h | 41 +++++++++++++++++++++++++++++++++++++++-- include/asm-x86/bug_32.h | 37 ------------------------------------- include/asm-x86/bug_64.h | 34 ---------------------------------- 3 files changed, 39 insertions(+), 73 deletions(-) Becomes include/asm-x86/{bug_64.h => bug.h} | 20 +++++++++++++----- include/asm-x86/bug_32.h | 37 ----------------------------------- 2 files changed, 14 insertions(+), 43 deletions(-) Now, in some other cases, it does actually turn a rename into a real "delete+create" pair, and then the diff is usually bigger, so truth in advertizing: it doesn't always generate a nicer diff. But for what -B was meant for, I think this is a big improvement, and I suspect those cases where it generates a bigger diff are tweakable. So I think this diff fixes a real bug, but we might still want to tweak the default values and perhaps the exact rules for when a break happens. Signed-off-by: Linus Torvalds Signed-off-by: Shawn O. Pearce --- diffcore-break.c | 11 +++++++---- tree-diff.c | 1 + 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/diffcore-break.c b/diffcore-break.c index ae8a7d03e2..c71a22621a 100644 --- a/diffcore-break.c +++ b/diffcore-break.c @@ -45,8 +45,8 @@ static int should_break(struct diff_filespec *src, * The value we return is 1 if we want the pair to be broken, * or 0 if we do not. */ - unsigned long delta_size, base_size, src_copied, literal_added, - src_removed; + unsigned long delta_size, base_size, max_size; + unsigned long src_copied, literal_added, src_removed; *merge_score_p = 0; /* assume no deletion --- "do not break" * is the default. @@ -63,7 +63,8 @@ static int should_break(struct diff_filespec *src, return 0; /* error but caught downstream */ base_size = ((src->size < dst->size) ? src->size : dst->size); - if (base_size < MINIMUM_BREAK_SIZE) + max_size = ((src->size > dst->size) ? src->size : dst->size); + if (max_size < MINIMUM_BREAK_SIZE) return 0; /* we do not break too small filepair */ if (diffcore_count_changes(src, dst, @@ -89,12 +90,14 @@ static int should_break(struct diff_filespec *src, * less than the minimum, after rename/copy runs. */ *merge_score_p = (int)(src_removed * MAX_SCORE / src->size); + if (*merge_score_p > break_score) + return 1; /* Extent of damage, which counts both inserts and * deletes. */ delta_size = src_removed + literal_added; - if (delta_size * MAX_SCORE / base_size < break_score) + if (delta_size * MAX_SCORE / max_size < break_score) return 0; /* If you removed a lot without adding new material, that is diff --git a/tree-diff.c b/tree-diff.c index 26bdbdd2bf..7c261fd7c3 100644 --- a/tree-diff.c +++ b/tree-diff.c @@ -319,6 +319,7 @@ static void try_to_follow_renames(struct tree_desc *t1, struct tree_desc *t2, co diff_opts.detect_rename = DIFF_DETECT_RENAME; diff_opts.output_format = DIFF_FORMAT_NO_OUTPUT; diff_opts.single_follow = opt->paths[0]; + diff_opts.break_opt = opt->break_opt; paths[0] = NULL; diff_tree_setup_paths(paths, &diff_opts); if (diff_setup_done(&diff_opts) < 0) From 2ee52eb17c26323b3f62538a44510aae75f09d6f Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Sat, 20 Oct 2007 23:40:06 -0400 Subject: [PATCH 0251/1490] Describe more 1.5.3.5 fixes in release notes Signed-off-by: Shawn O. Pearce --- Documentation/RelNotes-1.5.3.5.txt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Documentation/RelNotes-1.5.3.5.txt b/Documentation/RelNotes-1.5.3.5.txt index 49e52264ba..9581e03c49 100644 --- a/Documentation/RelNotes-1.5.3.5.txt +++ b/Documentation/RelNotes-1.5.3.5.txt @@ -4,6 +4,8 @@ GIT v1.5.3.5 Release Notes Fixes since v1.5.3.4 -------------------- + * Comes with git-gui 0.8.4. + * "git-config" silently ignored options after --list; now it will error out with a usage message. @@ -27,12 +29,20 @@ Fixes since v1.5.3.4 * "git-log --follow" did not work unless diff generation (e.g. -p) was also requested. + * "git-log --follow -B" did not work at all. Fixed. + + * "git-log -M -B" did not correctly handle cases of very large files + being renamed and replaced by very small files in the same commit. + * "git-log" printed extra newlines between commits when a diff was generated internally (e.g. -S or --follow) but not displayed. * "git-push" error message is more helpful when pushing to a repository with no matching refs and none specified. + * "git-push" now respects + (force push) on wildcard refspecs, + matching the behavior of git-fetch. + * "git-filter-branch" now updates the working directory when it has finished filtering the current branch. @@ -46,6 +56,11 @@ Fixes since v1.5.3.4 not impact correctness, only user perception. The bogus error is no longer printed. + * "git-ls-files --ignored" did not properly descend into non-ignored + directories that themselves contained ignored files if d_type + was not supported by the filesystem. This bug impacted systems + such as AFS. Fixed. + * Git segfaulted when reading an invalid .gitattributes file. Fixed. * post-receive-email example hook fixed was fixed for From 5be507fc955bd14643cac1162cfaa592d0e236ba Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Sun, 21 Oct 2007 00:51:09 -0400 Subject: [PATCH 0252/1490] Use PRIuMAX instead of 'unsigned long long' in show-index Elsewhere in Git we already use PRIuMAX and cast to uintmax_t when we need to display a value that is 'very big' and we're not exactly sure what the largest display size is for this platform. This particular fix is needed so we can do the incredibly crazy temporary hack of: diff --git a/cache.h b/cache.h index e0abcd6..6637fd8 100644 --- a/cache.h +++ b/cache.h @@ -6,6 +6,7 @@ #include SHA1_HEADER #include +#define long long long #if ZLIB_VERNUM < 0x1200 #define deflateBound(c,s) ((s) + (((s) + 7) >> 3) + (((s) + 63) >> 6) + 11) allowing us to more easily look for locations where we are passing a pointer to an 8 byte value to a function that expects a 4 byte value. This can occur on some platforms where sizeof(long) == 8 and sizeof(size_t) == 4. Signed-off-by: Shawn O. Pearce --- show-index.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/show-index.c b/show-index.c index 57ed9e87b7..7253991fff 100644 --- a/show-index.c +++ b/show-index.c @@ -68,7 +68,7 @@ int main(int argc, char **argv) ntohl(off64[1]); off64_nr++; } - printf("%llu %s (%08x)\n", (unsigned long long) offset, + printf("%" PRIuMAX " %s (%08x)\n", (uintmax_t) offset, sha1_to_hex(entries[i].sha1), ntohl(entries[i].crc)); } From c32f749fec69f92ce3b076128e6322f8130bd881 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Scharfe?= Date: Sun, 21 Oct 2007 11:23:49 +0200 Subject: [PATCH 0253/1490] Correct some sizeof(size_t) != sizeof(unsigned long) typing errors Fix size_t vs. unsigned long pointer mismatch warnings introduced with the addition of strbuf_detach(). Signed-off-by: Rene Scharfe Signed-off-by: Shawn O. Pearce --- builtin-apply.c | 2 +- builtin-archive.c | 4 +++- diff.c | 8 ++++++-- entry.c | 4 +++- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/builtin-apply.c b/builtin-apply.c index 05c6bc3592..8411b38c79 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -152,7 +152,7 @@ struct patch { unsigned int is_rename:1; struct fragment *fragments; char *result; - unsigned long resultsize; + size_t resultsize; char old_sha1_prefix[41]; char new_sha1_prefix[41]; struct patch *next; diff --git a/builtin-archive.c b/builtin-archive.c index 04385dea05..6f29c2f40a 100644 --- a/builtin-archive.c +++ b/builtin-archive.c @@ -148,12 +148,14 @@ void *sha1_file_to_archive(const char *path, const unsigned char *sha1, buffer = read_sha1_file(sha1, type, sizep); if (buffer && S_ISREG(mode)) { struct strbuf buf; + size_t size = 0; strbuf_init(&buf, 0); strbuf_attach(&buf, buffer, *sizep, *sizep + 1); convert_to_working_tree(path, buf.buf, buf.len, &buf); convert_to_archive(path, buf.buf, buf.len, &buf, commit); - buffer = strbuf_detach(&buf, sizep); + buffer = strbuf_detach(&buf, &size); + *sizep = size; } return buffer; diff --git a/diff.c b/diff.c index 6648e01521..dfb8595b70 100644 --- a/diff.c +++ b/diff.c @@ -1512,6 +1512,7 @@ static int reuse_worktree_file(const char *name, const unsigned char *sha1, int static int populate_from_stdin(struct diff_filespec *s) { struct strbuf buf; + size_t size = 0; strbuf_init(&buf, 0); if (strbuf_read(&buf, 0, 0) < 0) @@ -1519,7 +1520,8 @@ static int populate_from_stdin(struct diff_filespec *s) strerror(errno)); s->should_munmap = 0; - s->data = strbuf_detach(&buf, &s->size); + s->data = strbuf_detach(&buf, &size); + s->size = size; s->should_free = 1; return 0; } @@ -1609,9 +1611,11 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only) */ strbuf_init(&buf, 0); if (convert_to_git(s->path, s->data, s->size, &buf)) { + size_t size = 0; munmap(s->data, s->size); s->should_munmap = 0; - s->data = strbuf_detach(&buf, &s->size); + s->data = strbuf_detach(&buf, &size); + s->size = size; s->should_free = 1; } } diff --git a/entry.c b/entry.c index 98f5f6d4ec..cfadc6a292 100644 --- a/entry.c +++ b/entry.c @@ -119,8 +119,10 @@ static int write_entry(struct cache_entry *ce, char *path, const struct checkout */ strbuf_init(&buf, 0); if (convert_to_working_tree(ce->name, new, size, &buf)) { + size_t newsize = 0; free(new); - new = strbuf_detach(&buf, &size); + new = strbuf_detach(&buf, &newsize); + size = newsize; } if (to_tempfile) { From c43ff43601201e17be8882ee199542282f1531eb Mon Sep 17 00:00:00 2001 From: Kirill Date: Sat, 20 Oct 2007 15:35:53 -0400 Subject: [PATCH 0254/1490] Updated Russian translation. The most important changes are: - Git version cannot be determined... (lost in 57364320bf) - git-gui: fatal error Some changes need the second opinion (search for TOVERIFY), some changes are just copies (search for "carbon copy"). Signed-off-by: Shawn O. Pearce --- po/ru.po | 331 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 190 insertions(+), 141 deletions(-) diff --git a/po/ru.po b/po/ru.po index 3beaf9d52e..ed5b67a95c 100644 --- a/po/ru.po +++ b/po/ru.po @@ -8,8 +8,8 @@ msgstr "" "Project-Id-Version: git-gui\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2007-10-10 04:04-0400\n" -"PO-Revision-Date: 2007-07-28 18:30+0200\n" -"Last-Translator: Irina Riesen \n" +"PO-Revision-Date: 2007-10-20 14:29-0500\n" +"Last-Translator: Kirill \n" "Language-Team: Russian Translation \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -18,7 +18,7 @@ msgstr "" #: git-gui.sh:41 git-gui.sh:634 git-gui.sh:648 git-gui.sh:661 git-gui.sh:744 #: git-gui.sh:763 msgid "git-gui: fatal error" -msgstr "" +msgstr "git-gui: критическая ошибка" #: git-gui.sh:595 #, fuzzy, tcl-format @@ -52,6 +52,12 @@ msgid "" "\n" "Assume '%s' is version 1.5.0?\n" msgstr "" +"Невозможно определить версию Git\n" +"%s указывает на версию '%s'.\n" +"\n" +"для %s требуется версия Git, начиная с 1.5.0\n" +"\n" +"Принять '%s' как версию 1.5.0?\n" #: git-gui.sh:853 msgid "Git directory not found:" @@ -153,7 +159,7 @@ msgstr "Ветвь" #: git-gui.sh:1794 lib/choose_rev.tcl:547 #, fuzzy msgid "Commit@@noun" -msgstr "Сохранить" +msgstr "Состояние" #: git-gui.sh:1797 lib/merge.tcl:121 lib/merge.tcl:150 lib/merge.tcl:168 msgid "Merge" @@ -187,9 +193,9 @@ msgid "Browse %s's Files" msgstr "Показать файлы ветви" #: git-gui.sh:1829 -#, fuzzy, tcl-format +#, tcl-format msgid "Visualize %s's History" -msgstr "История всех ветвей наглядно" +msgstr "История ветви %s наглядно" #: git-gui.sh:1834 lib/database.tcl:27 lib/database.tcl:67 msgid "Database Statistics" @@ -277,12 +283,12 @@ msgstr "Перечитать" #: git-gui.sh:1953 #, fuzzy msgid "Stage To Commit" -msgstr "Подготовлено для сохранения" +msgstr "Подготовить для сохранения" #: git-gui.sh:1958 #, fuzzy msgid "Stage Changed Files To Commit" -msgstr "Подготовлено (будет сохранено)" +msgstr "Подготовить измененные файлы для сохранения" #: git-gui.sh:1964 msgid "Unstage From Commit" @@ -313,9 +319,11 @@ msgstr "Прервать объединение..." msgid "Push..." msgstr "Отправить..." +# carbon copy #: git-gui.sh:2019 lib/choose_repository.tcl:41 +#, fuzzy msgid "Apple" -msgstr "" +msgstr "Apple" #: git-gui.sh:2022 git-gui.sh:2044 lib/about.tcl:13 #: lib/choose_repository.tcl:44 lib/choose_repository.tcl:50 @@ -325,7 +333,7 @@ msgstr "О %s" #: git-gui.sh:2026 msgid "Preferences..." -msgstr "" +msgstr "Настройки..." #: git-gui.sh:2034 git-gui.sh:2558 msgid "Options..." @@ -339,10 +347,11 @@ msgstr "Помощь" msgid "Online Documentation" msgstr "Документация в интернете" +# TOVERIFY #: git-gui.sh:2165 -#, tcl-format +#, fuzzy, tcl-format msgid "fatal: cannot stat path %s: No such file or directory" -msgstr "" +msgstr "критическая ошибка: %s: нет такого файла или каталога" #: git-gui.sh:2198 msgid "Current Branch:" @@ -353,13 +362,17 @@ msgstr "Текущая ветвь:" msgid "Staged Changes (Will Commit)" msgstr "Подготовлено (будет сохранено)" +# TOVERIFY #: git-gui.sh:2239 +#, fuzzy msgid "Unstaged Changes" -msgstr "" +msgstr "Изменено" +# carbon copy #: git-gui.sh:2286 +#, fuzzy msgid "Stage Changed" -msgstr "" +msgstr "Stage Changed" #: git-gui.sh:2302 lib/transport.tcl:93 lib/transport.tcl:182 msgid "Push" @@ -447,13 +460,24 @@ msgid "" "by %s:\n" "\n" msgstr "" +"Возможны ошибки в переменных окружения.\n" +"\n" +"Переменные окружения, которые возможно\n" +"будут проигнорированы командами Git,\n" +"запущенными из %s\n" +"\n" +# TOVERIFY #: git-gui.sh:2707 +#, fuzzy msgid "" "\n" "This is due to a known issue with the\n" "Tcl binary distributed by Cygwin." msgstr "" +"\n" +"Это известная проблема с Tcl,\n" +"распространяемым Cygwin." #: git-gui.sh:2712 #, tcl-format @@ -465,6 +489,12 @@ msgid "" "user.email settings into your personal\n" "~/.gitconfig file.\n" msgstr "" +"\n" +"\n" +"Хорошая замена для %s\n" +"сохраняет значения для user.name и\n" +"user.email в Ваш персональный\n" +"~/.gitconfig файл.\n" #: lib/about.tcl:25 msgid "git-gui - a graphical user interface for Git." @@ -487,21 +517,29 @@ msgstr "Копировать сохраненное состояние" msgid "Reading %s..." msgstr "Чтение %s..." +# carbon copy #: lib/blame.tcl:473 +#, fuzzy msgid "Loading copy/move tracking annotations..." -msgstr "" +msgstr "Loading copy/move tracking annotations..." +# TOVERIFY #: lib/blame.tcl:493 +#, fuzzy msgid "lines annotated" -msgstr "" +msgstr "строк прокоментировано" +# carbon copy #: lib/blame.tcl:674 +#, fuzzy msgid "Loading original location annotations..." -msgstr "" +msgstr "Loading original location annotations..." +# carbon copy #: lib/blame.tcl:677 +#, fuzzy msgid "Annotation complete." -msgstr "" +msgstr "Annotation complete." #: lib/blame.tcl:731 #, fuzzy @@ -510,7 +548,7 @@ msgstr "Загрузка %s..." #: lib/blame.tcl:787 msgid "Author:" -msgstr "" +msgstr "Автор:" #: lib/blame.tcl:791 #, fuzzy @@ -519,11 +557,13 @@ msgstr "Сохраненное состояние:" #: lib/blame.tcl:796 msgid "Original File:" -msgstr "" +msgstr "Исходный файл:" +# carbon copy #: lib/blame.tcl:910 +#, fuzzy msgid "Originally By:" -msgstr "" +msgstr "Originally By:" #: lib/blame.tcl:916 #, fuzzy @@ -532,7 +572,7 @@ msgstr "Файл:" #: lib/blame.tcl:921 msgid "Copied Or Moved Here By:" -msgstr "" +msgstr "Кто скопировал/переместил сюда:" #: lib/branch_checkout.tcl:14 lib/branch_checkout.tcl:19 msgid "Checkout Branch" @@ -720,7 +760,7 @@ msgstr "Загрузка %s..." #: lib/browser.tcl:186 msgid "[Up To Parent]" -msgstr "" +msgstr "[На уровень выше]" #: lib/browser.tcl:266 lib/browser.tcl:272 msgid "Browse Branch Files" @@ -740,7 +780,7 @@ msgstr "Получение изменений из %s " #: lib/checkout_op.tcl:127 #, tcl-format msgid "fatal: Cannot resolve %s" -msgstr "" +msgstr "критическая ошибка: не могу распознать %s" #: lib/checkout_op.tcl:140 lib/console.tcl:79 lib/database.tcl:31 msgid "Close" @@ -783,15 +823,13 @@ msgstr "Индекс заблокирован." msgid "" "Last scanned state does not match repository state.\n" "\n" -"Another Git program has modified this repository since the last scan. A " -"rescan must be performed before the current branch can be changed.\n" +"Another Git program has modified this repository since the last scan. A rescan must be performed before the current branch can be changed.\n" "\n" "The rescan will be automatically started now.\n" msgstr "" "Последнее прочитанное состояние репозитория не соответствует текущему.\n" "\n" -"С момента последней проверки репозиторий был изменен другой программой Git." -"Необходимо перечитать репозиторий, прежде чем изменять текущую ветвь. \n" +"С момента последней проверки репозиторий был изменен другой программой Git.Необходимо перечитать репозиторий, прежде чем изменять текущую ветвь. \n" "\n" "Это будет сделано сейчас автоматически.\n" @@ -818,13 +856,11 @@ msgstr "Ветвь '%s' остается текущей." msgid "" "You are no longer on a local branch.\n" "\n" -"If you wanted to be on a branch, create one now starting from 'This Detached " -"Checkout'." +"If you wanted to be on a branch, create one now starting from 'This Detached Checkout'." msgstr "" "Вы находитесь не в локальной ветви.\n" "\n" -"Если вы хотите снова вернуться к какой-нибудь ветви, создайте ее сейчас, " -"начиная с 'Текущего отсоединенного состояния'." +"Если вы хотите снова вернуться к какой-нибудь ветви, создайте ее сейчас, начиная с 'Текущего отсоединенного состояния'." #: lib/checkout_op.tcl:446 #, fuzzy, tcl-format @@ -854,15 +890,13 @@ msgstr "Наглядно" msgid "" "Failed to set current branch.\n" "\n" -"This working directory is only partially switched. We successfully updated " -"your files, but failed to update an internal Git file.\n" +"This working directory is only partially switched. We successfully updated your files, but failed to update an internal Git file.\n" "\n" "This should not have occurred. %s will now close and give up." msgstr "" "Не удалось установить текущую ветвь.\n" "\n" -"Ваш рабочий каталог обновлен только частично. Были обновлены все файлы кроме " -"служебных файлов Git. \n" +"Ваш рабочий каталог обновлен только частично. Были обновлены все файлы кроме служебных файлов Git. \n" "\n" "Этого не должно было произойти. %s завершается." @@ -873,7 +907,7 @@ msgstr "Выделить все" #: lib/choose_font.tcl:53 msgid "Font Family" -msgstr "" +msgstr "Шрифт" #: lib/choose_font.tcl:73 #, fuzzy @@ -882,17 +916,20 @@ msgstr "Уменьшить размер шрифта" #: lib/choose_font.tcl:90 msgid "Font Example" -msgstr "" +msgstr "Пример текста" +# TOVERIFY: what's the Russian version of the font sample (see Windows Fonts). #: lib/choose_font.tcl:101 msgid "" "This is example text.\n" "If you like this text, it can be your font." msgstr "" +"Это пример текста.\n" +"Если Вам нравится этот текст, это может быть Ваш шрифт." #: lib/choose_repository.tcl:25 msgid "Git Gui" -msgstr "" +msgstr "Git Gui" #: lib/choose_repository.tcl:69 lib/choose_repository.tcl:204 #, fuzzy @@ -909,9 +946,11 @@ msgstr "Репозиторий назначения" msgid "Open Existing Repository" msgstr "Репозиторий назначения" +# TOVERIFY #: lib/choose_repository.tcl:91 +#, fuzzy msgid "Next >" -msgstr "" +msgstr "Дальше >" #: lib/choose_repository.tcl:152 #, fuzzy, tcl-format @@ -926,7 +965,7 @@ msgstr "Не удалось полностью сохранить настрой #: lib/choose_repository.tcl:209 lib/choose_repository.tcl:309 msgid "Directory:" -msgstr "" +msgstr "Каталог:" #: lib/choose_repository.tcl:238 lib/choose_repository.tcl:363 #: lib/choose_repository.tcl:834 @@ -951,23 +990,31 @@ msgstr "Закрыть" #: lib/choose_repository.tcl:299 msgid "URL:" -msgstr "" +msgstr "Ссылка:" +# TOVERIFY #: lib/choose_repository.tcl:319 +#, fuzzy msgid "Clone Type:" -msgstr "" +msgstr "Тип клона:" +# TOVERIFY #: lib/choose_repository.tcl:325 +#, fuzzy msgid "Standard (Fast, Semi-Redundant, Hardlinks)" -msgstr "" +msgstr "Стандартный (Быстрый, полуизбыточный, \"жесткие\" ссылки)" +# TOVERIFY #: lib/choose_repository.tcl:331 +#, fuzzy msgid "Full Copy (Slower, Redundant Backup)" -msgstr "" +msgstr "Полная копия (Медленный, избыточная резервная копия)" +# TOVERIFY #: lib/choose_repository.tcl:337 +#, fuzzy msgid "Shared (Fastest, Not Recommended, No Backup)" -msgstr "" +msgstr "Общий (Самый быстрый, не рекомендуется, без резервной копии)" #: lib/choose_repository.tcl:369 lib/choose_repository.tcl:418 #: lib/choose_repository.tcl:560 lib/choose_repository.tcl:630 @@ -976,44 +1023,57 @@ msgstr "" msgid "Not a Git repository: %s" msgstr "Не указан репозиторий" +# TOVERIFY #: lib/choose_repository.tcl:405 +#, fuzzy msgid "Standard only available for local repository." -msgstr "" +msgstr "Стандартный клон возможен только для локального репозитория." +# TOVERIFY #: lib/choose_repository.tcl:409 +#, fuzzy msgid "Shared only available for local repository." -msgstr "" +msgstr "Общий клон возможен только для локального репозитория." +# TOVERIFY #: lib/choose_repository.tcl:439 +#, fuzzy msgid "Failed to configure origin" -msgstr "" +msgstr "Не могу сконфигурировать искходник." #: lib/choose_repository.tcl:451 msgid "Counting objects" -msgstr "" +msgstr "Считаю объекты" +# carbon copy #: lib/choose_repository.tcl:452 +#, fuzzy msgid "buckets" -msgstr "" +msgstr "buckets" +# TOVERIFY #: lib/choose_repository.tcl:476 -#, tcl-format +#, fuzzy, tcl-format msgid "Unable to copy objects/info/alternates: %s" -msgstr "" +msgstr "Не могу скопировать объекты/инфо/альтернативы: %s" #: lib/choose_repository.tcl:512 #, fuzzy, tcl-format msgid "Nothing to clone from %s." msgstr "Получение изменений из %s " +# TOVERIFY #: lib/choose_repository.tcl:514 lib/choose_repository.tcl:728 #: lib/choose_repository.tcl:740 +#, fuzzy msgid "The 'master' branch has not been initialized." -msgstr "" +msgstr "Не инициализирована ветвь 'master'." +# TOVERIFY #: lib/choose_repository.tcl:527 +#, fuzzy msgid "Hardlinks are unavailable. Falling back to copying." -msgstr "" +msgstr "\"Жесткие ссылки\" не доступны. Буду использовать копирование." #: lib/choose_repository.tcl:539 #, fuzzy, tcl-format @@ -1027,55 +1087,64 @@ msgstr "Сжатие базы объектов" #: lib/choose_repository.tcl:571 msgid "KiB" -msgstr "" +msgstr "КБ" #: lib/choose_repository.tcl:595 #, tcl-format msgid "Unable to copy object: %s" -msgstr "" +msgstr "Не могу скопировать объект: %s" #: lib/choose_repository.tcl:605 msgid "Linking objects" -msgstr "" +msgstr "Связываю объекты" +# TOVERIFY #: lib/choose_repository.tcl:606 +#, fuzzy msgid "objects" -msgstr "" +msgstr "объектов" +# TOVERIFY #: lib/choose_repository.tcl:614 -#, tcl-format +#, fuzzy, tcl-format msgid "Unable to hardlink object: %s" -msgstr "" +msgstr "Не могу \"жестко связать\" объект: %s" +# TOVERIFY #: lib/choose_repository.tcl:669 +#, fuzzy msgid "Cannot fetch branches and objects. See console output for details." -msgstr "" +msgstr "Не могу получить ветви и объекты. Детали - на консоле." +# TOVERIFY #: lib/choose_repository.tcl:680 +#, fuzzy msgid "Cannot fetch tags. See console output for details." -msgstr "" +msgstr "Не могу получить таги. Детали - на консоле." +# TOVERIFY #: lib/choose_repository.tcl:704 +#, fuzzy msgid "Cannot determine HEAD. See console output for details." -msgstr "" +msgstr "Не могу определить главную ветвь. Детали - на консоле." #: lib/choose_repository.tcl:713 #, tcl-format msgid "Unable to cleanup %s" -msgstr "" +msgstr "Не могу почистить %s" #: lib/choose_repository.tcl:719 msgid "Clone failed." -msgstr "" +msgstr "Клонирование не удалось." #: lib/choose_repository.tcl:726 msgid "No default branch obtained." -msgstr "" +msgstr "Не возможно получить ветвь по умолчанию." #: lib/choose_repository.tcl:737 #, tcl-format msgid "Cannot resolve %s as a commit." -msgstr "" +msgstr "Не могу распознать %s как состояние." #: lib/choose_repository.tcl:749 #, fuzzy @@ -1085,15 +1154,15 @@ msgstr "Отсутствует рабочий каталог" #: lib/choose_repository.tcl:750 lib/index.tcl:15 lib/index.tcl:80 #: lib/index.tcl:149 msgid "files" -msgstr "" +msgstr "файлов" #: lib/choose_repository.tcl:779 msgid "Initial file checkout failed." -msgstr "" +msgstr "Первое получение файла не удалось." #: lib/choose_repository.tcl:795 msgid "Open" -msgstr "" +msgstr "Открыть" #: lib/choose_repository.tcl:805 #, fuzzy @@ -1140,36 +1209,31 @@ msgstr "Пустое выражения для определения верси #: lib/choose_rev.tcl:530 msgid "Updated" -msgstr "" +msgstr "Обновлено" #: lib/choose_rev.tcl:558 msgid "URL" -msgstr "" +msgstr "Ссылка" #: lib/commit.tcl:9 msgid "" "There is nothing to amend.\n" "\n" -"You are about to create the initial commit. There is no commit before this " -"to amend.\n" +"You are about to create the initial commit. There is no commit before this to amend.\n" msgstr "" "Отсутствует состояние для исправления.\n" "\n" -"Вы можете создать начальное сохраненное состояние. Других состояний для " -"исправления нет.\n" +"Вы можете создать начальное сохраненное состояние. Других состояний для исправления нет.\n" #: lib/commit.tcl:18 msgid "" "Cannot amend while merging.\n" "\n" -"You are currently in the middle of a merge that has not been fully " -"completed. You cannot amend the prior commit unless you first abort the " -"current merge activity.\n" +"You are currently in the middle of a merge that has not been fully completed. You cannot amend the prior commit unless you first abort the current merge activity.\n" msgstr "" "Невозможно исправить состояние во время объединения.\n" "\n" -"Текущее объединение не завершено. Невозможно исправить предыдущее " -"сохраненное состояние не прерывая текущее объединение.\n" +"Текущее объединение не завершено. Невозможно исправить предыдущее сохраненное состояние не прерывая текущее объединение.\n" #: lib/commit.tcl:49 msgid "Error loading commit data for amend:" @@ -1187,15 +1251,13 @@ msgstr "Неверная GIT_COMMITTER_IDENT:" msgid "" "Last scanned state does not match repository state.\n" "\n" -"Another Git program has modified this repository since the last scan. A " -"rescan must be performed before another commit can be created.\n" +"Another Git program has modified this repository since the last scan. A rescan must be performed before another commit can be created.\n" "\n" "The rescan will be automatically started now.\n" msgstr "" "Последнее прочитанное состояние репозитория не соответствует текущему.\n" "\n" -"С момента последней проверки репозиторий был изменен другой программой Git." -"Необходимо перечитать репозиторий, прежде чем изменять текущую ветвь. \n" +"С момента последней проверки репозиторий был изменен другой программой Git.Необходимо перечитать репозиторий, прежде чем изменять текущую ветвь. \n" "\n" "Это будет сделано сейчас автоматически.\n" @@ -1204,13 +1266,11 @@ msgstr "" msgid "" "Unmerged files cannot be committed.\n" "\n" -"File %s has merge conflicts. You must resolve them and stage the file " -"before committing.\n" +"File %s has merge conflicts. You must resolve them and stage the file before committing.\n" msgstr "" "Нельзя сохранить необъединенные файлы.\n" "\n" -"Для файла %s возник конфликт объединения. Разрешите конфликт и добавьте к " -"подготовленным файлам перед сохранением.\n" +"Для файла %s возник конфликт объединения. Разрешите конфликт и добавьте к подготовленным файлам перед сохранением.\n" #: lib/commit.tcl:162 #, tcl-format @@ -1259,7 +1319,7 @@ msgstr "Программа write-tree завершилась с ошибкой:" #: lib/commit.tcl:275 #, tcl-format msgid "Commit %s appears to be corrupt" -msgstr "" +msgstr "Состояние %s выглядит поврежденным" #: lib/commit.tcl:279 msgid "" @@ -1282,7 +1342,7 @@ msgstr "Отуствуют измения для сохранения." #: lib/commit.tcl:303 #, tcl-format msgid "warning: Tcl does not support encoding '%s'." -msgstr "" +msgstr "предупреждение: Tcl не поддерживает кодировку '%s'." #: lib/commit.tcl:317 msgid "commit-tree failed:" @@ -1350,11 +1410,15 @@ msgstr "Проверка базы объектов при помощи fsck" msgid "" "This repository currently has approximately %i loose objects.\n" "\n" -"To maintain optimal performance it is strongly recommended that you compress " -"the database when more than %i loose objects exist.\n" +"To maintain optimal performance it is strongly recommended that you compress the database when more than %i loose objects exist.\n" "\n" "Compress the database now?" msgstr "" +"Этот репозиторий сейчас содержит примерно %i свободных объектов\n" +"\n" +"Для лучшей производительности рекомендуется сжать базу данных, когда есть более %i свободных объектов.\n" +"\n" +"Сжать базу данных сейчас?" #: lib/date.tcl:25 #, fuzzy, tcl-format @@ -1368,18 +1432,15 @@ msgid "" "\n" "%s has no changes.\n" "\n" -"The modification date of this file was updated by another application, but " -"the content within the file was not changed.\n" +"The modification date of this file was updated by another application, but the content within the file was not changed.\n" "\n" -"A rescan will be automatically started to find other files which may have " -"the same state." +"A rescan will be automatically started to find other files which may have the same state." msgstr "" "Изменений не обнаружено.\n" "\n" "в %s отутствуют изменения.\n" "\n" -"Дата изменения файла была обновлена другой программой, но содержимое файла " -"осталось прежним.\n" +"Дата изменения файла была обновлена другой программой, но содержимое файла осталось прежним.\n" "\n" "Сейчас будет запущено перечитывание репозитория, чтобы найти подобные файлы." @@ -1391,7 +1452,7 @@ msgstr "Загрузка %s..." #: lib/diff.tcl:114 lib/diff.tcl:184 #, tcl-format msgid "Unable to display %s" -msgstr "" +msgstr "Не могу показать %s" #: lib/diff.tcl:115 msgid "Error loading file:" @@ -1399,11 +1460,11 @@ msgstr "Ошибка загрузки файла:" #: lib/diff.tcl:122 msgid "Git Repository (subproject)" -msgstr "" +msgstr "Репозиторий Git (под-проект)" #: lib/diff.tcl:134 msgid "* Binary file (not showing content)." -msgstr "" +msgstr "* Двоичный файл (содержимое не показано)" #: lib/diff.tcl:185 msgid "Error loading diff:" @@ -1455,8 +1516,7 @@ msgid "Any unstaged changes will be permanently lost by the revert." msgstr "" "Отменить изменения в %s?\n" "\n" -"Любые изменения, не подготовленные к сохранению, будут потеряны при данной " -"операции." +"Любые изменения, не подготовленные к сохранению, будут потеряны при данной операции." #: lib/index.tcl:351 msgid "Do Nothing" @@ -1470,22 +1530,19 @@ msgid "" msgstr "" "Невозможно выполнить объединение во время исправления.\n" "\n" -"Завершите исправление данного состояния перед выполнением операции " -"объединения.\n" +"Завершите исправление данного состояния перед выполнением операции объединения.\n" #: lib/merge.tcl:27 msgid "" "Last scanned state does not match repository state.\n" "\n" -"Another Git program has modified this repository since the last scan. A " -"rescan must be performed before a merge can be performed.\n" +"Another Git program has modified this repository since the last scan. A rescan must be performed before a merge can be performed.\n" "\n" "The rescan will be automatically started now.\n" msgstr "" "Последнее прочитанное состояние репозитория не соответствует текущему.\n" "\n" -"С момента последней проверки репозиторий был изменен другой программой Git." -"Необходимо перечитать репозиторий, прежде чем изменять текущую ветвь. \n" +"С момента последней проверки репозиторий был изменен другой программой Git.Необходимо перечитать репозиторий, прежде чем изменять текущую ветвь. \n" "\n" "Это будет сделано сейчас автоматически.\n" @@ -1496,14 +1553,12 @@ msgid "" "\n" "File %s has merge conflicts.\n" "\n" -"You must resolve them, stage the file, and commit to complete the current " -"merge. Only then can you begin another merge.\n" +"You must resolve them, stage the file, and commit to complete the current merge. Only then can you begin another merge.\n" msgstr "" "Предыдущее объединение не завершено из-за конфликта.\n" "\n" "Для файла %s возник конфликт объединения.\n" -"Разрешите конфликт, подготовьте файл и сохраните. Только после этого можно " -"начать следующее объединение.\n" +"Разрешите конфликт, подготовьте файл и сохраните. Только после этого можно начать следующее объединение.\n" #: lib/merge.tcl:54 #, tcl-format @@ -1512,20 +1567,18 @@ msgid "" "\n" "File %s is modified.\n" "\n" -"You should complete the current commit before starting a merge. Doing so " -"will help you abort a failed merge, should the need arise.\n" +"You should complete the current commit before starting a merge. Doing so will help you abort a failed merge, should the need arise.\n" msgstr "" "Изменения не сохранены.\n" "\n" "Файл %s изменен.\n" "\n" -"Подготовьте и сохраните измения перед началом объединения. В случае " -"необходимости это позволит прервать операцию объединения.\n" +"Подготовьте и сохраните измения перед началом объединения. В случае необходимости это позволит прервать операцию объединения.\n" #: lib/merge.tcl:106 #, tcl-format msgid "%s of %s" -msgstr "" +msgstr "%s из %s" #: lib/merge.tcl:119 #, tcl-format @@ -1589,11 +1642,11 @@ msgstr "" #: lib/merge.tcl:239 msgid "Aborting" -msgstr "" +msgstr "Прерываю" #: lib/merge.tcl:266 msgid "Abort failed." -msgstr "" +msgstr "Прервать не удалось." #: lib/merge.tcl:268 msgid "Abort completed. Ready." @@ -1664,15 +1717,17 @@ msgstr "Шрифт интерфейса" #: lib/option.tcl:180 #, tcl-format msgid "Choose %s" -msgstr "" +msgstr "Выберите %s" +# carbon copy #: lib/option.tcl:186 +#, fuzzy msgid "pt." -msgstr "" +msgstr "pt." #: lib/option.tcl:200 msgid "Preferences" -msgstr "" +msgstr "Настройки" #: lib/option.tcl:235 msgid "Failed to completely save options:" @@ -1737,12 +1792,11 @@ msgid "" " - %s" msgstr "Следующие ветви объединены с %s не полностью:" +# TOVERIFY #: lib/remote_branch_delete.tcl:189 -#, tcl-format -msgid "" -"One or more of the merge tests failed because you have not fetched the " -"necessary commits. Try fetching from %s first." -msgstr "" +#, fuzzy, tcl-format +msgid "One or more of the merge tests failed because you have not fetched the necessary commits. Try fetching from %s first." +msgstr "Один или несколько тестов на объединение не прошли, потому что Вы не получили необходимые состояния. Попробуйте сначала получить из %s." #: lib/remote_branch_delete.tcl:207 msgid "Please select one or more branches to delete." @@ -1795,10 +1849,11 @@ msgstr "Получить" msgid "Fetching new changes from %s" msgstr "Получение изменений из %s " +# carbon copy #: lib/transport.tcl:18 -#, tcl-format +#, fuzzy, tcl-format msgid "remote prune %s" -msgstr "" +msgstr "remote prune %s" #: lib/transport.tcl:19 #, tcl-format @@ -1808,7 +1863,7 @@ msgstr "Чистка ветвей слежения, удаленных из %s" #: lib/transport.tcl:25 lib/transport.tcl:71 #, tcl-format msgid "push %s" -msgstr "" +msgstr "отправить %s" #: lib/transport.tcl:26 #, tcl-format @@ -1838,7 +1893,7 @@ msgstr "Настройки передачи" #: lib/transport.tcl:160 msgid "Force overwrite existing branch (may discard changes)" -msgstr "" +msgstr "Намеренно переписать существующую ветвь (возможна потеря изменений)" #: lib/transport.tcl:164 msgid "Use thin pack (for slow network connections)" @@ -1850,19 +1905,14 @@ msgstr "Включить метки" #~ msgid "Cannot find the git directory:" #~ msgstr "Каталог Git не найден:" - #~ msgid "Add To Commit" #~ msgstr "Подготовить к сохранению" - #~ msgid "Add Existing To Commit" #~ msgstr "Подготовить имеющиеся файлы к сохранению" - #~ msgid "Unstaged Changes (Will Not Be Committed)" #~ msgstr "Изменено (не будет сохранено)" - #~ msgid "Add Existing" #~ msgstr "Добавить имеющиеся файлы" - #~ msgid "" #~ "Abort commit?\n" #~ "\n" @@ -1876,9 +1926,8 @@ msgstr "Включить метки" #~ "Вызванная операция приведет к потере *ВСЕХ* несохраненных изменений.\n" #~ "\n" #~ "Продолжить?" - #~ msgid "Aborting... please wait..." #~ msgstr "Прерывание выполнения... Пожалуйста, ждите..." - #~ msgid "Push to %s..." #~ msgstr "Отправка в %s..." + From dd8175f83c725619d72d6bbaacf8eaafc158edea Mon Sep 17 00:00:00 2001 From: Ralf Wildenhues Date: Sun, 21 Oct 2007 11:36:19 +0200 Subject: [PATCH 0255/1490] git-cherry-pick: improve description of -x. Reword the first sentence of the description of -x, in order to make it easier to read and understand. Signed-off-by: Ralf Wildenhues Signed-off-by: Shawn O. Pearce --- Documentation/git-cherry-pick.txt | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Documentation/git-cherry-pick.txt b/Documentation/git-cherry-pick.txt index 47b1e8c2fc..76a2edfd9b 100644 --- a/Documentation/git-cherry-pick.txt +++ b/Documentation/git-cherry-pick.txt @@ -27,11 +27,12 @@ OPTIONS message prior committing. -x:: - Cause the command to append which commit was - cherry-picked after the original commit message when - making a commit. Do not use this option if you are - cherry-picking from your private branch because the - information is useless to the recipient. If on the + When recording the commit, append to the original commit + message a note that indicates which commit this change + was cherry-picked from. Append the note only for cherry + picks without conflicts. Do not use this option if + you are cherry-picking from your private branch because + the information is useless to the recipient. If on the other hand you are cherry-picking between two publicly visible branches (e.g. backporting a fix to a maintenance branch for an older release from a From e076a0e71f25430205d0437c177fd12a7018e5ad Mon Sep 17 00:00:00 2001 From: David Symonds Date: Mon, 22 Oct 2007 10:28:03 +1000 Subject: [PATCH 0256/1490] gitweb: Provide title attributes for abbreviated author names. Signed-off-by: David Symonds Signed-off-by: Shawn O. Pearce --- gitweb/gitweb.perl | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 48e21dad6c..0d45769bc3 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -3437,9 +3437,15 @@ sub git_shortlog_body { print "\n"; } $alternate ^= 1; + my $author = chop_str($co{'author_name'}, 10); + if ($author ne $co{'author_name'}) { + $author = "" . esc_html($author) . ""; + } else { + $author = esc_html($author); + } # git_summary() used print "$co{'age_string'}\n" . print "$co{'age_string_date'}\n" . - "" . esc_html(chop_str($co{'author_name'}, 10)) . "\n" . + "" . $author . "\n" . ""; print format_subject_html($co{'title'}, $co{'title_short'}, href(action=>"commit", hash=>$commit), $ref); @@ -3487,9 +3493,15 @@ sub git_history_body { print "\n"; } $alternate ^= 1; + # shortlog uses chop_str($co{'author_name'}, 10) + my $author = chop_str($co{'author_name'}, 15, 3); + if ($author ne $co{'author_name'}) { + "" . esc_html($author) . ""; + } else { + $author = esc_html($author); + } print "$co{'age_string_date'}\n" . - # shortlog uses chop_str($co{'author_name'}, 10) - "" . esc_html(chop_str($co{'author_name'}, 15, 3)) . "\n" . + "" . $author . "\n" . ""; # originally git_history used chop_str($co{'title'}, 50) print format_subject_html($co{'title'}, $co{'title_short'}, @@ -3643,8 +3655,14 @@ sub git_search_grep_body { print "\n"; } $alternate ^= 1; + my $author = chop_str($co{'author_name'}, 15, 5); + if ($author ne $co{'author_name'}) { + $author = "" . esc_html($author) . ""; + } else { + $author = esc_html($author); + } print "$co{'age_string_date'}\n" . - "" . esc_html(chop_str($co{'author_name'}, 15, 5)) . "\n" . + "" . $author . "\n" . "" . $cgi->a({-href => href(action=>"commit", hash=>$co{'id'}), -class => "list subject"}, esc_html(chop_str($co{'title'}, 50)) . "
"); @@ -5157,8 +5175,14 @@ sub git_search { print "\n"; } $alternate ^= 1; + my $author = chop_str($co{'author_name'}, 15, 5); + if ($author ne $co{'author_name'}) { + $author = "" . esc_html($author) . ""; + } else { + $author = esc_html($author); + } print "$co{'age_string_date'}\n" . - "" . esc_html(chop_str($co{'author_name'}, 15, 5)) . "\n" . + "" . $author . "\n" . "" . $cgi->a({-href => href(action=>"commit", hash=>$co{'id'}), -class => "list subject"}, From b5d21a4b68aa69c7a2b4d2239aaa9ee5a51058a7 Mon Sep 17 00:00:00 2001 From: Jari Aalto Date: Sun, 21 Oct 2007 01:41:41 +0300 Subject: [PATCH 0257/1490] On error, do not list all commands, but point to --help option - Remove out call to list_common_cmds_help() - Send error message to stderr, not stdout. Signed-off-by: Jari Aalto Signed-off-by: Shawn O. Pearce --- help.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/help.c b/help.c index 1cd33ece6b..814a8cd02a 100644 --- a/help.c +++ b/help.c @@ -185,8 +185,7 @@ static void show_man_page(const char *git_cmd) void help_unknown_cmd(const char *cmd) { - printf("git: '%s' is not a git-command\n\n", cmd); - list_common_cmds_help(); + fprintf(stderr, "git: '%s' is not a git-command. See --help\n\n", cmd); exit(1); } From 7a39a17a873b818e3a4d121b3a43baf10f68cf61 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Tue, 23 Oct 2007 10:15:11 +1000 Subject: [PATCH 0258/1490] gitk: Limit diff display to listed paths by default When the user has specified a list of paths, either on the command line or when creating a view, gitk currently displays the diffs for all files that a commit has modified, not just the ones that match the path list. This is different from other git commands such as git log. This change makes gitk behave the same as these other git commands by default, that is, gitk only displays the diffs for files that match the path list. There is now a checkbox labelled "Limit diffs to listed paths" in the Edit/Preferences pane. If that is unchecked, gitk will display the diffs for all files as before. When gitk is run with the --merge flag, it will get the list of unmerged files at startup, intersect that with the paths listed on the command line (if any), and use that as the list of paths. Signed-off-by: Paul Mackerras --- gitk | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 86 insertions(+), 10 deletions(-) diff --git a/gitk b/gitk index 41a1c69e19..248f5fbd04 100755 --- a/gitk +++ b/gitk @@ -1019,7 +1019,7 @@ proc savestuff {w} { global stuffsaved findmergefiles maxgraphpct global maxwidth showneartags showlocalchanges global viewname viewfiles viewargs viewperm nextviewnum - global cmitmode wrapcomment datetimeformat + global cmitmode wrapcomment datetimeformat limitdiffs global colors bgcolor fgcolor diffcolors diffcontext selectbgcolor if {$stuffsaved} return @@ -1038,6 +1038,7 @@ proc savestuff {w} { puts $f [list set showneartags $showneartags] puts $f [list set showlocalchanges $showlocalchanges] puts $f [list set datetimeformat $datetimeformat] + puts $f [list set limitdiffs $limitdiffs] puts $f [list set bgcolor $bgcolor] puts $f [list set fgcolor $fgcolor] puts $f [list set colors $colors] @@ -5015,9 +5016,31 @@ proc startdiff {ids} { } } +proc path_filter {filter name} { + foreach p $filter { + set l [string length $p] + if {[string compare -length $l $p $name] == 0 && + ([string length $name] == $l || [string index $name $l] eq "/")} { + return 1 + } + } + return 0 +} + proc addtocflist {ids} { - global treediffs cflist - add_flist $treediffs($ids) + global treediffs cflist viewfiles curview limitdiffs + + if {$limitdiffs && $viewfiles($curview) ne {}} { + set flist {} + foreach f $treediffs($ids) { + if {[path_filter $viewfiles($curview) $f]} { + lappend flist $f + } + } + } else { + set flist $treediffs($ids) + } + add_flist $flist getblobdiffs $ids } @@ -5124,9 +5147,14 @@ proc getblobdiffs {ids} { global diffopts blobdifffd diffids env global diffinhdr treediffs global diffcontext + global limitdiffs viewfiles curview set env(GIT_DIFF_OPTS) $diffopts - if {[catch {set bdf [open [diffcmd $ids "-p -C --no-commit-id -U$diffcontext"] r]} err]} { + set cmd [diffcmd $ids "-p -C --no-commit-id -U$diffcontext"] + if {$limitdiffs && $viewfiles($curview) ne {}} { + set cmd [concat $cmd $viewfiles($curview)] + } + if {[catch {set bdf [open $cmd r]} err]} { puts "error getting diffs: $err" return } @@ -7382,7 +7410,7 @@ proc doprefs {} { global maxwidth maxgraphpct diffopts global oldprefs prefstop showneartags showlocalchanges global bgcolor fgcolor ctext diffcolors selectbgcolor - global uifont tabstop + global uifont tabstop limitdiffs set top .gitkprefs set prefstop $top @@ -7390,7 +7418,8 @@ proc doprefs {} { raise $top return } - foreach v {maxwidth maxgraphpct diffopts showneartags showlocalchanges} { + foreach v {maxwidth maxgraphpct diffopts showneartags showlocalchanges \ + limitdiffs} { set oldprefs($v) [set $v] } toplevel $top @@ -7428,6 +7457,11 @@ proc doprefs {} { label $top.tabstopl -text "tabstop" -font optionfont spinbox $top.tabstop -from 1 -to 20 -width 4 -textvariable tabstop grid x $top.tabstopl $top.tabstop -sticky w + frame $top.ldiff + label $top.ldiff.l -text "Limit diffs to listed paths" -font optionfont + checkbutton $top.ldiff.b -variable limitdiffs + pack $top.ldiff.b $top.ldiff.l -side left + grid x $top.ldiff -sticky w label $top.cdisp -text "Colors: press to choose" $top.cdisp configure -font $uifont @@ -7514,9 +7548,10 @@ proc setfg {c} { proc prefscan {} { global maxwidth maxgraphpct diffopts - global oldprefs prefstop showneartags showlocalchanges + global oldprefs prefstop showneartags showlocalchanges limitdiffs - foreach v {maxwidth maxgraphpct diffopts showneartags showlocalchanges} { + foreach v {maxwidth maxgraphpct diffopts showneartags showlocalchanges \ + limitdiffs} { set $v $oldprefs($v) } catch {destroy $prefstop} @@ -7526,7 +7561,7 @@ proc prefscan {} { proc prefsok {} { global maxwidth maxgraphpct global oldprefs prefstop showneartags showlocalchanges - global charspc ctext tabstop + global charspc ctext tabstop limitdiffs catch {destroy $prefstop} unset prefstop @@ -7541,7 +7576,8 @@ proc prefsok {} { if {$maxwidth != $oldprefs(maxwidth) || $maxgraphpct != $oldprefs(maxgraphpct)} { redisplay - } elseif {$showneartags != $oldprefs(showneartags)} { + } elseif {$showneartags != $oldprefs(showneartags) || + $limitdiffs != $oldprefs(limitdiffs)} { reselectline } } @@ -7869,6 +7905,7 @@ set showneartags 1 set maxrefs 20 set maxlinelen 200 set showlocalchanges 1 +set limitdiffs 1 set datetimeformat "%Y-%m-%d %H:%M:%S" set colors {green red blue magenta darkgrey brown orange} @@ -7892,6 +7929,7 @@ if {![file isdirectory $gitdir]} { exit 1 } +set mergeonly 0 set revtreeargs {} set cmdline_files {} set i 0 @@ -7899,6 +7937,10 @@ foreach arg $argv { switch -- $arg { "" { } "-d" { set datemode 1 } + "--merge" { + set mergeonly 1 + lappend revtreeargs $arg + } "--" { set cmdline_files [lrange $argv [expr {$i + 1}] end] break @@ -7939,6 +7981,40 @@ if {$i >= [llength $argv] && $revtreeargs ne {}} { } } +if {$mergeonly} { + # find the list of unmerged files + set mlist {} + set nr_unmerged 0 + if {[catch { + set fd [open "| git ls-files -u" r] + } err]} { + show_error {} . "Couldn't get list of unmerged files: $err" + exit 1 + } + while {[gets $fd line] >= 0} { + set i [string first "\t" $line] + if {$i < 0} continue + set fname [string range $line [expr {$i+1}] end] + if {[lsearch -exact $mlist $fname] >= 0} continue + incr nr_unmerged + if {$cmdline_files eq {} || [path_filter $cmdline_files $fname]} { + lappend mlist $fname + } + } + catch {close $fd} + if {$mlist eq {}} { + if {$nr_unmerged == 0} { + show_error {} . "No files selected: --merge specified but\ + no files are unmerged." + } else { + show_error {} . "No files selected: --merge specified but\ + no unmerged files are within file limit." + } + exit 1 + } + set cmdline_files $mlist +} + set nullid "0000000000000000000000000000000000000000" set nullid2 "0000000000000000000000000000000000000001" From 94503918e480123d0d4cf03b03153e4d83cdfd4e Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Tue, 23 Oct 2007 10:33:38 +1000 Subject: [PATCH 0259/1490] gitk: Ensure tabstop setting gets restored by Cancel button We weren't restoring the tabstop setting if the user pressed the Cancel button in the Edit/Preferences window. Also improved the label for the checkbox (made it "Tab spacing" rather than the laconic "tabstop") and moved it above the "Display nearby tags" checkbox. Signed-off-by: Paul Mackerras --- gitk | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/gitk b/gitk index 248f5fbd04..0d3705c43c 100755 --- a/gitk +++ b/gitk @@ -7419,7 +7419,7 @@ proc doprefs {} { return } foreach v {maxwidth maxgraphpct diffopts showneartags showlocalchanges \ - limitdiffs} { + limitdiffs tabstop} { set oldprefs($v) [set $v] } toplevel $top @@ -7449,14 +7449,14 @@ proc doprefs {} { -font optionfont entry $top.diffopt -width 20 -textvariable diffopts grid x $top.diffoptl $top.diffopt -sticky w + label $top.tabstopl -text "Tab spacing" -font optionfont + spinbox $top.tabstop -from 1 -to 20 -width 4 -textvariable tabstop + grid x $top.tabstopl $top.tabstop -sticky w frame $top.ntag label $top.ntag.l -text "Display nearby tags" -font optionfont checkbutton $top.ntag.b -variable showneartags pack $top.ntag.b $top.ntag.l -side left grid x $top.ntag -sticky w - label $top.tabstopl -text "tabstop" -font optionfont - spinbox $top.tabstop -from 1 -to 20 -width 4 -textvariable tabstop - grid x $top.tabstopl $top.tabstop -sticky w frame $top.ldiff label $top.ldiff.l -text "Limit diffs to listed paths" -font optionfont checkbutton $top.ldiff.b -variable limitdiffs @@ -7547,11 +7547,11 @@ proc setfg {c} { } proc prefscan {} { - global maxwidth maxgraphpct diffopts - global oldprefs prefstop showneartags showlocalchanges limitdiffs + global oldprefs prefstop foreach v {maxwidth maxgraphpct diffopts showneartags showlocalchanges \ - limitdiffs} { + limitdiffs tabstop} { + global $v set $v $oldprefs($v) } catch {destroy $prefstop} From dec2b4aaa87ab2b33d1ad8294872af1f1397ec7e Mon Sep 17 00:00:00 2001 From: Alex Riesen Date: Mon, 22 Oct 2007 22:28:48 +0200 Subject: [PATCH 0260/1490] More updates and corrections to the russian translation of git-gui In particular many screw-ups after po regeneration were fixed. Signed-off-by: Alex Riesen Signed-off-by: Shawn O. Pearce --- po/ru.po | 362 +++++++++++++++++++------------------------------------ 1 file changed, 127 insertions(+), 235 deletions(-) diff --git a/po/ru.po b/po/ru.po index ed5b67a95c..b8e9447942 100644 --- a/po/ru.po +++ b/po/ru.po @@ -8,8 +8,8 @@ msgstr "" "Project-Id-Version: git-gui\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2007-10-10 04:04-0400\n" -"PO-Revision-Date: 2007-10-20 14:29-0500\n" -"Last-Translator: Kirill \n" +"PO-Revision-Date: 2007-10-22 22:30-0200\n" +"Last-Translator: Alex Riesen \n" "Language-Team: Russian Translation \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -21,9 +21,9 @@ msgid "git-gui: fatal error" msgstr "git-gui: критическая ошибка" #: git-gui.sh:595 -#, fuzzy, tcl-format +#, tcl-format msgid "Invalid font specified in %s:" -msgstr "В оболочке установлен неверный шрифт.%s:" +msgstr "В %s установлен неверный шрифт:" #: git-gui.sh:620 msgid "Main Font" @@ -31,7 +31,7 @@ msgstr "Шрифт интерфейса" #: git-gui.sh:621 msgid "Diff/Console Font" -msgstr "Шрифт в консоли diff" +msgstr "Шрифт консоли и изменений (diff)" #: git-gui.sh:635 msgid "Cannot find git in PATH." @@ -64,9 +64,8 @@ msgid "Git directory not found:" msgstr "Каталог Git не найден:" #: git-gui.sh:860 -#, fuzzy msgid "Cannot move to top of working directory:" -msgstr "Каталог.git испорчен: " +msgstr "Невозможно перейти к корню рабочего каталога репозитория: " #: git-gui.sh:867 msgid "Cannot use funny .git directory:" @@ -78,7 +77,7 @@ msgstr "Отсутствует рабочий каталог" #: git-gui.sh:1019 msgid "Refreshing file status..." -msgstr "Обновление состояния файлов проекта..." +msgstr "Обновление информации о состоянии файлов..." #: git-gui.sh:1084 msgid "Scanning for modified files ..." @@ -94,7 +93,7 @@ msgstr "Не изменено" #: git-gui.sh:1527 msgid "Modified, not staged" -msgstr "Изменено, но не включено" +msgstr "Изменено, не подготовлено" #: git-gui.sh:1528 git-gui.sh:1533 msgid "Staged for commit" @@ -105,7 +104,6 @@ msgid "Portions staged for commit" msgstr "Части, подготовленные для сохранения" #: git-gui.sh:1530 git-gui.sh:1535 -#, fuzzy msgid "Staged for commit, missing" msgstr "Подготовлено для сохранения, отсутствует" @@ -123,7 +121,7 @@ msgstr "Подготовлено для удаления" #: git-gui.sh:1539 msgid "Staged for removal, still present" -msgstr "Подготовлено для удаления, но еще не удалено" +msgstr "Подготовлено для удаления, еще не удалено" #: git-gui.sh:1541 git-gui.sh:1542 git-gui.sh:1543 git-gui.sh:1544 msgid "Requires merge resolution" @@ -157,7 +155,6 @@ msgid "Branch" msgstr "Ветвь" #: git-gui.sh:1794 lib/choose_rev.tcl:547 -#, fuzzy msgid "Commit@@noun" msgstr "Состояние" @@ -166,18 +163,16 @@ msgid "Merge" msgstr "Объединить" #: git-gui.sh:1798 lib/choose_rev.tcl:556 -#, fuzzy msgid "Remote" -msgstr "внешний:" +msgstr "Внешние репозитории" #: git-gui.sh:1807 msgid "Browse Current Branch's Files" msgstr "Просмотреть файлы текущей ветви" #: git-gui.sh:1811 -#, fuzzy msgid "Browse Branch Files..." -msgstr "Показать файлы ветви" +msgstr "Показать файлы ветви..." #: git-gui.sh:1816 msgid "Visualize Current Branch's History" @@ -188,9 +183,9 @@ msgid "Visualize All Branch History" msgstr "История всех ветвей наглядно" #: git-gui.sh:1827 -#, fuzzy, tcl-format +#, tcl-format msgid "Browse %s's Files" -msgstr "Показать файлы ветви" +msgstr "Показать файлы ветви %s" #: git-gui.sh:1829 #, tcl-format @@ -281,12 +276,10 @@ msgid "Rescan" msgstr "Перечитать" #: git-gui.sh:1953 -#, fuzzy msgid "Stage To Commit" msgstr "Подготовить для сохранения" #: git-gui.sh:1958 -#, fuzzy msgid "Stage Changed Files To Commit" msgstr "Подготовить измененные файлы для сохранения" @@ -303,7 +296,6 @@ msgid "Sign Off" msgstr "Подписать" #: git-gui.sh:1980 git-gui.sh:2296 -#, fuzzy msgid "Commit@@verb" msgstr "Сохранить" @@ -319,11 +311,10 @@ msgstr "Прервать объединение..." msgid "Push..." msgstr "Отправить..." -# carbon copy #: git-gui.sh:2019 lib/choose_repository.tcl:41 #, fuzzy msgid "Apple" -msgstr "Apple" +msgstr "" #: git-gui.sh:2022 git-gui.sh:2044 lib/about.tcl:13 #: lib/choose_repository.tcl:44 lib/choose_repository.tcl:50 @@ -347,9 +338,8 @@ msgstr "Помощь" msgid "Online Documentation" msgstr "Документация в интернете" -# TOVERIFY #: git-gui.sh:2165 -#, fuzzy, tcl-format +#, tcl-format msgid "fatal: cannot stat path %s: No such file or directory" msgstr "критическая ошибка: %s: нет такого файла или каталога" @@ -358,43 +348,34 @@ msgid "Current Branch:" msgstr "Текущая ветвь:" #: git-gui.sh:2219 -#, fuzzy msgid "Staged Changes (Will Commit)" msgstr "Подготовлено (будет сохранено)" -# TOVERIFY #: git-gui.sh:2239 -#, fuzzy msgid "Unstaged Changes" -msgstr "Изменено" +msgstr "Изменено (не будет сохранено)" -# carbon copy #: git-gui.sh:2286 -#, fuzzy msgid "Stage Changed" -msgstr "Stage Changed" +msgstr "Подготовить все" #: git-gui.sh:2302 lib/transport.tcl:93 lib/transport.tcl:182 msgid "Push" msgstr "Отправить" #: git-gui.sh:2332 -#, fuzzy msgid "Initial Commit Message:" -msgstr "Первоначальный комментарий к состоянию:" +msgstr "Комментарий к первому состоянию:" #: git-gui.sh:2333 -#, fuzzy msgid "Amended Commit Message:" -msgstr "Исправленный комментарий к состоянию:" +msgstr "Комментарий к исправленному состоянию:" #: git-gui.sh:2334 -#, fuzzy msgid "Amended Initial Commit Message:" -msgstr "Первоначальный комментарий к исправленному состоянию:" +msgstr "Комментарий к исправленному первоначальному состоянию:" #: git-gui.sh:2335 -#, fuzzy msgid "Amended Merge Commit Message:" msgstr "Комментарий к исправленному объединению:" @@ -467,9 +448,7 @@ msgstr "" "запущенными из %s\n" "\n" -# TOVERIFY #: git-gui.sh:2707 -#, fuzzy msgid "" "\n" "This is due to a known issue with the\n" @@ -491,10 +470,10 @@ msgid "" msgstr "" "\n" "\n" -"Хорошая замена для %s\n" -"сохраняет значения для user.name и\n" -"user.email в Ваш персональный\n" -"~/.gitconfig файл.\n" +"Вместо использования %s можно\n" +"сохранить значения user.name и\n" +"user.email в Вашем персональном\n" +"файле ~/.gitconfig.\n" #: lib/about.tcl:25 msgid "git-gui - a graphical user interface for Git." @@ -510,69 +489,56 @@ msgstr "Сохраненное состояние:" #: lib/blame.tcl:249 msgid "Copy Commit" -msgstr "Копировать сохраненное состояние" +msgstr "Скопировать SHA-1" #: lib/blame.tcl:369 #, tcl-format msgid "Reading %s..." msgstr "Чтение %s..." -# carbon copy #: lib/blame.tcl:473 -#, fuzzy msgid "Loading copy/move tracking annotations..." -msgstr "Loading copy/move tracking annotations..." +msgstr "Загрузка аннотации копирований/переименований..." -# TOVERIFY #: lib/blame.tcl:493 -#, fuzzy msgid "lines annotated" -msgstr "строк прокоментировано" +msgstr "строк прокомментировано" -# carbon copy #: lib/blame.tcl:674 -#, fuzzy msgid "Loading original location annotations..." -msgstr "Loading original location annotations..." +msgstr "Загрузка аннотаций первоначального положения объекта..." -# carbon copy #: lib/blame.tcl:677 -#, fuzzy msgid "Annotation complete." -msgstr "Annotation complete." +msgstr "Аннотация завершена." #: lib/blame.tcl:731 -#, fuzzy msgid "Loading annotation..." -msgstr "Загрузка %s..." +msgstr "Загрузка аннотации..." #: lib/blame.tcl:787 msgid "Author:" msgstr "Автор:" #: lib/blame.tcl:791 -#, fuzzy msgid "Committer:" -msgstr "Сохраненное состояние:" +msgstr "Сохранил:" #: lib/blame.tcl:796 msgid "Original File:" msgstr "Исходный файл:" -# carbon copy #: lib/blame.tcl:910 -#, fuzzy msgid "Originally By:" -msgstr "Originally By:" +msgstr "Источник:" #: lib/blame.tcl:916 -#, fuzzy msgid "In File:" msgstr "Файл:" #: lib/blame.tcl:921 msgid "Copied Or Moved Here By:" -msgstr "Кто скопировал/переместил сюда:" +msgstr "Скопировано/перемещено в:" #: lib/branch_checkout.tcl:14 lib/branch_checkout.tcl:19 msgid "Checkout Branch" @@ -702,7 +668,7 @@ msgid "" "\n" " Delete the selected branches?" msgstr "" -"Восстановить удаленную ветвь сложно. \n" +"Восстанавливать удаленные ветви сложно. \n" "\n" " Удалить выбранные ветви?" @@ -773,14 +739,14 @@ msgid "Browse" msgstr "Показать" #: lib/checkout_op.tcl:79 -#, fuzzy, tcl-format +#, tcl-format msgid "Fetching %s from %s" -msgstr "Получение изменений из %s " +msgstr "Получение %s из %s " #: lib/checkout_op.tcl:127 #, tcl-format msgid "fatal: Cannot resolve %s" -msgstr "критическая ошибка: не могу распознать %s" +msgstr "критическая ошибка: невозможно разрешить %s" #: lib/checkout_op.tcl:140 lib/console.tcl:79 lib/database.tcl:31 msgid "Close" @@ -807,7 +773,7 @@ msgstr "" #: lib/checkout_op.tcl:220 #, tcl-format msgid "Merge strategy '%s' not supported." -msgstr "Операция объединения '%s' не поддерживается." +msgstr "Стратегия объединения '%s' не поддерживается." #: lib/checkout_op.tcl:239 #, tcl-format @@ -815,9 +781,8 @@ msgid "Failed to update '%s'." msgstr "Не удалось обновить '%s'." #: lib/checkout_op.tcl:251 -#, fuzzy msgid "Staging area (index) is already locked." -msgstr "Индекс заблокирован." +msgstr "Рабочая область заблокирована другим процессом." #: lib/checkout_op.tcl:266 msgid "" @@ -829,14 +794,15 @@ msgid "" msgstr "" "Последнее прочитанное состояние репозитория не соответствует текущему.\n" "\n" -"С момента последней проверки репозиторий был изменен другой программой Git.Необходимо перечитать репозиторий, прежде чем изменять текущую ветвь. \n" +"С момента последней проверки репозиторий был изменен другой программой Git. " +"Необходимо перечитать репозиторий, прежде чем изменять текущую ветвь.\n" "\n" "Это будет сделано сейчас автоматически.\n" #: lib/checkout_op.tcl:322 -#, fuzzy, tcl-format +#, tcl-format msgid "Updating working directory to '%s'..." -msgstr "Отсутствует рабочий каталог" +msgstr "Обновление рабочего каталога из '%s'..." #: lib/checkout_op.tcl:353 #, tcl-format @@ -863,9 +829,9 @@ msgstr "" "Если вы хотите снова вернуться к какой-нибудь ветви, создайте ее сейчас, начиная с 'Текущего отсоединенного состояния'." #: lib/checkout_op.tcl:446 -#, fuzzy, tcl-format +#, tcl-format msgid "Checked out '%s'." -msgstr "Перейти..." +msgstr "Ветвь '%s' сделана текущей." #: lib/checkout_op.tcl:478 #, tcl-format @@ -901,7 +867,6 @@ msgstr "" "Этого не должно было произойти. %s завершается." #: lib/choose_font.tcl:39 -#, fuzzy msgid "Select" msgstr "Выделить все" @@ -910,15 +875,13 @@ msgid "Font Family" msgstr "Шрифт" #: lib/choose_font.tcl:73 -#, fuzzy msgid "Font Size" -msgstr "Уменьшить размер шрифта" +msgstr "Размер шрифта" #: lib/choose_font.tcl:90 msgid "Font Example" msgstr "Пример текста" -# TOVERIFY: what's the Russian version of the font sample (see Windows Fonts). #: lib/choose_font.tcl:101 msgid "" "This is example text.\n" @@ -929,39 +892,34 @@ msgstr "" #: lib/choose_repository.tcl:25 msgid "Git Gui" -msgstr "Git Gui" +msgstr "" #: lib/choose_repository.tcl:69 lib/choose_repository.tcl:204 -#, fuzzy msgid "Create New Repository" -msgstr "Из репозитория" +msgstr "Создать новый репозиторий" #: lib/choose_repository.tcl:74 lib/choose_repository.tcl:291 -#, fuzzy msgid "Clone Existing Repository" -msgstr "Репозиторий назначения" +msgstr "Склонировать существующий репозиторий" #: lib/choose_repository.tcl:79 lib/choose_repository.tcl:800 -#, fuzzy msgid "Open Existing Repository" -msgstr "Репозиторий назначения" +msgstr "Выбрать существующий репозиторий" -# TOVERIFY #: lib/choose_repository.tcl:91 -#, fuzzy msgid "Next >" msgstr "Дальше >" #: lib/choose_repository.tcl:152 -#, fuzzy, tcl-format +#, tcl-format msgid "Location %s already exists." -msgstr "Ветвь '%s' уже существует." +msgstr "Путь '%s' уже существует." #: lib/choose_repository.tcl:158 lib/choose_repository.tcl:165 #: lib/choose_repository.tcl:172 -#, fuzzy, tcl-format +#, tcl-format msgid "Failed to create repository %s:" -msgstr "Не удалось полностью сохранить настройки:" +msgstr "Не удалось создать репозиторий %s:" #: lib/choose_repository.tcl:209 lib/choose_repository.tcl:309 msgid "Directory:" @@ -969,121 +927,98 @@ msgstr "Каталог:" #: lib/choose_repository.tcl:238 lib/choose_repository.tcl:363 #: lib/choose_repository.tcl:834 -#, fuzzy msgid "Git Repository" msgstr "Репозиторий" #: lib/choose_repository.tcl:253 lib/choose_repository.tcl:260 -#, fuzzy, tcl-format +#, tcl-format msgid "Directory %s already exists." -msgstr "Ветвь '%s' уже существует." +msgstr "Каталог '%s' уже существует." #: lib/choose_repository.tcl:265 -#, fuzzy, tcl-format +#, tcl-format msgid "File %s already exists." -msgstr "Ветвь '%s' уже существует." +msgstr "Файл '%s' уже существует." #: lib/choose_repository.tcl:286 -#, fuzzy msgid "Clone" -msgstr "Закрыть" +msgstr "Склонировать" #: lib/choose_repository.tcl:299 msgid "URL:" msgstr "Ссылка:" -# TOVERIFY #: lib/choose_repository.tcl:319 -#, fuzzy msgid "Clone Type:" msgstr "Тип клона:" -# TOVERIFY #: lib/choose_repository.tcl:325 -#, fuzzy msgid "Standard (Fast, Semi-Redundant, Hardlinks)" msgstr "Стандартный (Быстрый, полуизбыточный, \"жесткие\" ссылки)" -# TOVERIFY #: lib/choose_repository.tcl:331 -#, fuzzy msgid "Full Copy (Slower, Redundant Backup)" -msgstr "Полная копия (Медленный, избыточная резервная копия)" +msgstr "Полная копия (Медленный, создает резервную копию)" -# TOVERIFY #: lib/choose_repository.tcl:337 -#, fuzzy msgid "Shared (Fastest, Not Recommended, No Backup)" msgstr "Общий (Самый быстрый, не рекомендуется, без резервной копии)" #: lib/choose_repository.tcl:369 lib/choose_repository.tcl:418 #: lib/choose_repository.tcl:560 lib/choose_repository.tcl:630 #: lib/choose_repository.tcl:840 lib/choose_repository.tcl:848 -#, fuzzy, tcl-format +#, tcl-format msgid "Not a Git repository: %s" -msgstr "Не указан репозиторий" +msgstr "Каталог не является репозиторием: %s" -# TOVERIFY #: lib/choose_repository.tcl:405 -#, fuzzy msgid "Standard only available for local repository." msgstr "Стандартный клон возможен только для локального репозитория." -# TOVERIFY #: lib/choose_repository.tcl:409 -#, fuzzy msgid "Shared only available for local repository." msgstr "Общий клон возможен только для локального репозитория." -# TOVERIFY #: lib/choose_repository.tcl:439 -#, fuzzy msgid "Failed to configure origin" -msgstr "Не могу сконфигурировать искходник." +msgstr "Не могу сконфигурировать исходный репозиторий." #: lib/choose_repository.tcl:451 msgid "Counting objects" msgstr "Считаю объекты" -# carbon copy #: lib/choose_repository.tcl:452 #, fuzzy msgid "buckets" -msgstr "buckets" +msgstr "" -# TOVERIFY #: lib/choose_repository.tcl:476 -#, fuzzy, tcl-format +#, tcl-format msgid "Unable to copy objects/info/alternates: %s" -msgstr "Не могу скопировать объекты/инфо/альтернативы: %s" +msgstr "Не могу скопировать objects/info/alternates: %s" #: lib/choose_repository.tcl:512 -#, fuzzy, tcl-format +#, tcl-format msgid "Nothing to clone from %s." -msgstr "Получение изменений из %s " +msgstr "Нечего клонировать с %s." -# TOVERIFY #: lib/choose_repository.tcl:514 lib/choose_repository.tcl:728 #: lib/choose_repository.tcl:740 -#, fuzzy msgid "The 'master' branch has not been initialized." msgstr "Не инициализирована ветвь 'master'." -# TOVERIFY #: lib/choose_repository.tcl:527 -#, fuzzy msgid "Hardlinks are unavailable. Falling back to copying." msgstr "\"Жесткие ссылки\" не доступны. Буду использовать копирование." #: lib/choose_repository.tcl:539 -#, fuzzy, tcl-format +#, tcl-format msgid "Cloning from %s" -msgstr "Получение изменений из %s " +msgstr "Клонирование %s" #: lib/choose_repository.tcl:570 -#, fuzzy msgid "Copying objects" -msgstr "Сжатие базы объектов" +msgstr "Копирование objects" #: lib/choose_repository.tcl:571 msgid "KiB" @@ -1096,42 +1031,33 @@ msgstr "Не могу скопировать объект: %s" #: lib/choose_repository.tcl:605 msgid "Linking objects" -msgstr "Связываю объекты" +msgstr "Создание ссылок на objects" -# TOVERIFY #: lib/choose_repository.tcl:606 -#, fuzzy msgid "objects" -msgstr "объектов" +msgstr "объекты" -# TOVERIFY #: lib/choose_repository.tcl:614 -#, fuzzy, tcl-format +#, tcl-format msgid "Unable to hardlink object: %s" msgstr "Не могу \"жестко связать\" объект: %s" -# TOVERIFY #: lib/choose_repository.tcl:669 -#, fuzzy msgid "Cannot fetch branches and objects. See console output for details." -msgstr "Не могу получить ветви и объекты. Детали - на консоле." +msgstr "Не могу получить ветви и объекты. Дополнительная информация на консоли." -# TOVERIFY #: lib/choose_repository.tcl:680 -#, fuzzy msgid "Cannot fetch tags. See console output for details." -msgstr "Не могу получить таги. Детали - на консоле." +msgstr "Не могу получить метки. Дополнительная информация на консоли." -# TOVERIFY #: lib/choose_repository.tcl:704 -#, fuzzy msgid "Cannot determine HEAD. See console output for details." -msgstr "Не могу определить главную ветвь. Детали - на консоле." +msgstr "Не могу определить HEAD. Дополнительная информация на консоли." #: lib/choose_repository.tcl:713 #, tcl-format msgid "Unable to cleanup %s" -msgstr "Не могу почистить %s" +msgstr "Не могу очистить %s" #: lib/choose_repository.tcl:719 msgid "Clone failed." @@ -1139,7 +1065,7 @@ msgstr "Клонирование не удалось." #: lib/choose_repository.tcl:726 msgid "No default branch obtained." -msgstr "Не возможно получить ветвь по умолчанию." +msgstr "Не было получено ветви по умолчанию." #: lib/choose_repository.tcl:737 #, tcl-format @@ -1147,9 +1073,8 @@ msgid "Cannot resolve %s as a commit." msgstr "Не могу распознать %s как состояние." #: lib/choose_repository.tcl:749 -#, fuzzy msgid "Creating working directory" -msgstr "Отсутствует рабочий каталог" +msgstr "Создаю рабочий каталог" #: lib/choose_repository.tcl:750 lib/index.tcl:15 lib/index.tcl:80 #: lib/index.tcl:149 @@ -1158,21 +1083,20 @@ msgstr "файлов" #: lib/choose_repository.tcl:779 msgid "Initial file checkout failed." -msgstr "Первое получение файла не удалось." +msgstr "Не удалось получить начальное состояние файлов репозитория." #: lib/choose_repository.tcl:795 msgid "Open" msgstr "Открыть" #: lib/choose_repository.tcl:805 -#, fuzzy msgid "Repository:" -msgstr "Репозиторий" +msgstr "Репозиторий:" #: lib/choose_repository.tcl:854 -#, fuzzy, tcl-format +#, tcl-format msgid "Failed to open repository %s:" -msgstr "Не удалось полностью сохранить настройки:" +msgstr "Не удалось открыть репозиторий %s:" #: lib/choose_rev.tcl:53 msgid "This Detached Checkout" @@ -1205,7 +1129,7 @@ msgstr "Версия не указана." #: lib/choose_rev.tcl:346 msgid "Revision expression is empty." -msgstr "Пустое выражения для определения версии." +msgstr "Пустое выражение для определения версии." #: lib/choose_rev.tcl:530 msgid "Updated" @@ -1223,7 +1147,7 @@ msgid "" msgstr "" "Отсутствует состояние для исправления.\n" "\n" -"Вы можете создать начальное сохраненное состояние. Других состояний для исправления нет.\n" +"Вы создаете первое состояние в репозитории, здесь еще нечего исправлять.\n" #: lib/commit.tcl:18 msgid "" @@ -1257,12 +1181,12 @@ msgid "" msgstr "" "Последнее прочитанное состояние репозитория не соответствует текущему.\n" "\n" -"С момента последней проверки репозиторий был изменен другой программой Git.Необходимо перечитать репозиторий, прежде чем изменять текущую ветвь. \n" +"С момента последней проверки репозиторий был изменен другой программой Git. Необходимо перечитать репозиторий, прежде чем изменять текущую ветвь. \n" "\n" "Это будет сделано сейчас автоматически.\n" #: lib/commit.tcl:154 -#, fuzzy, tcl-format +#, tcl-format msgid "" "Unmerged files cannot be committed.\n" "\n" @@ -1284,7 +1208,6 @@ msgstr "" "Файл %s не может быть сохранен данной программой.\n" #: lib/commit.tcl:170 -#, fuzzy msgid "" "No changes to commit.\n" "\n" @@ -1416,14 +1339,14 @@ msgid "" msgstr "" "Этот репозиторий сейчас содержит примерно %i свободных объектов\n" "\n" -"Для лучшей производительности рекомендуется сжать базу данных, когда есть более %i свободных объектов.\n" +"Для лучшей производительности рекомендуется сжать базу данных, когда есть более %i несвязанных объектов.\n" "\n" "Сжать базу данных сейчас?" #: lib/date.tcl:25 -#, fuzzy, tcl-format +#, tcl-format msgid "Invalid date from Git: %s" -msgstr "Неверная версия: %s" +msgstr "Неправильная дата в репозитории: %s" #: lib/diff.tcl:42 #, tcl-format @@ -1445,9 +1368,9 @@ msgstr "" "Сейчас будет запущено перечитывание репозитория, чтобы найти подобные файлы." #: lib/diff.tcl:81 -#, fuzzy, tcl-format +#, tcl-format msgid "Loading diff of %s..." -msgstr "Загрузка %s..." +msgstr "Загрузка изменений в %s..." #: lib/diff.tcl:114 lib/diff.tcl:184 #, tcl-format @@ -1460,7 +1383,7 @@ msgstr "Ошибка загрузки файла:" #: lib/diff.tcl:122 msgid "Git Repository (subproject)" -msgstr "Репозиторий Git (под-проект)" +msgstr "Репозиторий Git (подпроект)" #: lib/diff.tcl:134 msgid "* Binary file (not showing content)." @@ -1472,11 +1395,11 @@ msgstr "Ошибка загрузки diff:" #: lib/diff.tcl:302 msgid "Failed to unstage selected hunk." -msgstr "Не удалось исключить выбранную часть" +msgstr "Не удалось исключить выбранную часть." #: lib/diff.tcl:309 msgid "Failed to stage selected hunk." -msgstr "Не удалось подготовить к сохранению выбранную часть" +msgstr "Не удалось подготовить к сохранению выбранную часть." #: lib/error.tcl:12 lib/error.tcl:102 msgid "error" @@ -1491,19 +1414,19 @@ msgid "You must correct the above errors before committing." msgstr "Прежде чем сохранить, исправьте вышеуказанные ошибки." #: lib/index.tcl:241 -#, fuzzy, tcl-format +#, tcl-format msgid "Unstaging %s from commit" -msgstr "Убрать из подготовленного" +msgstr "Удаление %s из подготовленного" #: lib/index.tcl:285 -#, fuzzy, tcl-format +#, tcl-format msgid "Adding %s" -msgstr "Чтение %s..." +msgstr "Добавление %s..." #: lib/index.tcl:340 -#, fuzzy, tcl-format +#, tcl-format msgid "Revert changes in file %s?" -msgstr "Отменить изменения" +msgstr "Отменить изменения в файле %s?" #: lib/index.tcl:342 #, tcl-format @@ -1511,11 +1434,8 @@ msgid "Revert changes in these %i files?" msgstr "Отменить изменения в %i файле(-ах)?" #: lib/index.tcl:348 -#, fuzzy msgid "Any unstaged changes will be permanently lost by the revert." msgstr "" -"Отменить изменения в %s?\n" -"\n" "Любые изменения, не подготовленные к сохранению, будут потеряны при данной операции." #: lib/index.tcl:351 @@ -1542,12 +1462,12 @@ msgid "" msgstr "" "Последнее прочитанное состояние репозитория не соответствует текущему.\n" "\n" -"С момента последней проверки репозиторий был изменен другой программой Git.Необходимо перечитать репозиторий, прежде чем изменять текущую ветвь. \n" +"С момента последней проверки репозиторий был изменен другой программой Git. Необходимо перечитать репозиторий, прежде чем изменять текущую ветвь.\n" "\n" "Это будет сделано сейчас автоматически.\n" #: lib/merge.tcl:44 -#, fuzzy, tcl-format +#, tcl-format msgid "" "You are in the middle of a conflicted merge.\n" "\n" @@ -1599,9 +1519,8 @@ msgid "Merge Into %s" msgstr "Объединить с %s" #: lib/merge.tcl:177 -#, fuzzy msgid "Revision To Merge" -msgstr "Версия" +msgstr "Версия для объединения" #: lib/merge.tcl:212 msgid "" @@ -1622,12 +1541,12 @@ msgid "" "Continue with aborting the current merge?" msgstr "" "Прервать объединение?\n" +"\n" "Прерывание объединения приведет к потере *ВСЕХ* несохраненных изменений.\n" "\n" "Продолжить?" #: lib/merge.tcl:228 -#, fuzzy msgid "" "Reset changes?\n" "\n" @@ -1636,6 +1555,7 @@ msgid "" "Continue with resetting the current changes?" msgstr "" "Прервать объединение?\n" +"\n" "Прерывание объединения приведет к потере *ВСЕХ* несохраненных изменений.\n" "\n" "Продолжить?" @@ -1663,7 +1583,7 @@ msgstr "Сохранить" #: lib/option.tcl:96 #, tcl-format msgid "%s Repository" -msgstr "для репозитория %s " +msgstr "для репозитория %s" #: lib/option.tcl:97 msgid "Global (All Repositories)" @@ -1710,7 +1630,6 @@ msgid "New Branch Name Template" msgstr "Шаблон для имени новой ветви" #: lib/option.tcl:176 -#, fuzzy msgid "Change Font" msgstr "Шрифт интерфейса" @@ -1723,7 +1642,7 @@ msgstr "Выберите %s" #: lib/option.tcl:186 #, fuzzy msgid "pt." -msgstr "pt." +msgstr "" #: lib/option.tcl:200 msgid "Preferences" @@ -1734,17 +1653,14 @@ msgid "Failed to completely save options:" msgstr "Не удалось полностью сохранить настройки:" #: lib/remote.tcl:165 -#, fuzzy msgid "Prune from" -msgstr "Чистка %s... " +msgstr "Чистка" #: lib/remote.tcl:170 -#, fuzzy msgid "Fetch from" -msgstr "Чистка %s... " +msgstr "Получение из" #: lib/remote.tcl:213 -#, fuzzy msgid "Push to" msgstr "Отправить" @@ -1785,18 +1701,22 @@ msgid "A branch is required for 'Merged Into'." msgstr "Для опции 'Объединено с' требуется указать ветвь." #: lib/remote_branch_delete.tcl:184 -#, fuzzy, tcl-format +#, tcl-format msgid "" "The following branches are not completely merged into %s:\n" "\n" " - %s" -msgstr "Следующие ветви объединены с %s не полностью:" +msgstr "" +"Следующие ветви объединены с %s не полностью:" +"\n" +" - %s" -# TOVERIFY #: lib/remote_branch_delete.tcl:189 -#, fuzzy, tcl-format +#, tcl-format msgid "One or more of the merge tests failed because you have not fetched the necessary commits. Try fetching from %s first." -msgstr "Один или несколько тестов на объединение не прошли, потому что Вы не получили необходимые состояния. Попробуйте сначала получить из %s." +msgstr "" +"Один или несколько тестов на объединение не прошли, потому что " +"Вы не получили необходимые состояния. Попробуйте сначала получить их из %s." #: lib/remote_branch_delete.tcl:207 msgid "Please select one or more branches to delete." @@ -1819,7 +1739,7 @@ msgstr "Удаление ветвей из %s" #: lib/remote_branch_delete.tcl:286 msgid "No repository selected." -msgstr "Не указан репозиторий" +msgstr "Не указан репозиторий." #: lib/remote_branch_delete.tcl:291 #, tcl-format @@ -1840,9 +1760,9 @@ msgid "%s ... %*i of %*i %s (%3i%%)" msgstr "%s ... %*i из %*i %s (%3i%%)" #: lib/transport.tcl:6 -#, fuzzy, tcl-format +#, tcl-format msgid "fetch %s" -msgstr "Получить" +msgstr "получение %s" #: lib/transport.tcl:7 #, tcl-format @@ -1851,9 +1771,9 @@ msgstr "Получение изменений из %s " # carbon copy #: lib/transport.tcl:18 -#, fuzzy, tcl-format +#, tcl-format msgid "remote prune %s" -msgstr "remote prune %s" +msgstr "чистка внешнего %s" #: lib/transport.tcl:19 #, tcl-format @@ -1877,7 +1797,7 @@ msgstr "Отправка %s %s в %s" #: lib/transport.tcl:89 msgid "Push Branches" -msgstr "Отправить изменения" +msgstr "Отправить изменения в ветвях" #: lib/transport.tcl:103 msgid "Source Branches" @@ -1889,7 +1809,7 @@ msgstr "Репозиторий назначения" #: lib/transport.tcl:158 msgid "Transfer Options" -msgstr "Настройки передачи" +msgstr "Настройки отправки" #: lib/transport.tcl:160 msgid "Force overwrite existing branch (may discard changes)" @@ -1903,31 +1823,3 @@ msgstr "Использовать thin pack (для медленных сетев msgid "Include tags" msgstr "Включить метки" -#~ msgid "Cannot find the git directory:" -#~ msgstr "Каталог Git не найден:" -#~ msgid "Add To Commit" -#~ msgstr "Подготовить к сохранению" -#~ msgid "Add Existing To Commit" -#~ msgstr "Подготовить имеющиеся файлы к сохранению" -#~ msgid "Unstaged Changes (Will Not Be Committed)" -#~ msgstr "Изменено (не будет сохранено)" -#~ msgid "Add Existing" -#~ msgstr "Добавить имеющиеся файлы" -#~ msgid "" -#~ "Abort commit?\n" -#~ "\n" -#~ "Aborting the current commit will cause *ALL* uncommitted changes to be " -#~ "lost.\n" -#~ "\n" -#~ "Continue with aborting the current commit?" -#~ msgstr "" -#~ "Отменить изменения?\n" -#~ "\n" -#~ "Вызванная операция приведет к потере *ВСЕХ* несохраненных изменений.\n" -#~ "\n" -#~ "Продолжить?" -#~ msgid "Aborting... please wait..." -#~ msgstr "Прерывание выполнения... Пожалуйста, ждите..." -#~ msgid "Push to %s..." -#~ msgstr "Отправка в %s..." - From a137a90f49e30fdcb24da0f9ff5c21b28d9cb227 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Tue, 23 Oct 2007 21:12:49 +1000 Subject: [PATCH 0261/1490] gitk: Integrate the reset progress bar in the main frame This makes the reset function use a progress bar in the same location as the progress bars for reading in commits and for finding commits, instead of a progress bar in a separate detached window. The progress bar for resetting is red. This also puts "Resetting" in the status window while the reset is in progress. The setting of the status window is done through an extension of the interface used for setting the watch cursor. Signed-off-by: Paul Mackerras --- gitk | 48 +++++++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/gitk b/gitk index 3b3cc4bd93..722e47869b 100755 --- a/gitk +++ b/gitk @@ -626,6 +626,7 @@ proc makewindow {} { global bgcolor fgcolor bglist fglist diffcolors selectbgcolor global headctxmenu progresscanv progressitem progresscoords statusw global fprogitem fprogcoord lastprogupdate progupdatepending + global rprogitem rprogcoord global have_tk85 menu .bar @@ -752,9 +753,11 @@ proc makewindow {} { canvas $progresscanv -relief sunken -height $h -borderwidth 2 set progressitem [$progresscanv create rect -1 0 0 $h -fill green] set fprogitem [$progresscanv create rect -1 0 0 $h -fill yellow] + set rprogitem [$progresscanv create rect -1 0 0 $h -fill red] pack $progresscanv -side right -expand 1 -fill x set progresscoords {0 0} set fprogcoord 0 + set rprogcoord 0 bind $progresscanv adjustprogress set lastprogupdate [clock clicks -milliseconds] set progupdatepending 0 @@ -1110,6 +1113,7 @@ proc click {w} { proc adjustprogress {} { global progresscanv progressitem progresscoords global fprogitem fprogcoord lastprogupdate progupdatepending + global rprogitem rprogcoord set w [expr {[winfo width $progresscanv] - 4}] set x0 [expr {$w * [lindex $progresscoords 0]}] @@ -1117,6 +1121,7 @@ proc adjustprogress {} { set h [winfo height $progresscanv] $progresscanv coords $progressitem $x0 0 $x1 $h $progresscanv coords $fprogitem 0 0 [expr {$w * $fprogcoord}] $h + $progresscanv coords $rprogitem 0 0 [expr {$w * $rprogcoord}] $h set now [clock clicks -milliseconds] if {$now >= $lastprogupdate + 100} { set progupdatepending 0 @@ -4195,20 +4200,30 @@ proc settextcursor {c} { set curtextcursor $c } -proc nowbusy {what} { - global isbusy +proc nowbusy {what {name {}}} { + global isbusy busyname statusw if {[array names isbusy] eq {}} { . config -cursor watch settextcursor watch } set isbusy($what) 1 + set busyname($what) $name + if {$name ne {}} { + $statusw conf -text $name + } } proc notbusy {what} { - global isbusy maincursor textcursor + global isbusy maincursor textcursor busyname statusw - catch {unset isbusy($what)} + catch { + unset isbusy($what) + if {$busyname($what) ne {} && + [$statusw cget -text] eq $busyname($what)} { + $statusw conf -text {} + } + } if {[array names isbusy] eq {}} { . config -cursor $maincursor settextcursor $textcursor @@ -6432,32 +6447,23 @@ proc resethead {} { error_popup $err } else { dohidelocalchanges - set w ".resetprogress" - filerun $fd [list readresetstat $fd $w] - toplevel $w - wm transient $w - wm title $w "Reset progress" - message $w.m -text "Reset in progress, please wait..." \ - -justify center -aspect 1000 - pack $w.m -side top -fill x -padx 20 -pady 5 - canvas $w.c -width 150 -height 20 -bg white - $w.c create rect 0 0 0 20 -fill green -tags rect - pack $w.c -side top -fill x -padx 20 -pady 5 -expand 1 - nowbusy reset + filerun $fd [list readresetstat $fd] + nowbusy reset "Resetting" } } -proc readresetstat {fd w} { - global mainhead mainheadid showlocalchanges +proc readresetstat {fd} { + global mainhead mainheadid showlocalchanges rprogcoord if {[gets $fd line] >= 0} { if {[regexp {([0-9]+)% \(([0-9]+)/([0-9]+)\)} $line match p m n]} { - set x [expr {($m * 150) / $n}] - $w.c coords rect 0 0 $x 20 + set rprogcoord [expr {1.0 * $m / $n}] + adjustprogress } return 1 } - destroy $w + set rprogcoord 0 + adjustprogress notbusy reset if {[catch {close $fd} err]} { error_popup $err From 4570b7e9d716e939287dea8193b7d2fb82e9f192 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Tue, 23 Oct 2007 21:19:06 +1000 Subject: [PATCH 0262/1490] gitk: Use the status window for other functions This sets the status window when reading commits, searching through commits, cherry-picking or checking out a head. Signed-off-by: Paul Mackerras --- gitk | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/gitk b/gitk index 722e47869b..951d39e21e 100755 --- a/gitk +++ b/gitk @@ -111,7 +111,7 @@ proc start_rev_list {view} { fconfigure $fd -encoding $tclencoding } filerun $fd [list getcommitlines $fd $view] - nowbusy $view + nowbusy $view "Reading" if {$view == $curview} { set progressdirn 1 set progresscoords {0 0} @@ -4264,7 +4264,7 @@ proc dofind {{rev 0}} { set findstartline $selectedline } set findcurline $findstartline - nowbusy finding + nowbusy finding "Searching" if {$gdttype ne "containing:" && ![info exists filehighlight]} { after cancel do_file_hl $fh_serial do_file_hl $fh_serial @@ -4303,7 +4303,7 @@ proc findnext {restart} { } else { set find_dirn 1 run findmore - nowbusy finding + nowbusy finding "Searching" } } @@ -4316,7 +4316,7 @@ proc findprev {} { } else { set find_dirn -1 run findmorerev - nowbusy finding + nowbusy finding "Searching" } } @@ -6381,7 +6381,7 @@ proc cherrypick {} { included in branch $mainhead -- really re-apply it?"] if {!$ok} return } - nowbusy cherrypick + nowbusy cherrypick "Cherry-picking" update # Unfortunately git-cherry-pick writes stuff to stderr even when # no error occurs, and exec takes that as an indication of error... @@ -6505,7 +6505,7 @@ proc cobranch {} { # check the tree is clean first?? set oldmainhead $mainhead - nowbusy checkout + nowbusy checkout "Checking out" update dohidelocalchanges if {[catch { From bd8f677e1c8349b9128490e2a21e0f573d0bea1d Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Tue, 23 Oct 2007 22:37:23 +1000 Subject: [PATCH 0263/1490] gitk: Fix some bugs with path limiting in the diff display First, we weren't putting "--" between the ids and the paths in the git diff-tree/diff-index/diff-files command, so if there was a tag and a file with the same name, we could get an ambiguity in the command. This puts the "--" in to make it clear that the paths are paths. Secondly, this implements the path limiting for merge diffs as well as the normal 2-way diffs. Signed-off-by: Paul Mackerras --- gitk | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/gitk b/gitk index 0d3705c43c..f41e30207b 100755 --- a/gitk +++ b/gitk @@ -4913,12 +4913,16 @@ proc mergediff {id l} { global diffmergeid diffopts mdifffd global diffids global parentlist + global limitdiffs viewfiles curview set diffmergeid $id set diffids $id # this doesn't seem to actually affect anything... set env(GIT_DIFF_OPTS) $diffopts set cmd [concat | git diff-tree --no-commit-id --cc $id] + if {$limitdiffs && $viewfiles($curview) ne {}} { + set cmd [concat $cmd -- $viewfiles($curview)] + } if {[catch {set mdf [open $cmd r]} err]} { error_popup "Error getting merge diffs: $err" return @@ -5152,7 +5156,7 @@ proc getblobdiffs {ids} { set env(GIT_DIFF_OPTS) $diffopts set cmd [diffcmd $ids "-p -C --no-commit-id -U$diffcontext"] if {$limitdiffs && $viewfiles($curview) ne {}} { - set cmd [concat $cmd $viewfiles($curview)] + set cmd [concat $cmd -- $viewfiles($curview)] } if {[catch {set bdf [open $cmd r]} err]} { puts "error getting diffs: $err" From 8d863c98b2f9b0d3777227b85b13b4095dd0f6dc Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 23 Oct 2007 12:10:55 -0700 Subject: [PATCH 0264/1490] k.org git toppage: Add link to 1.5.3 release notes. Signed-off-by: Junio C Hamano --- Documentation/git.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/git.txt b/Documentation/git.txt index ce8f923a15..c4d87ac201 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -49,7 +49,8 @@ Documentation for older releases are available here: link:RelNotes-1.5.3.4.txt[1.5.3.4], link:RelNotes-1.5.3.3.txt[1.5.3.3], link:RelNotes-1.5.3.2.txt[1.5.3.2], - link:RelNotes-1.5.3.1.txt[1.5.3.1]. + link:RelNotes-1.5.3.1.txt[1.5.3.1], + link:RelNotes-1.5.3.txt[1.5.3]. * release notes for link:RelNotes-1.5.2.5.txt[1.5.2.5], From d4e890e5de1ea7107d8d1b4134ab0144bbf27b8c Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Tue, 23 Oct 2007 16:55:32 -0400 Subject: [PATCH 0265/1490] git-gui: Make sure we get errors from git-update-index I'm seeing a lot of silent failures from git-update-index on Windows and this is leaving the index.lock file intact, which means users are later unable to perform additional operations. When the index is locked behind our back and we are unable to use it we may need to allow the user to delete the index lock and try again. However our UI state is probably not currect as we have assumed that some changes were applied but none of them actually did. A rescan is the easiest (in code anyway) solution to correct our UI to show what the index really has (or doesn't have). Signed-off-by: Shawn O. Pearce --- lib/index.tcl | 61 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 52 insertions(+), 9 deletions(-) diff --git a/lib/index.tcl b/lib/index.tcl index 44689ab63b..28ca039012 100644 --- a/lib/index.tcl +++ b/lib/index.tcl @@ -1,6 +1,55 @@ # git-gui index (add/remove) support # Copyright (C) 2006, 2007 Shawn Pearce +proc _delete_indexlock {} { + if {[catch {file delete -- [gitdir index.lock]} err]} { + error_popup [strcat [mc "Unable to unlock the index."] "\n\n$err"] + } +} + +proc _close_updateindex {fd after} { + fconfigure $fd -blocking 1 + if {[catch {close $fd} err]} { + set w .indexfried + toplevel $w + wm title $w [strcat "[appname] ([reponame]): " [mc "Index Error"]] + wm geometry $w "+[winfo rootx .]+[winfo rooty .]" + pack [label $w.msg \ + -justify left \ + -anchor w \ + -text [strcat \ + [mc "Updating the Git index failed. A rescan will be automatically started to resynchronize git-gui."] \ + "\n\n$err"] \ + ] -anchor w + + frame $w.buttons + button $w.buttons.continue \ + -text [mc "Continue"] \ + -command [list destroy $w] + pack $w.buttons.continue -side right -padx 5 + button $w.buttons.unlock \ + -text [mc "Unlock Index"] \ + -command "destroy $w; _delete_indexlock" + pack $w.buttons.unlock -side right + pack $w.buttons -side bottom -fill x -pady 10 -padx 10 + + wm protocol $w WM_DELETE_WINDOW update + bind $w.buttons.continue " + grab $w + focus $w.buttons.continue + " + tkwait window $w + + $::main_status stop + unlock_index + rescan $after 0 + return + } + + unlock_index + uplevel #0 $after +} + proc update_indexinfo {msg pathList after} { global update_index_cp @@ -41,9 +90,7 @@ proc write_update_indexinfo {fd pathList totalCnt batch msg after} { global file_states current_diff_path if {$update_index_cp >= $totalCnt} { - close $fd - unlock_index - uplevel #0 $after + _close_updateindex $fd $after return } @@ -116,9 +163,7 @@ proc write_update_index {fd pathList totalCnt batch msg after} { global file_states current_diff_path if {$update_index_cp >= $totalCnt} { - close $fd - unlock_index - uplevel #0 $after + _close_updateindex $fd $after return } @@ -201,9 +246,7 @@ proc write_checkout_index {fd pathList totalCnt batch msg after} { global file_states current_diff_path if {$update_index_cp >= $totalCnt} { - close $fd - unlock_index - uplevel #0 $after + _close_updateindex $fd $after return } From 74a40c71102ea925b174da15c74afb15b6b82537 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Wed, 24 Oct 2007 10:16:56 +1000 Subject: [PATCH 0266/1490] gitk: Fix a couple more bugs in the path limiting First, paths ending in a slash were not matching anything. This fixes path_filter to handle paths ending in a slash (such entries have to match a directory, and can't match a file, e.g., foo/bar/ can't match a plain file called foo/bar). Secondly, clicking in the file list pane (bottom right) was broken because $treediffs($ids) contained all the files modified by the commit, not just those within the file list. This fixes that too. Signed-off-by: Paul Mackerras --- gitk | 47 +++++++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/gitk b/gitk index f41e30207b..ff5eb5e8c4 100755 --- a/gitk +++ b/gitk @@ -5023,28 +5023,25 @@ proc startdiff {ids} { proc path_filter {filter name} { foreach p $filter { set l [string length $p] - if {[string compare -length $l $p $name] == 0 && - ([string length $name] == $l || [string index $name $l] eq "/")} { - return 1 + if {[string index $p end] eq "/"} { + if {[string compare -length $l $p $name] == 0} { + return 1 + } + } else { + if {[string compare -length $l $p $name] == 0 && + ([string length $name] == $l || + [string index $name $l] eq "/")} { + return 1 + } } } return 0 } proc addtocflist {ids} { - global treediffs cflist viewfiles curview limitdiffs + global treediffs - if {$limitdiffs && $viewfiles($curview) ne {}} { - set flist {} - foreach f $treediffs($ids) { - if {[path_filter $viewfiles($curview) $f]} { - lappend flist $f - } - } - } else { - set flist $treediffs($ids) - } - add_flist $flist + add_flist $treediffs($ids) getblobdiffs $ids } @@ -5100,7 +5097,7 @@ proc gettreediffs {ids} { proc gettreediffline {gdtf ids} { global treediff treediffs treepending diffids diffmergeid - global cmitmode + global cmitmode viewfiles curview limitdiffs set nr 0 while {[incr nr] <= 1000 && [gets $gdtf line] >= 0} { @@ -5117,7 +5114,17 @@ proc gettreediffline {gdtf ids} { return [expr {$nr >= 1000? 2: 1}] } close $gdtf - set treediffs($ids) $treediff + if {$limitdiffs && $viewfiles($curview) ne {}} { + set flist {} + foreach f $treediff { + if {[path_filter $viewfiles($curview) $f]} { + lappend flist $f + } + } + set treediffs($ids) $flist + } else { + set treediffs($ids) $treediff + } unset treepending if {$cmitmode eq "tree"} { gettree $diffids @@ -7565,7 +7572,7 @@ proc prefscan {} { proc prefsok {} { global maxwidth maxgraphpct global oldprefs prefstop showneartags showlocalchanges - global charspc ctext tabstop limitdiffs + global charspc ctext tabstop limitdiffs treediffs catch {destroy $prefstop} unset prefstop @@ -7577,6 +7584,10 @@ proc prefsok {} { dohidelocalchanges } } + if {$limitdiffs != $oldprefs(limitdiffs)} { + # treediffs elements are limited by path + catch {unset treediffs} + } if {$maxwidth != $oldprefs(maxwidth) || $maxgraphpct != $oldprefs(maxgraphpct)} { redisplay From 59b2023fbb154bc4671782955daddf8ef3018c93 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 24 Oct 2007 04:49:51 -0700 Subject: [PATCH 0267/1490] git-remote: fix "Use of uninitialized value in string ne" martin f krafft writes: > piper:~> git remote show origin > * remote origin > URL: ssh://git.madduck.net/~/git/etc/mailplate.git > Use of uninitialized value in string ne at /usr/local/stow/git/bin/git-remote line 248. This is because there might not be branch..remote defined but the code unconditionally dereferences $branch->{$name}{'REMOTE'} and compares with another string. Tested-by: Martin F Krafft Signed-off-by: Junio C Hamano --- git-remote.perl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/git-remote.perl b/git-remote.perl index 8e2dc4de73..11630b1a8b 100755 --- a/git-remote.perl +++ b/git-remote.perl @@ -244,7 +244,8 @@ sub show_remote { print "* remote $name\n"; print " URL: $info->{'URL'}\n"; for my $branchname (sort keys %$branch) { - next if ($branch->{$branchname}{'REMOTE'} ne $name); + next unless (defined $branch->{$branchname}{'REMOTE'} && + $branch->{$branchname}{'REMOTE'} eq $name); my @merged = map { s|^refs/heads/||; $_; From 2db9b49c6c19d3edaa3c20147f7d9f29588433df Mon Sep 17 00:00:00 2001 From: Miklos Vajna Date: Mon, 1 Oct 2007 14:42:42 +0200 Subject: [PATCH 0268/1490] git-send-email: add a new sendemail.to configuration variable Some projects prefer to receive patches via a given email address. In these cases, it's handy to configure that address once. Signed-off-by: Miklos Vajna Signed-off-by: Junio C Hamano --- Documentation/git-send-email.txt | 3 +++ git-send-email.perl | 1 + 2 files changed, 4 insertions(+) diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt index 3727776a0b..e38b7021b4 100644 --- a/Documentation/git-send-email.txt +++ b/Documentation/git-send-email.txt @@ -159,6 +159,9 @@ sendemail.aliasfiletype:: Format of the file(s) specified in sendemail.aliasesfile. Must be one of 'mutt', 'mailrc', 'pine', or 'gnus'. +sendemail.to:: + Email address (or alias) to always send to. + sendemail.cccmd:: Command to execute to generate per patch file specific "Cc:"s. diff --git a/git-send-email.perl b/git-send-email.perl index 62e1429733..96051bc01e 100755 --- a/git-send-email.perl +++ b/git-send-email.perl @@ -191,6 +191,7 @@ sub format_2822_time { "smtpserverport" => \$smtp_server_port, "smtpuser" => \$smtp_authuser, "smtppass" => \$smtp_authpass, + "to" => \@to, "cccmd" => \$cc_cmd, "aliasfiletype" => \$aliasfiletype, "bcc" => \@bcclist, From ce58ec9158fe398dc7142e34cf575d336f408370 Mon Sep 17 00:00:00 2001 From: David Symonds Date: Tue, 23 Oct 2007 11:31:22 +1000 Subject: [PATCH 0269/1490] gitweb: Refactor abbreviation-with-title-attribute code. Signed-off-by: David Symonds Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 45 +++++++++++++++++++++------------------------ 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 0d45769bc3..818783eba4 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -846,6 +846,23 @@ sub chop_str { return "$body$tail"; } +# takes the same arguments as chop_str, but also wraps a around the +# result with a title attribute if it does get chopped. Additionally, the +# string is HTML-escaped. +sub chop_and_escape_str { + my $str = shift; + my $len = shift; + my $add_len = shift || 10; + + my $chopped = chop_str($str, $len, $add_len); + if ($chopped eq $str) { + return esc_html($chopped); + } else { + return qq{} . + esc_html($chopped) . qq{}; + } +} + ## ---------------------------------------------------------------------- ## functions returning short strings @@ -3437,12 +3454,7 @@ sub git_shortlog_body { print "\n"; } $alternate ^= 1; - my $author = chop_str($co{'author_name'}, 10); - if ($author ne $co{'author_name'}) { - $author = "" . esc_html($author) . ""; - } else { - $author = esc_html($author); - } + my $author = chop_and_escape_str($co{'author_name'}, 10); # git_summary() used print "$co{'age_string'}\n" . print "$co{'age_string_date'}\n" . "" . $author . "\n" . @@ -3494,12 +3506,7 @@ sub git_history_body { } $alternate ^= 1; # shortlog uses chop_str($co{'author_name'}, 10) - my $author = chop_str($co{'author_name'}, 15, 3); - if ($author ne $co{'author_name'}) { - "" . esc_html($author) . ""; - } else { - $author = esc_html($author); - } + my $author = chop_and_escape_str($co{'author_name'}, 15, 3); print "$co{'age_string_date'}\n" . "" . $author . "\n" . ""; @@ -3655,12 +3662,7 @@ sub git_search_grep_body { print "\n"; } $alternate ^= 1; - my $author = chop_str($co{'author_name'}, 15, 5); - if ($author ne $co{'author_name'}) { - $author = "" . esc_html($author) . ""; - } else { - $author = esc_html($author); - } + my $author = chop_and_escape_str($co{'author_name'}, 15, 5); print "$co{'age_string_date'}\n" . "" . $author . "\n" . "" . @@ -5175,12 +5177,7 @@ sub git_search { print "\n"; } $alternate ^= 1; - my $author = chop_str($co{'author_name'}, 15, 5); - if ($author ne $co{'author_name'}) { - $author = "" . esc_html($author) . ""; - } else { - $author = esc_html($author); - } + my $author = chop_and_escape_str($co{'author_name'}, 15, 5); print "$co{'age_string_date'}\n" . "" . $author . "\n" . "" . From d3cd249565b6457d5845e7396530db7685a970bb Mon Sep 17 00:00:00 2001 From: David Symonds Date: Tue, 23 Oct 2007 11:31:23 +1000 Subject: [PATCH 0270/1490] gitweb: Use chop_and_escape_str in more places. Signed-off-by: David Symonds Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 818783eba4..8916950694 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -3412,7 +3412,7 @@ sub git_project_list_body { "" . $cgi->a({-href => href(project=>$pr->{'path'}, action=>"summary"), -class => "list", -title => $pr->{'descr_long'}}, esc_html($pr->{'descr'})) . "\n" . - "" . esc_html(chop_str($pr->{'owner'}, 15)) . "\n"; + "" . chop_and_escape_str($pr->{'owner'}, 15) . "\n"; print "{'age'}) . "\">" . (defined $pr->{'age_string'} ? $pr->{'age_string'} : "No commits") . "\n" . "" . @@ -3667,7 +3667,7 @@ sub git_search_grep_body { "" . $author . "\n" . "" . $cgi->a({-href => href(action=>"commit", hash=>$co{'id'}), -class => "list subject"}, - esc_html(chop_str($co{'title'}, 50)) . "
"); + chop_and_escape_str($co{'title'}, 50) . "
"); my $comment = $co{'comment'}; foreach my $line (@$comment) { if ($line =~ m/^(.*)($search_regexp)(.*)$/i) { @@ -5183,7 +5183,7 @@ sub git_search { "" . $cgi->a({-href => href(action=>"commit", hash=>$co{'id'}), -class => "list subject"}, - esc_html(chop_str($co{'title'}, 50)) . "
"); + chop_and_escape_str($co{'title'}, 50) . "
"); while (my $setref = shift @files) { my %set = %$setref; print $cgi->a({-href => href(action=>"blob", hash_base=>$co{'id'}, From 55db1df0c86b0fded61731647a8f1cd6e7dc9b04 Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Wed, 24 Oct 2007 22:03:38 +0200 Subject: [PATCH 0271/1490] Add some fancy colors in the test library when terminal supports it. Signed-off-by: Pierre Habouzit Signed-off-by: Junio C Hamano --- t/test-lib.sh | 62 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 45 insertions(+), 17 deletions(-) diff --git a/t/test-lib.sh b/t/test-lib.sh index cc1253ccab..66efcdaacd 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -59,15 +59,11 @@ esac # ' # . ./test-lib.sh -error () { - echo "* error: $*" - trap - exit - exit 1 -} - -say () { - echo "* $*" -} +[ "x$TERM" != "xdumb" ] && + tput bold >/dev/null 2>&1 && + tput setaf 1 >/dev/null 2>&1 && + tput sgr0 >/dev/null 2>&1 && + color=t test "${test_description}" != "" || error "Test script did not set test_description." @@ -84,6 +80,8 @@ do exit 0 ;; -v|--v|--ve|--ver|--verb|--verbo|--verbos|--verbose) verbose=t; shift ;; + --no-color) + color=; shift ;; --no-python) # noop now... shift ;; @@ -92,6 +90,36 @@ do esac done +if test -n "$color"; then + say_color () { + case "$1" in + error) tput bold; tput setaf 1;; # bold red + skip) tput bold; tput setaf 2;; # bold green + pass) tput setaf 2;; # green + info) tput setaf 3;; # brown + *);; + esac + shift + echo "* $*" + tput sgr0 + } +else + say_color() { + shift + echo "* $*" + } +fi + +error () { + say_color error "error: $*" + trap - exit + exit 1 +} + +say () { + say_color info "$*" +} + exec 5>&1 if test "$verbose" = "t" then @@ -122,13 +150,13 @@ test_tick () { test_ok_ () { test_count=$(expr "$test_count" + 1) - say " ok $test_count: $@" + say_color "" " ok $test_count: $@" } test_failure_ () { test_count=$(expr "$test_count" + 1) test_failure=$(expr "$test_failure" + 1); - say "FAIL $test_count: $1" + say_color error "FAIL $test_count: $1" shift echo "$@" | sed -e 's/^/ /' test "$immediate" = "" || { trap - exit; exit 1; } @@ -158,9 +186,9 @@ test_skip () { done case "$to_skip" in t) - say >&3 "skipping test: $@" + say_color skip >&3 "skipping test: $@" test_count=$(expr "$test_count" + 1) - say "skip $test_count: $1" + say_color skip "skip $test_count: $1" : true ;; *) @@ -247,11 +275,11 @@ test_done () { # The Makefile provided will clean this test area so # we will leave things as they are. - say "passed all $test_count test(s)" + say_color pass "passed all $test_count test(s)" exit 0 ;; *) - say "failed $test_failure among $test_count test(s)" + say_color error "failed $test_failure among $test_count test(s)" exit 1 ;; esac @@ -296,8 +324,8 @@ do done case "$to_skip" in t) - say >&3 "skipping test $this_test altogether" - say "skip all tests in $this_test" + say_color skip >&3 "skipping test $this_test altogether" + say_color skip "skip all tests in $this_test" test_done esac done From 1ece127467c1d65062f17777b1eedcd84fd9ea69 Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Wed, 24 Oct 2007 22:03:39 +0200 Subject: [PATCH 0272/1490] Support a --quiet option in the test-suite. This shuts down the "* ok ##: `test description`" messages. Signed-off-by: Pierre Habouzit Signed-off-by: Junio C Hamano --- t/test-lib.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/t/test-lib.sh b/t/test-lib.sh index 66efcdaacd..714de6e575 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -80,6 +80,8 @@ do exit 0 ;; -v|--v|--ve|--ver|--verb|--verbo|--verbos|--verbose) verbose=t; shift ;; + -q|--q|--qu|--qui|--quie|--quiet) + quiet=t; shift ;; --no-color) color=; shift ;; --no-python) @@ -97,7 +99,7 @@ if test -n "$color"; then skip) tput bold; tput setaf 2;; # bold green pass) tput setaf 2;; # green info) tput setaf 3;; # brown - *);; + *) test -n "$quiet" && return;; esac shift echo "* $*" @@ -105,6 +107,7 @@ if test -n "$color"; then } else say_color() { + test -z "$1" && test -n "$quiet" && return shift echo "* $*" } From ab0d33c43852b047c2a3e5ae960df9a146363e7c Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Tue, 23 Oct 2007 18:44:55 -0400 Subject: [PATCH 0273/1490] git-gui: Protect against bad translation strings If a translation string uses a format character we don't have an argument for then it may throw an error when we attempt to format the translation. In this case switch back to the default format that comes with the program (aka the English translation). Signed-off-by: Shawn O. Pearce --- git-gui.sh | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/git-gui.sh b/git-gui.sh index 38c6e595d8..a7227ac1b6 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -88,13 +88,20 @@ if {![catch {set _verbose $env(GITGUI_VERBOSE)}]} { package require msgcat -proc mc {fmt args} { - set fmt [::msgcat::mc $fmt] +proc _mc_trim {fmt} { set cmk [string first @@ $fmt] if {$cmk > 0} { - set fmt [string range $fmt 0 [expr {$cmk - 1}]] + return [string range $fmt 0 [expr {$cmk - 1}]] } - return [eval [list format $fmt] $args] + return $fmt +} + +proc mc {en_fmt args} { + set fmt [_mc_trim [::msgcat::mc $en_fmt]] + if {[catch {set msg [eval [list format $fmt] $args]} err]} { + set msg [eval [list format [_mc_trim $en_fmt]] $args] + } + return $msg } proc strcat {args} { From c2e6b6d0d1e97c5bc2db24388e247bef62faf917 Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Fri, 26 Oct 2007 09:59:12 +0200 Subject: [PATCH 0274/1490] fast-import.c: fix regression due to strbuf conversion Without this strbuf_detach(), it yields a double free later, the command is in fact stashed, and this is not a memory leak. Signed-off-by: Pierre Habouzit Signed-off-by: Junio C Hamano --- fast-import.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fast-import.c b/fast-import.c index 6f888f6476..f93d7d6c9b 100644 --- a/fast-import.c +++ b/fast-import.c @@ -1616,6 +1616,7 @@ static void cmd_data(struct strbuf *sb) char *term = xstrdup(command_buf.buf + 5 + 2); size_t term_len = command_buf.len - 5 - 2; + strbuf_detach(&command_buf, NULL); for (;;) { if (strbuf_getline(&command_buf, stdin, '\n') == EOF) die("EOF in data (terminator '%s' not found)", term); From d1a2057560b33c926ba481618105edbb65d2c91c Mon Sep 17 00:00:00 2001 From: Alex Riesen Date: Thu, 25 Oct 2007 22:17:24 +0200 Subject: [PATCH 0275/1490] Fix generation of perl/perl.mak The code generating perl/Makefile from Makefile.PL was causing trouble because it didn't considered NO_PERL_MAKEMAKER and ran makemaker unconditionally, rewriting perl.mak. Makemaker is FUBAR in ActiveState Perl, and perl/Makefile has a replacement for it. Besides, a changed Git.pm is *NOT* a reason to rebuild all the perl scripts, so remove the dependency too. Signed-off-by: Alex Riesen Signed-off-by: Junio C Hamano --- Makefile | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Makefile b/Makefile index c63d656f5d..e70e3209d9 100644 --- a/Makefile +++ b/Makefile @@ -778,7 +778,7 @@ $(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh $(patsubst %.perl,%,$(SCRIPT_PERL)): perl/perl.mak -perl/perl.mak: GIT-CFLAGS +perl/perl.mak: GIT-CFLAGS perl/Makefile perl/Makefile.PL $(QUIET_SUBDIR0)perl $(QUIET_SUBDIR1) PERL_PATH='$(PERL_PATH_SQ)' prefix='$(prefix_SQ)' $(@F) $(patsubst %.perl,%,$(SCRIPT_PERL)): % : %.perl @@ -907,10 +907,6 @@ $(XDIFF_LIB): $(XDIFF_OBJS) $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(XDIFF_OBJS) -perl/Makefile: perl/Git.pm perl/Makefile.PL GIT-CFLAGS - (cd perl && $(PERL_PATH) Makefile.PL \ - PREFIX='$(prefix_SQ)') - doc: $(MAKE) -C Documentation all From 4a21d13db4acb112bf210ab6febeed3269b28483 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Fri, 26 Oct 2007 12:48:41 +0200 Subject: [PATCH 0276/1490] hooks-pre-commit: use \t, rather than a literal TAB in regexp Signed-off-by: Jim Meyering Signed-off-by: Junio C Hamano --- templates/hooks--pre-commit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/hooks--pre-commit b/templates/hooks--pre-commit index 18b87309f6..a19279b3e4 100644 --- a/templates/hooks--pre-commit +++ b/templates/hooks--pre-commit @@ -58,7 +58,7 @@ perl -e ' if (/\s$/) { bad_line("trailing whitespace", $_); } - if (/^\s* /) { + if (/^\s* \t/) { bad_line("indent SP followed by a TAB", $_); } if (/^(?:[<>=]){7}/) { From 15387e32ff5116b82d3fe53df55b8c87eec83e01 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Fri, 26 Oct 2007 06:13:50 +0200 Subject: [PATCH 0277/1490] Test suite: reset TERM to its previous value after testing. Using konsole, I get no colored output at the end of "t7005-editor.sh" without this patch. Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- t/t7005-editor.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/t/t7005-editor.sh b/t/t7005-editor.sh index 28643b0da4..01cc0c02b1 100755 --- a/t/t7005-editor.sh +++ b/t/t7005-editor.sh @@ -4,6 +4,8 @@ test_description='GIT_EDITOR, core.editor, and stuff' . ./test-lib.sh +OLD_TERM="$TERM" + for i in GIT_EDITOR core_editor EDITOR VISUAL vi do cat >e-$i.sh <<-EOF @@ -88,4 +90,6 @@ do ' done +TERM="$OLD_TERM" + test_done From 505f297989f4b1fc4c5cb5d0c94e783e385f8d6d Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 25 Oct 2007 11:16:50 -0700 Subject: [PATCH 0278/1490] Add 'diffcore.h' to LIB_H The diffcore.h header file is included by more than just the internal diff generation files, and needs to be part of the proper dependencies. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 72f5ef43ce..ba969e4397 100644 --- a/Makefile +++ b/Makefile @@ -290,7 +290,7 @@ LIB_H = \ run-command.h strbuf.h tag.h tree.h git-compat-util.h revision.h \ tree-walk.h log-tree.h dir.h path-list.h unpack-trees.h builtin.h \ utf8.h reflog-walk.h patch-ids.h attr.h decorate.h progress.h \ - mailmap.h remote.h transport.h + mailmap.h remote.h transport.h diffcore.h DIFF_OBJS = \ diff.o diff-lib.o diffcore-break.o diffcore-order.o \ @@ -917,7 +917,6 @@ git-http-push$X: revision.o http.o http-push.o $(GITLIBS) $(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H) $(patsubst git-%$X,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h) -$(DIFF_OBJS): diffcore.h $(LIB_FILE): $(LIB_OBJS) $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS) From cb1491b6bff20748532c9e50afc7f9d6896167a8 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 25 Oct 2007 11:17:55 -0700 Subject: [PATCH 0279/1490] Split out "exact content match" phase of rename detection This makes the exact content match a separate function of its own. Partly to cut down a bit on the size of the diffcore_rename() function (which is too complex as it is), and partly because there are smarter ways to do this than an O(m*n) loop over it all, and that function should be rewritten to take that into account. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- diffcore-rename.c | 90 +++++++++++++++++++++++++++++------------------ 1 file changed, 56 insertions(+), 34 deletions(-) diff --git a/diffcore-rename.c b/diffcore-rename.c index 142e5376dd..2077a9b981 100644 --- a/diffcore-rename.c +++ b/diffcore-rename.c @@ -262,6 +262,58 @@ static int compute_stays(struct diff_queue_struct *q, return 1; } +/* + * Find exact renames first. + * + * The first round matches up the up-to-date entries, + * and then during the second round we try to match + * cache-dirty entries as well. + * + * Note: the rest of the rename logic depends on this + * phase also populating all the filespecs for any + * entry that isn't matched up with an exact rename, + * see "is_exact_match()". + */ +static int find_exact_renames(void) +{ + int rename_count = 0; + int contents_too; + + for (contents_too = 0; contents_too < 2; contents_too++) { + int i; + + for (i = 0; i < rename_dst_nr; i++) { + struct diff_filespec *two = rename_dst[i].two; + int j; + + if (rename_dst[i].pair) + continue; /* dealt with an earlier round */ + for (j = 0; j < rename_src_nr; j++) { + int k; + struct diff_filespec *one = rename_src[j].one; + if (!is_exact_match(one, two, contents_too)) + continue; + + /* see if there is a basename match, too */ + for (k = j; k < rename_src_nr; k++) { + one = rename_src[k].one; + if (basename_same(one, two) && + is_exact_match(one, two, + contents_too)) { + j = k; + break; + } + } + + record_rename_pair(i, j, (int)MAX_SCORE); + rename_count++; + break; /* we are done with this entry */ + } + } + } + return rename_count; +} + void diffcore_rename(struct diff_options *options) { int detect_rename = options->detect_rename; @@ -270,12 +322,11 @@ void diffcore_rename(struct diff_options *options) struct diff_queue_struct *q = &diff_queued_diff; struct diff_queue_struct outq; struct diff_score *mx; - int i, j, rename_count, contents_too; + int i, j, rename_count; int num_create, num_src, dst_cnt; if (!minimum_score) minimum_score = DEFAULT_RENAME_SCORE; - rename_count = 0; for (i = 0; i < q->nr; i++) { struct diff_filepair *p = q->queue[i]; @@ -318,40 +369,11 @@ void diffcore_rename(struct diff_options *options) if (rename_dst_nr * rename_src_nr > rename_limit * rename_limit) goto cleanup; - /* We really want to cull the candidates list early + /* + * We really want to cull the candidates list early * with cheap tests in order to avoid doing deltas. - * The first round matches up the up-to-date entries, - * and then during the second round we try to match - * cache-dirty entries as well. */ - for (contents_too = 0; contents_too < 2; contents_too++) { - for (i = 0; i < rename_dst_nr; i++) { - struct diff_filespec *two = rename_dst[i].two; - if (rename_dst[i].pair) - continue; /* dealt with an earlier round */ - for (j = 0; j < rename_src_nr; j++) { - int k; - struct diff_filespec *one = rename_src[j].one; - if (!is_exact_match(one, two, contents_too)) - continue; - - /* see if there is a basename match, too */ - for (k = j; k < rename_src_nr; k++) { - one = rename_src[k].one; - if (basename_same(one, two) && - is_exact_match(one, two, - contents_too)) { - j = k; - break; - } - } - - record_rename_pair(i, j, (int)MAX_SCORE); - rename_count++; - break; /* we are done with this entry */ - } - } - } + rename_count = find_exact_renames(); /* Have we run out the created file pool? If so we can avoid * doing the delta matrix altogether. From 9fb88419ba85e641006c80db53620423f37f1c93 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 25 Oct 2007 11:19:10 -0700 Subject: [PATCH 0280/1490] Ref-count the filespecs used by diffcore Rather than copy the filespecs when introducing new versions of them (for rename or copy detection), use a refcount and increment the count when reusing the diff_filespec. This avoids unnecessary allocations, but the real reason behind this is a future enhancement: we will want to track shared data across the copy/rename detection. In order to efficiently notice when a filespec is used by a rename, the rename machinery wants to keep track of a rename usage count which is shared across all different users of the filespec. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- diff.c | 15 +++++++++++---- diffcore-rename.c | 16 ++++++---------- diffcore.h | 2 ++ 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/diff.c b/diff.c index dfb8595b70..0b320f6b96 100644 --- a/diff.c +++ b/diff.c @@ -1440,9 +1440,18 @@ struct diff_filespec *alloc_filespec(const char *path) memset(spec, 0, sizeof(*spec)); spec->path = (char *)(spec + 1); memcpy(spec->path, path, namelen+1); + spec->count = 1; return spec; } +void free_filespec(struct diff_filespec *spec) +{ + if (!--spec->count) { + diff_free_filespec_data(spec); + free(spec); + } +} + void fill_filespec(struct diff_filespec *spec, const unsigned char *sha1, unsigned short mode) { @@ -2435,10 +2444,8 @@ struct diff_filepair *diff_queue(struct diff_queue_struct *queue, void diff_free_filepair(struct diff_filepair *p) { - diff_free_filespec_data(p->one); - diff_free_filespec_data(p->two); - free(p->one); - free(p->two); + free_filespec(p->one); + free_filespec(p->two); free(p); } diff --git a/diffcore-rename.c b/diffcore-rename.c index 2077a9b981..3da06b702b 100644 --- a/diffcore-rename.c +++ b/diffcore-rename.c @@ -209,21 +209,19 @@ static int estimate_similarity(struct diff_filespec *src, static void record_rename_pair(int dst_index, int src_index, int score) { - struct diff_filespec *one, *two, *src, *dst; + struct diff_filespec *src, *dst; struct diff_filepair *dp; if (rename_dst[dst_index].pair) die("internal error: dst already matched."); src = rename_src[src_index].one; - one = alloc_filespec(src->path); - fill_filespec(one, src->sha1, src->mode); + src->count++; dst = rename_dst[dst_index].two; - two = alloc_filespec(dst->path); - fill_filespec(two, dst->sha1, dst->mode); + dst->count++; - dp = diff_queue(NULL, one, two); + dp = diff_queue(NULL, src, dst); dp->renamed_pair = 1; if (!strcmp(src->path, dst->path)) dp->score = rename_src[src_index].score; @@ -526,10 +524,8 @@ void diffcore_rename(struct diff_options *options) } } - for (i = 0; i < rename_dst_nr; i++) { - diff_free_filespec_data(rename_dst[i].two); - free(rename_dst[i].two); - } + for (i = 0; i < rename_dst_nr; i++) + free_filespec(rename_dst[i].two); free(rename_dst); rename_dst = NULL; diff --git a/diffcore.h b/diffcore.h index eb618b1ec0..30055ac5a9 100644 --- a/diffcore.h +++ b/diffcore.h @@ -29,6 +29,7 @@ struct diff_filespec { void *cnt_data; const char *funcname_pattern_ident; unsigned long size; + int count; /* Reference count */ int xfrm_flags; /* for use by the xfrm */ unsigned short mode; /* file mode */ unsigned sha1_valid : 1; /* if true, use sha1 and trust mode; @@ -43,6 +44,7 @@ struct diff_filespec { }; extern struct diff_filespec *alloc_filespec(const char *); +extern void free_filespec(struct diff_filespec *); extern void fill_filespec(struct diff_filespec *, const unsigned char *, unsigned short); From 644797119d7a3b7a043a51a9cccd8758f8451f91 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 25 Oct 2007 11:20:56 -0700 Subject: [PATCH 0281/1490] copy vs rename detection: avoid unnecessary O(n*m) loops The core rename detection had some rather stupid code to check if a pathname was used by a later modification or rename, which basically walked the whole pathname space for all renames for each rename, in order to tell whether it was a pure rename (no remaining users) or should be considered a copy (other users of the source file remaining). That's really silly, since we can just keep a count of users around, and replace all those complex and expensive loops with just testing that simple counter (but this all depends on the previous commit that shared the diff_filespec data structure by using a separate reference count). Note that the reference count is not the same as the rename count: they behave otherwise rather similarly, but the reference count is tied to the allocation (and decremented at de-allocation, so that when it turns zero we can get rid of the memory), while the rename count is tied to the renames and is decremented when we find a rename (so that when it turns zero we know that it was a rename, not a copy). Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- diff.c | 40 ++++++++++++---------------- diffcore-rename.c | 68 ++++++++++++----------------------------------- diffcore.h | 2 +- 3 files changed, 35 insertions(+), 75 deletions(-) diff --git a/diff.c b/diff.c index 0b320f6b96..af85b94d1b 100644 --- a/diff.c +++ b/diff.c @@ -2597,9 +2597,9 @@ void diff_debug_filepair(const struct diff_filepair *p, int i) { diff_debug_filespec(p->one, i, "one"); diff_debug_filespec(p->two, i, "two"); - fprintf(stderr, "score %d, status %c stays %d broken %d\n", + fprintf(stderr, "score %d, status %c rename_used %d broken %d\n", p->score, p->status ? p->status : '?', - p->source_stays, p->broken_pair); + p->one->rename_used, p->broken_pair); } void diff_debug_queue(const char *msg, struct diff_queue_struct *q) @@ -2617,8 +2617,8 @@ void diff_debug_queue(const char *msg, struct diff_queue_struct *q) static void diff_resolve_rename_copy(void) { - int i, j; - struct diff_filepair *p, *pp; + int i; + struct diff_filepair *p; struct diff_queue_struct *q = &diff_queued_diff; diff_debug_queue("resolve-rename-copy", q); @@ -2640,27 +2640,21 @@ static void diff_resolve_rename_copy(void) * either in-place edit or rename/copy edit. */ else if (DIFF_PAIR_RENAME(p)) { - if (p->source_stays) { - p->status = DIFF_STATUS_COPIED; - continue; - } - /* See if there is some other filepair that - * copies from the same source as us. If so - * we are a copy. Otherwise we are either a - * copy if the path stays, or a rename if it - * does not, but we already handled "stays" case. + /* + * A rename might have re-connected a broken + * pair up, causing the pathnames to be the + * same again. If so, that's not a rename at + * all, just a modification.. + * + * Otherwise, see if this source was used for + * multiple renames, in which case we decrement + * the count, and call it a copy. */ - for (j = i + 1; j < q->nr; j++) { - pp = q->queue[j]; - if (strcmp(pp->one->path, p->one->path)) - continue; /* not us */ - if (!DIFF_PAIR_RENAME(pp)) - continue; /* not a rename/copy */ - /* pp is a rename/copy from the same source */ + if (!strcmp(p->one->path, p->two->path)) + p->status = DIFF_STATUS_MODIFIED; + else if (--p->one->rename_used > 0) p->status = DIFF_STATUS_COPIED; - break; - } - if (!p->status) + else p->status = DIFF_STATUS_RENAMED; } else if (hashcmp(p->one->sha1, p->two->sha1) || diff --git a/diffcore-rename.c b/diffcore-rename.c index 3da06b702b..edb2424d13 100644 --- a/diffcore-rename.c +++ b/diffcore-rename.c @@ -55,12 +55,10 @@ static struct diff_rename_dst *locate_rename_dst(struct diff_filespec *two, static struct diff_rename_src { struct diff_filespec *one; unsigned short score; /* to remember the break score */ - unsigned src_path_left : 1; } *rename_src; static int rename_src_nr, rename_src_alloc; static struct diff_rename_src *register_rename_src(struct diff_filespec *one, - int src_path_left, unsigned short score) { int first, last; @@ -92,7 +90,6 @@ static struct diff_rename_src *register_rename_src(struct diff_filespec *one, (rename_src_nr - first - 1) * sizeof(*rename_src)); rename_src[first].one = one; rename_src[first].score = score; - rename_src[first].src_path_left = src_path_left; return &(rename_src[first]); } @@ -216,6 +213,7 @@ static void record_rename_pair(int dst_index, int src_index, int score) die("internal error: dst already matched."); src = rename_src[src_index].one; + src->rename_used++; src->count++; dst = rename_dst[dst_index].two; @@ -227,7 +225,6 @@ static void record_rename_pair(int dst_index, int src_index, int score) dp->score = rename_src[src_index].score; else dp->score = score; - dp->source_stays = rename_src[src_index].src_path_left; rename_dst[dst_index].pair = dp; } @@ -245,21 +242,6 @@ static int score_compare(const void *a_, const void *b_) return b->score - a->score; } -static int compute_stays(struct diff_queue_struct *q, - struct diff_filespec *one) -{ - int i; - for (i = 0; i < q->nr; i++) { - struct diff_filepair *p = q->queue[i]; - if (strcmp(one->path, p->two->path)) - continue; - if (DIFF_PAIR_RENAME(p)) { - return 0; /* something else is renamed into this */ - } - } - return 1; -} - /* * Find exact renames first. * @@ -338,15 +320,25 @@ void diffcore_rename(struct diff_options *options) locate_rename_dst(p->two, 1); } else if (!DIFF_FILE_VALID(p->two)) { - /* If the source is a broken "delete", and + /* + * If the source is a broken "delete", and * they did not really want to get broken, * that means the source actually stays. + * So we increment the "rename_used" score + * by one, to indicate ourselves as a user */ - int stays = (p->broken_pair && !p->score); - register_rename_src(p->one, stays, p->score); + if (p->broken_pair && !p->score) + p->one->rename_used++; + register_rename_src(p->one, p->score); + } + else if (detect_rename == DIFF_DETECT_COPY) { + /* + * Increment the "rename_used" score by + * one, to indicate ourselves as a user. + */ + p->one->rename_used++; + register_rename_src(p->one, p->score); } - else if (detect_rename == DIFF_DETECT_COPY) - register_rename_src(p->one, 1, p->score); } if (rename_dst_nr == 0 || rename_src_nr == 0) goto cleanup; /* nothing to do */ @@ -472,16 +464,7 @@ void diffcore_rename(struct diff_options *options) pair_to_free = p; } else { - for (j = 0; j < rename_dst_nr; j++) { - if (!rename_dst[j].pair) - continue; - if (strcmp(rename_dst[j].pair-> - one->path, - p->one->path)) - continue; - break; - } - if (j < rename_dst_nr) + if (p->one->rename_used) /* this path remains */ pair_to_free = p; } @@ -507,23 +490,6 @@ void diffcore_rename(struct diff_options *options) *q = outq; diff_debug_queue("done collapsing", q); - /* We need to see which rename source really stays here; - * earlier we only checked if the path is left in the result, - * but even if a path remains in the result, if that is coming - * from copying something else on top of it, then the original - * source is lost and does not stay. - */ - for (i = 0; i < q->nr; i++) { - struct diff_filepair *p = q->queue[i]; - if (DIFF_PAIR_RENAME(p) && p->source_stays) { - /* If one appears as the target of a rename-copy, - * then mark p->source_stays = 0; otherwise - * leave it as is. - */ - p->source_stays = compute_stays(q, p->one); - } - } - for (i = 0; i < rename_dst_nr; i++) free_filespec(rename_dst[i].two); diff --git a/diffcore.h b/diffcore.h index 30055ac5a9..cc96c20734 100644 --- a/diffcore.h +++ b/diffcore.h @@ -31,6 +31,7 @@ struct diff_filespec { unsigned long size; int count; /* Reference count */ int xfrm_flags; /* for use by the xfrm */ + int rename_used; /* Count of rename users */ unsigned short mode; /* file mode */ unsigned sha1_valid : 1; /* if true, use sha1 and trust mode; * if false, use the name and read from @@ -58,7 +59,6 @@ struct diff_filepair { struct diff_filespec *two; unsigned short int score; char status; /* M C R N D U (see Documentation/diff-format.txt) */ - unsigned source_stays : 1; /* all of R/C are copies */ unsigned broken_pair : 1; unsigned renamed_pair : 1; unsigned is_unmerged : 1; From 9027f53cb5051bf83a0254e7f8aeb5d1a206de0b Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 25 Oct 2007 11:23:26 -0700 Subject: [PATCH 0282/1490] Do linear-time/space rename logic for exact renames This implements a smarter rename detector for exact renames, which rather than doing a pairwise comparison (time O(m*n)) will just hash the files into a hash-table (size O(n+m)), and only do pairwise comparisons to renames that have the same hash (time O(n+m) except for unrealistic hash collissions, which we just cull aggressively). Admittedly the exact rename case is not nearly as interesting as the generic case, but it's an important case none-the-less. A similar general approach should work for the generic case too, but even then you do need to handle the exact renames/copies separately (to avoid the inevitable added cost factor that comes from the _size_ of the file), so this is worth doing. In the expectation that we will indeed do the same hashing trick for the general rename case, this code uses a generic hash-table implementation that can be used for other things too. In fact, we might be able to consolidate some of our existing hash tables with the new generic code in hash.[ch]. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- Makefile | 4 +- diffcore-rename.c | 203 ++++++++++++++++++++++++++++++++-------------- hash.c | 110 +++++++++++++++++++++++++ hash.h | 43 ++++++++++ 4 files changed, 299 insertions(+), 61 deletions(-) create mode 100644 hash.c create mode 100644 hash.h diff --git a/Makefile b/Makefile index ba969e4397..2e6fd8f219 100644 --- a/Makefile +++ b/Makefile @@ -290,7 +290,7 @@ LIB_H = \ run-command.h strbuf.h tag.h tree.h git-compat-util.h revision.h \ tree-walk.h log-tree.h dir.h path-list.h unpack-trees.h builtin.h \ utf8.h reflog-walk.h patch-ids.h attr.h decorate.h progress.h \ - mailmap.h remote.h transport.h diffcore.h + mailmap.h remote.h transport.h diffcore.h hash.h DIFF_OBJS = \ diff.o diff-lib.o diffcore-break.o diffcore-order.o \ @@ -300,7 +300,7 @@ DIFF_OBJS = \ LIB_OBJS = \ blob.o commit.o connect.o csum-file.o cache-tree.o base85.o \ date.o diff-delta.o entry.o exec_cmd.o ident.o \ - interpolate.o \ + interpolate.o hash.o \ lockfile.o \ patch-ids.o \ object.o pack-check.o pack-write.o patch-delta.o path.o pkt-line.o \ diff --git a/diffcore-rename.c b/diffcore-rename.c index edb2424d13..e7e370b2cc 100644 --- a/diffcore-rename.c +++ b/diffcore-rename.c @@ -4,6 +4,7 @@ #include "cache.h" #include "diff.h" #include "diffcore.h" +#include "hash.h" /* Table of rename/copy destinations */ @@ -93,29 +94,6 @@ static struct diff_rename_src *register_rename_src(struct diff_filespec *one, return &(rename_src[first]); } -static int is_exact_match(struct diff_filespec *src, - struct diff_filespec *dst, - int contents_too) -{ - if (src->sha1_valid && dst->sha1_valid && - !hashcmp(src->sha1, dst->sha1)) - return 1; - if (!contents_too) - return 0; - if (diff_populate_filespec(src, 1) || diff_populate_filespec(dst, 1)) - return 0; - if (src->size != dst->size) - return 0; - if (src->sha1_valid && dst->sha1_valid) - return !hashcmp(src->sha1, dst->sha1); - if (diff_populate_filespec(src, 0) || diff_populate_filespec(dst, 0)) - return 0; - if (src->size == dst->size && - !memcmp(src->data, dst->data, src->size)) - return 1; - return 0; -} - static int basename_same(struct diff_filespec *src, struct diff_filespec *dst) { int src_len = strlen(src->path), dst_len = strlen(dst->path); @@ -242,56 +220,163 @@ static int score_compare(const void *a_, const void *b_) return b->score - a->score; } +struct file_similarity { + int src_dst, index; + struct diff_filespec *filespec; + struct file_similarity *next; +}; + +static int find_identical_files(struct file_similarity *src, + struct file_similarity *dst) +{ + int renames = 0; + + /* + * Walk over all the destinations ... + */ + do { + struct diff_filespec *one = dst->filespec; + struct file_similarity *p, *best; + int i = 100; + + /* + * .. to find the best source match + */ + best = NULL; + for (p = src; p; p = p->next) { + struct diff_filespec *two = p->filespec; + + /* False hash collission? */ + if (hashcmp(one->sha1, two->sha1)) + continue; + /* Non-regular files? If so, the modes must match! */ + if (!S_ISREG(one->mode) || !S_ISREG(two->mode)) { + if (one->mode != two->mode) + continue; + } + best = p; + if (basename_same(one, two)) + break; + + /* Too many identical alternatives? Pick one */ + if (!--i) + break; + } + if (best) { + record_rename_pair(dst->index, best->index, MAX_SCORE); + renames++; + } + } while ((dst = dst->next) != NULL); + return renames; +} + +/* + * Note: the rest of the rename logic depends on this + * phase also populating all the filespecs for any + * entry that isn't matched up with an exact rename. + */ +static void free_similarity_list(struct file_similarity *p) +{ + while (p) { + struct file_similarity *entry = p; + p = p->next; + + /* Stupid special case, see note above! */ + diff_populate_filespec(entry->filespec, 0); + free(entry); + } +} + +static int find_same_files(void *ptr) +{ + int ret; + struct file_similarity *p = ptr; + struct file_similarity *src = NULL, *dst = NULL; + + /* Split the hash list up into sources and destinations */ + do { + struct file_similarity *entry = p; + p = p->next; + if (entry->src_dst < 0) { + entry->next = src; + src = entry; + } else { + entry->next = dst; + dst = entry; + } + } while (p); + + /* + * If we have both sources *and* destinations, see if + * we can match them up + */ + ret = (src && dst) ? find_identical_files(src, dst) : 0; + + /* Free the hashes and return the number of renames found */ + free_similarity_list(src); + free_similarity_list(dst); + return ret; +} + +static unsigned int hash_filespec(struct diff_filespec *filespec) +{ + unsigned int hash; + if (!filespec->sha1_valid) { + if (diff_populate_filespec(filespec, 0)) + return 0; + hash_sha1_file(filespec->data, filespec->size, "blob", filespec->sha1); + } + memcpy(&hash, filespec->sha1, sizeof(hash)); + return hash; +} + +static void insert_file_table(struct hash_table *table, int src_dst, int index, struct diff_filespec *filespec) +{ + void **pos; + unsigned int hash; + struct file_similarity *entry = xmalloc(sizeof(*entry)); + + entry->src_dst = src_dst; + entry->index = index; + entry->filespec = filespec; + entry->next = NULL; + + hash = hash_filespec(filespec); + pos = insert_hash(hash, entry, table); + + /* We already had an entry there? */ + if (pos) { + entry->next = *pos; + *pos = entry; + } +} + /* * Find exact renames first. * * The first round matches up the up-to-date entries, * and then during the second round we try to match * cache-dirty entries as well. - * - * Note: the rest of the rename logic depends on this - * phase also populating all the filespecs for any - * entry that isn't matched up with an exact rename, - * see "is_exact_match()". */ static int find_exact_renames(void) { - int rename_count = 0; - int contents_too; + int i; + struct hash_table file_table; - for (contents_too = 0; contents_too < 2; contents_too++) { - int i; + init_hash(&file_table); + for (i = 0; i < rename_src_nr; i++) + insert_file_table(&file_table, -1, i, rename_src[i].one); - for (i = 0; i < rename_dst_nr; i++) { - struct diff_filespec *two = rename_dst[i].two; - int j; + for (i = 0; i < rename_dst_nr; i++) + insert_file_table(&file_table, 1, i, rename_dst[i].two); - if (rename_dst[i].pair) - continue; /* dealt with an earlier round */ - for (j = 0; j < rename_src_nr; j++) { - int k; - struct diff_filespec *one = rename_src[j].one; - if (!is_exact_match(one, two, contents_too)) - continue; + /* Find the renames */ + i = for_each_hash(&file_table, find_same_files); - /* see if there is a basename match, too */ - for (k = j; k < rename_src_nr; k++) { - one = rename_src[k].one; - if (basename_same(one, two) && - is_exact_match(one, two, - contents_too)) { - j = k; - break; - } - } + /* .. and free the hash data structure */ + free_hash(&file_table); - record_rename_pair(i, j, (int)MAX_SCORE); - rename_count++; - break; /* we are done with this entry */ - } - } - } - return rename_count; + return i; } void diffcore_rename(struct diff_options *options) diff --git a/hash.c b/hash.c new file mode 100644 index 0000000000..7b492d4fc0 --- /dev/null +++ b/hash.c @@ -0,0 +1,110 @@ +/* + * Some generic hashing helpers. + */ +#include "cache.h" +#include "hash.h" + +/* + * Look up a hash entry in the hash table. Return the pointer to + * the existing entry, or the empty slot if none existed. The caller + * can then look at the (*ptr) to see whether it existed or not. + */ +static struct hash_table_entry *lookup_hash_entry(unsigned int hash, struct hash_table *table) +{ + unsigned int size = table->size, nr = hash % size; + struct hash_table_entry *array = table->array; + + while (array[nr].ptr) { + if (array[nr].hash == hash) + break; + nr++; + if (nr >= size) + nr = 0; + } + return array + nr; +} + + +/* + * Insert a new hash entry pointer into the table. + * + * If that hash entry already existed, return the pointer to + * the existing entry (and the caller can create a list of the + * pointers or do anything else). If it didn't exist, return + * NULL (and the caller knows the pointer has been inserted). + */ +static void **insert_hash_entry(unsigned int hash, void *ptr, struct hash_table *table) +{ + struct hash_table_entry *entry = lookup_hash_entry(hash, table); + + if (!entry->ptr) { + entry->ptr = ptr; + entry->hash = hash; + table->nr++; + return NULL; + } + return &entry->ptr; +} + +static void grow_hash_table(struct hash_table *table) +{ + unsigned int i; + unsigned int old_size = table->size, new_size; + struct hash_table_entry *old_array = table->array, *new_array; + + new_size = alloc_nr(old_size); + new_array = xcalloc(sizeof(struct hash_table_entry), new_size); + table->size = new_size; + table->array = new_array; + table->nr = 0; + for (i = 0; i < old_size; i++) { + unsigned int hash = old_array[i].hash; + void *ptr = old_array[i].ptr; + if (ptr) + insert_hash_entry(hash, ptr, table); + } + free(old_array); +} + +void *lookup_hash(unsigned int hash, struct hash_table *table) +{ + if (!table->array) + return NULL; + return &lookup_hash_entry(hash, table)->ptr; +} + +void **insert_hash(unsigned int hash, void *ptr, struct hash_table *table) +{ + unsigned int nr = table->nr; + if (nr >= table->size/2) + grow_hash_table(table); + return insert_hash_entry(hash, ptr, table); +} + +int for_each_hash(struct hash_table *table, int (*fn)(void *)) +{ + int sum = 0; + unsigned int i; + unsigned int size = table->size; + struct hash_table_entry *array = table->array; + + for (i = 0; i < size; i++) { + void *ptr = array->ptr; + array++; + if (ptr) { + int val = fn(ptr); + if (val < 0) + return val; + sum += val; + } + } + return sum; +} + +void free_hash(struct hash_table *table) +{ + free(table->array); + table->array = NULL; + table->size = 0; + table->nr = 0; +} diff --git a/hash.h b/hash.h new file mode 100644 index 0000000000..a8b0fbb5b5 --- /dev/null +++ b/hash.h @@ -0,0 +1,43 @@ +#ifndef HASH_H +#define HASH_H + +/* + * These are some simple generic hash table helper functions. + * Not necessarily suitable for all users, but good for things + * where you want to just keep track of a list of things, and + * have a good hash to use on them. + * + * It keeps the hash table at roughly 50-75% free, so the memory + * cost of the hash table itself is roughly + * + * 3 * 2*sizeof(void *) * nr_of_objects + * + * bytes. + * + * FIXME: on 64-bit architectures, we waste memory. It would be + * good to have just 32-bit pointers, requiring a special allocator + * for hashed entries or something. + */ +struct hash_table_entry { + unsigned int hash; + void *ptr; +}; + +struct hash_table { + unsigned int size, nr; + struct hash_table_entry *array; +}; + +extern void *lookup_hash(unsigned int hash, struct hash_table *table); +extern void **insert_hash(unsigned int hash, void *ptr, struct hash_table *table); +extern int for_each_hash(struct hash_table *table, int (*fn)(void *)); +extern void free_hash(struct hash_table *table); + +static inline void init_hash(struct hash_table *table) +{ + table->size = 0; + table->nr = 0; + table->array = NULL; +} + +#endif From 17559a643ecef94834d930790498c6babe3e89a8 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 25 Oct 2007 11:24:47 -0700 Subject: [PATCH 0283/1490] Do exact rename detection regardless of rename limits Now that the exact rename detection is linear-time (with a very small constant factor to boot), there is no longer any reason to limit it by the number of files involved. In some trivial testing, I created a repository with a directory that had a hundred thousand files in it (all with different contents), and then moved that directory to show the effects of renaming 100,000 files. With the new code, that resulted in [torvalds@woody big-rename]$ time ~/git/git show -C | wc -l 400006 real 0m2.071s user 0m1.520s sys 0m0.576s ie the code can correctly detect the hundred thousand renames in about 2 seconds (the number "400006" comes from four lines for each rename: diff --git a/really-big-dir/file-1-1-1-1-1 b/moved-big-dir/file-1-1-1-1-1 similarity index 100% rename from really-big-dir/file-1-1-1-1-1 rename to moved-big-dir/file-1-1-1-1-1 and the extra six lines is from a one-liner commit message and all the commit information and spacing). Most of those two seconds weren't even really the rename detection, it's really all the other stuff needed to get there. With the old code, this wouldn't have been practically possible. Doing a pairwise check of the ten billion possible pairs would have been prohibitively expensive. In fact, even with the rename limiter in place, the old code would waste a lot of time just on the diff_filespec checks, and despite not even trying to find renames, it used to look like: [torvalds@woody big-rename]$ time git show -C | wc -l 1400006 real 0m12.337s user 0m12.285s sys 0m0.192s ie we used to take 12 seconds for this load and not even do any rename detection! (The number 1400006 comes from fourteen lines per file moved: seven lines each for the delete and the create of a one-liner file, and the same extra six lines of commit information). Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- diffcore-rename.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/diffcore-rename.c b/diffcore-rename.c index e7e370b2cc..394693222d 100644 --- a/diffcore-rename.c +++ b/diffcore-rename.c @@ -428,6 +428,12 @@ void diffcore_rename(struct diff_options *options) if (rename_dst_nr == 0 || rename_src_nr == 0) goto cleanup; /* nothing to do */ + /* + * We really want to cull the candidates list early + * with cheap tests in order to avoid doing deltas. + */ + rename_count = find_exact_renames(); + /* * This basically does a test for the rename matrix not * growing larger than a "rename_limit" square matrix, ie: @@ -444,12 +450,6 @@ void diffcore_rename(struct diff_options *options) if (rename_dst_nr * rename_src_nr > rename_limit * rename_limit) goto cleanup; - /* - * We really want to cull the candidates list early - * with cheap tests in order to avoid doing deltas. - */ - rename_count = find_exact_renames(); - /* Have we run out the created file pool? If so we can avoid * doing the delta matrix altogether. */ From 81ac051d6ac9deef9a34de496fb981469aae77f0 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 26 Oct 2007 16:51:28 -0700 Subject: [PATCH 0284/1490] Fix ugly magic special case in exact rename detection For historical reasons, the exact rename detection had populated the filespecs for the entries it compared, and the rest of the similarity analysis depended on that. I hadn't even bothered to debug why that was the case when I re-did the rename detection, I just made the new one have the same broken behaviour, with a note about this special case. This fixes that fixme. The reason the exact rename detector needed to fill in the file sizes of the files it checked was that the _inexact_ rename detector was broken, and started comparing file sizes before it filled them in. Fixing that allows the exact phase to do the sane thing of never even caring (since all *it* cares about is really just the SHA1 itself, not the size nor the contents). It turns out that this also indirectly fixes a bug: trying to populate all the filespecs will run out of virtual memory if there is tons and tons of possible rename options. The fuzzy similarity analysis does the right thing in this regard, and free's the blob info after it has generated the hash tables, so the special case code caused more trouble than just some extra illogical code. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- diffcore-rename.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/diffcore-rename.c b/diffcore-rename.c index 394693222d..7ed5ef81bf 100644 --- a/diffcore-rename.c +++ b/diffcore-rename.c @@ -144,6 +144,20 @@ static int estimate_similarity(struct diff_filespec *src, if (!S_ISREG(src->mode) || !S_ISREG(dst->mode)) return 0; + /* + * Need to check that source and destination sizes are + * filled in before comparing them. + * + * If we already have "cnt_data" filled in, we know it's + * all good (avoid checking the size for zero, as that + * is a possible size - we really should have a flag to + * say whether the size is valid or not!) + */ + if (!src->cnt_data && diff_populate_filespec(src, 0)) + return 0; + if (!dst->cnt_data && diff_populate_filespec(dst, 0)) + return 0; + max_size = ((src->size > dst->size) ? src->size : dst->size); base_size = ((src->size < dst->size) ? src->size : dst->size); delta_size = max_size - base_size; @@ -159,11 +173,6 @@ static int estimate_similarity(struct diff_filespec *src, if (base_size * (MAX_SCORE-minimum_score) < delta_size * MAX_SCORE) return 0; - if ((!src->cnt_data && diff_populate_filespec(src, 0)) - || (!dst->cnt_data && diff_populate_filespec(dst, 0))) - return 0; /* error but caught downstream */ - - delta_limit = (unsigned long) (base_size * (MAX_SCORE-minimum_score) / MAX_SCORE); if (diffcore_count_changes(src, dst, @@ -270,19 +279,11 @@ static int find_identical_files(struct file_similarity *src, return renames; } -/* - * Note: the rest of the rename logic depends on this - * phase also populating all the filespecs for any - * entry that isn't matched up with an exact rename. - */ static void free_similarity_list(struct file_similarity *p) { while (p) { struct file_similarity *entry = p; p = p->next; - - /* Stupid special case, see note above! */ - diff_populate_filespec(entry->filespec, 0); free(entry); } } From 42899ac898f2b539fc762c8452da2c981ccbd815 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 26 Oct 2007 16:56:34 -0700 Subject: [PATCH 0285/1490] Do the fuzzy rename detection limits with the exact renames removed When we do the fuzzy rename detection, we don't care about the destinations that we already handled with the exact rename detector. And, in fact, the code already knew that - but the rename limiter, which used to run *before* exact renames were detected, did not. This fixes it so that the rename detection limiter now bases its decisions on the *remaining* rename counts, rather than the original ones. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- diffcore-rename.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/diffcore-rename.c b/diffcore-rename.c index 7ed5ef81bf..f9ebea5640 100644 --- a/diffcore-rename.c +++ b/diffcore-rename.c @@ -435,33 +435,37 @@ void diffcore_rename(struct diff_options *options) */ rename_count = find_exact_renames(); + /* Did we only want exact renames? */ + if (minimum_score == MAX_SCORE) + goto cleanup; + + /* + * Calculate how many renames are left (but all the source + * files still remain as options for rename/copies!) + */ + num_create = (rename_dst_nr - rename_count); + num_src = rename_src_nr; + + /* All done? */ + if (!num_create) + goto cleanup; + /* * This basically does a test for the rename matrix not * growing larger than a "rename_limit" square matrix, ie: * - * rename_dst_nr * rename_src_nr > rename_limit * rename_limit + * num_create * num_src > rename_limit * rename_limit * * but handles the potential overflow case specially (and we * assume at least 32-bit integers) */ if (rename_limit <= 0 || rename_limit > 32767) rename_limit = 32767; - if (rename_dst_nr > rename_limit && rename_src_nr > rename_limit) + if (num_create > rename_limit && num_src > rename_limit) goto cleanup; - if (rename_dst_nr * rename_src_nr > rename_limit * rename_limit) + if (num_create * num_src > rename_limit * rename_limit) goto cleanup; - /* Have we run out the created file pool? If so we can avoid - * doing the delta matrix altogether. - */ - if (rename_count == rename_dst_nr) - goto cleanup; - - if (minimum_score == MAX_SCORE) - goto cleanup; - - num_create = (rename_dst_nr - rename_count); - num_src = rename_src_nr; mx = xmalloc(sizeof(*mx) * num_create * num_src); for (dst_cnt = i = 0; i < rename_dst_nr; i++) { int base = dst_cnt * num_src; From a238917ba48c44de8a00e3aee7898d9beb5afcd8 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 26 Oct 2007 23:26:41 -0700 Subject: [PATCH 0286/1490] help: remove extra blank line after "See 'git --help'" message The double LF were there only because we gave a list of common commands. WIth the list gone, there is no reason to have the extra blank line. Signed-off-by: Junio C Hamano --- help.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/help.c b/help.c index 814a8cd02a..e5662d9014 100644 --- a/help.c +++ b/help.c @@ -185,7 +185,7 @@ static void show_man_page(const char *git_cmd) void help_unknown_cmd(const char *cmd) { - fprintf(stderr, "git: '%s' is not a git-command. See --help\n\n", cmd); + fprintf(stderr, "git: '%s' is not a git-command. See 'git --help'.\n", cmd); exit(1); } From 50e62a8e703b78fbe59d5f98b1bb36464570a815 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Mon, 22 Oct 2007 07:47:56 +0200 Subject: [PATCH 0287/1490] rev-list: implement --bisect-all This is Junio's patch with some stuff to make --bisect-all compatible with --bisect-vars. This option makes it possible to see all the potential bisection points. The best ones are displayed first. Signed-off-by: Christian Couder Signed-off-by: Shawn O. Pearce --- builtin-rev-list.c | 100 ++++++++++++++++++++++++++++++++++++++------- log-tree.c | 2 +- log-tree.h | 1 + 3 files changed, 88 insertions(+), 15 deletions(-) diff --git a/builtin-rev-list.c b/builtin-rev-list.c index 33726b8d84..44393320e8 100644 --- a/builtin-rev-list.c +++ b/builtin-rev-list.c @@ -9,6 +9,7 @@ #include "revision.h" #include "list-objects.h" #include "builtin.h" +#include "log-tree.h" /* bits #0-15 in revision.h */ @@ -38,7 +39,8 @@ static const char rev_list_usage[] = " --left-right\n" " special purpose:\n" " --bisect\n" -" --bisect-vars" +" --bisect-vars\n" +" --bisect-all" ; static struct rev_info revs; @@ -74,6 +76,7 @@ static void show_commit(struct commit *commit) parents = parents->next; } } + show_decorations(commit); if (revs.commit_format == CMIT_FMT_ONELINE) putchar(' '); else @@ -278,6 +281,57 @@ static struct commit_list *best_bisection(struct commit_list *list, int nr) return best; } +struct commit_dist { + struct commit *commit; + int distance; +}; + +static int compare_commit_dist(const void *a_, const void *b_) +{ + struct commit_dist *a, *b; + + a = (struct commit_dist *)a_; + b = (struct commit_dist *)b_; + if (a->distance != b->distance) + return b->distance - a->distance; /* desc sort */ + return hashcmp(a->commit->object.sha1, b->commit->object.sha1); +} + +static struct commit_list *best_bisection_sorted(struct commit_list *list, int nr) +{ + struct commit_list *p; + struct commit_dist *array = xcalloc(nr, sizeof(*array)); + int cnt, i; + + for (p = list, cnt = 0; p; p = p->next) { + int distance; + unsigned flags = p->item->object.flags; + + if (revs.prune_fn && !(flags & TREECHANGE)) + continue; + distance = weight(p); + if (nr - distance < distance) + distance = nr - distance; + array[cnt].commit = p->item; + array[cnt].distance = distance; + cnt++; + } + qsort(array, cnt, sizeof(*array), compare_commit_dist); + for (p = list, i = 0; i < cnt; i++) { + struct name_decoration *r = xmalloc(sizeof(*r) + 100); + struct object *obj = &(array[i].commit->object); + + sprintf(r->name, "dist=%d", array[i].distance); + r->next = add_decoration(&name_decoration, obj, r); + p->item = array[i].commit; + p = p->next; + } + if (p) + p->next = NULL; + free(array); + return list; +} + /* * zero or positive weight is the number of interesting commits it can * reach, including itself. Especially, weight = 0 means it does not @@ -292,7 +346,8 @@ static struct commit_list *best_bisection(struct commit_list *list, int nr) * or positive distance. */ static struct commit_list *do_find_bisection(struct commit_list *list, - int nr, int *weights) + int nr, int *weights, + int find_all) { int n, counted; struct commit_list *p; @@ -351,7 +406,7 @@ static struct commit_list *do_find_bisection(struct commit_list *list, clear_distance(list); /* Does it happen to be at exactly half-way? */ - if (halfway(p, nr)) + if (!find_all && halfway(p, nr)) return p; counted++; } @@ -389,19 +444,22 @@ static struct commit_list *do_find_bisection(struct commit_list *list, weight_set(p, weight(q)); /* Does it happen to be at exactly half-way? */ - if (halfway(p, nr)) + if (!find_all && halfway(p, nr)) return p; } } show_list("bisection 2 counted all", counted, nr, list); - /* Then find the best one */ - return best_bisection(list, nr); + if (!find_all) + return best_bisection(list, nr); + else + return best_bisection_sorted(list, nr); } static struct commit_list *find_bisection(struct commit_list *list, - int *reaches, int *all) + int *reaches, int *all, + int find_all) { int nr, on_list; struct commit_list *p, *best, *next, *last; @@ -434,14 +492,13 @@ static struct commit_list *find_bisection(struct commit_list *list, weights = xcalloc(on_list, sizeof(*weights)); /* Do the real work of finding bisection commit. */ - best = do_find_bisection(list, nr, weights); - + best = do_find_bisection(list, nr, weights, find_all); if (best) { - best->next = NULL; + if (!find_all) + best->next = NULL; *reaches = weight(best); } free(weights); - return best; } @@ -468,6 +525,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) int i; int read_from_stdin = 0; int bisect_show_vars = 0; + int bisect_find_all = 0; git_config(git_default_config); init_revisions(&revs, prefix); @@ -490,6 +548,11 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) bisect_list = 1; continue; } + if (!strcmp(arg, "--bisect-all")) { + bisect_list = 1; + bisect_find_all = 1; + continue; + } if (!strcmp(arg, "--bisect-vars")) { bisect_list = 1; bisect_show_vars = 1; @@ -536,9 +599,11 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) if (bisect_list) { int reaches = reaches, all = all; - revs.commits = find_bisection(revs.commits, &reaches, &all); + revs.commits = find_bisection(revs.commits, &reaches, &all, + bisect_find_all); if (bisect_show_vars) { int cnt; + char hex[41]; if (!revs.commits) return 1; /* @@ -550,15 +615,22 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) * A bisect set of size N has (N-1) commits further * to test, as we already know one bad one. */ - cnt = all-reaches; + cnt = all - reaches; if (cnt < reaches) cnt = reaches; + strcpy(hex, sha1_to_hex(revs.commits->item->object.sha1)); + + if (bisect_find_all) { + traverse_commit_list(&revs, show_commit, show_object); + printf("------\n"); + } + printf("bisect_rev=%s\n" "bisect_nr=%d\n" "bisect_good=%d\n" "bisect_bad=%d\n" "bisect_all=%d\n", - sha1_to_hex(revs.commits->item->object.sha1), + hex, cnt - 1, all - reaches - 1, reaches - 1, diff --git a/log-tree.c b/log-tree.c index 62edd34455..3763ce94fc 100644 --- a/log-tree.c +++ b/log-tree.c @@ -15,7 +15,7 @@ static void show_parents(struct commit *commit, int abbrev) } } -static void show_decorations(struct commit *commit) +void show_decorations(struct commit *commit) { const char *prefix; struct name_decoration *decoration; diff --git a/log-tree.h b/log-tree.h index e82b56a20d..b33f7cd7ac 100644 --- a/log-tree.h +++ b/log-tree.h @@ -12,5 +12,6 @@ int log_tree_diff_flush(struct rev_info *); int log_tree_commit(struct rev_info *, struct commit *); int log_tree_opt_parse(struct rev_info *, const char **, int); void show_log(struct rev_info *opt, const char *sep); +void show_decorations(struct commit *commit); #endif From 3ac9f612cbbb146743c0734c707e6cb512c43aa4 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Mon, 22 Oct 2007 07:48:11 +0200 Subject: [PATCH 0288/1490] rev-list documentation: add "--bisect-all". Signed-off-by: Christian Couder Signed-off-by: Shawn O. Pearce --- Documentation/git-rev-list.txt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Documentation/git-rev-list.txt b/Documentation/git-rev-list.txt index 7cd0e8913e..485280423e 100644 --- a/Documentation/git-rev-list.txt +++ b/Documentation/git-rev-list.txt @@ -34,6 +34,7 @@ SYNOPSIS [ \--pretty | \--header ] [ \--bisect ] [ \--bisect-vars ] + [ \--bisect-all ] [ \--merge ] [ \--reverse ] [ \--walk-reflogs ] @@ -354,6 +355,21 @@ the expected number of commits to be tested if `bisect_rev` turns out to be bad to `bisect_bad`, and the number of commits we are bisecting right now to `bisect_all`. +--bisect-all:: + +This outputs all the commit objects between the included and excluded +commits, ordered by their distance to the included and excluded +commits. The farthest from them is displayed first. (This is the only +one displayed by `--bisect`.) + +This is useful because it makes it easy to choose a good commit to +test when you want to avoid to test some of them for some reason (they +may not compile for example). + +This option can be used along with `--bisect-vars`, in this case, +after all the sorted commit objects, there will be the same text as if +`--bisect-vars` had been used alone. + -- Commit Ordering From 8fe26f4481f274a6c752a6c13ac5da0460dbd1b6 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Mon, 22 Oct 2007 07:48:23 +0200 Subject: [PATCH 0289/1490] Bisect: fix some white spaces and empty lines breakages. Signed-off-by: Christian Couder Signed-off-by: Shawn O. Pearce --- git-bisect.sh | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/git-bisect.sh b/git-bisect.sh index 388887a556..436ccf66ff 100755 --- a/git-bisect.sh +++ b/git-bisect.sh @@ -64,7 +64,7 @@ bisect_start() { branch=`cat "$GIT_DIR/head-name"` else branch=master - fi + fi git checkout $branch || exit ;; refs/heads/*) @@ -95,11 +95,11 @@ bisect_start() { arg="$1" case "$arg" in --) - shift + shift break ;; *) - rev=$(git rev-parse --verify "$arg^{commit}" 2>/dev/null) || { + rev=$(git rev-parse --verify "$arg^{commit}" 2>/dev/null) || { test $has_double_dash -eq 1 && die "'$arg' does not appear to be a valid revision" break @@ -110,10 +110,10 @@ bisect_start() { else bisect_write_good "$rev" fi - shift + shift ;; esac - done + done sq "$@" >"$GIT_DIR/BISECT_NAMES" echo "git-bisect start$orig_args" >>"$GIT_DIR/BISECT_LOG" @@ -143,7 +143,7 @@ bisect_write_bad() { bisect_good() { bisect_autostart - case "$#" in + case "$#" in 0) revs=$(git rev-parse --verify HEAD) || exit ;; *) revs=$(git rev-parse --revs-only --no-flags "$@") && test '' != "$revs" || die "Bad rev input: $@" ;; @@ -153,7 +153,6 @@ bisect_good() { rev=$(git rev-parse --verify "$rev^{commit}") || exit bisect_write_good "$rev" echo "git-bisect good $rev" >>"$GIT_DIR/BISECT_LOG" - done bisect_auto_next } @@ -207,7 +206,7 @@ bisect_auto_next() { } bisect_next() { - case "$#" in 0) ;; *) usage ;; esac + case "$#" in 0) ;; *) usage ;; esac bisect_autostart bisect_next_check good @@ -255,7 +254,7 @@ bisect_reset() { exit 1 } branch="$1" ;; - *) + *) usage ;; esac if git checkout "$branch"; then From 97e1c51e15d94f523c67a499ecb633b0e20324cb Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Mon, 22 Oct 2007 07:48:36 +0200 Subject: [PATCH 0290/1490] Bisect: implement "bisect skip" to mark untestable revisions. When there are some "skip"ped revisions, we add the '--bisect-all' option to "git rev-list --bisect-vars". Then we filter out the "skip"ped revisions from the result of the rev-list command, and we modify the "bisect_rev" var accordingly. We don't always use "--bisect-all" because it is slower than "--bisect-vars" or "--bisect". When we cannot find for sure the first bad commit because of "skip"ped commits, we print the hash of each possible first bad commit and then we exit with code 2. Signed-off-by: Christian Couder Signed-off-by: Shawn O. Pearce --- git-bisect.sh | 125 ++++++++++++++++++++++++++++++++++-- t/t6030-bisect-porcelain.sh | 71 ++++++++++++++++++++ 2 files changed, 190 insertions(+), 6 deletions(-) diff --git a/git-bisect.sh b/git-bisect.sh index 436ccf66ff..cd46190302 100755 --- a/git-bisect.sh +++ b/git-bisect.sh @@ -17,6 +17,8 @@ git bisect replay replay bisection log. git bisect log show bisect log. +git bisect skip [...] + mark ... untestable revisions. git bisect run ... use ... to automatically bisect.' @@ -163,6 +165,28 @@ bisect_write_good() { echo "# good: "$(git show-branch $rev) >>"$GIT_DIR/BISECT_LOG" } +bisect_skip() { + bisect_autostart + case "$#" in + 0) revs=$(git rev-parse --verify HEAD) || exit ;; + *) revs=$(git rev-parse --revs-only --no-flags "$@") && + test '' != "$revs" || die "Bad rev input: $@" ;; + esac + for rev in $revs + do + rev=$(git rev-parse --verify "$rev^{commit}") || exit + bisect_write_skip "$rev" + echo "git-bisect skip $rev" >>"$GIT_DIR/BISECT_LOG" + done + bisect_auto_next +} + +bisect_write_skip() { + rev="$1" + echo "$rev" >"$GIT_DIR/refs/bisect/skip-$rev" + echo "# skip: "$(git show-branch $rev) >>"$GIT_DIR/BISECT_LOG" +} + bisect_next_check() { missing_good= missing_bad= git show-ref -q --verify refs/bisect/bad || missing_bad=t @@ -205,17 +229,97 @@ bisect_auto_next() { bisect_next_check && bisect_next || : } +filter_skipped() { + _eval="$1" + _skip="$2" + + if [ -z "$_skip" ]; then + eval $_eval + return + fi + + # Let's parse the output of: + # "git rev-list --bisect-vars --bisect-all ..." + eval $_eval | while read hash line + do + case "$VARS,$FOUND,$TRIED,$hash" in + # We display some vars. + 1,*,*,*) echo "$hash $line" ;; + + # Split line. + ,*,*,---*) ;; + + # We had nothing to search. + ,,,bisect_rev*) + echo "bisect_rev=" + VARS=1 + ;; + + # We did not find a good bisect rev. + # This should happen only if the "bad" + # commit is also a "skip" commit. + ,,*,bisect_rev*) + echo "bisect_rev=$TRIED" + VARS=1 + ;; + + # We are searching. + ,,*,*) + TRIED="${TRIED:+$TRIED|}$hash" + case "$_skip" in + *$hash*) ;; + *) + echo "bisect_rev=$hash" + echo "bisect_tried=\"$TRIED\"" + FOUND=1 + ;; + esac + ;; + + # We have already found a rev to be tested. + ,1,*,bisect_rev*) VARS=1 ;; + ,1,*,*) ;; + + # ??? + *) die "filter_skipped error " \ + "VARS: '$VARS' " \ + "FOUND: '$FOUND' " \ + "TRIED: '$TRIED' " \ + "hash: '$hash' " \ + "line: '$line'" + ;; + esac + done +} + +exit_if_skipped_commits () { + _tried=$1 + if expr "$_tried" : ".*[|].*" > /dev/null ; then + echo "There are only 'skip'ped commit left to test." + echo "The first bad commit could be any of:" + echo "$_tried" | sed -e 's/[|]/\n/g' + echo "We cannot bisect more!" + exit 2 + fi +} + bisect_next() { case "$#" in 0) ;; *) usage ;; esac bisect_autostart bisect_next_check good + skip=$(git for-each-ref --format='%(objectname)' \ + "refs/bisect/skip-*" | tr '[\012]' ' ') || exit + + BISECT_OPT='' + test -n "$skip" && BISECT_OPT='--bisect-all' + bad=$(git rev-parse --verify refs/bisect/bad) && good=$(git for-each-ref --format='^%(objectname)' \ "refs/bisect/good-*" | tr '[\012]' ' ') && - eval="git rev-list --bisect-vars $good $bad --" && + eval="git rev-list --bisect-vars $BISECT_OPT $good $bad --" && eval="$eval $(cat "$GIT_DIR/BISECT_NAMES")" && - eval=$(eval "$eval") && + eval=$(filter_skipped "$eval" "$skip") && eval "$eval" || exit if [ -z "$bisect_rev" ]; then @@ -223,11 +327,16 @@ bisect_next() { exit 1 fi if [ "$bisect_rev" = "$bad" ]; then + exit_if_skipped_commits "$bisect_tried" echo "$bisect_rev is first bad commit" git diff-tree --pretty $bisect_rev exit 0 fi + # We should exit here only if the "bad" + # commit is also a "skip" commit (see above). + exit_if_skipped_commits "$bisect_rev" + echo "Bisecting: $bisect_nr revisions left to test after this" echo "$bisect_rev" >"$GIT_DIR/refs/heads/new-bisect" git checkout -q new-bisect || exit @@ -286,15 +395,17 @@ bisect_replay () { eval "$cmd" ;; good) - echo "$rev" >"$GIT_DIR/refs/bisect/good-$rev" - echo "# good: "$(git show-branch $rev) >>"$GIT_DIR/BISECT_LOG" + bisect_write_good "$rev" echo "git-bisect good $rev" >>"$GIT_DIR/BISECT_LOG" ;; bad) - echo "$rev" >"$GIT_DIR/refs/bisect/bad" - echo "# bad: "$(git show-branch $rev) >>"$GIT_DIR/BISECT_LOG" + bisect_write_bad "$rev" echo "git-bisect bad $rev" >>"$GIT_DIR/BISECT_LOG" ;; + skip) + bisect_write_skip "$rev" + echo "git-bisect skip $rev" >>"$GIT_DIR/BISECT_LOG" + ;; *) echo >&2 "?? what are you talking about?" exit 1 ;; @@ -362,6 +473,8 @@ case "$#" in bisect_bad "$@" ;; good) bisect_good "$@" ;; + skip) + bisect_skip "$@" ;; next) # Not sure we want "next" at the UI level anymore. bisect_next "$@" ;; diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh index 03cdba5808..db82259afe 100755 --- a/t/t6030-bisect-porcelain.sh +++ b/t/t6030-bisect-porcelain.sh @@ -71,6 +71,63 @@ test_expect_success 'bisect start with one bad and good' ' git bisect next ' +# $HASH1 is good, $HASH4 is bad, we skip $HASH3 +# but $HASH2 is bad, +# so we should find $HASH2 as the first bad commit +test_expect_success 'bisect skip: successfull result' ' + git bisect reset && + git bisect start $HASH4 $HASH1 && + git bisect skip && + git bisect bad > my_bisect_log.txt && + grep "$HASH2 is first bad commit" my_bisect_log.txt && + git bisect reset +' + +# $HASH1 is good, $HASH4 is bad, we skip $HASH3 and $HASH2 +# so we should not be able to tell the first bad commit +# among $HASH2, $HASH3 and $HASH4 +test_expect_success 'bisect skip: cannot tell between 3 commits' ' + git bisect start $HASH4 $HASH1 && + git bisect skip || return 1 + + if git bisect skip > my_bisect_log.txt + then + echo Oops, should have failed. + false + else + test $? -eq 2 && + grep "first bad commit could be any of" my_bisect_log.txt && + ! grep $HASH1 my_bisect_log.txt && + grep $HASH2 my_bisect_log.txt && + grep $HASH3 my_bisect_log.txt && + grep $HASH4 my_bisect_log.txt && + git bisect reset + fi +' + +# $HASH1 is good, $HASH4 is bad, we skip $HASH3 +# but $HASH2 is good, +# so we should not be able to tell the first bad commit +# among $HASH3 and $HASH4 +test_expect_success 'bisect skip: cannot tell between 2 commits' ' + git bisect start $HASH4 $HASH1 && + git bisect skip || return 1 + + if git bisect good > my_bisect_log.txt + then + echo Oops, should have failed. + false + else + test $? -eq 2 && + grep "first bad commit could be any of" my_bisect_log.txt && + ! grep $HASH1 my_bisect_log.txt && + ! grep $HASH2 my_bisect_log.txt && + grep $HASH3 my_bisect_log.txt && + grep $HASH4 my_bisect_log.txt && + git bisect reset + fi +' + # We want to automatically find the commit that # introduced "Another" into hello. test_expect_success \ @@ -99,6 +156,20 @@ test_expect_success \ grep "$HASH4 is first bad commit" my_bisect_log.txt && git bisect reset' +# $HASH1 is good, $HASH5 is bad, we skip $HASH3 +# but $HASH4 is good, +# so we should find $HASH5 as the first bad commit +HASH5= +test_expect_success 'bisect skip: add line and then a new test' ' + add_line_into_file "5: Another new line." hello && + HASH5=$(git rev-parse --verify HEAD) && + git bisect start $HASH5 $HASH1 && + git bisect skip && + git bisect good > my_bisect_log.txt && + grep "$HASH5 is first bad commit" my_bisect_log.txt && + git bisect reset +' + # # test_done From 55624f9af49733ca6ae4abc3cd21e0f9a4f9f486 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Wed, 24 Oct 2007 07:01:05 +0200 Subject: [PATCH 0291/1490] Bisect: refactor "bisect_write_*" functions. Signed-off-by: Christian Couder Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- git-bisect.sh | 46 ++++++++++++++++++++-------------------------- 1 file changed, 20 insertions(+), 26 deletions(-) diff --git a/git-bisect.sh b/git-bisect.sh index cd46190302..82aa40433b 100755 --- a/git-bisect.sh +++ b/git-bisect.sh @@ -108,9 +108,9 @@ bisect_start() { } if [ $bad_seen -eq 0 ]; then bad_seen=1 - bisect_write_bad "$rev" + bisect_write 'bad' "$rev" else - bisect_write_good "$rev" + bisect_write 'good' "$rev" fi shift ;; @@ -122,6 +122,18 @@ bisect_start() { bisect_auto_next } +bisect_write() { + state="$1" + rev="$2" + case "$state" in + bad) tag="$state" ;; + good|skip) tag="$state"-"$rev" ;; + *) die "Bad bisect_write argument: $state" ;; + esac + echo "$rev" >"$GIT_DIR/refs/bisect/$tag" + echo "# $state: "$(git show-branch $rev) >>"$GIT_DIR/BISECT_LOG" +} + bisect_bad() { bisect_autostart case "$#" in @@ -132,17 +144,11 @@ bisect_bad() { *) usage ;; esac || exit - bisect_write_bad "$rev" + bisect_write 'bad' "$rev" echo "git-bisect bad $rev" >>"$GIT_DIR/BISECT_LOG" bisect_auto_next } -bisect_write_bad() { - rev="$1" - echo "$rev" >"$GIT_DIR/refs/bisect/bad" - echo "# bad: "$(git show-branch $rev) >>"$GIT_DIR/BISECT_LOG" -} - bisect_good() { bisect_autostart case "$#" in @@ -153,18 +159,12 @@ bisect_good() { for rev in $revs do rev=$(git rev-parse --verify "$rev^{commit}") || exit - bisect_write_good "$rev" + bisect_write 'good' "$rev" echo "git-bisect good $rev" >>"$GIT_DIR/BISECT_LOG" done bisect_auto_next } -bisect_write_good() { - rev="$1" - echo "$rev" >"$GIT_DIR/refs/bisect/good-$rev" - echo "# good: "$(git show-branch $rev) >>"$GIT_DIR/BISECT_LOG" -} - bisect_skip() { bisect_autostart case "$#" in @@ -175,18 +175,12 @@ bisect_skip() { for rev in $revs do rev=$(git rev-parse --verify "$rev^{commit}") || exit - bisect_write_skip "$rev" + bisect_write 'skip' "$rev" echo "git-bisect skip $rev" >>"$GIT_DIR/BISECT_LOG" done bisect_auto_next } -bisect_write_skip() { - rev="$1" - echo "$rev" >"$GIT_DIR/refs/bisect/skip-$rev" - echo "# skip: "$(git show-branch $rev) >>"$GIT_DIR/BISECT_LOG" -} - bisect_next_check() { missing_good= missing_bad= git show-ref -q --verify refs/bisect/bad || missing_bad=t @@ -395,15 +389,15 @@ bisect_replay () { eval "$cmd" ;; good) - bisect_write_good "$rev" + bisect_write 'good' "$rev" echo "git-bisect good $rev" >>"$GIT_DIR/BISECT_LOG" ;; bad) - bisect_write_bad "$rev" + bisect_write 'bad' "$rev" echo "git-bisect bad $rev" >>"$GIT_DIR/BISECT_LOG" ;; skip) - bisect_write_skip "$rev" + bisect_write 'skip' "$rev" echo "git-bisect skip $rev" >>"$GIT_DIR/BISECT_LOG" ;; *) From 737c74ee4219a81ebb616262579f63ce2a3f9698 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Wed, 24 Oct 2007 07:01:13 +0200 Subject: [PATCH 0292/1490] Bisect: refactor some logging into "bisect_write". Also use "die" instead of "echo >&2 something ; exit 1". And simplify "bisect_replay". Signed-off-by: Christian Couder Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- git-bisect.sh | 47 ++++++++++++++--------------------------------- 1 file changed, 14 insertions(+), 33 deletions(-) diff --git a/git-bisect.sh b/git-bisect.sh index 82aa40433b..61a2956647 100755 --- a/git-bisect.sh +++ b/git-bisect.sh @@ -106,12 +106,11 @@ bisect_start() { die "'$arg' does not appear to be a valid revision" break } - if [ $bad_seen -eq 0 ]; then - bad_seen=1 - bisect_write 'bad' "$rev" - else - bisect_write 'good' "$rev" - fi + case $bad_seen in + 0) state='bad' ; bad_seen=1 ;; + *) state='good' ;; + esac + bisect_write "$state" "$rev" 'nolog' shift ;; esac @@ -125,6 +124,7 @@ bisect_start() { bisect_write() { state="$1" rev="$2" + nolog="$3" case "$state" in bad) tag="$state" ;; good|skip) tag="$state"-"$rev" ;; @@ -132,6 +132,7 @@ bisect_write() { esac echo "$rev" >"$GIT_DIR/refs/bisect/$tag" echo "# $state: "$(git show-branch $rev) >>"$GIT_DIR/BISECT_LOG" + test -z "$nolog" && echo "git-bisect $state $rev" >>"$GIT_DIR/BISECT_LOG" } bisect_bad() { @@ -145,7 +146,6 @@ bisect_bad() { usage ;; esac || exit bisect_write 'bad' "$rev" - echo "git-bisect bad $rev" >>"$GIT_DIR/BISECT_LOG" bisect_auto_next } @@ -160,7 +160,6 @@ bisect_good() { do rev=$(git rev-parse --verify "$rev^{commit}") || exit bisect_write 'good' "$rev" - echo "git-bisect good $rev" >>"$GIT_DIR/BISECT_LOG" done bisect_auto_next } @@ -176,7 +175,6 @@ bisect_skip() { do rev=$(git rev-parse --verify "$rev^{commit}") || exit bisect_write 'skip' "$rev" - echo "git-bisect skip $rev" >>"$GIT_DIR/BISECT_LOG" done bisect_auto_next } @@ -352,10 +350,8 @@ bisect_reset() { else branch=master fi ;; - 1) git show-ref --verify --quiet -- "refs/heads/$1" || { - echo >&2 "$1 does not seem to be a valid branch" - exit 1 - } + 1) git show-ref --verify --quiet -- "refs/heads/$1" || + die "$1 does not seem to be a valid branch" branch="$1" ;; *) usage ;; @@ -375,10 +371,7 @@ bisect_clean_state() { } bisect_replay () { - test -r "$1" || { - echo >&2 "cannot read $1 for replaying" - exit 1 - } + test -r "$1" || die "cannot read $1 for replaying" bisect_reset while read bisect command rev do @@ -386,23 +379,11 @@ bisect_replay () { case "$command" in start) cmd="bisect_start $rev" - eval "$cmd" - ;; - good) - bisect_write 'good' "$rev" - echo "git-bisect good $rev" >>"$GIT_DIR/BISECT_LOG" - ;; - bad) - bisect_write 'bad' "$rev" - echo "git-bisect bad $rev" >>"$GIT_DIR/BISECT_LOG" - ;; - skip) - bisect_write 'skip' "$rev" - echo "git-bisect skip $rev" >>"$GIT_DIR/BISECT_LOG" - ;; + eval "$cmd" ;; + good|bad|skip) + bisect_write "$command" "$rev" ;; *) - echo >&2 "?? what are you talking about?" - exit 1 ;; + die "?? what are you talking about?" ;; esac done <"$1" bisect_auto_next From 155fc795b9c613af79781ebec5fd8eda084e1636 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Wed, 24 Oct 2007 07:01:21 +0200 Subject: [PATCH 0293/1490] Bisect: refactor "bisect_{bad,good,skip}" into "bisect_state". Signed-off-by: Christian Couder Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- git-bisect.sh | 82 +++++++++++++++++++-------------------------------- 1 file changed, 31 insertions(+), 51 deletions(-) diff --git a/git-bisect.sh b/git-bisect.sh index 61a2956647..f8d0099059 100755 --- a/git-bisect.sh +++ b/git-bisect.sh @@ -135,47 +135,33 @@ bisect_write() { test -z "$nolog" && echo "git-bisect $state $rev" >>"$GIT_DIR/BISECT_LOG" } -bisect_bad() { +bisect_state() { bisect_autostart - case "$#" in - 0) - rev=$(git rev-parse --verify HEAD) ;; - 1) - rev=$(git rev-parse --verify "$1^{commit}") ;; + state=$1 + case "$#,$state" in + 0,*) + die "Please call 'bisect_state' with at least one argument." ;; + 1,bad|1,good|1,skip) + rev=$(git rev-parse --verify HEAD) || + die "Bad rev input: HEAD" + bisect_write "$state" "$rev" ;; + 2,bad) + rev=$(git rev-parse --verify "$2^{commit}") || + die "Bad rev input: $2" + bisect_write "$state" "$rev" ;; + *,good|*,skip) + shift + revs=$(git rev-parse --revs-only --no-flags "$@") && + test '' != "$revs" || die "Bad rev input: $@" + for rev in $revs + do + rev=$(git rev-parse --verify "$rev^{commit}") || + die "Bad rev commit: $rev^{commit}" + bisect_write "$state" "$rev" + done ;; *) usage ;; - esac || exit - bisect_write 'bad' "$rev" - bisect_auto_next -} - -bisect_good() { - bisect_autostart - case "$#" in - 0) revs=$(git rev-parse --verify HEAD) || exit ;; - *) revs=$(git rev-parse --revs-only --no-flags "$@") && - test '' != "$revs" || die "Bad rev input: $@" ;; esac - for rev in $revs - do - rev=$(git rev-parse --verify "$rev^{commit}") || exit - bisect_write 'good' "$rev" - done - bisect_auto_next -} - -bisect_skip() { - bisect_autostart - case "$#" in - 0) revs=$(git rev-parse --verify HEAD) || exit ;; - *) revs=$(git rev-parse --revs-only --no-flags "$@") && - test '' != "$revs" || die "Bad rev input: $@" ;; - esac - for rev in $revs - do - rev=$(git rev-parse --verify "$rev^{commit}") || exit - bisect_write 'skip' "$rev" - done bisect_auto_next } @@ -405,24 +391,22 @@ bisect_run () { exit $res fi - # Use "bisect_good" or "bisect_bad" - # depending on run success or failure. + # Find current state depending on run success or failure. if [ $res -gt 0 ]; then - next_bisect='bisect_bad' + state='bad' else - next_bisect='bisect_good' + state='good' fi - # We have to use a subshell because bisect_good or - # bisect_bad functions can exit. - ( $next_bisect > "$GIT_DIR/BISECT_RUN" ) + # We have to use a subshell because "bisect_state" can exit. + ( bisect_state $state > "$GIT_DIR/BISECT_RUN" ) res=$? cat "$GIT_DIR/BISECT_RUN" if [ $res -ne 0 ]; then echo >&2 "bisect run failed:" - echo >&2 "$next_bisect exited with error code $res" + echo >&2 "'bisect_state $state' exited with error code $res" exit $res fi @@ -444,12 +428,8 @@ case "$#" in case "$cmd" in start) bisect_start "$@" ;; - bad) - bisect_bad "$@" ;; - good) - bisect_good "$@" ;; - skip) - bisect_skip "$@" ;; + bad|good|skip) + bisect_state "$cmd" "$@" ;; next) # Not sure we want "next" at the UI level anymore. bisect_next "$@" ;; From c39ce91827e6f8c9e2cbfb482f90fe6f58d4d573 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Mon, 22 Oct 2007 07:49:23 +0200 Subject: [PATCH 0294/1490] Bisect: add "bisect skip" to the documentation. Also fix "bisect bad" and "bisect good" short usage description. Signed-off-by: Christian Couder Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- Documentation/git-bisect.txt | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/Documentation/git-bisect.txt b/Documentation/git-bisect.txt index 1072fb87d1..785f381423 100644 --- a/Documentation/git-bisect.txt +++ b/Documentation/git-bisect.txt @@ -16,8 +16,9 @@ The command takes various subcommands, and different options depending on the subcommand: git bisect start [ [...]] [--] [...] - git bisect bad - git bisect good + git bisect bad [] + git bisect good [...] + git bisect skip [...] git bisect reset [] git bisect visualize git bisect replay @@ -134,6 +135,20 @@ $ git reset --hard HEAD~3 # try 3 revs before what Then compile and test the one you chose to try. After that, tell bisect what the result was as usual. +Bisect skip +~~~~~~~~~~~~ + +Instead of choosing by yourself a nearby commit, you may just want git +to do it for you using: + +------------ +$ git bisect skip # Current version cannot be tested +------------ + +But computing the commit to test may be slower afterwards and git may +eventually not be able to tell the first bad among a bad and one or +more "skip"ped commits. + Cutting down bisection by giving more parameters to bisect start ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 37f9fd0dde454db08d342e5ce7625e012507bb9b Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Mon, 22 Oct 2007 07:49:39 +0200 Subject: [PATCH 0295/1490] Bisect: add a "bisect replay" test case. Signed-off-by: Christian Couder Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- t/t6030-bisect-porcelain.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh index db82259afe..16d0c4a90e 100755 --- a/t/t6030-bisect-porcelain.sh +++ b/t/t6030-bisect-porcelain.sh @@ -167,6 +167,13 @@ test_expect_success 'bisect skip: add line and then a new test' ' git bisect skip && git bisect good > my_bisect_log.txt && grep "$HASH5 is first bad commit" my_bisect_log.txt && + git bisect log > log_to_replay.txt + git bisect reset +' + +test_expect_success 'bisect skip and bisect replay' ' + git bisect replay log_to_replay.txt > my_bisect_log.txt && + grep "$HASH5 is first bad commit" my_bisect_log.txt && git bisect reset ' From 71b0251cdd2cc35a983e21d4e71285db56d2a519 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Fri, 26 Oct 2007 05:39:37 +0200 Subject: [PATCH 0296/1490] Bisect run: "skip" current commit if script exit code is 125. This is incompatible with previous versions because an exit code of 125 used to mark current commit as "bad". But hopefully this exit code is not much used by test scripts or other programs. (126 and 127 are used by POSIX compliant shells to mean "found but not executable" and "command not found", respectively.) Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- Documentation/git-bisect.txt | 10 ++++++--- git-bisect.sh | 11 +++++++++- t/t6030-bisect-porcelain.sh | 40 ++++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 4 deletions(-) diff --git a/Documentation/git-bisect.txt b/Documentation/git-bisect.txt index 785f381423..4795349c10 100644 --- a/Documentation/git-bisect.txt +++ b/Documentation/git-bisect.txt @@ -182,14 +182,18 @@ $ git bisect run my_script ------------ Note that the "run" script (`my_script` in the above example) should -exit with code 0 in case the current source code is good and with a -code between 1 and 127 (included) in case the current source code is -bad. +exit with code 0 in case the current source code is good. Exit with a +code between 1 and 127 (inclusive), except 125, if the current +source code is bad. Any other exit code will abort the automatic bisect process. (A program that does "exit(-1)" leaves $? = 255, see exit(3) manual page, the value is chopped with "& 0377".) +The special exit code 125 should be used when the current source code +cannot be tested. If the "run" script exits with this code, the current +revision will be skipped, see `git bisect skip` above. + You may often find that during bisect you want to have near-constant tweaks (e.g., s/#define DEBUG 0/#define DEBUG 1/ in a header file, or "revision that does not have this commit needs this patch applied to diff --git a/git-bisect.sh b/git-bisect.sh index f8d0099059..180c6c280c 100755 --- a/git-bisect.sh +++ b/git-bisect.sh @@ -392,7 +392,10 @@ bisect_run () { fi # Find current state depending on run success or failure. - if [ $res -gt 0 ]; then + # A special exit code of 125 means cannot test. + if [ $res -eq 125 ]; then + state='skip' + elif [ $res -gt 0 ]; then state='bad' else state='good' @@ -404,6 +407,12 @@ bisect_run () { cat "$GIT_DIR/BISECT_RUN" + if grep "first bad commit could be any of" "$GIT_DIR/BISECT_RUN" \ + > /dev/null; then + echo >&2 "bisect run cannot continue any more" + exit $res + fi + if [ $res -ne 0 ]; then echo >&2 "bisect run failed:" echo >&2 "'bisect_state $state' exited with error code $res" diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh index 16d0c4a90e..53956c08e2 100755 --- a/t/t6030-bisect-porcelain.sh +++ b/t/t6030-bisect-porcelain.sh @@ -177,6 +177,46 @@ test_expect_success 'bisect skip and bisect replay' ' git bisect reset ' +HASH6= +test_expect_success 'bisect run & skip: cannot tell between 2' ' + add_line_into_file "6: Yet a line." hello && + HASH6=$(git rev-parse --verify HEAD) && + echo "#"\!"/bin/sh" > test_script.sh && + echo "tail -1 hello | grep Ciao > /dev/null && exit 125" >> test_script.sh && + echo "grep line hello > /dev/null" >> test_script.sh && + echo "test \$? -ne 0" >> test_script.sh && + chmod +x test_script.sh && + git bisect start $HASH6 $HASH1 && + if git bisect run ./test_script.sh > my_bisect_log.txt + then + echo Oops, should have failed. + false + else + test $? -eq 2 && + grep "first bad commit could be any of" my_bisect_log.txt && + ! grep $HASH3 my_bisect_log.txt && + ! grep $HASH6 my_bisect_log.txt && + grep $HASH4 my_bisect_log.txt && + grep $HASH5 my_bisect_log.txt + fi +' + +HASH7= +test_expect_success 'bisect run & skip: find first bad' ' + git bisect reset && + add_line_into_file "7: Should be the last line." hello && + HASH7=$(git rev-parse --verify HEAD) && + echo "#"\!"/bin/sh" > test_script.sh && + echo "tail -1 hello | grep Ciao > /dev/null && exit 125" >> test_script.sh && + echo "tail -1 hello | grep day > /dev/null && exit 125" >> test_script.sh && + echo "grep Yet hello > /dev/null" >> test_script.sh && + echo "test \$? -ne 0" >> test_script.sh && + chmod +x test_script.sh && + git bisect start $HASH7 $HASH1 && + git bisect run ./test_script.sh > my_bisect_log.txt && + grep "$HASH6 is first bad commit" my_bisect_log.txt +' + # # test_done From 7791ecbc62b792b3eaa6d722b6dadcea4d0f322d Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 23 Oct 2007 13:33:26 -0700 Subject: [PATCH 0297/1490] revert/cherry-pick: work on merge commits as well Usually you cannot revert a merge because you do not know which side of the merge should be considered the mainline (iow, what change to reverse). With this patch, cherry-pick and revert learn -m (--mainline) option that lets you specify the parent number (starting from 1) of the mainline, so that you can: git revert -m 1 $merge to reverse the changes introduced by the $merge commit relative to its first parent, and: git cherry-pick -m 2 $merge to replay the changes introduced by the $merge commit relative to its second parent. Signed-off-by: Junio C Hamano --- Documentation/git-cherry-pick.txt | 9 ++++++- Documentation/git-revert.txt | 9 ++++++- builtin-revert.c | 42 +++++++++++++++++++++++++------ git-compat-util.h | 13 ++++++++++ 4 files changed, 64 insertions(+), 9 deletions(-) diff --git a/Documentation/git-cherry-pick.txt b/Documentation/git-cherry-pick.txt index 76a2edfd9b..937c4a7926 100644 --- a/Documentation/git-cherry-pick.txt +++ b/Documentation/git-cherry-pick.txt @@ -7,7 +7,7 @@ git-cherry-pick - Apply the change introduced by an existing commit SYNOPSIS -------- -'git-cherry-pick' [--edit] [-n] [-x] +'git-cherry-pick' [--edit] [-n] [-m parent-number] [-x] DESCRIPTION ----------- @@ -44,6 +44,13 @@ OPTIONS described above, and `-r` was to disable it. Now the default is not to do `-x` so this option is a no-op. +-m parent-number|--mainline parent-number:: + Usually you cannot revert a merge because you do not know which + side of the merge should be considered the mainline. This + option specifies the parent number (starting from 1) of + the mainline and allows cherry-pick to replay the change + relative to the specified parent. + -n|--no-commit:: Usually the command automatically creates a commit with a commit log message stating which commit was diff --git a/Documentation/git-revert.txt b/Documentation/git-revert.txt index 69db498447..3457c40787 100644 --- a/Documentation/git-revert.txt +++ b/Documentation/git-revert.txt @@ -7,7 +7,7 @@ git-revert - Revert an existing commit SYNOPSIS -------- -'git-revert' [--edit | --no-edit] [-n] +'git-revert' [--edit | --no-edit] [-n] [-m parent-number] DESCRIPTION ----------- @@ -27,6 +27,13 @@ OPTIONS message prior committing the revert. This is the default if you run the command from a terminal. +-m parent-number|--mainline parent-number:: + Usually you cannot revert a merge because you do not know which + side of the merge should be considered the mainline. This + option specifies the parent number (starting from 1) of + the mainline and allows revert to reverse the change + relative to the specified parent. + --no-edit:: With this option, `git-revert` will not start the commit message editor. diff --git a/builtin-revert.c b/builtin-revert.c index a655c8ee2a..bfed69d7e2 100644 --- a/builtin-revert.c +++ b/builtin-revert.c @@ -19,9 +19,9 @@ * Copyright (c) 2005 Junio C Hamano */ -static const char *revert_usage = "git-revert [--edit | --no-edit] [-n] "; +static const char *revert_usage = "git-revert [--edit | --no-edit] [-n] [-m parent-number] "; -static const char *cherry_pick_usage = "git-cherry-pick [--edit] [-n] [-r] [-x] "; +static const char *cherry_pick_usage = "git-cherry-pick [--edit] [-n] [-m parent-number] [-r] [-x] "; static int edit; static int replay; @@ -29,6 +29,7 @@ static enum { REVERT, CHERRY_PICK } action; static int no_commit; static struct commit *commit; static int needed_deref; +static int mainline; static const char *me; @@ -58,6 +59,12 @@ static void parse_options(int argc, const char **argv) else if (!strcmp(arg, "-x") || !strcmp(arg, "--i-really-want-" "to-expose-my-private-commit-object-name")) replay = 0; + else if (!strcmp(arg, "-m") || !strcmp(arg, "--mainline")) { + if (++i >= argc || + strtol_i(argv[i], 10, &mainline) || + mainline <= 0) + usage(usage_str); + } else if (strcmp(arg, "-r")) usage(usage_str); } @@ -234,7 +241,7 @@ static int merge_recursive(const char *base_sha1, static int revert_or_cherry_pick(int argc, const char **argv) { unsigned char head[20]; - struct commit *base, *next; + struct commit *base, *next, *parent; int i; char *oneline, *reencoded_message = NULL; const char *message, *encoding; @@ -269,8 +276,29 @@ static int revert_or_cherry_pick(int argc, const char **argv) if (!commit->parents) die ("Cannot %s a root commit", me); - if (commit->parents->next) - die ("Cannot %s a multi-parent commit.", me); + if (commit->parents->next) { + /* Reverting or cherry-picking a merge commit */ + int cnt; + struct commit_list *p; + + if (!mainline) + die("Commit %s is a merge but no -m option was given.", + sha1_to_hex(commit->object.sha1)); + + for (cnt = 1, p = commit->parents; + cnt != mainline && p; + cnt++) + p = p->next; + if (cnt != mainline || !p) + die("Commit %s does not have parent %d", + sha1_to_hex(commit->object.sha1), mainline); + parent = p->item; + } else if (0 < mainline) + die("Mainline was specified but commit %s is not a merge.", + sha1_to_hex(commit->object.sha1)); + else + parent = commit->parents->item; + if (!(message = commit->buffer)) die ("Cannot get commit message for %s", sha1_to_hex(commit->object.sha1)); @@ -299,14 +327,14 @@ static int revert_or_cherry_pick(int argc, const char **argv) char *oneline_body = strchr(oneline, ' '); base = commit; - next = commit->parents->item; + next = parent; add_to_msg("Revert \""); add_to_msg(oneline_body + 1); add_to_msg("\"\n\nThis reverts commit "); add_to_msg(sha1_to_hex(commit->object.sha1)); add_to_msg(".\n"); } else { - base = commit->parents->item; + base = parent; next = commit; set_author_ident_env(message); add_message_to_msg(message); diff --git a/git-compat-util.h b/git-compat-util.h index 474f1d1ffb..7b29d1b905 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -381,4 +381,17 @@ static inline int strtoul_ui(char const *s, int base, unsigned int *result) return 0; } +static inline int strtol_i(char const *s, int base, int *result) +{ + long ul; + char *p; + + errno = 0; + ul = strtol(s, &p, base); + if (errno || *p || p == s || (int) ul != ul) + return -1; + *result = ul; + return 0; +} + #endif From cca5d946d692fde7ea5408a694cb4b1c97a5a838 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sat, 27 Oct 2007 21:16:56 +1000 Subject: [PATCH 0298/1490] gitk: Simplify the code for finding commits This unifies findmore and findmorerev, and adds the ability to do a search with or without wrap around from the end of the list of commits to the beginning (or vice versa for reverse searches). findnext and findprev are gone, and the buttons and keys for searching all call dofind now. dofind doesn't unmark the matches to start with. Shift-up and shift-down are back by popular request, and the searches they do don't wrap around. The other keys that do searches (/, ?, return, M-f) do wrapping searches except for M-g. Signed-off-by: Paul Mackerras --- gitk | 212 ++++++++++++++++------------------------------------------- 1 file changed, 57 insertions(+), 155 deletions(-) diff --git a/gitk b/gitk index 135511e9fb..5230e3bb9d 100755 --- a/gitk +++ b/gitk @@ -764,8 +764,8 @@ proc makewindow {} { # build up the bottom bar of upper window label .tf.lbar.flabel -text "Find " -font uifont - button .tf.lbar.fnext -text "next" -command dofind -font uifont - button .tf.lbar.fprev -text "prev" -command {dofind 1} -font uifont + button .tf.lbar.fnext -text "next" -command {dofind 1 1} -font uifont + button .tf.lbar.fprev -text "prev" -command {dofind -1 1} -font uifont label .tf.lbar.flab2 -text " commit " -font uifont pack .tf.lbar.flabel .tf.lbar.fnext .tf.lbar.fprev .tf.lbar.flab2 \ -side left -fill y @@ -959,6 +959,8 @@ proc makewindow {} { bindkey sellastline bind . "selnextline -1" bind . "selnextline 1" + bind . "dofind -1 0" + bind . "dofind 1 0" bindkey "goforw" bindkey "goback" bind . "selnextpage -1" @@ -983,14 +985,14 @@ proc makewindow {} { bindkey b "$ctext yview scroll -1 pages" bindkey d "$ctext yview scroll 18 units" bindkey u "$ctext yview scroll -18 units" - bindkey / {findnext 1} - bindkey {findnext 0} - bindkey ? findprev + bindkey / {dofind 1 1} + bindkey {dofind 1 1} + bindkey ? {dofind -1 1} bindkey f nextfile bindkey updatecommits bind . <$M1B-q> doquit - bind . <$M1B-f> dofind - bind . <$M1B-g> {findnext 0} + bind . <$M1B-f> {dofind 1 1} + bind . <$M1B-g> {dofind 1 0} bind . <$M1B-r> dosearchback bind . <$M1B-s> dosearch bind . <$M1B-equal> {incrfont 1} @@ -999,7 +1001,7 @@ proc makewindow {} { bind . <$M1B-KP_Subtract> {incrfont -1} wm protocol . WM_DELETE_WINDOW doquit bind . "click %W" - bind $fstring dofind + bind $fstring {dofind 1 1} bind $sha1entry gotocommit bind $sha1entry <> clearsha1 bind $cflist <1> {sel_flist %W %x %y; break} @@ -1325,8 +1327,8 @@ Gitk key bindings: <$M1T-Down> Scroll commit list down one line <$M1T-PageUp> Scroll commit list up one page <$M1T-PageDown> Scroll commit list down one page - Move to previous highlighted line - Move to next highlighted line + Find backwards (upwards, later commits) + Find forwards (downwards, earlier commits) , b Scroll diff view up one page Scroll diff view up one page Scroll diff view down one page @@ -2459,11 +2461,7 @@ proc readfhighlight {} { return 0 } if {[info exists find_dirn]} { - if {$find_dirn > 0} { - run findmore - } else { - run findmorerev - } + run findmore } return 1 } @@ -4247,15 +4245,18 @@ proc findmatches {f} { return $matches } -proc dofind {{rev 0}} { +proc dofind {{dirn 1} {wrap 1}} { global findstring findstartline findcurline selectedline numcommits - global gdttype filehighlight fh_serial find_dirn + global gdttype filehighlight fh_serial find_dirn findallowwrap - unmarkmatches + if {[info exists find_dirn]} { + if {$find_dirn == $dirn} return + stopfinding + } focus . if {$findstring eq {} || $numcommits == 0} return if {![info exists selectedline]} { - set findstartline [lindex [visiblerows] $rev] + set findstartline [lindex [visiblerows] [expr {$dirn < 0}]] } else { set findstartline $selectedline } @@ -4265,13 +4266,9 @@ proc dofind {{rev 0}} { after cancel do_file_hl $fh_serial do_file_hl $fh_serial } - if {!$rev} { - set find_dirn 1 - run findmore - } else { - set find_dirn -1 - run findmorerev - } + set find_dirn $dirn + set findallowwrap $wrap + run findmore } proc stopfinding {} { @@ -4286,61 +4283,50 @@ proc stopfinding {} { } } -proc findnext {restart} { - global findcurline find_dirn - - if {[info exists find_dirn]} return - if {![info exists findcurline]} { - if {$restart} { - dofind - } else { - bell - } - } else { - set find_dirn 1 - run findmore - nowbusy finding "Searching" - } -} - -proc findprev {} { - global findcurline find_dirn - - if {[info exists find_dirn]} return - if {![info exists findcurline]} { - dofind 1 - } else { - set find_dirn -1 - run findmorerev - nowbusy finding "Searching" - } -} - proc findmore {} { global commitdata commitinfo numcommits findpattern findloc global findstartline findcurline displayorder global find_dirn gdttype fhighlights fprogcoord + global findallowwrap if {![info exists find_dirn]} { return 0 } set fldtypes {Headline Author Date Committer CDate Comments} - set l [expr {$findcurline + 1}] - if {$l >= $numcommits} { - set l 0 - } - if {$l <= $findstartline} { - set lim [expr {$findstartline + 1}] + set l $findcurline + set moretodo 0 + if {$find_dirn > 0} { + incr l + if {$l >= $numcommits} { + set l 0 + } + if {$l <= $findstartline} { + set lim [expr {$findstartline + 1}] + } else { + set lim $numcommits + set moretodo $findallowwrap + } } else { - set lim $numcommits + if {$l == 0} { + set l $numcommits + } + incr l -1 + if {$l >= $findstartline} { + set lim [expr {$findstartline - 1}] + } else { + set lim -1 + set moretodo $findallowwrap + } } - if {$lim - $l > 500} { - set lim [expr {$l + 500}] + set n [expr {($lim - $l) * $find_dirn}] + if {$n > 500} { + set n 500 + set moretodo 1 } set found 0 set domore 1 if {$gdttype eq "containing:"} { - for {} {$l < $lim} {incr l} { + for {} {$n > 0} {incr n -1; incr l $find_dirn} { set id [lindex $displayorder $l] # shouldn't happen unless git log doesn't give all the commits... if {![info exists commitdata($id)]} continue @@ -4359,13 +4345,13 @@ proc findmore {} { if {$found} break } } else { - for {} {$l < $lim} {incr l} { + for {} {$n > 0} {incr n -1; incr l $find_dirn} { set id [lindex $displayorder $l] if {![info exists fhighlights($l)]} { askfilehighlight $l $id if {$domore} { set domore 0 - set findcurline [expr {$l - 1}] + set findcurline [expr {$l - $find_dirn}] } } elseif {$fhighlights($l)} { set found $domore @@ -4373,7 +4359,7 @@ proc findmore {} { } } } - if {$found || ($domore && $l == $findstartline + 1)} { + if {$found || ($domore && !$moretodo)} { unset findcurline unset find_dirn notbusy finding @@ -4389,93 +4375,9 @@ proc findmore {} { if {!$domore} { flushhighlights } else { - set findcurline [expr {$l - 1}] + set findcurline [expr {$l - $find_dirn}] } - set n [expr {$findcurline - ($findstartline + 1)}] - if {$n < 0} { - incr n $numcommits - } - set fprogcoord [expr {$n * 1.0 / $numcommits}] - adjustprogress - return $domore -} - -proc findmorerev {} { - global commitdata commitinfo numcommits findpattern findloc - global findstartline findcurline displayorder - global find_dirn gdttype fhighlights fprogcoord - - if {![info exists find_dirn]} { - return 0 - } - set fldtypes {Headline Author Date Committer CDate Comments} - set l $findcurline - if {$l == 0} { - set l $numcommits - } - incr l -1 - if {$l >= $findstartline} { - set lim [expr {$findstartline - 1}] - } else { - set lim -1 - } - if {$l - $lim > 500} { - set lim [expr {$l - 500}] - } - set found 0 - set domore 1 - if {$gdttype eq "containing:"} { - for {} {$l > $lim} {incr l -1} { - set id [lindex $displayorder $l] - if {![info exists commitdata($id)]} continue - if {![doesmatch $commitdata($id)]} continue - if {![info exists commitinfo($id)]} { - getcommit $id - } - set info $commitinfo($id) - foreach f $info ty $fldtypes { - if {($findloc eq "All fields" || $findloc eq $ty) && - [doesmatch $f]} { - set found 1 - break - } - } - if {$found} break - } - } else { - for {} {$l > $lim} {incr l -1} { - set id [lindex $displayorder $l] - if {![info exists fhighlights($l)]} { - askfilehighlight $l $id - if {$domore} { - set domore 0 - set findcurline [expr {$l + 1}] - } - } elseif {$fhighlights($l)} { - set found $domore - break - } - } - } - if {$found || ($domore && $l == $findstartline - 1)} { - unset findcurline - unset find_dirn - notbusy finding - set fprogcoord 0 - adjustprogress - if {$found} { - findselectline $l - } else { - bell - } - return 0 - } - if {!$domore} { - flushhighlights - } else { - set findcurline [expr {$l + 1}] - } - set n [expr {($findstartline - 1) - $findcurline}] + set n [expr {($findcurline - $findstartline) * $find_dirn - 1}] if {$n < 0} { incr n $numcommits } From 7388bcbc5431552718dde5c3259d861d2fa75a12 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sat, 27 Oct 2007 21:31:07 +1000 Subject: [PATCH 0299/1490] gitk: Use the UI font for the diff/old version/new version radio buttons This makes the radio buttons for selecting whether to see the full diff, the old version or the new version use the same font as the other user interface elements. Signed-off-by: Paul Mackerras --- gitk | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gitk b/gitk index 4efcbb7957..1da0b0af1d 100755 --- a/gitk +++ b/gitk @@ -830,11 +830,11 @@ proc makewindow {} { lappend entries $sstring trace add variable searchstring write incrsearch pack $sstring -side left -expand 1 -fill x - radiobutton .bleft.mid.diff -text "Diff" \ + radiobutton .bleft.mid.diff -text "Diff" -font uifont \ -command changediffdisp -variable diffelide -value {0 0} - radiobutton .bleft.mid.old -text "Old version" \ + radiobutton .bleft.mid.old -text "Old version" -font uifont \ -command changediffdisp -variable diffelide -value {0 1} - radiobutton .bleft.mid.new -text "New version" \ + radiobutton .bleft.mid.new -text "New version" -font uifont \ -command changediffdisp -variable diffelide -value {1 0} label .bleft.mid.labeldiffcontext -text " Lines of context: " \ -font uifont From 9ad7c5ae8ae4625bfe32d910b0b480cfea9819e0 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 26 Oct 2007 23:09:48 -0700 Subject: [PATCH 0300/1490] git-fetch: do not fail when remote branch disappears When the branch named with branch.$name.merge is not covered by the fetch configuration for the remote repository named with branch.$name.remote, we automatically add that branch to the set of branches to be fetched. However, if the remote repository does not have that branch (e.g. it used to exist, but got removed), this is not a reason to fail the git-fetch itself. The situation however will be noticed if git-fetch was called by git-pull, as the resulting FETCH_HEAD would not have any entry that is marked for merging. Acked-By: Daniel Barkalow Signed-off-by: Junio C Hamano --- builtin-fetch.c | 24 ++++++++++++++++-------- remote.c | 20 ++++++++++++-------- remote.h | 5 ++++- 3 files changed, 32 insertions(+), 17 deletions(-) diff --git a/builtin-fetch.c b/builtin-fetch.c index b9d2b0c27e..003ed76d16 100644 --- a/builtin-fetch.c +++ b/builtin-fetch.c @@ -48,15 +48,21 @@ static void add_merge_config(struct ref **head, if (rm) continue; - /* Not fetched to a tracking branch? We need to fetch + /* + * Not fetched to a tracking branch? We need to fetch * it anyway to allow this branch's "branch.$name.merge" - * to be honored by git-pull. + * to be honored by git-pull, but we do not have to + * fail if branch.$name.merge is misconfigured to point + * at a nonexisting branch. If we were indeed called by + * git-pull, it will notice the misconfiguration because + * there is no entry in the resulting FETCH_HEAD marked + * for merging. */ refspec.src = branch->merge[i]->src; refspec.dst = NULL; refspec.pattern = 0; refspec.force = 0; - get_fetch_map(remote_refs, &refspec, tail); + get_fetch_map(remote_refs, &refspec, tail, 1); for (rm = *old_tail; rm; rm = rm->next) rm->merge = 1; } @@ -75,7 +81,7 @@ static struct ref *get_ref_map(struct transport *transport, if (ref_count || tags) { for (i = 0; i < ref_count; i++) { - get_fetch_map(remote_refs, &refs[i], &tail); + get_fetch_map(remote_refs, &refs[i], &tail, 0); if (refs[i].dst && refs[i].dst[0]) *autotags = 1; } @@ -88,7 +94,7 @@ static struct ref *get_ref_map(struct transport *transport, refspec.dst = "refs/tags/"; refspec.pattern = 1; refspec.force = 0; - get_fetch_map(remote_refs, &refspec, &tail); + get_fetch_map(remote_refs, &refspec, &tail, 0); } } else { /* Use the defaults */ @@ -97,7 +103,7 @@ static struct ref *get_ref_map(struct transport *transport, int has_merge = branch_has_merge_config(branch); if (remote && (remote->fetch_refspec_nr || has_merge)) { for (i = 0; i < remote->fetch_refspec_nr; i++) { - get_fetch_map(remote_refs, &remote->fetch[i], &tail); + get_fetch_map(remote_refs, &remote->fetch[i], &tail, 0); if (remote->fetch[i].dst && remote->fetch[i].dst[0]) *autotags = 1; @@ -110,11 +116,13 @@ static struct ref *get_ref_map(struct transport *transport, * as given in branch..remote, we add the * ref given in branch..merge, too. */ - if (has_merge && !strcmp(branch->remote_name, - remote->name)) + if (has_merge && + !strcmp(branch->remote_name, remote->name)) add_merge_config(&ref_map, remote_refs, branch, &tail); } else { ref_map = get_remote_ref(remote_refs, "HEAD"); + if (!ref_map) + die("Couldn't find remote ref HEAD"); ref_map->merge = 1; } } diff --git a/remote.c b/remote.c index 170015aabf..bec2ba1adb 100644 --- a/remote.c +++ b/remote.c @@ -857,7 +857,7 @@ struct ref *get_remote_ref(struct ref *remote_refs, const char *name) struct ref *ref = find_ref_by_name_abbrev(remote_refs, name); if (!ref) - die("Couldn't find remote ref %s\n", name); + return NULL; return copy_ref(ref); } @@ -889,20 +889,24 @@ static struct ref *get_local_ref(const char *name) int get_fetch_map(struct ref *remote_refs, const struct refspec *refspec, - struct ref ***tail) + struct ref ***tail, + int missing_ok) { struct ref *ref_map, *rm; if (refspec->pattern) { ref_map = get_expanded_map(remote_refs, refspec); } else { - ref_map = get_remote_ref(remote_refs, - refspec->src[0] ? - refspec->src : "HEAD"); + const char *name = refspec->src[0] ? refspec->src : "HEAD"; - ref_map->peer_ref = get_local_ref(refspec->dst); - if (ref_map->peer_ref && refspec->force) - ref_map->peer_ref->force = 1; + ref_map = get_remote_ref(remote_refs, name); + if (!missing_ok && !ref_map) + die("Couldn't find remote ref %s", name); + if (ref_map) { + ref_map->peer_ref = get_local_ref(refspec->dst); + if (ref_map->peer_ref && refspec->force) + ref_map->peer_ref->force = 1; + } } for (rm = ref_map; rm; rm = rm->next) { diff --git a/remote.h b/remote.h index c62636d78e..878b4ecc32 100644 --- a/remote.h +++ b/remote.h @@ -67,9 +67,12 @@ int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail, * *tail is the pointer to the tail pointer of the list of results * beforehand, and will be set to the tail pointer of the list of * results afterward. + * + * missing_ok is usually false, but when we are adding branch.$name.merge + * it is Ok if the branch is not at the remote anymore. */ int get_fetch_map(struct ref *remote_refs, const struct refspec *refspec, - struct ref ***tail); + struct ref ***tail, int missing_ok); struct ref *get_remote_ref(struct ref *remote_refs, const char *name); From 3697c5f37a8b7b15d0a3be51d05147654a951115 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Sun, 28 Oct 2007 11:05:11 +0100 Subject: [PATCH 0301/1490] git.el: Fix typo in "Reverted file" message. Signed-off-by: Alexandre Julliard Signed-off-by: Junio C Hamano --- contrib/emacs/git.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/emacs/git.el b/contrib/emacs/git.el index 4286d160a0..8cfbdd7be4 100644 --- a/contrib/emacs/git.el +++ b/contrib/emacs/git.el @@ -955,7 +955,7 @@ Return the list of files that haven't been handled." (when modified (apply #'git-call-process-env nil nil "checkout" "HEAD" modified)) (git-update-status-files (append added modified) 'uptodate) - (git-success-message "Reverted" files)))) + (git-success-message "Reverted" (git-get-filenames files))))) (defun git-resolve-file () "Resolve conflicts in marked file(s)." From 6df023884b87ef140829d78b67fab90a7f9b1211 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Sun, 28 Oct 2007 11:05:45 +0100 Subject: [PATCH 0302/1490] git.el: Fix typo in git-update-saved-file error handling. Spotted by Matthieu Lemerre. Signed-off-by: Alexandre Julliard Signed-off-by: Junio C Hamano --- contrib/emacs/git.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/emacs/git.el b/contrib/emacs/git.el index 8cfbdd7be4..0e5091c1b7 100644 --- a/contrib/emacs/git.el +++ b/contrib/emacs/git.el @@ -1353,7 +1353,7 @@ Commands: "Update the corresponding git-status buffer when a file is saved. Meant to be used in `after-save-hook'." (let* ((file (expand-file-name buffer-file-name)) - (dir (condition-case nil (git-get-top-dir (file-name-directory file)))) + (dir (condition-case nil (git-get-top-dir (file-name-directory file)) (error nil))) (buffer (and dir (git-find-status-buffer dir)))) (when buffer (with-current-buffer buffer From 2f6e86a86fb9830c0c3205a317f6205f156cfacc Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Sun, 28 Oct 2007 11:06:27 +0100 Subject: [PATCH 0303/1490] git.el: Refresh only the changed file marks when marking/unmarking all. Signed-off-by: Alexandre Julliard Signed-off-by: Junio C Hamano --- contrib/emacs/git.el | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/contrib/emacs/git.el b/contrib/emacs/git.el index 0e5091c1b7..e5ee8ce58b 100644 --- a/contrib/emacs/git.el +++ b/contrib/emacs/git.el @@ -842,7 +842,8 @@ Return the list of files that haven't been handled." "Mark all files." (interactive) (unless git-status (error "Not in git-status buffer.")) - (ewoc-map (lambda (info) (setf (git-fileinfo->marked info) t) t) git-status) + (ewoc-map (lambda (info) (unless (git-fileinfo->marked info) + (setf (git-fileinfo->marked info) t))) git-status) ; move back to goal column after invalidate (when goal-column (move-to-column goal-column))) @@ -850,7 +851,9 @@ Return the list of files that haven't been handled." "Unmark all files." (interactive) (unless git-status (error "Not in git-status buffer.")) - (ewoc-map (lambda (info) (setf (git-fileinfo->marked info) nil) t) git-status) + (ewoc-map (lambda (info) (when (git-fileinfo->marked info) + (setf (git-fileinfo->marked info) nil) + t)) git-status) ; move back to goal column after invalidate (when goal-column (move-to-column goal-column))) From d53a35020d380c199b010c9884ab15995f8e982b Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Sun, 28 Oct 2007 11:07:14 +0100 Subject: [PATCH 0304/1490] git.el: Run git-gc --auto after commits. Signed-off-by: Alexandre Julliard Signed-off-by: Junio C Hamano --- contrib/emacs/git.el | 1 + 1 file changed, 1 insertion(+) diff --git a/contrib/emacs/git.el b/contrib/emacs/git.el index e5ee8ce58b..e147da0596 100644 --- a/contrib/emacs/git.el +++ b/contrib/emacs/git.el @@ -796,6 +796,7 @@ Return the list of files that haven't been handled." (with-current-buffer buffer (erase-buffer)) (dolist (info files) (git-set-fileinfo-state info 'uptodate)) (git-call-process-env nil nil "rerere") + (git-call-process-env nil nil "gc" "--auto") (git-refresh-files) (git-refresh-ewoc-hf git-status) (message "Committed %s." commit) From 1c1f79a1e44547d039e7bf94d9aaadd3fae007d1 Mon Sep 17 00:00:00 2001 From: Aurelien Bompard Date: Sun, 28 Oct 2007 18:47:30 +0100 Subject: [PATCH 0305/1490] honor the http.sslVerify option in shell scripts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Aurélien Bompard Signed-off-by: Junio C Hamano --- git-clone.sh | 3 ++- git-ls-remote.sh | 7 ++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/git-clone.sh b/git-clone.sh index 5e582fe247..0ea3c24f59 100755 --- a/git-clone.sh +++ b/git-clone.sh @@ -28,7 +28,8 @@ get_repo_base() { ) 2>/dev/null } -if [ -n "$GIT_SSL_NO_VERIFY" ]; then +if [ -n "$GIT_SSL_NO_VERIFY" -o \ + "`git config --bool http.sslVerify`" = false ]; then curl_extra_args="-k" fi diff --git a/git-ls-remote.sh b/git-ls-remote.sh index d56cf92ebf..fec70bbf88 100755 --- a/git-ls-remote.sh +++ b/git-ls-remote.sh @@ -54,9 +54,10 @@ tmpdir=$tmp-d case "$peek_repo" in http://* | https://* | ftp://* ) - if [ -n "$GIT_SSL_NO_VERIFY" ]; then - curl_extra_args="-k" - fi + if [ -n "$GIT_SSL_NO_VERIFY" -o \ + "`git config --bool http.sslVerify`" = false ]; then + curl_extra_args="-k" + fi if [ -n "$GIT_CURL_FTP_NO_EPSV" -o \ "`git config --bool http.noEPSV`" = true ]; then curl_extra_args="${curl_extra_args} --disable-epsv" From 399f0a8eedeec209c2eb97be6285331087234644 Mon Sep 17 00:00:00 2001 From: Benoit Sigoure Date: Mon, 29 Oct 2007 08:00:33 +0100 Subject: [PATCH 0306/1490] Fix a small memory leak in builtin-add prune_directory and fill_directory allocated one byte per pathspec and never freed it. Signed-off-by: Benoit Sigoure Signed-off-by: Junio C Hamano --- builtin-add.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/builtin-add.c b/builtin-add.c index 3d8b8b4f89..373f87f9f2 100644 --- a/builtin-add.c +++ b/builtin-add.c @@ -44,6 +44,7 @@ static void prune_directory(struct dir_struct *dir, const char **pathspec, int p die("pathspec '%s' did not match any files", pathspec[i]); } + free(seen); } static void fill_directory(struct dir_struct *dir, const char **pathspec, @@ -140,6 +141,7 @@ static void refresh(int verbose, const char **pathspec) if (!seen[i]) die("pathspec '%s' did not match any files", pathspec[i]); } + free(seen); } static int git_add_config(const char *var, const char *value) From 3b27428b9d3d8dc1c3f00da0ab94a1c7555a9265 Mon Sep 17 00:00:00 2001 From: Benoit Sigoure Date: Mon, 29 Oct 2007 08:00:32 +0100 Subject: [PATCH 0307/1490] core-tutorial: Catch up with current Git No longer talk about Cogito since it's deprecated. Some scripts (such as git-reset or git-branch) have undergone builtinification so adjust the text to reflect this. Fix a typo in the description of git-show-branch (merges are indicated by a `-', not by a `.'). git-pull/git-push do not seem to use the dumb git-ssh-fetch/git-ssh-upload (the text was probably missing a word). Adjust a link that wasn't rendered properly because it was wrapped. Signed-off-by: Benoit Sigoure Signed-off-by: Junio C Hamano --- Documentation/core-tutorial.txt | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/Documentation/core-tutorial.txt b/Documentation/core-tutorial.txt index 6b2590d072..d8e78ac8f1 100644 --- a/Documentation/core-tutorial.txt +++ b/Documentation/core-tutorial.txt @@ -553,13 +553,8 @@ can explore on your own. [NOTE] Most likely, you are not directly using the core -git Plumbing commands, but using Porcelain like Cogito on top -of it. Cogito works a bit differently and you usually do not -have to run `git-update-index` yourself for changed files (you -do tell underlying git about additions and removals via -`cg-add` and `cg-rm` commands). Just before you make a commit -with `cg-commit`, Cogito figures out which files you modified, -and runs `git-update-index` on them for you. +git Plumbing commands, but using Porcelain such as `git-add`, `git-rm' +and `git-commit'. Tagging a version @@ -686,8 +681,8 @@ $ git reset and in fact a lot of the common git command combinations can be scripted with the `git xyz` interfaces. You can learn things by just looking -at what the various git scripts do. For example, `git reset` is the -above two lines implemented in `git-reset`, but some things like +at what the various git scripts do. For example, `git reset` used to be +the above two lines implemented in `git-reset`, but some things like `git status` and `git commit` are slightly more complex scripts around the basic git commands. @@ -805,8 +800,8 @@ you have, you can say $ git branch ------------ -which is nothing more than a simple script around `ls .git/refs/heads`. -There will be asterisk in front of the branch you are currently on. +which used to be nothing more than a simple script around `ls .git/refs/heads`. +There will be an asterisk in front of the branch you are currently on. Sometimes you may wish to create a new branch _without_ actually checking it out and switching to it. If so, just use the command @@ -952,7 +947,7 @@ the later output lines is used to show commits contained in the `master` branch, and the second column for the `mybranch` branch. Three commits are shown along with their log messages. All of them have non blank characters in the first column (`*` -shows an ordinary commit on the current branch, `.` is a merge commit), which +shows an ordinary commit on the current branch, `-` is a merge commit), which means they are now part of the `master` branch. Only the "Some work" commit has the plus `+` character in the second column, because `mybranch` has not been merged to incorporate these @@ -1086,7 +1081,7 @@ to help dumb transport downloaders. There are (confusingly enough) `git-ssh-fetch` and `git-ssh-upload` programs, which are 'commit walkers'; they outlived their usefulness when git Native and SSH transports were introduced, -and not used by `git pull` or `git push` scripts. +and are not used by `git pull` or `git push` scripts. Once you fetch from the remote repository, you `merge` that with your current branch. @@ -1193,7 +1188,7 @@ $ mb=$(git-merge-base HEAD mybranch) The command writes the commit object name of the common ancestor to the standard output, so we captured its output to a variable, -because we will be using it in the next step. BTW, the common +because we will be using it in the next step. By the way, the common ancestor commit is the "New day." commit in this case. You can tell it by: @@ -1459,8 +1454,7 @@ Although git is a truly distributed system, it is often convenient to organize your project with an informal hierarchy of developers. Linux kernel development is run this way. There is a nice illustration (page 17, "Merges to Mainline") in -link:http://www.xenotime.net/linux/mentor/linux-mentoring-2006.pdf -[Randy Dunlap's presentation]. +link:http://www.xenotime.net/linux/mentor/linux-mentoring-2006.pdf[Randy Dunlap's presentation]. It should be stressed that this hierarchy is purely *informal*. There is nothing fundamental in git that enforces the "chain of From 7109c889f11b39a2c5a5122e3726be7ffce09faf Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 29 Oct 2007 11:53:55 -0700 Subject: [PATCH 0308/1490] sha1_file.c: avoid gcc signed overflow warnings With the recent gcc, we get: sha1_file.c: In check_packed_git_: sha1_file.c:527: warning: assuming signed overflow does not occur when assuming that (X + c) < X is always false sha1_file.c:527: warning: assuming signed overflow does not occur when assuming that (X + c) < X is always false for a piece of code that tries to make sure that off_t is large enough to hold more than 2^32 offset. The test tried to make sure these do not wrap-around: /* make sure we can deal with large pack offsets */ off_t x = 0x7fffffffUL, y = 0xffffffffUL; if (x > (x + 1) || y > (y + 1)) { but gcc assumes it can do whatever optimization it wants for a signed overflow (undefined behaviour) and warns about this construct. Follow Linus's suggestion to check sizeof(off_t) instead to work around the problem. Signed-off-by: Junio C Hamano --- sha1_file.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/sha1_file.c b/sha1_file.c index 9978a58da6..95b5a403d8 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -521,13 +521,15 @@ static int check_packed_git_idx(const char *path, struct packed_git *p) munmap(idx_map, idx_size); return error("wrong index v2 file size in %s", path); } - if (idx_size != min_size) { - /* make sure we can deal with large pack offsets */ - off_t x = 0x7fffffffUL, y = 0xffffffffUL; - if (x > (x + 1) || y > (y + 1)) { - munmap(idx_map, idx_size); - return error("pack too large for current definition of off_t in %s", path); - } + if (idx_size != min_size && + /* + * make sure we can deal with large pack offsets. + * 31-bit signed offset won't be enough, neither + * 32-bit unsigned one will be. + */ + (sizeof(off_t) <= 4)) { + munmap(idx_map, idx_size); + return error("pack too large for current definition of off_t in %s", path); } } From f120ae2a8e8cbe1bcbb2b55ebcd2e1eeb9f03ea2 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 29 Oct 2007 12:00:55 -0700 Subject: [PATCH 0309/1490] merge-recursive.c: mrtree in merge() is not used before set The called function merge_trees() sets its *result, to which the address of the variable mrtree in merge() function is passed, only when index_only is set. But that is Ok as the function uses the value in the variable only under index_only iteration. However, recent gcc does not realize this. Work it around by adding a fake initializer. Signed-off-by: Junio C Hamano --- merge-recursive.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/merge-recursive.c b/merge-recursive.c index 19d5f3b287..c2e1cb69e3 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -1586,7 +1586,7 @@ static int merge(struct commit *h1, { struct commit_list *iter; struct commit *merged_common_ancestors; - struct tree *mrtree; + struct tree *mrtree = mrtree; int clean; if (show(4)) { From e720c4382f6c9317a3b495e80c7dfc609a0db5e6 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 29 Oct 2007 12:02:59 -0700 Subject: [PATCH 0310/1490] RelNotes-1.5.3.5: describe recent fixes Signed-off-by: Junio C Hamano --- Documentation/RelNotes-1.5.3.5.txt | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Documentation/RelNotes-1.5.3.5.txt b/Documentation/RelNotes-1.5.3.5.txt index 9581e03c49..e28d92f618 100644 --- a/Documentation/RelNotes-1.5.3.5.txt +++ b/Documentation/RelNotes-1.5.3.5.txt @@ -71,3 +71,24 @@ Fixes since v1.5.3.4 * "make clean" no longer deletes the configure script that ships with the git tarball, making multiple architecture builds easier. + + * "git-remote show origin" spewed a warning message from Perl + when no remote is defined for the current branch via + branch..remote configuration settings. + + * Building with NO_PERL_MAKEMAKER excessively rebuilt contents + of perl/ subdirectory by rewriting perl.mak. + + * http.sslVerify configuration settings were not used in scripted + Porcelains. + + * "git-add" leaked a bit of memory while scanning for files to add. + + * A few workarounds to squelch false warnings from recent gcc have + been added. + +-- +exec >/var/tmp/1 +O=v1.5.3.4-55-gf120ae2 +echo O=`git describe refs/heads/maint` +git shortlog --no-merges $O..refs/heads/maint From 8371d8fd094548c1d02b8583fdbff8204a725ffc Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Sat, 27 Oct 2007 11:53:29 -0500 Subject: [PATCH 0311/1490] Remove outdated references to cogito in documentation Signed-off-by: Dan McGee Signed-off-by: Junio C Hamano --- Documentation/git-tools.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Documentation/git-tools.txt b/Documentation/git-tools.txt index 10653ff898..a96403cb8c 100644 --- a/Documentation/git-tools.txt +++ b/Documentation/git-tools.txt @@ -22,6 +22,9 @@ Alternative/Augmentative Porcelains providing generally smoother user experience than the "raw" Core GIT itself and indeed many other version control systems. + Cogito is no longer maintained as most of its functionality + is now in core GIT. + - *pg* (http://www.spearce.org/category/projects/scm/pg/) @@ -33,7 +36,7 @@ Alternative/Augmentative Porcelains - *StGit* (http://www.procode.org/stgit/) Stacked GIT provides a quilt-like patch management functionality in the - GIT environment. You can easily manage your patches in the scope of GIT + GIT environment. You can easily manage your patches in the scope of GIT until they get merged upstream. From 6ca8b977e4f678050db8fcb0eec2091dd44a2bd0 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Mon, 29 Oct 2007 05:31:52 +0100 Subject: [PATCH 0312/1490] Bisect: add "skip" to the short usage string. Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- git-bisect.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/git-bisect.sh b/git-bisect.sh index 180c6c280c..b74f44df60 100755 --- a/git-bisect.sh +++ b/git-bisect.sh @@ -1,12 +1,14 @@ #!/bin/sh -USAGE='[start|bad|good|next|reset|visualize|replay|log|run]' +USAGE='[start|bad|good|skip|next|reset|visualize|replay|log|run]' LONG_USAGE='git bisect start [ [...]] [--] [...] reset bisect state and start bisection. git bisect bad [] mark a known-bad revision. git bisect good [...] mark ... known-good revisions. +git bisect skip [...] + mark ... untestable revisions. git bisect next find next bisection to test and check it out. git bisect reset [] @@ -17,8 +19,6 @@ git bisect replay replay bisection log. git bisect log show bisect log. -git bisect skip [...] - mark ... untestable revisions. git bisect run ... use ... to automatically bisect.' From 5072a32382fb65fa7295811575d0f5c09cbe0dc3 Mon Sep 17 00:00:00 2001 From: Lars Hjemli Date: Mon, 29 Oct 2007 09:41:18 +0100 Subject: [PATCH 0313/1490] Teach git-pull about --[no-]ff, --no-squash and --commit These options are supported by git-merge, but git-pull didn't know about them. Signed-off-by: Lars Hjemli Signed-off-by: Junio C Hamano --- git-pull.sh | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/git-pull.sh b/git-pull.sh index 74bfc16744..75ec011969 100755 --- a/git-pull.sh +++ b/git-pull.sh @@ -4,7 +4,7 @@ # # Fetch one or more remote refs and merge it/them into the current HEAD. -USAGE='[-n | --no-summary] [--no-commit] [-s strategy]... [] ...' +USAGE='[-n | --no-summary] [--[no-]commit] [--[no-]squash] [--[no-]ff] [-s strategy]... [] ...' LONG_USAGE='Fetch one or more remote refs and merge it/them into the current HEAD.' SUBDIRECTORY_OK=Yes . git-sh-setup @@ -15,7 +15,7 @@ cd_to_toplevel test -z "$(git ls-files -u)" || die "You are in the middle of a conflicted merge." -strategy_args= no_summary= no_commit= squash= +strategy_args= no_summary= no_commit= squash= no_ff= while : do case "$1" in @@ -27,8 +27,16 @@ do ;; --no-c|--no-co|--no-com|--no-comm|--no-commi|--no-commit) no_commit=--no-commit ;; + --c|--co|--com|--comm|--commi|--commit) + no_commit=--commit ;; --sq|--squ|--squa|--squas|--squash) squash=--squash ;; + --no-sq|--no-squ|--no-squa|--no-squas|--no-squash) + squash=--no-squash ;; + --ff) + no_ff=--ff ;; + --no-ff) + no_ff=--no-ff ;; -s=*|--s=*|--st=*|--str=*|--stra=*|--strat=*|--strate=*|\ --strateg=*|--strategy=*|\ -s|--s|--st|--str|--stra|--strat|--strate|--strateg|--strategy) @@ -133,5 +141,5 @@ then fi merge_name=$(git fmt-merge-msg <"$GIT_DIR/FETCH_HEAD") || exit -exec git-merge $no_summary $no_commit $squash $strategy_args \ +exec git-merge $no_summary $no_commit $squash $no_ff $strategy_args \ "$merge_name" HEAD $merge_head From 79f3368d9a1bba022f38806b67c25ffffc0e7e92 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 29 Oct 2007 13:09:01 -0700 Subject: [PATCH 0314/1490] RelNotes-1.5.4: describe recent updates Signed-off-by: Junio C Hamano --- .mailmap | 1 + Documentation/RelNotes-1.5.4.txt | 28 ++++++++++++++++++++++++++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/.mailmap b/.mailmap index 5529b198e8..3b2ce578a1 100644 --- a/.mailmap +++ b/.mailmap @@ -37,6 +37,7 @@ Sam Vilain Santi Béjar Sean Estabrooks Shawn O. Pearce +Steven Grimm Theodore Ts'o Tony Luck Uwe Kleine-König diff --git a/Documentation/RelNotes-1.5.4.txt b/Documentation/RelNotes-1.5.4.txt index ceee857232..133fa64d22 100644 --- a/Documentation/RelNotes-1.5.4.txt +++ b/Documentation/RelNotes-1.5.4.txt @@ -4,6 +4,8 @@ GIT v1.5.4 Release Notes Updates since v1.5.3 -------------------- + * Comes with much improved gitk. + * git-reset is now built-in. * git-send-email can optionally talk over ssmtp and use SMTP-AUTH. @@ -19,6 +21,29 @@ Updates since v1.5.3 * git-archive can optionally substitute keywords in files marked with export-subst attribute. + * git-for-each-ref learned %(xxxdate:) syntax to + show the various date fields in different formats. + + * git-gc --auto is a low-impact way to automatically run a + variant of git-repack that does not lose unreferenced objects + (read: safer than the usual one) after the user accumulates + too many loose objects. + + * git-push has been rewritten in C. + + * git-push learned --dry-run option to show what would happen + if a push is run. + + * git-remote learned "rm" subcommand. + + * git-rebase --interactive mode can now work on detached HEAD. + + * git-cvsserver can be run via git-shell. + + * git-am and git-rebase are far less verbose. + + * git-pull learned to pass --[no-]ff option to underlying git-merge. + * Various Perforce importer updates. Fixes since v1.5.3 @@ -29,7 +54,6 @@ this release, unless otherwise noted. -- exec >/var/tmp/1 -O=v1.5.3.2-99-ge4b2890 +O=v1.5.3.4-450-g952a9e5 echo O=`git describe refs/heads/master` git shortlog --no-merges $O..refs/heads/master ^refs/heads/maint - From 68492fc73b7387fa72d09545f5743728c5fdb419 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Sun, 28 Oct 2007 21:27:13 +0100 Subject: [PATCH 0315/1490] Speedup scanning for excluded files. Try to avoid a lot of work scanning for excluded files, by caching some more information when setting up the exclusion data structure. Speeds up 'git runstatus' on a repository containing the Qt sources by 30% and reduces the amount of instructions executed (as measured by valgrind) by a factor of 2. Signed-off-by: Junio C Hamano --- dir.c | 59 +++++++++++++++++++++++++++++++++++++++++++---------------- dir.h | 7 +++++++ 2 files changed, 50 insertions(+), 16 deletions(-) diff --git a/dir.c b/dir.c index 4c17d3643e..5bcc764c97 100644 --- a/dir.c +++ b/dir.c @@ -118,14 +118,32 @@ int match_pathspec(const char **pathspec, const char *name, int namelen, int pre return retval; } +static int no_wildcard(const char *string) +{ + return string[strcspn(string, "*?[{")] == '\0'; +} + void add_exclude(const char *string, const char *base, int baselen, struct exclude_list *which) { struct exclude *x = xmalloc(sizeof (*x)); + x->to_exclude = 1; + if (*string == '!') { + x->to_exclude = 0; + string++; + } x->pattern = string; + x->patternlen = strlen(string); x->base = base; x->baselen = baselen; + x->flags = 0; + if (!strchr(string, '/')) + x->flags |= EXC_FLAG_NODIR; + if (no_wildcard(string)) + x->flags |= EXC_FLAG_NOWILDCARD; + if (*string == '*' && no_wildcard(string+1)) + x->flags |= EXC_FLAG_ENDSWITH; if (which->nr == which->alloc) { which->alloc = alloc_nr(which->alloc); which->excludes = xrealloc(which->excludes, @@ -209,7 +227,7 @@ void pop_exclude_per_directory(struct dir_struct *dir, int stk) * Return 1 for exclude, 0 for include and -1 for undecided. */ static int excluded_1(const char *pathname, - int pathlen, + int pathlen, const char *basename, struct exclude_list *el) { int i; @@ -218,19 +236,21 @@ static int excluded_1(const char *pathname, for (i = el->nr - 1; 0 <= i; i--) { struct exclude *x = el->excludes[i]; const char *exclude = x->pattern; - int to_exclude = 1; + int to_exclude = x->to_exclude; - if (*exclude == '!') { - to_exclude = 0; - exclude++; - } - - if (!strchr(exclude, '/')) { + if (x->flags & EXC_FLAG_NODIR) { /* match basename */ - const char *basename = strrchr(pathname, '/'); - basename = (basename) ? basename+1 : pathname; - if (fnmatch(exclude, basename, 0) == 0) - return to_exclude; + if (x->flags & EXC_FLAG_NOWILDCARD) { + if (!strcmp(exclude, basename)) + return to_exclude; + } else if (x->flags & EXC_FLAG_ENDSWITH) { + if (x->patternlen - 1 <= pathlen && + !strcmp(exclude + 1, pathname + pathlen - x->patternlen + 1)) + return to_exclude; + } else { + if (fnmatch(exclude, basename, 0) == 0) + return to_exclude; + } } else { /* match with FNM_PATHNAME: @@ -246,9 +266,14 @@ static int excluded_1(const char *pathname, strncmp(pathname, x->base, baselen)) continue; - if (fnmatch(exclude, pathname+baselen, - FNM_PATHNAME) == 0) - return to_exclude; + if (x->flags & EXC_FLAG_NOWILDCARD) { + if (!strcmp(exclude, pathname + baselen)) + return to_exclude; + } else { + if (fnmatch(exclude, pathname+baselen, + FNM_PATHNAME) == 0) + return to_exclude; + } } } } @@ -259,9 +284,11 @@ int excluded(struct dir_struct *dir, const char *pathname) { int pathlen = strlen(pathname); int st; + const char *basename = strrchr(pathname, '/'); + basename = (basename) ? basename+1 : pathname; for (st = EXC_CMDL; st <= EXC_FILE; st++) { - switch (excluded_1(pathname, pathlen, &dir->exclude_list[st])) { + switch (excluded_1(pathname, pathlen, basename, &dir->exclude_list[st])) { case 0: return 0; case 1: diff --git a/dir.h b/dir.h index a248a23ac4..aaa247b256 100644 --- a/dir.h +++ b/dir.h @@ -17,13 +17,20 @@ struct dir_entry { char name[FLEX_ARRAY]; /* more */ }; +#define EXC_FLAG_NODIR 1 +#define EXC_FLAG_NOWILDCARD 2 +#define EXC_FLAG_ENDSWITH 4 + struct exclude_list { int nr; int alloc; struct exclude { const char *pattern; + int patternlen; const char *base; int baselen; + int to_exclude; + int flags; } **excludes; }; From 09149c7809a37a52b38d8d7a0621e2fb8943d8fe Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Mon, 29 Oct 2007 22:35:08 -0400 Subject: [PATCH 0316/1490] Correct handling of upload-pack in builtin-fetch-pack The field in the args was being ignored in favor of a static constant Signed-off-by: Daniel Barkalow Thanked-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- builtin-fetch-pack.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/builtin-fetch-pack.c b/builtin-fetch-pack.c index 8f25d509a0..8753840a82 100644 --- a/builtin-fetch-pack.c +++ b/builtin-fetch-pack.c @@ -11,11 +11,12 @@ static int transfer_unpack_limit = -1; static int fetch_unpack_limit = -1; static int unpack_limit = 100; -static struct fetch_pack_args args; +static struct fetch_pack_args args = { + /* .uploadpack = */ "git-upload-pack", +}; static const char fetch_pack_usage[] = "git-fetch-pack [--all] [--quiet|-q] [--keep|-k] [--thin] [--upload-pack=] [--depth=] [--no-progress] [-v] [:] [...]"; -static const char *uploadpack = "git-upload-pack"; #define COMPLETE (1U << 0) #define COMMON (1U << 1) @@ -773,7 +774,7 @@ struct ref *fetch_pack(struct fetch_pack_args *my_args, st.st_mtime = 0; } - pid = git_connect(fd, (char *)dest, uploadpack, + pid = git_connect(fd, (char *)dest, args.uploadpack, args.verbose ? CONNECT_VERBOSE : 0); if (pid < 0) return NULL; From 3d7e2d857a570b1d6368285f95b67994fc95629e Mon Sep 17 00:00:00 2001 From: Scott R Parish Date: Sat, 27 Oct 2007 01:36:49 -0700 Subject: [PATCH 0317/1490] "git" returns 1; "git help" and "git help -a" return 0 Signed-off-by: Scott R Parish Signed-off-by: Junio C Hamano --- builtin.h | 1 + git.c | 7 ++++--- help.c | 6 +++--- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/builtin.h b/builtin.h index 65cc0fb34a..9a6213af12 100644 --- a/builtin.h +++ b/builtin.h @@ -6,6 +6,7 @@ extern const char git_version_string[]; extern const char git_usage_string[]; +extern void list_common_cmds_help(void); extern void help_unknown_cmd(const char *cmd); extern int write_tree(unsigned char *sha1, int missing_ok, const char *prefix); extern void prune_packed_objects(int); diff --git a/git.c b/git.c index 23a430c369..efed91c4f4 100644 --- a/git.c +++ b/git.c @@ -450,9 +450,10 @@ int main(int argc, const char **argv) if (!prefixcmp(argv[0], "--")) argv[0] += 2; } else { - /* Default command: "help" */ - argv[0] = "help"; - argc = 1; + /* The user didn't specify a command; give them help */ + printf("usage: %s\n\n", git_usage_string); + list_common_cmds_help(); + exit(1); } cmd = argv[0]; diff --git a/help.c b/help.c index e5662d9014..daefa75ea0 100644 --- a/help.c +++ b/help.c @@ -147,7 +147,7 @@ static void list_commands(const char *exec_path, const char *pattern) putchar('\n'); } -static void list_common_cmds_help(void) +void list_common_cmds_help(void) { int i, longest = 0; @@ -203,14 +203,14 @@ int cmd_help(int argc, const char **argv, const char *prefix) if (!help_cmd) { printf("usage: %s\n\n", git_usage_string); list_common_cmds_help(); - exit(1); + exit(0); } else if (!strcmp(help_cmd, "--all") || !strcmp(help_cmd, "-a")) { printf("usage: %s\n\n", git_usage_string); if(exec_path) list_commands(exec_path, "git-*"); - exit(1); + exit(0); } else From edb6ddc53e71f4f959665cbc3180bb21b7ee7634 Mon Sep 17 00:00:00 2001 From: Scott R Parish Date: Sat, 27 Oct 2007 01:36:50 -0700 Subject: [PATCH 0318/1490] remove unused/unneeded "pattern" argument of list_commands list_commands() currently accepts and ignores a "pattern" argument, and then hard codes a prefix as well as some magic numbers. This hardcodes the prefix inside of the function and removes the magic numbers. Signed-off-by: Scott R Parish Signed-off-by: Junio C Hamano --- help.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/help.c b/help.c index daefa75ea0..3d08973c9d 100644 --- a/help.c +++ b/help.c @@ -93,10 +93,12 @@ static void pretty_print_string_list(struct cmdname **cmdname, int longest) } } -static void list_commands(const char *exec_path, const char *pattern) +static void list_commands(const char *exec_path) { unsigned int longest = 0; char path[PATH_MAX]; + const char *prefix = "git-"; + int prefix_len = strlen(prefix); int dirlen; DIR *dir = opendir(exec_path); struct dirent *de; @@ -120,7 +122,7 @@ static void list_commands(const char *exec_path, const char *pattern) struct stat st; int entlen; - if (prefixcmp(de->d_name, "git-")) + if (prefixcmp(de->d_name, prefix)) continue; strcpy(path+dirlen, de->d_name); if (stat(path, &st) || /* stat, not lstat */ @@ -128,14 +130,14 @@ static void list_commands(const char *exec_path, const char *pattern) !(st.st_mode & S_IXUSR)) continue; - entlen = strlen(de->d_name); + entlen = strlen(de->d_name) - prefix_len; if (has_extension(de->d_name, ".exe")) entlen -= 4; if (longest < entlen) longest = entlen; - add_cmdname(de->d_name + 4, entlen-4); + add_cmdname(de->d_name + prefix_len, entlen); } closedir(dir); @@ -143,7 +145,7 @@ static void list_commands(const char *exec_path, const char *pattern) printf("----------------------------"); mput_char('-', strlen(exec_path)); putchar('\n'); - pretty_print_string_list(cmdname, longest - 4); + pretty_print_string_list(cmdname, longest); putchar('\n'); } @@ -209,7 +211,7 @@ int cmd_help(int argc, const char **argv, const char *prefix) else if (!strcmp(help_cmd, "--all") || !strcmp(help_cmd, "-a")) { printf("usage: %s\n\n", git_usage_string); if(exec_path) - list_commands(exec_path, "git-*"); + list_commands(exec_path); exit(0); } From 384df83312d24ea4d11adcf4e73921fc192595d2 Mon Sep 17 00:00:00 2001 From: Scott R Parish Date: Sat, 27 Oct 2007 01:36:51 -0700 Subject: [PATCH 0319/1490] "current_exec_path" is a misleading name, use "argv_exec_path" Signed-off-by: Scott R Parish Signed-off-by: Junio C Hamano --- exec_cmd.c | 12 ++++++------ exec_cmd.h | 2 +- git.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/exec_cmd.c b/exec_cmd.c index 9b74ed2f42..33b17a6b45 100644 --- a/exec_cmd.c +++ b/exec_cmd.c @@ -5,11 +5,11 @@ extern char **environ; static const char *builtin_exec_path = GIT_EXEC_PATH; -static const char *current_exec_path; +static const char *argv_exec_path; -void git_set_exec_path(const char *exec_path) +void git_set_argv_exec_path(const char *exec_path) { - current_exec_path = exec_path; + argv_exec_path = exec_path; } @@ -18,8 +18,8 @@ const char *git_exec_path(void) { const char *env; - if (current_exec_path) - return current_exec_path; + if (argv_exec_path) + return argv_exec_path; env = getenv(EXEC_PATH_ENVIRONMENT); if (env && *env) { @@ -34,7 +34,7 @@ int execv_git_cmd(const char **argv) { char git_command[PATH_MAX + 1]; int i; - const char *paths[] = { current_exec_path, + const char *paths[] = { argv_exec_path, getenv(EXEC_PATH_ENVIRONMENT), builtin_exec_path }; diff --git a/exec_cmd.h b/exec_cmd.h index 849a8395a0..da99287552 100644 --- a/exec_cmd.h +++ b/exec_cmd.h @@ -1,7 +1,7 @@ #ifndef GIT_EXEC_CMD_H #define GIT_EXEC_CMD_H -extern void git_set_exec_path(const char *exec_path); +extern void git_set_argv_exec_path(const char *exec_path); extern const char* git_exec_path(void); extern int execv_git_cmd(const char **argv); /* NULL terminated */ extern int execl_git_cmd(const char *cmd, ...); diff --git a/git.c b/git.c index efed91c4f4..c7cabf5f34 100644 --- a/git.c +++ b/git.c @@ -51,7 +51,7 @@ static int handle_options(const char*** argv, int* argc, int* envchanged) if (!prefixcmp(cmd, "--exec-path")) { cmd += 11; if (*cmd == '=') - git_set_exec_path(cmd + 1); + git_set_argv_exec_path(cmd + 1); else { puts(git_exec_path()); exit(0); From 0966003c8e8d1528912b10667b903cd981e3a7f6 Mon Sep 17 00:00:00 2001 From: Scott R Parish Date: Sat, 27 Oct 2007 01:36:52 -0700 Subject: [PATCH 0320/1490] list_commands(): simplify code by using chdir() The current code builds absolute path strings for each file to stat(), this can easily be avoided by chdir()ing into the directory. Signed-off-by: Scott R Parish Signed-off-by: Junio C Hamano --- help.c | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/help.c b/help.c index 3d08973c9d..34ac5db601 100644 --- a/help.c +++ b/help.c @@ -96,36 +96,24 @@ static void pretty_print_string_list(struct cmdname **cmdname, int longest) static void list_commands(const char *exec_path) { unsigned int longest = 0; - char path[PATH_MAX]; const char *prefix = "git-"; int prefix_len = strlen(prefix); - int dirlen; DIR *dir = opendir(exec_path); struct dirent *de; - if (!dir) { + if (!dir || chdir(exec_path)) { fprintf(stderr, "git: '%s': %s\n", exec_path, strerror(errno)); exit(1); } - dirlen = strlen(exec_path); - if (PATH_MAX - 20 < dirlen) { - fprintf(stderr, "git: insanely long exec-path '%s'\n", - exec_path); - exit(1); - } - - memcpy(path, exec_path, dirlen); - path[dirlen++] = '/'; - while ((de = readdir(dir)) != NULL) { struct stat st; int entlen; if (prefixcmp(de->d_name, prefix)) continue; - strcpy(path+dirlen, de->d_name); - if (stat(path, &st) || /* stat, not lstat */ + + if (stat(de->d_name, &st) || /* stat, not lstat */ !S_ISREG(st.st_mode) || !(st.st_mode & S_IXUSR)) continue; From 511707d42b3b3e57d9623493092590546ffeae80 Mon Sep 17 00:00:00 2001 From: Scott R Parish Date: Sun, 28 Oct 2007 04:17:20 -0700 Subject: [PATCH 0321/1490] use only the $PATH for exec'ing git commands We need to correctly set up $PATH for non-c based git commands. Since we already do this, we can just use that $PATH and execvp, instead of looping over the paths with execve. This patch adds a setup_path() function to exec_cmd.c, which sets the $PATH order correctly for our search order. execv_git_cmd() is stripped down to setting up argv and calling execvp(). git.c's main() only only needs to call setup_path(). Signed-off-by: Scott R Parish Signed-off-by: Junio C Hamano --- exec_cmd.c | 118 +++++++++++++++++++++++------------------------------ exec_cmd.h | 1 + git.c | 43 ++++--------------- 3 files changed, 59 insertions(+), 103 deletions(-) diff --git a/exec_cmd.c b/exec_cmd.c index 33b17a6b45..2d0a758512 100644 --- a/exec_cmd.c +++ b/exec_cmd.c @@ -29,85 +29,69 @@ const char *git_exec_path(void) return builtin_exec_path; } +static void add_path(struct strbuf *out, const char *path) +{ + if (path && *path) { + if (is_absolute_path(path)) + strbuf_addstr(out, path); + else + strbuf_addstr(out, make_absolute_path(path)); + + strbuf_addch(out, ':'); + } +} + +void setup_path(const char *cmd_path) +{ + const char *old_path = getenv("PATH"); + struct strbuf new_path; + + strbuf_init(&new_path, 0); + + add_path(&new_path, argv_exec_path); + add_path(&new_path, getenv(EXEC_PATH_ENVIRONMENT)); + add_path(&new_path, builtin_exec_path); + add_path(&new_path, cmd_path); + + if (old_path) + strbuf_addstr(&new_path, old_path); + else + strbuf_addstr(&new_path, "/usr/local/bin:/usr/bin:/bin"); + + setenv("PATH", new_path.buf, 1); + + strbuf_release(&new_path); +} int execv_git_cmd(const char **argv) { - char git_command[PATH_MAX + 1]; - int i; - const char *paths[] = { argv_exec_path, - getenv(EXEC_PATH_ENVIRONMENT), - builtin_exec_path }; + struct strbuf cmd; + const char *tmp; - for (i = 0; i < ARRAY_SIZE(paths); ++i) { - size_t len; - int rc; - const char *exec_dir = paths[i]; - const char *tmp; + strbuf_init(&cmd, 0); + strbuf_addf(&cmd, "git-%s", argv[0]); - if (!exec_dir || !*exec_dir) continue; + /* + * argv[0] must be the git command, but the argv array + * belongs to the caller, and may be reused in + * subsequent loop iterations. Save argv[0] and + * restore it on error. + */ + tmp = argv[0]; + argv[0] = cmd.buf; - if (*exec_dir != '/') { - if (!getcwd(git_command, sizeof(git_command))) { - fprintf(stderr, "git: cannot determine " - "current directory: %s\n", - strerror(errno)); - break; - } - len = strlen(git_command); + trace_argv_printf(argv, -1, "trace: exec:"); - /* Trivial cleanup */ - while (!prefixcmp(exec_dir, "./")) { - exec_dir += 2; - while (*exec_dir == '/') - exec_dir++; - } + /* execvp() can only ever return if it fails */ + execvp(cmd.buf, (char **)argv); - rc = snprintf(git_command + len, - sizeof(git_command) - len, "/%s", - exec_dir); - if (rc < 0 || rc >= sizeof(git_command) - len) { - fprintf(stderr, "git: command name given " - "is too long.\n"); - break; - } - } else { - if (strlen(exec_dir) + 1 > sizeof(git_command)) { - fprintf(stderr, "git: command name given " - "is too long.\n"); - break; - } - strcpy(git_command, exec_dir); - } + trace_printf("trace: exec failed: %s\n", strerror(errno)); - len = strlen(git_command); - rc = snprintf(git_command + len, sizeof(git_command) - len, - "/git-%s", argv[0]); - if (rc < 0 || rc >= sizeof(git_command) - len) { - fprintf(stderr, - "git: command name given is too long.\n"); - break; - } + argv[0] = tmp; - /* argv[0] must be the git command, but the argv array - * belongs to the caller, and my be reused in - * subsequent loop iterations. Save argv[0] and - * restore it on error. - */ + strbuf_release(&cmd); - tmp = argv[0]; - argv[0] = git_command; - - trace_argv_printf(argv, -1, "trace: exec:"); - - /* execve() can only ever return if it fails */ - execve(git_command, (char **)argv, environ); - - trace_printf("trace: exec failed: %s\n", strerror(errno)); - - argv[0] = tmp; - } return -1; - } diff --git a/exec_cmd.h b/exec_cmd.h index da99287552..a892355c82 100644 --- a/exec_cmd.h +++ b/exec_cmd.h @@ -3,6 +3,7 @@ extern void git_set_argv_exec_path(const char *exec_path); extern const char* git_exec_path(void); +extern void setup_path(const char *); extern int execv_git_cmd(const char **argv); /* NULL terminated */ extern int execl_git_cmd(const char *cmd, ...); diff --git a/git.c b/git.c index c7cabf5f34..4e10581101 100644 --- a/git.c +++ b/git.c @@ -6,28 +6,6 @@ const char git_usage_string[] = "git [--version] [--exec-path[=GIT_EXEC_PATH]] [-p|--paginate|--no-pager] [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE] [--help] COMMAND [ARGS]"; -static void prepend_to_path(const char *dir, int len) -{ - const char *old_path = getenv("PATH"); - char *path; - int path_len = len; - - if (!old_path) - old_path = "/usr/local/bin:/usr/bin:/bin"; - - path_len = len + strlen(old_path) + 1; - - path = xmalloc(path_len + 1); - - memcpy(path, dir, len); - path[len] = ':'; - memcpy(path + len + 1, old_path, path_len - len); - - setenv("PATH", path, 1); - - free(path); -} - static int handle_options(const char*** argv, int* argc, int* envchanged) { int handled = 0; @@ -408,7 +386,7 @@ int main(int argc, const char **argv) { const char *cmd = argv[0] ? argv[0] : "git-help"; char *slash = strrchr(cmd, '/'); - const char *exec_path = NULL; + const char *cmd_path = NULL; int done_alias = 0; /* @@ -418,10 +396,7 @@ int main(int argc, const char **argv) */ if (slash) { *slash++ = 0; - if (*cmd == '/') - exec_path = cmd; - else - exec_path = xstrdup(make_absolute_path(cmd)); + cmd_path = cmd; cmd = slash; } @@ -458,16 +433,12 @@ int main(int argc, const char **argv) cmd = argv[0]; /* - * We execute external git command via execv_git_cmd(), - * which looks at "--exec-path" option, GIT_EXEC_PATH - * environment, and $(gitexecdir) in Makefile while built, - * in this order. For scripted commands, we prepend - * the value of the exec_path variable to the PATH. + * We use PATH to find git commands, but we prepend some higher + * precidence paths: the "--exec-path" option, the GIT_EXEC_PATH + * environment, and the $(gitexecdir) from the Makefile at build + * time. */ - if (exec_path) - prepend_to_path(exec_path, strlen(exec_path)); - exec_path = git_exec_path(); - prepend_to_path(exec_path, strlen(exec_path)); + setup_path(cmd_path); while (1) { /* See if it's an internal command */ From 1eb056905a2956ca9fabd2edcce05c0a29ce64b1 Mon Sep 17 00:00:00 2001 From: Scott R Parish Date: Sun, 28 Oct 2007 20:30:52 -0700 Subject: [PATCH 0322/1490] include $PATH in generating list of commands for "help -a" Git had previously been using the $PATH for scripts--a previous patch moved exec'ed commands to also use the $PATH. For consistency "help -a" should also list commands in the $PATH. The main commands are still listed from the git_exec_path(), but the $PATH is walked and other git commands (probably extensions) are listed. Signed-off-by: Scott R Parish Signed-off-by: Junio C Hamano --- help.c | 155 +++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 119 insertions(+), 36 deletions(-) diff --git a/help.c b/help.c index 34ac5db601..855aeef92f 100644 --- a/help.c +++ b/help.c @@ -37,24 +37,25 @@ static inline void mput_char(char c, unsigned int num) putchar(c); } -static struct cmdname { - size_t len; - char name[1]; -} **cmdname; -static int cmdname_alloc, cmdname_cnt; +static struct cmdnames { + int alloc; + int cnt; + struct cmdname { + size_t len; + char name[1]; + } **names; +} main_cmds, other_cmds; -static void add_cmdname(const char *name, int len) +static void add_cmdname(struct cmdnames *cmds, const char *name, int len) { - struct cmdname *ent; - if (cmdname_alloc <= cmdname_cnt) { - cmdname_alloc = cmdname_alloc + 200; - cmdname = xrealloc(cmdname, cmdname_alloc * sizeof(*cmdname)); - } - ent = xmalloc(sizeof(*ent) + len); + struct cmdname *ent = xmalloc(sizeof(*ent) + len); + ent->len = len; memcpy(ent->name, name, len); ent->name[len] = 0; - cmdname[cmdname_cnt++] = ent; + + ALLOC_GROW(cmds->names, cmds->cnt + 1, cmds->alloc); + cmds->names[cmds->cnt++] = ent; } static int cmdname_compare(const void *a_, const void *b_) @@ -64,7 +65,42 @@ static int cmdname_compare(const void *a_, const void *b_) return strcmp(a->name, b->name); } -static void pretty_print_string_list(struct cmdname **cmdname, int longest) +static void uniq(struct cmdnames *cmds) +{ + int i, j; + + if (!cmds->cnt) + return; + + for (i = j = 1; i < cmds->cnt; i++) + if (strcmp(cmds->names[i]->name, cmds->names[i-1]->name)) + cmds->names[j++] = cmds->names[i]; + + cmds->cnt = j; +} + +static void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes) { + int ci, cj, ei; + int cmp; + + ci = cj = ei = 0; + while (ci < cmds->cnt && ei < excludes->cnt) { + cmp = strcmp(cmds->names[ci]->name, excludes->names[ei]->name); + if (cmp < 0) + cmds->names[cj++] = cmds->names[ci++]; + else if (cmp == 0) + ci++, ei++; + else if (cmp > 0) + ei++; + } + + while (ci < cmds->cnt) + cmds->names[cj++] = cmds->names[ci++]; + + cmds->cnt = cj; +} + +static void pretty_print_string_list(struct cmdnames *cmds, int longest) { int cols = 1, rows; int space = longest + 1; /* min 1 SP between words */ @@ -73,9 +109,7 @@ static void pretty_print_string_list(struct cmdname **cmdname, int longest) if (space < max_cols) cols = max_cols / space; - rows = (cmdname_cnt + cols - 1) / cols; - - qsort(cmdname, cmdname_cnt, sizeof(*cmdname), cmdname_compare); + rows = (cmds->cnt + cols - 1) / cols; for (i = 0; i < rows; i++) { printf(" "); @@ -83,28 +117,27 @@ static void pretty_print_string_list(struct cmdname **cmdname, int longest) for (j = 0; j < cols; j++) { int n = j * rows + i; int size = space; - if (n >= cmdname_cnt) + if (n >= cmds->cnt) break; - if (j == cols-1 || n + rows >= cmdname_cnt) + if (j == cols-1 || n + rows >= cmds->cnt) size = 1; - printf("%-*s", size, cmdname[n]->name); + printf("%-*s", size, cmds->names[n]->name); } putchar('\n'); } } -static void list_commands(const char *exec_path) +static unsigned int list_commands_in_dir(struct cmdnames *cmds, + const char *path) { unsigned int longest = 0; const char *prefix = "git-"; int prefix_len = strlen(prefix); - DIR *dir = opendir(exec_path); + DIR *dir = opendir(path); struct dirent *de; - if (!dir || chdir(exec_path)) { - fprintf(stderr, "git: '%s': %s\n", exec_path, strerror(errno)); - exit(1); - } + if (!dir || chdir(path)) + return 0; while ((de = readdir(dir)) != NULL) { struct stat st; @@ -125,16 +158,68 @@ static void list_commands(const char *exec_path) if (longest < entlen) longest = entlen; - add_cmdname(de->d_name + prefix_len, entlen); + add_cmdname(cmds, de->d_name + prefix_len, entlen); } closedir(dir); - printf("git commands available in '%s'\n", exec_path); - printf("----------------------------"); - mput_char('-', strlen(exec_path)); - putchar('\n'); - pretty_print_string_list(cmdname, longest); - putchar('\n'); + return longest; +} + +static void list_commands(void) +{ + unsigned int longest = 0; + unsigned int len; + const char *env_path = getenv("PATH"); + char *paths, *path, *colon; + const char *exec_path = git_exec_path(); + + if (exec_path) + longest = list_commands_in_dir(&main_cmds, exec_path); + + if (!env_path) { + fprintf(stderr, "PATH not set\n"); + exit(1); + } + + path = paths = xstrdup(env_path); + while (1) { + if ((colon = strchr(path, ':'))) + *colon = 0; + + len = list_commands_in_dir(&other_cmds, path); + if (len > longest) + longest = len; + + if (!colon) + break; + path = colon + 1; + } + free(paths); + + qsort(main_cmds.names, main_cmds.cnt, + sizeof(*main_cmds.names), cmdname_compare); + uniq(&main_cmds); + + qsort(other_cmds.names, other_cmds.cnt, + sizeof(*other_cmds.names), cmdname_compare); + uniq(&other_cmds); + exclude_cmds(&other_cmds, &main_cmds); + + if (main_cmds.cnt) { + printf("available git commands in '%s'\n", exec_path); + printf("----------------------------"); + mput_char('-', strlen(exec_path)); + putchar('\n'); + pretty_print_string_list(&main_cmds, longest); + putchar('\n'); + } + + if (other_cmds.cnt) { + printf("git commands available from elsewhere on your $PATH\n"); + printf("---------------------------------------------------\n"); + pretty_print_string_list(&other_cmds, longest); + putchar('\n'); + } } void list_common_cmds_help(void) @@ -188,7 +273,6 @@ int cmd_version(int argc, const char **argv, const char *prefix) int cmd_help(int argc, const char **argv, const char *prefix) { const char *help_cmd = argc > 1 ? argv[1] : NULL; - const char *exec_path = git_exec_path(); if (!help_cmd) { printf("usage: %s\n\n", git_usage_string); @@ -198,8 +282,7 @@ int cmd_help(int argc, const char **argv, const char *prefix) else if (!strcmp(help_cmd, "--all") || !strcmp(help_cmd, "-a")) { printf("usage: %s\n\n", git_usage_string); - if(exec_path) - list_commands(exec_path); + list_commands(); exit(0); } From e8f5d87056093f40a271f89c2c91d1a7025e2440 Mon Sep 17 00:00:00 2001 From: Scott R Parish Date: Sat, 27 Oct 2007 01:36:55 -0700 Subject: [PATCH 0323/1490] shell should call the new setup_path() to setup $PATH Shell currently does its own manual thing for setting up the $PATH; it can now call setup_path(). Signed-off-by: Scott R Parish Signed-off-by: Junio C Hamano --- shell.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/shell.c b/shell.c index cfe372b213..9826109d5b 100644 --- a/shell.c +++ b/shell.c @@ -24,17 +24,11 @@ static int do_cvs_cmd(const char *me, char *arg) const char *cvsserver_argv[3] = { "cvsserver", "server", NULL }; - const char *oldpath = getenv("PATH"); - struct strbuf newpath = STRBUF_INIT; if (!arg || strcmp(arg, "server")) die("git-cvsserver only handles server: %s", arg); - strbuf_addstr(&newpath, git_exec_path()); - strbuf_addch(&newpath, ':'); - strbuf_addstr(&newpath, oldpath); - - setenv("PATH", strbuf_detach(&newpath, NULL), 1); + setup_path(NULL); return execv_git_cmd(cvsserver_argv); } From 4a59fd131229968b08af9bdf221c341f54c52983 Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Mon, 15 Oct 2007 01:35:37 +0200 Subject: [PATCH 0324/1490] Add a simple option parser. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The option parser takes argc, argv, an array of struct option and a usage string. Each of the struct option elements in the array describes a valid option, its type and a pointer to the location where the value is written. The entry point is parse_options(), which scans through the given argv, and matches each option there against the list of valid options. During the scan, argv is rewritten to only contain the non-option command line arguments and the number of these is returned. Aggregation of single switches is allowed: -rC0 is the same as -r -C 0 (supposing that -C wants an arg). Every long option automatically support the option with the same name, prefixed with 'no-' to unset the switch. It assumes that initial value for strings are "NULL" and for integers is "0". Long options are supported either with '=' or without: --some-option=foo is the same as --some-option foo Acked-by: Kristian Høgsberg Signed-off-by: Pierre Habouzit Signed-off-by: Shawn O. Pearce --- Makefile | 4 +- parse-options.c | 167 ++++++++++++++++++++++++++++++++++++++++++++++++ parse-options.h | 35 ++++++++++ 3 files changed, 204 insertions(+), 2 deletions(-) create mode 100644 parse-options.c create mode 100644 parse-options.h diff --git a/Makefile b/Makefile index 72f5ef43ce..7e6e1d65f9 100644 --- a/Makefile +++ b/Makefile @@ -290,7 +290,7 @@ LIB_H = \ run-command.h strbuf.h tag.h tree.h git-compat-util.h revision.h \ tree-walk.h log-tree.h dir.h path-list.h unpack-trees.h builtin.h \ utf8.h reflog-walk.h patch-ids.h attr.h decorate.h progress.h \ - mailmap.h remote.h transport.h + mailmap.h remote.h parse-options.h transport.h DIFF_OBJS = \ diff.o diff-lib.o diffcore-break.o diffcore-order.o \ @@ -313,7 +313,7 @@ LIB_OBJS = \ alloc.o merge-file.o path-list.o help.o unpack-trees.o $(DIFF_OBJS) \ color.o wt-status.o archive-zip.o archive-tar.o shallow.o utf8.o \ convert.o attr.o decorate.o progress.o mailmap.o symlinks.o remote.o \ - transport.o bundle.o walker.o + transport.o bundle.o walker.o parse-options.o BUILTIN_OBJS = \ builtin-add.o \ diff --git a/parse-options.c b/parse-options.c new file mode 100644 index 0000000000..7bdffdbe51 --- /dev/null +++ b/parse-options.c @@ -0,0 +1,167 @@ +#include "git-compat-util.h" +#include "parse-options.h" +#include "strbuf.h" + +#define OPT_SHORT 1 +#define OPT_UNSET 2 + +struct optparse_t { + const char **argv; + int argc; + const char *opt; +}; + +static inline const char *get_arg(struct optparse_t *p) +{ + if (p->opt) { + const char *res = p->opt; + p->opt = NULL; + return res; + } + p->argc--; + return *++p->argv; +} + +static inline const char *skip_prefix(const char *str, const char *prefix) +{ + size_t len = strlen(prefix); + return strncmp(str, prefix, len) ? NULL : str + len; +} + +static int opterror(const struct option *opt, const char *reason, int flags) +{ + if (flags & OPT_SHORT) + return error("switch `%c' %s", opt->short_name, reason); + if (flags & OPT_UNSET) + return error("option `no-%s' %s", opt->long_name, reason); + return error("option `%s' %s", opt->long_name, reason); +} + +static int get_value(struct optparse_t *p, + const struct option *opt, int flags) +{ + const char *s; + + if (p->opt && (flags & OPT_UNSET)) + return opterror(opt, "takes no value", flags); + + switch (opt->type) { + case OPTION_BOOLEAN: + if (!(flags & OPT_SHORT) && p->opt) + return opterror(opt, "takes no value", flags); + if (flags & OPT_UNSET) + *(int *)opt->value = 0; + else + (*(int *)opt->value)++; + return 0; + + case OPTION_STRING: + if (flags & OPT_UNSET) { + *(const char **)opt->value = (const char *)NULL; + return 0; + } + if (!p->opt && p->argc <= 1) + return opterror(opt, "requires a value", flags); + *(const char **)opt->value = get_arg(p); + return 0; + + case OPTION_INTEGER: + if (flags & OPT_UNSET) { + *(int *)opt->value = 0; + return 0; + } + if (!p->opt && p->argc <= 1) + return opterror(opt, "requires a value", flags); + *(int *)opt->value = strtol(get_arg(p), (char **)&s, 10); + if (*s) + return opterror(opt, "expects a numerical value", flags); + return 0; + + default: + die("should not happen, someone must be hit on the forehead"); + } +} + +static int parse_short_opt(struct optparse_t *p, const struct option *options) +{ + for (; options->type != OPTION_END; options++) { + if (options->short_name == *p->opt) { + p->opt = p->opt[1] ? p->opt + 1 : NULL; + return get_value(p, options, OPT_SHORT); + } + } + return error("unknown switch `%c'", *p->opt); +} + +static int parse_long_opt(struct optparse_t *p, const char *arg, + const struct option *options) +{ + for (; options->type != OPTION_END; options++) { + const char *rest; + int flags = 0; + + if (!options->long_name) + continue; + + rest = skip_prefix(arg, options->long_name); + if (!rest) { + if (strncmp(arg, "no-", 3)) + continue; + flags |= OPT_UNSET; + rest = skip_prefix(arg + 3, options->long_name); + if (!rest) + continue; + } + if (*rest) { + if (*rest != '=') + continue; + p->opt = rest + 1; + } + return get_value(p, options, flags); + } + return error("unknown option `%s'", arg); +} + +int parse_options(int argc, const char **argv, const struct option *options, + const char *usagestr, int flags) +{ + struct optparse_t args = { argv + 1, argc - 1, NULL }; + int j = 0; + + for (; args.argc; args.argc--, args.argv++) { + const char *arg = args.argv[0]; + + if (*arg != '-' || !arg[1]) { + argv[j++] = args.argv[0]; + continue; + } + + if (arg[1] != '-') { + args.opt = arg + 1; + do { + if (*args.opt == 'h') + usage(usagestr); + if (parse_short_opt(&args, options) < 0) + usage(usagestr); + } while (args.opt); + continue; + } + + if (!arg[2]) { /* "--" */ + if (!(flags & PARSE_OPT_KEEP_DASHDASH)) { + args.argc--; + args.argv++; + } + break; + } + + if (!strcmp(arg + 2, "help")) + usage(usagestr); + if (parse_long_opt(&args, arg + 2, options)) + usage(usagestr); + } + + memmove(argv + j, args.argv, args.argc * sizeof(*argv)); + argv[j + args.argc] = NULL; + return j + args.argc; +} diff --git a/parse-options.h b/parse-options.h new file mode 100644 index 0000000000..76d73b299f --- /dev/null +++ b/parse-options.h @@ -0,0 +1,35 @@ +#ifndef PARSE_OPTIONS_H +#define PARSE_OPTIONS_H + +enum parse_opt_type { + OPTION_END, + OPTION_BOOLEAN, + OPTION_STRING, + OPTION_INTEGER, +}; + +enum parse_opt_flags { + PARSE_OPT_KEEP_DASHDASH = 1, +}; + +struct option { + enum parse_opt_type type; + int short_name; + const char *long_name; + void *value; +}; + +#define OPT_END() { OPTION_END } +#define OPT_BOOLEAN(s, l, v, h) { OPTION_BOOLEAN, (s), (l), (v) } +#define OPT_INTEGER(s, l, v, h) { OPTION_INTEGER, (s), (l), (v) } +#define OPT_STRING(s, l, v, a, h) { OPTION_STRING, (s), (l), (v) } + +/* parse_options() will filter out the processed options and leave the + * non-option argments in argv[]. + * Returns the number of arguments left in argv[]. + */ +extern int parse_options(int argc, const char **argv, + const struct option *options, + const char *usagestr, int flags); + +#endif From d7a38c54a6ccbcbcf29d8cf1110b2702c8b3f7f8 Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Mon, 15 Oct 2007 01:38:30 +0200 Subject: [PATCH 0325/1490] parse-options: be able to generate usages automatically Signed-off-by: Pierre Habouzit Signed-off-by: Shawn O. Pearce --- parse-options.c | 73 +++++++++++++++++++++++++++++++++++++++++++++---- parse-options.h | 15 +++++++--- 2 files changed, 79 insertions(+), 9 deletions(-) diff --git a/parse-options.c b/parse-options.c index 7bdffdbe51..57a2a11266 100644 --- a/parse-options.c +++ b/parse-options.c @@ -123,7 +123,7 @@ static int parse_long_opt(struct optparse_t *p, const char *arg, } int parse_options(int argc, const char **argv, const struct option *options, - const char *usagestr, int flags) + const char * const usagestr[], int flags) { struct optparse_t args = { argv + 1, argc - 1, NULL }; int j = 0; @@ -140,9 +140,9 @@ int parse_options(int argc, const char **argv, const struct option *options, args.opt = arg + 1; do { if (*args.opt == 'h') - usage(usagestr); + usage_with_options(usagestr, options); if (parse_short_opt(&args, options) < 0) - usage(usagestr); + usage_with_options(usagestr, options); } while (args.opt); continue; } @@ -156,12 +156,75 @@ int parse_options(int argc, const char **argv, const struct option *options, } if (!strcmp(arg + 2, "help")) - usage(usagestr); + usage_with_options(usagestr, options); if (parse_long_opt(&args, arg + 2, options)) - usage(usagestr); + usage_with_options(usagestr, options); } memmove(argv + j, args.argv, args.argc * sizeof(*argv)); argv[j + args.argc] = NULL; return j + args.argc; } + +#define USAGE_OPTS_WIDTH 24 +#define USAGE_GAP 2 + +void usage_with_options(const char * const *usagestr, + const struct option *opts) +{ + struct strbuf sb; + + strbuf_init(&sb, 4096); + strbuf_addstr(&sb, *usagestr); + strbuf_addch(&sb, '\n'); + while (*++usagestr) + strbuf_addf(&sb, " %s\n", *usagestr); + + if (opts->type != OPTION_GROUP) + strbuf_addch(&sb, '\n'); + + for (; opts->type != OPTION_END; opts++) { + size_t pos; + int pad; + + if (opts->type == OPTION_GROUP) { + strbuf_addch(&sb, '\n'); + if (*opts->help) + strbuf_addf(&sb, "%s\n", opts->help); + continue; + } + + pos = sb.len; + strbuf_addstr(&sb, " "); + if (opts->short_name) + strbuf_addf(&sb, "-%c", opts->short_name); + if (opts->long_name && opts->short_name) + strbuf_addstr(&sb, ", "); + if (opts->long_name) + strbuf_addf(&sb, "--%s", opts->long_name); + + switch (opts->type) { + case OPTION_INTEGER: + strbuf_addstr(&sb, " "); + break; + case OPTION_STRING: + if (opts->argh) + strbuf_addf(&sb, " <%s>", opts->argh); + else + strbuf_addstr(&sb, " ..."); + break; + default: + break; + } + + pad = sb.len - pos; + if (pad <= USAGE_OPTS_WIDTH) + pad = USAGE_OPTS_WIDTH - pad; + else { + strbuf_addch(&sb, '\n'); + pad = USAGE_OPTS_WIDTH; + } + strbuf_addf(&sb, "%*s%s\n", pad + USAGE_GAP, "", opts->help); + } + usage(sb.buf); +} diff --git a/parse-options.h b/parse-options.h index 76d73b299f..3006a769cd 100644 --- a/parse-options.h +++ b/parse-options.h @@ -3,6 +3,7 @@ enum parse_opt_type { OPTION_END, + OPTION_GROUP, OPTION_BOOLEAN, OPTION_STRING, OPTION_INTEGER, @@ -17,12 +18,15 @@ struct option { int short_name; const char *long_name; void *value; + const char *argh; + const char *help; }; #define OPT_END() { OPTION_END } -#define OPT_BOOLEAN(s, l, v, h) { OPTION_BOOLEAN, (s), (l), (v) } -#define OPT_INTEGER(s, l, v, h) { OPTION_INTEGER, (s), (l), (v) } -#define OPT_STRING(s, l, v, a, h) { OPTION_STRING, (s), (l), (v) } +#define OPT_GROUP(h) { OPTION_GROUP, 0, NULL, NULL, NULL, (h) } +#define OPT_BOOLEAN(s, l, v, h) { OPTION_BOOLEAN, (s), (l), (v), NULL, (h) } +#define OPT_INTEGER(s, l, v, h) { OPTION_INTEGER, (s), (l), (v), NULL, (h) } +#define OPT_STRING(s, l, v, a, h) { OPTION_STRING, (s), (l), (v), (a), (h) } /* parse_options() will filter out the processed options and leave the * non-option argments in argv[]. @@ -30,6 +34,9 @@ struct option { */ extern int parse_options(int argc, const char **argv, const struct option *options, - const char *usagestr, int flags); + const char * const usagestr[], int flags); + +extern NORETURN void usage_with_options(const char * const *usagestr, + const struct option *options); #endif From beb474379315654566e78eea8a0e39c66ebcbb8a Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sat, 13 Oct 2007 17:34:45 +0100 Subject: [PATCH 0326/1490] Add tests for parse-options.c Signed-off-by: Johannes Schindelin Signed-off-by: Shawn O. Pearce --- .gitignore | 1 + Makefile | 2 +- t/t0040-parse-options.sh | 70 ++++++++++++++++++++++++++++++++++++++++ test-parse-options.c | 35 ++++++++++++++++++++ 4 files changed, 107 insertions(+), 1 deletion(-) create mode 100755 t/t0040-parse-options.sh create mode 100644 test-parse-options.c diff --git a/.gitignore b/.gitignore index 62afef2347..249b451b87 100644 --- a/.gitignore +++ b/.gitignore @@ -154,6 +154,7 @@ test-delta test-dump-cache-tree test-genrandom test-match-trees +test-parse-options test-sha1 common-cmds.h *.tar.gz diff --git a/Makefile b/Makefile index 7e6e1d65f9..3c9af55f44 100644 --- a/Makefile +++ b/Makefile @@ -976,7 +976,7 @@ endif ### Testing rules -TEST_PROGRAMS = test-chmtime$X test-genrandom$X test-date$X test-delta$X test-sha1$X test-match-trees$X test-absolute-path$X +TEST_PROGRAMS = test-chmtime$X test-genrandom$X test-date$X test-delta$X test-sha1$X test-match-trees$X test-absolute-path$X test-parse-options$X all:: $(TEST_PROGRAMS) diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh new file mode 100755 index 0000000000..8e4d74b200 --- /dev/null +++ b/t/t0040-parse-options.sh @@ -0,0 +1,70 @@ +#!/bin/sh +# +# Copyright (c) 2007 Johannes Schindelin +# + +test_description='our own option parser' + +. ./test-lib.sh + +cat > expect.err << EOF +usage: test-parse-options + + -b, --boolean get a boolean + -i, --integer get a integer + -j get a integer, too + +string options + -s, --string + get a string + --string2 get another string + +EOF + +test_expect_success 'test help' ' + ! test-parse-options -h > output 2> output.err && + test ! -s output && + git diff expect.err output.err +' + +cat > expect << EOF +boolean: 2 +integer: 1729 +string: 123 +EOF + +test_expect_success 'short options' ' + test-parse-options -s123 -b -i 1729 -b > output 2> output.err && + git diff expect output && + test ! -s output.err +' +cat > expect << EOF +boolean: 2 +integer: 1729 +string: 321 +EOF + +test_expect_success 'long options' ' + test-parse-options --boolean --integer 1729 --boolean --string2=321 \ + > output 2> output.err && + test ! -s output.err && + git diff expect output +' + +cat > expect << EOF +boolean: 1 +integer: 13 +string: 123 +arg 00: a1 +arg 01: b1 +arg 02: --boolean +EOF + +test_expect_success 'intermingled arguments' ' + test-parse-options a1 --string 123 b1 --boolean -j 13 -- --boolean \ + > output 2> output.err && + test ! -s output.err && + git diff expect output +' + +test_done diff --git a/test-parse-options.c b/test-parse-options.c new file mode 100644 index 0000000000..277cfe4d6d --- /dev/null +++ b/test-parse-options.c @@ -0,0 +1,35 @@ +#include "cache.h" +#include "parse-options.h" + +static int boolean = 0; +static int integer = 0; +static char *string = NULL; + +int main(int argc, const char **argv) +{ + const char *usage[] = { + "test-parse-options ", + NULL + }; + struct option options[] = { + OPT_BOOLEAN('b', "boolean", &boolean, "get a boolean"), + OPT_INTEGER('i', "integer", &integer, "get a integer"), + OPT_INTEGER('j', NULL, &integer, "get a integer, too"), + OPT_GROUP("string options"), + OPT_STRING('s', "string", &string, "string", "get a string"), + OPT_STRING(0, "string2", &string, "str", "get another string"), + OPT_END(), + }; + int i; + + argc = parse_options(argc, argv, options, usage, 0); + + printf("boolean: %d\n", boolean); + printf("integer: %d\n", integer); + printf("string: %s\n", string ? string : "(not set)"); + + for (i = 0; i < argc; i++) + printf("arg %02d: %s\n", i, argv[i]); + + return 0; +} From f389c808b6774fb0a1fc54cf2563a7b3038dd1d4 Mon Sep 17 00:00:00 2001 From: Alex Riesen Date: Sun, 14 Oct 2007 00:10:51 +0200 Subject: [PATCH 0327/1490] Rework make_usage to print the usage message immediately Signed-off-by: Alex Riesen Signed-off-by: Shawn O. Pearce --- parse-options.c | 47 ++++++++++++++++++++++------------------------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/parse-options.c b/parse-options.c index 57a2a11266..89c5f52be5 100644 --- a/parse-options.c +++ b/parse-options.c @@ -1,6 +1,5 @@ #include "git-compat-util.h" #include "parse-options.h" -#include "strbuf.h" #define OPT_SHORT 1 #define OPT_UNSET 2 @@ -172,59 +171,57 @@ int parse_options(int argc, const char **argv, const struct option *options, void usage_with_options(const char * const *usagestr, const struct option *opts) { - struct strbuf sb; - - strbuf_init(&sb, 4096); - strbuf_addstr(&sb, *usagestr); - strbuf_addch(&sb, '\n'); - while (*++usagestr) - strbuf_addf(&sb, " %s\n", *usagestr); + fprintf(stderr, "usage: %s\n", *usagestr++); + while (*usagestr && **usagestr) + fprintf(stderr, " or: %s\n", *usagestr++); + while (*usagestr) + fprintf(stderr, " %s\n", *usagestr++); if (opts->type != OPTION_GROUP) - strbuf_addch(&sb, '\n'); + fputc('\n', stderr); for (; opts->type != OPTION_END; opts++) { size_t pos; int pad; if (opts->type == OPTION_GROUP) { - strbuf_addch(&sb, '\n'); + fputc('\n', stderr); if (*opts->help) - strbuf_addf(&sb, "%s\n", opts->help); + fprintf(stderr, "%s\n", opts->help); continue; } - pos = sb.len; - strbuf_addstr(&sb, " "); + pos = fprintf(stderr, " "); if (opts->short_name) - strbuf_addf(&sb, "-%c", opts->short_name); + pos += fprintf(stderr, "-%c", opts->short_name); if (opts->long_name && opts->short_name) - strbuf_addstr(&sb, ", "); + pos += fprintf(stderr, ", "); if (opts->long_name) - strbuf_addf(&sb, "--%s", opts->long_name); + pos += fprintf(stderr, "--%s", opts->long_name); switch (opts->type) { case OPTION_INTEGER: - strbuf_addstr(&sb, " "); + pos += fprintf(stderr, " "); break; case OPTION_STRING: if (opts->argh) - strbuf_addf(&sb, " <%s>", opts->argh); + pos += fprintf(stderr, " <%s>", opts->argh); else - strbuf_addstr(&sb, " ..."); + pos += fprintf(stderr, " ..."); break; default: break; } - pad = sb.len - pos; - if (pad <= USAGE_OPTS_WIDTH) - pad = USAGE_OPTS_WIDTH - pad; + if (pos <= USAGE_OPTS_WIDTH) + pad = USAGE_OPTS_WIDTH - pos; else { - strbuf_addch(&sb, '\n'); + fputc('\n', stderr); pad = USAGE_OPTS_WIDTH; } - strbuf_addf(&sb, "%*s%s\n", pad + USAGE_GAP, "", opts->help); + fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opts->help); } - usage(sb.buf); + fputc('\n', stderr); + + exit(129); } From ffe659f94d793375fca97dd296422fc10c155016 Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Mon, 15 Oct 2007 01:45:45 +0200 Subject: [PATCH 0328/1490] parse-options: make some arguments optional, add callbacks. * add the possibility to use callbacks to parse some options, this can help implementing new options kinds with great flexibility. struct option gains a callback pointer and a `defval' where callbacks user can put either integers or pointers. callbacks also can use the `value' pointer for anything, preferably to the pointer to the final storage for the value though. * add a `flag' member to struct option to make explicit that this option may have an optional argument. The semantics depends on the option type. For INTEGERS, it means that if the switch is not used in its --long-form= form, and that there is no token after it or that the token does not starts with a digit, then it's assumed that the switch has no argument. For STRING or CALLBACK it works the same, except that the condition is that the next atom starts with a dash. This is needed to implement backward compatible behaviour with existing ways to parse the command line. Its use for new options is discouraged. Signed-off-by: Pierre Habouzit Signed-off-by: Shawn O. Pearce --- parse-options.c | 45 +++++++++++++++++++++++++++++++++++++-------- parse-options.h | 16 ++++++++++++++++ 2 files changed, 53 insertions(+), 8 deletions(-) diff --git a/parse-options.c b/parse-options.c index 89c5f52be5..c751ebf601 100644 --- a/parse-options.c +++ b/parse-options.c @@ -39,7 +39,8 @@ static int opterror(const struct option *opt, const char *reason, int flags) static int get_value(struct optparse_t *p, const struct option *opt, int flags) { - const char *s; + const char *s, *arg; + arg = p->opt ? p->opt : (p->argc > 1 ? p->argv[1] : NULL); if (p->opt && (flags & OPT_UNSET)) return opterror(opt, "takes no value", flags); @@ -59,17 +60,34 @@ static int get_value(struct optparse_t *p, *(const char **)opt->value = (const char *)NULL; return 0; } - if (!p->opt && p->argc <= 1) + if (opt->flags & PARSE_OPT_OPTARG && (!arg || *arg == '-')) { + *(const char **)opt->value = (const char *)opt->defval; + return 0; + } + if (!arg) return opterror(opt, "requires a value", flags); *(const char **)opt->value = get_arg(p); return 0; + case OPTION_CALLBACK: + if (flags & OPT_UNSET) + return (*opt->callback)(opt, NULL, 1); + if (opt->flags & PARSE_OPT_OPTARG && (!arg || *arg == '-')) + return (*opt->callback)(opt, NULL, 0); + if (!arg) + return opterror(opt, "requires a value", flags); + return (*opt->callback)(opt, get_arg(p), 0); + case OPTION_INTEGER: if (flags & OPT_UNSET) { *(int *)opt->value = 0; return 0; } - if (!p->opt && p->argc <= 1) + if (opt->flags & PARSE_OPT_OPTARG && (!arg || !isdigit(*arg))) { + *(int *)opt->value = opt->defval; + return 0; + } + if (!arg) return opterror(opt, "requires a value", flags); *(int *)opt->value = strtol(get_arg(p), (char **)&s, 10); if (*s) @@ -201,13 +219,24 @@ void usage_with_options(const char * const *usagestr, switch (opts->type) { case OPTION_INTEGER: - pos += fprintf(stderr, " "); + if (opts->flags & PARSE_OPT_OPTARG) + pos += fprintf(stderr, " []"); + else + pos += fprintf(stderr, " "); break; case OPTION_STRING: - if (opts->argh) - pos += fprintf(stderr, " <%s>", opts->argh); - else - pos += fprintf(stderr, " ..."); + case OPTION_CALLBACK: + if (opts->argh) { + if (opts->flags & PARSE_OPT_OPTARG) + pos += fprintf(stderr, " [<%s>]", opts->argh); + else + pos += fprintf(stderr, " <%s>", opts->argh); + } else { + if (opts->flags & PARSE_OPT_OPTARG) + pos += fprintf(stderr, " [...]"); + else + pos += fprintf(stderr, " ..."); + } break; default: break; diff --git a/parse-options.h b/parse-options.h index 3006a769cd..2b8e7624d6 100644 --- a/parse-options.h +++ b/parse-options.h @@ -7,12 +7,20 @@ enum parse_opt_type { OPTION_BOOLEAN, OPTION_STRING, OPTION_INTEGER, + OPTION_CALLBACK, }; enum parse_opt_flags { PARSE_OPT_KEEP_DASHDASH = 1, }; +enum parse_opt_option_flags { + PARSE_OPT_OPTARG = 1, +}; + +struct option; +typedef int parse_opt_cb(const struct option *, const char *arg, int unset); + struct option { enum parse_opt_type type; int short_name; @@ -20,6 +28,12 @@ struct option { void *value; const char *argh; const char *help; + + int flags; + parse_opt_cb *callback; + /* holds default value for PARSE_OPT_OPTARG, + though callbacks can use it like they want */ + intptr_t defval; }; #define OPT_END() { OPTION_END } @@ -27,6 +41,8 @@ struct option { #define OPT_BOOLEAN(s, l, v, h) { OPTION_BOOLEAN, (s), (l), (v), NULL, (h) } #define OPT_INTEGER(s, l, v, h) { OPTION_INTEGER, (s), (l), (v), NULL, (h) } #define OPT_STRING(s, l, v, a, h) { OPTION_STRING, (s), (l), (v), (a), (h) } +#define OPT_CALLBACK(s, l, v, a, h, f) \ + { OPTION_CALLBACK, (s), (l), (v), (a), (h), 0, (f) } /* parse_options() will filter out the processed options and leave the * non-option argments in argv[]. From 0ce865b134f8ccd60f6e584744144b0978a9fdf2 Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Sun, 14 Oct 2007 11:05:12 +0200 Subject: [PATCH 0329/1490] Add shortcuts for very often used options. It helps with consistency of the help strings, for example. Signed-off-by: Pierre Habouzit Signed-off-by: Shawn O. Pearce --- parse-options.c | 21 +++++++++++++++++++++ parse-options.h | 11 +++++++++++ 2 files changed, 32 insertions(+) diff --git a/parse-options.c b/parse-options.c index c751ebf601..12a9f9ea68 100644 --- a/parse-options.c +++ b/parse-options.c @@ -254,3 +254,24 @@ void usage_with_options(const char * const *usagestr, exit(129); } + +/*----- some often used options -----*/ +#include "cache.h" +int parse_opt_abbrev_cb(const struct option *opt, const char *arg, int unset) +{ + int v; + + if (!arg) { + v = unset ? 0 : DEFAULT_ABBREV; + } else { + v = strtol(arg, (char **)&arg, 10); + if (*arg) + return opterror(opt, "expects a numerical value", 0); + if (v && v < MINIMUM_ABBREV) + v = MINIMUM_ABBREV; + else if (v > 40) + v = 40; + } + *(int *)(opt->value) = v; + return 0; +} diff --git a/parse-options.h b/parse-options.h index 2b8e7624d6..2558e00a7c 100644 --- a/parse-options.h +++ b/parse-options.h @@ -55,4 +55,15 @@ extern int parse_options(int argc, const char **argv, extern NORETURN void usage_with_options(const char * const *usagestr, const struct option *options); +/*----- some often used options -----*/ +extern int parse_opt_abbrev_cb(const struct option *, const char *, int); + +#define OPT__VERBOSE(var) OPT_BOOLEAN('v', "verbose", (var), "be verbose") +#define OPT__QUIET(var) OPT_BOOLEAN('q', "quiet", (var), "be quiet") +#define OPT__DRY_RUN(var) OPT_BOOLEAN('n', "dry-run", (var), "dry run") +#define OPT__ABBREV(var) \ + { OPTION_CALLBACK, 0, "abbrev", (var), "n", \ + "use digits to display SHA-1s", \ + PARSE_OPT_OPTARG, &parse_opt_abbrev_cb, 0 } + #endif From 7f275b91520d31bfbe43ec5a9bbaf8ac6e663ce0 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sun, 14 Oct 2007 17:54:06 +0100 Subject: [PATCH 0330/1490] parse-options: Allow abbreviated options when unambiguous When there is an option "--amend", the option parser now recognizes "--am" for that option, provided that there is no other option beginning with "--am". Signed-off-by: Johannes Schindelin Signed-off-by: Shawn O. Pearce --- parse-options.c | 37 +++++++++++++++++++++++++++++++++++++ t/t0040-parse-options.sh | 23 +++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/parse-options.c b/parse-options.c index 12a9f9ea68..b4a3b63e9f 100644 --- a/parse-options.c +++ b/parse-options.c @@ -113,6 +113,13 @@ static int parse_short_opt(struct optparse_t *p, const struct option *options) static int parse_long_opt(struct optparse_t *p, const char *arg, const struct option *options) { + const char *arg_end = strchr(arg, '='); + const struct option *abbrev_option = NULL; + int abbrev_flags = 0; + + if (!arg_end) + arg_end = arg + strlen(arg); + for (; options->type != OPTION_END; options++) { const char *rest; int flags = 0; @@ -122,10 +129,38 @@ static int parse_long_opt(struct optparse_t *p, const char *arg, rest = skip_prefix(arg, options->long_name); if (!rest) { + /* abbreviated? */ + if (!strncmp(options->long_name, arg, arg_end - arg)) { +is_abbreviated: + if (abbrev_option) + return error("Ambiguous option: %s " + "(could be --%s%s or --%s%s)", + arg, + (flags & OPT_UNSET) ? + "no-" : "", + options->long_name, + (abbrev_flags & OPT_UNSET) ? + "no-" : "", + abbrev_option->long_name); + if (!(flags & OPT_UNSET) && *arg_end) + p->opt = arg_end + 1; + abbrev_option = options; + abbrev_flags = flags; + continue; + } + /* negated and abbreviated very much? */ + if (!prefixcmp("no-", arg)) { + flags |= OPT_UNSET; + goto is_abbreviated; + } + /* negated? */ if (strncmp(arg, "no-", 3)) continue; flags |= OPT_UNSET; rest = skip_prefix(arg + 3, options->long_name); + /* abbreviated and negated? */ + if (!rest && !prefixcmp(options->long_name, arg + 3)) + goto is_abbreviated; if (!rest) continue; } @@ -136,6 +171,8 @@ static int parse_long_opt(struct optparse_t *p, const char *arg, } return get_value(p, options, flags); } + if (abbrev_option) + return get_value(p, abbrev_option, abbrev_flags); return error("unknown option `%s'", arg); } diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh index 8e4d74b200..ae49424aa0 100755 --- a/t/t0040-parse-options.sh +++ b/t/t0040-parse-options.sh @@ -67,4 +67,27 @@ test_expect_success 'intermingled arguments' ' git diff expect output ' +cat > expect << EOF +boolean: 0 +integer: 2 +string: (not set) +EOF + +test_expect_success 'unambiguously abbreviated option' ' + test-parse-options --int 2 --boolean --no-bo > output 2> output.err && + test ! -s output.err && + git diff expect output +' + +test_expect_success 'unambiguously abbreviated option with "="' ' + test-parse-options --int=2 > output 2> output.err && + test ! -s output.err && + git diff expect output +' + +test_expect_failure 'ambiguously abbreviated option' ' + test-parse-options --strin 123; + test $? != 129 +' + test_done From f481e22a145ed17e85b68bf8ce2de4b80dfa4323 Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Tue, 16 Oct 2007 00:32:38 +0200 Subject: [PATCH 0331/1490] parse-options: allow callbacks to take no arguments at all. Signed-off-by: Pierre Habouzit Signed-off-by: Shawn O. Pearce --- parse-options.c | 10 +++++++++- parse-options.h | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/parse-options.c b/parse-options.c index b4a3b63e9f..cc09c98ec3 100644 --- a/parse-options.c +++ b/parse-options.c @@ -72,6 +72,11 @@ static int get_value(struct optparse_t *p, case OPTION_CALLBACK: if (flags & OPT_UNSET) return (*opt->callback)(opt, NULL, 1); + if (opt->flags & PARSE_OPT_NOARG) { + if (p->opt && !(flags & OPT_SHORT)) + return opterror(opt, "takes no value", flags); + return (*opt->callback)(opt, NULL, 0); + } if (opt->flags & PARSE_OPT_OPTARG && (!arg || *arg == '-')) return (*opt->callback)(opt, NULL, 0); if (!arg) @@ -261,8 +266,11 @@ void usage_with_options(const char * const *usagestr, else pos += fprintf(stderr, " "); break; - case OPTION_STRING: case OPTION_CALLBACK: + if (opts->flags & PARSE_OPT_NOARG) + break; + /* FALLTHROUGH */ + case OPTION_STRING: if (opts->argh) { if (opts->flags & PARSE_OPT_OPTARG) pos += fprintf(stderr, " [<%s>]", opts->argh); diff --git a/parse-options.h b/parse-options.h index 2558e00a7c..3a470e5eb8 100644 --- a/parse-options.h +++ b/parse-options.h @@ -16,6 +16,7 @@ enum parse_opt_flags { enum parse_opt_option_flags { PARSE_OPT_OPTARG = 1, + PARSE_OPT_NOARG = 2, }; struct option; From 5c46f75437e6764532f46cbaf1e0bedb52f5acb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Wed, 3 Oct 2007 17:45:02 -0400 Subject: [PATCH 0332/1490] Port builtin-add.c to use the new option parser. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kristian Høgsberg Signed-off-by: Shawn O. Pearce --- builtin-add.c | 73 +++++++++++++++++++-------------------------------- 1 file changed, 27 insertions(+), 46 deletions(-) diff --git a/builtin-add.c b/builtin-add.c index b8e6094b21..f61681c3ae 100644 --- a/builtin-add.c +++ b/builtin-add.c @@ -12,9 +12,13 @@ #include "diffcore.h" #include "commit.h" #include "revision.h" +#include "run-command.h" +#include "parse-options.h" -static const char builtin_add_usage[] = -"git-add [-n] [-v] [-f] [--interactive | -i] [-u] [--refresh] [--] ..."; +static const char * const builtin_add_usage[] = { + "git-add [options] [--] ...", + NULL +}; static int take_worktree_changes; static const char *excludes_file; @@ -156,23 +160,32 @@ static struct lock_file lock_file; static const char ignore_error[] = "The following paths are ignored by one of your .gitignore files:\n"; +static int verbose = 0, show_only = 0, ignored_too = 0, refresh_only = 0; +static int add_interactive = 0; + +static struct option builtin_add_options[] = { + OPT__DRY_RUN(&show_only), + OPT__VERBOSE(&verbose), + OPT_GROUP(""), + OPT_BOOLEAN('i', "interactive", &add_interactive, "interactive picking"), + OPT_BOOLEAN('f', NULL, &ignored_too, "allow adding otherwise ignored files"), + OPT_BOOLEAN('u', NULL, &take_worktree_changes, "update tracked files"), + OPT_BOOLEAN( 0 , "refresh", &refresh_only, "don't add, only refresh the index"), + OPT_END(), +}; + int cmd_add(int argc, const char **argv, const char *prefix) { - int i, newfd; - int verbose = 0, show_only = 0, ignored_too = 0, refresh_only = 0; + int i, newfd, orig_argc = argc; const char **pathspec; struct dir_struct dir; - int add_interactive = 0; - for (i = 1; i < argc; i++) { - if (!strcmp("--interactive", argv[i]) || - !strcmp("-i", argv[i])) - add_interactive++; - } + argc = parse_options(argc, argv, builtin_add_options, + builtin_add_usage, 0); if (add_interactive) { const char *args[] = { "add--interactive", NULL }; - if (add_interactive != 1 || argc != 2) + if (add_interactive != 1 || orig_argc != 2) die("add --interactive does not take any parameters"); execv_git_cmd(args); exit(1); @@ -182,49 +195,17 @@ int cmd_add(int argc, const char **argv, const char *prefix) newfd = hold_locked_index(&lock_file, 1); - for (i = 1; i < argc; i++) { - const char *arg = argv[i]; - - if (arg[0] != '-') - break; - if (!strcmp(arg, "--")) { - i++; - break; - } - if (!strcmp(arg, "-n")) { - show_only = 1; - continue; - } - if (!strcmp(arg, "-f")) { - ignored_too = 1; - continue; - } - if (!strcmp(arg, "-v")) { - verbose = 1; - continue; - } - if (!strcmp(arg, "-u")) { - take_worktree_changes = 1; - continue; - } - if (!strcmp(arg, "--refresh")) { - refresh_only = 1; - continue; - } - usage(builtin_add_usage); - } - if (take_worktree_changes) { - update(verbose, prefix, argv + i); + update(verbose, prefix, argv); goto finish; } - if (argc <= i) { + if (argc == 0) { fprintf(stderr, "Nothing specified, nothing added.\n"); fprintf(stderr, "Maybe you wanted to say 'git add .'?\n"); return 0; } - pathspec = get_pathspec(prefix, argv + i); + pathspec = get_pathspec(prefix, argv); if (refresh_only) { refresh(verbose, pathspec); From f09985c265f8ea2195a6d6c3e151813e6890dd7d Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Fri, 5 Oct 2007 21:09:19 +0200 Subject: [PATCH 0333/1490] Make builtin-rm.c use parse_options. Signed-off-by: Pierre Habouzit Signed-off-by: Shawn O. Pearce --- builtin-rm.c | 54 ++++++++++++++++++++++------------------------------ 1 file changed, 23 insertions(+), 31 deletions(-) diff --git a/builtin-rm.c b/builtin-rm.c index 3b0677e44b..bca2bd9703 100644 --- a/builtin-rm.c +++ b/builtin-rm.c @@ -8,9 +8,12 @@ #include "dir.h" #include "cache-tree.h" #include "tree-walk.h" +#include "parse-options.h" -static const char builtin_rm_usage[] = -"git-rm [-f] [-n] [-r] [--cached] [--ignore-unmatch] [--quiet] [--] ..."; +static const char * const builtin_rm_usage[] = { + "git-rm [options] [--] ...", + NULL +}; static struct { int nr, alloc; @@ -121,11 +124,23 @@ static int check_local_mod(unsigned char *head, int index_only) static struct lock_file lock_file; +static int show_only = 0, force = 0, index_only = 0, recursive = 0, quiet = 0; +static int ignore_unmatch = 0; + +static struct option builtin_rm_options[] = { + OPT__DRY_RUN(&show_only), + OPT__QUIET(&quiet), + OPT_BOOLEAN( 0 , "cached", &index_only, "only remove from the index"), + OPT_BOOLEAN('f', NULL, &force, "override the up-to-date check"), + OPT_BOOLEAN('r', NULL, &recursive, "allow recursive removal"), + OPT_BOOLEAN( 0 , "ignore-unmatch", &ignore_unmatch, + "exit with a zero status even if nothing matched"), + OPT_END(), +}; + int cmd_rm(int argc, const char **argv, const char *prefix) { int i, newfd; - int show_only = 0, force = 0, index_only = 0, recursive = 0, quiet = 0; - int ignore_unmatch = 0; const char **pathspec; char *seen; @@ -136,34 +151,11 @@ int cmd_rm(int argc, const char **argv, const char *prefix) if (read_cache() < 0) die("index file corrupt"); - for (i = 1 ; i < argc ; i++) { - const char *arg = argv[i]; + argc = parse_options(argc, argv, builtin_rm_options, builtin_rm_usage, 0); + if (!argc) + usage_with_options(builtin_rm_usage, builtin_rm_options); - if (*arg != '-') - break; - else if (!strcmp(arg, "--")) { - i++; - break; - } - else if (!strcmp(arg, "-n")) - show_only = 1; - else if (!strcmp(arg, "--cached")) - index_only = 1; - else if (!strcmp(arg, "-f")) - force = 1; - else if (!strcmp(arg, "-r")) - recursive = 1; - else if (!strcmp(arg, "--quiet")) - quiet = 1; - else if (!strcmp(arg, "--ignore-unmatch")) - ignore_unmatch = 1; - else - usage(builtin_rm_usage); - } - if (argc <= i) - usage(builtin_rm_usage); - - pathspec = get_pathspec(prefix, argv + i); + pathspec = get_pathspec(prefix, argv); seen = NULL; for (i = 0; pathspec[i] ; i++) /* nothing */; From c7a20c117fedd40652d446e58b3eba7e2420fa47 Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Sun, 7 Oct 2007 14:19:33 +0200 Subject: [PATCH 0334/1490] Make builtin-mv.c use parse-options Signed-off-by: Pierre Habouzit Signed-off-by: Shawn O. Pearce --- builtin-mv.c | 84 ++++++++++++++++++++++------------------------------ 1 file changed, 35 insertions(+), 49 deletions(-) diff --git a/builtin-mv.c b/builtin-mv.c index b944651691..a3f9ad1744 100644 --- a/builtin-mv.c +++ b/builtin-mv.c @@ -8,9 +8,12 @@ #include "dir.h" #include "cache-tree.h" #include "path-list.h" +#include "parse-options.h" -static const char builtin_mv_usage[] = -"git-mv [-n] [-f] ( | [-k] ... )"; +static const char * const builtin_mv_usage[] = { + "git-mv [options] ... ", + NULL +}; static const char **copy_pathspec(const char *prefix, const char **pathspec, int count, int base_name) @@ -61,8 +64,14 @@ static struct lock_file lock_file; int cmd_mv(int argc, const char **argv, const char *prefix) { - int i, newfd, count; + int i, newfd; int verbose = 0, show_only = 0, force = 0, ignore_errors = 0; + struct option builtin_mv_options[] = { + OPT__DRY_RUN(&show_only), + OPT_BOOLEAN('f', NULL, &force, "force move/rename even if target exists"), + OPT_BOOLEAN('k', NULL, &ignore_errors, "skip move/rename errors"), + OPT_END(), + }; const char **source, **destination, **dest_path; enum update_mode { BOTH = 0, WORKING_DIRECTORY, INDEX } *modes; struct stat st; @@ -78,52 +87,29 @@ int cmd_mv(int argc, const char **argv, const char *prefix) if (read_cache() < 0) die("index file corrupt"); - for (i = 1; i < argc; i++) { - const char *arg = argv[i]; + argc = parse_options(argc, argv, builtin_mv_options, builtin_mv_usage, 0); + if (--argc < 1) + usage_with_options(builtin_mv_usage, builtin_mv_options); - if (arg[0] != '-') - break; - if (!strcmp(arg, "--")) { - i++; - break; - } - if (!strcmp(arg, "-n")) { - show_only = 1; - continue; - } - if (!strcmp(arg, "-f")) { - force = 1; - continue; - } - if (!strcmp(arg, "-k")) { - ignore_errors = 1; - continue; - } - usage(builtin_mv_usage); - } - count = argc - i - 1; - if (count < 1) - usage(builtin_mv_usage); - - source = copy_pathspec(prefix, argv + i, count, 0); - modes = xcalloc(count, sizeof(enum update_mode)); - dest_path = copy_pathspec(prefix, argv + argc - 1, 1, 0); + source = copy_pathspec(prefix, argv, argc, 0); + modes = xcalloc(argc, sizeof(enum update_mode)); + dest_path = copy_pathspec(prefix, argv + argc, 1, 0); if (dest_path[0][0] == '\0') /* special case: "." was normalized to "" */ - destination = copy_pathspec(dest_path[0], argv + i, count, 1); + destination = copy_pathspec(dest_path[0], argv, argc, 1); else if (!lstat(dest_path[0], &st) && S_ISDIR(st.st_mode)) { dest_path[0] = add_slash(dest_path[0]); - destination = copy_pathspec(dest_path[0], argv + i, count, 1); + destination = copy_pathspec(dest_path[0], argv, argc, 1); } else { - if (count != 1) - usage(builtin_mv_usage); + if (argc != 1) + usage_with_options(builtin_mv_usage, builtin_mv_options); destination = dest_path; } /* Checking */ - for (i = 0; i < count; i++) { + for (i = 0; i < argc; i++) { const char *src = source[i], *dst = destination[i]; int length, src_is_dir; const char *bad = NULL; @@ -167,13 +153,13 @@ int cmd_mv(int argc, const char **argv, const char *prefix) if (last - first > 0) { source = xrealloc(source, - (count + last - first) + (argc + last - first) * sizeof(char *)); destination = xrealloc(destination, - (count + last - first) + (argc + last - first) * sizeof(char *)); modes = xrealloc(modes, - (count + last - first) + (argc + last - first) * sizeof(enum update_mode)); } @@ -183,13 +169,13 @@ int cmd_mv(int argc, const char **argv, const char *prefix) for (j = 0; j < last - first; j++) { const char *path = active_cache[first + j]->name; - source[count + j] = path; - destination[count + j] = + source[argc + j] = path; + destination[argc + j] = prefix_path(dst, dst_len, path + length); - modes[count + j] = INDEX; + modes[argc + j] = INDEX; } - count += last - first; + argc += last - first; } } else if (lstat(dst, &st) == 0) { bad = "destination exists"; @@ -216,12 +202,12 @@ int cmd_mv(int argc, const char **argv, const char *prefix) if (bad) { if (ignore_errors) { - if (--count > 0) { + if (--argc > 0) { memmove(source + i, source + i + 1, - (count - i) * sizeof(char *)); + (argc - i) * sizeof(char *)); memmove(destination + i, destination + i + 1, - (count - i) * sizeof(char *)); + (argc - i) * sizeof(char *)); } } else die ("%s, source=%s, destination=%s", @@ -229,7 +215,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix) } } - for (i = 0; i < count; i++) { + for (i = 0; i < argc; i++) { const char *src = source[i], *dst = destination[i]; enum update_mode mode = modes[i]; if (show_only || verbose) @@ -253,7 +239,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix) path_list_insert(dst, &added); } - if (show_only) { + if (show_only) { show_list("Changed : ", &changed); show_list("Adding : ", &added); show_list("Deleting : ", &deleted); From a8dfd5eac40143030d47da6fd87906990d7bf28c Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Sun, 7 Oct 2007 18:26:21 +0200 Subject: [PATCH 0335/1490] Make builtin-branch.c use parse_options. Signed-off-by: Pierre Habouzit Signed-off-by: Shawn O. Pearce --- builtin-branch.c | 143 +++++++++++++++++------------------------------ 1 file changed, 50 insertions(+), 93 deletions(-) diff --git a/builtin-branch.c b/builtin-branch.c index 3da8b55b8f..d6d5cff6b8 100644 --- a/builtin-branch.c +++ b/builtin-branch.c @@ -11,9 +11,15 @@ #include "commit.h" #include "builtin.h" #include "remote.h" +#include "parse-options.h" -static const char builtin_branch_usage[] = - "git-branch [-r] (-d | -D) | [--track | --no-track] [-l] [-f] [] | (-m | -M) [] | [--color | --no-color] [-r | -a] [-v [--abbrev= | --no-abbrev]]"; +static const char * const builtin_branch_usage[] = { + "git-branch [options] [-r | -a]", + "git-branch [options] [-l] [-f] []", + "git-branch [options] [-r] (-d | -D) ", + "git-branch [options] (-m | -M) [] ", + NULL +}; #define REF_UNKNOWN_TYPE 0x00 #define REF_LOCAL_BRANCH 0x01 @@ -505,93 +511,45 @@ int cmd_branch(int argc, const char **argv, const char *prefix) int rename = 0, force_rename = 0; int verbose = 0, abbrev = DEFAULT_ABBREV, detached = 0; int reflog = 0, track; - int kinds = REF_LOCAL_BRANCH; - int i; + int kinds = REF_LOCAL_BRANCH, kind_remote = 0, kind_any = 0; + + struct option options[] = { + OPT_GROUP("Generic options"), + OPT__VERBOSE(&verbose), + OPT_BOOLEAN( 0 , "track", &track, "set up tracking mode (see git-pull(1))"), + OPT_BOOLEAN( 0 , "color", &branch_use_color, "use colored output"), + OPT_BOOLEAN('r', NULL, &kind_remote, "act on remote-tracking branches"), + OPT__ABBREV(&abbrev), + + OPT_GROUP("Specific git-branch actions:"), + OPT_BOOLEAN('a', NULL, &kind_any, "list both remote-tracking and local branches"), + OPT_BOOLEAN('d', NULL, &delete, "delete fully merged branch"), + OPT_BOOLEAN('D', NULL, &force_delete, "delete branch (even if not merged)"), + OPT_BOOLEAN('l', NULL, &reflog, "create the branch's reflog"), + OPT_BOOLEAN('f', NULL, &force_create, "force creation (when already exists)"), + OPT_BOOLEAN('m', NULL, &rename, "move/rename a branch and its reflog"), + OPT_BOOLEAN('M', NULL, &force_rename, "move/rename a branch, even if target exists"), + OPT_END(), + }; git_config(git_branch_config); track = branch_track; + argc = parse_options(argc, argv, options, builtin_branch_usage, 0); - for (i = 1; i < argc; i++) { - const char *arg = argv[i]; - - if (arg[0] != '-') - break; - if (!strcmp(arg, "--")) { - i++; - break; - } - if (!strcmp(arg, "--track")) { - track = 1; - continue; - } - if (!strcmp(arg, "--no-track")) { - track = 0; - continue; - } - if (!strcmp(arg, "-d")) { - delete = 1; - continue; - } - if (!strcmp(arg, "-D")) { - delete = 1; - force_delete = 1; - continue; - } - if (!strcmp(arg, "-f")) { - force_create = 1; - continue; - } - if (!strcmp(arg, "-m")) { - rename = 1; - continue; - } - if (!strcmp(arg, "-M")) { - rename = 1; - force_rename = 1; - continue; - } - if (!strcmp(arg, "-r")) { - kinds = REF_REMOTE_BRANCH; - continue; - } - if (!strcmp(arg, "-a")) { - kinds = REF_REMOTE_BRANCH | REF_LOCAL_BRANCH; - continue; - } - if (!strcmp(arg, "-l")) { - reflog = 1; - continue; - } - if (!prefixcmp(arg, "--no-abbrev")) { - abbrev = 0; - continue; - } - if (!prefixcmp(arg, "--abbrev=")) { - abbrev = strtoul(arg + 9, NULL, 10); - if (abbrev < MINIMUM_ABBREV) - abbrev = MINIMUM_ABBREV; - else if (abbrev > 40) - abbrev = 40; - continue; - } - if (!strcmp(arg, "-v")) { - verbose = 1; - continue; - } - if (!strcmp(arg, "--color")) { - branch_use_color = 1; - continue; - } - if (!strcmp(arg, "--no-color")) { - branch_use_color = 0; - continue; - } - usage(builtin_branch_usage); - } + delete |= force_delete; + rename |= force_rename; + if (kind_remote) + kinds = REF_REMOTE_BRANCH; + if (kind_any) + kinds = REF_REMOTE_BRANCH | REF_LOCAL_BRANCH; + if (abbrev && abbrev < MINIMUM_ABBREV) + abbrev = MINIMUM_ABBREV; + else if (abbrev > 40) + abbrev = 40; if ((delete && rename) || (delete && force_create) || (rename && force_create)) - usage(builtin_branch_usage); + usage_with_options(builtin_branch_usage, options); head = resolve_ref("HEAD", head_sha1, 0, NULL); if (!head) @@ -599,26 +557,25 @@ int cmd_branch(int argc, const char **argv, const char *prefix) head = xstrdup(head); if (!strcmp(head, "HEAD")) { detached = 1; - } - else { + } else { if (prefixcmp(head, "refs/heads/")) die("HEAD not found below refs/heads!"); head += 11; } if (delete) - return delete_branches(argc - i, argv + i, force_delete, kinds); - else if (i == argc) + return delete_branches(argc, argv, force_delete, kinds); + else if (argc == 0) print_ref_list(kinds, detached, verbose, abbrev); - else if (rename && (i == argc - 1)) - rename_branch(head, argv[i], force_rename); - else if (rename && (i == argc - 2)) - rename_branch(argv[i], argv[i + 1], force_rename); - else if (i == argc - 1 || i == argc - 2) - create_branch(argv[i], (i == argc - 2) ? argv[i+1] : head, + else if (rename && (argc == 1)) + rename_branch(head, argv[0], force_rename); + else if (rename && (argc == 2)) + rename_branch(argv[0], argv[1], force_rename); + else if (argc <= 2) + create_branch(argv[0], (argc == 2) ? argv[1] : head, force_create, reflog, track); else - usage(builtin_branch_usage); + usage_with_options(builtin_branch_usage, options); return 0; } From 166185be7c730a25308b251508aa8f1a39ea476b Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Sun, 7 Oct 2007 20:54:08 +0200 Subject: [PATCH 0336/1490] Make builtin-describe.c use parse_options Signed-off-by: Pierre Habouzit Signed-off-by: Shawn O. Pearce --- builtin-describe.c | 70 +++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 41 deletions(-) diff --git a/builtin-describe.c b/builtin-describe.c index 669110cb06..6eeb9b5045 100644 --- a/builtin-describe.c +++ b/builtin-describe.c @@ -4,12 +4,15 @@ #include "refs.h" #include "builtin.h" #include "exec_cmd.h" +#include "parse-options.h" #define SEEN (1u<<0) #define MAX_TAGS (FLAG_BITS - 1) -static const char describe_usage[] = -"git-describe [--all] [--tags] [--abbrev=] *"; +static const char * const describe_usage[] = { + "git-describe [options] *", + NULL +}; static int debug; /* Display lots of verbose info */ static int all; /* Default to annotated tags only */ @@ -242,57 +245,42 @@ static void describe(const char *arg, int last_one) int cmd_describe(int argc, const char **argv, const char *prefix) { - int i; int contains = 0; + struct option options[] = { + OPT_BOOLEAN(0, "contains", &contains, "find the tag that comes after the commit"), + OPT_BOOLEAN(0, "debug", &debug, "debug search strategy on stderr"), + OPT_BOOLEAN(0, "all", &all, "use any ref in .git/refs"), + OPT_BOOLEAN(0, "tags", &tags, "use any tag in .git/refs/tags"), + OPT__ABBREV(&abbrev), + OPT_INTEGER(0, "candidates", &max_candidates, + "consider most recent tags (default: 10)"), + OPT_END(), + }; - for (i = 1; i < argc; i++) { - const char *arg = argv[i]; - - if (*arg != '-') - break; - else if (!strcmp(arg, "--contains")) - contains = 1; - else if (!strcmp(arg, "--debug")) - debug = 1; - else if (!strcmp(arg, "--all")) - all = 1; - else if (!strcmp(arg, "--tags")) - tags = 1; - else if (!prefixcmp(arg, "--abbrev=")) { - abbrev = strtoul(arg + 9, NULL, 10); - if (abbrev != 0 && (abbrev < MINIMUM_ABBREV || 40 < abbrev)) - abbrev = DEFAULT_ABBREV; - } - else if (!prefixcmp(arg, "--candidates=")) { - max_candidates = strtoul(arg + 13, NULL, 10); - if (max_candidates < 1) - max_candidates = 1; - else if (max_candidates > MAX_TAGS) - max_candidates = MAX_TAGS; - } - else - usage(describe_usage); - } + argc = parse_options(argc, argv, options, describe_usage, 0); + if (max_candidates < 1) + max_candidates = 1; + else if (max_candidates > MAX_TAGS) + max_candidates = MAX_TAGS; save_commit_buffer = 0; if (contains) { - const char **args = xmalloc((4 + argc - i) * sizeof(char*)); + const char **args = xmalloc((4 + argc) * sizeof(char*)); args[0] = "name-rev"; args[1] = "--name-only"; args[2] = "--tags"; - memcpy(args + 3, argv + i, (argc - i) * sizeof(char*)); - args[3 + argc - i] = NULL; - return cmd_name_rev(3 + argc - i, args, prefix); + memcpy(args + 3, argv, argc * sizeof(char*)); + args[3 + argc] = NULL; + return cmd_name_rev(3 + argc, args, prefix); } - if (argc <= i) + if (argc == 0) { describe("HEAD", 1); - else - while (i < argc) { - describe(argv[i], (i == argc - 1)); - i++; + } else { + while (argc-- > 0) { + describe(*argv++, argc == 0); } - + } return 0; } From f81037947c518703cefee2ada5a5d7f724191bc6 Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Sun, 7 Oct 2007 23:02:29 +0200 Subject: [PATCH 0337/1490] Make builtin-revert.c use parse_options. Signed-off-by: Pierre Habouzit Signed-off-by: Shawn O. Pearce --- builtin-revert.c | 65 +++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 36 deletions(-) diff --git a/builtin-revert.c b/builtin-revert.c index a655c8ee2a..2ea766b5bf 100644 --- a/builtin-revert.c +++ b/builtin-revert.c @@ -7,6 +7,7 @@ #include "run-command.h" #include "exec_cmd.h" #include "utf8.h" +#include "parse-options.h" /* * This implements the builtins revert and cherry-pick. @@ -19,51 +20,42 @@ * Copyright (c) 2005 Junio C Hamano */ -static const char *revert_usage = "git-revert [--edit | --no-edit] [-n] "; +static const char * const revert_usage[] = { + "git-revert [options] ", + NULL +}; -static const char *cherry_pick_usage = "git-cherry-pick [--edit] [-n] [-r] [-x] "; +static const char * const cherry_pick_usage[] = { + "git-cherry-pick [options] ", + NULL +}; -static int edit; -static int replay; +static int edit, no_replay, no_commit, needed_deref; static enum { REVERT, CHERRY_PICK } action; -static int no_commit; static struct commit *commit; -static int needed_deref; static const char *me; #define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION" -static void parse_options(int argc, const char **argv) +static void parse_args(int argc, const char **argv) { - const char *usage_str = action == REVERT ? - revert_usage : cherry_pick_usage; + const char * const * usage_str = + action == REVERT ? revert_usage : cherry_pick_usage; unsigned char sha1[20]; const char *arg; - int i; + int noop; + struct option options[] = { + OPT_BOOLEAN('n', "no-commit", &no_commit, "don't automatically commit"), + OPT_BOOLEAN('e', "edit", &edit, "edit the commit message"), + OPT_BOOLEAN('x', NULL, &no_replay, "append commit name when cherry-picking"), + OPT_BOOLEAN('r', NULL, &noop, "no-op (backward compatibility)"), + OPT_END(), + }; - if (argc < 2) - usage(usage_str); - - for (i = 1; i < argc; i++) { - arg = argv[i]; - if (arg[0] != '-') - break; - if (!strcmp(arg, "-n") || !strcmp(arg, "--no-commit")) - no_commit = 1; - else if (!strcmp(arg, "-e") || !strcmp(arg, "--edit")) - edit = 1; - else if (!strcmp(arg, "--no-edit")) - edit = 0; - else if (!strcmp(arg, "-x") || !strcmp(arg, "--i-really-want-" - "to-expose-my-private-commit-object-name")) - replay = 0; - else if (strcmp(arg, "-r")) - usage(usage_str); - } - if (i != argc - 1) - usage(usage_str); - arg = argv[argc - 1]; + if (parse_options(argc, argv, options, usage_str, 0) != 1) + usage_with_options(usage_str, options); + arg = argv[0]; if (get_sha1(arg, sha1)) die ("Cannot find '%s'", arg); commit = (struct commit *)parse_object(sha1); @@ -243,10 +235,10 @@ static int revert_or_cherry_pick(int argc, const char **argv) git_config(git_default_config); me = action == REVERT ? "revert" : "cherry-pick"; setenv(GIT_REFLOG_ACTION, me, 0); - parse_options(argc, argv); + parse_args(argc, argv); /* this is copied from the shell script, but it's never triggered... */ - if (action == REVERT && replay) + if (action == REVERT && !no_replay) die("revert is incompatible with replay"); if (no_commit) { @@ -310,7 +302,7 @@ static int revert_or_cherry_pick(int argc, const char **argv) next = commit; set_author_ident_env(message); add_message_to_msg(message); - if (!replay) { + if (no_replay) { add_to_msg("(cherry picked from commit "); add_to_msg(sha1_to_hex(commit->object.sha1)); add_to_msg(")\n"); @@ -388,13 +380,14 @@ int cmd_revert(int argc, const char **argv, const char *prefix) { if (isatty(0)) edit = 1; + no_replay = 1; action = REVERT; return revert_or_cherry_pick(argc, argv); } int cmd_cherry_pick(int argc, const char **argv, const char *prefix) { - replay = 1; + no_replay = 0; action = CHERRY_PICK; return revert_or_cherry_pick(argc, argv); } From 89942be6a13f69a34e5e824977b45204c36cf9e8 Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Sun, 7 Oct 2007 23:14:43 +0200 Subject: [PATCH 0338/1490] Make builtin-update-ref.c use parse_options Signed-off-by: Pierre Habouzit Signed-off-by: Shawn O. Pearce --- builtin-update-ref.c | 65 +++++++++++++++++--------------------------- 1 file changed, 25 insertions(+), 40 deletions(-) diff --git a/builtin-update-ref.c b/builtin-update-ref.c index fe1f74c9f3..e90737c350 100644 --- a/builtin-update-ref.c +++ b/builtin-update-ref.c @@ -1,59 +1,44 @@ #include "cache.h" #include "refs.h" #include "builtin.h" +#include "parse-options.h" -static const char git_update_ref_usage[] = -"git-update-ref [-m ] (-d | [--no-deref] [])"; +static const char * const git_update_ref_usage[] = { + "git-update-ref [options] -d ", + "git-update-ref [options] []", + NULL +}; int cmd_update_ref(int argc, const char **argv, const char *prefix) { - const char *refname=NULL, *value=NULL, *oldval=NULL, *msg=NULL; + const char *refname, *value, *oldval, *msg=NULL; unsigned char sha1[20], oldsha1[20]; - int i, delete, ref_flags; + int delete = 0, no_deref = 0; + struct option options[] = { + OPT_STRING( 'm', NULL, &msg, "reason", "reason of the update"), + OPT_BOOLEAN('d', NULL, &delete, "deletes the reference"), + OPT_BOOLEAN( 0 , "no-deref", &no_deref, + "update not the one it points to"), + OPT_END(), + }; - delete = 0; - ref_flags = 0; git_config(git_default_config); + argc = parse_options(argc, argv, options, git_update_ref_usage, 0); + if (msg && !*msg) + die("Refusing to perform update with empty message."); - for (i = 1; i < argc; i++) { - if (!strcmp("-m", argv[i])) { - if (i+1 >= argc) - usage(git_update_ref_usage); - msg = argv[++i]; - if (!*msg) - die("Refusing to perform update with empty message."); - continue; - } - if (!strcmp("-d", argv[i])) { - delete = 1; - continue; - } - if (!strcmp("--no-deref", argv[i])) { - ref_flags |= REF_NODEREF; - continue; - } - if (!refname) { - refname = argv[i]; - continue; - } - if (!value) { - value = argv[i]; - continue; - } - if (!oldval) { - oldval = argv[i]; - continue; - } - } - if (!refname || !value) - usage(git_update_ref_usage); + if (argc < 2 || argc > 3) + usage_with_options(git_update_ref_usage, options); + refname = argv[0]; + value = argv[1]; + oldval = argv[2]; if (get_sha1(value, sha1)) die("%s: not a valid SHA1", value); if (delete) { if (oldval) - usage(git_update_ref_usage); + usage_with_options(git_update_ref_usage, options); return delete_ref(refname, sha1); } @@ -62,5 +47,5 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix) die("%s: not a valid old SHA1", oldval); return update_ref(msg, refname, sha1, oldval ? oldsha1 : NULL, - ref_flags, DIE_ON_ERR); + no_deref ? REF_NODEREF : 0, DIE_ON_ERR); } From 785586142a5ed083b97b7be472c08982ae88fd8f Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Sun, 7 Oct 2007 23:18:23 +0200 Subject: [PATCH 0339/1490] Make builtin-symbolic-ref.c use parse_options. Signed-off-by: Pierre Habouzit Signed-off-by: Shawn O. Pearce --- builtin-symbolic-ref.c | 52 +++++++++++++++--------------------------- 1 file changed, 18 insertions(+), 34 deletions(-) diff --git a/builtin-symbolic-ref.c b/builtin-symbolic-ref.c index 9eb95e50da..d33982b967 100644 --- a/builtin-symbolic-ref.c +++ b/builtin-symbolic-ref.c @@ -1,9 +1,12 @@ #include "builtin.h" #include "cache.h" #include "refs.h" +#include "parse-options.h" -static const char git_symbolic_ref_usage[] = -"git-symbolic-ref [-q] [-m ] name [ref]"; +static const char * const git_symbolic_ref_usage[] = { + "git-symbolic-ref [options] name [ref]", + NULL +}; static void check_symref(const char *HEAD, int quiet) { @@ -26,44 +29,25 @@ int cmd_symbolic_ref(int argc, const char **argv, const char *prefix) { int quiet = 0; const char *msg = NULL; + struct option options[] = { + OPT__QUIET(&quiet), + OPT_STRING('m', NULL, &msg, "reason", "reason of the update"), + OPT_END(), + }; git_config(git_default_config); - - while (1 < argc) { - const char *arg = argv[1]; - if (arg[0] != '-') - break; - else if (!strcmp("-q", arg)) - quiet = 1; - else if (!strcmp("-m", arg)) { - argc--; - argv++; - if (argc <= 1) - break; - msg = argv[1]; - if (!*msg) - die("Refusing to perform update with empty message"); - } - else if (!strcmp("--", arg)) { - argc--; - argv++; - break; - } - else - die("unknown option %s", arg); - argc--; - argv++; - } - + argc = parse_options(argc, argv, options, git_symbolic_ref_usage, 0); + if (msg &&!*msg) + die("Refusing to perform update with empty message"); switch (argc) { - case 2: - check_symref(argv[1], quiet); + case 1: + check_symref(argv[0], quiet); break; - case 3: - create_symref(argv[1], argv[2], msg); + case 2: + create_symref(argv[0], argv[1], msg); break; default: - usage(git_symbolic_ref_usage); + usage_with_options(git_symbolic_ref_usage, options); } return 0; } From c3428da87f625d22b7f0ea1e1fb7028264943da3 Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Sat, 13 Oct 2007 20:40:46 +0200 Subject: [PATCH 0340/1490] Make builtin-for-each-ref.c use parse-opts. Signed-off-by: Pierre Habouzit Signed-off-by: Shawn O. Pearce --- builtin-for-each-ref.c | 134 ++++++++++++++++++---------------------- t/t6300-for-each-ref.sh | 0 2 files changed, 59 insertions(+), 75 deletions(-) mode change 100644 => 100755 t/t6300-for-each-ref.sh diff --git a/builtin-for-each-ref.c b/builtin-for-each-ref.c index c74ef2800c..da8c7948e6 100644 --- a/builtin-for-each-ref.c +++ b/builtin-for-each-ref.c @@ -7,6 +7,7 @@ #include "tree.h" #include "blob.h" #include "quote.h" +#include "parse-options.h" /* Quoting styles */ #define QUOTE_NONE 0 @@ -158,17 +159,18 @@ static const char *find_next(const char *cp) * Make sure the format string is well formed, and parse out * the used atoms. */ -static void verify_format(const char *format) +static int verify_format(const char *format) { const char *cp, *sp; for (cp = format; *cp && (sp = find_next(cp)); ) { const char *ep = strchr(sp, ')'); if (!ep) - die("malformatted format string %s", sp); + return error("malformatted format string %s", sp); /* sp points at "%(" and ep points at the closing ")" */ parse_atom(sp + 2, ep); cp = ep + 1; } + return 0; } /* @@ -800,94 +802,76 @@ static struct ref_sort *default_sort(void) return sort; } -int cmd_for_each_ref(int ac, const char **av, const char *prefix) +int opt_parse_sort(const struct option *opt, const char *arg, int unset) +{ + struct ref_sort **sort_tail = opt->value; + struct ref_sort *s; + int len; + + if (!arg) /* should --no-sort void the list ? */ + return -1; + + *sort_tail = s = xcalloc(1, sizeof(*s)); + sort_tail = &s->next; + + if (*arg == '-') { + s->reverse = 1; + arg++; + } + len = strlen(arg); + s->atom = parse_atom(arg, arg+len); + return 0; +} + +static char const * const for_each_ref_usage[] = { + "git-for-each-ref [options] []", + NULL +}; + +int cmd_for_each_ref(int argc, const char **argv, const char *prefix) { int i, num_refs; - const char *format = NULL; + const char *format = "%(objectname) %(objecttype)\t%(refname)"; struct ref_sort *sort = NULL, **sort_tail = &sort; - int maxcount = 0; - int quote_style = -1; /* unspecified yet */ + int maxcount = 0, quote_style; + int quote_shell = 0, quote_perl = 0, quote_python = 0, quote_tcl = 0; struct refinfo **refs; struct grab_ref_cbdata cbdata; - for (i = 1; i < ac; i++) { - const char *arg = av[i]; - if (arg[0] != '-') - break; - if (!strcmp(arg, "--")) { - i++; - break; - } - if (!prefixcmp(arg, "--format=")) { - if (format) - die("more than one --format?"); - format = arg + 9; - continue; - } - if (!strcmp(arg, "-s") || !strcmp(arg, "--shell") ) { - if (0 <= quote_style) - die("more than one quoting style?"); - quote_style = QUOTE_SHELL; - continue; - } - if (!strcmp(arg, "-p") || !strcmp(arg, "--perl") ) { - if (0 <= quote_style) - die("more than one quoting style?"); - quote_style = QUOTE_PERL; - continue; - } - if (!strcmp(arg, "--python") ) { - if (0 <= quote_style) - die("more than one quoting style?"); - quote_style = QUOTE_PYTHON; - continue; - } - if (!strcmp(arg, "--tcl") ) { - if (0 <= quote_style) - die("more than one quoting style?"); - quote_style = QUOTE_TCL; - continue; - } - if (!prefixcmp(arg, "--count=")) { - if (maxcount) - die("more than one --count?"); - maxcount = atoi(arg + 8); - if (maxcount <= 0) - die("The number %s did not parse", arg); - continue; - } - if (!prefixcmp(arg, "--sort=")) { - struct ref_sort *s = xcalloc(1, sizeof(*s)); - int len; + struct option opts[] = { + OPT_BOOLEAN('s', "shell", "e_shell, "quote placeholders suitably for shells"), + OPT_BOOLEAN('p', "perl", "e_perl, "quote placeholders suitably for perl"), + OPT_BOOLEAN( 0 , "python", "e_python, "quote placeholders suitably for python"), + OPT_BOOLEAN( 0 , "tcl", "e_tcl, "quote placeholders suitably for tcl"), - s->next = NULL; - *sort_tail = s; - sort_tail = &s->next; + OPT_GROUP(""), + OPT_INTEGER( 0 , "count", &maxcount, "show only matched refs"), + OPT_STRING( 0 , "format", &format, "format", "format to use for the output"), + OPT_CALLBACK(0 , "sort", &sort_tail, "key", + "field name to sort on", &opt_parse_sort), + OPT_END(), + }; - arg += 7; - if (*arg == '-') { - s->reverse = 1; - arg++; - } - len = strlen(arg); - sort->atom = parse_atom(arg, arg+len); - continue; - } - break; + parse_options(argc, argv, opts, for_each_ref_usage, 0); + if (maxcount < 0) { + error("invalid --count argument: `%d'", maxcount); + usage_with_options(for_each_ref_usage, opts); } - if (quote_style < 0) - quote_style = QUOTE_NONE; + if (quote_shell + quote_perl + quote_python + quote_tcl > 1) { + error("more than one quoting style ?"); + usage_with_options(for_each_ref_usage, opts); + } + if (verify_format(format)) + usage_with_options(for_each_ref_usage, opts); + quote_style = QUOTE_SHELL * quote_shell + QUOTE_PERL * quote_perl + + QUOTE_PYTHON * quote_python + QUOTE_TCL * quote_tcl; if (!sort) sort = default_sort(); sort_atom_limit = used_atom_cnt; - if (!format) - format = "%(objectname) %(objecttype)\t%(refname)"; - - verify_format(format); memset(&cbdata, 0, sizeof(cbdata)); - cbdata.grab_pattern = av + i; + cbdata.grab_pattern = argv; for_each_ref(grab_single_ref, &cbdata); refs = cbdata.grab_array; num_refs = cbdata.grab_cnt; diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh old mode 100644 new mode 100755 From e0e6c0961140c0329a9cfccc1d227f3f4bcd4777 Mon Sep 17 00:00:00 2001 From: Jonas Fonseca Date: Sun, 14 Oct 2007 16:10:42 +0200 Subject: [PATCH 0341/1490] Update manpages to reflect new short and long option aliases Signed-off-by: Jonas Fonseca Signed-off-by: Shawn O. Pearce --- Documentation/git-add.txt | 4 ++-- Documentation/git-branch.txt | 2 +- Documentation/git-mv.txt | 2 +- Documentation/git-rm.txt | 4 ++-- Documentation/git-symbolic-ref.txt | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt index 2fe7355555..963e1ab1e2 100644 --- a/Documentation/git-add.txt +++ b/Documentation/git-add.txt @@ -50,10 +50,10 @@ OPTIONS and `dir/file2`) can be given to add all files in the directory, recursively. --n:: +-n, \--dry-run:: Don't actually add the file(s), just show if they exist. --v:: +-v, \--verbose:: Be verbose. -f:: diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt index b7285bcdbc..5e81aa4ee1 100644 --- a/Documentation/git-branch.txt +++ b/Documentation/git-branch.txt @@ -85,7 +85,7 @@ OPTIONS -a:: List both remote-tracking branches and local branches. --v:: +-v, --verbose:: Show sha1 and commit subject line for each head. --abbrev=:: diff --git a/Documentation/git-mv.txt b/Documentation/git-mv.txt index 2c9cf743c7..3b8ca76dff 100644 --- a/Documentation/git-mv.txt +++ b/Documentation/git-mv.txt @@ -34,7 +34,7 @@ OPTIONS condition. An error happens when a source is neither existing nor controlled by GIT, or when it would overwrite an existing file unless '-f' is given. --n:: +-n, \--dry-run:: Do nothing; only show what would happen diff --git a/Documentation/git-rm.txt b/Documentation/git-rm.txt index be61a82164..48c1d97f93 100644 --- a/Documentation/git-rm.txt +++ b/Documentation/git-rm.txt @@ -30,7 +30,7 @@ OPTIONS -f:: Override the up-to-date check. --n:: +-n, \--dry-run:: Don't actually remove the file(s), just show if they exist in the index. @@ -51,7 +51,7 @@ OPTIONS \--ignore-unmatch:: Exit with a zero status even if no files matched. -\--quiet:: +-q, \--quiet:: git-rm normally outputs one line (in the form of an "rm" command) for each file removed. This option suppresses that output. diff --git a/Documentation/git-symbolic-ref.txt b/Documentation/git-symbolic-ref.txt index a88f722860..694cabab24 100644 --- a/Documentation/git-symbolic-ref.txt +++ b/Documentation/git-symbolic-ref.txt @@ -26,7 +26,7 @@ a regular file whose contents is `ref: refs/heads/master`. OPTIONS ------- --q:: +-q, --quiet:: Do not issue an error message if the is not a symbolic ref but a detached HEAD; instead exit with non-zero status silently. From 5ac0a2063e8f824f6e8ffb4d18de74c55aae7131 Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Mon, 15 Oct 2007 22:34:05 +0200 Subject: [PATCH 0342/1490] Make builtin-fsck.c use parse_options. Signed-off-by: Pierre Habouzit Signed-off-by: Shawn O. Pearce --- builtin-fsck.c | 80 ++++++++++++++++---------------------------------- 1 file changed, 26 insertions(+), 54 deletions(-) diff --git a/builtin-fsck.c b/builtin-fsck.c index 8d12287f03..64da3bd363 100644 --- a/builtin-fsck.c +++ b/builtin-fsck.c @@ -8,6 +8,7 @@ #include "pack.h" #include "cache-tree.h" #include "tree-walk.h" +#include "parse-options.h" #define REACHABLE 0x0001 #define SEEN 0x0002 @@ -666,9 +667,24 @@ static int fsck_cache_tree(struct cache_tree *it) return err; } -static const char fsck_usage[] = -"git-fsck [--tags] [--root] [[--unreachable] [--cache] [--full] " -"[--strict] [--verbose] *]"; +static char const * const fsck_usage[] = { + "git-fsck [options] [...]", + NULL +}; + +static struct option fsck_opts[] = { + OPT__VERBOSE(&verbose), + OPT_BOOLEAN(0, "unreachable", &show_unreachable, "show unreachable objects"), + OPT_BOOLEAN(0, "tags", &show_tags, "report tags"), + OPT_BOOLEAN(0, "root", &show_root, "report root nodes"), + OPT_BOOLEAN(0, "cache", &keep_cache_objects, "make index objects head nodes"), + OPT_BOOLEAN(0, "reflogs", &include_reflogs, "make reflogs head nodes (default)"), + OPT_BOOLEAN(0, "full", &check_full, "also consider alternate objects"), + OPT_BOOLEAN(0, "struct", &check_strict, "enable more strict checking"), + OPT_BOOLEAN(0, "lost-found", &write_lost_and_found, + "write dangling objects in .git/lost-found"), + OPT_END(), +}; int cmd_fsck(int argc, const char **argv, const char *prefix) { @@ -677,49 +693,10 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) track_object_refs = 1; errors_found = 0; - for (i = 1; i < argc; i++) { - const char *arg = argv[i]; - - if (!strcmp(arg, "--unreachable")) { - show_unreachable = 1; - continue; - } - if (!strcmp(arg, "--tags")) { - show_tags = 1; - continue; - } - if (!strcmp(arg, "--root")) { - show_root = 1; - continue; - } - if (!strcmp(arg, "--cache")) { - keep_cache_objects = 1; - continue; - } - if (!strcmp(arg, "--no-reflogs")) { - include_reflogs = 0; - continue; - } - if (!strcmp(arg, "--full")) { - check_full = 1; - continue; - } - if (!strcmp(arg, "--strict")) { - check_strict = 1; - continue; - } - if (!strcmp(arg, "--verbose")) { - verbose = 1; - continue; - } - if (!strcmp(arg, "--lost-found")) { - check_full = 1; - include_reflogs = 0; - write_lost_and_found = 1; - continue; - } - if (*arg == '-') - usage(fsck_usage); + argc = parse_options(argc, argv, fsck_opts, fsck_usage, 0); + if (write_lost_and_found) { + check_full = 1; + include_reflogs = 0; } fsck_head_link(); @@ -741,22 +718,18 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) verify_pack(p, 0); for (p = packed_git; p; p = p->next) { - uint32_t i, num; + uint32_t j, num; if (open_pack_index(p)) continue; num = p->num_objects; - for (i = 0; i < num; i++) - fsck_sha1(nth_packed_object_sha1(p, i)); + for (j = 0; j < num; j++) + fsck_sha1(nth_packed_object_sha1(p, j)); } } heads = 0; for (i = 1; i < argc; i++) { const char *arg = argv[i]; - - if (*arg == '-') - continue; - if (!get_sha1(arg, head_sha1)) { struct object *obj = lookup_object(head_sha1); @@ -783,7 +756,6 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) } if (keep_cache_objects) { - int i; read_cache(); for (i = 0; i < active_nr; i++) { unsigned int mode; From 833f3abd821434fd9b12d6cea66f04f232479c22 Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Mon, 15 Oct 2007 22:38:51 +0200 Subject: [PATCH 0343/1490] Make builtin-count-objects.c use parse_options. Signed-off-by: Pierre Habouzit Signed-off-by: Shawn O. Pearce --- builtin-count-objects.c | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/builtin-count-objects.c b/builtin-count-objects.c index 4274ec1950..f00306fb67 100644 --- a/builtin-count-objects.c +++ b/builtin-count-objects.c @@ -6,8 +6,7 @@ #include "cache.h" #include "builtin.h" - -static const char count_objects_usage[] = "git-count-objects [-v]"; +#include "parse-options.h" static void count_objects(DIR *d, char *path, int len, int verbose, unsigned long *loose, @@ -67,29 +66,28 @@ static void count_objects(DIR *d, char *path, int len, int verbose, } } -int cmd_count_objects(int ac, const char **av, const char *prefix) +static char const * const count_objects_usage[] = { + "git-count-objects [-v]", + NULL +}; + +int cmd_count_objects(int argc, const char **argv, const char *prefix) { - int i; - int verbose = 0; + int i, verbose = 0; const char *objdir = get_object_directory(); int len = strlen(objdir); char *path = xmalloc(len + 50); unsigned long loose = 0, packed = 0, packed_loose = 0, garbage = 0; unsigned long loose_size = 0; + struct option opts[] = { + OPT__VERBOSE(&verbose), + OPT_END(), + }; - for (i = 1; i < ac; i++) { - const char *arg = av[i]; - if (*arg != '-') - break; - else if (!strcmp(arg, "-v")) - verbose = 1; - else - usage(count_objects_usage); - } - + argc = parse_options(argc, argv, opts, count_objects_usage, 0); /* we do not take arguments other than flags for now */ - if (i < ac) - usage(count_objects_usage); + if (argc) + usage_with_options(count_objects_usage, opts); memcpy(path, objdir, len); if (len && objdir[len-1] != '/') path[len++] = '/'; From edefb1a23755505cc9b4e750c292cd236b1e8655 Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Mon, 15 Oct 2007 22:57:59 +0200 Subject: [PATCH 0344/1490] Make builtin-name-rev.c use parse_options. Signed-off-by: Pierre Habouzit Signed-off-by: Shawn O. Pearce --- builtin-name-rev.c | 64 ++++++++++++++++++---------------------------- 1 file changed, 25 insertions(+), 39 deletions(-) diff --git a/builtin-name-rev.c b/builtin-name-rev.c index 03083e9477..a0c89a827b 100644 --- a/builtin-name-rev.c +++ b/builtin-name-rev.c @@ -3,12 +3,10 @@ #include "commit.h" #include "tag.h" #include "refs.h" +#include "parse-options.h" #define CUTOFF_DATE_SLOP 86400 /* one day */ -static const char name_rev_usage[] = - "git-name-rev [--tags | --refs=] ( --all | --stdin | committish [committish...] )\n"; - typedef struct rev_name { const char *tip_name; int generation; @@ -153,51 +151,41 @@ static const char* get_rev_name(struct object *o) } } +static char const * const name_rev_usage[] = { + "git-name-rev [options] ( --all | --stdin | ... )", + NULL +}; + int cmd_name_rev(int argc, const char **argv, const char *prefix) { struct object_array revs = { 0, 0, NULL }; - int as_is = 0, all = 0, transform_stdin = 0; + int all = 0, transform_stdin = 0; struct name_ref_data data = { 0, 0, NULL }; + struct option opts[] = { + OPT_BOOLEAN(0, "name-only", &data.name_only, "print only names (no SHA-1)"), + OPT_BOOLEAN(0, "tags", &data.tags_only, "only use tags to name the commits"), + OPT_STRING(0, "refs", &data.ref_filter, "pattern", + "only use refs matching "), + OPT_GROUP(""), + OPT_BOOLEAN(0, "all", &all, "list all commits reachable from all refs"), + OPT_BOOLEAN(0, "stdin", &transform_stdin, "read from stdin"), + OPT_END(), + }; git_config(git_default_config); + argc = parse_options(argc, argv, opts, name_rev_usage, 0); + if (!!all + !!transform_stdin + !!argc > 1) { + error("Specify either a list, or --all, not both!"); + usage_with_options(name_rev_usage, opts); + } + if (all || transform_stdin) + cutoff = 0; - if (argc < 2) - usage(name_rev_usage); - - for (--argc, ++argv; argc; --argc, ++argv) { + for (; argc; argc--, argv++) { unsigned char sha1[20]; struct object *o; struct commit *commit; - if (!as_is && (*argv)[0] == '-') { - if (!strcmp(*argv, "--")) { - as_is = 1; - continue; - } else if (!strcmp(*argv, "--name-only")) { - data.name_only = 1; - continue; - } else if (!strcmp(*argv, "--tags")) { - data.tags_only = 1; - continue; - } else if (!prefixcmp(*argv, "--refs=")) { - data.ref_filter = *argv + 7; - continue; - } else if (!strcmp(*argv, "--all")) { - if (argc > 1) - die("Specify either a list, or --all, not both!"); - all = 1; - cutoff = 0; - continue; - } else if (!strcmp(*argv, "--stdin")) { - if (argc > 1) - die("Specify either a list, or --stdin, not both!"); - transform_stdin = 1; - cutoff = 0; - continue; - } - usage(name_rev_usage); - } - if (get_sha1(*argv, sha1)) { fprintf(stderr, "Could not get sha1 for %s. Skipping.\n", *argv); @@ -212,10 +200,8 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix) } commit = (struct commit *)o; - if (cutoff > commit->date) cutoff = commit->date; - add_object_array((struct object *)commit, *argv, &revs); } From b2565ae57376116b9d78369b6eac07e55c6f7851 Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Mon, 15 Oct 2007 23:06:02 +0200 Subject: [PATCH 0345/1490] Make builtin-pack-refs.c use parse_options. Signed-off-by: Pierre Habouzit Signed-off-by: Shawn O. Pearce --- builtin-pack-refs.c | 45 +++++++++++++++++++-------------------------- 1 file changed, 19 insertions(+), 26 deletions(-) diff --git a/builtin-pack-refs.c b/builtin-pack-refs.c index 09df4e11a8..a62f06bb89 100644 --- a/builtin-pack-refs.c +++ b/builtin-pack-refs.c @@ -3,9 +3,7 @@ #include "refs.h" #include "object.h" #include "tag.h" - -static const char builtin_pack_refs_usage[] = -"git-pack-refs [--all] [--prune | --no-prune]"; +#include "parse-options.h" struct ref_to_prune { struct ref_to_prune *next; @@ -117,31 +115,26 @@ static int pack_refs(unsigned int flags) return 0; } +static char const * const pack_refs_usage[] = { + "git-pack-refs [options]", + NULL +}; + int cmd_pack_refs(int argc, const char **argv, const char *prefix) { - int i; - unsigned int flags; - - flags = PACK_REFS_PRUNE; - for (i = 1; i < argc; i++) { - const char *arg = argv[i]; - if (!strcmp(arg, "--prune")) { - flags |= PACK_REFS_PRUNE; /* now the default */ - continue; - } - if (!strcmp(arg, "--no-prune")) { - flags &= ~PACK_REFS_PRUNE; - continue; - } - if (!strcmp(arg, "--all")) { - flags |= PACK_REFS_ALL; - continue; - } - /* perhaps other parameters later... */ - break; - } - if (i != argc) - usage(builtin_pack_refs_usage); + int all = 0, prune = 1; + unsigned int flags = 0; + struct option opts[] = { + OPT_BOOLEAN(0, "all", &all, "pack everything"), + OPT_BOOLEAN(0, "prune", &prune, "prune loose refs (default)"), + OPT_END(), + }; + if (parse_options(argc, argv, opts, pack_refs_usage, 0)) + usage_with_options(pack_refs_usage, opts); + if (prune) + flags |= PACK_REFS_PRUNE; + if (all) + flags |= PACK_REFS_ALL; return pack_refs(flags); } From 6b9ff1e3bd089d1bef211ba74c12e056810755b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?= Date: Sat, 27 Oct 2007 14:47:21 +0700 Subject: [PATCH 0346/1490] git-sh-setup.sh: use "git rev-parse --show-cdup" to check for SUBDIRECTORY_OK MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "git rev-parse --git-dir" trick does not play well with worktree Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano --- git-sh-setup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git-sh-setup.sh b/git-sh-setup.sh index 3c325fd133..86d7d4c4e7 100755 --- a/git-sh-setup.sh +++ b/git-sh-setup.sh @@ -110,7 +110,7 @@ esac if [ -z "$SUBDIRECTORY_OK" ] then : ${GIT_DIR=.git} - GIT_DIR=$(GIT_DIR="$GIT_DIR" git rev-parse --git-dir) || { + test -z "$(git rev-parse --show-cdup)" || { exit=$? echo >&2 "You need to run this command from the toplevel of the working tree." exit $exit From 0cec6db5cfbb109eebb3a50b6213cab2dc68f0c8 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Tue, 30 Oct 2007 01:35:05 +0100 Subject: [PATCH 0347/1490] gitweb: Fix and simplify "split patch" detection There are some cases when one line from "raw" git-diff output (raw format) corresponds to more than one patch in the patchset git-diff output; we call this situation "split patch". Old code misdetected subsequent patches (for different files) with the same pre-image and post-image as fragments of "split patch", leading to mislabeled from-file/to-file diff header etc. Old code used pre-image and post-image SHA-1 identifier ('from_id' and 'to_id') to check if current patch corresponds to old raw diff format line, to find if one difftree raw line coresponds to more than one patch in the patch format. Now we use post-image filename for that. This assumes that post-image filename alone can be used to identify difftree raw line. In the case this changes (which is unlikely considering current diff engine) we can add 'from_id' and 'to_id' to detect "patch splitting" together with 'to_file'. Because old code got pre-image and post-image SHA-1 identifier for the patch from the "index" line in extended diff header, diff header had to be buffered. New code takes post-image filename from "git diff" header, which is first line of a patch; this allows to simplify git_patchset_body code. A side effect of resigning diff header buffering is that there is always "diff extended_header" div, even if extended diff header is empty. Alternate solution would be to check when git splits patches, and do not check if parsed info from current patch corresponds to current or next raw diff format output line. Git splits patches only for 'T' (typechange) status filepair, and there always two patches corresponding to one raw diff line. It was not used because it would tie gitweb code to minute details of git diff output. While at it, use newly introduced parsed_difftree_line wrapper subroutine in git_difftree_body. Noticed-by: Yann Dirson Diagnosed-by: Petr Baudis Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 152 ++++++++++++++++++++------------------------- 1 file changed, 67 insertions(+), 85 deletions(-) diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 48e21dad6c..1537b0ec1d 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -2000,6 +2000,19 @@ sub parse_difftree_raw_line { return wantarray ? %res : \%res; } +# wrapper: return parsed line of git-diff-tree "raw" output +# (the argument might be raw line, or parsed info) +sub parsed_difftree_line { + my $line_or_ref = shift; + + if (ref($line_or_ref) eq "HASH") { + # pre-parsed (or generated by hand) + return $line_or_ref; + } else { + return parse_difftree_raw_line($line_or_ref); + } +} + # parse line of git-ls-tree output sub parse_ls_tree_line ($;%) { my $line = shift; @@ -2043,6 +2056,7 @@ sub parse_from_to_diffinfo { } } } else { + # ordinary (not combined) diff $from->{'file'} = $diffinfo->{'from_file'} || $diffinfo->{'file'}; if ($diffinfo->{'status'} ne "A") { # not new (added) file $from->{'href'} = href(action=>"blob", hash_base=>$hash_parent, @@ -2766,6 +2780,7 @@ sub git_print_tree_entry { ## ...................................................................... ## functions printing large fragments of HTML +# get pre-image filenames for merge (combined) diff sub fill_from_file_info { my ($diff, @parents) = @_; @@ -2782,28 +2797,25 @@ sub fill_from_file_info { return $diff; } -# parameters can be strings, or references to arrays of strings -sub from_ids_eq { - my ($a, $b) = @_; - - if (ref($a) eq "ARRAY" && ref($b) eq "ARRAY" && @$a == @$b) { - for (my $i = 0; $i < @$a; ++$i) { - return 0 unless ($a->[$i] eq $b->[$i]); - } - return 1; - } elsif (!ref($a) && !ref($b)) { - return $a eq $b; - } else { - return 0; - } -} - +# is current raw difftree line of file deletion sub is_deleted { my $diffinfo = shift; return $diffinfo->{'to_id'} eq ('0' x 40); } +# does patch correspond to [previous] difftree raw line +# $diffinfo - hashref of parsed raw diff format +# $patchinfo - hashref of parsed patch diff format +# (the same keys as in $diffinfo) +sub is_patch_split { + my ($diffinfo, $patchinfo) = @_; + + return defined $diffinfo && defined $patchinfo + && ($diffinfo->{'to_file'} || $diffinfo->{'file'}) eq $patchinfo->{'to_file'}; +} + + sub git_difftree_body { my ($difftree, $hash, @parents) = @_; my ($parent) = $parents[0]; @@ -2840,13 +2852,7 @@ sub git_difftree_body { my $alternate = 1; my $patchno = 0; foreach my $line (@{$difftree}) { - my $diff; - if (ref($line) eq "HASH") { - # pre-parsed (or generated by hand) - $diff = $line; - } else { - $diff = parse_difftree_raw_line($line); - } + my $diff = parsed_difftree_line($line); if ($alternate) { print "\n"; @@ -3117,10 +3123,12 @@ sub git_patchset_body { my ($fd, $difftree, $hash, @hash_parents) = @_; my ($hash_parent) = $hash_parents[0]; + my $is_combined = (@hash_parents > 1); my $patch_idx = 0; my $patch_number = 0; my $patch_line; my $diffinfo; + my $to_name; my (%from, %to); print "
\n"; @@ -3134,73 +3142,46 @@ sub git_patchset_body { PATCH: while ($patch_line) { - my @diff_header; - my ($from_id, $to_id); - # git diff header - #assert($patch_line =~ m/^diff /) if DEBUG; - #assert($patch_line !~ m!$/$!) if DEBUG; # is chomp-ed - $patch_number++; - push @diff_header, $patch_line; - - # extended diff header - EXTENDED_HEADER: - while ($patch_line = <$fd>) { - chomp $patch_line; - - last EXTENDED_HEADER if ($patch_line =~ m/^--- |^diff /); - - if ($patch_line =~ m/^index ([0-9a-fA-F]{40})..([0-9a-fA-F]{40})/) { - $from_id = $1; - $to_id = $2; - } elsif ($patch_line =~ m/^index ((?:[0-9a-fA-F]{40},)+[0-9a-fA-F]{40})..([0-9a-fA-F]{40})/) { - $from_id = [ split(',', $1) ]; - $to_id = $2; - } - - push @diff_header, $patch_line; + # parse "git diff" header line + if ($patch_line =~ m/^diff --git (\"(?:[^\\\"]*(?:\\.[^\\\"]*)*)\"|[^ "]*) (.*)$/) { + # $1 is from_name, which we do not use + $to_name = unquote($2); + $to_name =~ s!^b/!!; + } elsif ($patch_line =~ m/^diff --(cc|combined) ("?.*"?)$/) { + # $1 is 'cc' or 'combined', which we do not use + $to_name = unquote($2); + } else { + $to_name = undef; } - my $last_patch_line = $patch_line; # check if current patch belong to current raw line # and parse raw git-diff line if needed - if (defined $diffinfo && - defined $from_id && defined $to_id && - from_ids_eq($diffinfo->{'from_id'}, $from_id) && - $diffinfo->{'to_id'} eq $to_id) { + if (is_patch_split($diffinfo, { 'to_file' => $to_name })) { # this is continuation of a split patch print "
\n"; } else { # advance raw git-diff output if needed $patch_idx++ if defined $diffinfo; + # read and prepare patch information + $diffinfo = parsed_difftree_line($difftree->[$patch_idx]); + # compact combined diff output can have some patches skipped - # find which patch (using pathname of result) we are at now - my $to_name; - if ($diff_header[0] =~ m!^diff --cc "?(.*)"?$!) { - $to_name = $1; - } - - do { - # read and prepare patch information - if (ref($difftree->[$patch_idx]) eq "HASH") { - # pre-parsed (or generated by hand) - $diffinfo = $difftree->[$patch_idx]; - } else { - $diffinfo = parse_difftree_raw_line($difftree->[$patch_idx]); - } - - # check if current raw line has no patch (it got simplified) - if (defined $to_name && $to_name ne $diffinfo->{'to_file'}) { + # find which patch (using pathname of result) we are at now; + if ($is_combined) { + while ($to_name ne $diffinfo->{'to_file'}) { print "
\n" . format_diff_cc_simplified($diffinfo, @hash_parents) . "
\n"; # class="patch" $patch_idx++; $patch_number++; + + last if $patch_idx > $#$difftree; + $diffinfo = parsed_difftree_line($difftree->[$patch_idx]); } - } until (!defined $to_name || $to_name eq $diffinfo->{'to_file'} || - $patch_idx > $#$difftree); + } # modifies %from, %to hashes parse_from_to_diffinfo($diffinfo, \%from, \%to, @hash_parents); @@ -3210,30 +3191,36 @@ sub git_patchset_body { print "
\n"; } + # git diff header + #assert($patch_line =~ m/^diff /) if DEBUG; + #assert($patch_line !~ m!$/$!) if DEBUG; # is chomp-ed + $patch_number++; # print "git diff" header - $patch_line = shift @diff_header; print format_git_diff_header_line($patch_line, $diffinfo, \%from, \%to); # print extended diff header - print "
\n" if (@diff_header > 0); + print "
\n"; EXTENDED_HEADER: - foreach $patch_line (@diff_header) { + while ($patch_line = <$fd>) { + chomp $patch_line; + + last EXTENDED_HEADER if ($patch_line =~ m/^--- |^diff /); + print format_extended_diff_header_line($patch_line, $diffinfo, \%from, \%to); } - print "
\n" if (@diff_header > 0); # class="diff extended_header" + print "
\n"; # class="diff extended_header" # from-file/to-file diff header - $patch_line = $last_patch_line; if (! $patch_line) { print "
\n"; # class="patch" last PATCH; } next PATCH if ($patch_line =~ m/^diff /); #assert($patch_line =~ m/^---/) if DEBUG; - #assert($patch_line eq $last_patch_line) if DEBUG; + my $last_patch_line = $patch_line; $patch_line = <$fd>; chomp $patch_line; #assert($patch_line =~ m/^\+\+\+/) if DEBUG; @@ -3258,16 +3245,11 @@ sub git_patchset_body { # for compact combined (--cc) format, with chunk and patch simpliciaction # patchset might be empty, but there might be unprocessed raw lines - for ($patch_idx++ if $patch_number > 0; + for (++$patch_idx if $patch_number > 0; $patch_idx < @$difftree; - $patch_idx++) { + ++$patch_idx) { # read and prepare patch information - if (ref($difftree->[$patch_idx]) eq "HASH") { - # pre-parsed (or generated by hand) - $diffinfo = $difftree->[$patch_idx]; - } else { - $diffinfo = parse_difftree_raw_line($difftree->[$patch_idx]); - } + $diffinfo = parsed_difftree_line($difftree->[$patch_idx]); # generate anchor for "patch" links in difftree / whatchanged part print "
\n" . From 562e35c34ced4ca7af024d213737411238dbe0f5 Mon Sep 17 00:00:00 2001 From: "Michael W. Olson" Date: Tue, 30 Oct 2007 09:53:47 -0400 Subject: [PATCH 0348/1490] Documentation/git-cvsexportcommit.txt: s/mgs/msg/ in example Signed-off-by: Junio C Hamano --- Documentation/git-cvsexportcommit.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/git-cvsexportcommit.txt b/Documentation/git-cvsexportcommit.txt index 4c8d1e6386..c3922f9238 100644 --- a/Documentation/git-cvsexportcommit.txt +++ b/Documentation/git-cvsexportcommit.txt @@ -73,7 +73,7 @@ Merge one patch into CVS:: $ export GIT_DIR=~/project/.git $ cd ~/project_cvs_checkout $ git-cvsexportcommit -v -$ cvs commit -F .mgs +$ cvs commit -F .msg ------------ Merge pending patches into CVS automatically -- only if you really know what you are doing:: From 0e549137966feb016927a827fb6e359aec8264a3 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 30 Oct 2007 14:57:31 -0400 Subject: [PATCH 0349/1490] prune-packed: don't call display_progress() for every file The progress count is per fanout directory, so it is useless to call it for every file as the count doesn't change that often. Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- builtin-prune-packed.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/builtin-prune-packed.c b/builtin-prune-packed.c index 015c8bb7cc..907e36828f 100644 --- a/builtin-prune-packed.c +++ b/builtin-prune-packed.c @@ -15,6 +15,9 @@ static void prune_dir(int i, DIR *dir, char *pathname, int len, int opts) struct dirent *de; char hex[40]; + if (opts == VERBOSE) + display_progress(&progress, i + 1); + sprintf(hex, "%02x", i); while ((de = readdir(dir)) != NULL) { unsigned char sha1[20]; @@ -26,8 +29,6 @@ static void prune_dir(int i, DIR *dir, char *pathname, int len, int opts) if (!has_sha1_pack(sha1, NULL)) continue; memcpy(pathname + len, de->d_name, 38); - if (opts == VERBOSE) - display_progress(&progress, i + 1); if (opts & DRY_RUN) printf("rm -f %s\n", pathname); else if (unlink(pathname) < 0) From dc6a0757c4f966dd124bd85be2adad5a0b7b2167 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 30 Oct 2007 14:57:32 -0400 Subject: [PATCH 0350/1490] make struct progress an opaque type This allows for better management of progress "object" existence, as well as making the progress display implementation more independent from its callers. Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- builtin-pack-objects.c | 16 ++++++++-------- builtin-prune-packed.c | 7 +++---- builtin-unpack-objects.c | 6 +++--- index-pack.c | 12 ++++++------ progress.c | 33 +++++++++++++++++++++++++++------ progress.h | 18 +++++------------- unpack-trees.c | 10 +++++----- 7 files changed, 57 insertions(+), 45 deletions(-) diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index 21ba977df3..3ca5cc7800 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -73,7 +73,7 @@ static int depth = 50; static int delta_search_threads = 1; static int pack_to_stdout; static int num_preferred_base; -static struct progress progress_state; +static struct progress *progress_state; static int pack_compression_level = Z_DEFAULT_COMPRESSION; static int pack_compression_seen; @@ -598,7 +598,7 @@ static void write_pack_file(void) uint32_t nr_remaining = nr_result; if (do_progress) - start_progress(&progress_state, "Writing objects", nr_result); + progress_state = start_progress("Writing objects", nr_result); written_list = xmalloc(nr_objects * sizeof(struct object_entry *)); do { @@ -630,7 +630,7 @@ static void write_pack_file(void) break; offset = offset_one; if (do_progress) - display_progress(&progress_state, written); + display_progress(progress_state, written); } /* @@ -854,7 +854,7 @@ static int add_object_entry(const unsigned char *sha1, enum object_type type, object_ix[-1 - ix] = nr_objects; if (progress) - display_progress(&progress_state, nr_objects); + display_progress(progress_state, nr_objects); if (name && no_try_delta(name)) entry->no_try_delta = 1; @@ -1518,7 +1518,7 @@ static void find_deltas(struct object_entry **list, unsigned list_size, progress_lock(); (*processed)++; if (progress) - display_progress(&progress_state, *processed); + display_progress(progress_state, *processed); progress_unlock(); /* @@ -1718,8 +1718,8 @@ static void prepare_pack(int window, int depth) if (nr_deltas && n > 1) { unsigned nr_done = 0; if (progress) - start_progress(&progress_state, "Compressing objects", - nr_deltas); + progress_state = start_progress("Compressing objects", + nr_deltas); qsort(delta_list, n, sizeof(*delta_list), type_size_sort); ll_find_deltas(delta_list, n, window+1, depth, &nr_done); if (progress) @@ -2135,7 +2135,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) prepare_packed_git(); if (progress) - start_progress(&progress_state, "Counting objects", 0); + progress_state = start_progress("Counting objects", 0); if (!use_internal_rev_list) read_object_list_from_stdin(); else { diff --git a/builtin-prune-packed.c b/builtin-prune-packed.c index 907e36828f..c66fb037f6 100644 --- a/builtin-prune-packed.c +++ b/builtin-prune-packed.c @@ -8,7 +8,7 @@ static const char prune_packed_usage[] = #define DRY_RUN 01 #define VERBOSE 02 -static struct progress progress; +static struct progress *progress; static void prune_dir(int i, DIR *dir, char *pathname, int len, int opts) { @@ -16,7 +16,7 @@ static void prune_dir(int i, DIR *dir, char *pathname, int len, int opts) char hex[40]; if (opts == VERBOSE) - display_progress(&progress, i + 1); + display_progress(progress, i + 1); sprintf(hex, "%02x", i); while ((de = readdir(dir)) != NULL) { @@ -46,8 +46,7 @@ void prune_packed_objects(int opts) int len = strlen(dir); if (opts == VERBOSE) - start_progress_delay(&progress, - "Removing duplicate objects", + progress = start_progress_delay("Removing duplicate objects", 256, 95, 2); if (len > PATH_MAX - 42) diff --git a/builtin-unpack-objects.c b/builtin-unpack-objects.c index 2317b8f411..e0ecbc51a7 100644 --- a/builtin-unpack-objects.c +++ b/builtin-unpack-objects.c @@ -311,7 +311,7 @@ static void unpack_one(unsigned nr) static void unpack_all(void) { int i; - struct progress progress; + struct progress *progress = NULL; struct pack_header *hdr = fill(sizeof(struct pack_header)); unsigned nr_objects = ntohl(hdr->hdr_entries); @@ -322,12 +322,12 @@ static void unpack_all(void) use(sizeof(struct pack_header)); if (!quiet) - start_progress(&progress, "Unpacking objects", nr_objects); + progress = start_progress("Unpacking objects", nr_objects); obj_list = xmalloc(nr_objects * sizeof(*obj_list)); for (i = 0; i < nr_objects; i++) { unpack_one(i); if (!quiet) - display_progress(&progress, i + 1); + display_progress(progress, i + 1); } if (!quiet) stop_progress(&progress); diff --git a/index-pack.c b/index-pack.c index 2f149a40fd..b4543a4cc2 100644 --- a/index-pack.c +++ b/index-pack.c @@ -46,7 +46,7 @@ static int nr_resolved_deltas; static int from_stdin; static int verbose; -static struct progress progress; +static struct progress *progress; /* We always read in 4kB chunks. */ static unsigned char input_buffer[4096]; @@ -406,7 +406,7 @@ static void parse_pack_objects(unsigned char *sha1) * - remember base (SHA1 or offset) for all deltas. */ if (verbose) - start_progress(&progress, "Indexing objects", nr_objects); + progress = start_progress("Indexing objects", nr_objects); for (i = 0; i < nr_objects; i++) { struct object_entry *obj = &objects[i]; data = unpack_raw_entry(obj, &delta->base); @@ -419,7 +419,7 @@ static void parse_pack_objects(unsigned char *sha1) sha1_object(data, obj->size, obj->type, obj->idx.sha1); free(data); if (verbose) - display_progress(&progress, i+1); + display_progress(progress, i+1); } objects[i].idx.offset = consumed_bytes; if (verbose) @@ -455,7 +455,7 @@ static void parse_pack_objects(unsigned char *sha1) * for some more deltas. */ if (verbose) - start_progress(&progress, "Resolving deltas", nr_deltas); + progress = start_progress("Resolving deltas", nr_deltas); for (i = 0; i < nr_objects; i++) { struct object_entry *obj = &objects[i]; union delta_base base; @@ -487,7 +487,7 @@ static void parse_pack_objects(unsigned char *sha1) } free(data); if (verbose) - display_progress(&progress, nr_resolved_deltas); + display_progress(progress, nr_resolved_deltas); } } @@ -595,7 +595,7 @@ static void fix_unresolved_deltas(int nr_unresolved) append_obj_to_pack(d->base.sha1, data, size, type); free(data); if (verbose) - display_progress(&progress, nr_resolved_deltas); + display_progress(progress, nr_resolved_deltas); } free(sorted_by_pos); } diff --git a/progress.c b/progress.c index 7629e0572b..c342e39c5d 100644 --- a/progress.c +++ b/progress.c @@ -1,6 +1,15 @@ #include "git-compat-util.h" #include "progress.h" +struct progress { + const char *title; + int last_value; + unsigned total; + unsigned last_percent; + unsigned delay; + unsigned delayed_percent_treshold; +}; + static volatile sig_atomic_t progress_update; static void progress_interval(int signum) @@ -76,12 +85,18 @@ static int display(struct progress *progress, unsigned n, int done) int display_progress(struct progress *progress, unsigned n) { - return display(progress, n, 0); + return progress ? display(progress, n, 0) : 0; } -void start_progress_delay(struct progress *progress, const char *title, - unsigned total, unsigned percent_treshold, unsigned delay) +struct progress *start_progress_delay(const char *title, unsigned total, + unsigned percent_treshold, unsigned delay) { + struct progress *progress = malloc(sizeof(*progress)); + if (!progress) { + /* unlikely, but here's a good fallback */ + fprintf(stderr, "%s...\n", title); + return NULL; + } progress->title = title; progress->total = total; progress->last_value = -1; @@ -89,19 +104,25 @@ void start_progress_delay(struct progress *progress, const char *title, progress->delayed_percent_treshold = percent_treshold; progress->delay = delay; set_progress_signal(); + return progress; } -void start_progress(struct progress *progress, const char *title, unsigned total) +struct progress *start_progress(const char *title, unsigned total) { - start_progress_delay(progress, title, total, 0, 0); + return start_progress_delay(title, total, 0, 0); } -void stop_progress(struct progress *progress) +void stop_progress(struct progress **p_progress) { + struct progress *progress = *p_progress; + if (!progress) + return; + *p_progress = NULL; if (progress->last_value != -1) { /* Force the last update */ progress_update = 1; display(progress, progress->last_value, 1); } clear_progress_signal(); + free(progress); } diff --git a/progress.h b/progress.h index 07b56bdbb5..4c6d53524b 100644 --- a/progress.h +++ b/progress.h @@ -1,20 +1,12 @@ #ifndef PROGRESS_H #define PROGRESS_H -struct progress { - const char *title; - int last_value; - unsigned total; - unsigned last_percent; - unsigned delay; - unsigned delayed_percent_treshold; -}; +struct progress; int display_progress(struct progress *progress, unsigned n); -void start_progress(struct progress *progress, const char *title, - unsigned total); -void start_progress_delay(struct progress *progress, const char *title, - unsigned total, unsigned percent_treshold, unsigned delay); -void stop_progress(struct progress *progress); +struct progress *start_progress(const char *title, unsigned total); +struct progress *start_progress_delay(const char *title, unsigned total, + unsigned percent_treshold, unsigned delay); +void stop_progress(struct progress **progress); #endif diff --git a/unpack-trees.c b/unpack-trees.c index 32251018b2..6776c29cde 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -297,7 +297,7 @@ static void check_updates(struct cache_entry **src, int nr, { unsigned short mask = htons(CE_UPDATE); unsigned cnt = 0, total = 0; - struct progress progress; + struct progress *progress = NULL; char last_symlink[PATH_MAX]; if (o->update && o->verbose_update) { @@ -307,8 +307,8 @@ static void check_updates(struct cache_entry **src, int nr, total++; } - start_progress_delay(&progress, "Checking out files", - total, 50, 2); + progress = start_progress_delay("Checking out files", + total, 50, 2); cnt = 0; } @@ -318,7 +318,7 @@ static void check_updates(struct cache_entry **src, int nr, if (total) if (!ce->ce_mode || ce->ce_flags & mask) - display_progress(&progress, ++cnt); + display_progress(progress, ++cnt); if (!ce->ce_mode) { if (o->update) unlink_entry(ce->name, last_symlink); @@ -333,7 +333,7 @@ static void check_updates(struct cache_entry **src, int nr, } } if (total) - stop_progress(&progress);; + stop_progress(&progress); } int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options *o) From 4d4fcc5451d9d653bebcc8afa18543cb426abeed Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 30 Oct 2007 14:57:33 -0400 Subject: [PATCH 0351/1490] relax usage of the progress API Since it is now OK to pass a null pointer to display_progress() and stop_progress() resulting in a no-op, then we can simplify the code and remove a bunch of lines by not making those calls conditional all the time. Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- builtin-pack-objects.c | 18 ++++++------------ builtin-prune-packed.c | 6 ++---- builtin-unpack-objects.c | 6 ++---- index-pack.c | 20 +++++++------------- unpack-trees.c | 8 +++----- 5 files changed, 20 insertions(+), 38 deletions(-) diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index 3ca5cc7800..52a26a28f4 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -629,8 +629,7 @@ static void write_pack_file(void) if (!offset_one) break; offset = offset_one; - if (do_progress) - display_progress(progress_state, written); + display_progress(progress_state, written); } /* @@ -684,8 +683,7 @@ static void write_pack_file(void) } while (nr_remaining && i < nr_objects); free(written_list); - if (do_progress) - stop_progress(&progress_state); + stop_progress(&progress_state); if (written != nr_result) die("wrote %u objects while expecting %u", written, nr_result); /* @@ -853,8 +851,7 @@ static int add_object_entry(const unsigned char *sha1, enum object_type type, else object_ix[-1 - ix] = nr_objects; - if (progress) - display_progress(progress_state, nr_objects); + display_progress(progress_state, nr_objects); if (name && no_try_delta(name)) entry->no_try_delta = 1; @@ -1517,8 +1514,7 @@ static void find_deltas(struct object_entry **list, unsigned list_size, progress_lock(); (*processed)++; - if (progress) - display_progress(progress_state, *processed); + display_progress(progress_state, *processed); progress_unlock(); /* @@ -1722,8 +1718,7 @@ static void prepare_pack(int window, int depth) nr_deltas); qsort(delta_list, n, sizeof(*delta_list), type_size_sort); ll_find_deltas(delta_list, n, window+1, depth, &nr_done); - if (progress) - stop_progress(&progress_state); + stop_progress(&progress_state); if (nr_done != nr_deltas) die("inconsistency with delta count"); } @@ -2142,8 +2137,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) rp_av[rp_ac] = NULL; get_object_list(rp_ac, rp_av); } - if (progress) - stop_progress(&progress_state); + stop_progress(&progress_state); if (non_empty && !nr_result) return 0; diff --git a/builtin-prune-packed.c b/builtin-prune-packed.c index c66fb037f6..f4287dad10 100644 --- a/builtin-prune-packed.c +++ b/builtin-prune-packed.c @@ -15,8 +15,7 @@ static void prune_dir(int i, DIR *dir, char *pathname, int len, int opts) struct dirent *de; char hex[40]; - if (opts == VERBOSE) - display_progress(progress, i + 1); + display_progress(progress, i + 1); sprintf(hex, "%02x", i); while ((de = readdir(dir)) != NULL) { @@ -64,8 +63,7 @@ void prune_packed_objects(int opts) prune_dir(i, d, pathname, len + 3, opts); closedir(d); } - if (opts == VERBOSE) - stop_progress(&progress); + stop_progress(&progress); } int cmd_prune_packed(int argc, const char **argv, const char *prefix) diff --git a/builtin-unpack-objects.c b/builtin-unpack-objects.c index e0ecbc51a7..1e51865c52 100644 --- a/builtin-unpack-objects.c +++ b/builtin-unpack-objects.c @@ -326,11 +326,9 @@ static void unpack_all(void) obj_list = xmalloc(nr_objects * sizeof(*obj_list)); for (i = 0; i < nr_objects; i++) { unpack_one(i); - if (!quiet) - display_progress(progress, i + 1); + display_progress(progress, i + 1); } - if (!quiet) - stop_progress(&progress); + stop_progress(&progress); if (delta_list) die("unresolved deltas left after unpacking"); diff --git a/index-pack.c b/index-pack.c index b4543a4cc2..879ea15485 100644 --- a/index-pack.c +++ b/index-pack.c @@ -418,12 +418,10 @@ static void parse_pack_objects(unsigned char *sha1) } else sha1_object(data, obj->size, obj->type, obj->idx.sha1); free(data); - if (verbose) - display_progress(progress, i+1); + display_progress(progress, i+1); } objects[i].idx.offset = consumed_bytes; - if (verbose) - stop_progress(&progress); + stop_progress(&progress); /* Check pack integrity */ flush(); @@ -486,8 +484,7 @@ static void parse_pack_objects(unsigned char *sha1) obj->size, obj->type); } free(data); - if (verbose) - display_progress(progress, nr_resolved_deltas); + display_progress(progress, nr_resolved_deltas); } } @@ -594,8 +591,7 @@ static void fix_unresolved_deltas(int nr_unresolved) die("local object %s is corrupt", sha1_to_hex(d->base.sha1)); append_obj_to_pack(d->base.sha1, data, size, type); free(data); - if (verbose) - display_progress(progress, nr_resolved_deltas); + display_progress(progress, nr_resolved_deltas); } free(sorted_by_pos); } @@ -774,8 +770,7 @@ int main(int argc, char **argv) deltas = xmalloc(nr_objects * sizeof(struct delta_entry)); parse_pack_objects(sha1); if (nr_deltas == nr_resolved_deltas) { - if (verbose) - stop_progress(&progress); + stop_progress(&progress); /* Flush remaining pack final 20-byte SHA1. */ flush(); } else { @@ -788,11 +783,10 @@ int main(int argc, char **argv) (nr_objects + nr_unresolved + 1) * sizeof(*objects)); fix_unresolved_deltas(nr_unresolved); - if (verbose) { - stop_progress(&progress); + stop_progress(&progress); + if (verbose) fprintf(stderr, "%d objects were added to complete this thin pack.\n", nr_objects - nr_objects_initial); - } fixup_pack_header_footer(output_fd, sha1, curr_pack, nr_objects); } diff --git a/unpack-trees.c b/unpack-trees.c index 6776c29cde..c527d7d049 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -316,9 +316,8 @@ static void check_updates(struct cache_entry **src, int nr, while (nr--) { struct cache_entry *ce = *src++; - if (total) - if (!ce->ce_mode || ce->ce_flags & mask) - display_progress(progress, ++cnt); + if (!ce->ce_mode || ce->ce_flags & mask) + display_progress(progress, ++cnt); if (!ce->ce_mode) { if (o->update) unlink_entry(ce->name, last_symlink); @@ -332,8 +331,7 @@ static void check_updates(struct cache_entry **src, int nr, } } } - if (total) - stop_progress(&progress); + stop_progress(&progress); } int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options *o) From cf84d51c43fa05cce416bfa3f5db3ad70773abdf Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 30 Oct 2007 14:57:34 -0400 Subject: [PATCH 0352/1490] add throughput to progress display This adds the ability for the progress code to also display transfer throughput when that makes sense. The math was inspired by commit c548cf4ee0737a321ffe94f6a97c65baf87281be from Linus. Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- progress.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++--- progress.h | 1 + 2 files changed, 77 insertions(+), 4 deletions(-) diff --git a/progress.c b/progress.c index c342e39c5d..15197fbe6c 100644 --- a/progress.c +++ b/progress.c @@ -1,6 +1,19 @@ #include "git-compat-util.h" #include "progress.h" +#define TP_IDX_MAX 8 + +struct throughput { + struct timeval prev_tv; + unsigned long count; + unsigned long avg_bytes; + unsigned long last_bytes[TP_IDX_MAX]; + unsigned int avg_misecs; + unsigned int last_misecs[TP_IDX_MAX]; + unsigned int idx; + char display[20]; +}; + struct progress { const char *title; int last_value; @@ -8,6 +21,7 @@ struct progress { unsigned last_percent; unsigned delay; unsigned delayed_percent_treshold; + struct throughput *throughput; }; static volatile sig_atomic_t progress_update; @@ -46,7 +60,7 @@ static void clear_progress_signal(void) static int display(struct progress *progress, unsigned n, int done) { - char *eol; + char *eol, *tp; if (progress->delay) { if (!progress_update || --progress->delay) @@ -64,18 +78,20 @@ static int display(struct progress *progress, unsigned n, int done) } progress->last_value = n; + tp = (progress->throughput) ? progress->throughput->display : ""; eol = done ? ", done. \n" : " \r"; if (progress->total) { unsigned percent = n * 100 / progress->total; if (percent != progress->last_percent || progress_update) { progress->last_percent = percent; - fprintf(stderr, "%s: %3u%% (%u/%u)%s", progress->title, - percent, n, progress->total, eol); + fprintf(stderr, "%s: %3u%% (%u/%u)%s%s", + progress->title, percent, n, + progress->total, tp, eol); progress_update = 0; return 1; } } else if (progress_update) { - fprintf(stderr, "%s: %u%s", progress->title, n, eol); + fprintf(stderr, "%s: %u%s%s", progress->title, n, tp, eol); progress_update = 0; return 1; } @@ -83,6 +99,60 @@ static int display(struct progress *progress, unsigned n, int done) return 0; } +void display_throughput(struct progress *progress, unsigned long n) +{ + struct throughput *tp; + struct timeval tv; + unsigned int misecs; + + if (!progress) + return; + tp = progress->throughput; + + gettimeofday(&tv, NULL); + + if (!tp) { + progress->throughput = tp = calloc(1, sizeof(*tp)); + if (tp) + tp->prev_tv = tv; + return; + } + + tp->count += n; + + /* + * We have x = bytes and y = microsecs. We want z = KiB/s: + * + * z = (x / 1024) / (y / 1000000) + * z = x / y * 1000000 / 1024 + * z = x / (y * 1024 / 1000000) + * z = x / y' + * + * To simplify things we'll keep track of misecs, or 1024th of a sec + * obtained with: + * + * y' = y * 1024 / 1000000 + * y' = y / (1000000 / 1024) + * y' = y / 977 + */ + misecs = (tv.tv_sec - tp->prev_tv.tv_sec) * 1024; + misecs += (int)(tv.tv_usec - tp->prev_tv.tv_usec) / 977; + + if (misecs > 512) { + tp->prev_tv = tv; + tp->avg_bytes += tp->count; + tp->avg_misecs += misecs; + snprintf(tp->display, sizeof(tp->display), + ", %lu KiB/s", tp->avg_bytes / tp->avg_misecs); + tp->avg_bytes -= tp->last_bytes[tp->idx]; + tp->avg_misecs -= tp->last_misecs[tp->idx]; + tp->last_bytes[tp->idx] = tp->count; + tp->last_misecs[tp->idx] = misecs; + tp->idx = (tp->idx + 1) % TP_IDX_MAX; + tp->count = 0; + } +} + int display_progress(struct progress *progress, unsigned n) { return progress ? display(progress, n, 0) : 0; @@ -103,6 +173,7 @@ struct progress *start_progress_delay(const char *title, unsigned total, progress->last_percent = -1; progress->delayed_percent_treshold = percent_treshold; progress->delay = delay; + progress->throughput = NULL; set_progress_signal(); return progress; } @@ -124,5 +195,6 @@ void stop_progress(struct progress **p_progress) display(progress, progress->last_value, 1); } clear_progress_signal(); + free(progress->throughput); free(progress); } diff --git a/progress.h b/progress.h index 4c6d53524b..61cb68dfa5 100644 --- a/progress.h +++ b/progress.h @@ -3,6 +3,7 @@ struct progress; +void display_throughput(struct progress *progress, unsigned long n); int display_progress(struct progress *progress, unsigned n); struct progress *start_progress(const char *title, unsigned total); struct progress *start_progress_delay(const char *title, unsigned total, From 29e63ed3f6962cd96f7153e9f492f36797d25c33 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 30 Oct 2007 14:57:35 -0400 Subject: [PATCH 0353/1490] add throughput display to index-pack ... and call it "Receiving objects" when over stdin to look clearer to end users. Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- index-pack.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/index-pack.c b/index-pack.c index 879ea15485..61ea7621be 100644 --- a/index-pack.c +++ b/index-pack.c @@ -87,6 +87,8 @@ static void *fill(int min) die("early EOF"); die("read error on input: %s", strerror(errno)); } + if (from_stdin) + display_throughput(progress, ret); input_len += ret; } while (input_len < min); return input_buffer; @@ -406,7 +408,9 @@ static void parse_pack_objects(unsigned char *sha1) * - remember base (SHA1 or offset) for all deltas. */ if (verbose) - progress = start_progress("Indexing objects", nr_objects); + progress = start_progress( + from_stdin ? "Receiving objects" : "Indexing objects", + nr_objects); for (i = 0; i < nr_objects; i++) { struct object_entry *obj = &objects[i]; data = unpack_raw_entry(obj, &delta->base); From 74b6792f7b2d4b410459cf96977a2007ddea8675 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 30 Oct 2007 15:41:13 -0400 Subject: [PATCH 0354/1490] add some copyright notice to the progress display code Some self patting on the back to keep my ego alive. Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- progress.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/progress.c b/progress.c index 15197fbe6c..34a59611fb 100644 --- a/progress.c +++ b/progress.c @@ -1,3 +1,13 @@ +/* + * Simple text-based progress display module for GIT + * + * Copyright (c) 2007 by Nicolas Pitre + * + * This code is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + #include "git-compat-util.h" #include "progress.h" From 2a128d63dc140e8daeaf68659d9263b7389b7d1b Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 30 Oct 2007 17:06:21 -0400 Subject: [PATCH 0355/1490] add throughput display to git-push This one triggers only when git-pack-objects is called with --all-progress and --stdout which is the combination used by git-push. Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- builtin-pack-objects.c | 2 +- csum-file.c | 8 ++++++++ csum-file.h | 4 ++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index 52a26a28f4..25ec65d0f0 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -606,7 +606,7 @@ static void write_pack_file(void) char *pack_tmp_name = NULL; if (pack_to_stdout) { - f = sha1fd(1, ""); + f = sha1fd_throughput(1, "", progress_state); } else { char tmpname[PATH_MAX]; int fd; diff --git a/csum-file.c b/csum-file.c index 9929991dea..3729e73e19 100644 --- a/csum-file.c +++ b/csum-file.c @@ -8,6 +8,7 @@ * able to verify hasn't been messed with afterwards. */ #include "cache.h" +#include "progress.h" #include "csum-file.h" static void sha1flush(struct sha1file *f, unsigned int count) @@ -17,6 +18,7 @@ static void sha1flush(struct sha1file *f, unsigned int count) for (;;) { int ret = xwrite(f->fd, buf, count); if (ret > 0) { + display_throughput(f->tp, ret); buf = (char *) buf + ret; count -= ret; if (count) @@ -79,6 +81,11 @@ int sha1write(struct sha1file *f, void *buf, unsigned int count) } struct sha1file *sha1fd(int fd, const char *name) +{ + return sha1fd_throughput(fd, name, NULL); +} + +struct sha1file *sha1fd_throughput(int fd, const char *name, struct progress *tp) { struct sha1file *f; unsigned len; @@ -94,6 +101,7 @@ struct sha1file *sha1fd(int fd, const char *name) f->fd = fd; f->error = 0; f->offset = 0; + f->tp = tp; f->do_crc = 0; SHA1_Init(&f->ctx); return f; diff --git a/csum-file.h b/csum-file.h index c3c792f1b5..4d1b231292 100644 --- a/csum-file.h +++ b/csum-file.h @@ -1,11 +1,14 @@ #ifndef CSUM_FILE_H #define CSUM_FILE_H +struct progress; + /* A SHA1-protected file */ struct sha1file { int fd, error; unsigned int offset, namelen; SHA_CTX ctx; + struct progress *tp; char name[PATH_MAX]; int do_crc; uint32_t crc32; @@ -13,6 +16,7 @@ struct sha1file { }; extern struct sha1file *sha1fd(int fd, const char *name); +extern struct sha1file *sha1fd_throughput(int fd, const char *name, struct progress *tp); extern int sha1close(struct sha1file *, unsigned char *, int); extern int sha1write(struct sha1file *, void *, unsigned int); extern void crc32_begin(struct sha1file *); From dd46b9b95b853328e7ff1c11b7f5cae68751c79e Mon Sep 17 00:00:00 2001 From: Emil Medve Date: Tue, 30 Oct 2007 14:15:21 -0500 Subject: [PATCH 0356/1490] Fixed a command line option type for builtin-fsck.c The typo was introduced by 5ac0a2063e8f824f6e8ffb4d18de74c55aae7131 (Make builtin-fsck.c use parse_options.) Signed-off-by: Emil Medve Acked-by: Pierre Habouzit Signed-off-by: Junio C Hamano --- builtin-fsck.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin-fsck.c b/builtin-fsck.c index 64da3bd363..e4874f64a3 100644 --- a/builtin-fsck.c +++ b/builtin-fsck.c @@ -680,7 +680,7 @@ static struct option fsck_opts[] = { OPT_BOOLEAN(0, "cache", &keep_cache_objects, "make index objects head nodes"), OPT_BOOLEAN(0, "reflogs", &include_reflogs, "make reflogs head nodes (default)"), OPT_BOOLEAN(0, "full", &check_full, "also consider alternate objects"), - OPT_BOOLEAN(0, "struct", &check_strict, "enable more strict checking"), + OPT_BOOLEAN(0, "strict", &check_strict, "enable more strict checking"), OPT_BOOLEAN(0, "lost-found", &write_lost_and_found, "write dangling objects in .git/lost-found"), OPT_END(), From b6c9fb5100f8cd4081f1c6df5aea7335a11e9659 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 30 Oct 2007 11:30:43 -0700 Subject: [PATCH 0357/1490] Prevent send-pack from segfaulting (backport from 'master') 4491e62ae932d5774f628d1bd3be663c11058a73 (Prevent send-pack from segfaulting when a branch doesn't match) is hereby cherry-picked back to 'maint'. If we can't find a source match, and we have no destination, we need to abort the match function early before we try to match the destination against the remote. Signed-off-by: Junio C Hamano --- remote.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/remote.c b/remote.c index cdbbdcb00d..9a88917aab 100644 --- a/remote.c +++ b/remote.c @@ -504,8 +504,11 @@ static int match_explicit(struct ref *src, struct ref *dst, if (!matched_src) errs = 1; - if (dst_value == NULL) + if (!dst_value) { + if (!matched_src) + return errs; dst_value = matched_src->name; + } switch (count_refspec_match(dst_value, dst, &matched_dst)) { case 1: From dee48c3c7ed7f7a32a524e8a492c6bc4e3c1c78d Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 30 Oct 2007 11:54:11 -0700 Subject: [PATCH 0358/1490] git-merge: document but discourage the historical syntax Historically "git merge" took its command line arguments in a rather strange order. Document the historical syntax, and also document clearly that it is not encouraged in new scripts. There is no reason to deprecate the historical syntax, as the current code can sanely tell which syntax the caller is using, and existing scripts by people do use the historical syntax. Signed-off-by: Junio C Hamano --- Documentation/git-merge.txt | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt index eae49c4876..827838f7d0 100644 --- a/Documentation/git-merge.txt +++ b/Documentation/git-merge.txt @@ -11,26 +11,27 @@ SYNOPSIS [verse] 'git-merge' [-n] [--summary] [--no-commit] [--squash] [-s ]... [-m ] ... +'git-merge' HEAD ... DESCRIPTION ----------- This is the top-level interface to the merge machinery which drives multiple merge strategy scripts. +The second syntax ( `HEAD` ) is supported for +historical reasons. Do not use it from the command line or in +new scripts. It is the same as `git merge -m `. + OPTIONS ------- include::merge-options.txt[] -:: +-m :: The commit message to be used for the merge commit (in case it is created). The `git-fmt-merge-msg` script can be used to give a good default for automated `git-merge` invocations. -:: - Our branch head commit. This has to be `HEAD`, so new - syntax does not require it - :: Other branch head merged into our branch. You need at least one . Specifying more than one From ba17892ddc85c0ffe8fecd600c29cb38ec7e5587 Mon Sep 17 00:00:00 2001 From: Sergei Organov Date: Tue, 30 Oct 2007 22:54:02 +0300 Subject: [PATCH 0359/1490] core-tutorial: Use new syntax for git-merge. "git-merge HEAD " is still supported but we shouldn't encourage its use. Signed-off-by: Junio C Hamano --- Documentation/core-tutorial.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Documentation/core-tutorial.txt b/Documentation/core-tutorial.txt index 6b2590d072..df147b5e76 100644 --- a/Documentation/core-tutorial.txt +++ b/Documentation/core-tutorial.txt @@ -883,7 +883,7 @@ script called `git merge`, which wants to know which branches you want to resolve and what the merge is all about: ------------ -$ git merge "Merge work in mybranch" HEAD mybranch +$ git merge -m "Merge work in mybranch" mybranch ------------ where the first argument is going to be used as the commit message if @@ -970,7 +970,7 @@ to the `master` branch. Let's go back to `mybranch`, and run ------------ $ git checkout mybranch -$ git merge "Merge upstream changes." HEAD master +$ git merge -m "Merge upstream changes." master ------------ This outputs something like this (the actual commit object names @@ -1613,8 +1613,8 @@ in both of them. You could merge in 'diff-fix' first and then 'commit-fix' next, like this: ------------ -$ git merge 'Merge fix in diff-fix' master diff-fix -$ git merge 'Merge fix in commit-fix' master commit-fix +$ git merge -m 'Merge fix in diff-fix' diff-fix +$ git merge -m 'Merge fix in commit-fix' commit-fix ------------ Which would result in: From 04bd8e5fea48a00816b461b0fb934627cfd2c45f Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 30 Oct 2007 15:59:24 -0400 Subject: [PATCH 0360/1490] cherry-pick/revert: more compact user direction message A failed cherry-pick (and friend) currently says: |Automatic cherry-pick failed. After resolving the conflicts, |mark the corrected paths with 'git-add ' |and commit the result. This can obviously be displayed on two lines only. While at it, change "git-add" to "git add". Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- builtin-revert.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin-revert.c b/builtin-revert.c index 499bbe7343..eafafbc333 100644 --- a/builtin-revert.c +++ b/builtin-revert.c @@ -351,7 +351,7 @@ static int revert_or_cherry_pick(int argc, const char **argv) die ("Error wrapping up %s", defmsg); fprintf(stderr, "Automatic %s failed. " "After resolving the conflicts,\n" - "mark the corrected paths with 'git-add '\n" + "mark the corrected paths with 'git add ' " "and commit the result.\n", me); if (action == CHERRY_PICK) { fprintf(stderr, "When commiting, use the option " From 07b45f8c1754a13bca67f70b600bf51ba33cf98d Mon Sep 17 00:00:00 2001 From: Lars Hjemli Date: Tue, 25 Sep 2007 08:36:38 +0200 Subject: [PATCH 0361/1490] Make merge-recursive honor diff.renamelimit It might be a sign of source code management gone bad, but when two branches has diverged almost beyond recognition and time has come for the branches to merge, the user is going to need all the help his tool can give him. Honoring diff.renamelimit has great potential as a painkiller in such situations. The painkiller effect could have been achieved by e.g. 'merge.renamelimit', but the flexibility gained by a separate option is questionable: our user would probably expect git to detect renames equally good when merging as when diffing (I known I did). Signed-off-by: Lars Hjemli Signed-off-by: Junio C Hamano --- merge-recursive.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/merge-recursive.c b/merge-recursive.c index c2e1cb69e3..fedfff4aed 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -96,6 +96,7 @@ static struct path_list current_directory_set = {NULL, 0, 0, 1}; static int call_depth = 0; static int verbosity = 2; +static int rename_limit = -1; static int buffer_output = 1; static struct output_buffer *output_list, *output_end; @@ -372,6 +373,7 @@ static struct path_list *get_renames(struct tree *tree, diff_setup(&opts); opts.recursive = 1; opts.detect_rename = DIFF_DETECT_RENAME; + opts.rename_limit = rename_limit; opts.output_format = DIFF_FORMAT_NO_OUTPUT; if (diff_setup_done(&opts) < 0) die("diff setup failed"); @@ -1693,6 +1695,10 @@ static int merge_config(const char *var, const char *value) verbosity = git_config_int(var, value); return 0; } + if (!strcasecmp(var, "diff.renamelimit")) { + rename_limit = git_config_int(var, value); + return 0; + } return git_default_config(var, value); } From 3524b282dabd254fc50b186e35ea5c6f612aeb46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Steinbrink?= Date: Wed, 31 Oct 2007 03:20:30 +0100 Subject: [PATCH 0362/1490] Fix --strategy parsing in git-rebase--interactive.sh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For the --strategy/-s option, git-rebase--interactive.sh dropped the parameter which it was trying to parse. Signed-off-by: Björn Steinbrink Acked-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- git-rebase--interactive.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh index 50b79ff8ff..ebc67e515d 100755 --- a/git-rebase--interactive.sh +++ b/git-rebase--interactive.sh @@ -357,7 +357,6 @@ do output git reset --hard && do_rest ;; -s|--strategy) - shift case "$#,$1" in *,*=*) STRATEGY="-s `expr "z$1" : 'z-[^=]*=\(.*\)'`" ;; From 2a9c53e03d8293577b5163910f178075725b39dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Steinbrink?= Date: Wed, 31 Oct 2007 03:20:31 +0100 Subject: [PATCH 0363/1490] git-rebase--interactive.sh: Don't pass a strategy to git-cherry-pick. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-cherry-pick doesn't support a strategy paramter, so don't pass one. This means that --strategy for interactive rebases is a no-op for anything but merge commits, but that's still better than being broken. A correct fix would probably need to port the --merge behaviour from plain git-rebase.sh, but I have no clue how to integrate that cleanly. Signed-off-by: Björn Steinbrink Acked-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- git-rebase--interactive.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh index ebc67e515d..db04057653 100755 --- a/git-rebase--interactive.sh +++ b/git-rebase--interactive.sh @@ -109,7 +109,7 @@ pick_one () { sha1=$(git rev-parse --short $sha1) output warn Fast forward to $sha1 else - output git cherry-pick $STRATEGY "$@" + output git cherry-pick "$@" fi } @@ -173,7 +173,7 @@ pick_one_preserving_merges () { fi ;; *) - output git cherry-pick $STRATEGY "$@" || + output git cherry-pick "$@" || die_with_patch $sha1 "Could not pick $sha1" esac esac From f91333d646e690d9a10717c96e166a069b2bb586 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Steinbrink?= Date: Wed, 31 Oct 2007 03:20:32 +0100 Subject: [PATCH 0364/1490] git-rebase--interactive.sh: Make 3-way merge strategies work for -p. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-rebase--interactive.sh used to pass all parents of a merge commit to git-merge, which means that we have at least 3 heads to merge: HEAD, first parent and second parent. So 3-way merge strategies like recursive wouldn't work. Fortunately, we have checked out the first parent right before the merge anyway, so that is HEAD. Therefore we can drop simply it from the list of parents, making 3-way strategies work for merge commits with only two parents. Signed-off-by: Björn Steinbrink Acked-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- git-rebase--interactive.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh index db04057653..f28c3df204 100755 --- a/git-rebase--interactive.sh +++ b/git-rebase--interactive.sh @@ -165,6 +165,8 @@ pick_one_preserving_merges () { eval "$author_script" msg="$(git cat-file commit $sha1 | \ sed -e '1,/^$/d' -e "s/[\"\\]/\\\\&/g")" + # No point in merging the first parent, that's HEAD + new_parents=${new_parents# $first_parent} # NEEDSWORK: give rerere a chance if ! output git merge $STRATEGY -m "$msg" $new_parents then From 0bdb5af7a571ee2bd71550a545632b1cb7f8f8f3 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 30 Oct 2007 21:32:49 -0700 Subject: [PATCH 0365/1490] Update GIT 1.5.3.5 Release Notes Signed-off-by: Junio C Hamano --- Documentation/RelNotes-1.5.3.5.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Documentation/RelNotes-1.5.3.5.txt b/Documentation/RelNotes-1.5.3.5.txt index e28d92f618..bf6a279ede 100644 --- a/Documentation/RelNotes-1.5.3.5.txt +++ b/Documentation/RelNotes-1.5.3.5.txt @@ -87,8 +87,14 @@ Fixes since v1.5.3.4 * A few workarounds to squelch false warnings from recent gcc have been added. + * "git-send-pack $remote frotz" segfaulted when there is nothing + named 'frotz' on the local end. + + * "git-rebase -interactive" did not handle its "--strategy" option + properly. + -- exec >/var/tmp/1 -O=v1.5.3.4-55-gf120ae2 +O=v1.5.3.4-65-gf91333d echo O=`git describe refs/heads/maint` git shortlog --no-merges $O..refs/heads/maint From fee9832a8dea5d9c98c5c3a4797615d52814df16 Mon Sep 17 00:00:00 2001 From: Gerrit Pape Date: Tue, 30 Oct 2007 14:24:27 +0000 Subject: [PATCH 0366/1490] No longer install git-svnimport, move to contrib/examples This has been proposed for a few times without much reaction from the list. Actually remove it to see who screams. Signed-off-by: Gerrit Pape Signed-off-by: Junio C Hamano --- .gitignore | 1 - Documentation/cmd-list.perl | 1 - Makefile | 3 +-- contrib/completion/git-completion.bash | 1 - git-svnimport.perl => contrib/examples/git-svnimport.perl | 0 {Documentation => contrib/examples}/git-svnimport.txt | 0 6 files changed, 1 insertion(+), 5 deletions(-) rename git-svnimport.perl => contrib/examples/git-svnimport.perl (100%) rename {Documentation => contrib/examples}/git-svnimport.txt (100%) diff --git a/.gitignore b/.gitignore index 62afef2347..8670081adf 100644 --- a/.gitignore +++ b/.gitignore @@ -128,7 +128,6 @@ git-status git-stripspace git-submodule git-svn -git-svnimport git-symbolic-ref git-tag git-tar-tree diff --git a/Documentation/cmd-list.perl b/Documentation/cmd-list.perl index 1061fd8bcd..8d21d423e5 100755 --- a/Documentation/cmd-list.perl +++ b/Documentation/cmd-list.perl @@ -185,7 +185,6 @@ sub format_one { git-stripspace purehelpers git-submodule mainporcelain git-svn foreignscminterface -git-svnimport foreignscminterface git-symbolic-ref plumbingmanipulators git-tag mainporcelain git-tar-tree plumbinginterrogators diff --git a/Makefile b/Makefile index 72f5ef43ce..eb98d91bdf 100644 --- a/Makefile +++ b/Makefile @@ -225,8 +225,7 @@ SCRIPT_SH = \ SCRIPT_PERL = \ git-add--interactive.perl \ git-archimport.perl git-cvsimport.perl git-relink.perl \ - git-cvsserver.perl git-remote.perl \ - git-svnimport.perl git-cvsexportcommit.perl \ + git-cvsserver.perl git-remote.perl git-cvsexportcommit.perl \ git-send-email.perl git-svn.perl SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \ diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash index e760930740..599b2fc571 100755 --- a/contrib/completion/git-completion.bash +++ b/contrib/completion/git-completion.bash @@ -346,7 +346,6 @@ __git_commands () ssh-*) : transport;; stripspace) : plumbing;; svn) : import export;; - svnimport) : import;; symbolic-ref) : plumbing;; tar-tree) : deprecated;; unpack-file) : plumbing;; diff --git a/git-svnimport.perl b/contrib/examples/git-svnimport.perl similarity index 100% rename from git-svnimport.perl rename to contrib/examples/git-svnimport.perl diff --git a/Documentation/git-svnimport.txt b/contrib/examples/git-svnimport.txt similarity index 100% rename from Documentation/git-svnimport.txt rename to contrib/examples/git-svnimport.txt From 3f2a7ae2c84c921e11041a5edc2522964fc1cce5 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 31 Oct 2007 12:20:05 -0700 Subject: [PATCH 0367/1490] GIT 1.5.3.5 Signed-off-by: Junio C Hamano --- Documentation/RelNotes-1.5.3.5.txt | 6 ------ GIT-VERSION-GEN | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/Documentation/RelNotes-1.5.3.5.txt b/Documentation/RelNotes-1.5.3.5.txt index bf6a279ede..4e46d2c2a2 100644 --- a/Documentation/RelNotes-1.5.3.5.txt +++ b/Documentation/RelNotes-1.5.3.5.txt @@ -92,9 +92,3 @@ Fixes since v1.5.3.4 * "git-rebase -interactive" did not handle its "--strategy" option properly. - --- -exec >/var/tmp/1 -O=v1.5.3.4-65-gf91333d -echo O=`git describe refs/heads/maint` -git shortlog --no-merges $O..refs/heads/maint diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 223c4f5e14..88a4acad15 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v1.5.3.4.GIT +DEF_VER=v1.5.3.5.GIT LF=' ' From f94872dfc18c2670c9eb4ed8528ba45943213f39 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Tue, 30 Oct 2007 11:24:37 +0000 Subject: [PATCH 0368/1490] po2msg: ignore entries marked with "fuzzy" As Christian Stimming pointed out, entries which are "fuzzy" need to be checked by human translators, and cannot be used. Signed-off-by: Johannes Schindelin Signed-off-by: Shawn O. Pearce --- po/po2msg.sh | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/po/po2msg.sh b/po/po2msg.sh index da0765dd80..48a2669967 100644 --- a/po/po2msg.sh +++ b/po/po2msg.sh @@ -48,12 +48,16 @@ for {set i 1} {$i < $argc} {incr i} { } proc flush_msg {} { - global msgid msgstr mode lang out + global msgid msgstr mode lang out fuzzy if {![info exists msgid] || $mode == ""} { return } set mode "" + if {$fuzzy == 1} { + set fuzzy 0 + return + } if {$msgid == ""} { set prefix "set ::msgcat::header" @@ -64,6 +68,7 @@ proc flush_msg {} { puts $out "$prefix \"[u2a $msgstr]\"" } +set fuzzy 0 foreach file $files { regsub "^.*/\(\[^/\]*\)\.po$" $file "$output_directory\\1.msg" outfile set in [open $file "r"] @@ -73,7 +78,11 @@ foreach file $files { set mode "" while {[gets $in line] >= 0} { if {[regexp "^#" $line]} { - flush_msg + if {[regexp ", fuzzy" $line]} { + set fuzzy 1 + } else { + flush_msg + } continue } elseif {[regexp "^msgid \"(.*)\"$" $line dummy match]} { flush_msg From 9a25ae82dd635957e40e2d29ea5022d25fb6c2b0 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Tue, 30 Oct 2007 11:24:53 +0000 Subject: [PATCH 0369/1490] po2msg: ignore untranslated messages Do not generate translations when the translated message is empty. Signed-off-by: Johannes Schindelin Signed-off-by: Shawn O. Pearce --- po/po2msg.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/po/po2msg.sh b/po/po2msg.sh index 48a2669967..91d420b4fb 100644 --- a/po/po2msg.sh +++ b/po/po2msg.sh @@ -62,6 +62,9 @@ proc flush_msg {} { if {$msgid == ""} { set prefix "set ::msgcat::header" } else { + if {$msgstr == ""} { + return + } set prefix "::msgcat::mcset $lang \"[u2a $msgid]\"" } From 95a8b67c2642c576f848005e72126fb25d11286c Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Tue, 30 Oct 2007 11:25:31 +0000 Subject: [PATCH 0370/1490] po2msg: actually output statistics The "--statistics" option was ignored so far; no longer. Now we have a message similar to that of msgfmt. (Untranslated, though ;-) Signed-off-by: Johannes Schindelin Signed-off-by: Shawn O. Pearce --- po/po2msg.sh | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/po/po2msg.sh b/po/po2msg.sh index 91d420b4fb..c63248e375 100644 --- a/po/po2msg.sh +++ b/po/po2msg.sh @@ -26,11 +26,17 @@ proc u2a {s} { set output_directory "." set lang "dummy" set files [list] +set show_statistics 0 # parse options -for {set i 1} {$i < $argc} {incr i} { +for {set i 0} {$i < $argc} {incr i} { set arg [lindex $argv $i] - if {$arg == "--statistics" || $arg == "--tcl"} { + if {$arg == "--statistics"} { + incr show_statistics + continue + } + if {$arg == "--tcl"} { + # we know continue } if {$arg == "-l"} { @@ -49,12 +55,14 @@ for {set i 1} {$i < $argc} {incr i} { proc flush_msg {} { global msgid msgstr mode lang out fuzzy + global translated_count fuzzy_count not_translated_count if {![info exists msgid] || $mode == ""} { return } set mode "" if {$fuzzy == 1} { + incr fuzzy_count set fuzzy 0 return } @@ -63,15 +71,20 @@ proc flush_msg {} { set prefix "set ::msgcat::header" } else { if {$msgstr == ""} { + incr not_translated_count return } set prefix "::msgcat::mcset $lang \"[u2a $msgid]\"" + incr translated_count } puts $out "$prefix \"[u2a $msgstr]\"" } set fuzzy 0 +set translated_count 0 +set fuzzy_count 0 +set not_translated_count 0 foreach file $files { regsub "^.*/\(\[^/\]*\)\.po$" $file "$output_directory\\1.msg" outfile set in [open $file "r"] @@ -113,3 +126,8 @@ foreach file $files { close $out } +if {$show_statistics} { + puts [concat "$translated_count translated messages, " \ + "$fuzzy_count fuzzy ones, " \ + "$not_translated_count untranslated ones."] +} From efb848666cd45be5bc213785bedc772969fb3da0 Mon Sep 17 00:00:00 2001 From: Alex Riesen Date: Wed, 31 Oct 2007 22:16:17 +0100 Subject: [PATCH 0371/1490] Updated russian translation of git-gui Fixed some spelling mistakes. Signed-off-by: Shawn O. Pearce --- po/ru.po | 516 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 292 insertions(+), 224 deletions(-) diff --git a/po/ru.po b/po/ru.po index b8e9447942..6727a832ea 100644 --- a/po/ru.po +++ b/po/ru.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: git-gui\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2007-10-10 04:04-0400\n" +"POT-Creation-Date: 2007-10-31 21:23+0100\n" "PO-Revision-Date: 2007-10-22 22:30-0200\n" "Last-Translator: Alex Riesen \n" "Language-Team: Russian Translation \n" @@ -15,33 +15,33 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: git-gui.sh:41 git-gui.sh:634 git-gui.sh:648 git-gui.sh:661 git-gui.sh:744 -#: git-gui.sh:763 +#: git-gui.sh:41 git-gui.sh:597 git-gui.sh:611 git-gui.sh:624 git-gui.sh:707 +#: git-gui.sh:726 msgid "git-gui: fatal error" msgstr "git-gui: критическая ошибка" -#: git-gui.sh:595 +#: git-gui.sh:558 #, tcl-format msgid "Invalid font specified in %s:" msgstr "В %s установлен неверный шрифт:" -#: git-gui.sh:620 +#: git-gui.sh:583 msgid "Main Font" msgstr "Шрифт интерфейса" -#: git-gui.sh:621 +#: git-gui.sh:584 msgid "Diff/Console Font" msgstr "Шрифт консоли и изменений (diff)" -#: git-gui.sh:635 +#: git-gui.sh:598 msgid "Cannot find git in PATH." msgstr "git не найден в PATH." -#: git-gui.sh:662 +#: git-gui.sh:625 msgid "Cannot parse Git version string:" msgstr "Невозможно распознать строку версии Git: " -#: git-gui.sh:680 +#: git-gui.sh:643 #, tcl-format msgid "" "Git version cannot be determined.\n" @@ -59,79 +59,79 @@ msgstr "" "\n" "Принять '%s' как версию 1.5.0?\n" -#: git-gui.sh:853 +#: git-gui.sh:881 msgid "Git directory not found:" msgstr "Каталог Git не найден:" -#: git-gui.sh:860 +#: git-gui.sh:888 msgid "Cannot move to top of working directory:" msgstr "Невозможно перейти к корню рабочего каталога репозитория: " -#: git-gui.sh:867 +#: git-gui.sh:895 msgid "Cannot use funny .git directory:" msgstr "Каталог.git испорчен: " -#: git-gui.sh:872 +#: git-gui.sh:900 msgid "No working directory" msgstr "Отсутствует рабочий каталог" -#: git-gui.sh:1019 +#: git-gui.sh:1047 msgid "Refreshing file status..." msgstr "Обновление информации о состоянии файлов..." -#: git-gui.sh:1084 +#: git-gui.sh:1112 msgid "Scanning for modified files ..." msgstr "Поиск измененных файлов..." -#: git-gui.sh:1259 lib/browser.tcl:245 +#: git-gui.sh:1287 lib/browser.tcl:245 msgid "Ready." msgstr "Готово." -#: git-gui.sh:1525 +#: git-gui.sh:1553 msgid "Unmodified" msgstr "Не изменено" -#: git-gui.sh:1527 +#: git-gui.sh:1555 msgid "Modified, not staged" msgstr "Изменено, не подготовлено" -#: git-gui.sh:1528 git-gui.sh:1533 +#: git-gui.sh:1556 git-gui.sh:1561 msgid "Staged for commit" msgstr "Подготовлено для сохранения" -#: git-gui.sh:1529 git-gui.sh:1534 +#: git-gui.sh:1557 git-gui.sh:1562 msgid "Portions staged for commit" msgstr "Части, подготовленные для сохранения" -#: git-gui.sh:1530 git-gui.sh:1535 +#: git-gui.sh:1558 git-gui.sh:1563 msgid "Staged for commit, missing" msgstr "Подготовлено для сохранения, отсутствует" -#: git-gui.sh:1532 +#: git-gui.sh:1560 msgid "Untracked, not staged" msgstr "Не отслеживается, не подготовлено" -#: git-gui.sh:1537 +#: git-gui.sh:1565 msgid "Missing" msgstr "Отсутствует" -#: git-gui.sh:1538 +#: git-gui.sh:1566 msgid "Staged for removal" msgstr "Подготовлено для удаления" -#: git-gui.sh:1539 +#: git-gui.sh:1567 msgid "Staged for removal, still present" msgstr "Подготовлено для удаления, еще не удалено" -#: git-gui.sh:1541 git-gui.sh:1542 git-gui.sh:1543 git-gui.sh:1544 +#: git-gui.sh:1569 git-gui.sh:1570 git-gui.sh:1571 git-gui.sh:1572 msgid "Requires merge resolution" msgstr "Требуется разрешение конфликта при объединении" -#: git-gui.sh:1579 +#: git-gui.sh:1607 msgid "Starting gitk... please wait..." msgstr "Запускается gitk... пожалуйста, ждите..." -#: git-gui.sh:1588 +#: git-gui.sh:1616 #, tcl-format msgid "" "Unable to start gitk:\n" @@ -142,296 +142,295 @@ msgstr "" "\n" "%s не существует" -#: git-gui.sh:1788 lib/choose_repository.tcl:32 +#: git-gui.sh:1816 lib/choose_repository.tcl:35 msgid "Repository" msgstr "Репозиторий" -#: git-gui.sh:1789 +#: git-gui.sh:1817 msgid "Edit" msgstr "Редактировать" -#: git-gui.sh:1791 lib/choose_rev.tcl:560 +#: git-gui.sh:1819 lib/choose_rev.tcl:560 msgid "Branch" msgstr "Ветвь" -#: git-gui.sh:1794 lib/choose_rev.tcl:547 +#: git-gui.sh:1822 lib/choose_rev.tcl:547 msgid "Commit@@noun" msgstr "Состояние" -#: git-gui.sh:1797 lib/merge.tcl:121 lib/merge.tcl:150 lib/merge.tcl:168 +#: git-gui.sh:1825 lib/merge.tcl:121 lib/merge.tcl:150 lib/merge.tcl:168 msgid "Merge" msgstr "Объединить" -#: git-gui.sh:1798 lib/choose_rev.tcl:556 +#: git-gui.sh:1826 lib/choose_rev.tcl:556 msgid "Remote" msgstr "Внешние репозитории" -#: git-gui.sh:1807 +#: git-gui.sh:1835 msgid "Browse Current Branch's Files" msgstr "Просмотреть файлы текущей ветви" -#: git-gui.sh:1811 +#: git-gui.sh:1839 msgid "Browse Branch Files..." msgstr "Показать файлы ветви..." -#: git-gui.sh:1816 +#: git-gui.sh:1844 msgid "Visualize Current Branch's History" msgstr "История текущей ветви наглядно" -#: git-gui.sh:1820 +#: git-gui.sh:1848 msgid "Visualize All Branch History" msgstr "История всех ветвей наглядно" -#: git-gui.sh:1827 +#: git-gui.sh:1855 #, tcl-format msgid "Browse %s's Files" msgstr "Показать файлы ветви %s" -#: git-gui.sh:1829 +#: git-gui.sh:1857 #, tcl-format msgid "Visualize %s's History" msgstr "История ветви %s наглядно" -#: git-gui.sh:1834 lib/database.tcl:27 lib/database.tcl:67 +#: git-gui.sh:1862 lib/database.tcl:27 lib/database.tcl:67 msgid "Database Statistics" msgstr "Статистика базы данных" -#: git-gui.sh:1837 lib/database.tcl:34 +#: git-gui.sh:1865 lib/database.tcl:34 msgid "Compress Database" msgstr "Сжать базу данных" -#: git-gui.sh:1840 +#: git-gui.sh:1868 msgid "Verify Database" msgstr "Проверить базу данных" -#: git-gui.sh:1847 git-gui.sh:1851 git-gui.sh:1855 lib/shortcut.tcl:9 -#: lib/shortcut.tcl:45 lib/shortcut.tcl:84 +#: git-gui.sh:1875 git-gui.sh:1879 git-gui.sh:1883 lib/shortcut.tcl:7 +#: lib/shortcut.tcl:39 lib/shortcut.tcl:71 msgid "Create Desktop Icon" msgstr "Создать ярлык на рабочем столе" -#: git-gui.sh:1860 lib/choose_repository.tcl:36 lib/choose_repository.tcl:95 +#: git-gui.sh:1888 lib/choose_repository.tcl:176 lib/choose_repository.tcl:184 msgid "Quit" msgstr "Выход" -#: git-gui.sh:1867 +#: git-gui.sh:1895 msgid "Undo" msgstr "Отменить" -#: git-gui.sh:1870 +#: git-gui.sh:1898 msgid "Redo" msgstr "Повторить" -#: git-gui.sh:1874 git-gui.sh:2366 +#: git-gui.sh:1902 git-gui.sh:2395 msgid "Cut" msgstr "Вырезать" -#: git-gui.sh:1877 git-gui.sh:2369 git-gui.sh:2440 git-gui.sh:2512 +#: git-gui.sh:1905 git-gui.sh:2398 git-gui.sh:2469 git-gui.sh:2541 #: lib/console.tcl:67 msgid "Copy" msgstr "Копировать" -#: git-gui.sh:1880 git-gui.sh:2372 +#: git-gui.sh:1908 git-gui.sh:2401 msgid "Paste" msgstr "Вставить" -#: git-gui.sh:1883 git-gui.sh:2375 lib/branch_delete.tcl:26 +#: git-gui.sh:1911 git-gui.sh:2404 lib/branch_delete.tcl:26 #: lib/remote_branch_delete.tcl:38 msgid "Delete" msgstr "Удалить" -#: git-gui.sh:1887 git-gui.sh:2379 git-gui.sh:2516 lib/console.tcl:69 +#: git-gui.sh:1915 git-gui.sh:2408 git-gui.sh:2545 lib/console.tcl:69 msgid "Select All" msgstr "Выделить все" -#: git-gui.sh:1896 +#: git-gui.sh:1924 msgid "Create..." msgstr "Создать..." -#: git-gui.sh:1902 +#: git-gui.sh:1930 msgid "Checkout..." msgstr "Перейти..." -#: git-gui.sh:1908 +#: git-gui.sh:1936 msgid "Rename..." msgstr "Переименовать..." -#: git-gui.sh:1913 git-gui.sh:2012 +#: git-gui.sh:1941 git-gui.sh:2040 msgid "Delete..." msgstr "Удалить..." -#: git-gui.sh:1918 +#: git-gui.sh:1946 msgid "Reset..." msgstr "Сбросить..." -#: git-gui.sh:1930 git-gui.sh:2313 +#: git-gui.sh:1958 git-gui.sh:2342 msgid "New Commit" msgstr "Новое состояние" -#: git-gui.sh:1938 git-gui.sh:2320 +#: git-gui.sh:1966 git-gui.sh:2349 msgid "Amend Last Commit" msgstr "Исправить последнее состояние" -#: git-gui.sh:1947 git-gui.sh:2280 lib/remote_branch_delete.tcl:99 +#: git-gui.sh:1975 git-gui.sh:2309 lib/remote_branch_delete.tcl:99 msgid "Rescan" msgstr "Перечитать" -#: git-gui.sh:1953 +#: git-gui.sh:1981 msgid "Stage To Commit" msgstr "Подготовить для сохранения" -#: git-gui.sh:1958 +#: git-gui.sh:1986 msgid "Stage Changed Files To Commit" msgstr "Подготовить измененные файлы для сохранения" -#: git-gui.sh:1964 +#: git-gui.sh:1992 msgid "Unstage From Commit" msgstr "Убрать из подготовленного" -#: git-gui.sh:1969 lib/index.tcl:352 +#: git-gui.sh:1997 lib/index.tcl:393 msgid "Revert Changes" msgstr "Отменить изменения" -#: git-gui.sh:1976 git-gui.sh:2292 git-gui.sh:2390 +#: git-gui.sh:2004 git-gui.sh:2321 git-gui.sh:2419 msgid "Sign Off" msgstr "Подписать" -#: git-gui.sh:1980 git-gui.sh:2296 +#: git-gui.sh:2008 git-gui.sh:2325 msgid "Commit@@verb" msgstr "Сохранить" -#: git-gui.sh:1991 +#: git-gui.sh:2019 msgid "Local Merge..." msgstr "Локальное объединение..." -#: git-gui.sh:1996 +#: git-gui.sh:2024 msgid "Abort Merge..." msgstr "Прервать объединение..." -#: git-gui.sh:2008 +#: git-gui.sh:2036 msgid "Push..." msgstr "Отправить..." -#: git-gui.sh:2019 lib/choose_repository.tcl:41 -#, fuzzy +#: git-gui.sh:2047 lib/choose_repository.tcl:40 msgid "Apple" msgstr "" -#: git-gui.sh:2022 git-gui.sh:2044 lib/about.tcl:13 -#: lib/choose_repository.tcl:44 lib/choose_repository.tcl:50 +#: git-gui.sh:2050 git-gui.sh:2072 lib/about.tcl:13 +#: lib/choose_repository.tcl:43 lib/choose_repository.tcl:49 #, tcl-format msgid "About %s" msgstr "О %s" -#: git-gui.sh:2026 +#: git-gui.sh:2054 msgid "Preferences..." msgstr "Настройки..." -#: git-gui.sh:2034 git-gui.sh:2558 +#: git-gui.sh:2062 git-gui.sh:2587 msgid "Options..." msgstr "Настройки..." -#: git-gui.sh:2040 lib/choose_repository.tcl:47 +#: git-gui.sh:2068 lib/choose_repository.tcl:46 msgid "Help" msgstr "Помощь" -#: git-gui.sh:2081 +#: git-gui.sh:2109 msgid "Online Documentation" msgstr "Документация в интернете" -#: git-gui.sh:2165 +#: git-gui.sh:2193 #, tcl-format msgid "fatal: cannot stat path %s: No such file or directory" msgstr "критическая ошибка: %s: нет такого файла или каталога" -#: git-gui.sh:2198 +#: git-gui.sh:2226 msgid "Current Branch:" msgstr "Текущая ветвь:" -#: git-gui.sh:2219 +#: git-gui.sh:2247 msgid "Staged Changes (Will Commit)" msgstr "Подготовлено (будет сохранено)" -#: git-gui.sh:2239 +#: git-gui.sh:2266 msgid "Unstaged Changes" msgstr "Изменено (не будет сохранено)" -#: git-gui.sh:2286 +#: git-gui.sh:2315 msgid "Stage Changed" msgstr "Подготовить все" -#: git-gui.sh:2302 lib/transport.tcl:93 lib/transport.tcl:182 +#: git-gui.sh:2331 lib/transport.tcl:93 lib/transport.tcl:182 msgid "Push" msgstr "Отправить" -#: git-gui.sh:2332 +#: git-gui.sh:2361 msgid "Initial Commit Message:" msgstr "Комментарий к первому состоянию:" -#: git-gui.sh:2333 +#: git-gui.sh:2362 msgid "Amended Commit Message:" msgstr "Комментарий к исправленному состоянию:" -#: git-gui.sh:2334 +#: git-gui.sh:2363 msgid "Amended Initial Commit Message:" msgstr "Комментарий к исправленному первоначальному состоянию:" -#: git-gui.sh:2335 +#: git-gui.sh:2364 msgid "Amended Merge Commit Message:" msgstr "Комментарий к исправленному объединению:" -#: git-gui.sh:2336 +#: git-gui.sh:2365 msgid "Merge Commit Message:" msgstr "Комментарий к объединению:" -#: git-gui.sh:2337 +#: git-gui.sh:2366 msgid "Commit Message:" msgstr "Комментарий к состоянию:" -#: git-gui.sh:2382 git-gui.sh:2520 lib/console.tcl:71 +#: git-gui.sh:2411 git-gui.sh:2549 lib/console.tcl:71 msgid "Copy All" msgstr "Копировать все" -#: git-gui.sh:2406 lib/blame.tcl:104 +#: git-gui.sh:2435 lib/blame.tcl:104 msgid "File:" msgstr "Файл:" -#: git-gui.sh:2508 +#: git-gui.sh:2537 msgid "Refresh" msgstr "Обновить" -#: git-gui.sh:2529 +#: git-gui.sh:2558 msgid "Apply/Reverse Hunk" msgstr "Применить/Убрать изменение" -#: git-gui.sh:2535 +#: git-gui.sh:2564 msgid "Decrease Font Size" msgstr "Уменьшить размер шрифта" -#: git-gui.sh:2539 +#: git-gui.sh:2568 msgid "Increase Font Size" msgstr "Увеличить размер шрифта" -#: git-gui.sh:2544 +#: git-gui.sh:2573 msgid "Show Less Context" msgstr "Меньше контекста" -#: git-gui.sh:2551 +#: git-gui.sh:2580 msgid "Show More Context" msgstr "Больше контекста" -#: git-gui.sh:2565 +#: git-gui.sh:2594 msgid "Unstage Hunk From Commit" msgstr "Не сохранять часть" -#: git-gui.sh:2567 +#: git-gui.sh:2596 msgid "Stage Hunk For Commit" msgstr "Подготовить часть для сохранения" -#: git-gui.sh:2586 +#: git-gui.sh:2615 msgid "Initializing..." msgstr "Инициализация..." -#: git-gui.sh:2677 +#: git-gui.sh:2706 #, tcl-format msgid "" "Possible environment issues exist.\n" @@ -448,7 +447,7 @@ msgstr "" "запущенными из %s\n" "\n" -#: git-gui.sh:2707 +#: git-gui.sh:2736 msgid "" "\n" "This is due to a known issue with the\n" @@ -458,7 +457,7 @@ msgstr "" "Это известная проблема с Tcl,\n" "распространяемым Cygwin." -#: git-gui.sh:2712 +#: git-gui.sh:2741 #, tcl-format msgid "" "\n" @@ -579,7 +578,7 @@ msgstr "Создание ветви" msgid "Create New Branch" msgstr "Создать новую ветвь" -#: lib/branch_create.tcl:31 lib/choose_repository.tcl:199 +#: lib/branch_create.tcl:31 lib/choose_repository.tcl:375 msgid "Create" msgstr "Создать" @@ -732,9 +731,9 @@ msgstr "[На уровень выше]" msgid "Browse Branch Files" msgstr "Показать файлы ветви" -#: lib/browser.tcl:277 lib/choose_repository.tcl:215 -#: lib/choose_repository.tcl:305 lib/choose_repository.tcl:315 -#: lib/choose_repository.tcl:811 +#: lib/browser.tcl:277 lib/choose_repository.tcl:391 +#: lib/choose_repository.tcl:482 lib/choose_repository.tcl:492 +#: lib/choose_repository.tcl:989 msgid "Browse" msgstr "Показать" @@ -788,7 +787,8 @@ msgstr "Рабочая область заблокирована другим п msgid "" "Last scanned state does not match repository state.\n" "\n" -"Another Git program has modified this repository since the last scan. A rescan must be performed before the current branch can be changed.\n" +"Another Git program has modified this repository since the last scan. A " +"rescan must be performed before the current branch can be changed.\n" "\n" "The rescan will be automatically started now.\n" msgstr "" @@ -822,11 +822,13 @@ msgstr "Ветвь '%s' остается текущей." msgid "" "You are no longer on a local branch.\n" "\n" -"If you wanted to be on a branch, create one now starting from 'This Detached Checkout'." +"If you wanted to be on a branch, create one now starting from 'This Detached " +"Checkout'." msgstr "" "Вы находитесь не в локальной ветви.\n" "\n" -"Если вы хотите снова вернуться к какой-нибудь ветви, создайте ее сейчас, начиная с 'Текущего отсоединенного состояния'." +"Если вы хотите снова вернуться к какой-нибудь ветви, создайте ее сейчас, " +"начиная с 'Текущего отсоединенного состояния'." #: lib/checkout_op.tcl:446 #, tcl-format @@ -856,19 +858,21 @@ msgstr "Наглядно" msgid "" "Failed to set current branch.\n" "\n" -"This working directory is only partially switched. We successfully updated your files, but failed to update an internal Git file.\n" +"This working directory is only partially switched. We successfully updated " +"your files, but failed to update an internal Git file.\n" "\n" "This should not have occurred. %s will now close and give up." msgstr "" "Не удалось установить текущую ветвь.\n" "\n" -"Ваш рабочий каталог обновлен только частично. Были обновлены все файлы кроме служебных файлов Git. \n" +"Ваш рабочий каталог обновлен только частично. Были обновлены все файлы кроме " +"служебных файлов Git. \n" "\n" "Этого не должно было произойти. %s завершается." #: lib/choose_font.tcl:39 msgid "Select" -msgstr "Выделить все" +msgstr "Выбрать" #: lib/choose_font.tcl:53 msgid "Font Family" @@ -890,210 +894,226 @@ msgstr "" "Это пример текста.\n" "Если Вам нравится этот текст, это может быть Ваш шрифт." -#: lib/choose_repository.tcl:25 +#: lib/choose_repository.tcl:27 msgid "Git Gui" msgstr "" -#: lib/choose_repository.tcl:69 lib/choose_repository.tcl:204 +#: lib/choose_repository.tcl:80 lib/choose_repository.tcl:380 msgid "Create New Repository" msgstr "Создать новый репозиторий" -#: lib/choose_repository.tcl:74 lib/choose_repository.tcl:291 +#: lib/choose_repository.tcl:86 +msgid "New..." +msgstr "Новый..." + +#: lib/choose_repository.tcl:93 lib/choose_repository.tcl:468 msgid "Clone Existing Repository" msgstr "Склонировать существующий репозиторий" -#: lib/choose_repository.tcl:79 lib/choose_repository.tcl:800 +#: lib/choose_repository.tcl:99 +msgid "Clone..." +msgstr "Склонировать..." + +#: lib/choose_repository.tcl:106 lib/choose_repository.tcl:978 msgid "Open Existing Repository" msgstr "Выбрать существующий репозиторий" -#: lib/choose_repository.tcl:91 -msgid "Next >" -msgstr "Дальше >" +#: lib/choose_repository.tcl:112 +msgid "Open..." +msgstr "Открыть..." -#: lib/choose_repository.tcl:152 +#: lib/choose_repository.tcl:125 +msgid "Recent Repositories" +msgstr "Недавние репозитории" + +#: lib/choose_repository.tcl:131 +msgid "Open Recent Repository:" +msgstr "Открыть последний репозиторий" + +#: lib/choose_repository.tcl:294 #, tcl-format msgid "Location %s already exists." msgstr "Путь '%s' уже существует." -#: lib/choose_repository.tcl:158 lib/choose_repository.tcl:165 -#: lib/choose_repository.tcl:172 +#: lib/choose_repository.tcl:300 lib/choose_repository.tcl:307 +#: lib/choose_repository.tcl:314 #, tcl-format msgid "Failed to create repository %s:" msgstr "Не удалось создать репозиторий %s:" -#: lib/choose_repository.tcl:209 lib/choose_repository.tcl:309 +#: lib/choose_repository.tcl:385 lib/choose_repository.tcl:486 msgid "Directory:" msgstr "Каталог:" -#: lib/choose_repository.tcl:238 lib/choose_repository.tcl:363 -#: lib/choose_repository.tcl:834 +#: lib/choose_repository.tcl:415 lib/choose_repository.tcl:544 +#: lib/choose_repository.tcl:1013 msgid "Git Repository" msgstr "Репозиторий" -#: lib/choose_repository.tcl:253 lib/choose_repository.tcl:260 +#: lib/choose_repository.tcl:430 lib/choose_repository.tcl:437 #, tcl-format msgid "Directory %s already exists." msgstr "Каталог '%s' уже существует." -#: lib/choose_repository.tcl:265 +#: lib/choose_repository.tcl:442 #, tcl-format msgid "File %s already exists." msgstr "Файл '%s' уже существует." -#: lib/choose_repository.tcl:286 +#: lib/choose_repository.tcl:463 msgid "Clone" msgstr "Склонировать" -#: lib/choose_repository.tcl:299 +#: lib/choose_repository.tcl:476 msgid "URL:" msgstr "Ссылка:" -#: lib/choose_repository.tcl:319 +#: lib/choose_repository.tcl:496 msgid "Clone Type:" msgstr "Тип клона:" -#: lib/choose_repository.tcl:325 +#: lib/choose_repository.tcl:502 msgid "Standard (Fast, Semi-Redundant, Hardlinks)" msgstr "Стандартный (Быстрый, полуизбыточный, \"жесткие\" ссылки)" -#: lib/choose_repository.tcl:331 +#: lib/choose_repository.tcl:508 msgid "Full Copy (Slower, Redundant Backup)" msgstr "Полная копия (Медленный, создает резервную копию)" -#: lib/choose_repository.tcl:337 +#: lib/choose_repository.tcl:514 msgid "Shared (Fastest, Not Recommended, No Backup)" msgstr "Общий (Самый быстрый, не рекомендуется, без резервной копии)" -#: lib/choose_repository.tcl:369 lib/choose_repository.tcl:418 -#: lib/choose_repository.tcl:560 lib/choose_repository.tcl:630 -#: lib/choose_repository.tcl:840 lib/choose_repository.tcl:848 +#: lib/choose_repository.tcl:550 lib/choose_repository.tcl:597 +#: lib/choose_repository.tcl:738 lib/choose_repository.tcl:808 +#: lib/choose_repository.tcl:1019 lib/choose_repository.tcl:1027 #, tcl-format msgid "Not a Git repository: %s" msgstr "Каталог не является репозиторием: %s" -#: lib/choose_repository.tcl:405 +#: lib/choose_repository.tcl:586 msgid "Standard only available for local repository." msgstr "Стандартный клон возможен только для локального репозитория." -#: lib/choose_repository.tcl:409 +#: lib/choose_repository.tcl:590 msgid "Shared only available for local repository." msgstr "Общий клон возможен только для локального репозитория." -#: lib/choose_repository.tcl:439 +#: lib/choose_repository.tcl:617 msgid "Failed to configure origin" msgstr "Не могу сконфигурировать исходный репозиторий." -#: lib/choose_repository.tcl:451 +#: lib/choose_repository.tcl:629 msgid "Counting objects" msgstr "Считаю объекты" -#: lib/choose_repository.tcl:452 -#, fuzzy +#: lib/choose_repository.tcl:630 msgid "buckets" msgstr "" -#: lib/choose_repository.tcl:476 +#: lib/choose_repository.tcl:654 #, tcl-format msgid "Unable to copy objects/info/alternates: %s" msgstr "Не могу скопировать objects/info/alternates: %s" -#: lib/choose_repository.tcl:512 +#: lib/choose_repository.tcl:690 #, tcl-format msgid "Nothing to clone from %s." msgstr "Нечего клонировать с %s." -#: lib/choose_repository.tcl:514 lib/choose_repository.tcl:728 -#: lib/choose_repository.tcl:740 +#: lib/choose_repository.tcl:692 lib/choose_repository.tcl:906 +#: lib/choose_repository.tcl:918 msgid "The 'master' branch has not been initialized." msgstr "Не инициализирована ветвь 'master'." -#: lib/choose_repository.tcl:527 +#: lib/choose_repository.tcl:705 msgid "Hardlinks are unavailable. Falling back to copying." msgstr "\"Жесткие ссылки\" не доступны. Буду использовать копирование." -#: lib/choose_repository.tcl:539 +#: lib/choose_repository.tcl:717 #, tcl-format msgid "Cloning from %s" msgstr "Клонирование %s" -#: lib/choose_repository.tcl:570 +#: lib/choose_repository.tcl:748 msgid "Copying objects" msgstr "Копирование objects" -#: lib/choose_repository.tcl:571 +#: lib/choose_repository.tcl:749 msgid "KiB" msgstr "КБ" -#: lib/choose_repository.tcl:595 +#: lib/choose_repository.tcl:773 #, tcl-format msgid "Unable to copy object: %s" msgstr "Не могу скопировать объект: %s" -#: lib/choose_repository.tcl:605 +#: lib/choose_repository.tcl:783 msgid "Linking objects" msgstr "Создание ссылок на objects" -#: lib/choose_repository.tcl:606 +#: lib/choose_repository.tcl:784 msgid "objects" msgstr "объекты" -#: lib/choose_repository.tcl:614 +#: lib/choose_repository.tcl:792 #, tcl-format msgid "Unable to hardlink object: %s" msgstr "Не могу \"жестко связать\" объект: %s" -#: lib/choose_repository.tcl:669 +#: lib/choose_repository.tcl:847 msgid "Cannot fetch branches and objects. See console output for details." -msgstr "Не могу получить ветви и объекты. Дополнительная информация на консоли." +msgstr "" +"Не могу получить ветви и объекты. Дополнительная информация на консоли." -#: lib/choose_repository.tcl:680 +#: lib/choose_repository.tcl:858 msgid "Cannot fetch tags. See console output for details." msgstr "Не могу получить метки. Дополнительная информация на консоли." -#: lib/choose_repository.tcl:704 +#: lib/choose_repository.tcl:882 msgid "Cannot determine HEAD. See console output for details." msgstr "Не могу определить HEAD. Дополнительная информация на консоли." -#: lib/choose_repository.tcl:713 +#: lib/choose_repository.tcl:891 #, tcl-format msgid "Unable to cleanup %s" msgstr "Не могу очистить %s" -#: lib/choose_repository.tcl:719 +#: lib/choose_repository.tcl:897 msgid "Clone failed." msgstr "Клонирование не удалось." -#: lib/choose_repository.tcl:726 +#: lib/choose_repository.tcl:904 msgid "No default branch obtained." msgstr "Не было получено ветви по умолчанию." -#: lib/choose_repository.tcl:737 +#: lib/choose_repository.tcl:915 #, tcl-format msgid "Cannot resolve %s as a commit." msgstr "Не могу распознать %s как состояние." -#: lib/choose_repository.tcl:749 +#: lib/choose_repository.tcl:927 msgid "Creating working directory" msgstr "Создаю рабочий каталог" -#: lib/choose_repository.tcl:750 lib/index.tcl:15 lib/index.tcl:80 -#: lib/index.tcl:149 +#: lib/choose_repository.tcl:928 lib/index.tcl:65 lib/index.tcl:127 +#: lib/index.tcl:193 msgid "files" msgstr "файлов" -#: lib/choose_repository.tcl:779 +#: lib/choose_repository.tcl:957 msgid "Initial file checkout failed." msgstr "Не удалось получить начальное состояние файлов репозитория." -#: lib/choose_repository.tcl:795 +#: lib/choose_repository.tcl:973 msgid "Open" msgstr "Открыть" -#: lib/choose_repository.tcl:805 +#: lib/choose_repository.tcl:983 msgid "Repository:" msgstr "Репозиторий:" -#: lib/choose_repository.tcl:854 +#: lib/choose_repository.tcl:1033 #, tcl-format msgid "Failed to open repository %s:" msgstr "Не удалось открыть репозиторий %s:" @@ -1116,7 +1136,7 @@ msgstr "Ветвь слежения" #: lib/choose_rev.tcl:84 lib/choose_rev.tcl:537 msgid "Tag" -msgstr "Метка" +msgstr "Таг" #: lib/choose_rev.tcl:317 #, tcl-format @@ -1143,7 +1163,8 @@ msgstr "Ссылка" msgid "" "There is nothing to amend.\n" "\n" -"You are about to create the initial commit. There is no commit before this to amend.\n" +"You are about to create the initial commit. There is no commit before this " +"to amend.\n" msgstr "" "Отсутствует состояние для исправления.\n" "\n" @@ -1153,11 +1174,14 @@ msgstr "" msgid "" "Cannot amend while merging.\n" "\n" -"You are currently in the middle of a merge that has not been fully completed. You cannot amend the prior commit unless you first abort the current merge activity.\n" +"You are currently in the middle of a merge that has not been fully " +"completed. You cannot amend the prior commit unless you first abort the " +"current merge activity.\n" msgstr "" "Невозможно исправить состояние во время объединения.\n" "\n" -"Текущее объединение не завершено. Невозможно исправить предыдущее сохраненное состояние не прерывая текущее объединение.\n" +"Текущее объединение не завершено. Невозможно исправить предыдущее " +"сохраненное состояние не прерывая текущее объединение.\n" #: lib/commit.tcl:49 msgid "Error loading commit data for amend:" @@ -1169,19 +1193,21 @@ msgstr "Невозможно получить информацию об авто #: lib/commit.tcl:81 msgid "Invalid GIT_COMMITTER_IDENT:" -msgstr "Неверная GIT_COMMITTER_IDENT:" +msgstr "Неверный GIT_COMMITTER_IDENT:" #: lib/commit.tcl:133 msgid "" "Last scanned state does not match repository state.\n" "\n" -"Another Git program has modified this repository since the last scan. A rescan must be performed before another commit can be created.\n" +"Another Git program has modified this repository since the last scan. A " +"rescan must be performed before another commit can be created.\n" "\n" "The rescan will be automatically started now.\n" msgstr "" "Последнее прочитанное состояние репозитория не соответствует текущему.\n" "\n" -"С момента последней проверки репозиторий был изменен другой программой Git. Необходимо перечитать репозиторий, прежде чем изменять текущую ветвь. \n" +"С момента последней проверки репозиторий был изменен другой программой Git. " +"Необходимо перечитать репозиторий, прежде чем изменять текущую ветвь. \n" "\n" "Это будет сделано сейчас автоматически.\n" @@ -1190,11 +1216,13 @@ msgstr "" msgid "" "Unmerged files cannot be committed.\n" "\n" -"File %s has merge conflicts. You must resolve them and stage the file before committing.\n" +"File %s has merge conflicts. You must resolve them and stage the file " +"before committing.\n" msgstr "" "Нельзя сохранить необъединенные файлы.\n" "\n" -"Для файла %s возник конфликт объединения. Разрешите конфликт и добавьте к подготовленным файлам перед сохранением.\n" +"Для файла %s возник конфликт объединения. Разрешите конфликт и добавьте к " +"подготовленным файлам перед сохранением.\n" #: lib/commit.tcl:162 #, tcl-format @@ -1333,13 +1361,15 @@ msgstr "Проверка базы объектов при помощи fsck" msgid "" "This repository currently has approximately %i loose objects.\n" "\n" -"To maintain optimal performance it is strongly recommended that you compress the database when more than %i loose objects exist.\n" +"To maintain optimal performance it is strongly recommended that you compress " +"the database when more than %i loose objects exist.\n" "\n" "Compress the database now?" msgstr "" "Этот репозиторий сейчас содержит примерно %i свободных объектов\n" "\n" -"Для лучшей производительности рекомендуется сжать базу данных, когда есть более %i несвязанных объектов.\n" +"Для лучшей производительности рекомендуется сжать базу данных, когда есть " +"более %i несвязанных объектов.\n" "\n" "Сжать базу данных сейчас?" @@ -1355,15 +1385,18 @@ msgid "" "\n" "%s has no changes.\n" "\n" -"The modification date of this file was updated by another application, but the content within the file was not changed.\n" +"The modification date of this file was updated by another application, but " +"the content within the file was not changed.\n" "\n" -"A rescan will be automatically started to find other files which may have the same state." +"A rescan will be automatically started to find other files which may have " +"the same state." msgstr "" "Изменений не обнаружено.\n" "\n" "в %s отутствуют изменения.\n" "\n" -"Дата изменения файла была обновлена другой программой, но содержимое файла осталось прежним.\n" +"Дата изменения файла была обновлена другой программой, но содержимое файла " +"осталось прежним.\n" "\n" "Сейчас будет запущено перечитывание репозитория, чтобы найти подобные файлы." @@ -1413,32 +1446,57 @@ msgstr "предупреждение" msgid "You must correct the above errors before committing." msgstr "Прежде чем сохранить, исправьте вышеуказанные ошибки." -#: lib/index.tcl:241 +#: lib/index.tcl:6 +msgid "Unable to unlock the index." +msgstr "Не удалось разблокировать индекс" + +#: lib/index.tcl:15 +msgid "Index Error" +msgstr "Ошибка индекса" + +#: lib/index.tcl:21 +msgid "" +"Updating the Git index failed. A rescan will be automatically started to " +"resynchronize git-gui." +msgstr "" +"Не удалось обновить индекс Git. Состояние репозитория будет" +"перечитано автоматически." + +#: lib/index.tcl:27 +msgid "Continue" +msgstr "Продолжить" + +#: lib/index.tcl:31 +msgid "Unlock Index" +msgstr "Разблокировать индекс" + +#: lib/index.tcl:282 #, tcl-format msgid "Unstaging %s from commit" msgstr "Удаление %s из подготовленного" -#: lib/index.tcl:285 +#: lib/index.tcl:326 #, tcl-format msgid "Adding %s" msgstr "Добавление %s..." -#: lib/index.tcl:340 +#: lib/index.tcl:381 #, tcl-format msgid "Revert changes in file %s?" msgstr "Отменить изменения в файле %s?" -#: lib/index.tcl:342 +#: lib/index.tcl:383 #, tcl-format msgid "Revert changes in these %i files?" msgstr "Отменить изменения в %i файле(-ах)?" -#: lib/index.tcl:348 +#: lib/index.tcl:389 msgid "Any unstaged changes will be permanently lost by the revert." msgstr "" -"Любые изменения, не подготовленные к сохранению, будут потеряны при данной операции." +"Любые изменения, не подготовленные к сохранению, будут потеряны при данной " +"операции." -#: lib/index.tcl:351 +#: lib/index.tcl:392 msgid "Do Nothing" msgstr "Ничего не делать" @@ -1450,19 +1508,22 @@ msgid "" msgstr "" "Невозможно выполнить объединение во время исправления.\n" "\n" -"Завершите исправление данного состояния перед выполнением операции объединения.\n" +"Завершите исправление данного состояния перед выполнением операции " +"объединения.\n" #: lib/merge.tcl:27 msgid "" "Last scanned state does not match repository state.\n" "\n" -"Another Git program has modified this repository since the last scan. A rescan must be performed before a merge can be performed.\n" +"Another Git program has modified this repository since the last scan. A " +"rescan must be performed before a merge can be performed.\n" "\n" "The rescan will be automatically started now.\n" msgstr "" "Последнее прочитанное состояние репозитория не соответствует текущему.\n" "\n" -"С момента последней проверки репозиторий был изменен другой программой Git. Необходимо перечитать репозиторий, прежде чем изменять текущую ветвь.\n" +"С момента последней проверки репозиторий был изменен другой программой Git. " +"Необходимо перечитать репозиторий, прежде чем изменять текущую ветвь.\n" "\n" "Это будет сделано сейчас автоматически.\n" @@ -1473,12 +1534,15 @@ msgid "" "\n" "File %s has merge conflicts.\n" "\n" -"You must resolve them, stage the file, and commit to complete the current merge. Only then can you begin another merge.\n" +"You must resolve them, stage the file, and commit to complete the current " +"merge. Only then can you begin another merge.\n" msgstr "" "Предыдущее объединение не завершено из-за конфликта.\n" "\n" "Для файла %s возник конфликт объединения.\n" -"Разрешите конфликт, подготовьте файл и сохраните. Только после этого можно начать следующее объединение.\n" +"\n" +"Разрешите конфликт, подготовьте файл и сохраните. Только после этого можно " +"начать следующее объединение.\n" #: lib/merge.tcl:54 #, tcl-format @@ -1487,13 +1551,15 @@ msgid "" "\n" "File %s is modified.\n" "\n" -"You should complete the current commit before starting a merge. Doing so will help you abort a failed merge, should the need arise.\n" +"You should complete the current commit before starting a merge. Doing so " +"will help you abort a failed merge, should the need arise.\n" msgstr "" "Изменения не сохранены.\n" "\n" -"Файл %s изменен.\n" +"Файл %s изменен.\n" "\n" -"Подготовьте и сохраните измения перед началом объединения. В случае необходимости это позволит прервать операцию объединения.\n" +"Подготовьте и сохраните измения перед началом объединения. В случае " +"необходимости это позволит прервать операцию объединения.\n" #: lib/merge.tcl:106 #, tcl-format @@ -1631,7 +1697,7 @@ msgstr "Шаблон для имени новой ветви" #: lib/option.tcl:176 msgid "Change Font" -msgstr "Шрифт интерфейса" +msgstr "Изменить шрифт" #: lib/option.tcl:180 #, tcl-format @@ -1640,7 +1706,6 @@ msgstr "Выберите %s" # carbon copy #: lib/option.tcl:186 -#, fuzzy msgid "pt." msgstr "" @@ -1652,18 +1717,6 @@ msgstr "Настройки" msgid "Failed to completely save options:" msgstr "Не удалось полностью сохранить настройки:" -#: lib/remote.tcl:165 -msgid "Prune from" -msgstr "Чистка" - -#: lib/remote.tcl:170 -msgid "Fetch from" -msgstr "Получение из" - -#: lib/remote.tcl:213 -msgid "Push to" -msgstr "Отправить" - #: lib/remote_branch_delete.tcl:29 lib/remote_branch_delete.tcl:34 msgid "Delete Remote Branch" msgstr "Удалить внешнюю ветвь" @@ -1707,16 +1760,17 @@ msgid "" "\n" " - %s" msgstr "" -"Следующие ветви объединены с %s не полностью:" -"\n" +"Следующие ветви объединены с %s не полностью:\n" " - %s" #: lib/remote_branch_delete.tcl:189 #, tcl-format -msgid "One or more of the merge tests failed because you have not fetched the necessary commits. Try fetching from %s first." +msgid "" +"One or more of the merge tests failed because you have not fetched the " +"necessary commits. Try fetching from %s first." msgstr "" -"Один или несколько тестов на объединение не прошли, потому что " -"Вы не получили необходимые состояния. Попробуйте сначала получить их из %s." +"Один или несколько тестов на объединение не прошли, потому что Вы не " +"получили необходимые состояния. Попытайтесь получить их из %s." #: lib/remote_branch_delete.tcl:207 msgid "Please select one or more branches to delete." @@ -1746,11 +1800,23 @@ msgstr "Не указан репозиторий." msgid "Scanning %s..." msgstr "Перечитывание %s... " -#: lib/shortcut.tcl:26 lib/shortcut.tcl:74 -msgid "Cannot write script:" -msgstr "Невозможно записать скрипт:" +#: lib/remote.tcl:165 +msgid "Prune from" +msgstr "Чистка" -#: lib/shortcut.tcl:149 +#: lib/remote.tcl:170 +msgid "Fetch from" +msgstr "Получение из" + +#: lib/remote.tcl:213 +msgid "Push to" +msgstr "Отправить" + +#: lib/shortcut.tcl:20 lib/shortcut.tcl:61 +msgid "Cannot write shortcut:" +msgstr "Невозможно записать ссылку:" + +#: lib/shortcut.tcl:136 msgid "Cannot write icon:" msgstr "Невозможно записать значок:" @@ -1821,5 +1887,7 @@ msgstr "Использовать thin pack (для медленных сетев #: lib/transport.tcl:168 msgid "Include tags" -msgstr "Включить метки" +msgstr "Передать таги" +#~ msgid "Next >" +#~ msgstr "Дальше >" From 76d536b8af3a2cdf6fb86b2f05051a31b7096cbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=97=E3=82=89=E3=81=84=E3=81=97=E3=81=AA=E3=81=AA?= =?UTF-8?q?=E3=81=93?= Date: Wed, 31 Oct 2007 23:12:12 +0900 Subject: [PATCH 0372/1490] git-gui: Update Japanese strings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This updates the Japanese translation file. Signed-off-by: しらいしななこ Signed-off-by: Shawn O. Pearce --- po/ja.po | 277 ++++++++++++++++++++++++++----------------------------- 1 file changed, 133 insertions(+), 144 deletions(-) diff --git a/po/ja.po b/po/ja.po index f65e460686..e4491f704c 100644 --- a/po/ja.po +++ b/po/ja.po @@ -9,7 +9,7 @@ msgstr "" "Project-Id-Version: git-gui\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2007-10-10 04:04-0400\n" -"PO-Revision-Date: 2007-08-14 18:49+0900\n" +"PO-Revision-Date: 2007-10-31 16:23+0900\n" "Last-Translator: しらいし ななこ \n" "Language-Team: Japanese\n" "MIME-Version: 1.0\n" @@ -19,12 +19,12 @@ msgstr "" #: git-gui.sh:41 git-gui.sh:634 git-gui.sh:648 git-gui.sh:661 git-gui.sh:744 #: git-gui.sh:763 msgid "git-gui: fatal error" -msgstr "" +msgstr "git-gui: 致命的なエラー" #: git-gui.sh:595 -#, fuzzy, tcl-format +#, tcl-format msgid "Invalid font specified in %s:" -msgstr "gui.%s に無効なフォントが指定されています:" +msgstr "%s に無効なフォントが指定されています:" #: git-gui.sh:620 msgid "Main Font" @@ -66,9 +66,8 @@ msgid "Git directory not found:" msgstr "Git ディレクトリが見つかりません:" #: git-gui.sh:860 -#, fuzzy msgid "Cannot move to top of working directory:" -msgstr "変な .git ディレクトリは使えません" +msgstr "作業ディレクトリの最上位に移動できません" #: git-gui.sh:867 msgid "Cannot use funny .git directory:" @@ -158,7 +157,6 @@ msgid "Branch" msgstr "ブランチ" #: git-gui.sh:1794 lib/choose_rev.tcl:547 -#, fuzzy msgid "Commit@@noun" msgstr "コミット" @@ -167,9 +165,8 @@ msgid "Merge" msgstr "マージ" #: git-gui.sh:1798 lib/choose_rev.tcl:556 -#, fuzzy msgid "Remote" -msgstr "リモート:" +msgstr "リモート" #: git-gui.sh:1807 msgid "Browse Current Branch's Files" @@ -301,7 +298,6 @@ msgid "Sign Off" msgstr "署名" #: git-gui.sh:1980 git-gui.sh:2296 -#, fuzzy msgid "Commit@@verb" msgstr "コミット" @@ -329,7 +325,7 @@ msgstr "%s について" #: git-gui.sh:2026 msgid "Preferences..." -msgstr "" +msgstr "設定…" #: git-gui.sh:2034 git-gui.sh:2558 msgid "Options..." @@ -346,21 +342,19 @@ msgstr "オンライン・ドキュメント" #: git-gui.sh:2165 #, tcl-format msgid "fatal: cannot stat path %s: No such file or directory" -msgstr "" +msgstr "致命的: パス %s が stat できません。そのようなファイルやディレクトリはありません" #: git-gui.sh:2198 msgid "Current Branch:" msgstr "現在のブランチ" #: git-gui.sh:2219 -#, fuzzy msgid "Staged Changes (Will Commit)" msgstr "ステージングされた(コミット予定済の)変更" #: git-gui.sh:2239 -#, fuzzy msgid "Unstaged Changes" -msgstr "変更をコミット予定に入れる" +msgstr "コミット予定に入っていない変更" #: git-gui.sh:2286 msgid "Stage Changed" @@ -448,6 +442,10 @@ msgid "" "by %s:\n" "\n" msgstr "" +"環境に問題がある可能性があります\n" +"\n" +"以下の環境変数は %s が起動する Git サブプロセスによって無視されるでしょう:\n" +"\n" #: git-gui.sh:2707 msgid "" @@ -455,6 +453,9 @@ msgid "" "This is due to a known issue with the\n" "Tcl binary distributed by Cygwin." msgstr "" +"\n" +"これは Cygwin で配布されている Tcl バイナリに\n" +"関しての既知の問題によります" #: git-gui.sh:2712 #, tcl-format @@ -466,6 +467,10 @@ msgid "" "user.email settings into your personal\n" "~/.gitconfig file.\n" msgstr "" +"\n" +"\n" +"個人的な ~/.gitconfig ファイル内で user.name と user.email の値を設定\n" +"するのが、%s の良い代用となります\n" #: lib/about.tcl:25 msgid "git-gui - a graphical user interface for Git." @@ -490,50 +495,47 @@ msgstr "%s を読んでいます…" #: lib/blame.tcl:473 msgid "Loading copy/move tracking annotations..." -msgstr "" +msgstr "コピー・移動追跡データを読んでいます…" #: lib/blame.tcl:493 msgid "lines annotated" -msgstr "" +msgstr "行を注釈しました" #: lib/blame.tcl:674 msgid "Loading original location annotations..." -msgstr "" +msgstr "元位置行の注釈データを読んでいます…" #: lib/blame.tcl:677 msgid "Annotation complete." -msgstr "" +msgstr "注釈完了しました" #: lib/blame.tcl:731 -#, fuzzy msgid "Loading annotation..." -msgstr "%s をロード中…" +msgstr "注釈を読み込んでいます…" #: lib/blame.tcl:787 msgid "Author:" -msgstr "" +msgstr "作者:" #: lib/blame.tcl:791 -#, fuzzy msgid "Committer:" -msgstr "コミット:" +msgstr "コミット者:" #: lib/blame.tcl:796 msgid "Original File:" -msgstr "" +msgstr "元ファイル" #: lib/blame.tcl:910 msgid "Originally By:" -msgstr "" +msgstr "原作者:" #: lib/blame.tcl:916 -#, fuzzy msgid "In File:" msgstr "ファイル:" #: lib/blame.tcl:921 msgid "Copied Or Moved Here By:" -msgstr "" +msgstr "複写・移動者:" #: lib/branch_checkout.tcl:14 lib/branch_checkout.tcl:19 msgid "Checkout Branch" @@ -741,7 +743,7 @@ msgstr "%s から %s をフェッチしています" #: lib/checkout_op.tcl:127 #, tcl-format msgid "fatal: Cannot resolve %s" -msgstr "" +msgstr "致命的エラー: %s を解決できません" #: lib/checkout_op.tcl:140 lib/console.tcl:79 lib/database.tcl:31 msgid "Close" @@ -796,9 +798,9 @@ msgstr "" "自動的に再スキャンを開始します。\n" #: lib/checkout_op.tcl:322 -#, fuzzy, tcl-format +#, tcl-format msgid "Updating working directory to '%s'..." -msgstr "作業ディレクトリがありません" +msgstr "作業ディレクトリを '%s' に更新しています…" #: lib/checkout_op.tcl:353 #, tcl-format @@ -827,9 +829,9 @@ msgstr "" "チを開始してください。" #: lib/checkout_op.tcl:446 -#, fuzzy, tcl-format +#, tcl-format msgid "Checked out '%s'." -msgstr "チェックアウト" +msgstr "'%s' をチェックアウトしました" #: lib/checkout_op.tcl:478 #, tcl-format @@ -866,244 +868,235 @@ msgstr "" "起こるはずのないエラーです。あきらめて %s を終了します。" #: lib/choose_font.tcl:39 -#, fuzzy msgid "Select" -msgstr "全て選択" +msgstr "選択" #: lib/choose_font.tcl:53 msgid "Font Family" -msgstr "" +msgstr "フォント・ファミリー" #: lib/choose_font.tcl:73 -#, fuzzy msgid "Font Size" -msgstr "フォントを小さく" +msgstr "フォントの大きさ" #: lib/choose_font.tcl:90 msgid "Font Example" -msgstr "" +msgstr "フォント・サンプル" #: lib/choose_font.tcl:101 msgid "" "This is example text.\n" "If you like this text, it can be your font." msgstr "" +"これはサンプル文です。\n" +"このフォントが気に入ればお使いになれます。" #: lib/choose_repository.tcl:25 msgid "Git Gui" -msgstr "" +msgstr "Git GUI" #: lib/choose_repository.tcl:69 lib/choose_repository.tcl:204 -#, fuzzy msgid "Create New Repository" -msgstr "元のリポジトリ" +msgstr "新しいリポジトリを作る" #: lib/choose_repository.tcl:74 lib/choose_repository.tcl:291 -#, fuzzy msgid "Clone Existing Repository" -msgstr "送り先リポジトリ" +msgstr "既存リポジトリを複製する" #: lib/choose_repository.tcl:79 lib/choose_repository.tcl:800 -#, fuzzy msgid "Open Existing Repository" -msgstr "送り先リポジトリ" +msgstr "既存リポジトリを開く" #: lib/choose_repository.tcl:91 msgid "Next >" -msgstr "" +msgstr "次 >" #: lib/choose_repository.tcl:152 -#, fuzzy, tcl-format +#, tcl-format msgid "Location %s already exists." -msgstr "'%s'というブランチは既に存在します。" +msgstr "'%s' は既に存在します。" #: lib/choose_repository.tcl:158 lib/choose_repository.tcl:165 #: lib/choose_repository.tcl:172 -#, fuzzy, tcl-format +#, tcl-format msgid "Failed to create repository %s:" -msgstr "完全にオプションを保存できません:" +msgstr "リポジトリ %s を作製できません:" #: lib/choose_repository.tcl:209 lib/choose_repository.tcl:309 msgid "Directory:" -msgstr "" +msgstr "ディレクトリ:" #: lib/choose_repository.tcl:238 lib/choose_repository.tcl:363 #: lib/choose_repository.tcl:834 -#, fuzzy msgid "Git Repository" -msgstr "リポジトリ" +msgstr "GIT リポジトリ" #: lib/choose_repository.tcl:253 lib/choose_repository.tcl:260 -#, fuzzy, tcl-format +#, tcl-format msgid "Directory %s already exists." -msgstr "'%s'というブランチは既に存在します。" +msgstr "ディレクトリ '%s' は既に存在します。" #: lib/choose_repository.tcl:265 -#, fuzzy, tcl-format +#, tcl-format msgid "File %s already exists." -msgstr "'%s'というブランチは既に存在します。" +msgstr "ファイル '%s' は既に存在します。" #: lib/choose_repository.tcl:286 -#, fuzzy msgid "Clone" -msgstr "閉じる" +msgstr "複製" #: lib/choose_repository.tcl:299 msgid "URL:" -msgstr "" +msgstr "URL:" #: lib/choose_repository.tcl:319 msgid "Clone Type:" -msgstr "" +msgstr "複製方式:" #: lib/choose_repository.tcl:325 msgid "Standard (Fast, Semi-Redundant, Hardlinks)" -msgstr "" +msgstr "標準(高速・中冗長度・ハードリンク)" #: lib/choose_repository.tcl:331 msgid "Full Copy (Slower, Redundant Backup)" -msgstr "" +msgstr "全複写(低速・冗長バックアップ)" #: lib/choose_repository.tcl:337 msgid "Shared (Fastest, Not Recommended, No Backup)" -msgstr "" +msgstr "共有(最高速・非推奨・バックアップ無し)" #: lib/choose_repository.tcl:369 lib/choose_repository.tcl:418 #: lib/choose_repository.tcl:560 lib/choose_repository.tcl:630 #: lib/choose_repository.tcl:840 lib/choose_repository.tcl:848 -#, fuzzy, tcl-format +#, tcl-format msgid "Not a Git repository: %s" -msgstr "リポジトリが選択されていません。" +msgstr "Git リポジトリではありません: %s" #: lib/choose_repository.tcl:405 msgid "Standard only available for local repository." -msgstr "" +msgstr "標準方式は同一計算機上のリポジトリにのみ使えます。" #: lib/choose_repository.tcl:409 msgid "Shared only available for local repository." -msgstr "" +msgstr "共有方式は同一計算機上のリポジトリにのみ使えます。" #: lib/choose_repository.tcl:439 msgid "Failed to configure origin" -msgstr "" +msgstr "origin を設定できませんでした" #: lib/choose_repository.tcl:451 msgid "Counting objects" -msgstr "" +msgstr "オブジェクトを数えています" #: lib/choose_repository.tcl:452 msgid "buckets" -msgstr "" +msgstr "バケツ" #: lib/choose_repository.tcl:476 #, tcl-format msgid "Unable to copy objects/info/alternates: %s" -msgstr "" +msgstr "objects/info/alternates を複写できません: %s" #: lib/choose_repository.tcl:512 -#, fuzzy, tcl-format +#, tcl-format msgid "Nothing to clone from %s." -msgstr "%s から新しい変更をフェッチしています" +msgstr "%s から複製する内容はありません" #: lib/choose_repository.tcl:514 lib/choose_repository.tcl:728 #: lib/choose_repository.tcl:740 msgid "The 'master' branch has not been initialized." -msgstr "" +msgstr "'master' ブランチが初期化されていません" #: lib/choose_repository.tcl:527 msgid "Hardlinks are unavailable. Falling back to copying." -msgstr "" +msgstr "ハードリンクが作れないので、コピーします" #: lib/choose_repository.tcl:539 -#, fuzzy, tcl-format +#, tcl-format msgid "Cloning from %s" -msgstr "%s から %s をフェッチしています" +msgstr "%s から複製しています" #: lib/choose_repository.tcl:570 -#, fuzzy msgid "Copying objects" -msgstr "データベース圧縮" +msgstr "オブジェクトを複写しています" #: lib/choose_repository.tcl:571 msgid "KiB" -msgstr "" +msgstr "KiB" #: lib/choose_repository.tcl:595 #, tcl-format msgid "Unable to copy object: %s" -msgstr "" +msgstr "オブジェクトを複写できません: %s" #: lib/choose_repository.tcl:605 msgid "Linking objects" -msgstr "" +msgstr "オブジェクトを連結しています" #: lib/choose_repository.tcl:606 msgid "objects" -msgstr "" +msgstr "オブジェクト" #: lib/choose_repository.tcl:614 #, tcl-format msgid "Unable to hardlink object: %s" -msgstr "" +msgstr "オブジェクトをハードリンクできません: %s" #: lib/choose_repository.tcl:669 msgid "Cannot fetch branches and objects. See console output for details." -msgstr "" +msgstr "ブランチやオブジェクトを取得できません。コンソール出力を見て下さい" #: lib/choose_repository.tcl:680 msgid "Cannot fetch tags. See console output for details." -msgstr "" +msgstr "タグを取得できません。コンソール出力を見て下さい" #: lib/choose_repository.tcl:704 msgid "Cannot determine HEAD. See console output for details." -msgstr "" +msgstr "HEAD を確定できません。コンソール出力を見て下さい" #: lib/choose_repository.tcl:713 #, tcl-format msgid "Unable to cleanup %s" -msgstr "" +msgstr "%s を掃除できません" #: lib/choose_repository.tcl:719 -#, fuzzy msgid "Clone failed." -msgstr "中断に失敗しました。" +msgstr "複写に失敗しました。" #: lib/choose_repository.tcl:726 msgid "No default branch obtained." -msgstr "" +msgstr "デフォールト・ブランチが取得されませんでした" #: lib/choose_repository.tcl:737 #, tcl-format msgid "Cannot resolve %s as a commit." -msgstr "" +msgstr "%s をコミットとして解釈できません" #: lib/choose_repository.tcl:749 -#, fuzzy msgid "Creating working directory" -msgstr "作業ディレクトリがありません" +msgstr "作業ディレクトリを作成しています" #: lib/choose_repository.tcl:750 lib/index.tcl:15 lib/index.tcl:80 #: lib/index.tcl:149 msgid "files" -msgstr "" +msgstr "ファイル" #: lib/choose_repository.tcl:779 msgid "Initial file checkout failed." -msgstr "" +msgstr "初期チェックアウトに失敗しました" #: lib/choose_repository.tcl:795 msgid "Open" -msgstr "" +msgstr "開く" #: lib/choose_repository.tcl:805 -#, fuzzy msgid "Repository:" -msgstr "リポジトリ" +msgstr "リポジトリ:" #: lib/choose_repository.tcl:854 -#, fuzzy, tcl-format +#, tcl-format msgid "Failed to open repository %s:" -msgstr "完全にオプションを保存できません:" +msgstr "リポジトリ %s を開けません:" #: lib/choose_rev.tcl:53 msgid "This Detached Checkout" @@ -1140,11 +1133,11 @@ msgstr "リビジョン式が空です。" #: lib/choose_rev.tcl:530 msgid "Updated" -msgstr "" +msgstr "更新しました" #: lib/choose_rev.tcl:558 msgid "URL" -msgstr "" +msgstr "URL" #: lib/commit.tcl:9 msgid "" @@ -1258,7 +1251,7 @@ msgstr "write-tree が失敗しました:" #: lib/commit.tcl:275 #, tcl-format msgid "Commit %s appears to be corrupt" -msgstr "" +msgstr "コミット %s は壊れています" #: lib/commit.tcl:279 msgid "" @@ -1281,7 +1274,7 @@ msgstr "コミットする変更がありません。" #: lib/commit.tcl:303 #, tcl-format msgid "warning: Tcl does not support encoding '%s'." -msgstr "" +msgstr "警告: Tcl はエンコーディング '%s' をサポートしていません" #: lib/commit.tcl:317 msgid "commit-tree failed:" @@ -1354,11 +1347,16 @@ msgid "" "\n" "Compress the database now?" msgstr "" +"このリポジトリにはおおよそ %i 個の個別オブジェクトがあります\n" +"\n" +"最適な性能を保つために、%i 個以上の個別オブジェクトを作る毎にデータベースを圧縮することを推奨します\n" +"\n" +"データベースを圧縮しますか?" #: lib/date.tcl:25 -#, fuzzy, tcl-format +#, tcl-format msgid "Invalid date from Git: %s" -msgstr "無効なリビジョン: %s" +msgstr "Git から出た無効な日付: %s" #: lib/diff.tcl:42 #, tcl-format @@ -1383,14 +1381,14 @@ msgstr "" "同様な状態のファイルを探すために、自動的に再スキャンを開始します。" #: lib/diff.tcl:81 -#, fuzzy, tcl-format +#, tcl-format msgid "Loading diff of %s..." -msgstr "%s をロード中…" +msgstr "%s の変更点をロード中…" #: lib/diff.tcl:114 lib/diff.tcl:184 #, tcl-format msgid "Unable to display %s" -msgstr "" +msgstr "%s を表示できません" #: lib/diff.tcl:115 msgid "Error loading file:" @@ -1398,11 +1396,11 @@ msgstr "ファイルを読む際のエラーです:" #: lib/diff.tcl:122 msgid "Git Repository (subproject)" -msgstr "" +msgstr "Git リポジトリ(サブプロジェクト)" #: lib/diff.tcl:134 msgid "* Binary file (not showing content)." -msgstr "" +msgstr "* バイナリファイル(内容は表示しません)" #: lib/diff.tcl:185 msgid "Error loading diff:" @@ -1429,14 +1427,14 @@ msgid "You must correct the above errors before committing." msgstr "コミットする前に、以上のエラーを修正して下さい" #: lib/index.tcl:241 -#, fuzzy, tcl-format +#, tcl-format msgid "Unstaging %s from commit" -msgstr "コミットから降ろす" +msgstr "コミットから '%s' を降ろす" #: lib/index.tcl:285 -#, fuzzy, tcl-format +#, tcl-format msgid "Adding %s" -msgstr "%s を読んでいます…" +msgstr "コミットに %s を加えています" #: lib/index.tcl:340 #, tcl-format @@ -1651,41 +1649,37 @@ msgid "New Branch Name Template" msgstr "新しいブランチ名のテンプレート" #: lib/option.tcl:176 -#, fuzzy msgid "Change Font" -msgstr "主フォント" +msgstr "フォントを変更" #: lib/option.tcl:180 #, tcl-format msgid "Choose %s" -msgstr "" +msgstr "%s を選択" #: lib/option.tcl:186 msgid "pt." -msgstr "" +msgstr "ポイント" #: lib/option.tcl:200 msgid "Preferences" -msgstr "" +msgstr "設定" #: lib/option.tcl:235 msgid "Failed to completely save options:" msgstr "完全にオプションを保存できません:" #: lib/remote.tcl:165 -#, fuzzy msgid "Prune from" -msgstr "%s から刈る…" +msgstr "から刈込む…" #: lib/remote.tcl:170 -#, fuzzy msgid "Fetch from" -msgstr "%s からフェッチ…" +msgstr "取得元" #: lib/remote.tcl:213 -#, fuzzy msgid "Push to" -msgstr "プッシュ" +msgstr "プッシュ先" #: lib/remote_branch_delete.tcl:29 lib/remote_branch_delete.tcl:34 msgid "Delete Remote Branch" @@ -1724,12 +1718,15 @@ msgid "A branch is required for 'Merged Into'." msgstr "'マージ先' にはブランチが必要です。" #: lib/remote_branch_delete.tcl:184 -#, fuzzy, tcl-format +#, tcl-format msgid "" "The following branches are not completely merged into %s:\n" "\n" " - %s" -msgstr "以下のブランチは %s に完全にマージされていません:" +msgstr "" +"以下のブランチは %s に完全にマージされていません:\n" +"\n" +" - %s" #: lib/remote_branch_delete.tcl:189 #, tcl-format @@ -1782,9 +1779,9 @@ msgid "%s ... %*i of %*i %s (%3i%%)" msgstr "%1$s ... %3$*i %4$s 中の %$2*i (%5$3i%%)" #: lib/transport.tcl:6 -#, fuzzy, tcl-format +#, tcl-format msgid "fetch %s" -msgstr "フェッチ" +msgstr "%s を取得" #: lib/transport.tcl:7 #, tcl-format @@ -1794,7 +1791,7 @@ msgstr "%s から新しい変更をフェッチしています" #: lib/transport.tcl:18 #, tcl-format msgid "remote prune %s" -msgstr "" +msgstr "遠隔刈込 %s" #: lib/transport.tcl:19 #, tcl-format @@ -1804,7 +1801,7 @@ msgstr "%s から削除されたトラッキング・ブランチを刈ってい #: lib/transport.tcl:25 lib/transport.tcl:71 #, tcl-format msgid "push %s" -msgstr "" +msgstr "%s をプッシュ" #: lib/transport.tcl:26 #, tcl-format @@ -1834,7 +1831,7 @@ msgstr "通信オプション" #: lib/transport.tcl:160 msgid "Force overwrite existing branch (may discard changes)" -msgstr "" +msgstr "既存ブランチを上書き(変更を破棄する可能性があります)" #: lib/transport.tcl:164 msgid "Use thin pack (for slow network connections)" @@ -1844,11 +1841,3 @@ msgstr "Thin Pack を使う(遅いネットワーク接続)" msgid "Include tags" msgstr "タグを含める" -#~ msgid "Cannot find the git directory:" -#~ msgstr "git ディレクトリが見つかりません:" - -#~ msgid "Unstaged Changes (Will Not Be Committed)" -#~ msgstr "ステージングされていない(コミット未予定の)変更" - -#~ msgid "Push to %s..." -#~ msgstr "%s へプッシュ…" From 6ea10797deb7699c35a2b097938bf02aabc29e45 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 31 Oct 2007 21:14:01 -0700 Subject: [PATCH 0373/1490] git-gui: Update Japanese strings (part 2) Resolve an earlier suggestion from Christian. Signed-off-by: Shawn O. Pearce --- po/ja.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/po/ja.po b/po/ja.po index e4491f704c..f3a547b1b9 100644 --- a/po/ja.po +++ b/po/ja.po @@ -1776,7 +1776,7 @@ msgstr "アイコンが書けません:" #: lib/status_bar.tcl:83 #, tcl-format msgid "%s ... %*i of %*i %s (%3i%%)" -msgstr "%1$s ... %3$*i %4$s 中の %$2*i (%5$3i%%)" +msgstr "%1$s ... %4$*i %6$s 中の %2$*i (%7$3i%%)" #: lib/transport.tcl:6 #, tcl-format From 48b8d2b3792339d4dbd37802db8ec797361dd1fe Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Thu, 1 Nov 2007 00:31:36 -0400 Subject: [PATCH 0374/1490] git-gui: Allow users to set font weights to bold Previously we allowed users to tweak their font weight to be bold by setting it manually in their ~/.gitconfig prior to starting git-gui. This was broken in ae0754ac9a24afa2693246222fc078fe9c133b3a when Simon set the font weight to normal by default, overridding whatever we found from the ~/.gitconfig file. Signed-off-by: Shawn O. Pearce --- git-gui.sh | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/git-gui.sh b/git-gui.sh index a7227ac1b6..b41e107d94 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -551,8 +551,15 @@ proc apply_config {} { set name [lindex $option 0] set font [lindex $option 1] if {[catch { + set need_weight 1 foreach {cn cv} $repo_config(gui.$name) { - font configure $font $cn $cv -weight normal + if {$cn eq {-weight}} { + set need_weight 0 + } + font configure $font $cn $cv + } + if {$need_weight} { + font configure $font -weight normal } } err]} { error_popup [strcat [mc "Invalid font specified in %s:" "gui.$name"] "\n\n$err"] From 6b6012e6ca628a00d2e0fa6f686017f9e2d66203 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 31 Oct 2007 16:55:13 -0400 Subject: [PATCH 0375/1490] cvsexportcommit: fix for commits that do not have parents Previously commits without parents would fail to export with a message indicating that the commits had more than one parent. Instead we should use the --root option for git-diff-tree in place of a parent. Signed-off-by: Brad King Signed-off-by: Junio C Hamano --- git-cvsexportcommit.perl | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/git-cvsexportcommit.perl b/git-cvsexportcommit.perl index 7b19a33ad1..b2c9f98e86 100755 --- a/git-cvsexportcommit.perl +++ b/git-cvsexportcommit.perl @@ -87,6 +87,7 @@ } } +my $noparent = "0000000000000000000000000000000000000000"; if ($parent) { my $found; # double check that it's a valid parent @@ -100,8 +101,10 @@ } else { # we don't have a parent from the cmdline... if (@parents == 1) { # it's safe to get it from the commit $parent = $parents[0]; - } else { # or perhaps not! - die "This commit has more than one parent -- please name the parent you want to use explicitly"; + } elsif (@parents == 0) { # there is no parent + $parent = $noparent; + } else { # cannot choose automatically from multiple parents + die "This commit has more than one parent -- please name the parent you want to use explicitly"; } } @@ -121,7 +124,11 @@ } close MSG; -`git-diff-tree --binary -p $parent $commit >.cvsexportcommit.diff`;# || die "Cannot diff"; +if ($parent eq $noparent) { + `git-diff-tree --binary -p --root $commit >.cvsexportcommit.diff`;# || die "Cannot diff"; +} else { + `git-diff-tree --binary -p $parent $commit >.cvsexportcommit.diff`;# || die "Cannot diff"; +} ## apply non-binary changes From 0f49327c9755b6575b447f79b540749d231cb26d Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 1 Nov 2007 13:46:20 -0700 Subject: [PATCH 0376/1490] Revert "rebase: allow starting from a dirty tree." This reverts commit 6c9ad166dbbf9e5a0c09450b892151dbec49b8dc. Allowing rebase to start in a dirty tree might have been a worthy goal, but it is not necessarily always wanted (some people prefer to be reminded that the state is dirty, and think about the next action that may not be to stash and proceed). Furthermore, depending on the nature of local changes, unstashing the dirty state on top of the rebased result is not always desirable. Signed-off-by: Junio C Hamano --- git-rebase.sh | 72 ++++++++++----------------------------------------- 1 file changed, 14 insertions(+), 58 deletions(-) diff --git a/git-rebase.sh b/git-rebase.sh index e342974dc0..c9942f2400 100755 --- a/git-rebase.sh +++ b/git-rebase.sh @@ -116,30 +116,10 @@ call_merge () { } finish_rb_merge () { - if test -f "$dotest/stash" - then - stash=$(cat "$dotest/stash") - git stash apply --index "$stash" - fi rm -r "$dotest" echo "All done." } -read_stash () { - if test -f "$1" - then - cat "$1" - fi -} -unstash_and_exit () { - err=$? - if test -f "$1" && test $err = 0 - then - git stash apply --index "$1" - fi - exit $err -} - is_interactive () { test -f "$dotest"/interactive || while case $#,"$1" in 0,|*,-i|*,--interactive) break ;; esac @@ -174,9 +154,8 @@ do finish_rb_merge exit fi - stash=$(read_stash ".dotest/stash") git am --resolved --3way --resolvemsg="$RESOLVEMSG" - unstash_and_exit "$stash" + exit ;; --skip) if test -d "$dotest" @@ -195,31 +174,21 @@ do finish_rb_merge exit fi - stash=$(read_stash ".dotest/stash") git am -3 --skip --resolvemsg="$RESOLVEMSG" - unstash_and_exit "$stash" + exit ;; --abort) git rerere clear if test -d "$dotest" then - if test -f "$dotest/stash" - then - stash=$(cat "$dotest/stash") - fi rm -r "$dotest" elif test -d .dotest then - if test -f ".dotest/stash" - then - stash=$(cat ".dotest/stash") - fi rm -r .dotest else die "No rebase in progress?" fi git reset --hard ORIG_HEAD - test -z "$stash" || git stash apply --index "$stash" exit ;; --onto) @@ -285,6 +254,16 @@ else fi fi +# The tree must be really really clean. +git update-index --refresh || exit +diff=$(git diff-index --cached --name-status -r HEAD) +case "$diff" in +?*) echo "cannot rebase: your index is not up-to-date" + echo "$diff" + exit 1 + ;; +esac + # The upstream head must be given. Make sure it is valid. upstream_name="$1" upstream=`git rev-parse --verify "${upstream_name}^0"` || @@ -294,19 +273,11 @@ upstream=`git rev-parse --verify "${upstream_name}^0"` || onto_name=${newbase-"$upstream_name"} onto=$(git rev-parse --verify "${onto_name}^0") || exit -# The tree must be clean enough for us to create a stash -stash=$(git stash create) || exit -if test -n "$stash" -then - echo >&2 "Stashed away your working tree changes" -fi - # If a hook exists, give it a chance to interrupt if test -x "$GIT_DIR/hooks/pre-rebase" then "$GIT_DIR/hooks/pre-rebase" ${1+"$@"} || { echo >&2 "The pre-rebase hook refused to rebase." - test -z "$stash" || git stash apply --index "$stash" exit 1 } fi @@ -315,10 +286,7 @@ fi case "$#" in 2) branch_name="$2" - git-checkout "$2" || { - test -z "$stash" || git stash apply --index "$stash" - usage - } + git-checkout "$2" || usage ;; *) if branch_name=`git symbolic-ref -q HEAD` @@ -341,7 +309,6 @@ if test "$upstream" = "$onto" && test "$mb" = "$onto" && ! git rev-list --parents "$onto".."$branch" | grep " .* " > /dev/null then echo >&2 "Current branch $branch_name is up to date." - test -z "$stash" || git stash apply --index "$stash" exit 0 fi @@ -361,7 +328,6 @@ git-reset --hard "$onto" if test "$mb" = "$branch" then echo >&2 "Fast-forwarded $branch_name to $onto_name." - test -z "$stash" || git stash apply --index "$stash" exit 0 fi @@ -369,16 +335,7 @@ if test -z "$do_merge" then git format-patch -k --stdout --full-index --ignore-if-in-upstream "$upstream"..ORIG_HEAD | git am $git_am_opt --binary -3 -k --resolvemsg="$RESOLVEMSG" - err=$? - - if test $err = 0 - then - test -z "$stash" || git stash apply --index "$stash" - exit - else - test -z "$stash" || echo "$stash" >.dotest/stash - exit $err - fi + exit $? fi # start doing a rebase with git-merge @@ -389,7 +346,6 @@ echo "$onto" > "$dotest/onto" echo "$onto_name" > "$dotest/onto_name" prev_head=`git rev-parse HEAD^0` echo "$prev_head" > "$dotest/prev_head" -test -z "$stash" || echo "$stash" >"$dotest/stash" msgnum=0 for cmt in `git rev-list --reverse --no-merges "$upstream"..ORIG_HEAD` From a64d7784e830b3140e7d0f2b45cb3d8fafb84cca Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 1 Nov 2007 14:30:30 -0700 Subject: [PATCH 0377/1490] git-merge: no reason to use cpio anymore Now we have "git stash create", we can use it to safely stash away the dirty state in the tree. Signed-off-by: Junio C Hamano --- git-merge.sh | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/git-merge.sh b/git-merge.sh index 3a01db0d75..976117ac90 100755 --- a/git-merge.sh +++ b/git-merge.sh @@ -28,20 +28,19 @@ allow_trivial_merge=t dropsave() { rm -f -- "$GIT_DIR/MERGE_HEAD" "$GIT_DIR/MERGE_MSG" \ - "$GIT_DIR/MERGE_SAVE" || exit 1 + "$GIT_DIR/MERGE_STASH" || exit 1 } savestate() { # Stash away any local modifications. - git diff-index -z --name-only $head | - cpio -0 -o >"$GIT_DIR/MERGE_SAVE" + git stash create >"$GIT_DIR/MERGE_STASH" } restorestate() { - if test -f "$GIT_DIR/MERGE_SAVE" + if test -f "$GIT_DIR/MERGE_STASH" then git reset --hard $head >/dev/null - cpio -iuv <"$GIT_DIR/MERGE_SAVE" + git stash apply $(cat "$GIT_DIR/MERGE_STASH") git update-index --refresh >/dev/null fi } @@ -386,7 +385,7 @@ case "$use_strategies" in single_strategy=no ;; *) - rm -f "$GIT_DIR/MERGE_SAVE" + rm -f "$GIT_DIR/MERGE_STASH" single_strategy=yes ;; esac From 1e3a2eb667256716e101707f4da7179da2ba3c65 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Thu, 1 Nov 2007 13:45:33 +0100 Subject: [PATCH 0378/1490] gitweb: Update config file example for snapshot feature in gitweb/INSTALL Commit a3c8ab30a54c30a6a434760bedf04548425416ef by Matt McCutchen "gitweb: snapshot cleanups & support for offering multiple formats" introduced new format of $feature{'snapshot'}{'default'} value. Update "Config file example" in gitweb/INSTALL accordingly. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/INSTALL | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gitweb/INSTALL b/gitweb/INSTALL index 6328e26f56..9cd5b0a2b1 100644 --- a/gitweb/INSTALL +++ b/gitweb/INSTALL @@ -116,7 +116,7 @@ GITWEB_CONFIG file: $feature{'pickaxe'}{'default'} = [1]; $feature{'pickaxe'}{'override'} = 1; - $feature{'snapshot'}{'default'} = ['x-gzip', 'gz', 'gzip']; + $feature{'snapshot'}{'default'} = ['zip', 'tgz']; $feature{'snapshot'}{'override'} = 1; From d9d10bb8549ca0353d13298e372c1c87bcc530ef Mon Sep 17 00:00:00 2001 From: Ralf Wildenhues Date: Thu, 1 Nov 2007 09:46:02 +0100 Subject: [PATCH 0379/1490] git-clone.txt: Improve --depth description. Avoid abbreviation 'revs', improve the language a bit. Signed-off-by: Junio C Hamano --- Documentation/git-clone.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt index 253f4f03c5..cca14d6b5d 100644 --- a/Documentation/git-clone.txt +++ b/Documentation/git-clone.txt @@ -111,11 +111,11 @@ OPTIONS --depth :: Create a 'shallow' clone with a history truncated to the - specified number of revs. A shallow repository has + specified number of revisions. A shallow repository has a number of limitations (you cannot clone or fetch from it, nor push from nor into it), but is adequate if you - want to only look at near the tip of a large project - with a long history, and would want to send in a fixes + are only interested in the recent history of a large project + with a long history, and would want to send in fixes as patches. :: From 8451c565bceaf9c402fadba16d2b9c2dcf71bbc2 Mon Sep 17 00:00:00 2001 From: Sergei Organov Date: Thu, 1 Nov 2007 16:24:11 +0300 Subject: [PATCH 0380/1490] git-filter-branch.txt: fix a typo. Signed-off-by: Sergei Organov Acked-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- Documentation/git-filter-branch.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/git-filter-branch.txt b/Documentation/git-filter-branch.txt index ba9b4fbca7..385ecc900f 100644 --- a/Documentation/git-filter-branch.txt +++ b/Documentation/git-filter-branch.txt @@ -219,7 +219,7 @@ git filter-branch --commit-filter ' fi' HEAD ------------------------------------------------------------------------------ -The function 'skip_commits' is defined as follows: +The function 'skip_commit' is defined as follows: -------------------------- skip_commit() From 136e6316705e9e83cbb09c2a9ac4cb29c3e4662d Mon Sep 17 00:00:00 2001 From: Sergei Organov Date: Thu, 1 Nov 2007 17:21:39 +0300 Subject: [PATCH 0381/1490] git-format-patch.txt: fix explanation of an example. Signed-off-by: Sergei Organov Signed-off-by: Junio C Hamano --- Documentation/git-format-patch.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt index c9857a2d62..f0617efa0a 100644 --- a/Documentation/git-format-patch.txt +++ b/Documentation/git-format-patch.txt @@ -168,7 +168,7 @@ git-format-patch origin:: is created in the current directory. git-format-patch \--root origin:: - Extract all commits which that leads to 'origin' since the + Extract all commits that lead to 'origin' since the inception of the project. git-format-patch -M -B origin:: From 93ff3f6a5311ebb6347b817d1c57c94dbbe4de73 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Thu, 1 Nov 2007 16:59:55 -0400 Subject: [PATCH 0382/1490] return the prune-packed progress display to the inner loop This reverts commit 0e549137966feb016927a827fb6e359aec8264a3 so to return to the same state as commit b5d72f0a4cd3cce945ca0d37e4fa0ebbfcdcdb52. On Wed, 31 Oct 2007, Shawn O. Pearce wrote: > During my testing with a 40,000 loose object case (yea, I fully > unpacked a git.git clone I had laying around) my system stalled > hard in the first object directory. A *lot* longer than 1 second. > So I got no progress meter for a long time, and then a progress > meter appeared on the second directory. Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- builtin-prune-packed.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/builtin-prune-packed.c b/builtin-prune-packed.c index f4287dad10..23faf3129f 100644 --- a/builtin-prune-packed.c +++ b/builtin-prune-packed.c @@ -15,8 +15,6 @@ static void prune_dir(int i, DIR *dir, char *pathname, int len, int opts) struct dirent *de; char hex[40]; - display_progress(progress, i + 1); - sprintf(hex, "%02x", i); while ((de = readdir(dir)) != NULL) { unsigned char sha1[20]; @@ -32,6 +30,7 @@ static void prune_dir(int i, DIR *dir, char *pathname, int len, int opts) printf("rm -f %s\n", pathname); else if (unlink(pathname) < 0) error("unable to unlink %s", pathname); + display_progress(progress, i + 1); } pathname[len] = 0; rmdir(pathname); From 3e935d19822db08cc0dedd8764135771ffd6ec7b Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Thu, 1 Nov 2007 16:59:56 -0400 Subject: [PATCH 0383/1490] make sure throughput display gets updated even if progress doesn't move Currently the progress/throughput display update happens only through display_progress(). If the progress based on object count remains unchanged because a large object is being received, the latest throughput won't be displayed. The display update should occur through display_throughput() as well. Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- progress.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/progress.c b/progress.c index 34a59611fb..39d5d2c9f2 100644 --- a/progress.c +++ b/progress.c @@ -160,6 +160,9 @@ void display_throughput(struct progress *progress, unsigned long n) tp->last_misecs[tp->idx] = misecs; tp->idx = (tp->idx + 1) % TP_IDX_MAX; tp->count = 0; + + if (progress->last_value != -1 && progress_update) + display(progress, progress->last_value, 0); } } From 81f6654a47075a345ba63a394921f77fc87b6500 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Thu, 1 Nov 2007 16:59:57 -0400 Subject: [PATCH 0384/1490] Show total transferred as part of throughput progress Right now it is infeasible to offer to the user a reasonable concept of when a clone will be complete as we aren't able to come up with the final pack size until after we have actually transferred the entire thing to the client. However in many cases users can work with a rough rule-of-thumb; for example it is somewhat well known that git.git is about 16 MiB today and that linux-2.6.git is over 120 MiB. We now show the total amount of data we have transferred over the network as part of the throughput meter, organizing it in "human friendly" terms like `ls -h` would do. Users can glance at this, see that the total transferred size is about 3 MiB, see the throughput of X KiB/sec, and determine a reasonable figure of about when the clone will be complete, assuming they know the rough size of the source repository or are able to obtain it. This is also a helpful indicator that there is progress being made even if we stall on a very large object. The thoughput meter may remain relatively constant and the percentage complete and object count won't be changing, but the total transferred will be increasing as additional data is received for this object. [from an initial proposal from Shawn O. Pearce] Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- progress.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/progress.c b/progress.c index 39d5d2c9f2..3f6a602a53 100644 --- a/progress.c +++ b/progress.c @@ -15,13 +15,14 @@ struct throughput { struct timeval prev_tv; + off_t total; unsigned long count; unsigned long avg_bytes; unsigned long last_bytes[TP_IDX_MAX]; unsigned int avg_misecs; unsigned int last_misecs[TP_IDX_MAX]; unsigned int idx; - char display[20]; + char display[32]; }; struct progress { @@ -128,6 +129,7 @@ void display_throughput(struct progress *progress, unsigned long n) return; } + tp->total += n; tp->count += n; /* @@ -149,11 +151,32 @@ void display_throughput(struct progress *progress, unsigned long n) misecs += (int)(tv.tv_usec - tp->prev_tv.tv_usec) / 977; if (misecs > 512) { + int l = sizeof(tp->display); tp->prev_tv = tv; tp->avg_bytes += tp->count; tp->avg_misecs += misecs; - snprintf(tp->display, sizeof(tp->display), - ", %lu KiB/s", tp->avg_bytes / tp->avg_misecs); + + if (tp->total > 1 << 30) { + l -= snprintf(tp->display, l, ", %u.%2.2u GiB", + (int)(tp->total >> 30), + (int)(tp->total & ((1 << 30) - 1)) / 10737419); + } else if (tp->total > 1 << 20) { + l -= snprintf(tp->display, l, ", %u.%2.2u MiB", + (int)(tp->total >> 20), + ((int)(tp->total & ((1 << 20) - 1)) + * 100) >> 20); + } else if (tp->total > 1 << 10) { + l -= snprintf(tp->display, l, ", %u.%2.2u KiB", + (int)(tp->total >> 10), + ((int)(tp->total & ((1 << 10) - 1)) + * 100) >> 10); + } else { + l -= snprintf(tp->display, l, ", %u bytes", + (int)tp->total); + } + snprintf(tp->display + sizeof(tp->display) - l, l, + " | %lu KiB/s", tp->avg_bytes / tp->avg_misecs); + tp->avg_bytes -= tp->last_bytes[tp->idx]; tp->avg_misecs -= tp->last_misecs[tp->idx]; tp->last_bytes[tp->idx] = tp->count; From f31dfa604c83fd998f7b57942a7bac4defc8c435 Mon Sep 17 00:00:00 2001 From: Alex Riesen Date: Thu, 1 Nov 2007 15:01:58 +0100 Subject: [PATCH 0385/1490] Do no colorify test output if stdout is not a terminal like when the output is redirected into a file in a cron job. Signed-off-by: Junio C Hamano --- t/test-lib.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/t/test-lib.sh b/t/test-lib.sh index 714de6e575..603a8cd5e7 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -60,6 +60,7 @@ esac # . ./test-lib.sh [ "x$TERM" != "xdumb" ] && + [ -t 1 ] && tput bold >/dev/null 2>&1 && tput setaf 1 >/dev/null 2>&1 && tput sgr0 >/dev/null 2>&1 && From 9e6c723087def70d001740db48cf042b77a1d9cd Mon Sep 17 00:00:00 2001 From: Gerrit Pape Date: Wed, 31 Oct 2007 13:59:16 +0000 Subject: [PATCH 0386/1490] git-diff.txt: add section "output format" describing the diff formats git-diff.txt includes diff-options.txt which for the -p option refers to a section "generating patches.." which is missing from the git-diff documentation. This patch adapts diff-format.txt to additionally mention the git-diff program, and includes diff-format.txt into git-diff.txt. Tino Keitel noticed this problem. Signed-off-by: Gerrit Pape Signed-off-by: Junio C Hamano --- Documentation/diff-format.txt | 19 ++++++++++--------- Documentation/git-diff.txt | 3 +++ 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/Documentation/diff-format.txt b/Documentation/diff-format.txt index 001503205b..9709c35c98 100644 --- a/Documentation/diff-format.txt +++ b/Documentation/diff-format.txt @@ -1,5 +1,5 @@ -The output format from "git-diff-index", "git-diff-tree" and -"git-diff-files" are very similar. +The output format from "git-diff-index", "git-diff-tree", +"git-diff-files" and "git diff --raw" are very similar. These commands all compare two sets of things; what is compared differs: @@ -62,7 +62,8 @@ respectively. diff format for merges ---------------------- -"git-diff-tree" and "git-diff-files" can take '-c' or '--cc' option +"git-diff-tree", "git-diff-files" and "git-diff --raw" +can take '-c' or '--cc' option to generate diff output also for merge commits. The output differs from the format described above in the following way: @@ -86,10 +87,10 @@ Generating patches with -p -------------------------- When "git-diff-index", "git-diff-tree", or "git-diff-files" are run -with a '-p' option, they do not produce the output described above; -instead they produce a patch file. You can customize the creation -of such patches via the GIT_EXTERNAL_DIFF and the GIT_DIFF_OPTS -environment variables. +with a '-p' option, or "git diff" without the '--raw' option, they +do not produce the output described above; instead they produce a +patch file. You can customize the creation of such patches via the +GIT_EXTERNAL_DIFF and the GIT_DIFF_OPTS environment variables. What the -p option produces is slightly different from the traditional diff format. @@ -137,8 +138,8 @@ file made it into the new one. combined diff format -------------------- -git-diff-tree and git-diff-files can take '-c' or '--cc' option -to produce 'combined diff', which looks like this: +"git-diff-tree", "git-diff-files" and "git-diff" can take '-c' or +'--cc' option to produce 'combined diff', which looks like this: ------------ diff --combined describe.c diff --git a/Documentation/git-diff.txt b/Documentation/git-diff.txt index db2eb46a19..201d5daf1a 100644 --- a/Documentation/git-diff.txt +++ b/Documentation/git-diff.txt @@ -82,6 +82,9 @@ include::diff-options.txt[] the diff to the named paths (you can give directory names and get diff for all files under them). +Output format +------------- +include::diff-format.txt[] EXAMPLES -------- From 4593fb84051d39f65cec81958e91056986e4682f Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 31 Oct 2007 14:55:17 -0700 Subject: [PATCH 0387/1490] format-patch -s: add MIME encoding header if signer's name requires so When the body of the commit log message contains a non-ASCII character, format-patch correctly emitted the encoding header to mark the resulting message as such. However, if the original message was fully ASCII, the command line switch "-s" was given to add a new sign-off, and the signer's name was not ASCII only, the resulting message would have contained non-ASCII character but was not marked as such. Signed-off-by: Junio C Hamano --- builtin-branch.c | 2 +- builtin-log.c | 2 +- builtin-rev-list.c | 3 ++- builtin-show-branch.c | 2 +- commit.c | 5 ++--- commit.h | 4 +++- log-tree.c | 15 ++++++++++++++- 7 files changed, 24 insertions(+), 9 deletions(-) diff --git a/builtin-branch.c b/builtin-branch.c index 3da8b55b8f..3e020ccf17 100644 --- a/builtin-branch.c +++ b/builtin-branch.c @@ -276,7 +276,7 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose, commit = lookup_commit(item->sha1); if (commit && !parse_commit(commit)) { pretty_print_commit(CMIT_FMT_ONELINE, commit, - &subject, 0, NULL, NULL, 0); + &subject, 0, NULL, NULL, 0, 0); sub = subject.buf; } printf("%c %s%-*s%s %s %s\n", c, branch_get_color(color), diff --git a/builtin-log.c b/builtin-log.c index e8b982db7c..8b2bf632c5 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -787,7 +787,7 @@ int cmd_cherry(int argc, const char **argv, const char *prefix) struct strbuf buf; strbuf_init(&buf, 0); pretty_print_commit(CMIT_FMT_ONELINE, commit, - &buf, 0, NULL, NULL, 0); + &buf, 0, NULL, NULL, 0, 0); printf("%c %s %s\n", sign, sha1_to_hex(commit->object.sha1), buf.buf); strbuf_release(&buf); diff --git a/builtin-rev-list.c b/builtin-rev-list.c index 44393320e8..697046723f 100644 --- a/builtin-rev-list.c +++ b/builtin-rev-list.c @@ -86,7 +86,8 @@ static void show_commit(struct commit *commit) struct strbuf buf; strbuf_init(&buf, 0); pretty_print_commit(revs.commit_format, commit, - &buf, revs.abbrev, NULL, NULL, revs.date_mode); + &buf, revs.abbrev, NULL, NULL, + revs.date_mode, 0); if (buf.len) printf("%s%c", buf.buf, hdr_termination); strbuf_release(&buf); diff --git a/builtin-show-branch.c b/builtin-show-branch.c index 07a0c2316b..6dc835d30a 100644 --- a/builtin-show-branch.c +++ b/builtin-show-branch.c @@ -266,7 +266,7 @@ static void show_one_commit(struct commit *commit, int no_name) strbuf_init(&pretty, 0); if (commit->object.parsed) { pretty_print_commit(CMIT_FMT_ONELINE, commit, - &pretty, 0, NULL, NULL, 0); + &pretty, 0, NULL, NULL, 0, 0); pretty_str = pretty.buf; } if (!prefixcmp(pretty_str, "[PATCH] ")) diff --git a/commit.c b/commit.c index ac24266e93..8262f6ac58 100644 --- a/commit.c +++ b/commit.c @@ -479,7 +479,7 @@ static int get_one_line(const char *msg) } /* High bit set, or ISO-2022-INT */ -static int non_ascii(int ch) +int non_ascii(int ch) { ch = (ch & 0xff); return ((ch & 0x80) || (ch == 0x1b)); @@ -1046,12 +1046,11 @@ static void pp_remainder(enum cmit_fmt fmt, void pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit, struct strbuf *sb, int abbrev, const char *subject, const char *after_subject, - enum date_mode dmode) + enum date_mode dmode, int plain_non_ascii) { unsigned long beginning_of_body; int indent = 4; const char *msg = commit->buffer; - int plain_non_ascii = 0; char *reencoded; const char *encoding; diff --git a/commit.h b/commit.h index b661503972..13b537293d 100644 --- a/commit.h +++ b/commit.h @@ -61,13 +61,15 @@ enum cmit_fmt { CMIT_FMT_UNSPECIFIED, }; +extern int non_ascii(int); extern enum cmit_fmt get_commit_format(const char *arg); extern void format_commit_message(const struct commit *commit, const void *format, struct strbuf *sb); extern void pretty_print_commit(enum cmit_fmt fmt, const struct commit*, struct strbuf *, int abbrev, const char *subject, - const char *after_subject, enum date_mode); + const char *after_subject, enum date_mode, + int non_ascii_present); /** Removes the first commit from a list sorted by date, and adds all * of its parents. diff --git a/log-tree.c b/log-tree.c index 3763ce94fc..a34beb0b02 100644 --- a/log-tree.c +++ b/log-tree.c @@ -125,6 +125,18 @@ static unsigned int digits_in_number(unsigned int number) return result; } +static int has_non_ascii(const char *s) +{ + int ch; + if (!s) + return 0; + while ((ch = *s++) != '\0') { + if (non_ascii(ch)) + return 1; + } + return 0; +} + void show_log(struct rev_info *opt, const char *sep) { struct strbuf msgbuf; @@ -273,7 +285,8 @@ void show_log(struct rev_info *opt, const char *sep) */ strbuf_init(&msgbuf, 0); pretty_print_commit(opt->commit_format, commit, &msgbuf, - abbrev, subject, extra_headers, opt->date_mode); + abbrev, subject, extra_headers, opt->date_mode, + has_non_ascii(opt->add_signoff)); if (opt->add_signoff) append_signoff(&msgbuf, opt->add_signoff); From 648ee5500920b49a5ee5822076104b9304ec97c8 Mon Sep 17 00:00:00 2001 From: Robin Rosenberg Date: Wed, 31 Oct 2007 23:12:20 +0100 Subject: [PATCH 0388/1490] cvsexportcommit: Add switch to specify CVS workdir Signed-off-by: Robin Rosenberg Signed-off-by: Junio C Hamano --- Documentation/git-cvsexportcommit.txt | 22 +++++++++++---- git-cvsexportcommit.perl | 39 ++++++++++++++++++--------- 2 files changed, 44 insertions(+), 17 deletions(-) diff --git a/Documentation/git-cvsexportcommit.txt b/Documentation/git-cvsexportcommit.txt index c3922f9238..3f9d2295d3 100644 --- a/Documentation/git-cvsexportcommit.txt +++ b/Documentation/git-cvsexportcommit.txt @@ -8,7 +8,7 @@ git-cvsexportcommit - Export a single commit to a CVS checkout SYNOPSIS -------- -'git-cvsexportcommit' [-h] [-u] [-v] [-c] [-P] [-p] [-a] [-d cvsroot] [-f] [-m msgprefix] [PARENTCOMMIT] COMMITID +'git-cvsexportcommit' [-h] [-u] [-v] [-c] [-P] [-p] [-a] [-d cvsroot] [-w cvsworkdir] [-f] [-m msgprefix] [PARENTCOMMIT] COMMITID DESCRIPTION @@ -16,8 +16,9 @@ DESCRIPTION Exports a commit from GIT to a CVS checkout, making it easier to merge patches from a git repository into a CVS repository. -Execute it from the root of the CVS working copy. GIT_DIR must be defined. -See examples below. +Specify the name of a CVS checkout using the -w switch or execute it +from the root of the CVS working copy. In the latter case GIT_DIR must +be defined. See examples below. It does its best to do the safe thing, it will check that the files are unchanged and up to date in the CVS checkout, and it will not autocommit @@ -61,6 +62,11 @@ OPTIONS -u:: Update affected files from CVS repository before attempting export. +-w:: + Specify the location of the CVS checkout to use for the export. This + option does not require GIT_DIR to be set before execution if the + current directory is within a git repository. + -v:: Verbose. @@ -76,6 +82,12 @@ $ git-cvsexportcommit -v $ cvs commit -F .msg ------------ +Merge one patch into CVS (-c and -w options). The working directory is within the Git Repo:: ++ +------------ + $ git-cvsexportcommit -v -c -w ~/project_cvs_checkout +------------ + Merge pending patches into CVS automatically -- only if you really know what you are doing:: + ------------ @@ -86,11 +98,11 @@ $ git-cherry cvshead myhead | sed -n 's/^+ //p' | xargs -l1 git-cvsexportcommit Author ------ -Written by Martin Langhoff +Written by Martin Langhoff and others. Documentation -------------- -Documentation by Martin Langhoff +Documentation by Martin Langhoff and others. GIT --- diff --git a/git-cvsexportcommit.perl b/git-cvsexportcommit.perl index 26844af439..92e41620fd 100755 --- a/git-cvsexportcommit.perl +++ b/git-cvsexportcommit.perl @@ -1,28 +1,42 @@ #!/usr/bin/perl -w -# Known limitations: -# - does not propagate permissions -# - error handling has not been extensively tested -# - use strict; use Getopt::Std; use File::Temp qw(tempdir); use Data::Dumper; use File::Basename qw(basename dirname); -unless ($ENV{GIT_DIR} && -r $ENV{GIT_DIR}){ - die "GIT_DIR is not defined or is unreadable"; -} +our ($opt_h, $opt_P, $opt_p, $opt_v, $opt_c, $opt_f, $opt_a, $opt_m, $opt_d, $opt_u, $opt_w); -our ($opt_h, $opt_P, $opt_p, $opt_v, $opt_c, $opt_f, $opt_a, $opt_m, $opt_d, $opt_u); - -getopts('uhPpvcfam:d:'); +getopts('uhPpvcfam:d:w:'); $opt_h && usage(); die "Need at least one commit identifier!" unless @ARGV; +if ($opt_w) { + unless ($ENV{GIT_DIR}) { + # Remember where our GIT_DIR is before changing to CVS checkout + my $gd =`git-rev-parse --git-dir`; + chomp($gd); + if ($gd eq '.git') { + my $wd = `pwd`; + chomp($wd); + $gd = $wd."/.git" ; + } + $ENV{GIT_DIR} = $gd; + } + + if (! -d $opt_w."/CVS" ) { + die "$opt_w is not a CVS checkout"; + } + chdir $opt_w or die "Cannot change to CVS checkout at $opt_w"; +} +unless ($ENV{GIT_DIR} && -r $ENV{GIT_DIR}){ + die "GIT_DIR is not defined or is unreadable"; +} + + my @cvs; if ($opt_d) { @cvs = ('cvs', '-d', $opt_d); @@ -274,6 +288,7 @@ print "You'll need to apply the patch in .cvsexportcommit.diff manually\n"; print "using a patch program. After applying the patch and resolving the\n"; print "problems you may commit using:"; + print "\n cd \"$opt_w\"" if $opt_w; print "\n $cmd\n\n"; exit(1); } @@ -301,7 +316,7 @@ sub usage { print STDERR < Date: Thu, 1 Nov 2007 12:38:08 +0100 Subject: [PATCH 0389/1490] gitweb: Always set 'from_file' and 'to_file' in parse_difftree_raw_line Always set 'from_file' and 'to_file' keys when parsing raw diff output format line, even if filename didn't change (file was not renamed). This allows for simpler code. Previously, you would have written: $diffinfo->{'from_file'} || $diffinfo->{'file'} but now you can just use $diffinfo->{'from_file'} as 'from_file' is always defined. While at it, replace (for merge commits) $diffinfo->{'from_file'}[$i] || $diffinfo->{'to_file'} by defined $diffinfo->{'from_file'}[$i] ? $diffinfo->{'from_file'}[$i] : $diffinfo->{'to_file'}; to have no problems with file named '0'. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 2e00756276..b22f4be152 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1995,7 +1995,7 @@ sub parse_difftree_raw_line { if ($res{'status'} eq 'R' || $res{'status'} eq 'C') { # renamed or copied ($res{'from_file'}, $res{'to_file'}) = map { unquote($_) } split("\t", $7); } else { - $res{'file'} = unquote($7); + $res{'from_file'} = $res{'to_file'} = $res{'file'} = unquote($7); } } # '::100755 100755 100755 60e79ca1b01bc8b057abe17ddab484699a7f5fdb 94067cc5f73388f33722d52ae02f44692bc07490 94067cc5f73388f33722d52ae02f44692bc07490 MR git-gui/git-gui.sh' @@ -2062,7 +2062,10 @@ sub parse_from_to_diffinfo { fill_from_file_info($diffinfo, @parents) unless exists $diffinfo->{'from_file'}; for (my $i = 0; $i < $diffinfo->{'nparents'}; $i++) { - $from->{'file'}[$i] = $diffinfo->{'from_file'}[$i] || $diffinfo->{'to_file'}; + $from->{'file'}[$i] = + defined $diffinfo->{'from_file'}[$i] ? + $diffinfo->{'from_file'}[$i] : + $diffinfo->{'to_file'}; if ($diffinfo->{'status'}[$i] ne "A") { # not new (added) file $from->{'href'}[$i] = href(action=>"blob", hash_base=>$parents[$i], @@ -2074,7 +2077,7 @@ sub parse_from_to_diffinfo { } } else { # ordinary (not combined) diff - $from->{'file'} = $diffinfo->{'from_file'} || $diffinfo->{'file'}; + $from->{'file'} = $diffinfo->{'from_file'}; if ($diffinfo->{'status'} ne "A") { # not new (added) file $from->{'href'} = href(action=>"blob", hash_base=>$hash_parent, hash=>$diffinfo->{'from_id'}, @@ -2084,7 +2087,7 @@ sub parse_from_to_diffinfo { } } - $to->{'file'} = $diffinfo->{'to_file'} || $diffinfo->{'file'}; + $to->{'file'} = $diffinfo->{'to_file'}; if (!is_deleted($diffinfo)) { # file exists in result $to->{'href'} = href(action=>"blob", hash_base=>$hash, hash=>$diffinfo->{'to_id'}, @@ -2829,7 +2832,7 @@ sub is_patch_split { my ($diffinfo, $patchinfo) = @_; return defined $diffinfo && defined $patchinfo - && ($diffinfo->{'to_file'} || $diffinfo->{'file'}) eq $patchinfo->{'to_file'}; + && $diffinfo->{'to_file'} eq $patchinfo->{'to_file'}; } @@ -4667,8 +4670,8 @@ sub git_blobdiff { } %diffinfo = parse_difftree_raw_line($difftree[0]); - $file_parent ||= $diffinfo{'from_file'} || $file_name || $diffinfo{'file'}; - $file_name ||= $diffinfo{'to_file'} || $diffinfo{'file'}; + $file_parent ||= $diffinfo{'from_file'} || $file_name; + $file_name ||= $diffinfo{'to_file'}; $hash_parent ||= $diffinfo{'from_id'}; $hash ||= $diffinfo{'to_id'}; From 6aa6f92fda47cc4ee5f599895e8a5a327fb6f9ab Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Thu, 1 Nov 2007 12:38:09 +0100 Subject: [PATCH 0390/1490] gitweb: Add 'status_str' to parse_difftree_raw_line output Add 'status_str' to diffinfo output, which stores status (also for merge commit) as a string. This allows for easy checking if there is given status among all for merge commit, e.g. $diffinfo->{'status_str'} =~ /D/; Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index b22f4be152..abb5a7d39f 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1990,7 +1990,7 @@ sub parse_difftree_raw_line { $res{'to_mode'} = $2; $res{'from_id'} = $3; $res{'to_id'} = $4; - $res{'status'} = $5; + $res{'status'} = $res{'status_str'} = $5; $res{'similarity'} = $6; if ($res{'status'} eq 'R' || $res{'status'} eq 'C') { # renamed or copied ($res{'from_file'}, $res{'to_file'}) = map { unquote($_) } split("\t", $7); @@ -2006,6 +2006,7 @@ sub parse_difftree_raw_line { $res{'to_mode'} = pop @{$res{'from_mode'}}; $res{'from_id'} = [ split(' ', $3) ]; $res{'to_id'} = pop @{$res{'from_id'}}; + $res{'status_str'} = $4; $res{'status'} = [ split('', $4) ]; $res{'to_file'} = unquote($5); } @@ -2821,7 +2822,7 @@ sub fill_from_file_info { sub is_deleted { my $diffinfo = shift; - return $diffinfo->{'to_id'} eq ('0' x 40); + return $diffinfo->{'status_str'} =~ /D/; } # does patch correspond to [previous] difftree raw line From fa9aff463da42feea68228ca51685cd9f4403e92 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Thu, 1 Nov 2007 14:23:16 +0100 Subject: [PATCH 0391/1490] gitweb: Remove CGI::Carp::set_programname() call from t9500 gitweb test It does appear to do nothing; gitweb is run as standalone program and not as CGI script in this test. This call caused problems later. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- t/t9500-gitweb-standalone-no-errors.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/t/t9500-gitweb-standalone-no-errors.sh b/t/t9500-gitweb-standalone-no-errors.sh index f7bad5bb2f..1bf0988d9a 100755 --- a/t/t9500-gitweb-standalone-no-errors.sh +++ b/t/t9500-gitweb-standalone-no-errors.sh @@ -31,7 +31,6 @@ our \$projects_list = ""; our \$export_ok = ""; our \$strict_export = ""; -CGI::Carp::set_programname("gitweb/gitweb.cgi"); EOF cat >.git/description < Date: Thu, 1 Nov 2007 13:06:27 +0100 Subject: [PATCH 0392/1490] gitweb: Easier adding/changing parameters to current URL Add boolean option '-replay' to href() subroutine, which is used to generate links in gitweb. This option "replays" current URL, overriding it with provided parameters. It means that current value of each CGI parameter is used unless otherwise provided. This change is meant to make it easier to generate links which differ from current page URL only by one parameter, for example the same view but sorted by different column: href(-replay=>1, order=>"age") or view which differs by some option, e.g. in log views href(-replay=>1, extra_options=>"--no-merges") or alternate view of the same object, e.g. in the 'blob' view href(-replay=>1, action=>"blob_plain") Actual use of this functionality is left for later. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index abb5a7d39f..c93c546fbf 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -611,6 +611,15 @@ (%) ); my %mapping = @mapping; + if ($params{-replay}) { + while (my ($name, $symbol) = each %mapping) { + if (!exists $params{$name}) { + # to allow for multivalued params we use arrayref form + $params{$name} = [ $cgi->param($symbol) ]; + } + } + } + $params{'project'} = $project unless exists $params{'project'}; my ($use_pathinfo) = gitweb_check_feature('pathinfo'); From 7afd77bfc1b6881fd9e476274d3f08b793c292ed Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Thu, 1 Nov 2007 13:06:28 +0100 Subject: [PATCH 0393/1490] gitweb: Use href(-replay=>1, page=>...) to generate pagination links Use href(-replay=>1, page=>$page-1) and href(-replay=>1, page=>$page+1) to generate previous page and next page links. Generate next page link only once. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 48 ++++++++++++++++------------------------------ 1 file changed, 17 insertions(+), 31 deletions(-) diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index c93c546fbf..d2adae31c8 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -2518,7 +2518,7 @@ sub format_paging_nav { if ($page > 0) { $paging_nav .= " ⋅ " . - $cgi->a({-href => href(action=>$action, hash=>$hash, page=>$page-1), + $cgi->a({-href => href(-replay=>1, page=>$page-1), -accesskey => "p", -title => "Alt-p"}, "prev"); } else { $paging_nav .= " ⋅ prev"; @@ -2526,7 +2526,7 @@ sub format_paging_nav { if ($nrevs >= (100 * ($page+1)-1)) { $paging_nav .= " ⋅ " . - $cgi->a({-href => href(action=>$action, hash=>$hash, page=>$page+1), + $cgi->a({-href => href(-replay=>1, page=>$page+1), -accesskey => "n", -title => "Alt-n"}, "next"); } else { $paging_nav .= " ⋅ next"; @@ -4448,7 +4448,7 @@ sub git_log { } if ($#commitlist >= 100) { print "
\n"; - print $cgi->a({-href => href(action=>"log", hash=>$hash, page=>$page+1), + print $cgi->a({-href => href(-replay=>1, page=>$page+1), -accesskey => "n", -title => "Alt-n"}, "next"); print "
\n"; } @@ -5015,27 +5015,20 @@ sub git_history { file_name=>$file_name)}, "first"); $paging_nav .= " ⋅ " . - $cgi->a({-href => href(action=>"history", hash=>$hash, hash_base=>$hash_base, - file_name=>$file_name, page=>$page-1), + $cgi->a({-href => href(-replay=>1, page=>$page-1), -accesskey => "p", -title => "Alt-p"}, "prev"); } else { $paging_nav .= "first"; $paging_nav .= " ⋅ prev"; } - if ($#commitlist >= 100) { - $paging_nav .= " ⋅ " . - $cgi->a({-href => href(action=>"history", hash=>$hash, hash_base=>$hash_base, - file_name=>$file_name, page=>$page+1), - -accesskey => "n", -title => "Alt-n"}, "next"); - } else { - $paging_nav .= " ⋅ next"; - } my $next_link = ''; if ($#commitlist >= 100) { $next_link = - $cgi->a({-href => href(action=>"history", hash=>$hash, hash_base=>$hash_base, - file_name=>$file_name, page=>$page+1), + $cgi->a({-href => href(-replay=>1, page=>$page+1), -accesskey => "n", -title => "Alt-n"}, "next"); + $paging_nav .= " ⋅ $next_link"; + } else { + $paging_nav .= " ⋅ next"; } git_header_html(); @@ -5105,30 +5098,23 @@ sub git_search { searchtext=>$searchtext, searchtype=>$searchtype)}, "first"); $paging_nav .= " ⋅ " . - $cgi->a({-href => href(action=>"search", hash=>$hash, - searchtext=>$searchtext, searchtype=>$searchtype, - page=>$page-1), + $cgi->a({-href => href(-replay=>1, page=>$page-1), -accesskey => "p", -title => "Alt-p"}, "prev"); } else { $paging_nav .= "first"; $paging_nav .= " ⋅ prev"; } - if ($#commitlist >= 100) { - $paging_nav .= " ⋅ " . - $cgi->a({-href => href(action=>"search", hash=>$hash, - searchtext=>$searchtext, searchtype=>$searchtype, - page=>$page+1), - -accesskey => "n", -title => "Alt-n"}, "next"); - } else { - $paging_nav .= " ⋅ next"; - } my $next_link = ''; if ($#commitlist >= 100) { $next_link = - $cgi->a({-href => href(action=>"search", hash=>$hash, - searchtext=>$searchtext, searchtype=>$searchtype, - page=>$page+1), + $cgi->a({-href => href(-replay=>1, page=>$page+1), -accesskey => "n", -title => "Alt-n"}, "next"); + $paging_nav .= " ⋅ $next_link"; + } else { + $paging_nav .= " ⋅ next"; + } + + if ($#commitlist >= 100) { } git_print_page_nav('','', $hash,$co{'tree'},$hash, $paging_nav); @@ -5327,7 +5313,7 @@ sub git_shortlog { my $next_link = ''; if ($#commitlist >= 100) { $next_link = - $cgi->a({-href => href(action=>"shortlog", hash=>$hash, page=>$page+1), + $cgi->a({-href => href(-replay=>1, page=>$page+1), -accesskey => "n", -title => "Alt-n"}, "next"); } From a3823e5ad75498774a32850f44e8254b0e1c0901 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Thu, 1 Nov 2007 13:06:29 +0100 Subject: [PATCH 0394/1490] gitweb: Use href(-replay=>1, action=>...) to generate alternate views Use href(action=>..., -replay=>1) to generate links to alternate views of current page in the $formats_nav (bottom) part of page_nav navigation bar. This form is used only when all parameters are repeated, and when the replay form is shorter. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index d2adae31c8..ecb0113a79 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -3911,11 +3911,11 @@ sub git_blame2 { or die_error(undef, "Open git-blame failed"); git_header_html(); my $formats_nav = - $cgi->a({-href => href(action=>"blob", hash=>$hash, hash_base=>$hash_base, file_name=>$file_name)}, + $cgi->a({-href => href(action=>"blob", -replay=>1)}, "blob") . " | " . - $cgi->a({-href => href(action=>"history", hash=>$hash, hash_base=>$hash_base, file_name=>$file_name)}, - "history") . + $cgi->a({-href => href(action=>"history", -replay=>1)}, + "history") . " | " . $cgi->a({-href => href(action=>"blame", file_name=>$file_name)}, "HEAD"); @@ -4191,18 +4191,15 @@ sub git_blob { if (defined $file_name) { if ($have_blame) { $formats_nav .= - $cgi->a({-href => href(action=>"blame", hash_base=>$hash_base, - hash=>$hash, file_name=>$file_name)}, + $cgi->a({-href => href(action=>"blame", -replay=>1)}, "blame") . " | "; } $formats_nav .= - $cgi->a({-href => href(action=>"history", hash_base=>$hash_base, - hash=>$hash, file_name=>$file_name)}, + $cgi->a({-href => href(action=>"history", -replay=>1)}, "history") . " | " . - $cgi->a({-href => href(action=>"blob_plain", - hash=>$hash, file_name=>$file_name)}, + $cgi->a({-href => href(action=>"blob_plain", -replay=>1)}, "raw") . " | " . $cgi->a({-href => href(action=>"blob", @@ -4210,7 +4207,8 @@ sub git_blob { "HEAD"); } else { $formats_nav .= - $cgi->a({-href => href(action=>"blob_plain", hash=>$hash)}, "raw"); + $cgi->a({-href => href(action=>"blob_plain", -replay=>1)}, + "raw"); } git_print_page_nav('','', $hash_base,$co{'tree'},$hash_base, $formats_nav); git_print_header_div('commit', esc_html($co{'title'}), $hash_base); @@ -4273,8 +4271,7 @@ sub git_tree { my @views_nav = (); if (defined $file_name) { push @views_nav, - $cgi->a({-href => href(action=>"history", hash_base=>$hash_base, - hash=>$hash, file_name=>$file_name)}, + $cgi->a({-href => href(action=>"history", -replay=>1)}, "history"), $cgi->a({-href => href(action=>"tree", hash_base=>"HEAD", file_name=>$file_name)}, @@ -4742,10 +4739,7 @@ sub git_blobdiff { # header if ($format eq 'html') { my $formats_nav = - $cgi->a({-href => href(action=>"blobdiff_plain", - hash=>$hash, hash_parent=>$hash_parent, - hash_base=>$hash_base, hash_parent_base=>$hash_parent_base, - file_name=>$file_name, file_parent=>$file_parent)}, + $cgi->a({-href => href(action=>"blobdiff_plain", -replay=>1)}, "raw"); git_header_html(undef, $expires); if (defined $hash_base && (my %co = parse_commit($hash_base))) { @@ -4819,8 +4813,7 @@ sub git_commitdiff { my $formats_nav; if ($format eq 'html') { $formats_nav = - $cgi->a({-href => href(action=>"commitdiff_plain", - hash=>$hash, hash_parent=>$hash_parent)}, + $cgi->a({-href => href(action=>"commitdiff_plain", -replay=>1)}, "raw"); if (defined $hash_parent && From 44c637c8021e44253f0f8cb17391092e08b39e73 Mon Sep 17 00:00:00 2001 From: James Bowes Date: Thu, 1 Nov 2007 21:02:27 -0400 Subject: [PATCH 0395/1490] gc: use parse_options Signed-off-by: James Bowes Signed-off-by: Junio C Hamano --- builtin-gc.c | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/builtin-gc.c b/builtin-gc.c index 3a2ca4f901..c5bce893a6 100644 --- a/builtin-gc.c +++ b/builtin-gc.c @@ -12,11 +12,15 @@ #include "builtin.h" #include "cache.h" +#include "parse-options.h" #include "run-command.h" #define FAILED_RUN "failed to run %s" -static const char builtin_gc_usage[] = "git-gc [--prune] [--aggressive]"; +static const char * const builtin_gc_usage[] = { + "git-gc [options]", + NULL +}; static int pack_refs = 1; static int aggressive_window = -1; @@ -165,38 +169,34 @@ static int need_to_gc(void) int cmd_gc(int argc, const char **argv, const char *prefix) { - int i; int prune = 0; + int aggressive = 0; int auto_gc = 0; char buf[80]; + struct option builtin_gc_options[] = { + OPT_BOOLEAN(0, "prune", &prune, "prune unreferenced loose objects"), + OPT_BOOLEAN(0, "aggressive", &aggressive, "be more thorough (increased runtime)"), + OPT_BOOLEAN(0, "auto", &auto_gc, "enable auto-gc mode"), + OPT_END() + }; + git_config(gc_config); if (pack_refs < 0) pack_refs = !is_bare_repository(); - for (i = 1; i < argc; i++) { - const char *arg = argv[i]; - if (!strcmp(arg, "--prune")) { - prune = 1; - continue; + argc = parse_options(argc, argv, builtin_gc_options, builtin_gc_usage, 0); + if (argc > 0) + usage_with_options(builtin_gc_usage, builtin_gc_options); + + if (aggressive) { + append_option(argv_repack, "-f", MAX_ADD); + if (aggressive_window > 0) { + sprintf(buf, "--window=%d", aggressive_window); + append_option(argv_repack, buf, MAX_ADD); } - if (!strcmp(arg, "--aggressive")) { - append_option(argv_repack, "-f", MAX_ADD); - if (aggressive_window > 0) { - sprintf(buf, "--window=%d", aggressive_window); - append_option(argv_repack, buf, MAX_ADD); - } - continue; - } - if (!strcmp(arg, "--auto")) { - auto_gc = 1; - continue; - } - break; } - if (i != argc) - usage(builtin_gc_usage); if (auto_gc) { /* From 4d00bda2aa9dd8cd6ec4015832b80eb1273d46d7 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Thu, 1 Nov 2007 23:26:04 -0400 Subject: [PATCH 0396/1490] make the pack index version configurable It is a good idea to use pack index version 2 all the time since it has proper protection against propagation of certain pack corruptions when repacking which is not possible with index version 1, as demonstrated in test t5302. Hence this config option. The default is still pack index version 1. Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- Documentation/config.txt | 9 +++++++++ builtin-pack-objects.c | 6 ++++++ index-pack.c | 13 +++++++++++++ 3 files changed, 28 insertions(+) diff --git a/Documentation/config.txt b/Documentation/config.txt index edf50cd211..0df004ea26 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -661,6 +661,15 @@ pack.threads:: machines. The required amount of memory for the delta search window is however multiplied by the number of threads. +pack.indexVersion:: + Specify the default pack index version. Valid values are 1 for + legacy pack index used by Git versions prior to 1.5.2, and 2 for + the new pack index with capabilities for packs larger than 4 GB + as well as proper protection against the repacking of corrupted + packs. Version 2 is selected and this config option ignored + whenever the corresponding pack is larger than 2 GB. Otherwise + the default is 1. + pull.octopus:: The default merge strategy to use when pulling multiple branches at once. diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index 0be539ed7f..f4b90c1e4d 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -1773,6 +1773,12 @@ static int git_pack_config(const char *k, const char *v) #endif return 0; } + if (!strcmp(k, "pack.indexversion")) { + pack_idx_default_version = git_config_int(k, v); + if (pack_idx_default_version > 2) + die("bad pack.indexversion=%d", pack_idx_default_version); + return 0; + } return git_default_config(k, v); } diff --git a/index-pack.c b/index-pack.c index db58e05041..c0bb78a8ed 100644 --- a/index-pack.c +++ b/index-pack.c @@ -683,6 +683,17 @@ static void final(const char *final_pack_name, const char *curr_pack_name, } } +static int git_index_pack_config(const char *k, const char *v) +{ + if (!strcmp(k, "pack.indexversion")) { + pack_idx_default_version = git_config_int(k, v); + if (pack_idx_default_version > 2) + die("bad pack.indexversion=%d", pack_idx_default_version); + return 0; + } + return git_default_config(k, v); +} + int main(int argc, char **argv) { int i, fix_thin_pack = 0; @@ -693,6 +704,8 @@ int main(int argc, char **argv) struct pack_idx_entry **idx_objects; unsigned char sha1[20]; + git_config(git_index_pack_config); + for (i = 1; i < argc; i++) { const char *arg = argv[i]; From 79814f425c00129dbdbdc3c99d04af52ccc58254 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Thu, 1 Nov 2007 23:43:24 -0400 Subject: [PATCH 0397/1490] pack-objects: get rid of an ugly cast ... when calling write_idx_file(). Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- builtin-pack-objects.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index f4b90c1e4d..d0ca165c9b 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -57,7 +57,7 @@ struct object_entry { * nice "minimum seek" order. */ static struct object_entry *objects; -static struct object_entry **written_list; +static struct pack_idx_entry **written_list; static uint32_t nr_objects, nr_alloc, nr_result, nr_written; static int non_empty; @@ -579,7 +579,7 @@ static off_t write_one(struct sha1file *f, e->idx.offset = 0; return 0; } - written_list[nr_written++] = e; + written_list[nr_written++] = &e->idx; /* make sure off_t is sufficiently large not to wrap */ if (offset > offset + size) @@ -607,7 +607,7 @@ static void write_pack_file(void) if (do_progress) start_progress(&progress_state, "Writing %u objects...", "", nr_result); - written_list = xmalloc(nr_objects * sizeof(struct object_entry *)); + written_list = xmalloc(nr_objects * sizeof(*written_list)); do { unsigned char sha1[20]; @@ -654,8 +654,8 @@ static void write_pack_file(void) umask(mode); mode = 0444 & ~mode; - idx_tmp_name = write_idx_file(NULL, - (struct pack_idx_entry **) written_list, nr_written, sha1); + idx_tmp_name = write_idx_file(NULL, written_list, + nr_written, sha1); snprintf(tmpname, sizeof(tmpname), "%s-%s.pack", base_name, sha1_to_hex(sha1)); if (adjust_perm(pack_tmp_name, mode)) @@ -677,7 +677,7 @@ static void write_pack_file(void) /* mark written objects as written to previous pack */ for (j = 0; j < nr_written; j++) { - written_list[j]->idx.offset = (off_t)-1; + written_list[j]->offset = (off_t)-1; } nr_remaining -= nr_written; } while (nr_remaining && i < nr_objects); From f88a545a94cb474d370ef97dd3694d09b6ac90c1 Mon Sep 17 00:00:00 2001 From: Simon Sasburg Date: Thu, 1 Nov 2007 23:57:45 +0100 Subject: [PATCH 0398/1490] Make mailsplit and mailinfo strip whitespace from the start of the input Signed-off-by: Simon Sasburg Signed-off-by: Junio C Hamano --- builtin-mailinfo.c | 6 ++++++ builtin-mailsplit.c | 6 ++++++ t/t5100/sample.mbox | 3 +++ 3 files changed, 15 insertions(+) diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c index fb12248f82..2600847974 100644 --- a/builtin-mailinfo.c +++ b/builtin-mailinfo.c @@ -915,6 +915,7 @@ static void handle_info(void) static int mailinfo(FILE *in, FILE *out, int ks, const char *encoding, const char *msg, const char *patch) { + int peek; keep_subject = ks; metainfo_charset = encoding; fin = in; @@ -935,6 +936,11 @@ static int mailinfo(FILE *in, FILE *out, int ks, const char *encoding, p_hdr_data = xcalloc(MAX_HDR_PARSED, sizeof(char *)); s_hdr_data = xcalloc(MAX_HDR_PARSED, sizeof(char *)); + do { + peek = fgetc(in); + } while (isspace(peek)); + ungetc(peek, in); + /* process the email header */ while (read_one_header_line(line, sizeof(line), fin)) check_header(line, sizeof(line), p_hdr_data, 1); diff --git a/builtin-mailsplit.c b/builtin-mailsplit.c index 43fc373a15..74b04706f3 100644 --- a/builtin-mailsplit.c +++ b/builtin-mailsplit.c @@ -164,6 +164,7 @@ static int split_mbox(const char *file, const char *dir, int allow_bare, { char name[PATH_MAX]; int ret = -1; + int peek; FILE *f = !strcmp(file, "-") ? stdin : fopen(file, "r"); int file_done = 0; @@ -173,6 +174,11 @@ static int split_mbox(const char *file, const char *dir, int allow_bare, goto out; } + do { + peek = fgetc(f); + } while (isspace(peek)); + ungetc(peek, f); + if (fgets(buf, sizeof(buf), f) == NULL) { /* empty stdin is OK */ if (f != stdin) { diff --git a/t/t5100/sample.mbox b/t/t5100/sample.mbox index b80c981c16..070c1661b9 100644 --- a/t/t5100/sample.mbox +++ b/t/t5100/sample.mbox @@ -1,3 +1,6 @@ + + + From nobody Mon Sep 17 00:00:00 2001 From: A U Thor Date: Fri, 9 Jun 2006 00:44:16 -0700 From b43b0a3c5c313619397b2f81d5a4acad2c3cb4a9 Mon Sep 17 00:00:00 2001 From: Chris Pettitt Date: Thu, 1 Nov 2007 20:43:13 -0700 Subject: [PATCH 0399/1490] git-p4: Add a helper function to parse the full git diff-tree output. Signed-off-by: Chris Pettitt Signed-off-by: Junio C Hamano --- contrib/fast-import/git-p4 | 49 ++++++++++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index bf33f74b70..c7fc564a5b 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -71,6 +71,46 @@ def isP4Exec(kind): a plus sign, it is also executable""" return (re.search(r"(^[cku]?x)|\+.*x", kind) != None) +def diffTreePattern(): + # This is a simple generator for the diff tree regex pattern. This could be + # a class variable if this and parseDiffTreeEntry were a part of a class. + pattern = re.compile(':(\d+) (\d+) (\w+) (\w+) ([A-Z])(\d+)?\t(.*?)((\t(.*))|$)') + while True: + yield pattern + +def parseDiffTreeEntry(entry): + """Parses a single diff tree entry into its component elements. + + See git-diff-tree(1) manpage for details about the format of the diff + output. This method returns a dictionary with the following elements: + + src_mode - The mode of the source file + dst_mode - The mode of the destination file + src_sha1 - The sha1 for the source file + dst_sha1 - The sha1 fr the destination file + status - The one letter status of the diff (i.e. 'A', 'M', 'D', etc) + status_score - The score for the status (applicable for 'C' and 'R' + statuses). This is None if there is no score. + src - The path for the source file. + dst - The path for the destination file. This is only present for + copy or renames. If it is not present, this is None. + + If the pattern is not matched, None is returned.""" + + match = diffTreePattern().next().match(entry) + if match: + return { + 'src_mode': match.group(1), + 'dst_mode': match.group(2), + 'src_sha1': match.group(3), + 'dst_sha1': match.group(4), + 'status': match.group(5), + 'status_score': match.group(6), + 'src': match.group(7), + 'dst': match.group(10) + } + return None + def p4CmdList(cmd, stdin=None, stdin_mode='w+b'): cmd = "p4 -G %s" % cmd if verbose: @@ -494,13 +534,14 @@ class P4Submit(Command): else: print "Applying %s" % (read_pipe("git log --max-count=1 --pretty=oneline %s" % id)) diffOpts = ("", "-M")[self.detectRename] - diff = read_pipe_lines("git diff-tree -r --name-status %s \"%s^\" \"%s\"" % (diffOpts, id, id)) + diff = read_pipe_lines("git diff-tree -r %s \"%s^\" \"%s\"" % (diffOpts, id, id)) filesToAdd = set() filesToDelete = set() editedFiles = set() for line in diff: - modifier = line[0] - path = line[1:].strip() + diff = parseDiffTreeEntry(line) + modifier = diff['status'] + path = diff['src'] if modifier == "M": system("p4 edit \"%s\"" % path) editedFiles.add(path) @@ -513,7 +554,7 @@ class P4Submit(Command): if path in filesToAdd: filesToAdd.remove(path) elif modifier == "R": - src, dest = line.strip().split("\t")[1:3] + src, dest = diff['src'], diff['dst'] system("p4 integrate -Dt \"%s\" \"%s\"" % (src, dest)) system("p4 edit \"%s\"" % (dest)) os.unlink(dest) From c65b670e858a0fc010c8b8bb3cbf064bb22e1839 Mon Sep 17 00:00:00 2001 From: Chris Pettitt Date: Thu, 1 Nov 2007 20:43:14 -0700 Subject: [PATCH 0400/1490] git-p4: Detect changes to executable bit and include them in p4 submit. This changeset takes advantage of the new parseDiffTreeEntry(...) function to detect changes to the execute bit in the git repository. During submit, git-p4 now looks for changes to the executable bit and if it finds them it "reopens" the file in perforce, which allows it to change the file type. The logic for adding the executable bit in perforce is straightforward: the +x modifier can be used. Removing the executable bit in perforce requires that the entire filetype be redefined (there is no way to join remove the bit with a -x modifier, for example). This changeset includes logic to remove the executable bit from the full file type while preserving the base file type and other modifiers. Signed-off-by: Chris Pettitt Signed-off-by: Junio C Hamano --- contrib/fast-import/git-p4 | 44 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4 index c7fc564a5b..c148b5ab7d 100755 --- a/contrib/fast-import/git-p4 +++ b/contrib/fast-import/git-p4 @@ -71,6 +71,31 @@ def isP4Exec(kind): a plus sign, it is also executable""" return (re.search(r"(^[cku]?x)|\+.*x", kind) != None) +def setP4ExecBit(file, mode): + # Reopens an already open file and changes the execute bit to match + # the execute bit setting in the passed in mode. + + p4Type = "+x" + + if not isModeExec(mode): + p4Type = getP4OpenedType(file) + p4Type = re.sub('^([cku]?)x(.*)', '\\1\\2', p4Type) + p4Type = re.sub('(.*?\+.*?)x(.*?)', '\\1\\2', p4Type) + if p4Type[-1] == "+": + p4Type = p4Type[0:-1] + + system("p4 reopen -t %s %s" % (p4Type, file)) + +def getP4OpenedType(file): + # Returns the perforce file type for the given file. + + result = read_pipe("p4 opened %s" % file) + match = re.match(".*\((.+)\)$", result) + if match: + return match.group(1) + else: + die("Could not determine file type for %s" % file) + def diffTreePattern(): # This is a simple generator for the diff tree regex pattern. This could be # a class variable if this and parseDiffTreeEntry were a part of a class. @@ -111,6 +136,14 @@ def parseDiffTreeEntry(entry): } return None +def isModeExec(mode): + # Returns True if the given git mode represents an executable file, + # otherwise False. + return mode[-3:] == "755" + +def isModeExecChanged(src_mode, dst_mode): + return isModeExec(src_mode) != isModeExec(dst_mode) + def p4CmdList(cmd, stdin=None, stdin_mode='w+b'): cmd = "p4 -G %s" % cmd if verbose: @@ -538,15 +571,19 @@ class P4Submit(Command): filesToAdd = set() filesToDelete = set() editedFiles = set() + filesToChangeExecBit = {} for line in diff: diff = parseDiffTreeEntry(line) modifier = diff['status'] path = diff['src'] if modifier == "M": system("p4 edit \"%s\"" % path) + if isModeExecChanged(diff['src_mode'], diff['dst_mode']): + filesToChangeExecBit[path] = diff['dst_mode'] editedFiles.add(path) elif modifier == "A": filesToAdd.add(path) + filesToChangeExecBit[path] = diff['dst_mode'] if path in filesToDelete: filesToDelete.remove(path) elif modifier == "D": @@ -557,6 +594,8 @@ class P4Submit(Command): src, dest = diff['src'], diff['dst'] system("p4 integrate -Dt \"%s\" \"%s\"" % (src, dest)) system("p4 edit \"%s\"" % (dest)) + if isModeExecChanged(diff['src_mode'], diff['dst_mode']): + filesToChangeExecBit[dest] = diff['dst_mode'] os.unlink(dest) editedFiles.add(dest) filesToDelete.add(src) @@ -609,6 +648,11 @@ class P4Submit(Command): system("p4 revert \"%s\"" % f) system("p4 delete \"%s\"" % f) + # Set/clear executable bits + for f in filesToChangeExecBit.keys(): + mode = filesToChangeExecBit[f] + setP4ExecBit(f, mode) + logMessage = "" if not self.directSubmit: logMessage = extractLogMessageFromGitCommit(id) From 47ec79430dc6a60336bebdc0a45fb9f15129d0c7 Mon Sep 17 00:00:00 2001 From: Blake Ramsdell Date: Thu, 1 Nov 2007 19:38:22 -0700 Subject: [PATCH 0401/1490] transport.c: squelch a gcc 4.0.1 complaint about an uninitialized variable The variable is always set if it is going to be used; gcc just does not notice it. Signed-off-by: Blake Ramsdell Signed-off-by: Junio C Hamano --- transport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/transport.c b/transport.c index 5132d289da..d44fe7cee7 100644 --- a/transport.c +++ b/transport.c @@ -107,7 +107,7 @@ static void insert_packed_refs(const char *packed_refs, struct ref **list) return; for (;;) { - int cmp, len; + int cmp = cmp, len; if (!fgets(buffer, sizeof(buffer), f)) { fclose(f); From 7b55eee77e11da162fb197a79b72af375ed0f1d0 Mon Sep 17 00:00:00 2001 From: Jonas Fonseca Date: Fri, 2 Nov 2007 10:10:11 +0100 Subject: [PATCH 0402/1490] Remove escaping of '|' in manpage option sections The escaped were ending up verbatim in the generated documentation. Signed-off-by: Jonas Fonseca Signed-off-by: Junio C Hamano --- Documentation/git-filter-branch.txt | 2 +- Documentation/git-stripspace.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/git-filter-branch.txt b/Documentation/git-filter-branch.txt index 385ecc900f..895d750310 100644 --- a/Documentation/git-filter-branch.txt +++ b/Documentation/git-filter-branch.txt @@ -152,7 +152,7 @@ definition impossible to preserve signatures at any rate.) does this in the '.git-rewrite/' directory but you can override that choice by this parameter. --f\|--force:: +-f|--force:: `git filter-branch` refuses to start with an existing temporary directory or when there are already refs starting with 'refs/original/', unless forced. diff --git a/Documentation/git-stripspace.txt b/Documentation/git-stripspace.txt index 5212358306..f80526ba7e 100644 --- a/Documentation/git-stripspace.txt +++ b/Documentation/git-stripspace.txt @@ -16,7 +16,7 @@ Remove multiple empty lines, and empty lines at beginning and end. OPTIONS ------- --s\|--strip-comments:: +-s|--strip-comments:: In addition to empty lines, also strip lines starting with '#'. :: From d336fc096b450c01502e99fa17583d5bebf9aa24 Mon Sep 17 00:00:00 2001 From: Sergei Organov Date: Fri, 2 Nov 2007 20:12:57 +0300 Subject: [PATCH 0403/1490] Documentation: quote commit messages consistently. Documentation quotes commit messages 14 times with double-quotes, and 7 times with single-quotes. The patch turns everything to double-quotes. A nice side effect is that documentation becomes more Windoze-friendly as AFAIK single quotes won't work there. Signed-off-by: Sergei Organov Signed-off-by: Junio C Hamano --- Documentation/core-tutorial.txt | 8 ++++---- Documentation/everyday.txt | 4 ++-- Documentation/git-reset.txt | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Documentation/core-tutorial.txt b/Documentation/core-tutorial.txt index df147b5e76..67064dd31a 100644 --- a/Documentation/core-tutorial.txt +++ b/Documentation/core-tutorial.txt @@ -833,7 +833,7 @@ that branch, and do some work there. ------------------------------------------------ $ git checkout mybranch $ echo "Work, work, work" >>hello -$ git commit -m 'Some work.' -i hello +$ git commit -m "Some work." -i hello ------------------------------------------------ Here, we just added another line to `hello`, and we used a shorthand for @@ -858,7 +858,7 @@ hasn't happened in the `master` branch at all. Then do ------------ $ echo "Play, play, play" >>hello $ echo "Lots of fun" >>example -$ git commit -m 'Some fun.' -i hello example +$ git commit -m "Some fun." -i hello example ------------ since the master branch is obviously in a much better mood. @@ -1613,8 +1613,8 @@ in both of them. You could merge in 'diff-fix' first and then 'commit-fix' next, like this: ------------ -$ git merge -m 'Merge fix in diff-fix' diff-fix -$ git merge -m 'Merge fix in commit-fix' commit-fix +$ git merge -m "Merge fix in diff-fix" diff-fix +$ git merge -m "Merge fix in commit-fix" commit-fix ------------ Which would result in: diff --git a/Documentation/everyday.txt b/Documentation/everyday.txt index 08c61b1f1a..ce7c170d69 100644 --- a/Documentation/everyday.txt +++ b/Documentation/everyday.txt @@ -109,7 +109,7 @@ $ tar zxf frotz.tar.gz $ cd frotz $ git-init $ git add . <1> -$ git commit -m 'import of frotz source tree.' +$ git commit -m "import of frotz source tree." $ git tag v2.43 <2> ------------ + @@ -300,7 +300,7 @@ $ git merge topic/one topic/two && git merge hold/linus <8> $ git checkout maint $ git cherry-pick master~4 <9> $ compile/test -$ git tag -s -m 'GIT 0.99.9x' v0.99.9x <10> +$ git tag -s -m "GIT 0.99.9x" v0.99.9x <10> $ git fetch ko && git show-branch master maint 'tags/ko-*' <11> $ git push ko <12> $ git push ko v0.99.9x <13> diff --git a/Documentation/git-reset.txt b/Documentation/git-reset.txt index 15e3aca9a1..87afa6f8da 100644 --- a/Documentation/git-reset.txt +++ b/Documentation/git-reset.txt @@ -157,7 +157,7 @@ need to get to the other branch for a quick bugfix. ------------ $ git checkout feature ;# you were working in "feature" branch and $ work work work ;# got interrupted -$ git commit -a -m 'snapshot WIP' <1> +$ git commit -a -m "snapshot WIP" <1> $ git checkout master $ fix fix fix $ git commit ;# commit with real log From 9e54dc6c12b14c12094c3a0f0b1e437148bbc0bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Fri, 2 Nov 2007 11:33:07 -0400 Subject: [PATCH 0404/1490] Remove unecessary hard-coding of EDITOR=':' VISUAL=':' in some test suites. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit They are already set and exoprted by sourcing ./test-lib.sh in all test scripts. Signed-off-by: Kristian Høgsberg Signed-off-by: Junio C Hamano --- t/t3501-revert-cherry-pick.sh | 4 ++-- t/t3901-i18n-patch.sh | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/t/t3501-revert-cherry-pick.sh b/t/t3501-revert-cherry-pick.sh index 552af1c4d2..2dbe04fb20 100755 --- a/t/t3501-revert-cherry-pick.sh +++ b/t/t3501-revert-cherry-pick.sh @@ -44,7 +44,7 @@ test_expect_success setup ' test_expect_success 'cherry-pick after renaming branch' ' git checkout rename2 && - EDITOR=: VISUAL=: git cherry-pick added && + git cherry-pick added && test -f opos && grep "Add extra line at the end" opos @@ -53,7 +53,7 @@ test_expect_success 'cherry-pick after renaming branch' ' test_expect_success 'revert after renaming branch' ' git checkout rename1 && - EDITOR=: VISUAL=: git revert added && + git revert added && test -f spoo && ! grep "Add extra line at the end" spoo diff --git a/t/t3901-i18n-patch.sh b/t/t3901-i18n-patch.sh index 28e9e372f3..235f372832 100755 --- a/t/t3901-i18n-patch.sh +++ b/t/t3901-i18n-patch.sh @@ -154,7 +154,7 @@ test_expect_success 'cherry-pick(U/U)' ' git reset --hard master && git cherry-pick side^ && git cherry-pick side && - EDITOR=: VISUAL=: git revert HEAD && + git revert HEAD && check_encoding 3 ' @@ -169,7 +169,7 @@ test_expect_success 'cherry-pick(L/L)' ' git reset --hard master && git cherry-pick side^ && git cherry-pick side && - EDITOR=: VISUAL=: git revert HEAD && + git revert HEAD && check_encoding 3 8859 ' @@ -184,7 +184,7 @@ test_expect_success 'cherry-pick(U/L)' ' git reset --hard master && git cherry-pick side^ && git cherry-pick side && - EDITOR=: VISUAL=: git revert HEAD && + git revert HEAD && check_encoding 3 ' @@ -200,7 +200,7 @@ test_expect_success 'cherry-pick(L/U)' ' git reset --hard master && git cherry-pick side^ && git cherry-pick side && - EDITOR=: VISUAL=: git revert HEAD && + git revert HEAD && check_encoding 3 8859 ' From f45e867b1a60a2023c18719888bb52965ade7192 Mon Sep 17 00:00:00 2001 From: Jonathan del Strother Date: Wed, 17 Oct 2007 10:31:35 +0100 Subject: [PATCH 0405/1490] Fixing path quoting in git-rebase git-rebase used to fail when run from a path containing a space. Signed-off-by: Jonathan del Strother Signed-off-by: Shawn O. Pearce --- git-rebase.sh | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/git-rebase.sh b/git-rebase.sh index 058fcacb7e..b0c8ac1c8d 100755 --- a/git-rebase.sh +++ b/git-rebase.sh @@ -59,7 +59,7 @@ continue_merge () { die "$RESOLVEMSG" fi - cmt=`cat $dotest/current` + cmt=`cat "$dotest/current"` if ! git diff-index --quiet HEAD then if ! git-commit -C "$cmt" @@ -84,14 +84,14 @@ continue_merge () { } call_merge () { - cmt="$(cat $dotest/cmt.$1)" + cmt="$(cat "$dotest/cmt.$1")" echo "$cmt" > "$dotest/current" hd=$(git rev-parse --verify HEAD) cmt_name=$(git symbolic-ref HEAD) - msgnum=$(cat $dotest/msgnum) - end=$(cat $dotest/end) + msgnum=$(cat "$dotest/msgnum") + end=$(cat "$dotest/end") eval GITHEAD_$cmt='"${cmt_name##refs/heads/}~$(($end - $msgnum))"' - eval GITHEAD_$hd='"$(cat $dotest/onto_name)"' + eval GITHEAD_$hd='$(cat "$dotest/onto_name")' export GITHEAD_$cmt GITHEAD_$hd git-merge-$strategy "$cmt^" -- "$hd" "$cmt" rv=$? @@ -140,10 +140,10 @@ do } if test -d "$dotest" then - prev_head="`cat $dotest/prev_head`" - end="`cat $dotest/end`" - msgnum="`cat $dotest/msgnum`" - onto="`cat $dotest/onto`" + prev_head=$(cat "$dotest/prev_head") + end=$(cat "$dotest/end") + msgnum=$(cat "$dotest/msgnum") + onto=$(cat "$dotest/onto") continue_merge while test "$msgnum" -le "$end" do @@ -160,11 +160,11 @@ do if test -d "$dotest" then git rerere clear - prev_head="`cat $dotest/prev_head`" - end="`cat $dotest/end`" - msgnum="`cat $dotest/msgnum`" + prev_head=$(cat "$dotest/prev_head") + end=$(cat "$dotest/end") + msgnum=$(cat "$dotest/msgnum") msgnum=$(($msgnum + 1)) - onto="`cat $dotest/onto`" + onto=$(cat "$dotest/onto") while test "$msgnum" -le "$end" do call_merge "$msgnum" From 6232b3438d127def8cc0612e45422347578c6102 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 2 Nov 2007 17:25:24 -0700 Subject: [PATCH 0406/1490] cherry-pick/revert -m: add tests This adds a new test to check cherry-pick/revert of a merge commit. Signed-off-by: Junio C Hamano --- t/t3502-cherry-pick-merge.sh | 123 +++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100755 t/t3502-cherry-pick-merge.sh diff --git a/t/t3502-cherry-pick-merge.sh b/t/t3502-cherry-pick-merge.sh new file mode 100755 index 0000000000..3274c6141b --- /dev/null +++ b/t/t3502-cherry-pick-merge.sh @@ -0,0 +1,123 @@ +#!/bin/sh + +test_description='cherry picking and reverting a merge + + b---c + / / + initial---a + +' + +. ./test-lib.sh + +test_expect_success setup ' + + >A && + >B && + git add A B && + git commit -m "Initial" && + git tag initial && + git branch side && + echo new line >A && + git commit -m "add line to A" A && + git tag a && + git checkout side && + echo new line >B && + git commit -m "add line to B" B && + git tag b && + git checkout master && + git merge side && + git tag c + +' + +test_expect_success 'cherry-pick a non-merge with -m should fail' ' + + git reset --hard && + git checkout a^0 && + ! git cherry-pick -m 1 b && + git diff --exit-code a + +' + +test_expect_success 'cherry pick a merge without -m should fail' ' + + git reset --hard && + git checkout a^0 && + ! git cherry-pick c && + git diff --exit-code a + +' + +test_expect_success 'cherry pick a merge (1)' ' + + git reset --hard && + git checkout a^0 && + git cherry-pick -m 1 c && + git diff --exit-code c + +' + +test_expect_success 'cherry pick a merge (2)' ' + + git reset --hard && + git checkout b^0 && + git cherry-pick -m 2 c && + git diff --exit-code c + +' + +test_expect_success 'cherry pick a merge relative to nonexistent parent should fail' ' + + git reset --hard && + git checkout b^0 && + ! git cherry-pick -m 3 c + +' + +test_expect_success 'revert a non-merge with -m should fail' ' + + git reset --hard && + git checkout c^0 && + ! git revert -m 1 b && + git diff --exit-code c + +' + +test_expect_success 'revert a merge without -m should fail' ' + + git reset --hard && + git checkout c^0 && + ! git revert c && + git diff --exit-code c + +' + +test_expect_success 'revert a merge (1)' ' + + git reset --hard && + git checkout c^0 && + git revert -m 1 c && + git diff --exit-code a + +' + +test_expect_success 'revert a merge (2)' ' + + git reset --hard && + git checkout c^0 && + git revert -m 2 c && + git diff --exit-code b + +' + +test_expect_success 'revert a merge relative to nonexistent parent should fail' ' + + git reset --hard && + git checkout c^0 && + ! git revert -m 3 c && + git diff --exit-code c + +' + +test_done From aacb8f10a70c07dfe1461684f098313f0edb371f Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 2 Nov 2007 17:55:31 -0700 Subject: [PATCH 0407/1490] test format-patch -s: make sure MIME content type is shown as needed Signed-off-by: Junio C Hamano --- t/t4021-format-patch-signer-mime.sh | 42 +++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100755 t/t4021-format-patch-signer-mime.sh diff --git a/t/t4021-format-patch-signer-mime.sh b/t/t4021-format-patch-signer-mime.sh new file mode 100755 index 0000000000..67a70fadab --- /dev/null +++ b/t/t4021-format-patch-signer-mime.sh @@ -0,0 +1,42 @@ +#!/bin/sh + +test_description='format-patch -s should force MIME encoding as needed' + +. ./test-lib.sh + +test_expect_success setup ' + + >F && + git add F && + git commit -m initial && + echo new line >F && + + test_tick && + git commit -m "This adds some lines to F" F + +' + +test_expect_success 'format normally' ' + + git format-patch --stdout -1 >output && + ! grep Content-Type output + +' + +test_expect_success 'format with signoff without funny signer name' ' + + git format-patch -s --stdout -1 >output && + ! grep Content-Type output + +' + +test_expect_success 'format with non ASCII signer name' ' + + GIT_COMMITTER_NAME="$B$O$^$N(B $B$U$K$*$&(B" \ + git format-patch -s --stdout -1 >output && + grep Content-Type output + +' + +test_done + From a9cc857ada7c57069ff00eed8d0addcf55849f39 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 2 Nov 2007 00:24:27 -0700 Subject: [PATCH 0408/1490] War on whitespace: first, a bit of retreat. This introduces core.whitespace configuration variable that lets you specify the definition of "whitespace error". Currently there are two kinds of whitespace errors defined: * trailing-space: trailing whitespaces at the end of the line. * space-before-tab: a SP appears immediately before HT in the indent part of the line. You can specify the desired types of errors to be detected by listing their names (unique abbreviations are accepted) separated by comma. By default, these two errors are always detected, as that is the traditional behaviour. You can disable detection of a particular type of error by prefixing a '-' in front of the name of the error, like this: [core] whitespace = -trailing-space This patch teaches the code to output colored diff with DIFF_WHITESPACE color to highlight the detected whitespace errors to honor the new configuration. Signed-off-by: Junio C Hamano --- cache.h | 9 +++++++++ config.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++ diff.c | 13 ++++++++----- environment.c | 1 + 4 files changed, 70 insertions(+), 5 deletions(-) diff --git a/cache.h b/cache.h index bfffa05dff..a6e5988f07 100644 --- a/cache.h +++ b/cache.h @@ -602,4 +602,13 @@ extern int diff_auto_refresh_index; /* match-trees.c */ void shift_tree(const unsigned char *, const unsigned char *, unsigned char *, int); +/* + * whitespace rules. + * used by both diff and apply + */ +#define WS_TRAILING_SPACE 01 +#define WS_SPACE_BEFORE_TAB 02 +#define WS_DEFAULT_RULE (WS_TRAILING_SPACE|WS_SPACE_BEFORE_TAB) +extern unsigned whitespace_rule; + #endif /* CACHE_H */ diff --git a/config.c b/config.c index dc3148d456..ffb418ccff 100644 --- a/config.c +++ b/config.c @@ -246,6 +246,53 @@ static unsigned long get_unit_factor(const char *end) die("unknown unit: '%s'", end); } +static struct whitespace_rule { + const char *rule_name; + unsigned rule_bits; +} whitespace_rule_names[] = { + { "trailing-space", WS_TRAILING_SPACE }, + { "space-before-tab", WS_SPACE_BEFORE_TAB }, +}; + +static unsigned parse_whitespace_rule(const char *string) +{ + unsigned rule = WS_DEFAULT_RULE; + + while (string) { + int i; + size_t len; + const char *ep; + int negated = 0; + + string = string + strspn(string, ", \t\n\r"); + ep = strchr(string, ','); + if (!ep) + len = strlen(string); + else + len = ep - string; + + if (*string == '-') { + negated = 1; + string++; + len--; + } + if (!len) + break; + for (i = 0; i < ARRAY_SIZE(whitespace_rule_names); i++) { + if (strncmp(whitespace_rule_names[i].rule_name, + string, len)) + continue; + if (negated) + rule &= ~whitespace_rule_names[i].rule_bits; + else + rule |= whitespace_rule_names[i].rule_bits; + break; + } + string = ep; + } + return rule; +} + int git_parse_long(const char *value, long *ret) { if (value && *value) { @@ -431,6 +478,11 @@ int git_default_config(const char *var, const char *value) return 0; } + if (!strcmp(var, "core.whitespace")) { + whitespace_rule = parse_whitespace_rule(value); + return 0; + } + /* Add other config variables here and to Documentation/config.txt. */ return 0; } diff --git a/diff.c b/diff.c index a6aaaf7e5a..211235376d 100644 --- a/diff.c +++ b/diff.c @@ -508,7 +508,8 @@ static void emit_line_with_ws(int nparents, for (i = col0; i < len; i++) { if (line[i] == '\t') { last_tab_in_indent = i; - if (0 <= last_space_in_indent) + if ((whitespace_rule & WS_SPACE_BEFORE_TAB) && + 0 <= last_space_in_indent) need_highlight_leading_space = 1; } else if (line[i] == ' ') @@ -540,10 +541,12 @@ static void emit_line_with_ws(int nparents, tail = len - 1; if (line[tail] == '\n' && i < tail) tail--; - while (i < tail) { - if (!isspace(line[tail])) - break; - tail--; + if (whitespace_rule & WS_TRAILING_SPACE) { + while (i < tail) { + if (!isspace(line[tail])) + break; + tail--; + } } if ((i < tail && line[tail + 1] != '\n')) { /* This has whitespace between tail+1..len */ diff --git a/environment.c b/environment.c index b5a6c69f7c..624dd9677c 100644 --- a/environment.c +++ b/environment.c @@ -35,6 +35,7 @@ int pager_in_use; int pager_use_color = 1; char *editor_program; int auto_crlf = 0; /* 1: both ways, -1: only when adding git objects */ +unsigned whitespace_rule = WS_DEFAULT_RULE; /* This is set by setup_git_dir_gently() and/or git_default_config() */ char *git_work_tree_cfg; From 459fa6d0fe6a45b8b120463b56a68e943e3a8101 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 2 Oct 2007 18:00:27 -0700 Subject: [PATCH 0409/1490] git-diff: complain about >=8 consecutive spaces in initial indent This introduces a new whitespace error type, "indent-with-non-tab". The error is about starting a line with 8 or more SP, instead of indenting it with a HT. This is not enabled by default, as some projects employ an indenting policy to use only SPs and no HTs. The kernel folks and git contributors may want to enable this detection with: [core] whitespace = indent-with-non-tab Signed-off-by: Junio C Hamano --- cache.h | 1 + config.c | 1 + diff.c | 14 ++++++++++++-- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/cache.h b/cache.h index a6e5988f07..3f4282795e 100644 --- a/cache.h +++ b/cache.h @@ -608,6 +608,7 @@ void shift_tree(const unsigned char *, const unsigned char *, unsigned char *, i */ #define WS_TRAILING_SPACE 01 #define WS_SPACE_BEFORE_TAB 02 +#define WS_INDENT_WITH_NON_TAB 04 #define WS_DEFAULT_RULE (WS_TRAILING_SPACE|WS_SPACE_BEFORE_TAB) extern unsigned whitespace_rule; diff --git a/config.c b/config.c index ffb418ccff..d5b976696c 100644 --- a/config.c +++ b/config.c @@ -252,6 +252,7 @@ static struct whitespace_rule { } whitespace_rule_names[] = { { "trailing-space", WS_TRAILING_SPACE }, { "space-before-tab", WS_SPACE_BEFORE_TAB }, + { "indent-with-non-tab", WS_INDENT_WITH_NON_TAB }, }; static unsigned parse_whitespace_rule(const char *string) diff --git a/diff.c b/diff.c index 211235376d..6bb902f4af 100644 --- a/diff.c +++ b/diff.c @@ -502,8 +502,11 @@ static void emit_line_with_ws(int nparents, int i; int tail = len; int need_highlight_leading_space = 0; - /* The line is a newly added line. Does it have funny leading - * whitespaces? In indent, SP should never precede a TAB. + /* + * The line is a newly added line. Does it have funny leading + * whitespaces? In indent, SP should never precede a TAB. In + * addition, under "indent with non tab" rule, there should not + * be more than 8 consecutive spaces. */ for (i = col0; i < len; i++) { if (line[i] == '\t') { @@ -517,6 +520,13 @@ static void emit_line_with_ws(int nparents, else break; } + if ((whitespace_rule & WS_INDENT_WITH_NON_TAB) && + 0 <= last_space_in_indent && + last_tab_in_indent < 0 && + 8 <= (i - col0)) { + last_tab_in_indent = i; + need_highlight_leading_space = 1; + } fputs(set, stdout); fwrite(line, col0, 1, stdout); fputs(reset, stdout); From 49e703afda0e4e67050fcc8e05b175987c83391c Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 2 Nov 2007 17:46:55 -0700 Subject: [PATCH 0410/1490] core.whitespace: add test for diff whitespace error highlighting This tests seletive enabling/disabling of whitespace error highlighting done by colored diff output. Signed-off-by: Junio C Hamano --- t/t4019-diff-wserror.sh | 76 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100755 t/t4019-diff-wserror.sh diff --git a/t/t4019-diff-wserror.sh b/t/t4019-diff-wserror.sh new file mode 100755 index 0000000000..dbc895b9b7 --- /dev/null +++ b/t/t4019-diff-wserror.sh @@ -0,0 +1,76 @@ +#!/bin/sh + +test_description='diff whitespace error detection' + +. ./test-lib.sh + +test_expect_success setup ' + + git config diff.color.whitespace "blue reverse" && + >F && + git add F && + echo " Eight SP indent" >>F && + echo " HT and SP indent" >>F && + echo "With trailing SP " >>F && + echo "No problem" >>F + +' + +blue_grep='7;34m' ;# ESC [ 7 ; 3 4 m + +test_expect_success default ' + + git diff --color >output + grep "$blue_grep" output >error + grep -v "$blue_grep" output >normal + + grep Eight normal >/dev/null && + grep HT error >/dev/null && + grep With error >/dev/null && + grep No normal >/dev/null + +' + +test_expect_success 'without -trail' ' + + git config core.whitespace -trail + git diff --color >output + grep "$blue_grep" output >error + grep -v "$blue_grep" output >normal + + grep Eight normal >/dev/null && + grep HT error >/dev/null && + grep With normal >/dev/null && + grep No normal >/dev/null + +' + +test_expect_success 'without -space' ' + + git config core.whitespace -space + git diff --color >output + grep "$blue_grep" output >error + grep -v "$blue_grep" output >normal + + grep Eight normal >/dev/null && + grep HT normal >/dev/null && + grep With error >/dev/null && + grep No normal >/dev/null + +' + +test_expect_success 'with indent-non-tab only' ' + + git config core.whitespace indent,-trailing,-space + git diff --color >output + grep "$blue_grep" output >error + grep -v "$blue_grep" output >normal + + grep Eight error >/dev/null && + grep HT normal >/dev/null && + grep With normal >/dev/null && + grep No normal >/dev/null + +' + +test_done From e9c34c233f2e838c334f6e8a807ebc6a988e9509 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Sat, 3 Nov 2007 00:41:18 +0100 Subject: [PATCH 0411/1490] gitweb: Add tests for overriding gitweb config with repo config Make blame view and snapshot support overridable by repository config. Test tree view with both features disabled, and with both features enabled. Test with features enabled also tests multiple formats snapshot support (in tree view). Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- t/t9500-gitweb-standalone-no-errors.sh | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/t/t9500-gitweb-standalone-no-errors.sh b/t/t9500-gitweb-standalone-no-errors.sh index 1bf0988d9a..35fff3ddba 100755 --- a/t/t9500-gitweb-standalone-no-errors.sh +++ b/t/t9500-gitweb-standalone-no-errors.sh @@ -557,4 +557,27 @@ test_expect_success \ 'gitweb_run "p=.git;a=tree;opt=--no-merges"' test_debug 'cat gitweb.log' +# ---------------------------------------------------------------------- +# gitweb config and repo config + +cat >>gitweb_config.perl < Date: Sat, 3 Nov 2007 00:41:19 +0100 Subject: [PATCH 0412/1490] gitweb: Read repo config using 'git config -z -l' Change git_get_project_config to run git-config only once per repository, without changing its signature (its calling convention). This means for example that it returns 'true' or 'false' when called with second argument '--bool', and not true or false value. Instead of calling 'git config [] --get gitweb.' once for each config variable, call 'git config -z -l' only once, parsing and saving its output to %config variable. This makes possible to add new per repository configuration without paying cost of forking once per variable checked. We can now allow repository description and repository URLs to be stored in config file without badly affecting gitweb performance. For now only configuration variables for 'gitweb' section are stored. Multiple values for single configuration variable are stored as anonymous array reference; configuration variable with no value is stored as undef. Converting configuration variable values to boolean or integer value are done in Perl. Results differ from git-config in the fact that no conversion error is ever raised. For boolean values no value, 'true' (any case) and 'false' (any case) are considered true, numbers are true if not zero; all other values (even invalid for bool) are considered false. For integer values value suffix of 'k', 'm', or 'g' following decimal number will cause the value to be multiplied by 1024, 1048576, or 1073741824; other values are returned as-is, only whitespace stripped. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 115 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 108 insertions(+), 7 deletions(-) diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index ecb0113a79..e94ff96337 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1432,20 +1432,121 @@ sub git_get_type { return $type; } +# repository configuration +our $config_file = ''; +our %config; + +# store multiple values for single key as anonymous array reference +# single values stored directly in the hash, not as [ ] +sub hash_set_multi { + my ($hash, $key, $value) = @_; + + if (!exists $hash->{$key}) { + $hash->{$key} = $value; + } elsif (!ref $hash->{$key}) { + $hash->{$key} = [ $hash->{$key}, $value ]; + } else { + push @{$hash->{$key}}, $value; + } +} + +# return hash of git project configuration +# optionally limited to some section, e.g. 'gitweb' +sub git_parse_project_config { + my $section_regexp = shift; + my %config; + + local $/ = "\0"; + + open my $fh, "-|", git_cmd(), "config", '-z', '-l', + or return; + + while (my $keyval = <$fh>) { + chomp $keyval; + my ($key, $value) = split(/\n/, $keyval, 2); + + hash_set_multi(\%config, $key, $value) + if (!defined $section_regexp || $key =~ /^(?:$section_regexp)\./o); + } + close $fh; + + return %config; +} + +# convert config value to boolean, 'true' or 'false' +# no value, number > 0, 'true' and 'yes' values are true +# rest of values are treated as false (never as error) +sub config_to_bool { + my $val = shift; + + # strip leading and trailing whitespace + $val =~ s/^\s+//; + $val =~ s/\s+$//; + + return (!defined $val || # section.key + ($val =~ /^\d+$/ && $val) || # section.key = 1 + ($val =~ /^(?:true|yes)$/i)); # section.key = true +} + +# convert config value to simple decimal number +# an optional value suffix of 'k', 'm', or 'g' will cause the value +# to be multiplied by 1024, 1048576, or 1073741824 +sub config_to_int { + my $val = shift; + + # strip leading and trailing whitespace + $val =~ s/^\s+//; + $val =~ s/\s+$//; + + if (my ($num, $unit) = ($val =~ /^([0-9]*)([kmg])$/i)) { + $unit = lc($unit); + # unknown unit is treated as 1 + return $num * ($unit eq 'g' ? 1073741824 : + $unit eq 'm' ? 1048576 : + $unit eq 'k' ? 1024 : 1); + } + return $val; +} + +# convert config value to array reference, if needed +sub config_to_multi { + my $val = shift; + + return ref($val) ? $val : [ $val ]; +} + sub git_get_project_config { my ($key, $type) = @_; + # key sanity check return unless ($key); $key =~ s/^gitweb\.//; return if ($key =~ m/\W/); - my @x = (git_cmd(), 'config'); - if (defined $type) { push @x, $type; } - push @x, "--get"; - push @x, "gitweb.$key"; - my $val = qx(@x); - chomp $val; - return ($val); + # type sanity check + if (defined $type) { + $type =~ s/^--//; + $type = undef + unless ($type eq 'bool' || $type eq 'int'); + } + + # get config + if (!defined $config_file || + $config_file ne "$git_dir/config") { + %config = git_parse_project_config('gitweb'); + $config_file = "$git_dir/config"; + } + + # ensure given type + if (!defined $type) { + return $config{"gitweb.$key"}; + } elsif ($type eq 'bool') { + # backward compatibility: 'git config --bool' returns true/false + return config_to_bool($config{"gitweb.$key"}) ? 'true' : 'false'; + } elsif ($type eq 'int') { + return config_to_int($config{"gitweb.$key"}); + } + return $config{"gitweb.$key"}; } # get hash of given path at given ref From 0e121a2cd42d28bc4034feedf8a13c5a91f85bd3 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Sat, 3 Nov 2007 00:41:20 +0100 Subject: [PATCH 0413/1490] gitweb: Use config file for repository description and URLs Allow to use configuration variable gitweb.description for repository description if there is no $GIT_DIR/description file, and multivalued configuration variable gitweb.url for URLs of a project (to clone or fetch from) if there is no $GIT_DIR/cloneurl file. While repository description is shown in the projects list page, so it is better to use file and not config variable for performance, it is I think better to use gitweb.url for URLs (as it is shown only on project summary page). Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index e94ff96337..759dff1cce 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1606,7 +1606,9 @@ sub git_get_path_by_hash { sub git_get_project_description { my $path = shift; - open my $fd, "$projectroot/$path/description" or return undef; + $git_dir = "$projectroot/$path"; + open my $fd, "$projectroot/$path/description" + or return git_get_project_config('description'); my $descr = <$fd>; close $fd; if (defined $descr) { @@ -1618,7 +1620,11 @@ sub git_get_project_description { sub git_get_project_url_list { my $path = shift; - open my $fd, "$projectroot/$path/cloneurl" or return; + $git_dir = "$projectroot/$path"; + open my $fd, "$projectroot/$path/cloneurl" + or return wantarray ? + @{ config_to_multi(git_get_project_config('url')) } : + config_to_multi(git_get_project_config('url')); my @git_project_url_list = map { chomp; $_ } <$fd>; close $fd; From 165f390250874b32ed8158150fe49d574297c9f9 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sat, 3 Nov 2007 01:32:48 -0400 Subject: [PATCH 0414/1490] git-fetch: more terse fetch output This makes the fetch output much more terse and prettier on a 80 column display, based on a consensus reached on the mailing list. Here's an example output: Receiving objects: 100% (5439/5439), 1.60 MiB | 636 KiB/s, done. Resolving deltas: 100% (4604/4604), done. From git://git.kernel.org/pub/scm/git/git ! [rejected] html -> origin/html (non fast forward) 136e631..f45e867 maint -> origin/maint (fast forward) 9850e2e..44dd7e0 man -> origin/man (fast forward) 3e4bb08..e3d6d56 master -> origin/master (fast forward) fa3665c..536f64a next -> origin/next (fast forward) + 4f6d9d6...768326f pu -> origin/pu (forced update) * [new branch] todo -> origin/todo Some portions of this patch have been extracted from earlier proposals by Jeff King and Shawn Pearce. Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- builtin-fetch.c | 114 +++++++++++++++++++++++++----------------------- 1 file changed, 60 insertions(+), 54 deletions(-) diff --git a/builtin-fetch.c b/builtin-fetch.c index 003ed76d16..960b1dae89 100644 --- a/builtin-fetch.c +++ b/builtin-fetch.c @@ -131,12 +131,6 @@ static struct ref *get_ref_map(struct transport *transport, return ref_map; } -static void show_new(enum object_type type, unsigned char *sha1_new) -{ - fprintf(stderr, " %s: %s\n", typename(type), - find_unique_abbrev(sha1_new, DEFAULT_ABBREV)); -} - static int s_update_ref(const char *action, struct ref *ref, int check_old) @@ -157,34 +151,38 @@ static int s_update_ref(const char *action, return 0; } +#define SUMMARY_WIDTH (2 * DEFAULT_ABBREV + 3) + static int update_local_ref(struct ref *ref, - const char *note, - int verbose) + const char *remote, + int verbose, + char *display) { - char oldh[41], newh[41]; struct commit *current = NULL, *updated; enum object_type type; struct branch *current_branch = branch_get(NULL); + const char *pretty_ref = ref->name + ( + !prefixcmp(ref->name, "refs/heads/") ? 11 : + !prefixcmp(ref->name, "refs/tags/") ? 10 : + !prefixcmp(ref->name, "refs/remotes/") ? 13 : + 0); + *display = 0; type = sha1_object_info(ref->new_sha1, NULL); if (type < 0) die("object %s not found", sha1_to_hex(ref->new_sha1)); if (!*ref->name) { /* Not storing */ - if (verbose) { - fprintf(stderr, "* fetched %s\n", note); - show_new(type, ref->new_sha1); - } + if (verbose) + sprintf(display, "* branch %s -> FETCH_HEAD", remote); return 0; } if (!hashcmp(ref->old_sha1, ref->new_sha1)) { - if (verbose) { - fprintf(stderr, "* %s: same as %s\n", - ref->name, note); - show_new(type, ref->new_sha1); - } + if (verbose) + sprintf(display, "= %-*s %s -> %s", SUMMARY_WIDTH, + "[up to date]", remote, pretty_ref); return 0; } @@ -196,63 +194,65 @@ static int update_local_ref(struct ref *ref, * If this is the head, and it's not okay to update * the head, and the old value of the head isn't empty... */ - fprintf(stderr, - " * %s: Cannot fetch into the current branch.\n", - ref->name); + sprintf(display, "! %-*s %s -> %s (can't fetch in current branch)", + SUMMARY_WIDTH, "[rejected]", remote, pretty_ref); return 1; } if (!is_null_sha1(ref->old_sha1) && !prefixcmp(ref->name, "refs/tags/")) { - fprintf(stderr, "* %s: updating with %s\n", - ref->name, note); - show_new(type, ref->new_sha1); + sprintf(display, "- %-*s %s -> %s", + SUMMARY_WIDTH, "[tag update]", remote, pretty_ref); return s_update_ref("updating tag", ref, 0); } current = lookup_commit_reference_gently(ref->old_sha1, 1); updated = lookup_commit_reference_gently(ref->new_sha1, 1); if (!current || !updated) { - char *msg; - if (!strncmp(ref->name, "refs/tags/", 10)) + const char *msg; + const char *what; + if (!strncmp(ref->name, "refs/tags/", 10)) { msg = "storing tag"; - else + what = "[new tag]"; + } + else { msg = "storing head"; - fprintf(stderr, "* %s: storing %s\n", - ref->name, note); - show_new(type, ref->new_sha1); + what = "[new branch]"; + } + + sprintf(display, "* %-*s %s -> %s", + SUMMARY_WIDTH, what, remote, pretty_ref); return s_update_ref(msg, ref, 0); } - strcpy(oldh, find_unique_abbrev(current->object.sha1, DEFAULT_ABBREV)); - strcpy(newh, find_unique_abbrev(ref->new_sha1, DEFAULT_ABBREV)); - if (in_merge_bases(current, &updated, 1)) { - fprintf(stderr, "* %s: fast forward to %s\n", - ref->name, note); - fprintf(stderr, " old..new: %s..%s\n", oldh, newh); + char quickref[83]; + strcpy(quickref, find_unique_abbrev(current->object.sha1, DEFAULT_ABBREV)); + strcat(quickref, ".."); + strcat(quickref, find_unique_abbrev(ref->new_sha1, DEFAULT_ABBREV)); + sprintf(display, " %-*s %s -> %s (fast forward)", + SUMMARY_WIDTH, quickref, remote, pretty_ref); return s_update_ref("fast forward", ref, 1); - } - if (!force && !ref->force) { - fprintf(stderr, - "* %s: not updating to non-fast forward %s\n", - ref->name, note); - fprintf(stderr, - " old...new: %s...%s\n", oldh, newh); + } else if (force || ref->force) { + char quickref[84]; + strcpy(quickref, find_unique_abbrev(current->object.sha1, DEFAULT_ABBREV)); + strcat(quickref, "..."); + strcat(quickref, find_unique_abbrev(ref->new_sha1, DEFAULT_ABBREV)); + sprintf(display, "+ %-*s %s -> %s (forced update)", + SUMMARY_WIDTH, quickref, remote, pretty_ref); + return s_update_ref("forced-update", ref, 1); + } else { + sprintf(display, "! %-*s %s -> %s (non fast forward)", + SUMMARY_WIDTH, "[rejected]", remote, pretty_ref); return 1; } - fprintf(stderr, - "* %s: forcing update to non-fast forward %s\n", - ref->name, note); - fprintf(stderr, " old...new: %s...%s\n", oldh, newh); - return s_update_ref("forced-update", ref, 1); } static void store_updated_refs(const char *url, struct ref *ref_map) { FILE *fp; struct commit *commit; - int url_len, i, note_len; + int url_len, i, note_len, shown_url = 0; char note[1024]; const char *what, *kind; struct ref *rm; @@ -315,8 +315,17 @@ static void store_updated_refs(const char *url, struct ref *ref_map) rm->merge ? "" : "not-for-merge", note); - if (ref) - update_local_ref(ref, note, verbose); + if (ref) { + update_local_ref(ref, what, verbose, note); + if (*note) { + if (!shown_url) { + fprintf(stderr, "From %.*s\n", + url_len, url); + shown_url = 1; + } + fprintf(stderr, " %s\n", note); + } + } } fclose(fp); } @@ -376,9 +385,6 @@ static struct ref *find_non_local_tags(struct transport *transport, if (!path_list_has_path(&existing_refs, ref_name) && !path_list_has_path(&new_refs, ref_name) && lookup_object(ref->old_sha1)) { - fprintf(stderr, "Auto-following %s\n", - ref_name); - path_list_insert(ref_name, &new_refs); rm = alloc_ref(strlen(ref_name) + 1); From 4577370e9bfeca8652880b99b8499f76d18865ba Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Mon, 29 Oct 2007 21:05:40 -0400 Subject: [PATCH 0415/1490] Miscellaneous const changes and utilities The list of remote refs in struct transport should be const, because builtin-fetch will get confused if it changes. The url in git_connect should be const (and work on a copy) instead of requiring the caller to copy it. match_refs doesn't modify the refspecs it gets. get_fetch_map and get_remote_ref don't change the list they get. Allow transport get_refs_list methods to modify the struct transport. Add a function to copy a list of refs, when a function needs a mutable copy of a const list. Add a function to check the type of a ref, as per the code in connect.c Signed-off-by: Daniel Barkalow Signed-off-by: Junio C Hamano --- builtin-fetch.c | 10 +++++----- cache.h | 2 +- connect.c | 10 +++++++++- http-push.c | 2 +- remote.c | 32 ++++++++++++++++++++++---------- remote.h | 10 +++++++--- send-pack.c | 8 ++++---- transport.c | 10 +++++----- transport.h | 6 +++--- 9 files changed, 57 insertions(+), 33 deletions(-) diff --git a/builtin-fetch.c b/builtin-fetch.c index 003ed76d16..fa0af170dd 100644 --- a/builtin-fetch.c +++ b/builtin-fetch.c @@ -29,7 +29,7 @@ static void unlock_pack_on_signal(int signo) } static void add_merge_config(struct ref **head, - struct ref *remote_refs, + const struct ref *remote_refs, struct branch *branch, struct ref ***tail) { @@ -77,7 +77,7 @@ static struct ref *get_ref_map(struct transport *transport, struct ref *ref_map = NULL; struct ref **tail = &ref_map; - struct ref *remote_refs = transport_get_remote_refs(transport); + const struct ref *remote_refs = transport_get_remote_refs(transport); if (ref_count || tags) { for (i = 0; i < ref_count; i++) { @@ -345,12 +345,12 @@ static struct ref *find_non_local_tags(struct transport *transport, struct path_list new_refs = { NULL, 0, 0, 1 }; char *ref_name; int ref_name_len; - unsigned char *ref_sha1; - struct ref *tag_ref; + const unsigned char *ref_sha1; + const struct ref *tag_ref; struct ref *rm = NULL; struct ref *ref_map = NULL; struct ref **tail = &ref_map; - struct ref *ref; + const struct ref *ref; for_each_ref(add_existing, &existing_refs); for (ref = transport_get_remote_refs(transport); ref; ref = ref->next) { diff --git a/cache.h b/cache.h index bfffa05dff..119566bf6f 100644 --- a/cache.h +++ b/cache.h @@ -503,7 +503,7 @@ struct ref { #define REF_TAGS (1u << 2) #define CONNECT_VERBOSE (1u << 0) -extern struct child_process *git_connect(int fd[2], char *url, const char *prog, int flags); +extern struct child_process *git_connect(int fd[2], const char *url, const char *prog, int flags); extern int finish_connect(struct child_process *conn); extern int path_match(const char *path, int nr, char **match); extern int get_ack(int fd, unsigned char *result_sha1); diff --git a/connect.c b/connect.c index 44e423dafd..3aefd4ace5 100644 --- a/connect.c +++ b/connect.c @@ -36,6 +36,11 @@ static int check_ref(const char *name, int len, unsigned int flags) return !(flags & ~REF_NORMAL); } +int check_ref_type(const struct ref *ref, int flags) +{ + return check_ref(ref->name, strlen(ref->name), flags); +} + /* * Read all the refs from the other end */ @@ -476,9 +481,10 @@ char *get_port(char *host) * * If it returns, the connect is successful; it just dies on errors. */ -struct child_process *git_connect(int fd[2], char *url, +struct child_process *git_connect(int fd[2], const char *url_orig, const char *prog, int flags) { + char *url = xstrdup(url_orig); char *host, *path = url; char *end; int c; @@ -568,6 +574,7 @@ struct child_process *git_connect(int fd[2], char *url, prog, path, 0, target_host, 0); free(target_host); + free(url); if (free_path) free(path); return NULL; @@ -619,6 +626,7 @@ struct child_process *git_connect(int fd[2], char *url, fd[0] = conn->out; /* read from child's stdout */ fd[1] = conn->in; /* write to child's stdin */ strbuf_release(&cmd); + free(url); if (free_path) free(path); return conn; diff --git a/http-push.c b/http-push.c index c02a3af634..f461bb3248 100644 --- a/http-push.c +++ b/http-push.c @@ -2389,7 +2389,7 @@ int main(int argc, char **argv) if (!remote_tail) remote_tail = &remote_refs; if (match_refs(local_refs, remote_refs, &remote_tail, - nr_refspec, refspec, push_all)) + nr_refspec, (const char **) refspec, push_all)) return -1; if (!remote_refs) { fprintf(stderr, "No refs in common and none specified; doing nothing.\n"); diff --git a/remote.c b/remote.c index bec2ba1adb..59defdbf14 100644 --- a/remote.c +++ b/remote.c @@ -485,7 +485,7 @@ struct ref *alloc_ref(unsigned namelen) return ret; } -static struct ref *copy_ref(struct ref *ref) +static struct ref *copy_ref(const struct ref *ref) { struct ref *ret = xmalloc(sizeof(struct ref) + strlen(ref->name) + 1); memcpy(ret, ref, sizeof(struct ref) + strlen(ref->name) + 1); @@ -493,6 +493,18 @@ static struct ref *copy_ref(struct ref *ref) return ret; } +struct ref *copy_ref_list(const struct ref *ref) +{ + struct ref *ret = NULL; + struct ref **tail = &ret; + while (ref) { + *tail = copy_ref(ref); + ref = ref->next; + tail = &((*tail)->next); + } + return ret; +} + void free_refs(struct ref *ref) { struct ref *next; @@ -710,7 +722,7 @@ static const struct refspec *check_pattern_match(const struct refspec *rs, * without thinking. */ int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail, - int nr_refspec, char **refspec, int all) + int nr_refspec, const char **refspec, int all) { struct refspec *rs = parse_ref_spec(nr_refspec, (const char **) refspec); @@ -810,10 +822,10 @@ int branch_merge_matches(struct branch *branch, return ref_matches_abbrev(branch->merge[i]->src, refname); } -static struct ref *get_expanded_map(struct ref *remote_refs, +static struct ref *get_expanded_map(const struct ref *remote_refs, const struct refspec *refspec) { - struct ref *ref; + const struct ref *ref; struct ref *ret = NULL; struct ref **tail = &ret; @@ -824,7 +836,7 @@ static struct ref *get_expanded_map(struct ref *remote_refs, if (strchr(ref->name, '^')) continue; /* a dereference item */ if (!prefixcmp(ref->name, refspec->src)) { - char *match; + const char *match; struct ref *cpy = copy_ref(ref); match = ref->name + remote_prefix_len; @@ -842,9 +854,9 @@ static struct ref *get_expanded_map(struct ref *remote_refs, return ret; } -static struct ref *find_ref_by_name_abbrev(struct ref *refs, const char *name) +static const struct ref *find_ref_by_name_abbrev(const struct ref *refs, const char *name) { - struct ref *ref; + const struct ref *ref; for (ref = refs; ref; ref = ref->next) { if (ref_matches_abbrev(name, ref->name)) return ref; @@ -852,9 +864,9 @@ static struct ref *find_ref_by_name_abbrev(struct ref *refs, const char *name) return NULL; } -struct ref *get_remote_ref(struct ref *remote_refs, const char *name) +struct ref *get_remote_ref(const struct ref *remote_refs, const char *name) { - struct ref *ref = find_ref_by_name_abbrev(remote_refs, name); + const struct ref *ref = find_ref_by_name_abbrev(remote_refs, name); if (!ref) return NULL; @@ -887,7 +899,7 @@ static struct ref *get_local_ref(const char *name) return ret; } -int get_fetch_map(struct ref *remote_refs, +int get_fetch_map(const struct ref *remote_refs, const struct refspec *refspec, struct ref ***tail, int missing_ok) diff --git a/remote.h b/remote.h index 878b4ecc32..6a4c7a0f37 100644 --- a/remote.h +++ b/remote.h @@ -44,6 +44,10 @@ struct refspec { struct ref *alloc_ref(unsigned namelen); +struct ref *copy_ref_list(const struct ref *ref); + +int check_ref_type(const struct ref *ref, int flags); + /* * Frees the entire list and peers of elements. */ @@ -57,7 +61,7 @@ void ref_remove_duplicates(struct ref *ref_map); struct refspec *parse_ref_spec(int nr_refspec, const char **refspec); int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail, - int nr_refspec, char **refspec, int all); + int nr_refspec, const char **refspec, int all); /* * Given a list of the remote refs and the specification of things to @@ -71,10 +75,10 @@ int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail, * missing_ok is usually false, but when we are adding branch.$name.merge * it is Ok if the branch is not at the remote anymore. */ -int get_fetch_map(struct ref *remote_refs, const struct refspec *refspec, +int get_fetch_map(const struct ref *remote_refs, const struct refspec *refspec, struct ref ***tail, int missing_ok); -struct ref *get_remote_ref(struct ref *remote_refs, const char *name); +struct ref *get_remote_ref(const struct ref *remote_refs, const char *name); /* * For the given remote, reads the refspec's src and sets the other fields. diff --git a/send-pack.c b/send-pack.c index 5e127a1b7b..456fe4f125 100644 --- a/send-pack.c +++ b/send-pack.c @@ -207,7 +207,7 @@ static void update_tracking_ref(struct remote *remote, struct ref *ref) } } -static int send_pack(int in, int out, struct remote *remote, int nr_refspec, char **refspec) +static int send_pack(int in, int out, struct remote *remote, int nr_refspec, const char **refspec) { struct ref *ref; int new_refs; @@ -357,7 +357,7 @@ static int send_pack(int in, int out, struct remote *remote, int nr_refspec, cha return ret; } -static void verify_remote_names(int nr_heads, char **heads) +static void verify_remote_names(int nr_heads, const char **heads) { int i; @@ -382,7 +382,7 @@ int main(int argc, char **argv) { int i, nr_heads = 0; char *dest = NULL; - char **heads = NULL; + const char **heads = NULL; int fd[2], ret; struct child_process *conn; char *remote_name = NULL; @@ -434,7 +434,7 @@ int main(int argc, char **argv) dest = arg; continue; } - heads = argv; + heads = (const char **) argv; nr_heads = argc - i; break; } diff --git a/transport.c b/transport.c index d44fe7cee7..ab79f0cbb0 100644 --- a/transport.c +++ b/transport.c @@ -141,7 +141,7 @@ static void insert_packed_refs(const char *packed_refs, struct ref **list) } } -static struct ref *get_refs_via_rsync(const struct transport *transport) +static struct ref *get_refs_via_rsync(struct transport *transport) { struct strbuf buf = STRBUF_INIT, temp_dir = STRBUF_INIT; struct ref dummy, *tail = &dummy; @@ -427,7 +427,7 @@ static int missing__target(int code, int result) #define missing_target(a) missing__target((a)->http_code, (a)->curl_result) -static struct ref *get_refs_via_curl(const struct transport *transport) +static struct ref *get_refs_via_curl(struct transport *transport) { struct buffer buffer; char *data, *start, *mid; @@ -524,7 +524,7 @@ struct bundle_transport_data { struct bundle_header header; }; -static struct ref *get_refs_from_bundle(const struct transport *transport) +static struct ref *get_refs_from_bundle(struct transport *transport) { struct bundle_transport_data *data = transport->data; struct ref *result = NULL; @@ -596,7 +596,7 @@ static int set_git_option(struct transport *connection, return 1; } -static struct ref *get_refs_via_connect(const struct transport *transport) +static struct ref *get_refs_via_connect(struct transport *transport) { struct git_transport_data *data = transport->data; struct ref *refs; @@ -781,7 +781,7 @@ int transport_push(struct transport *transport, return transport->push(transport, refspec_nr, refspec, flags); } -struct ref *transport_get_remote_refs(struct transport *transport) +const struct ref *transport_get_remote_refs(struct transport *transport) { if (!transport->remote_refs) transport->remote_refs = transport->get_refs_list(transport); diff --git a/transport.h b/transport.h index df12ea7424..d27f5629d2 100644 --- a/transport.h +++ b/transport.h @@ -8,7 +8,7 @@ struct transport { struct remote *remote; const char *url; void *data; - struct ref *remote_refs; + const struct ref *remote_refs; /** * Returns 0 if successful, positive if the option is not @@ -18,7 +18,7 @@ struct transport { int (*set_option)(struct transport *connection, const char *name, const char *value); - struct ref *(*get_refs_list)(const struct transport *transport); + struct ref *(*get_refs_list)(struct transport *transport); int (*fetch)(struct transport *transport, int refs_nr, struct ref **refs); int (*push)(struct transport *connection, int refspec_nr, const char **refspec, int flags); @@ -61,7 +61,7 @@ int transport_set_option(struct transport *transport, const char *name, int transport_push(struct transport *connection, int refspec_nr, const char **refspec, int flags); -struct ref *transport_get_remote_refs(struct transport *transport); +const struct ref *transport_get_remote_refs(struct transport *transport); int transport_fetch_refs(struct transport *transport, struct ref *refs); void transport_unlock_pack(struct transport *transport); From 18f7c51cf921f7db021e012499456120f3f095a9 Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Mon, 29 Oct 2007 21:05:43 -0400 Subject: [PATCH 0416/1490] Build-in peek-remote, using transport infrastructure. Signed-off-by: Daniel Barkalow Signed-off-by: Junio C Hamano --- Makefile | 3 +- peek-remote.c => builtin-peek-remote.c | 55 ++++++++++++-------------- builtin.h | 1 + git.c | 1 + 4 files changed, 30 insertions(+), 30 deletions(-) rename peek-remote.c => builtin-peek-remote.c (59%) diff --git a/Makefile b/Makefile index 042f79ef8f..14f25ff8ec 100644 --- a/Makefile +++ b/Makefile @@ -239,7 +239,7 @@ PROGRAMS = \ git-fast-import$X \ git-daemon$X \ git-merge-index$X git-mktag$X git-mktree$X git-patch-id$X \ - git-peek-remote$X git-receive-pack$X \ + git-receive-pack$X \ git-send-pack$X git-shell$X \ git-show-index$X \ git-unpack-file$X \ @@ -352,6 +352,7 @@ BUILTIN_OBJS = \ builtin-mv.o \ builtin-name-rev.o \ builtin-pack-objects.o \ + builtin-peek-remote.o \ builtin-prune.o \ builtin-prune-packed.o \ builtin-push.o \ diff --git a/peek-remote.c b/builtin-peek-remote.c similarity index 59% rename from peek-remote.c rename to builtin-peek-remote.c index 8d20f7c9c6..b4106f510a 100644 --- a/peek-remote.c +++ b/builtin-peek-remote.c @@ -1,38 +1,26 @@ +#include "builtin.h" #include "cache.h" -#include "refs.h" -#include "pkt-line.h" +#include "transport.h" +#include "remote.h" static const char peek_remote_usage[] = "git-peek-remote [--upload-pack=] [:]"; -static const char *uploadpack = "git-upload-pack"; -static int peek_remote(int fd[2], unsigned flags) +int cmd_peek_remote(int argc, const char **argv, const char *prefix) { - struct ref *ref; - - get_remote_heads(fd[0], &ref, 0, NULL, flags); - packet_flush(fd[1]); - - while (ref) { - printf("%s %s\n", sha1_to_hex(ref->old_sha1), ref->name); - ref = ref->next; - } - return 0; -} - -int main(int argc, char **argv) -{ - int i, ret; - char *dest = NULL; - int fd[2]; - struct child_process *conn; + int i; + const char *dest = NULL; int nongit = 0; unsigned flags = 0; + const char *uploadpack = NULL; + + struct transport *transport; + const struct ref *ref; setup_git_directory_gently(&nongit); for (i = 1; i < argc; i++) { - char *arg = argv[i]; + const char *arg = argv[i]; if (*arg == '-') { if (!prefixcmp(arg, "--upload-pack=")) { @@ -64,10 +52,19 @@ int main(int argc, char **argv) if (!dest || i != argc - 1) usage(peek_remote_usage); - conn = git_connect(fd, dest, uploadpack, 0); - ret = peek_remote(fd, flags); - close(fd[0]); - close(fd[1]); - ret |= finish_connect(conn); - return !!ret; + transport = transport_get(NULL, dest); + if (uploadpack != NULL) + transport_set_option(transport, TRANS_OPT_UPLOADPACK, uploadpack); + + ref = transport_get_remote_refs(transport); + + if (!ref) + return 1; + + while (ref) { + if (check_ref_type(ref, flags)) + printf("%s %s\n", sha1_to_hex(ref->old_sha1), ref->name); + ref = ref->next; + } + return 0; } diff --git a/builtin.h b/builtin.h index 9a6213af12..62ee5373dc 100644 --- a/builtin.h +++ b/builtin.h @@ -55,6 +55,7 @@ extern int cmd_merge_file(int argc, const char **argv, const char *prefix); extern int cmd_mv(int argc, const char **argv, const char *prefix); extern int cmd_name_rev(int argc, const char **argv, const char *prefix); extern int cmd_pack_objects(int argc, const char **argv, const char *prefix); +extern int cmd_peek_remote(int argc, const char **argv, const char *prefix); extern int cmd_pickaxe(int argc, const char **argv, const char *prefix); extern int cmd_prune(int argc, const char **argv, const char *prefix); extern int cmd_prune_packed(int argc, const char **argv, const char *prefix); diff --git a/git.c b/git.c index 4e10581101..c55a13de17 100644 --- a/git.c +++ b/git.c @@ -333,6 +333,7 @@ static void handle_internal_command(int argc, const char **argv) { "mv", cmd_mv, RUN_SETUP | NEED_WORK_TREE }, { "name-rev", cmd_name_rev, RUN_SETUP }, { "pack-objects", cmd_pack_objects, RUN_SETUP }, + { "peek-remote", cmd_peek_remote }, { "pickaxe", cmd_blame, RUN_SETUP }, { "prune", cmd_prune, RUN_SETUP }, { "prune-packed", cmd_prune_packed, RUN_SETUP }, From 40cb4fab720807f8525fb125e6c4ddc802ee8ed1 Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Mon, 29 Oct 2007 22:03:42 -0400 Subject: [PATCH 0417/1490] Use built-in send-pack. Signed-off-by: Daniel Barkalow Signed-off-by: Junio C Hamano --- transport.c | 51 ++++++++++----------------------------------------- 1 file changed, 10 insertions(+), 41 deletions(-) diff --git a/transport.c b/transport.c index ab79f0cbb0..f4577b7fc6 100644 --- a/transport.c +++ b/transport.c @@ -6,6 +6,7 @@ #endif #include "pkt-line.h" #include "fetch-pack.h" +#include "send-pack.h" #include "walker.h" #include "bundle.h" #include "dir.h" @@ -648,48 +649,16 @@ static int fetch_refs_via_pack(struct transport *transport, static int git_transport_push(struct transport *transport, int refspec_nr, const char **refspec, int flags) { struct git_transport_data *data = transport->data; - const char **argv; - char *rem; - int argc; - int err; + struct send_pack_args args; - argv = xmalloc((refspec_nr + 11) * sizeof(char *)); - argv[0] = "send-pack"; - argc = 1; - if (flags & TRANSPORT_PUSH_ALL) - argv[argc++] = "--all"; - if (flags & TRANSPORT_PUSH_FORCE) - argv[argc++] = "--force"; - if (flags & TRANSPORT_PUSH_DRY_RUN) - argv[argc++] = "--dry-run"; - if (data->receivepack) { - char *rp = xmalloc(strlen(data->receivepack) + 16); - sprintf(rp, "--receive-pack=%s", data->receivepack); - argv[argc++] = rp; - } - if (data->thin) - argv[argc++] = "--thin"; - rem = xmalloc(strlen(transport->remote->name) + 10); - sprintf(rem, "--remote=%s", transport->remote->name); - argv[argc++] = rem; - argv[argc++] = transport->url; - while (refspec_nr--) - argv[argc++] = *refspec++; - argv[argc] = NULL; - err = run_command_v_opt(argv, RUN_GIT_CMD); - switch (err) { - case -ERR_RUN_COMMAND_FORK: - error("unable to fork for %s", argv[0]); - case -ERR_RUN_COMMAND_EXEC: - error("unable to exec %s", argv[0]); - break; - case -ERR_RUN_COMMAND_WAITPID: - case -ERR_RUN_COMMAND_WAITPID_WRONG_PID: - case -ERR_RUN_COMMAND_WAITPID_SIGNAL: - case -ERR_RUN_COMMAND_WAITPID_NOEXIT: - error("%s died with strange error", argv[0]); - } - return !!err; + args.receivepack = data->receivepack; + args.send_all = !!(flags & TRANSPORT_PUSH_ALL); + args.force_update = !!(flags & TRANSPORT_PUSH_FORCE); + args.use_thin_pack = data->thin; + args.verbose = transport->verbose; + args.dry_run = !!(flags & TRANSPORT_PUSH_DRY_RUN); + + return send_pack(&args, transport->url, transport->remote, refspec_nr, refspec); } static int disconnect_git(struct transport *transport) From 96249c04c07f00485a3ed1052ff10b27ab147fc5 Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Mon, 29 Oct 2007 22:03:39 -0400 Subject: [PATCH 0418/1490] Build-in send-pack, with an API for other programs to call. Also marks some more things as const, as needed. Signed-off-by: Daniel Barkalow Signed-off-by: Junio C Hamano --- Makefile | 1 + send-pack.c => builtin-send-pack.c | 81 ++++++++++++++++-------------- builtin.h | 1 + git.c | 1 + send-pack.h | 17 +++++++ 5 files changed, 64 insertions(+), 37 deletions(-) rename send-pack.c => builtin-send-pack.c (88%) create mode 100644 send-pack.h diff --git a/Makefile b/Makefile index 14f25ff8ec..3ec1876cbb 100644 --- a/Makefile +++ b/Makefile @@ -358,6 +358,7 @@ BUILTIN_OBJS = \ builtin-push.o \ builtin-read-tree.o \ builtin-reflog.o \ + builtin-send-pack.o \ builtin-config.o \ builtin-rerere.o \ builtin-reset.o \ diff --git a/send-pack.c b/builtin-send-pack.c similarity index 88% rename from send-pack.c rename to builtin-send-pack.c index 456fe4f125..aedef09ef0 100644 --- a/send-pack.c +++ b/builtin-send-pack.c @@ -5,16 +5,15 @@ #include "pkt-line.h" #include "run-command.h" #include "remote.h" +#include "send-pack.h" static const char send_pack_usage[] = "git-send-pack [--all] [--dry-run] [--force] [--receive-pack=] [--verbose] [--thin] [:] [...]\n" " --all and explicit specification are mutually exclusive."; -static const char *receivepack = "git-receive-pack"; -static int verbose; -static int send_all; -static int force_update; -static int use_thin_pack; -static int dry_run; + +static struct send_pack_args args = { + /* .receivepack = */ "git-receive-pack", +}; /* * Make a pack stream and spit it out into file descriptor fd @@ -26,7 +25,7 @@ static int pack_objects(int fd, struct ref *refs) * the revision parameters to it via its stdin and * let its stdout go back to the other end. */ - const char *args[] = { + const char *argv[] = { "pack-objects", "--all-progress", "--revs", @@ -36,10 +35,10 @@ static int pack_objects(int fd, struct ref *refs) }; struct child_process po; - if (use_thin_pack) - args[4] = "--thin"; + if (args.use_thin_pack) + argv[4] = "--thin"; memset(&po, 0, sizeof(po)); - po.argv = args; + po.argv = argv; po.in = -1; po.out = fd; po.git_cmd = 1; @@ -207,7 +206,7 @@ static void update_tracking_ref(struct remote *remote, struct ref *ref) } } -static int send_pack(int in, int out, struct remote *remote, int nr_refspec, const char **refspec) +static int do_send_pack(int in, int out, struct remote *remote, int nr_refspec, const char **refspec) { struct ref *ref; int new_refs; @@ -230,7 +229,7 @@ static int send_pack(int in, int out, struct remote *remote, int nr_refspec, con if (!remote_tail) remote_tail = &remote_refs; if (match_refs(local_refs, remote_refs, &remote_tail, - nr_refspec, refspec, send_all)) + nr_refspec, refspec, args.send_all)) return -1; if (!remote_refs) { @@ -259,7 +258,7 @@ static int send_pack(int in, int out, struct remote *remote, int nr_refspec, con } if (!will_delete_ref && !hashcmp(ref->old_sha1, ref->peer_ref->new_sha1)) { - if (verbose) + if (args.verbose) fprintf(stderr, "'%s': up-to-date\n", ref->name); continue; } @@ -283,7 +282,7 @@ static int send_pack(int in, int out, struct remote *remote, int nr_refspec, con * always allowed. */ - if (!force_update && + if (!args.force_update && !will_delete_ref && !is_null_sha1(ref->old_sha1) && !ref->force) { @@ -313,7 +312,7 @@ static int send_pack(int in, int out, struct remote *remote, int nr_refspec, con strcpy(old_hex, sha1_to_hex(ref->old_sha1)); new_hex = sha1_to_hex(ref->new_sha1); - if (!dry_run) { + if (!args.dry_run) { if (ask_for_status_report) { packet_write(out, "%s %s %s%c%s", old_hex, new_hex, ref->name, 0, @@ -338,7 +337,7 @@ static int send_pack(int in, int out, struct remote *remote, int nr_refspec, con } packet_flush(out); - if (new_refs && !dry_run) + if (new_refs && !args.dry_run) ret = pack_objects(out, remote_refs); close(out); @@ -347,7 +346,7 @@ static int send_pack(int in, int out, struct remote *remote, int nr_refspec, con ret = -4; } - if (!dry_run && remote && ret == 0) { + if (!args.dry_run && remote && ret == 0) { for (ref = remote_refs; ref; ref = ref->next) update_tracking_ref(remote, ref); } @@ -378,30 +377,25 @@ static void verify_remote_names(int nr_heads, const char **heads) } } -int main(int argc, char **argv) +int cmd_send_pack(int argc, const char **argv, const char *prefix) { int i, nr_heads = 0; - char *dest = NULL; const char **heads = NULL; - int fd[2], ret; - struct child_process *conn; - char *remote_name = NULL; + const char *remote_name = NULL; struct remote *remote = NULL; - - setup_git_directory(); - git_config(git_default_config); + const char *dest = NULL; argv++; for (i = 1; i < argc; i++, argv++) { - char *arg = *argv; + const char *arg = *argv; if (*arg == '-') { if (!prefixcmp(arg, "--receive-pack=")) { - receivepack = arg + 15; + args.receivepack = arg + 15; continue; } if (!prefixcmp(arg, "--exec=")) { - receivepack = arg + 7; + args.receivepack = arg + 7; continue; } if (!prefixcmp(arg, "--remote=")) { @@ -409,23 +403,23 @@ int main(int argc, char **argv) continue; } if (!strcmp(arg, "--all")) { - send_all = 1; + args.send_all = 1; continue; } if (!strcmp(arg, "--dry-run")) { - dry_run = 1; + args.dry_run = 1; continue; } if (!strcmp(arg, "--force")) { - force_update = 1; + args.force_update = 1; continue; } if (!strcmp(arg, "--verbose")) { - verbose = 1; + args.verbose = 1; continue; } if (!strcmp(arg, "--thin")) { - use_thin_pack = 1; + args.use_thin_pack = 1; continue; } usage(send_pack_usage); @@ -440,9 +434,8 @@ int main(int argc, char **argv) } if (!dest) usage(send_pack_usage); - if (heads && send_all) + if (heads && args.send_all) usage(send_pack_usage); - verify_remote_names(nr_heads, heads); if (remote_name) { remote = remote_get(remote_name); @@ -452,8 +445,22 @@ int main(int argc, char **argv) } } - conn = git_connect(fd, dest, receivepack, verbose ? CONNECT_VERBOSE : 0); - ret = send_pack(fd[0], fd[1], remote, nr_heads, heads); + return send_pack(&args, dest, remote, nr_heads, heads); +} + +int send_pack(struct send_pack_args *my_args, + const char *dest, struct remote *remote, + int nr_heads, const char **heads) +{ + int fd[2], ret; + struct child_process *conn; + + memcpy(&args, my_args, sizeof(args)); + + verify_remote_names(nr_heads, heads); + + conn = git_connect(fd, dest, args.receivepack, args.verbose ? CONNECT_VERBOSE : 0); + ret = do_send_pack(fd[0], fd[1], remote, nr_heads, heads); close(fd[0]); close(fd[1]); ret |= finish_connect(conn); diff --git a/builtin.h b/builtin.h index 62ee5373dc..2335c01b02 100644 --- a/builtin.h +++ b/builtin.h @@ -70,6 +70,7 @@ extern int cmd_rev_parse(int argc, const char **argv, const char *prefix); extern int cmd_revert(int argc, const char **argv, const char *prefix); extern int cmd_rm(int argc, const char **argv, const char *prefix); extern int cmd_runstatus(int argc, const char **argv, const char *prefix); +extern int cmd_send_pack(int argc, const char **argv, const char *prefix); extern int cmd_shortlog(int argc, const char **argv, const char *prefix); extern int cmd_show(int argc, const char **argv, const char *prefix); extern int cmd_show_branch(int argc, const char **argv, const char *prefix); diff --git a/git.c b/git.c index c55a13de17..19a2172a10 100644 --- a/git.c +++ b/git.c @@ -348,6 +348,7 @@ static void handle_internal_command(int argc, const char **argv) { "revert", cmd_revert, RUN_SETUP | NEED_WORK_TREE }, { "rm", cmd_rm, RUN_SETUP | NEED_WORK_TREE }, { "runstatus", cmd_runstatus, RUN_SETUP | NEED_WORK_TREE }, + { "send-pack", cmd_send_pack, RUN_SETUP }, { "shortlog", cmd_shortlog, RUN_SETUP | USE_PAGER }, { "show-branch", cmd_show_branch, RUN_SETUP }, { "show", cmd_show, RUN_SETUP | USE_PAGER }, diff --git a/send-pack.h b/send-pack.h new file mode 100644 index 0000000000..7a24f71c77 --- /dev/null +++ b/send-pack.h @@ -0,0 +1,17 @@ +#ifndef SEND_PACK_H +#define SEND_PACK_H + +struct send_pack_args { + const char *receivepack; + unsigned verbose:1, + send_all:1, + force_update:1, + use_thin_pack:1, + dry_run:1; +}; + +int send_pack(struct send_pack_args *args, + const char *dest, struct remote *remote, + int nr_heads, const char **heads); + +#endif From 00ae82895e7f30e52ff12edc1076409c7c53d99e Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Fri, 2 Nov 2007 22:39:44 -0400 Subject: [PATCH 0419/1490] errors: "strict subset" -> "ancestor" The term "ancestor" is a bit more intuitive (and more consistent with the documentation) than the term "strict subset". Also, remove superfluous "ref", capitalize, and add some carriage returns, changing: error: remote 'refs/heads/master' is not a strict subset of local ref 'refs/heads/master'. maybe you are not up-to-date and need to pull first? error: failed to push to 'ssh://linux-nfs.org/~bfields/exports/git.git' to: error: remote 'refs/heads/master' is not an ancestor of local 'refs/heads/master'. Maybe you are not up-to-date and need to pull first? error: failed to push to 'ssh://linux-nfs.org/~bfields/exports/git.git' Signed-off-by: J. Bruce Fields Signed-off-by: Junio C Hamano --- builtin-branch.c | 2 +- http-push.c | 15 ++++++++++----- send-pack.c | 6 +++--- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/builtin-branch.c b/builtin-branch.c index d6d5cff6b8..fbd90e42d1 100644 --- a/builtin-branch.c +++ b/builtin-branch.c @@ -148,7 +148,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds) if (!force && !in_merge_bases(rev, &head_rev, 1)) { - error("The branch '%s' is not a strict subset of " + error("The branch '%s' is not an ancestor of " "your current HEAD.\n" "If you are sure you want to delete it, " "run 'git branch -D %s'.", argv[i], argv[i]); diff --git a/http-push.c b/http-push.c index c02a3af634..9314621a11 100644 --- a/http-push.c +++ b/http-push.c @@ -2241,7 +2241,11 @@ static int delete_remote_branch(char *pattern, int force) /* Remote branch must be an ancestor of remote HEAD */ if (!verify_merge_base(head_sha1, remote_ref->old_sha1)) { - return error("The branch '%s' is not a strict subset of your current HEAD.\nIf you are sure you want to delete it, run:\n\t'git http-push -D %s %s'", remote_ref->name, remote->url, pattern); + return error("The branch '%s' is not an ancestor " + "of your current HEAD.\n" + "If you are sure you want to delete it," + " run:\n\t'git http-push -D %s %s'", + remote_ref->name, remote->url, pattern); } } @@ -2417,16 +2421,17 @@ int main(int argc, char **argv) if (!has_sha1_file(ref->old_sha1) || !ref_newer(ref->peer_ref->new_sha1, ref->old_sha1)) { - /* We do not have the remote ref, or + /* + * We do not have the remote ref, or * we know that the remote ref is not * an ancestor of what we are trying to * push. Either way this can be losing * commits at the remote end and likely * we were not up to date to begin with. */ - error("remote '%s' is not a strict " - "subset of local ref '%s'. " - "maybe you are not up-to-date and " + error("remote '%s' is not an ancestor of\n" + "local '%s'.\n" + "Maybe you are not up-to-date and " "need to pull first?", ref->name, ref->peer_ref->name); diff --git a/send-pack.c b/send-pack.c index 5e127a1b7b..b74fd454f2 100644 --- a/send-pack.c +++ b/send-pack.c @@ -297,9 +297,9 @@ static int send_pack(int in, int out, struct remote *remote, int nr_refspec, cha * commits at the remote end and likely * we were not up to date to begin with. */ - error("remote '%s' is not a strict " - "subset of local ref '%s'. " - "maybe you are not up-to-date and " + error("remote '%s' is not an ancestor of\n" + " local '%s'.\n" + " Maybe you are not up-to-date and " "need to pull first?", ref->name, ref->peer_ref->name); From a0554224a285b73b87fe1c95dbdff469561b182f Mon Sep 17 00:00:00 2001 From: Gerrit Pape Date: Sat, 3 Nov 2007 11:55:02 +0000 Subject: [PATCH 0420/1490] git-cvsimport: really convert underscores in branch names to dots with -u The documentation states for the -u option that underscores in tag and branch names are converted to dots, but this was actually implemented for the tag names only. Kurt Roeckx reported this through http://bugs.debian.org/446495 Signed-off-by: Gerrit Pape Signed-off-by: Junio C Hamano --- git-cvsimport.perl | 1 + 1 file changed, 1 insertion(+) diff --git a/git-cvsimport.perl b/git-cvsimport.perl index 2954fb846e..e4bc2b54f6 100755 --- a/git-cvsimport.perl +++ b/git-cvsimport.perl @@ -818,6 +818,7 @@ sub commit { $state = 4; } elsif ($state == 4 and s/^Branch:\s+//) { s/\s+$//; + tr/_/\./ if ( $opt_u ); s/[\/]/$opt_s/g; $branch = $_; $state = 5; From b92565dc5c505c3d01f3219fb7f61ebc70630a2c Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Sat, 3 Nov 2007 13:22:53 +0100 Subject: [PATCH 0421/1490] Delay pager setup in git blame This avoids to launch the pager when git blame fails for any reason. Signed-off-by: Mike Hommey Signed-off-by: Junio C Hamano --- builtin-blame.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/builtin-blame.c b/builtin-blame.c index dc88a953a5..e17b03d876 100644 --- a/builtin-blame.c +++ b/builtin-blame.c @@ -2231,9 +2231,6 @@ int cmd_blame(int argc, const char **argv, const char *prefix) argv[unk++] = arg; } - if (!incremental) - setup_pager(); - if (!blame_move_score) blame_move_score = BLAME_DEFAULT_MOVE_SCORE; if (!blame_copy_score) @@ -2427,6 +2424,9 @@ int cmd_blame(int argc, const char **argv, const char *prefix) read_mailmap(&mailmap, ".mailmap", NULL); + if (!incremental) + setup_pager(); + assign_blame(&sb, &revs, opt); if (incremental) From 4b7bbdd14c6b926fbb0dbd203ce02e150b308694 Mon Sep 17 00:00:00 2001 From: Steven Grimm Date: Sat, 3 Nov 2007 19:26:54 -0700 Subject: [PATCH 0422/1490] builtin-fetch: Add "-q" as a synonym for "--quiet" "-q" is the very first option described in the git-fetch manpage, and it isn't supported. Signed-off-by: Steven Grimm Signed-off-by: Junio C Hamano --- builtin-fetch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin-fetch.c b/builtin-fetch.c index 003ed76d16..8e790552cd 100644 --- a/builtin-fetch.c +++ b/builtin-fetch.c @@ -517,7 +517,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) depth = argv[i]; continue; } - if (!strcmp(arg, "--quiet")) { + if (!strcmp(arg, "--quiet") || !strcmp(arg, "-q")) { quiet = 1; continue; } From aa807bc2663d69d6adb1d823231ba4b6d30d4860 Mon Sep 17 00:00:00 2001 From: Benoit Sigoure Date: Sat, 3 Nov 2007 19:53:34 +0100 Subject: [PATCH 0423/1490] git-svn: sort the options in the --help message. "git svn --help" gave options in the order they were found in a Perl hash, which meant "randomly" to humans. Signed-off-by: Benoit Sigoure Acked-by: Eric Wong Signed-off-by: Junio C Hamano --- git-svn.perl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git-svn.perl b/git-svn.perl index 22bb47b34d..4900f57f18 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -252,7 +252,7 @@ sub usage { next if $cmd && $cmd ne $_; next if /^multi-/; # don't show deprecated commands print $fd ' ',pack('A17',$_),$cmd{$_}->[1],"\n"; - foreach (keys %{$cmd{$_}->[2]}) { + foreach (sort keys %{$cmd{$_}->[2]}) { # mixed-case options are for .git/config only next if /[A-Z]/ && /^[a-z]+$/i; # prints out arguments as they should be passed: From ee787400de25ed419f40e70698ba35db475b2d61 Mon Sep 17 00:00:00 2001 From: David D Kilzer Date: Sat, 3 Nov 2007 07:04:52 -0700 Subject: [PATCH 0424/1490] RelNotes-1.5.3.5: fix typo Signed-off-by: David D Kilzer Signed-off-by: Junio C Hamano --- Documentation/RelNotes-1.5.3.5.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/RelNotes-1.5.3.5.txt b/Documentation/RelNotes-1.5.3.5.txt index 4e46d2c2a2..f99a2cd650 100644 --- a/Documentation/RelNotes-1.5.3.5.txt +++ b/Documentation/RelNotes-1.5.3.5.txt @@ -63,8 +63,8 @@ Fixes since v1.5.3.4 * Git segfaulted when reading an invalid .gitattributes file. Fixed. - * post-receive-email example hook fixed was fixed for - non-fast-forward updates. + * post-receive-email example hook was fixed for non-fast-forward + updates. * Documentation updates for supported (but previously undocumented) options of "git-archive" and "git-reflog". From 19391c371cec06da6cca45dbe3c212bd479cc48c Mon Sep 17 00:00:00 2001 From: Heikki Orsila Date: Thu, 1 Nov 2007 16:21:39 +0200 Subject: [PATCH 0425/1490] git-clone: honor "--" to end argument parsing Signed-off-by: Heikki Orsila --- Documentation/git-clone.txt | 2 +- git-clone.sh | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt index cca14d6b5d..14e58f3866 100644 --- a/Documentation/git-clone.txt +++ b/Documentation/git-clone.txt @@ -12,7 +12,7 @@ SYNOPSIS 'git-clone' [--template=] [-l] [-s] [--no-hardlinks] [-q] [-n] [--bare] [-o ] [-u ] [--reference ] - [--depth ] [] + [--depth ] [--] [] DESCRIPTION ----------- diff --git a/git-clone.sh b/git-clone.sh index 0ea3c24f59..3f00693608 100755 --- a/git-clone.sh +++ b/git-clone.sh @@ -14,7 +14,7 @@ die() { } usage() { - die "Usage: $0 [--template=] [--reference ] [--bare] [-l [-s]] [-q] [-u ] [--origin ] [--depth ] [-n] []" + die "Usage: $0 [--template=] [--reference ] [--bare] [-l [-s]] [-q] [-u ] [--origin ] [--depth ] [-n] [--] []" } get_repo_base() { @@ -160,6 +160,9 @@ while *,--depth) shift depth="--depth=$1";; + *,--) + shift + break ;; *,-*) usage ;; *) break ;; esac From 2e7a9785c27f00a8f7a06edc1d4c9b2f3fa2eeb9 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sat, 3 Nov 2007 13:12:17 +0000 Subject: [PATCH 0426/1490] git-reset: do not be confused if there is nothing to reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The purpose of the function update_index_from_diff() (which is the callback function we give do_diff_cache()) is to update those index entries which differ from the given commit. Since do_diff_cache() plays games with the in-memory index, this function discarded the cache and reread it. Then, back in the function read_from_tree() we wrote the index. Of course, this broke down when there were no changes and update_index_from_diff() was not called, and therefore the mangled index was not discarded. The solution is to move the index writing into the function update_index_from_diff(). Noticed by Björn Steinbrink. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- builtin-reset.c | 24 ++++++++++++++++++------ t/t7102-reset.sh | 7 +++++++ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/builtin-reset.c b/builtin-reset.c index e1dc31e0eb..5467e36c73 100644 --- a/builtin-reset.c +++ b/builtin-reset.c @@ -113,10 +113,17 @@ static int update_index_refresh(void) return run_command_v_opt(argv_update_index, RUN_GIT_CMD); } +struct update_cb_data { + int index_fd; + struct lock_file *lock; + int exit_code; +}; + static void update_index_from_diff(struct diff_queue_struct *q, struct diff_options *opt, void *data) { int i; + struct update_cb_data *cb = data; /* do_diff_cache() mangled the index */ discard_cache(); @@ -133,29 +140,34 @@ static void update_index_from_diff(struct diff_queue_struct *q, } else remove_file_from_cache(one->path); } + + cb->exit_code = write_cache(cb->index_fd, active_cache, active_nr) || + close(cb->index_fd) || + commit_locked_index(cb->lock); } static int read_from_tree(const char *prefix, const char **argv, unsigned char *tree_sha1) { - struct lock_file *lock = xcalloc(1, sizeof(struct lock_file)); - int index_fd; struct diff_options opt; + struct update_cb_data cb; memset(&opt, 0, sizeof(opt)); diff_tree_setup_paths(get_pathspec(prefix, (const char **)argv), &opt); opt.output_format = DIFF_FORMAT_CALLBACK; opt.format_callback = update_index_from_diff; + opt.format_callback_data = &cb; - index_fd = hold_locked_index(lock, 1); + cb.lock = xcalloc(1, sizeof(struct lock_file)); + cb.index_fd = hold_locked_index(cb.lock, 1); + cb.exit_code = 0; read_cache(); if (do_diff_cache(tree_sha1, &opt)) return 1; diffcore_std(&opt); diff_flush(&opt); - return write_cache(index_fd, active_cache, active_nr) || - close(index_fd) || - commit_locked_index(lock); + + return cb.exit_code; } static void prepend_reflog_action(const char *action, char *buf, size_t size) diff --git a/t/t7102-reset.sh b/t/t7102-reset.sh index f64b1cbf75..cea9afb764 100755 --- a/t/t7102-reset.sh +++ b/t/t7102-reset.sh @@ -402,4 +402,11 @@ test_expect_success 'test resetting the index at give paths' ' ' +test_expect_success 'resetting an unmodified path is a no-op' ' + git reset --hard && + git reset -- file1 && + git diff-files --exit-code && + git diff-index --cached --exit-code HEAD +' + test_done From 1e8a1954519a070e92cb73f756b271664e1cc4d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?= Date: Sat, 3 Nov 2007 20:18:06 +0700 Subject: [PATCH 0427/1490] Add missing inside_work_tree setting in setup_git_directory_gently MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When both GIT_DIR and GIT_WORK_TREE are set, and setup_git_directory_gently() changes the current working directory accordingly, it should also set inside_work_tree = 1. Without this, work_tree handling code in setup_git_directory() will be activated. If you stay in root work tree (no prefix), it does not harm. It does if you work from a subdirectory though. Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano --- setup.c | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.c b/setup.c index 145eca50f4..6f8f769584 100644 --- a/setup.c +++ b/setup.c @@ -240,6 +240,7 @@ const char *setup_git_directory_gently(int *nongit_ok) if (chdir(work_tree_env) < 0) die ("Could not chdir to %s", work_tree_env); strcat(buffer, "/"); + inside_work_tree = 1; return retval; } if (nongit_ok) { From 23c17d4a4a0e1fc9a5fa347f1fc6be3cf477e543 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 2 Nov 2007 13:32:58 -0700 Subject: [PATCH 0428/1490] Simplify topo-sort logic .. by not using quite so much indirection. This currently grows the "struct commit" a bit, which could be avoided by using a union for "util" and "indegree" (the topo-sort used to use "util" anyway, so you cannot use them together), but for now the goal of this was to simplify, not optimize. Signed-off-by: Linus Torvalds --- commit.c | 148 ++++++++++++++++++----------------------------------- commit.h | 20 +------- revision.c | 7 +-- revision.h | 4 +- 4 files changed, 54 insertions(+), 125 deletions(-) diff --git a/commit.c b/commit.c index 8262f6ac58..ab4eb8bdd1 100644 --- a/commit.c +++ b/commit.c @@ -9,22 +9,6 @@ int save_commit_buffer = 1; -struct sort_node -{ - /* - * the number of children of the associated commit - * that also occur in the list being sorted. - */ - unsigned int indegree; - - /* - * reference to original list item that we will re-use - * on output. - */ - struct commit_list * list_item; - -}; - const char *commit_type = "commit"; static struct cmt_fmt_map { @@ -1149,69 +1133,38 @@ struct commit *pop_commit(struct commit_list **stack) return item; } -void topo_sort_default_setter(struct commit *c, void *data) -{ - c->util = data; -} - -void *topo_sort_default_getter(struct commit *c) -{ - return c->util; -} - /* * Performs an in-place topological sort on the list supplied. */ void sort_in_topological_order(struct commit_list ** list, int lifo) { - sort_in_topological_order_fn(list, lifo, topo_sort_default_setter, - topo_sort_default_getter); -} + struct commit_list *next, *orig = *list; + struct commit_list *work, **insert; + struct commit_list **pptr; -void sort_in_topological_order_fn(struct commit_list ** list, int lifo, - topo_sort_set_fn_t setter, - topo_sort_get_fn_t getter) -{ - struct commit_list * next = *list; - struct commit_list * work = NULL, **insert; - struct commit_list ** pptr = list; - struct sort_node * nodes; - struct sort_node * next_nodes; - int count = 0; - - /* determine the size of the list */ - while (next) { - next = next->next; - count++; - } - - if (!count) + if (!orig) return; - /* allocate an array to help sort the list */ - nodes = xcalloc(count, sizeof(*nodes)); - /* link the list to the array */ - next_nodes = nodes; - next=*list; - while (next) { - next_nodes->list_item = next; - setter(next->item, next_nodes); - next_nodes++; - next = next->next; + *list = NULL; + + /* Mark them and clear the indegree */ + for (next = orig; next; next = next->next) { + struct commit *commit = next->item; + commit->object.flags |= TOPOSORT; + commit->indegree = 0; } + /* update the indegree */ - next=*list; - while (next) { + for (next = orig; next; next = next->next) { struct commit_list * parents = next->item->parents; while (parents) { - struct commit * parent=parents->item; - struct sort_node * pn = (struct sort_node *) getter(parent); + struct commit *parent = parents->item; - if (pn) - pn->indegree++; - parents=parents->next; + if (parent->object.flags & TOPOSORT) + parent->indegree++; + parents = parents->next; } - next=next->next; } + /* * find the tips * @@ -1219,55 +1172,56 @@ void sort_in_topological_order_fn(struct commit_list ** list, int lifo, * * the tips serve as a starting set for the work queue. */ - next=*list; + work = NULL; insert = &work; - while (next) { - struct sort_node * node = (struct sort_node *) getter(next->item); + for (next = orig; next; next = next->next) { + struct commit *commit = next->item; - if (node->indegree == 0) { - insert = &commit_list_insert(next->item, insert)->next; - } - next=next->next; + if (!commit->indegree) + insert = &commit_list_insert(commit, insert)->next; } /* process the list in topological order */ if (!lifo) sort_by_date(&work); + + pptr = list; + *list = NULL; while (work) { - struct commit * work_item = pop_commit(&work); - struct sort_node * work_node = (struct sort_node *) getter(work_item); - struct commit_list * parents = work_item->parents; + struct commit *commit; + struct commit_list *parents, *work_item; - while (parents) { - struct commit * parent=parents->item; - struct sort_node * pn = (struct sort_node *) getter(parent); + work_item = work; + work = work_item->next; + work_item->next = NULL; - if (pn) { - /* - * parents are only enqueued for emission - * when all their children have been emitted thereby - * guaranteeing topological order. - */ - pn->indegree--; - if (!pn->indegree) { - if (!lifo) - insert_by_date(parent, &work); - else - commit_list_insert(parent, &work); - } + commit = work_item->item; + for (parents = commit->parents; parents ; parents = parents->next) { + struct commit *parent=parents->item; + + if (!(parent->object.flags & TOPOSORT)) + continue; + + /* + * parents are only enqueued for emission + * when all their children have been emitted thereby + * guaranteeing topological order. + */ + if (!--parent->indegree) { + if (!lifo) + insert_by_date(parent, &work); + else + commit_list_insert(parent, &work); } - parents=parents->next; } /* * work_item is a commit all of whose children * have already been emitted. we can emit it now. */ - *pptr = work_node->list_item; - pptr = &(*pptr)->next; - *pptr = NULL; - setter(work_item, NULL); + commit->object.flags &= ~TOPOSORT; + *pptr = work_item; + pptr = &work_item->next; } - free(nodes); } /* merge-base stuff */ diff --git a/commit.h b/commit.h index 13b537293d..4ed0c1cf7f 100644 --- a/commit.h +++ b/commit.h @@ -14,6 +14,7 @@ struct commit_list { struct commit { struct object object; void *util; + unsigned int indegree; unsigned long date; struct commit_list *parents; struct tree *tree; @@ -84,31 +85,12 @@ void clear_commit_marks(struct commit *commit, unsigned int mark); /* * Performs an in-place topological sort of list supplied. * - * Pre-conditions for sort_in_topological_order: - * all commits in input list and all parents of those - * commits must have object.util == NULL - * - * Pre-conditions for sort_in_topological_order_fn: - * all commits in input list and all parents of those - * commits must have getter(commit) == NULL - * - * Post-conditions: * invariant of resulting list is: * a reachable from b => ord(b) < ord(a) * in addition, when lifo == 0, commits on parallel tracks are * sorted in the dates order. */ - -typedef void (*topo_sort_set_fn_t)(struct commit*, void *data); -typedef void* (*topo_sort_get_fn_t)(struct commit*); - -void topo_sort_default_setter(struct commit *c, void *data); -void *topo_sort_default_getter(struct commit *c); - void sort_in_topological_order(struct commit_list ** list, int lifo); -void sort_in_topological_order_fn(struct commit_list ** list, int lifo, - topo_sort_set_fn_t setter, - topo_sort_get_fn_t getter); struct commit_graft { unsigned char sha1[20]; diff --git a/revision.c b/revision.c index e76da0d448..e85b4af392 100644 --- a/revision.c +++ b/revision.c @@ -677,9 +677,6 @@ void init_revisions(struct rev_info *revs, const char *prefix) revs->prune_fn = NULL; revs->prune_data = NULL; - revs->topo_setter = topo_sort_default_setter; - revs->topo_getter = topo_sort_default_getter; - revs->commit_format = CMIT_FMT_DEFAULT; diff_setup(&revs->diffopt); @@ -1303,9 +1300,7 @@ int prepare_revision_walk(struct rev_info *revs) if (limit_list(revs) < 0) return -1; if (revs->topo_order) - sort_in_topological_order_fn(&revs->commits, revs->lifo, - revs->topo_setter, - revs->topo_getter); + sort_in_topological_order(&revs->commits, revs->lifo); return 0; } diff --git a/revision.h b/revision.h index 98a0a8f3fa..1f645764a5 100644 --- a/revision.h +++ b/revision.h @@ -10,6 +10,7 @@ #define CHILD_SHOWN (1u<<6) #define ADDED (1u<<7) /* Parents already parsed and added? */ #define SYMMETRIC_LEFT (1u<<8) +#define TOPOSORT (1u<<9) /* In the active toposort list.. */ struct rev_info; struct log_info; @@ -96,9 +97,6 @@ struct rev_info { struct diff_options diffopt; struct diff_options pruning; - topo_sort_set_fn_t topo_setter; - topo_sort_get_fn_t topo_getter; - struct reflog_walk_info *reflog_info; }; From cdcefbc971d8fcdd293750af7571d4c715f86964 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 3 Nov 2007 11:11:10 -0700 Subject: [PATCH 0429/1490] Add "--early-output" log flag for interactive GUI use This adds support for "--early-output[=n]" as a flag to the "git log" family of commands. This allows GUI programs to state that they want to get some output early, in order to be able to show at least something quickly, even if the full output may take longer to generate. If no count is specified, a default count of a hundred commits will be used, although the actual numbr of commits output may be smaller depending on how many commits were actually found in the first tenth of a second (or if *everything* was found before that, in which case no early output will be provided, and only the final list is made available). When the full list is generated, there will be a "Final output:" string prepended to it, regardless of whether any early commits were shown or not, so that the consumer can always know the difference between early output and the final list. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- builtin-log.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++ revision.c | 22 +++++++++++++++++ revision.h | 4 +++ 3 files changed, 93 insertions(+) diff --git a/builtin-log.c b/builtin-log.c index 8b2bf632c5..4e9d0cb69c 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -77,11 +77,78 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix, } } +static void log_show_early(struct rev_info *revs, struct commit_list *list) +{ + int i = revs->early_output; + + sort_in_topological_order(&list, revs->lifo); + while (list && i) { + struct commit *commit = list->item; + log_tree_commit(revs, commit); + list = list->next; + i--; + } +} + +static void early_output(int signal) +{ + show_early_output = log_show_early; +} + +static void setup_early_output(struct rev_info *rev) +{ + struct sigaction sa; + struct itimerval v; + + /* + * Set up the signal handler, minimally intrusively: + * we only set a single volatile integer word (not + * using sigatomic_t - trying to avoid unnecessary + * system dependencies and headers), and using + * SA_RESTART. + */ + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = early_output; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESTART; + sigaction(SIGALRM, &sa, NULL); + + /* + * If we can get the whole output in less than a + * tenth of a second, don't even bother doing the + * early-output thing.. + * + * This is a one-time-only trigger. + */ + memset(&v, 0, sizeof(v)); + v.it_value.tv_sec = 0; + v.it_value.tv_usec = 100000; + setitimer(ITIMER_REAL, &v, NULL); +} + +static void finish_early_output(struct rev_info *rev) +{ + signal(SIGALRM, SIG_IGN); + if (rev->shown_one) { + rev->shown_one = 0; + if (rev->commit_format != CMIT_FMT_ONELINE) + putchar(rev->diffopt.line_termination); + } + printf("Final output:\n"); +} + static int cmd_log_walk(struct rev_info *rev) { struct commit *commit; + if (rev->early_output) + setup_early_output(rev); + prepare_revision_walk(rev); + + if (rev->early_output) + finish_early_output(rev); + while ((commit = get_revision(rev)) != NULL) { log_tree_commit(rev, commit); if (!rev->reflog_info) { diff --git a/revision.c b/revision.c index e85b4af392..26610bb42d 100644 --- a/revision.c +++ b/revision.c @@ -10,6 +10,8 @@ #include "reflog-walk.h" #include "patch-ids.h" +volatile show_early_output_fn_t show_early_output; + static char *path_name(struct name_path *path, const char *name) { struct name_path *p; @@ -533,6 +535,7 @@ static int limit_list(struct rev_info *revs) struct commit_list *entry = list; struct commit *commit = list->item; struct object *obj = &commit->object; + show_early_output_fn_t show; list = list->next; free(entry); @@ -550,6 +553,13 @@ static int limit_list(struct rev_info *revs) if (revs->min_age != -1 && (commit->date > revs->min_age)) continue; p = &commit_list_insert(commit, p)->next; + + show = show_early_output; + if (!show) + continue; + + show(revs, newlist); + show_early_output = NULL; } if (revs->cherry_pick) cherry_pick_list(newlist, revs); @@ -991,6 +1001,18 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch revs->topo_order = 1; continue; } + if (!prefixcmp(arg, "--early-output")) { + int count = 100; + switch (arg[14]) { + case '=': + count = atoi(arg+15); + /* Fallthrough */ + case 0: + revs->topo_order = 1; + revs->early_output = count; + continue; + } + } if (!strcmp(arg, "--parents")) { revs->parents = 1; continue; diff --git a/revision.h b/revision.h index 1f645764a5..d8a5a5021f 100644 --- a/revision.h +++ b/revision.h @@ -30,6 +30,8 @@ struct rev_info { void *prune_data; prune_fn_t *prune_fn; + unsigned int early_output; + /* Traversal flags */ unsigned int dense:1, no_merges:1, @@ -105,6 +107,8 @@ struct rev_info { #define REV_TREE_DIFFERENT 2 /* revision.c */ +typedef void (*show_early_output_fn_t)(struct rev_info *, struct commit_list *); +volatile show_early_output_fn_t show_early_output; extern void init_revisions(struct rev_info *revs, const char *prefix); extern int setup_revisions(int argc, const char **argv, struct rev_info *revs, const char *def); From ebe8fa738dcf6911fe520adce0cfa0cb26dee5e2 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sun, 4 Nov 2007 00:22:42 -0400 Subject: [PATCH 0430/1490] fix display overlap between remote and local progress It is possible for the remote summary line to be displayed over the local progress display line, and therefore that local progress gets bumped to the next line. However, if the progress line is long enough, it might not be entirely overwritten by the remote summary line. This creates a messed up display such as: remote: Total 310 (delta 160), reused 178 (delta 112)iB/s Receiving objects: 100% (310/310), 379.98 KiB | 136 KiB/s, done. So we have to clear the screen line before displaying the remote message to make sure the local progress is not visible anymore on the first line. Yet some Git versions on the remote side might be sending updates to the same line and terminate it with \r, and a separate packet with a single \n might be sent later when the progress display is done. This means the screen line must *not* be cleared in that case. Since the sideband code already has to figure out line breaks in the received packet to properly prepend the "remote:" prefix, we can easily determine if the remote line about to be displayed is empty. Only when it is not then a proper suffix is inserted before the \r or \n to clear the end of the screen line. Also some magic constants related to the prefix length have been replaced with a variable, making it similar to the suffix length handling. Since gcc is smart enough to detect that the variable is constant there is no impact on the generated code. Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- sideband.c | 51 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 14 deletions(-) diff --git a/sideband.c b/sideband.c index ab8a1e990d..58edea68ee 100644 --- a/sideband.c +++ b/sideband.c @@ -11,13 +11,19 @@ * stream, aka "verbose"). A message over band #3 is a signal that * the remote died unexpectedly. A flush() concludes the stream. */ + +#define PREFIX "remote:" +#define SUFFIX "\e[K" /* change to " " if ANSI sequences don't work */ + int recv_sideband(const char *me, int in_stream, int out, int err) { - char buf[7 + LARGE_PACKET_MAX + 1]; - strcpy(buf, "remote:"); + unsigned pf = strlen(PREFIX); + unsigned sf = strlen(SUFFIX); + char buf[pf + LARGE_PACKET_MAX + sf + 1]; + memcpy(buf, PREFIX, pf); while (1) { int band, len; - len = packet_read_line(in_stream, buf+7, LARGE_PACKET_MAX); + len = packet_read_line(in_stream, buf + pf, LARGE_PACKET_MAX); if (len == 0) break; if (len < 1) { @@ -25,35 +31,52 @@ int recv_sideband(const char *me, int in_stream, int out, int err) safe_write(err, buf, len); return SIDEBAND_PROTOCOL_ERROR; } - band = buf[7] & 0xff; + band = buf[pf] & 0xff; len--; switch (band) { case 3: - buf[7] = ' '; - buf[8+len] = '\n'; - safe_write(err, buf, 8+len+1); + buf[pf] = ' '; + buf[pf+1+len] = '\n'; + safe_write(err, buf, pf+1+len+1); return SIDEBAND_REMOTE_ERROR; case 2: - buf[7] = ' '; - len += 8; + buf[pf] = ' '; + len += pf+1; while (1) { - int brk = 8; + int brk = pf+1; + + /* Break the buffer into separate lines. */ while (brk < len) { brk++; if (buf[brk-1] == '\n' || buf[brk-1] == '\r') break; } - safe_write(err, buf, brk); + + /* + * Let's insert a suffix to clear the end + * of the screen line, but only if current + * line data actually contains something. + */ + if (brk > pf+1 + 1) { + char save[sf]; + memcpy(save, buf + brk, sf); + buf[brk + sf - 1] = buf[brk - 1]; + memcpy(buf + brk - 1, SUFFIX, sf); + safe_write(err, buf, brk + sf); + memcpy(buf + brk, save, sf); + } else + safe_write(err, buf, brk); + if (brk < len) { - memmove(buf + 8, buf + brk, len - brk); - len = len - brk + 8; + memmove(buf + pf+1, buf + brk, len - brk); + len = len - brk + pf+1; } else break; } continue; case 1: - safe_write(out, buf+8, len); + safe_write(out, buf + pf+1, len); continue; default: len = sprintf(buf, From 49604a4d62d9055dbfc06472e7ef20d8a6114123 Mon Sep 17 00:00:00 2001 From: Brian Gernhardt Date: Sat, 3 Nov 2007 23:38:24 -0400 Subject: [PATCH 0431/1490] format-patch: Add configuration and off switch for --numbered format.numbered is a tri-state variable. Boolean values enable or disable numbering by default and "auto" enables number when outputting more than one patch. --no-numbered (short: -N) will disable numbering. Signed-off-by: Brian Gernhardt Signed-off-by: Junio C Hamano --- Documentation/config.txt | 6 ++++++ Documentation/git-format-patch.txt | 12 ++++++++---- builtin-log.c | 19 ++++++++++++++++++- 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/Documentation/config.txt b/Documentation/config.txt index 0df004ea26..268839da73 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -432,6 +432,12 @@ fetch.unpackLimit:: pack from a push can make the push operation complete faster, especially on slow filesystems. +format.numbered:: + A boolean which can enable sequence numbers in patch subjects. + Seting this option to "auto" will enable it only if there is + more than one patch. See --numbered option in + gitlink:git-format-patch[1]. + format.headers:: Additional email headers to include in a patch to be submitted by mail. See gitlink:git-format-patch[1]. diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt index f0617efa0a..92c0ab63b2 100644 --- a/Documentation/git-format-patch.txt +++ b/Documentation/git-format-patch.txt @@ -9,7 +9,7 @@ git-format-patch - Prepare patches for e-mail submission SYNOPSIS -------- [verse] -'git-format-patch' [-n | -k] [-o | --stdout] [--thread] +'git-format-patch' [-n | -N | -k] [-o | --stdout] [--thread] [--attach[=] | --inline[=]] [-s | --signoff] [] [--start-number ] [--numbered-files] @@ -77,6 +77,9 @@ include::diff-options.txt[] -n|--numbered:: Name output in '[PATCH n/m]' format. +-N|--no-numbered:: + Name output in '[PATCH]' format. + --start-number :: Start numbering the patches at instead of 1. @@ -142,15 +145,16 @@ not add any suffix. CONFIGURATION ------------- -You can specify extra mail header lines to be added to each -message in the repository configuration. You can also specify -new defaults for the subject prefix and file suffix. +You can specify extra mail header lines to be added to each message +in the repository configuration, new defaults for the subject prefix +and file suffix, and number patches when outputting more than one. ------------ [format] headers = "Organization: git-foo\n" subjectprefix = CHANGE suffix = .txt + numbered = auto ------------ diff --git a/builtin-log.c b/builtin-log.c index 8b2bf632c5..c5230106a0 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -273,6 +273,8 @@ static int istitlechar(char c) static char *extra_headers = NULL; static int extra_headers_size = 0; static const char *fmt_patch_suffix = ".patch"; +static int numbered = 0; +static int auto_number = 0; static int git_format_config(const char *var, const char *value) { @@ -297,6 +299,15 @@ static int git_format_config(const char *var, const char *value) if (!strcmp(var, "diff.color") || !strcmp(var, "color.diff")) { return 0; } + if (!strcmp(var, "format.numbered")) { + if (!strcasecmp(value, "auto")) { + auto_number = 1; + return 0; + } + + numbered = git_config_bool(var, value); + return 0; + } return git_log_config(var, value); } @@ -466,7 +477,6 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) struct rev_info rev; int nr = 0, total, i, j; int use_stdout = 0; - int numbered = 0; int start_number = -1; int keep_subject = 0; int numbered_files = 0; /* _just_ numbers */ @@ -503,6 +513,11 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) else if (!strcmp(argv[i], "-n") || !strcmp(argv[i], "--numbered")) numbered = 1; + else if (!strcmp(argv[i], "-N") || + !strcmp(argv[i], "--no-numbered")) { + numbered = 0; + auto_number = 0; + } else if (!prefixcmp(argv[i], "--start-number=")) start_number = strtol(argv[i] + 15, NULL, 10); else if (!strcmp(argv[i], "--numbered-files")) @@ -642,6 +657,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) list[nr - 1] = commit; } total = nr; + if (!keep_subject && auto_number && total > 1) + numbered = 1; if (numbered) rev.total = total + start_number - 1; rev.add_signoff = add_signoff; From e90ecb68178b41357f40b058aa760c2338974c13 Mon Sep 17 00:00:00 2001 From: Brian Gernhardt Date: Sun, 4 Nov 2007 01:50:23 -0400 Subject: [PATCH 0432/1490] format-patch: Test --[no-]numbered and format.numbered Just because there wasn't a test for --numbered isn't a good reason not to test format.numbered. So now we test both. Signed-off-by: Brian Gernhardt Signed-off-by: Junio C Hamano --- t/t4021-format-patch-numbered.sh | 106 +++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100755 t/t4021-format-patch-numbered.sh diff --git a/t/t4021-format-patch-numbered.sh b/t/t4021-format-patch-numbered.sh new file mode 100755 index 0000000000..43d64bbd82 --- /dev/null +++ b/t/t4021-format-patch-numbered.sh @@ -0,0 +1,106 @@ +#!/bin/sh +# +# Copyright (c) 2006 Brian C Gernhardt +# + +test_description='Format-patch numbering options' + +. ./test-lib.sh + +test_expect_success setup ' + + echo A > file && + git add file && + git commit -m First && + + echo B >> file && + git commit -a -m Second && + + echo C >> file && + git commit -a -m Third + +' + +# Each of these gets used multiple times. + +test_num_no_numbered() { + cnt=$(grep "^Subject: \[PATCH\]" $1 | wc -l) && + test $cnt = $2 +} + +test_single_no_numbered() { + test_num_no_numbered $1 1 +} + +test_no_numbered() { + test_num_no_numbered $1 2 +} + +test_single_numbered() { + grep "^Subject: \[PATCH 1/1\]" $1 +} + +test_numbered() { + grep "^Subject: \[PATCH 1/2\]" $1 && + grep "^Subject: \[PATCH 2/2\]" $1 +} + +test_expect_success 'Default: no numbered' ' + + git format-patch --stdout HEAD~2 >patch0 && + test_no_numbered patch0 + +' + +test_expect_success 'Use --numbered' ' + + git format-patch --numbered --stdout HEAD~2 >patch1 && + test_numbered patch1 + +' + +test_expect_success 'format.numbered = true' ' + + git config format.numbered true && + git format-patch --stdout HEAD~2 >patch2 && + test_numbered patch2 + +' + +test_expect_success 'format.numbered && single patch' ' + + git format-patch --stdout HEAD^ > patch3 && + test_single_numbered patch3 + +' + +test_expect_success 'format.numbered && --no-numbered' ' + + git format-patch --no-numbered --stdout HEAD~2 >patch4 && + test_no_numbered patch4 + +' + +test_expect_success 'format.numbered = auto' ' + + git config format.numbered auto + git format-patch --stdout HEAD~2 > patch5 && + test_numbered patch5 + +' + +test_expect_success 'format.numbered = auto && single patch' ' + + git format-patch --stdout HEAD^ > patch6 && + test_single_no_numbered patch6 + +' + +test_expect_success 'format.numbered = auto && --no-numbered' ' + + git format-patch --no-numbered --stdout HEAD~2 > patch7 && + test_no_numbered patch7 + +' + +test_done From 562ca192f94496611583688beb3725603ce51f89 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 1 Nov 2007 17:32:04 -0700 Subject: [PATCH 0433/1490] clean: require -f to do damage by default This makes the clean.requireForce configuration default to true. Too many people are burned by typing "git clean" by mistake when they meant to say "make clean". Signed-off-by: Junio C Hamano --- Documentation/config.txt | 4 ++-- git-clean.sh | 6 +++++- t/t7201-co.sh | 12 ++++++------ t/t7300-clean.sh | 9 +++++++++ 4 files changed, 22 insertions(+), 9 deletions(-) diff --git a/Documentation/config.txt b/Documentation/config.txt index 7ee97df8a7..aeb7961ade 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -338,8 +338,8 @@ branch..merge:: `.` (a period) for branch..remote. clean.requireForce:: - A boolean to make git-clean do nothing unless given -f or -n. Defaults - to false. + A boolean to make git-clean do nothing unless given -f + or -n. Defaults to true. color.branch:: A boolean to enable/disable color in the output of diff --git a/git-clean.sh b/git-clean.sh index 4491738186..f4965b8391 100755 --- a/git-clean.sh +++ b/git-clean.sh @@ -20,12 +20,16 @@ require_work_tree ignored= ignoredonly= cleandir= -disabled="`git config --bool clean.requireForce`" rmf="rm -f --" rmrf="rm -rf --" rm_refuse="echo Not removing" echo1="echo" +# requireForce used to default to false but now it defaults to true. +# IOW, lack of explicit "clean.requireForce = false" is taken as +# "clean.requireForce = true". +disabled=$(git config --bool clean.requireForce || echo true) + while test $# != 0 do case "$1" in diff --git a/t/t7201-co.sh b/t/t7201-co.sh index ed2e9ee3c6..55558aba8b 100755 --- a/t/t7201-co.sh +++ b/t/t7201-co.sh @@ -77,7 +77,7 @@ test_expect_success "checkout with dirty tree without -m" ' test_expect_success "checkout -m with dirty tree" ' git checkout -f master && - git clean && + git clean -f && fill 0 1 2 3 4 5 6 7 8 >one && git checkout -m side && @@ -99,7 +99,7 @@ test_expect_success "checkout -m with dirty tree" ' test_expect_success "checkout -m with dirty tree, renamed" ' - git checkout -f master && git clean && + git checkout -f master && git clean -f && fill 1 2 3 4 5 7 8 >one && if git checkout renamer @@ -121,7 +121,7 @@ test_expect_success "checkout -m with dirty tree, renamed" ' test_expect_success 'checkout -m with merge conflict' ' - git checkout -f master && git clean && + git checkout -f master && git clean -f && fill 1 T 3 4 5 6 S 8 >one && if git checkout renamer @@ -144,7 +144,7 @@ test_expect_success 'checkout -m with merge conflict' ' test_expect_success 'checkout to detach HEAD' ' - git checkout -f renamer && git clean && + git checkout -f renamer && git clean -f && git checkout renamer^ && H=$(git rev-parse --verify HEAD) && M=$(git show-ref -s --verify refs/heads/master) && @@ -160,7 +160,7 @@ test_expect_success 'checkout to detach HEAD' ' test_expect_success 'checkout to detach HEAD with branchname^' ' - git checkout -f master && git clean && + git checkout -f master && git clean -f && git checkout renamer^ && H=$(git rev-parse --verify HEAD) && M=$(git show-ref -s --verify refs/heads/master) && @@ -176,7 +176,7 @@ test_expect_success 'checkout to detach HEAD with branchname^' ' test_expect_success 'checkout to detach HEAD with HEAD^0' ' - git checkout -f master && git clean && + git checkout -f master && git clean -f && git checkout HEAD^0 && H=$(git rev-parse --verify HEAD) && M=$(git show-ref -s --verify refs/heads/master) && diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh index eb0847afe9..8697213e6b 100755 --- a/t/t7300-clean.sh +++ b/t/t7300-clean.sh @@ -7,6 +7,8 @@ test_description='git-clean basic tests' . ./test-lib.sh +git config clean.requireForce no + test_expect_success 'setup' ' mkdir -p src && @@ -139,6 +141,13 @@ test_expect_success 'git-clean -d -X' ' ' +test_expect_success 'clean.requireForce defaults to true' ' + + git config --unset clean.requireForce && + ! git-clean + +' + test_expect_success 'clean.requireForce' ' git config clean.requireForce true && From c2015b3ae0d52ccae33ee00c2b25b8402c66bdf0 Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Sun, 4 Nov 2007 21:26:22 +0100 Subject: [PATCH 0434/1490] Fix an infinite loop in sq_quote_buf(). sq_quote_buf() treats single-quotes and exclamation marks specially, but it incorrectly parsed the input for single-quotes and backslashes. Signed-off-by: Johannes Sixt Signed-off-by: Junio C Hamano --- quote.c | 2 +- t/t5510-fetch.sh | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/quote.c b/quote.c index 482be05b7a..919d0920ab 100644 --- a/quote.c +++ b/quote.c @@ -26,7 +26,7 @@ void sq_quote_buf(struct strbuf *dst, const char *src) strbuf_addch(dst, '\''); while (*src) { - size_t len = strcspn(src, "'\\"); + size_t len = strcspn(src, "'!"); strbuf_add(dst, src, len); src += len; while (need_bs_quote(*src)) { diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh index d217657146..aad863db7a 100755 --- a/t/t5510-fetch.sh +++ b/t/t5510-fetch.sh @@ -208,4 +208,11 @@ test_expect_success 'fetch with a non-applying branch..merge' ' git fetch blub ' +# the strange name is: a\!'b +test_expect_success 'quoting of a strangely named repo' ' + ! git fetch "a\\!'\''b" > result 2>&1 && + cat result && + grep "fatal: '\''a\\\\!'\''b'\''" result +' + test_done From 93fc05eb9ef505a05d9ce9415177697449afc8ad Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sun, 4 Nov 2007 19:15:06 +0000 Subject: [PATCH 0435/1490] Split off the pretty print stuff into its own file The file commit.c got quite large, but it does not have to be: the code concerning pretty printing is pretty well contained. In fact, this commit just splits it off into pretty.c, leaving commit.c with just 672 lines. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- Makefile | 2 +- commit.c | 718 ------------------------------------------------------ pretty.c | 723 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 724 insertions(+), 719 deletions(-) create mode 100644 pretty.c diff --git a/Makefile b/Makefile index 042f79ef8f..cf8ec49d12 100644 --- a/Makefile +++ b/Makefile @@ -299,7 +299,7 @@ DIFF_OBJS = \ LIB_OBJS = \ blob.o commit.o connect.o csum-file.o cache-tree.o base85.o \ date.o diff-delta.o entry.o exec_cmd.o ident.o \ - interpolate.o hash.o \ + pretty.o interpolate.o hash.o \ lockfile.o \ patch-ids.o \ object.o pack-check.o pack-write.o patch-delta.o path.o pkt-line.o \ diff --git a/commit.c b/commit.c index 8262f6ac58..b509265872 100644 --- a/commit.c +++ b/commit.c @@ -3,7 +3,6 @@ #include "commit.h" #include "pkt-line.h" #include "utf8.h" -#include "interpolate.h" #include "diff.h" #include "revision.h" @@ -27,46 +26,6 @@ struct sort_node const char *commit_type = "commit"; -static struct cmt_fmt_map { - const char *n; - size_t cmp_len; - enum cmit_fmt v; -} cmt_fmts[] = { - { "raw", 1, CMIT_FMT_RAW }, - { "medium", 1, CMIT_FMT_MEDIUM }, - { "short", 1, CMIT_FMT_SHORT }, - { "email", 1, CMIT_FMT_EMAIL }, - { "full", 5, CMIT_FMT_FULL }, - { "fuller", 5, CMIT_FMT_FULLER }, - { "oneline", 1, CMIT_FMT_ONELINE }, - { "format:", 7, CMIT_FMT_USERFORMAT}, -}; - -static char *user_format; - -enum cmit_fmt get_commit_format(const char *arg) -{ - int i; - - if (!arg || !*arg) - return CMIT_FMT_DEFAULT; - if (*arg == '=') - arg++; - if (!prefixcmp(arg, "format:")) { - if (user_format) - free(user_format); - user_format = xstrdup(arg + 7); - return CMIT_FMT_USERFORMAT; - } - for (i = 0; i < ARRAY_SIZE(cmt_fmts); i++) { - if (!strncmp(arg, cmt_fmts[i].n, cmt_fmts[i].cmp_len) && - !strncmp(arg, cmt_fmts[i].n, strlen(arg))) - return cmt_fmts[i].v; - } - - die("invalid --pretty format: %s", arg); -} - static struct commit *check_commit(struct object *obj, const unsigned char *sha1, int quiet) @@ -460,683 +419,6 @@ void clear_commit_marks(struct commit *commit, unsigned int mark) } } -/* - * Generic support for pretty-printing the header - */ -static int get_one_line(const char *msg) -{ - int ret = 0; - - for (;;) { - char c = *msg++; - if (!c) - break; - ret++; - if (c == '\n') - break; - } - return ret; -} - -/* High bit set, or ISO-2022-INT */ -int non_ascii(int ch) -{ - ch = (ch & 0xff); - return ((ch & 0x80) || (ch == 0x1b)); -} - -static int is_rfc2047_special(char ch) -{ - return (non_ascii(ch) || (ch == '=') || (ch == '?') || (ch == '_')); -} - -static void add_rfc2047(struct strbuf *sb, const char *line, int len, - const char *encoding) -{ - int i, last; - - for (i = 0; i < len; i++) { - int ch = line[i]; - if (non_ascii(ch)) - goto needquote; - if ((i + 1 < len) && (ch == '=' && line[i+1] == '?')) - goto needquote; - } - strbuf_add(sb, line, len); - return; - -needquote: - strbuf_grow(sb, len * 3 + strlen(encoding) + 100); - strbuf_addf(sb, "=?%s?q?", encoding); - for (i = last = 0; i < len; i++) { - unsigned ch = line[i] & 0xFF; - /* - * We encode ' ' using '=20' even though rfc2047 - * allows using '_' for readability. Unfortunately, - * many programs do not understand this and just - * leave the underscore in place. - */ - if (is_rfc2047_special(ch) || ch == ' ') { - strbuf_add(sb, line + last, i - last); - strbuf_addf(sb, "=%02X", ch); - last = i + 1; - } - } - strbuf_add(sb, line + last, len - last); - strbuf_addstr(sb, "?="); -} - -static void add_user_info(const char *what, enum cmit_fmt fmt, struct strbuf *sb, - const char *line, enum date_mode dmode, - const char *encoding) -{ - char *date; - int namelen; - unsigned long time; - int tz; - const char *filler = " "; - - if (fmt == CMIT_FMT_ONELINE) - return; - date = strchr(line, '>'); - if (!date) - return; - namelen = ++date - line; - time = strtoul(date, &date, 10); - tz = strtol(date, NULL, 10); - - if (fmt == CMIT_FMT_EMAIL) { - char *name_tail = strchr(line, '<'); - int display_name_length; - if (!name_tail) - return; - while (line < name_tail && isspace(name_tail[-1])) - name_tail--; - display_name_length = name_tail - line; - filler = ""; - strbuf_addstr(sb, "From: "); - add_rfc2047(sb, line, display_name_length, encoding); - strbuf_add(sb, name_tail, namelen - display_name_length); - strbuf_addch(sb, '\n'); - } else { - strbuf_addf(sb, "%s: %.*s%.*s\n", what, - (fmt == CMIT_FMT_FULLER) ? 4 : 0, - filler, namelen, line); - } - switch (fmt) { - case CMIT_FMT_MEDIUM: - strbuf_addf(sb, "Date: %s\n", show_date(time, tz, dmode)); - break; - case CMIT_FMT_EMAIL: - strbuf_addf(sb, "Date: %s\n", show_date(time, tz, DATE_RFC2822)); - break; - case CMIT_FMT_FULLER: - strbuf_addf(sb, "%sDate: %s\n", what, show_date(time, tz, dmode)); - break; - default: - /* notin' */ - break; - } -} - -static int is_empty_line(const char *line, int *len_p) -{ - int len = *len_p; - while (len && isspace(line[len-1])) - len--; - *len_p = len; - return !len; -} - -static void add_merge_info(enum cmit_fmt fmt, struct strbuf *sb, - const struct commit *commit, int abbrev) -{ - struct commit_list *parent = commit->parents; - - if ((fmt == CMIT_FMT_ONELINE) || (fmt == CMIT_FMT_EMAIL) || - !parent || !parent->next) - return; - - strbuf_addstr(sb, "Merge:"); - - while (parent) { - struct commit *p = parent->item; - const char *hex = NULL; - const char *dots; - if (abbrev) - hex = find_unique_abbrev(p->object.sha1, abbrev); - if (!hex) - hex = sha1_to_hex(p->object.sha1); - dots = (abbrev && strlen(hex) != 40) ? "..." : ""; - parent = parent->next; - - strbuf_addf(sb, " %s%s", hex, dots); - } - strbuf_addch(sb, '\n'); -} - -static char *get_header(const struct commit *commit, const char *key) -{ - int key_len = strlen(key); - const char *line = commit->buffer; - - for (;;) { - const char *eol = strchr(line, '\n'), *next; - - if (line == eol) - return NULL; - if (!eol) { - eol = line + strlen(line); - next = NULL; - } else - next = eol + 1; - if (eol - line > key_len && - !strncmp(line, key, key_len) && - line[key_len] == ' ') { - return xmemdupz(line + key_len + 1, eol - line - key_len - 1); - } - line = next; - } -} - -static char *replace_encoding_header(char *buf, const char *encoding) -{ - struct strbuf tmp; - size_t start, len; - char *cp = buf; - - /* guess if there is an encoding header before a \n\n */ - while (strncmp(cp, "encoding ", strlen("encoding "))) { - cp = strchr(cp, '\n'); - if (!cp || *++cp == '\n') - return buf; - } - start = cp - buf; - cp = strchr(cp, '\n'); - if (!cp) - return buf; /* should not happen but be defensive */ - len = cp + 1 - (buf + start); - - strbuf_init(&tmp, 0); - strbuf_attach(&tmp, buf, strlen(buf), strlen(buf) + 1); - if (is_encoding_utf8(encoding)) { - /* we have re-coded to UTF-8; drop the header */ - strbuf_remove(&tmp, start, len); - } else { - /* just replaces XXXX in 'encoding XXXX\n' */ - strbuf_splice(&tmp, start + strlen("encoding "), - len - strlen("encoding \n"), - encoding, strlen(encoding)); - } - return strbuf_detach(&tmp, NULL); -} - -static char *logmsg_reencode(const struct commit *commit, - const char *output_encoding) -{ - static const char *utf8 = "utf-8"; - const char *use_encoding; - char *encoding; - char *out; - - if (!*output_encoding) - return NULL; - encoding = get_header(commit, "encoding"); - use_encoding = encoding ? encoding : utf8; - if (!strcmp(use_encoding, output_encoding)) - if (encoding) /* we'll strip encoding header later */ - out = xstrdup(commit->buffer); - else - return NULL; /* nothing to do */ - else - out = reencode_string(commit->buffer, - output_encoding, use_encoding); - if (out) - out = replace_encoding_header(out, output_encoding); - - free(encoding); - return out; -} - -static void fill_person(struct interp *table, const char *msg, int len) -{ - int start, end, tz = 0; - unsigned long date; - char *ep; - - /* parse name */ - for (end = 0; end < len && msg[end] != '<'; end++) - ; /* do nothing */ - start = end + 1; - while (end > 0 && isspace(msg[end - 1])) - end--; - table[0].value = xmemdupz(msg, end); - - if (start >= len) - return; - - /* parse email */ - for (end = start + 1; end < len && msg[end] != '>'; end++) - ; /* do nothing */ - - if (end >= len) - return; - - table[1].value = xmemdupz(msg + start, end - start); - - /* parse date */ - for (start = end + 1; start < len && isspace(msg[start]); start++) - ; /* do nothing */ - if (start >= len) - return; - date = strtoul(msg + start, &ep, 10); - if (msg + start == ep) - return; - - table[5].value = xmemdupz(msg + start, ep - (msg + start)); - - /* parse tz */ - for (start = ep - msg + 1; start < len && isspace(msg[start]); start++) - ; /* do nothing */ - if (start + 1 < len) { - tz = strtoul(msg + start + 1, NULL, 10); - if (msg[start] == '-') - tz = -tz; - } - - interp_set_entry(table, 2, show_date(date, tz, DATE_NORMAL)); - interp_set_entry(table, 3, show_date(date, tz, DATE_RFC2822)); - interp_set_entry(table, 4, show_date(date, tz, DATE_RELATIVE)); - interp_set_entry(table, 6, show_date(date, tz, DATE_ISO8601)); -} - -void format_commit_message(const struct commit *commit, - const void *format, struct strbuf *sb) -{ - struct interp table[] = { - { "%H" }, /* commit hash */ - { "%h" }, /* abbreviated commit hash */ - { "%T" }, /* tree hash */ - { "%t" }, /* abbreviated tree hash */ - { "%P" }, /* parent hashes */ - { "%p" }, /* abbreviated parent hashes */ - { "%an" }, /* author name */ - { "%ae" }, /* author email */ - { "%ad" }, /* author date */ - { "%aD" }, /* author date, RFC2822 style */ - { "%ar" }, /* author date, relative */ - { "%at" }, /* author date, UNIX timestamp */ - { "%ai" }, /* author date, ISO 8601 */ - { "%cn" }, /* committer name */ - { "%ce" }, /* committer email */ - { "%cd" }, /* committer date */ - { "%cD" }, /* committer date, RFC2822 style */ - { "%cr" }, /* committer date, relative */ - { "%ct" }, /* committer date, UNIX timestamp */ - { "%ci" }, /* committer date, ISO 8601 */ - { "%e" }, /* encoding */ - { "%s" }, /* subject */ - { "%b" }, /* body */ - { "%Cred" }, /* red */ - { "%Cgreen" }, /* green */ - { "%Cblue" }, /* blue */ - { "%Creset" }, /* reset color */ - { "%n" }, /* newline */ - { "%m" }, /* left/right/bottom */ - }; - enum interp_index { - IHASH = 0, IHASH_ABBREV, - ITREE, ITREE_ABBREV, - IPARENTS, IPARENTS_ABBREV, - IAUTHOR_NAME, IAUTHOR_EMAIL, - IAUTHOR_DATE, IAUTHOR_DATE_RFC2822, IAUTHOR_DATE_RELATIVE, - IAUTHOR_TIMESTAMP, IAUTHOR_ISO8601, - ICOMMITTER_NAME, ICOMMITTER_EMAIL, - ICOMMITTER_DATE, ICOMMITTER_DATE_RFC2822, - ICOMMITTER_DATE_RELATIVE, ICOMMITTER_TIMESTAMP, - ICOMMITTER_ISO8601, - IENCODING, - ISUBJECT, - IBODY, - IRED, IGREEN, IBLUE, IRESET_COLOR, - INEWLINE, - ILEFT_RIGHT, - }; - struct commit_list *p; - char parents[1024]; - unsigned long len; - int i; - enum { HEADER, SUBJECT, BODY } state; - const char *msg = commit->buffer; - - if (ILEFT_RIGHT + 1 != ARRAY_SIZE(table)) - die("invalid interp table!"); - - /* these are independent of the commit */ - interp_set_entry(table, IRED, "\033[31m"); - interp_set_entry(table, IGREEN, "\033[32m"); - interp_set_entry(table, IBLUE, "\033[34m"); - interp_set_entry(table, IRESET_COLOR, "\033[m"); - interp_set_entry(table, INEWLINE, "\n"); - - /* these depend on the commit */ - if (!commit->object.parsed) - parse_object(commit->object.sha1); - interp_set_entry(table, IHASH, sha1_to_hex(commit->object.sha1)); - interp_set_entry(table, IHASH_ABBREV, - find_unique_abbrev(commit->object.sha1, - DEFAULT_ABBREV)); - interp_set_entry(table, ITREE, sha1_to_hex(commit->tree->object.sha1)); - interp_set_entry(table, ITREE_ABBREV, - find_unique_abbrev(commit->tree->object.sha1, - DEFAULT_ABBREV)); - interp_set_entry(table, ILEFT_RIGHT, - (commit->object.flags & BOUNDARY) - ? "-" - : (commit->object.flags & SYMMETRIC_LEFT) - ? "<" - : ">"); - - parents[1] = 0; - for (i = 0, p = commit->parents; - p && i < sizeof(parents) - 1; - p = p->next) - i += snprintf(parents + i, sizeof(parents) - i - 1, " %s", - sha1_to_hex(p->item->object.sha1)); - interp_set_entry(table, IPARENTS, parents + 1); - - parents[1] = 0; - for (i = 0, p = commit->parents; - p && i < sizeof(parents) - 1; - p = p->next) - i += snprintf(parents + i, sizeof(parents) - i - 1, " %s", - find_unique_abbrev(p->item->object.sha1, - DEFAULT_ABBREV)); - interp_set_entry(table, IPARENTS_ABBREV, parents + 1); - - for (i = 0, state = HEADER; msg[i] && state < BODY; i++) { - int eol; - for (eol = i; msg[eol] && msg[eol] != '\n'; eol++) - ; /* do nothing */ - - if (state == SUBJECT) { - table[ISUBJECT].value = xmemdupz(msg + i, eol - i); - i = eol; - } - if (i == eol) { - state++; - /* strip empty lines */ - while (msg[eol + 1] == '\n') - eol++; - } else if (!prefixcmp(msg + i, "author ")) - fill_person(table + IAUTHOR_NAME, - msg + i + 7, eol - i - 7); - else if (!prefixcmp(msg + i, "committer ")) - fill_person(table + ICOMMITTER_NAME, - msg + i + 10, eol - i - 10); - else if (!prefixcmp(msg + i, "encoding ")) - table[IENCODING].value = - xmemdupz(msg + i + 9, eol - i - 9); - i = eol; - } - if (msg[i]) - table[IBODY].value = xstrdup(msg + i); - - len = interpolate(sb->buf + sb->len, strbuf_avail(sb), - format, table, ARRAY_SIZE(table)); - if (len > strbuf_avail(sb)) { - strbuf_grow(sb, len); - interpolate(sb->buf + sb->len, strbuf_avail(sb) + 1, - format, table, ARRAY_SIZE(table)); - } - strbuf_setlen(sb, sb->len + len); - interp_clear_table(table, ARRAY_SIZE(table)); -} - -static void pp_header(enum cmit_fmt fmt, - int abbrev, - enum date_mode dmode, - const char *encoding, - const struct commit *commit, - const char **msg_p, - struct strbuf *sb) -{ - int parents_shown = 0; - - for (;;) { - const char *line = *msg_p; - int linelen = get_one_line(*msg_p); - - if (!linelen) - return; - *msg_p += linelen; - - if (linelen == 1) - /* End of header */ - return; - - if (fmt == CMIT_FMT_RAW) { - strbuf_add(sb, line, linelen); - continue; - } - - if (!memcmp(line, "parent ", 7)) { - if (linelen != 48) - die("bad parent line in commit"); - continue; - } - - if (!parents_shown) { - struct commit_list *parent; - int num; - for (parent = commit->parents, num = 0; - parent; - parent = parent->next, num++) - ; - /* with enough slop */ - strbuf_grow(sb, num * 50 + 20); - add_merge_info(fmt, sb, commit, abbrev); - parents_shown = 1; - } - - /* - * MEDIUM == DEFAULT shows only author with dates. - * FULL shows both authors but not dates. - * FULLER shows both authors and dates. - */ - if (!memcmp(line, "author ", 7)) { - strbuf_grow(sb, linelen + 80); - add_user_info("Author", fmt, sb, line + 7, dmode, encoding); - } - if (!memcmp(line, "committer ", 10) && - (fmt == CMIT_FMT_FULL || fmt == CMIT_FMT_FULLER)) { - strbuf_grow(sb, linelen + 80); - add_user_info("Commit", fmt, sb, line + 10, dmode, encoding); - } - } -} - -static void pp_title_line(enum cmit_fmt fmt, - const char **msg_p, - struct strbuf *sb, - const char *subject, - const char *after_subject, - const char *encoding, - int plain_non_ascii) -{ - struct strbuf title; - - strbuf_init(&title, 80); - - for (;;) { - const char *line = *msg_p; - int linelen = get_one_line(line); - - *msg_p += linelen; - if (!linelen || is_empty_line(line, &linelen)) - break; - - strbuf_grow(&title, linelen + 2); - if (title.len) { - if (fmt == CMIT_FMT_EMAIL) { - strbuf_addch(&title, '\n'); - } - strbuf_addch(&title, ' '); - } - strbuf_add(&title, line, linelen); - } - - strbuf_grow(sb, title.len + 1024); - if (subject) { - strbuf_addstr(sb, subject); - add_rfc2047(sb, title.buf, title.len, encoding); - } else { - strbuf_addbuf(sb, &title); - } - strbuf_addch(sb, '\n'); - - if (plain_non_ascii) { - const char *header_fmt = - "MIME-Version: 1.0\n" - "Content-Type: text/plain; charset=%s\n" - "Content-Transfer-Encoding: 8bit\n"; - strbuf_addf(sb, header_fmt, encoding); - } - if (after_subject) { - strbuf_addstr(sb, after_subject); - } - if (fmt == CMIT_FMT_EMAIL) { - strbuf_addch(sb, '\n'); - } - strbuf_release(&title); -} - -static void pp_remainder(enum cmit_fmt fmt, - const char **msg_p, - struct strbuf *sb, - int indent) -{ - int first = 1; - for (;;) { - const char *line = *msg_p; - int linelen = get_one_line(line); - *msg_p += linelen; - - if (!linelen) - break; - - if (is_empty_line(line, &linelen)) { - if (first) - continue; - if (fmt == CMIT_FMT_SHORT) - break; - } - first = 0; - - strbuf_grow(sb, linelen + indent + 20); - if (indent) { - memset(sb->buf + sb->len, ' ', indent); - strbuf_setlen(sb, sb->len + indent); - } - strbuf_add(sb, line, linelen); - strbuf_addch(sb, '\n'); - } -} - -void pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit, - struct strbuf *sb, int abbrev, - const char *subject, const char *after_subject, - enum date_mode dmode, int plain_non_ascii) -{ - unsigned long beginning_of_body; - int indent = 4; - const char *msg = commit->buffer; - char *reencoded; - const char *encoding; - - if (fmt == CMIT_FMT_USERFORMAT) { - format_commit_message(commit, user_format, sb); - return; - } - - encoding = (git_log_output_encoding - ? git_log_output_encoding - : git_commit_encoding); - if (!encoding) - encoding = "utf-8"; - reencoded = logmsg_reencode(commit, encoding); - if (reencoded) { - msg = reencoded; - } - - if (fmt == CMIT_FMT_ONELINE || fmt == CMIT_FMT_EMAIL) - indent = 0; - - /* After-subject is used to pass in Content-Type: multipart - * MIME header; in that case we do not have to do the - * plaintext content type even if the commit message has - * non 7-bit ASCII character. Otherwise, check if we need - * to say this is not a 7-bit ASCII. - */ - if (fmt == CMIT_FMT_EMAIL && !after_subject) { - int i, ch, in_body; - - for (in_body = i = 0; (ch = msg[i]); i++) { - if (!in_body) { - /* author could be non 7-bit ASCII but - * the log may be so; skip over the - * header part first. - */ - if (ch == '\n' && msg[i+1] == '\n') - in_body = 1; - } - else if (non_ascii(ch)) { - plain_non_ascii = 1; - break; - } - } - } - - pp_header(fmt, abbrev, dmode, encoding, commit, &msg, sb); - if (fmt != CMIT_FMT_ONELINE && !subject) { - strbuf_addch(sb, '\n'); - } - - /* Skip excess blank lines at the beginning of body, if any... */ - for (;;) { - int linelen = get_one_line(msg); - int ll = linelen; - if (!linelen) - break; - if (!is_empty_line(msg, &ll)) - break; - msg += linelen; - } - - /* These formats treat the title line specially. */ - if (fmt == CMIT_FMT_ONELINE || fmt == CMIT_FMT_EMAIL) - pp_title_line(fmt, &msg, sb, subject, - after_subject, encoding, plain_non_ascii); - - beginning_of_body = sb->len; - if (fmt != CMIT_FMT_ONELINE) - pp_remainder(fmt, &msg, sb, indent); - strbuf_rtrim(sb); - - /* Make sure there is an EOLN for the non-oneline case */ - if (fmt != CMIT_FMT_ONELINE) - strbuf_addch(sb, '\n'); - - /* - * The caller may append additional body text in e-mail - * format. Make sure we did not strip the blank line - * between the header and the body. - */ - if (fmt == CMIT_FMT_EMAIL && sb->len <= beginning_of_body) - strbuf_addch(sb, '\n'); - free(reencoded); -} - struct commit *pop_commit(struct commit_list **stack) { struct commit_list *top = *stack; diff --git a/pretty.c b/pretty.c new file mode 100644 index 0000000000..490cede263 --- /dev/null +++ b/pretty.c @@ -0,0 +1,723 @@ +#include "cache.h" +#include "commit.h" +#include "interpolate.h" +#include "utf8.h" +#include "diff.h" +#include "revision.h" + +static struct cmt_fmt_map { + const char *n; + size_t cmp_len; + enum cmit_fmt v; +} cmt_fmts[] = { + { "raw", 1, CMIT_FMT_RAW }, + { "medium", 1, CMIT_FMT_MEDIUM }, + { "short", 1, CMIT_FMT_SHORT }, + { "email", 1, CMIT_FMT_EMAIL }, + { "full", 5, CMIT_FMT_FULL }, + { "fuller", 5, CMIT_FMT_FULLER }, + { "oneline", 1, CMIT_FMT_ONELINE }, + { "format:", 7, CMIT_FMT_USERFORMAT}, +}; + +static char *user_format; + +enum cmit_fmt get_commit_format(const char *arg) +{ + int i; + + if (!arg || !*arg) + return CMIT_FMT_DEFAULT; + if (*arg == '=') + arg++; + if (!prefixcmp(arg, "format:")) { + if (user_format) + free(user_format); + user_format = xstrdup(arg + 7); + return CMIT_FMT_USERFORMAT; + } + for (i = 0; i < ARRAY_SIZE(cmt_fmts); i++) { + if (!strncmp(arg, cmt_fmts[i].n, cmt_fmts[i].cmp_len) && + !strncmp(arg, cmt_fmts[i].n, strlen(arg))) + return cmt_fmts[i].v; + } + + die("invalid --pretty format: %s", arg); +} + +/* + * Generic support for pretty-printing the header + */ +static int get_one_line(const char *msg) +{ + int ret = 0; + + for (;;) { + char c = *msg++; + if (!c) + break; + ret++; + if (c == '\n') + break; + } + return ret; +} + +/* High bit set, or ISO-2022-INT */ +int non_ascii(int ch) +{ + ch = (ch & 0xff); + return ((ch & 0x80) || (ch == 0x1b)); +} + +static int is_rfc2047_special(char ch) +{ + return (non_ascii(ch) || (ch == '=') || (ch == '?') || (ch == '_')); +} + +static void add_rfc2047(struct strbuf *sb, const char *line, int len, + const char *encoding) +{ + int i, last; + + for (i = 0; i < len; i++) { + int ch = line[i]; + if (non_ascii(ch)) + goto needquote; + if ((i + 1 < len) && (ch == '=' && line[i+1] == '?')) + goto needquote; + } + strbuf_add(sb, line, len); + return; + +needquote: + strbuf_grow(sb, len * 3 + strlen(encoding) + 100); + strbuf_addf(sb, "=?%s?q?", encoding); + for (i = last = 0; i < len; i++) { + unsigned ch = line[i] & 0xFF; + /* + * We encode ' ' using '=20' even though rfc2047 + * allows using '_' for readability. Unfortunately, + * many programs do not understand this and just + * leave the underscore in place. + */ + if (is_rfc2047_special(ch) || ch == ' ') { + strbuf_add(sb, line + last, i - last); + strbuf_addf(sb, "=%02X", ch); + last = i + 1; + } + } + strbuf_add(sb, line + last, len - last); + strbuf_addstr(sb, "?="); +} + +static void add_user_info(const char *what, enum cmit_fmt fmt, struct strbuf *sb, + const char *line, enum date_mode dmode, + const char *encoding) +{ + char *date; + int namelen; + unsigned long time; + int tz; + const char *filler = " "; + + if (fmt == CMIT_FMT_ONELINE) + return; + date = strchr(line, '>'); + if (!date) + return; + namelen = ++date - line; + time = strtoul(date, &date, 10); + tz = strtol(date, NULL, 10); + + if (fmt == CMIT_FMT_EMAIL) { + char *name_tail = strchr(line, '<'); + int display_name_length; + if (!name_tail) + return; + while (line < name_tail && isspace(name_tail[-1])) + name_tail--; + display_name_length = name_tail - line; + filler = ""; + strbuf_addstr(sb, "From: "); + add_rfc2047(sb, line, display_name_length, encoding); + strbuf_add(sb, name_tail, namelen - display_name_length); + strbuf_addch(sb, '\n'); + } else { + strbuf_addf(sb, "%s: %.*s%.*s\n", what, + (fmt == CMIT_FMT_FULLER) ? 4 : 0, + filler, namelen, line); + } + switch (fmt) { + case CMIT_FMT_MEDIUM: + strbuf_addf(sb, "Date: %s\n", show_date(time, tz, dmode)); + break; + case CMIT_FMT_EMAIL: + strbuf_addf(sb, "Date: %s\n", show_date(time, tz, DATE_RFC2822)); + break; + case CMIT_FMT_FULLER: + strbuf_addf(sb, "%sDate: %s\n", what, show_date(time, tz, dmode)); + break; + default: + /* notin' */ + break; + } +} + +static int is_empty_line(const char *line, int *len_p) +{ + int len = *len_p; + while (len && isspace(line[len-1])) + len--; + *len_p = len; + return !len; +} + +static void add_merge_info(enum cmit_fmt fmt, struct strbuf *sb, + const struct commit *commit, int abbrev) +{ + struct commit_list *parent = commit->parents; + + if ((fmt == CMIT_FMT_ONELINE) || (fmt == CMIT_FMT_EMAIL) || + !parent || !parent->next) + return; + + strbuf_addstr(sb, "Merge:"); + + while (parent) { + struct commit *p = parent->item; + const char *hex = NULL; + const char *dots; + if (abbrev) + hex = find_unique_abbrev(p->object.sha1, abbrev); + if (!hex) + hex = sha1_to_hex(p->object.sha1); + dots = (abbrev && strlen(hex) != 40) ? "..." : ""; + parent = parent->next; + + strbuf_addf(sb, " %s%s", hex, dots); + } + strbuf_addch(sb, '\n'); +} + +static char *get_header(const struct commit *commit, const char *key) +{ + int key_len = strlen(key); + const char *line = commit->buffer; + + for (;;) { + const char *eol = strchr(line, '\n'), *next; + + if (line == eol) + return NULL; + if (!eol) { + eol = line + strlen(line); + next = NULL; + } else + next = eol + 1; + if (eol - line > key_len && + !strncmp(line, key, key_len) && + line[key_len] == ' ') { + return xmemdupz(line + key_len + 1, eol - line - key_len - 1); + } + line = next; + } +} + +static char *replace_encoding_header(char *buf, const char *encoding) +{ + struct strbuf tmp; + size_t start, len; + char *cp = buf; + + /* guess if there is an encoding header before a \n\n */ + while (strncmp(cp, "encoding ", strlen("encoding "))) { + cp = strchr(cp, '\n'); + if (!cp || *++cp == '\n') + return buf; + } + start = cp - buf; + cp = strchr(cp, '\n'); + if (!cp) + return buf; /* should not happen but be defensive */ + len = cp + 1 - (buf + start); + + strbuf_init(&tmp, 0); + strbuf_attach(&tmp, buf, strlen(buf), strlen(buf) + 1); + if (is_encoding_utf8(encoding)) { + /* we have re-coded to UTF-8; drop the header */ + strbuf_remove(&tmp, start, len); + } else { + /* just replaces XXXX in 'encoding XXXX\n' */ + strbuf_splice(&tmp, start + strlen("encoding "), + len - strlen("encoding \n"), + encoding, strlen(encoding)); + } + return strbuf_detach(&tmp, NULL); +} + +static char *logmsg_reencode(const struct commit *commit, + const char *output_encoding) +{ + static const char *utf8 = "utf-8"; + const char *use_encoding; + char *encoding; + char *out; + + if (!*output_encoding) + return NULL; + encoding = get_header(commit, "encoding"); + use_encoding = encoding ? encoding : utf8; + if (!strcmp(use_encoding, output_encoding)) + if (encoding) /* we'll strip encoding header later */ + out = xstrdup(commit->buffer); + else + return NULL; /* nothing to do */ + else + out = reencode_string(commit->buffer, + output_encoding, use_encoding); + if (out) + out = replace_encoding_header(out, output_encoding); + + free(encoding); + return out; +} + +static void fill_person(struct interp *table, const char *msg, int len) +{ + int start, end, tz = 0; + unsigned long date; + char *ep; + + /* parse name */ + for (end = 0; end < len && msg[end] != '<'; end++) + ; /* do nothing */ + start = end + 1; + while (end > 0 && isspace(msg[end - 1])) + end--; + table[0].value = xmemdupz(msg, end); + + if (start >= len) + return; + + /* parse email */ + for (end = start + 1; end < len && msg[end] != '>'; end++) + ; /* do nothing */ + + if (end >= len) + return; + + table[1].value = xmemdupz(msg + start, end - start); + + /* parse date */ + for (start = end + 1; start < len && isspace(msg[start]); start++) + ; /* do nothing */ + if (start >= len) + return; + date = strtoul(msg + start, &ep, 10); + if (msg + start == ep) + return; + + table[5].value = xmemdupz(msg + start, ep - (msg + start)); + + /* parse tz */ + for (start = ep - msg + 1; start < len && isspace(msg[start]); start++) + ; /* do nothing */ + if (start + 1 < len) { + tz = strtoul(msg + start + 1, NULL, 10); + if (msg[start] == '-') + tz = -tz; + } + + interp_set_entry(table, 2, show_date(date, tz, DATE_NORMAL)); + interp_set_entry(table, 3, show_date(date, tz, DATE_RFC2822)); + interp_set_entry(table, 4, show_date(date, tz, DATE_RELATIVE)); + interp_set_entry(table, 6, show_date(date, tz, DATE_ISO8601)); +} + +void format_commit_message(const struct commit *commit, + const void *format, struct strbuf *sb) +{ + struct interp table[] = { + { "%H" }, /* commit hash */ + { "%h" }, /* abbreviated commit hash */ + { "%T" }, /* tree hash */ + { "%t" }, /* abbreviated tree hash */ + { "%P" }, /* parent hashes */ + { "%p" }, /* abbreviated parent hashes */ + { "%an" }, /* author name */ + { "%ae" }, /* author email */ + { "%ad" }, /* author date */ + { "%aD" }, /* author date, RFC2822 style */ + { "%ar" }, /* author date, relative */ + { "%at" }, /* author date, UNIX timestamp */ + { "%ai" }, /* author date, ISO 8601 */ + { "%cn" }, /* committer name */ + { "%ce" }, /* committer email */ + { "%cd" }, /* committer date */ + { "%cD" }, /* committer date, RFC2822 style */ + { "%cr" }, /* committer date, relative */ + { "%ct" }, /* committer date, UNIX timestamp */ + { "%ci" }, /* committer date, ISO 8601 */ + { "%e" }, /* encoding */ + { "%s" }, /* subject */ + { "%b" }, /* body */ + { "%Cred" }, /* red */ + { "%Cgreen" }, /* green */ + { "%Cblue" }, /* blue */ + { "%Creset" }, /* reset color */ + { "%n" }, /* newline */ + { "%m" }, /* left/right/bottom */ + }; + enum interp_index { + IHASH = 0, IHASH_ABBREV, + ITREE, ITREE_ABBREV, + IPARENTS, IPARENTS_ABBREV, + IAUTHOR_NAME, IAUTHOR_EMAIL, + IAUTHOR_DATE, IAUTHOR_DATE_RFC2822, IAUTHOR_DATE_RELATIVE, + IAUTHOR_TIMESTAMP, IAUTHOR_ISO8601, + ICOMMITTER_NAME, ICOMMITTER_EMAIL, + ICOMMITTER_DATE, ICOMMITTER_DATE_RFC2822, + ICOMMITTER_DATE_RELATIVE, ICOMMITTER_TIMESTAMP, + ICOMMITTER_ISO8601, + IENCODING, + ISUBJECT, + IBODY, + IRED, IGREEN, IBLUE, IRESET_COLOR, + INEWLINE, + ILEFT_RIGHT, + }; + struct commit_list *p; + char parents[1024]; + unsigned long len; + int i; + enum { HEADER, SUBJECT, BODY } state; + const char *msg = commit->buffer; + + if (ILEFT_RIGHT + 1 != ARRAY_SIZE(table)) + die("invalid interp table!"); + + /* these are independent of the commit */ + interp_set_entry(table, IRED, "\033[31m"); + interp_set_entry(table, IGREEN, "\033[32m"); + interp_set_entry(table, IBLUE, "\033[34m"); + interp_set_entry(table, IRESET_COLOR, "\033[m"); + interp_set_entry(table, INEWLINE, "\n"); + + /* these depend on the commit */ + if (!commit->object.parsed) + parse_object(commit->object.sha1); + interp_set_entry(table, IHASH, sha1_to_hex(commit->object.sha1)); + interp_set_entry(table, IHASH_ABBREV, + find_unique_abbrev(commit->object.sha1, + DEFAULT_ABBREV)); + interp_set_entry(table, ITREE, sha1_to_hex(commit->tree->object.sha1)); + interp_set_entry(table, ITREE_ABBREV, + find_unique_abbrev(commit->tree->object.sha1, + DEFAULT_ABBREV)); + interp_set_entry(table, ILEFT_RIGHT, + (commit->object.flags & BOUNDARY) + ? "-" + : (commit->object.flags & SYMMETRIC_LEFT) + ? "<" + : ">"); + + parents[1] = 0; + for (i = 0, p = commit->parents; + p && i < sizeof(parents) - 1; + p = p->next) + i += snprintf(parents + i, sizeof(parents) - i - 1, " %s", + sha1_to_hex(p->item->object.sha1)); + interp_set_entry(table, IPARENTS, parents + 1); + + parents[1] = 0; + for (i = 0, p = commit->parents; + p && i < sizeof(parents) - 1; + p = p->next) + i += snprintf(parents + i, sizeof(parents) - i - 1, " %s", + find_unique_abbrev(p->item->object.sha1, + DEFAULT_ABBREV)); + interp_set_entry(table, IPARENTS_ABBREV, parents + 1); + + for (i = 0, state = HEADER; msg[i] && state < BODY; i++) { + int eol; + for (eol = i; msg[eol] && msg[eol] != '\n'; eol++) + ; /* do nothing */ + + if (state == SUBJECT) { + table[ISUBJECT].value = xmemdupz(msg + i, eol - i); + i = eol; + } + if (i == eol) { + state++; + /* strip empty lines */ + while (msg[eol + 1] == '\n') + eol++; + } else if (!prefixcmp(msg + i, "author ")) + fill_person(table + IAUTHOR_NAME, + msg + i + 7, eol - i - 7); + else if (!prefixcmp(msg + i, "committer ")) + fill_person(table + ICOMMITTER_NAME, + msg + i + 10, eol - i - 10); + else if (!prefixcmp(msg + i, "encoding ")) + table[IENCODING].value = + xmemdupz(msg + i + 9, eol - i - 9); + i = eol; + } + if (msg[i]) + table[IBODY].value = xstrdup(msg + i); + + len = interpolate(sb->buf + sb->len, strbuf_avail(sb), + format, table, ARRAY_SIZE(table)); + if (len > strbuf_avail(sb)) { + strbuf_grow(sb, len); + interpolate(sb->buf + sb->len, strbuf_avail(sb) + 1, + format, table, ARRAY_SIZE(table)); + } + strbuf_setlen(sb, sb->len + len); + interp_clear_table(table, ARRAY_SIZE(table)); +} + +static void pp_header(enum cmit_fmt fmt, + int abbrev, + enum date_mode dmode, + const char *encoding, + const struct commit *commit, + const char **msg_p, + struct strbuf *sb) +{ + int parents_shown = 0; + + for (;;) { + const char *line = *msg_p; + int linelen = get_one_line(*msg_p); + + if (!linelen) + return; + *msg_p += linelen; + + if (linelen == 1) + /* End of header */ + return; + + if (fmt == CMIT_FMT_RAW) { + strbuf_add(sb, line, linelen); + continue; + } + + if (!memcmp(line, "parent ", 7)) { + if (linelen != 48) + die("bad parent line in commit"); + continue; + } + + if (!parents_shown) { + struct commit_list *parent; + int num; + for (parent = commit->parents, num = 0; + parent; + parent = parent->next, num++) + ; + /* with enough slop */ + strbuf_grow(sb, num * 50 + 20); + add_merge_info(fmt, sb, commit, abbrev); + parents_shown = 1; + } + + /* + * MEDIUM == DEFAULT shows only author with dates. + * FULL shows both authors but not dates. + * FULLER shows both authors and dates. + */ + if (!memcmp(line, "author ", 7)) { + strbuf_grow(sb, linelen + 80); + add_user_info("Author", fmt, sb, line + 7, dmode, encoding); + } + if (!memcmp(line, "committer ", 10) && + (fmt == CMIT_FMT_FULL || fmt == CMIT_FMT_FULLER)) { + strbuf_grow(sb, linelen + 80); + add_user_info("Commit", fmt, sb, line + 10, dmode, encoding); + } + } +} + +static void pp_title_line(enum cmit_fmt fmt, + const char **msg_p, + struct strbuf *sb, + const char *subject, + const char *after_subject, + const char *encoding, + int plain_non_ascii) +{ + struct strbuf title; + + strbuf_init(&title, 80); + + for (;;) { + const char *line = *msg_p; + int linelen = get_one_line(line); + + *msg_p += linelen; + if (!linelen || is_empty_line(line, &linelen)) + break; + + strbuf_grow(&title, linelen + 2); + if (title.len) { + if (fmt == CMIT_FMT_EMAIL) { + strbuf_addch(&title, '\n'); + } + strbuf_addch(&title, ' '); + } + strbuf_add(&title, line, linelen); + } + + strbuf_grow(sb, title.len + 1024); + if (subject) { + strbuf_addstr(sb, subject); + add_rfc2047(sb, title.buf, title.len, encoding); + } else { + strbuf_addbuf(sb, &title); + } + strbuf_addch(sb, '\n'); + + if (plain_non_ascii) { + const char *header_fmt = + "MIME-Version: 1.0\n" + "Content-Type: text/plain; charset=%s\n" + "Content-Transfer-Encoding: 8bit\n"; + strbuf_addf(sb, header_fmt, encoding); + } + if (after_subject) { + strbuf_addstr(sb, after_subject); + } + if (fmt == CMIT_FMT_EMAIL) { + strbuf_addch(sb, '\n'); + } + strbuf_release(&title); +} + +static void pp_remainder(enum cmit_fmt fmt, + const char **msg_p, + struct strbuf *sb, + int indent) +{ + int first = 1; + for (;;) { + const char *line = *msg_p; + int linelen = get_one_line(line); + *msg_p += linelen; + + if (!linelen) + break; + + if (is_empty_line(line, &linelen)) { + if (first) + continue; + if (fmt == CMIT_FMT_SHORT) + break; + } + first = 0; + + strbuf_grow(sb, linelen + indent + 20); + if (indent) { + memset(sb->buf + sb->len, ' ', indent); + strbuf_setlen(sb, sb->len + indent); + } + strbuf_add(sb, line, linelen); + strbuf_addch(sb, '\n'); + } +} + +void pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit, + struct strbuf *sb, int abbrev, + const char *subject, const char *after_subject, + enum date_mode dmode, int plain_non_ascii) +{ + unsigned long beginning_of_body; + int indent = 4; + const char *msg = commit->buffer; + char *reencoded; + const char *encoding; + + if (fmt == CMIT_FMT_USERFORMAT) { + format_commit_message(commit, user_format, sb); + return; + } + + encoding = (git_log_output_encoding + ? git_log_output_encoding + : git_commit_encoding); + if (!encoding) + encoding = "utf-8"; + reencoded = logmsg_reencode(commit, encoding); + if (reencoded) { + msg = reencoded; + } + + if (fmt == CMIT_FMT_ONELINE || fmt == CMIT_FMT_EMAIL) + indent = 0; + + /* After-subject is used to pass in Content-Type: multipart + * MIME header; in that case we do not have to do the + * plaintext content type even if the commit message has + * non 7-bit ASCII character. Otherwise, check if we need + * to say this is not a 7-bit ASCII. + */ + if (fmt == CMIT_FMT_EMAIL && !after_subject) { + int i, ch, in_body; + + for (in_body = i = 0; (ch = msg[i]); i++) { + if (!in_body) { + /* author could be non 7-bit ASCII but + * the log may be so; skip over the + * header part first. + */ + if (ch == '\n' && msg[i+1] == '\n') + in_body = 1; + } + else if (non_ascii(ch)) { + plain_non_ascii = 1; + break; + } + } + } + + pp_header(fmt, abbrev, dmode, encoding, commit, &msg, sb); + if (fmt != CMIT_FMT_ONELINE && !subject) { + strbuf_addch(sb, '\n'); + } + + /* Skip excess blank lines at the beginning of body, if any... */ + for (;;) { + int linelen = get_one_line(msg); + int ll = linelen; + if (!linelen) + break; + if (!is_empty_line(msg, &ll)) + break; + msg += linelen; + } + + /* These formats treat the title line specially. */ + if (fmt == CMIT_FMT_ONELINE || fmt == CMIT_FMT_EMAIL) + pp_title_line(fmt, &msg, sb, subject, + after_subject, encoding, plain_non_ascii); + + beginning_of_body = sb->len; + if (fmt != CMIT_FMT_ONELINE) + pp_remainder(fmt, &msg, sb, indent); + strbuf_rtrim(sb); + + /* Make sure there is an EOLN for the non-oneline case */ + if (fmt != CMIT_FMT_ONELINE) + strbuf_addch(sb, '\n'); + + /* + * The caller may append additional body text in e-mail + * format. Make sure we did not strip the blank line + * between the header and the body. + */ + if (fmt == CMIT_FMT_EMAIL && sb->len <= beginning_of_body) + strbuf_addch(sb, '\n'); + free(reencoded); +} From 8951d7c1f1ae38f34617b6c2490bf65e73e371f7 Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Sun, 4 Nov 2007 15:51:17 -0500 Subject: [PATCH 0436/1490] Build in ls-remote This actually replaces peek-remote with ls-remote, since peek-remote now handles everything. peek-remote remains an a second name for ls-remote, although its help message now gives the "ls-remote" name. Signed-off-by: Daniel Barkalow Signed-off-by: Junio C Hamano --- Makefile | 3 +-- builtin-peek-remote.c => builtin-ls-remote.c | 10 +++++----- builtin.h | 2 +- git-ls-remote.sh => contrib/examples/git-ls-remote.sh | 0 git.c | 3 ++- 5 files changed, 9 insertions(+), 9 deletions(-) rename builtin-peek-remote.c => builtin-ls-remote.c (83%) rename git-ls-remote.sh => contrib/examples/git-ls-remote.sh (100%) diff --git a/Makefile b/Makefile index 3ec1876cbb..470e54a60d 100644 --- a/Makefile +++ b/Makefile @@ -210,7 +210,6 @@ BASIC_LDFLAGS = SCRIPT_SH = \ git-bisect.sh git-checkout.sh \ git-clean.sh git-clone.sh git-commit.sh \ - git-ls-remote.sh \ git-merge-one-file.sh git-mergetool.sh git-parse-remote.sh \ git-pull.sh git-rebase.sh git-rebase--interactive.sh \ git-repack.sh git-request-pull.sh \ @@ -345,6 +344,7 @@ BUILTIN_OBJS = \ builtin-log.o \ builtin-ls-files.o \ builtin-ls-tree.o \ + builtin-ls-remote.o \ builtin-mailinfo.o \ builtin-mailsplit.o \ builtin-merge-base.o \ @@ -352,7 +352,6 @@ BUILTIN_OBJS = \ builtin-mv.o \ builtin-name-rev.o \ builtin-pack-objects.o \ - builtin-peek-remote.o \ builtin-prune.o \ builtin-prune-packed.o \ builtin-push.o \ diff --git a/builtin-peek-remote.c b/builtin-ls-remote.c similarity index 83% rename from builtin-peek-remote.c rename to builtin-ls-remote.c index b4106f510a..003580c26a 100644 --- a/builtin-peek-remote.c +++ b/builtin-ls-remote.c @@ -3,10 +3,10 @@ #include "transport.h" #include "remote.h" -static const char peek_remote_usage[] = -"git-peek-remote [--upload-pack=] [:]"; +static const char ls_remote_usage[] = +"git-ls-remote [--upload-pack=] [:]"; -int cmd_peek_remote(int argc, const char **argv, const char *prefix) +int cmd_ls_remote(int argc, const char **argv, const char *prefix) { int i; const char *dest = NULL; @@ -43,14 +43,14 @@ int cmd_peek_remote(int argc, const char **argv, const char *prefix) flags |= REF_NORMAL; continue; } - usage(peek_remote_usage); + usage(ls_remote_usage); } dest = arg; break; } if (!dest || i != argc - 1) - usage(peek_remote_usage); + usage(ls_remote_usage); transport = transport_get(NULL, dest); if (uploadpack != NULL) diff --git a/builtin.h b/builtin.h index 2335c01b02..525107f385 100644 --- a/builtin.h +++ b/builtin.h @@ -48,6 +48,7 @@ extern int cmd_log(int argc, const char **argv, const char *prefix); extern int cmd_log_reflog(int argc, const char **argv, const char *prefix); extern int cmd_ls_files(int argc, const char **argv, const char *prefix); extern int cmd_ls_tree(int argc, const char **argv, const char *prefix); +extern int cmd_ls_remote(int argc, const char **argv, const char *prefix); extern int cmd_mailinfo(int argc, const char **argv, const char *prefix); extern int cmd_mailsplit(int argc, const char **argv, const char *prefix); extern int cmd_merge_base(int argc, const char **argv, const char *prefix); @@ -55,7 +56,6 @@ extern int cmd_merge_file(int argc, const char **argv, const char *prefix); extern int cmd_mv(int argc, const char **argv, const char *prefix); extern int cmd_name_rev(int argc, const char **argv, const char *prefix); extern int cmd_pack_objects(int argc, const char **argv, const char *prefix); -extern int cmd_peek_remote(int argc, const char **argv, const char *prefix); extern int cmd_pickaxe(int argc, const char **argv, const char *prefix); extern int cmd_prune(int argc, const char **argv, const char *prefix); extern int cmd_prune_packed(int argc, const char **argv, const char *prefix); diff --git a/git-ls-remote.sh b/contrib/examples/git-ls-remote.sh similarity index 100% rename from git-ls-remote.sh rename to contrib/examples/git-ls-remote.sh diff --git a/git.c b/git.c index 19a2172a10..b173f227f0 100644 --- a/git.c +++ b/git.c @@ -326,6 +326,7 @@ static void handle_internal_command(int argc, const char **argv) { "log", cmd_log, RUN_SETUP | USE_PAGER }, { "ls-files", cmd_ls_files, RUN_SETUP }, { "ls-tree", cmd_ls_tree, RUN_SETUP }, + { "ls-remote", cmd_ls_remote }, { "mailinfo", cmd_mailinfo }, { "mailsplit", cmd_mailsplit }, { "merge-base", cmd_merge_base, RUN_SETUP }, @@ -333,7 +334,7 @@ static void handle_internal_command(int argc, const char **argv) { "mv", cmd_mv, RUN_SETUP | NEED_WORK_TREE }, { "name-rev", cmd_name_rev, RUN_SETUP }, { "pack-objects", cmd_pack_objects, RUN_SETUP }, - { "peek-remote", cmd_peek_remote }, + { "peek-remote", cmd_ls_remote }, { "pickaxe", cmd_blame, RUN_SETUP }, { "prune", cmd_prune, RUN_SETUP }, { "prune-packed", cmd_prune_packed, RUN_SETUP }, From 0d8aafd25271c8d1cf185019437e21362edc1bc7 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sun, 4 Nov 2007 20:07:29 -0500 Subject: [PATCH 0437/1490] sideband.c: ESC is spelled '\033' not '\e' for portability. Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- sideband.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sideband.c b/sideband.c index 58edea68ee..756bbc28d7 100644 --- a/sideband.c +++ b/sideband.c @@ -13,7 +13,7 @@ */ #define PREFIX "remote:" -#define SUFFIX "\e[K" /* change to " " if ANSI sequences don't work */ +#define SUFFIX "\033[K" /* change to " " if ANSI sequences don't work */ int recv_sideband(const char *me, int in_stream, int out, int err) { From 218558af599c01e5dec17a7399d9188a76c50203 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sun, 4 Nov 2007 22:15:41 -0500 Subject: [PATCH 0438/1490] make display of total transferred more accurate The throughput display needs a delay period before accounting and displaying anything. Yet it might be called after some amount of data has already been transferred. The display of total data is therefore accounted late and therefore smaller than the reality. Let's call display_throughput() with an absolute amount of transferred data instead of a relative number, and let the throughput code find the relative amount of data by itself as needed. This way the displayed total is always exact. Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- csum-file.c | 4 +++- csum-file.h | 1 + index-pack.c | 4 ++-- progress.c | 46 ++++++++++++++++++++++------------------------ progress.h | 2 +- 5 files changed, 29 insertions(+), 28 deletions(-) diff --git a/csum-file.c b/csum-file.c index 3729e73e19..b445e6a2e5 100644 --- a/csum-file.c +++ b/csum-file.c @@ -18,7 +18,8 @@ static void sha1flush(struct sha1file *f, unsigned int count) for (;;) { int ret = xwrite(f->fd, buf, count); if (ret > 0) { - display_throughput(f->tp, ret); + f->total += ret; + display_throughput(f->tp, f->total); buf = (char *) buf + ret; count -= ret; if (count) @@ -101,6 +102,7 @@ struct sha1file *sha1fd_throughput(int fd, const char *name, struct progress *tp f->fd = fd; f->error = 0; f->offset = 0; + f->total = 0; f->tp = tp; f->do_crc = 0; SHA1_Init(&f->ctx); diff --git a/csum-file.h b/csum-file.h index 4d1b231292..a38cc3a2d7 100644 --- a/csum-file.h +++ b/csum-file.h @@ -8,6 +8,7 @@ struct sha1file { int fd, error; unsigned int offset, namelen; SHA_CTX ctx; + off_t total; struct progress *tp; char name[PATH_MAX]; int do_crc; diff --git a/index-pack.c b/index-pack.c index 715a5bb7a6..581a7f5650 100644 --- a/index-pack.c +++ b/index-pack.c @@ -87,9 +87,9 @@ static void *fill(int min) die("early EOF"); die("read error on input: %s", strerror(errno)); } - if (from_stdin) - display_throughput(progress, ret); input_len += ret; + if (from_stdin) + display_throughput(progress, consumed_bytes + input_len); } while (input_len < min); return input_buffer; } diff --git a/progress.c b/progress.c index 3f6a602a53..a963bd8bfc 100644 --- a/progress.c +++ b/progress.c @@ -14,11 +14,10 @@ #define TP_IDX_MAX 8 struct throughput { + off_t prev_total; struct timeval prev_tv; - off_t total; - unsigned long count; - unsigned long avg_bytes; - unsigned long last_bytes[TP_IDX_MAX]; + unsigned int avg_bytes; + unsigned int last_bytes[TP_IDX_MAX]; unsigned int avg_misecs; unsigned int last_misecs[TP_IDX_MAX]; unsigned int idx; @@ -110,7 +109,7 @@ static int display(struct progress *progress, unsigned n, int done) return 0; } -void display_throughput(struct progress *progress, unsigned long n) +void display_throughput(struct progress *progress, off_t total) { struct throughput *tp; struct timeval tv; @@ -124,14 +123,13 @@ void display_throughput(struct progress *progress, unsigned long n) if (!tp) { progress->throughput = tp = calloc(1, sizeof(*tp)); - if (tp) + if (tp) { + tp->prev_total = total; tp->prev_tv = tv; + } return; } - tp->total += n; - tp->count += n; - /* * We have x = bytes and y = microsecs. We want z = KiB/s: * @@ -152,37 +150,37 @@ void display_throughput(struct progress *progress, unsigned long n) if (misecs > 512) { int l = sizeof(tp->display); + unsigned int count = total - tp->prev_total; + tp->prev_total = total; tp->prev_tv = tv; - tp->avg_bytes += tp->count; + tp->avg_bytes += count; tp->avg_misecs += misecs; - if (tp->total > 1 << 30) { + if (total > 1 << 30) { l -= snprintf(tp->display, l, ", %u.%2.2u GiB", - (int)(tp->total >> 30), - (int)(tp->total & ((1 << 30) - 1)) / 10737419); - } else if (tp->total > 1 << 20) { + (int)(total >> 30), + (int)(total & ((1 << 30) - 1)) / 10737419); + } else if (total > 1 << 20) { l -= snprintf(tp->display, l, ", %u.%2.2u MiB", - (int)(tp->total >> 20), - ((int)(tp->total & ((1 << 20) - 1)) + (int)(total >> 20), + ((int)(total & ((1 << 20) - 1)) * 100) >> 20); - } else if (tp->total > 1 << 10) { + } else if (total > 1 << 10) { l -= snprintf(tp->display, l, ", %u.%2.2u KiB", - (int)(tp->total >> 10), - ((int)(tp->total & ((1 << 10) - 1)) + (int)(total >> 10), + ((int)(total & ((1 << 10) - 1)) * 100) >> 10); } else { - l -= snprintf(tp->display, l, ", %u bytes", - (int)tp->total); + l -= snprintf(tp->display, l, ", %u bytes", (int)total); } snprintf(tp->display + sizeof(tp->display) - l, l, - " | %lu KiB/s", tp->avg_bytes / tp->avg_misecs); + " | %u KiB/s", tp->avg_bytes / tp->avg_misecs); tp->avg_bytes -= tp->last_bytes[tp->idx]; tp->avg_misecs -= tp->last_misecs[tp->idx]; - tp->last_bytes[tp->idx] = tp->count; + tp->last_bytes[tp->idx] = count; tp->last_misecs[tp->idx] = misecs; tp->idx = (tp->idx + 1) % TP_IDX_MAX; - tp->count = 0; if (progress->last_value != -1 && progress_update) display(progress, progress->last_value, 0); diff --git a/progress.h b/progress.h index 61cb68dfa5..3912969e60 100644 --- a/progress.h +++ b/progress.h @@ -3,7 +3,7 @@ struct progress; -void display_throughput(struct progress *progress, unsigned long n); +void display_throughput(struct progress *progress, off_t total); int display_progress(struct progress *progress, unsigned n); struct progress *start_progress(const char *title, unsigned total); struct progress *start_progress_delay(const char *title, unsigned total, From 9ef4272bea94b022aa84372c06e211bccd5f8a54 Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Sun, 4 Nov 2007 15:05:45 -0800 Subject: [PATCH 0439/1490] git-fetch: be even quieter. Signed-off-by: Pierre Habouzit Signed-off-by: Junio C Hamano --- builtin-fetch.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/builtin-fetch.c b/builtin-fetch.c index 5f5b59bfdb..e65690f25c 100644 --- a/builtin-fetch.c +++ b/builtin-fetch.c @@ -152,6 +152,7 @@ static int s_update_ref(const char *action, } #define SUMMARY_WIDTH (2 * DEFAULT_ABBREV + 3) +#define REFCOL_WIDTH 10 static int update_local_ref(struct ref *ref, const char *remote, @@ -181,8 +182,9 @@ static int update_local_ref(struct ref *ref, if (!hashcmp(ref->old_sha1, ref->new_sha1)) { if (verbose) - sprintf(display, "= %-*s %s -> %s", SUMMARY_WIDTH, - "[up to date]", remote, pretty_ref); + sprintf(display, "= %-*s %-*s -> %s", SUMMARY_WIDTH, + "[up to date]", REFCOL_WIDTH, remote, + pretty_ref); return 0; } @@ -194,15 +196,17 @@ static int update_local_ref(struct ref *ref, * If this is the head, and it's not okay to update * the head, and the old value of the head isn't empty... */ - sprintf(display, "! %-*s %s -> %s (can't fetch in current branch)", - SUMMARY_WIDTH, "[rejected]", remote, pretty_ref); + sprintf(display, "! %-*s %-*s -> %s (can't fetch in current branch)", + SUMMARY_WIDTH, "[rejected]", REFCOL_WIDTH, remote, + pretty_ref); return 1; } if (!is_null_sha1(ref->old_sha1) && !prefixcmp(ref->name, "refs/tags/")) { - sprintf(display, "- %-*s %s -> %s", - SUMMARY_WIDTH, "[tag update]", remote, pretty_ref); + sprintf(display, "- %-*s %-*s -> %s", + SUMMARY_WIDTH, "[tag update]", REFCOL_WIDTH, remote, + pretty_ref); return s_update_ref("updating tag", ref, 0); } @@ -220,8 +224,8 @@ static int update_local_ref(struct ref *ref, what = "[new branch]"; } - sprintf(display, "* %-*s %s -> %s", - SUMMARY_WIDTH, what, remote, pretty_ref); + sprintf(display, "* %-*s %-*s -> %s", SUMMARY_WIDTH, what, + REFCOL_WIDTH, remote, pretty_ref); return s_update_ref(msg, ref, 0); } @@ -230,20 +234,21 @@ static int update_local_ref(struct ref *ref, strcpy(quickref, find_unique_abbrev(current->object.sha1, DEFAULT_ABBREV)); strcat(quickref, ".."); strcat(quickref, find_unique_abbrev(ref->new_sha1, DEFAULT_ABBREV)); - sprintf(display, " %-*s %s -> %s (fast forward)", - SUMMARY_WIDTH, quickref, remote, pretty_ref); + sprintf(display, " %-*s %-*s -> %s", SUMMARY_WIDTH, quickref, + REFCOL_WIDTH, remote, pretty_ref); return s_update_ref("fast forward", ref, 1); } else if (force || ref->force) { char quickref[84]; strcpy(quickref, find_unique_abbrev(current->object.sha1, DEFAULT_ABBREV)); strcat(quickref, "..."); strcat(quickref, find_unique_abbrev(ref->new_sha1, DEFAULT_ABBREV)); - sprintf(display, "+ %-*s %s -> %s (forced update)", - SUMMARY_WIDTH, quickref, remote, pretty_ref); + sprintf(display, "+ %-*s %-*s -> %s (forced update)", + SUMMARY_WIDTH, quickref, REFCOL_WIDTH, remote, pretty_ref); return s_update_ref("forced-update", ref, 1); } else { - sprintf(display, "! %-*s %s -> %s (non fast forward)", - SUMMARY_WIDTH, "[rejected]", remote, pretty_ref); + sprintf(display, "! %-*s %-*s -> %s (non fast forward)", + SUMMARY_WIDTH, "[rejected]", REFCOL_WIDTH, remote, + pretty_ref); return 1; } } From ec640ed1cf1d62730555705ec18b785c43e81f62 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sun, 4 Nov 2007 22:54:50 -0500 Subject: [PATCH 0440/1490] remove dead code from the csum-file interface The provided name argument is always constant and valid in every caller's context, so no need to have an array of PATH_MAX chars to copy it into when a simple pointer will do. Unfortunately that means getting rid of wascally wabbits too. The 'error' field is also unused. Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- csum-file.c | 14 ++------------ csum-file.h | 6 +++--- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/csum-file.c b/csum-file.c index b445e6a2e5..9728a99541 100644 --- a/csum-file.c +++ b/csum-file.c @@ -88,22 +88,12 @@ struct sha1file *sha1fd(int fd, const char *name) struct sha1file *sha1fd_throughput(int fd, const char *name, struct progress *tp) { - struct sha1file *f; - unsigned len; - - f = xmalloc(sizeof(*f)); - - len = strlen(name); - if (len >= PATH_MAX) - die("you wascally wabbit, you"); - f->namelen = len; - memcpy(f->name, name, len+1); - + struct sha1file *f = xmalloc(sizeof(*f)); f->fd = fd; - f->error = 0; f->offset = 0; f->total = 0; f->tp = tp; + f->name = name; f->do_crc = 0; SHA1_Init(&f->ctx); return f; diff --git a/csum-file.h b/csum-file.h index a38cc3a2d7..1af76562f3 100644 --- a/csum-file.h +++ b/csum-file.h @@ -5,12 +5,12 @@ struct progress; /* A SHA1-protected file */ struct sha1file { - int fd, error; - unsigned int offset, namelen; + int fd; + unsigned int offset; SHA_CTX ctx; off_t total; struct progress *tp; - char name[PATH_MAX]; + const char *name; int do_crc; uint32_t crc32; unsigned char buffer[8192]; From c74d9acf20ba0c69bbd67c5b0bb3bd3c2349cebe Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Mon, 5 Nov 2007 03:21:47 -0800 Subject: [PATCH 0441/1490] git-svn: fix dcommit clobbering when committing a series of diffs Our revision number sent to SVN is set to the last revision we committed if we've made any previous commits in a dcommit invocation. Although our SVN Editor code uses the delta of two (old) trees to generate information to send upstream, it'll still send complete resultant files upstream; even if the tree they're based against is out-of-date. The combination of sending a file that does not include the latest changes, but set with a revision number of a commit we just made will cause SVN to accept the resultant file even if it was generated against an old tree. More trouble was caused when fixing this because we were rebasing uncessarily at times. We used git-diff-tree to check the imported SVN revision against our HEAD, not the last tree we committed to SVN. The unnecessary rebasing caused merge commits upstream to SVN to fail. Signed-off-by: Eric Wong Signed-off-by: Junio C Hamano --- git-svn.perl | 48 +++++++++++++++++-- t/t9106-git-svn-dcommit-clobber-series.sh | 56 +++++++++++++++++++++++ 2 files changed, 100 insertions(+), 4 deletions(-) create mode 100755 t/t9106-git-svn-dcommit-clobber-series.sh diff --git a/git-svn.perl b/git-svn.perl index c015ea8580..ec25ea4231 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -390,7 +390,8 @@ sub cmd_dcommit { "If these changes depend on each other, re-running ", "without --no-rebase will be required." } - foreach my $d (@$linear_refs) { + while (1) { + my $d = shift @$linear_refs or last; unless (defined $last_rev) { (undef, $last_rev, undef) = cmt_metadata("$d~1"); unless (defined $last_rev) { @@ -423,14 +424,14 @@ sub cmd_dcommit { # we always want to rebase against the current HEAD, # not any head that was passed to us - my @diff = command('diff-tree', 'HEAD', + my @diff = command('diff-tree', $d, $gs->refname, '--'); my @finish; if (@diff) { @finish = rebase_cmd(); - print STDERR "W: HEAD and ", $gs->refname, + print STDERR "W: $d and ", $gs->refname, " differ, using @finish:\n", - "@diff"; + join("\n", @diff), "\n"; } else { print "No changes between current HEAD and ", $gs->refname, @@ -439,6 +440,45 @@ sub cmd_dcommit { @finish = qw/reset --mixed/; } command_noisy(@finish, $gs->refname); + if (@diff) { + @refs = (); + my ($url_, $rev_, $uuid_, $gs_) = + working_head_info($head, \@refs); + my ($linear_refs_, $parents_) = + linearize_history($gs_, \@refs); + if (scalar(@$linear_refs) != + scalar(@$linear_refs_)) { + fatal "# of revisions changed ", + "\nbefore:\n", + join("\n", @$linear_refs), + "\n\nafter:\n", + join("\n", @$linear_refs_), "\n", + 'If you are attempting to commit ', + "merges, try running:\n\t", + 'git rebase --interactive', + '--preserve-merges ', + $gs->refname, + "\nBefore dcommitting"; + } + if ($url_ ne $url) { + fatal "URL mismatch after rebase: ", + "$url_ != $url"; + } + if ($uuid_ ne $uuid) { + fatal "uuid mismatch after rebase: ", + "$uuid_ != $uuid"; + } + # remap parents + my (%p, @l, $i); + for ($i = 0; $i < scalar @$linear_refs; $i++) { + my $new = $linear_refs_->[$i] or next; + $p{$new} = + $parents->{$linear_refs->[$i]}; + push @l, $new; + } + $parents = \%p; + $linear_refs = \@l; + } $last_rev = $cmt_rev; } } diff --git a/t/t9106-git-svn-dcommit-clobber-series.sh b/t/t9106-git-svn-dcommit-clobber-series.sh new file mode 100755 index 0000000000..7eff4cdc05 --- /dev/null +++ b/t/t9106-git-svn-dcommit-clobber-series.sh @@ -0,0 +1,56 @@ +#!/bin/sh +# +# Copyright (c) 2007 Eric Wong +test_description='git-svn dcommit clobber series' +. ./lib-git-svn.sh + +test_expect_success 'initialize repo' " + mkdir import && + cd import && + awk 'BEGIN { for (i = 1; i < 64; i++) { print i } }' > file + svn import -m 'initial' . $svnrepo && + cd .. && + git svn init $svnrepo && + git svn fetch && + test -e file + " + +test_expect_success '(supposedly) non-conflicting change from SVN' " + test x\"\`sed -n -e 58p < file\`\" = x58 && + test x\"\`sed -n -e 61p < file\`\" = x61 && + svn co $svnrepo tmp && + cd tmp && + perl -i -p -e 's/^58\$/5588/' file && + perl -i -p -e 's/^61\$/6611/' file && + test x\"\`sed -n -e 58p < file\`\" = x5588 && + test x\"\`sed -n -e 61p < file\`\" = x6611 && + svn commit -m '58 => 5588, 61 => 6611' && + cd .. + " + +test_expect_success 'some unrelated changes to git' " + echo hi > life && + git update-index --add life && + git commit -m hi-life && + echo bye >> life && + git commit -m bye-life life + " + +test_expect_success 'change file but in unrelated area' " + test x\"\`sed -n -e 4p < file\`\" = x4 && + test x\"\`sed -n -e 7p < file\`\" = x7 && + perl -i -p -e 's/^4\$/4444/' file && + perl -i -p -e 's/^7\$/7777/' file && + test x\"\`sed -n -e 4p < file\`\" = x4444 && + test x\"\`sed -n -e 7p < file\`\" = x7777 && + git commit -m '4 => 4444, 7 => 7777' file && + git svn dcommit && + svn up tmp && + cd tmp && + test x\"\`sed -n -e 4p < file\`\" = x4444 && + test x\"\`sed -n -e 7p < file\`\" = x7777 && + test x\"\`sed -n -e 58p < file\`\" = x5588 && + test x\"\`sed -n -e 61p < file\`\" = x6611 + " + +test_done From fb159580a1628947f0a088e24cfe6fe4c81d99d0 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Mon, 5 Nov 2007 03:21:48 -0800 Subject: [PATCH 0442/1490] git-svn: t9114: verify merge commit message in test It's possible that we end up with an incorrect commit message in this test after making changes to fix the clobber bug in dcommit. Signed-off-by: Eric Wong Signed-off-by: Junio C Hamano --- t/t9114-git-svn-dcommit-merge.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/t/t9114-git-svn-dcommit-merge.sh b/t/t9114-git-svn-dcommit-merge.sh index d6ca955081..225060b88b 100755 --- a/t/t9114-git-svn-dcommit-merge.sh +++ b/t/t9114-git-svn-dcommit-merge.sh @@ -86,4 +86,9 @@ test_expect_success 'verify post-merge ancestry' " git cat-file commit refs/heads/svn^ | grep '^friend$' " +test_expect_success 'verify merge commit message' " + git rev-list --pretty=raw -1 refs/heads/svn | \ + grep \" Merge branch 'merge' into svn\" + " + test_done From f76734902bba47afff622068524a0c38f642d769 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Mon, 5 Nov 2007 00:11:15 -0500 Subject: [PATCH 0443/1490] more terse push output This changes the output of send-pack to match the new, more terse fetch output. It looks like this: To git://host.tld/path/to/repo + f3325dc...3b91d1c hasforce -> mirror/hasforce (forced update) f3325dc..bb022dc master -> mirror/master ! [rejected] needsforce -> mirror/needsforce (non-fast forward) * [new branch] newbranch -> mirror/newbranch * [new tag] v1.0 -> v1.0 instead of: updating 'refs/heads/mirror/hasforce' using 'refs/heads/hasforce' from f3325dca9c4a34d74012c0e159254f454930cec7 to 3b91d1c310ca9d7b547b85466dd876e143498304 updating 'refs/heads/mirror/master' using 'refs/heads/master' from f3325dca9c4a34d74012c0e159254f454930cec7 to bb022dc363d5c2aa9aa3026beb9706d44fbe1328 error: remote 'refs/heads/mirror/needsforce' is not an ancestor of local 'refs/heads/needsforce'. Maybe you are not up-to-date and need to pull first? updating 'refs/heads/mirror/newbranch' using 'refs/heads/newbranch' from 0000000000000000000000000000000000000000 to 3b91d1c310ca9d7b547b85466dd876e143498304 updating 'refs/tags/v1.0' from 0000000000000000000000000000000000000000 to bb022dc363d5c2aa9aa3026beb9706d44fbe1328 Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- builtin-send-pack.c | 81 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 64 insertions(+), 17 deletions(-) diff --git a/builtin-send-pack.c b/builtin-send-pack.c index aedef09ef0..d74cc3c4a6 100644 --- a/builtin-send-pack.c +++ b/builtin-send-pack.c @@ -206,7 +206,18 @@ static void update_tracking_ref(struct remote *remote, struct ref *ref) } } -static int do_send_pack(int in, int out, struct remote *remote, int nr_refspec, const char **refspec) +static const char *prettify_ref(const char *name) +{ + return name + ( + !prefixcmp(name, "refs/heads/") ? 11 : + !prefixcmp(name, "refs/tags/") ? 10 : + !prefixcmp(name, "refs/remotes/") ? 13 : + 0); +} + +#define SUMMARY_WIDTH (2 * DEFAULT_ABBREV + 3) + +static int do_send_pack(int in, int out, struct remote *remote, const char *dest, int nr_refspec, const char **refspec) { struct ref *ref; int new_refs; @@ -214,6 +225,7 @@ static int do_send_pack(int in, int out, struct remote *remote, int nr_refspec, int ask_for_status_report = 0; int allow_deleting_refs = 0; int expect_status_report = 0; + int shown_dest = 0; /* No funny business with the matcher */ remote_tail = get_remote_heads(in, &remote_refs, 0, NULL, REF_NORMAL); @@ -245,21 +257,33 @@ static int do_send_pack(int in, int out, struct remote *remote, int nr_refspec, for (ref = remote_refs; ref; ref = ref->next) { char old_hex[60], *new_hex; int will_delete_ref; + const char *pretty_ref; + const char *pretty_peer; if (!ref->peer_ref) continue; + if (!shown_dest) { + fprintf(stderr, "To %s\n", dest); + shown_dest = 1; + } + + pretty_ref = prettify_ref(ref->name); + pretty_peer = prettify_ref(ref->peer_ref->name); will_delete_ref = is_null_sha1(ref->peer_ref->new_sha1); if (will_delete_ref && !allow_deleting_refs) { - error("remote does not support deleting refs"); + fprintf(stderr, " ! %-*s %s (remote does not support deleting refs)\n", + SUMMARY_WIDTH, "[rejected]", pretty_ref); ret = -2; continue; } if (!will_delete_ref && !hashcmp(ref->old_sha1, ref->peer_ref->new_sha1)) { if (args.verbose) - fprintf(stderr, "'%s': up-to-date\n", ref->name); + fprintf(stderr, " = %-*s %s -> %s\n", + SUMMARY_WIDTH, "[up to date]", + pretty_peer, pretty_ref); continue; } @@ -296,12 +320,9 @@ static int do_send_pack(int in, int out, struct remote *remote, int nr_refspec, * commits at the remote end and likely * we were not up to date to begin with. */ - error("remote '%s' is not a strict " - "subset of local ref '%s'. " - "maybe you are not up-to-date and " - "need to pull first?", - ref->name, - ref->peer_ref->name); + fprintf(stderr, " ! %-*s %s -> %s (non-fast forward)\n", + SUMMARY_WIDTH, "[rejected]", + pretty_peer, pretty_ref); ret = -2; continue; } @@ -325,14 +346,40 @@ static int do_send_pack(int in, int out, struct remote *remote, int nr_refspec, old_hex, new_hex, ref->name); } if (will_delete_ref) - fprintf(stderr, "deleting '%s'\n", ref->name); + fprintf(stderr, " - %-*s %s\n", + SUMMARY_WIDTH, "[deleting]", + pretty_ref); + else if (is_null_sha1(ref->old_sha1)) { + const char *msg; + + if (!prefixcmp(ref->name, "refs/tags/")) + msg = "[new tag]"; + else + msg = "[new branch]"; + fprintf(stderr, " * %-*s %s -> %s\n", + SUMMARY_WIDTH, msg, + pretty_peer, pretty_ref); + } else { - fprintf(stderr, "updating '%s'", ref->name); - if (strcmp(ref->name, ref->peer_ref->name)) - fprintf(stderr, " using '%s'", - ref->peer_ref->name); - fprintf(stderr, "\n from %s\n to %s\n", - old_hex, new_hex); + char quickref[83]; + char type = ' '; + const char *msg = ""; + + strcpy(quickref, find_unique_abbrev(ref->old_sha1, DEFAULT_ABBREV)); + if (ref_newer(ref->peer_ref->new_sha1, ref->old_sha1)) + strcat(quickref, ".."); + else { + strcat(quickref, "..."); + type = '+'; + msg = " (forced update)"; + } + strcat(quickref, find_unique_abbrev(ref->new_sha1, DEFAULT_ABBREV)); + + fprintf(stderr, " %c %-*s %s -> %s%s\n", + type, + SUMMARY_WIDTH, quickref, + pretty_peer, pretty_ref, + msg); } } @@ -460,7 +507,7 @@ int send_pack(struct send_pack_args *my_args, verify_remote_names(nr_heads, heads); conn = git_connect(fd, dest, args.receivepack, args.verbose ? CONNECT_VERBOSE : 0); - ret = do_send_pack(fd[0], fd[1], remote, nr_heads, heads); + ret = do_send_pack(fd[0], fd[1], remote, dest, nr_heads, heads); close(fd[0]); close(fd[1]); ret |= finish_connect(conn); From 3b70da2b17dc5b7df644701a96a141d8f7c5ea15 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Mon, 5 Nov 2007 00:11:41 -0500 Subject: [PATCH 0444/1490] receive-pack: don't mention successful updates The proposed updates are already shown to the user by send-pack, so there's no point. We continue to show errors, since they are unexpected. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- receive-pack.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/receive-pack.c b/receive-pack.c index 38e35c06b9..ed44b897f6 100644 --- a/receive-pack.c +++ b/receive-pack.c @@ -204,8 +204,6 @@ static const char *update(struct command *cmd) error("failed to delete %s", name); return "failed to delete"; } - fprintf(stderr, "%s: %s -> deleted\n", name, - sha1_to_hex(old_sha1)); return NULL; /* good */ } else { @@ -217,8 +215,6 @@ static const char *update(struct command *cmd) if (write_ref_sha1(lock, new_sha1, "push")) { return "failed to write"; /* error() already called */ } - fprintf(stderr, "%s: %s -> %s\n", name, - sha1_to_hex(old_sha1), sha1_to_hex(new_sha1)); return NULL; /* good */ } } From b50fa2bd061c3bb21f2918849ece43ac9ca2c504 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Mon, 5 Nov 2007 00:12:18 -0500 Subject: [PATCH 0445/1490] send-pack: require --verbose to show update of tracking refs This is really an uninteresting detail, and it just takes attention away from the actual push updates and posssible errors. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- builtin-send-pack.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/builtin-send-pack.c b/builtin-send-pack.c index d74cc3c4a6..c1fd3f5fbb 100644 --- a/builtin-send-pack.c +++ b/builtin-send-pack.c @@ -195,7 +195,8 @@ static void update_tracking_ref(struct remote *remote, struct ref *ref) return; if (!remote_find_tracking(remote, &rs)) { - fprintf(stderr, "updating local tracking ref '%s'\n", rs.dst); + if (args.verbose) + fprintf(stderr, "updating local tracking ref '%s'\n", rs.dst); if (is_null_sha1(ref->peer_ref->new_sha1)) { if (delete_ref(rs.dst, NULL)) error("Failed to delete"); From 378c4832ef7271a389913f5533611a06415ac5a6 Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Sun, 4 Nov 2007 22:35:37 -0500 Subject: [PATCH 0446/1490] Use parseopts in builtin-push Signed-off-by: Daniel Barkalow Signed-off-by: Junio C Hamano --- builtin-push.c | 88 +++++++++++++++++++++----------------------------- 1 file changed, 36 insertions(+), 52 deletions(-) diff --git a/builtin-push.c b/builtin-push.c index 4b39ef3852..2c561953fc 100644 --- a/builtin-push.c +++ b/builtin-push.c @@ -7,8 +7,12 @@ #include "builtin.h" #include "remote.h" #include "transport.h" +#include "parse-options.h" -static const char push_usage[] = "git-push [--all] [--dry-run] [--tags] [--receive-pack=] [--repo=all] [-f | --force] [-v] [ ...]"; +static const char * const push_usage[] = { + "git-push [--all] [--dry-run] [--tags] [--receive-pack=] [--repo=all] [-f | --force] [-v] [ ...]", + NULL, +}; static int thin, verbose; static const char *receivepack; @@ -85,63 +89,43 @@ static int do_push(const char *repo, int flags) int cmd_push(int argc, const char **argv, const char *prefix) { - int i; int flags = 0; + int all = 0; + int dry_run = 0; + int force = 0; + int tags = 0; const char *repo = NULL; /* default repository */ - for (i = 1; i < argc; i++) { - const char *arg = argv[i]; + struct option options[] = { + OPT__VERBOSE(&verbose), + OPT_STRING( 0 , "repo", &repo, "repository", "repository"), + OPT_BOOLEAN( 0 , "all", &all, "push all refs"), + OPT_BOOLEAN( 0 , "tags", &tags, "push tags"), + OPT_BOOLEAN( 0 , "dry-run", &dry_run, "dry run"), + OPT_BOOLEAN('f', "force", &force, "force updates"), + OPT_BOOLEAN( 0 , "thin", &thin, "use thin pack"), + OPT_STRING( 0 , "receive-pack", &receivepack, "receive-pack", "receive pack program"), + OPT_STRING( 0 , "exec", &receivepack, "receive-pack", "receive pack program"), + OPT_END() + }; - if (arg[0] != '-') { - repo = arg; - i++; - break; - } - if (!strcmp(arg, "-v")) { - verbose=1; - continue; - } - if (!prefixcmp(arg, "--repo=")) { - repo = arg+7; - continue; - } - if (!strcmp(arg, "--all")) { - flags |= TRANSPORT_PUSH_ALL; - continue; - } - if (!strcmp(arg, "--dry-run")) { - flags |= TRANSPORT_PUSH_DRY_RUN; - continue; - } - if (!strcmp(arg, "--tags")) { - add_refspec("refs/tags/*"); - continue; - } - if (!strcmp(arg, "--force") || !strcmp(arg, "-f")) { - flags |= TRANSPORT_PUSH_FORCE; - continue; - } - if (!strcmp(arg, "--thin")) { - thin = 1; - continue; - } - if (!strcmp(arg, "--no-thin")) { - thin = 0; - continue; - } - if (!prefixcmp(arg, "--receive-pack=")) { - receivepack = arg + 15; - continue; - } - if (!prefixcmp(arg, "--exec=")) { - receivepack = arg + 7; - continue; - } - usage(push_usage); + argc = parse_options(argc, argv, options, push_usage, 0); + + if (force) + flags |= TRANSPORT_PUSH_FORCE; + if (dry_run) + flags |= TRANSPORT_PUSH_DRY_RUN; + if (tags) + add_refspec("refs/tags/*"); + if (all) + flags |= TRANSPORT_PUSH_ALL; + + if (argc > 0) { + repo = argv[0]; + set_refspecs(argv + 1, argc - 1); } - set_refspecs(argv + i, argc - i); if ((flags & TRANSPORT_PUSH_ALL) && refspec) - usage(push_usage); + usage_with_options(push_usage, options); return do_push(repo, flags); } From ae3e76c2991ddd5fd72cff22cd39d5d297e63504 Mon Sep 17 00:00:00 2001 From: Shawn Bohrer Date: Sun, 4 Nov 2007 22:28:12 -0600 Subject: [PATCH 0447/1490] Add more tests for git-clean Signed-off-by: Shawn Bohrer Signed-off-by: Junio C Hamano --- t/t7300-clean.sh | 105 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh index eb0847afe9..2327436187 100755 --- a/t/t7300-clean.sh +++ b/t/t7300-clean.sh @@ -37,6 +37,93 @@ test_expect_success 'git-clean' ' ' +test_expect_success 'git-clean src/' ' + + mkdir -p build docs && + touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && + git-clean src/ && + test -f Makefile && + test -f README && + test -f src/part1.c && + test -f src/part2.c && + test -f a.out && + test ! -f src/part3.c && + test -f docs/manual.txt && + test -f obj.o && + test -f build/lib.so + +' + +test_expect_success 'git-clean src/ src/' ' + + mkdir -p build docs && + touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && + git-clean src/ src/ && + test -f Makefile && + test -f README && + test -f src/part1.c && + test -f src/part2.c && + test -f a.out && + test ! -f src/part3.c && + test -f docs/manual.txt && + test -f obj.o && + test -f build/lib.so + +' + +test_expect_success 'git-clean with prefix' ' + + mkdir -p build docs && + touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && + (cd src/ && git-clean) && + test -f Makefile && + test -f README && + test -f src/part1.c && + test -f src/part2.c && + test -f a.out && + test ! -f src/part3.c && + test -f docs/manual.txt && + test -f obj.o && + test -f build/lib.so + +' +test_expect_success 'git-clean -d with prefix and path' ' + + mkdir -p build docs src/feature && + touch a.out src/part3.c src/feature/file.c docs/manual.txt obj.o build/lib.so && + (cd src/ && git-clean -d feature/) && + test -f Makefile && + test -f README && + test -f src/part1.c && + test -f src/part2.c && + test -f a.out && + test -f src/part3.c && + test ! -f src/feature/file.c && + test -f docs/manual.txt && + test -f obj.o && + test -f build/lib.so + +' + +test_expect_success 'git-clean symbolic link' ' + + mkdir -p build docs && + touch a.out src/part3.c docs/manual.txt obj.o build/lib.so && + ln -s docs/manual.txt src/part4.c + git-clean && + test -f Makefile && + test -f README && + test -f src/part1.c && + test -f src/part2.c && + test ! -f a.out && + test ! -f src/part3.c && + test ! -f src/part4.c && + test -f docs/manual.txt && + test -f obj.o && + test -f build/lib.so + +' + test_expect_success 'git-clean -n' ' mkdir -p build docs && @@ -71,6 +158,24 @@ test_expect_success 'git-clean -d' ' ' +test_expect_success 'git-clean -d src/ examples/' ' + + mkdir -p build docs examples && + touch a.out src/part3.c docs/manual.txt obj.o build/lib.so examples/1.c && + git-clean -d src/ examples/ && + test -f Makefile && + test -f README && + test -f src/part1.c && + test -f src/part2.c && + test -f a.out && + test ! -f src/part3.c && + test ! -f examples/1.c && + test -f docs/manual.txt && + test -f obj.o && + test -f build/lib.so + +' + test_expect_success 'git-clean -x' ' mkdir -p build docs && From 252a7c02354a3e2825cfde3c5053a04acc07be9c Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 4 Nov 2007 12:12:05 -0800 Subject: [PATCH 0448/1490] Enhance --early-output format This makes --early-output a bit more advanced, and actually makes it generate multiple "Final output:" headers as it updates things asynchronously. I realize that the "Final output:" line is now illogical, since it's not really final until it also says "done", but It now _always_ generates a "Final output:" header in front of any commit list, and that output header gives you a *guess* at the maximum number of commits available. However, it should be noted that the guess can be completely off: I do a reasonable job estimating it, but it is not meant to be exact. So what happens is that you may get output like this: - at 0.1 seconds: Final output: 2 incomplete .. 2 commits listed .. - half a second later: Final output: 33 incomplete .. 33 commits listed .. - another half a second after that: Final output: 71 incomplete .. 71 commits listed .. - another half second later: Final output: 136 incomplete .. 100 commits listed: we hit the --early-output limit, and .. will only output 100 commits, and after this you'll not .. see an "incomplete" report any more since you got as much .. early output as you asked for! - .. and then finally: Final output: 73106 done .. all the commits .. The above is a real-life scenario on my current kernel tree after having flushed all the caches. Tested with the experimental gitk patch that Paul sent out, and by looking at the actual log output (and verifying that my commit count guesses actually match real life fairly well). Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- builtin-log.c | 88 +++++++++++++++++++++++++++++++++++++++++++-------- revision.c | 63 ++++++++++++++++++++---------------- revision.h | 8 +++++ 3 files changed, 119 insertions(+), 40 deletions(-) diff --git a/builtin-log.c b/builtin-log.c index 4e9d0cb69c..981f38872c 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -77,17 +77,85 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix, } } +/* + * This gives a rough estimate for how many commits we + * will print out in the list. + */ +static int estimate_commit_count(struct rev_info *rev, struct commit_list *list) +{ + int n = 0; + + while (list) { + struct commit *commit = list->item; + unsigned int flags = commit->object.flags; + + list = list->next; + if (flags & UNINTERESTING) + continue; + if (rev->prune_fn && rev->dense && !(flags & TREECHANGE)) { + if (commit->parents && !commit->parents->next) + continue; + } + n++; + } + return n; +} + +static void show_early_header(struct rev_info *rev, const char *stage, int nr) +{ + if (rev->shown_one) { + rev->shown_one = 0; + if (rev->commit_format != CMIT_FMT_ONELINE) + putchar(rev->diffopt.line_termination); + } + printf("Final output: %d %s\n", nr, stage); +} + +struct itimerval early_output_timer; + static void log_show_early(struct rev_info *revs, struct commit_list *list) { int i = revs->early_output; + int show_header = 1; sort_in_topological_order(&list, revs->lifo); while (list && i) { struct commit *commit = list->item; - log_tree_commit(revs, commit); + switch (simplify_commit(revs, commit)) { + case commit_show: + if (show_header) { + int n = estimate_commit_count(revs, list); + show_early_header(revs, "incomplete", n); + show_header = 0; + } + log_tree_commit(revs, commit); + i--; + break; + case commit_ignore: + break; + case commit_error: + return; + } list = list->next; - i--; } + + /* Did we already get enough commits for the early output? */ + if (!i) + return; + + /* + * ..if no, then repeat it twice a second until we + * do. + * + * NOTE! We don't use "it_interval", because if the + * reader isn't listening, we want our output to be + * throttled by the writing, and not have the timer + * trigger every second even if we're blocked on a + * reader! + */ + early_output_timer.it_value.tv_sec = 0; + early_output_timer.it_value.tv_usec = 500000; + setitimer(ITIMER_REAL, &early_output_timer, NULL); } static void early_output(int signal) @@ -98,7 +166,6 @@ static void early_output(int signal) static void setup_early_output(struct rev_info *rev) { struct sigaction sa; - struct itimerval v; /* * Set up the signal handler, minimally intrusively: @@ -120,21 +187,16 @@ static void setup_early_output(struct rev_info *rev) * * This is a one-time-only trigger. */ - memset(&v, 0, sizeof(v)); - v.it_value.tv_sec = 0; - v.it_value.tv_usec = 100000; - setitimer(ITIMER_REAL, &v, NULL); + early_output_timer.it_value.tv_sec = 0; + early_output_timer.it_value.tv_usec = 100000; + setitimer(ITIMER_REAL, &early_output_timer, NULL); } static void finish_early_output(struct rev_info *rev) { + int n = estimate_commit_count(rev, rev->commits); signal(SIGALRM, SIG_IGN); - if (rev->shown_one) { - rev->shown_one = 0; - if (rev->commit_format != CMIT_FMT_ONELINE) - putchar(rev->diffopt.line_termination); - } - printf("Final output:\n"); + show_early_header(rev, "done", n); } static int cmd_log_walk(struct rev_info *rev) diff --git a/revision.c b/revision.c index 26610bb42d..2e6121fa1b 100644 --- a/revision.c +++ b/revision.c @@ -1398,6 +1398,36 @@ static int commit_match(struct commit *commit, struct rev_info *opt) commit->buffer, strlen(commit->buffer)); } +enum commit_action simplify_commit(struct rev_info *revs, struct commit *commit) +{ + if (commit->object.flags & SHOWN) + return commit_ignore; + if (revs->unpacked && has_sha1_pack(commit->object.sha1, revs->ignore_packed)) + return commit_ignore; + if (commit->object.flags & UNINTERESTING) + return commit_ignore; + if (revs->min_age != -1 && (commit->date > revs->min_age)) + return commit_ignore; + if (revs->no_merges && commit->parents && commit->parents->next) + return commit_ignore; + if (!commit_match(commit, revs)) + return commit_ignore; + if (revs->prune_fn && revs->dense) { + /* Commit without changes? */ + if (!(commit->object.flags & TREECHANGE)) { + /* drop merges unless we want parenthood */ + if (!revs->parents) + return commit_ignore; + /* non-merge - always ignore it */ + if (!commit->parents || !commit->parents->next) + return commit_ignore; + } + if (revs->parents && rewrite_parents(revs, commit) < 0) + return commit_error; + } + return commit_show; +} + static struct commit *get_revision_1(struct rev_info *revs) { if (!revs->commits) @@ -1425,36 +1455,15 @@ static struct commit *get_revision_1(struct rev_info *revs) if (add_parents_to_list(revs, commit, &revs->commits) < 0) return NULL; } - if (commit->object.flags & SHOWN) - continue; - if (revs->unpacked && has_sha1_pack(commit->object.sha1, - revs->ignore_packed)) - continue; - - if (commit->object.flags & UNINTERESTING) + switch (simplify_commit(revs, commit)) { + case commit_ignore: continue; - if (revs->min_age != -1 && (commit->date > revs->min_age)) - continue; - if (revs->no_merges && - commit->parents && commit->parents->next) - continue; - if (!commit_match(commit, revs)) - continue; - if (revs->prune_fn && revs->dense) { - /* Commit without changes? */ - if (!(commit->object.flags & TREECHANGE)) { - /* drop merges unless we want parenthood */ - if (!revs->parents) - continue; - /* non-merge - always ignore it */ - if (!commit->parents || !commit->parents->next) - continue; - } - if (revs->parents && rewrite_parents(revs, commit) < 0) - return NULL; + case commit_error: + return NULL; + default: + return commit; } - return commit; } while (revs->commits); return NULL; } diff --git a/revision.h b/revision.h index d8a5a5021f..2232247be4 100644 --- a/revision.h +++ b/revision.h @@ -133,4 +133,12 @@ extern void add_object(struct object *obj, extern void add_pending_object(struct rev_info *revs, struct object *obj, const char *name); +enum commit_action { + commit_ignore, + commit_show, + commit_error +}; + +extern enum commit_action simplify_commit(struct rev_info *revs, struct commit *commit); + #endif From 9f12bec4386fc96e5b617268822cbb75e4c76101 Mon Sep 17 00:00:00 2001 From: Brian Gernhardt Date: Sun, 4 Nov 2007 10:31:26 -0500 Subject: [PATCH 0449/1490] t3502: Disambiguate between file and rev by adding -- On a case insensitive file system, this test fails because git-diff doesn't know if it is asking for the file "A" or the tag "a". Adding "--" at the end of the ambiguous commands allows the test to finish properly. Signed-off-by: Brian Gernhardt Signed-off-by: Junio C Hamano --- t/t3502-cherry-pick-merge.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/t/t3502-cherry-pick-merge.sh b/t/t3502-cherry-pick-merge.sh index 3274c6141b..7c92e261fc 100755 --- a/t/t3502-cherry-pick-merge.sh +++ b/t/t3502-cherry-pick-merge.sh @@ -36,7 +36,7 @@ test_expect_success 'cherry-pick a non-merge with -m should fail' ' git reset --hard && git checkout a^0 && ! git cherry-pick -m 1 b && - git diff --exit-code a + git diff --exit-code a -- ' @@ -45,7 +45,7 @@ test_expect_success 'cherry pick a merge without -m should fail' ' git reset --hard && git checkout a^0 && ! git cherry-pick c && - git diff --exit-code a + git diff --exit-code a -- ' @@ -98,7 +98,7 @@ test_expect_success 'revert a merge (1)' ' git reset --hard && git checkout c^0 && git revert -m 1 c && - git diff --exit-code a + git diff --exit-code a -- ' @@ -107,7 +107,7 @@ test_expect_success 'revert a merge (2)' ' git reset --hard && git checkout c^0 && git revert -m 2 c && - git diff --exit-code b + git diff --exit-code b -- ' From 0aab4abdd4e6461d61ce6cf1392e1d31c4d1573a Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 5 Nov 2007 16:39:00 -0800 Subject: [PATCH 0450/1490] gc: --prune prunes unreferenced objects. Brandon Casey correctly points out that we repack with -A without --prune and with -a with --prune, so it is not just unreferenced loose objects that are pruned away when the option is given. Signed-off-by: Junio C Hamano --- builtin-gc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin-gc.c b/builtin-gc.c index c5bce893a6..799c263936 100644 --- a/builtin-gc.c +++ b/builtin-gc.c @@ -175,7 +175,7 @@ int cmd_gc(int argc, const char **argv, const char *prefix) char buf[80]; struct option builtin_gc_options[] = { - OPT_BOOLEAN(0, "prune", &prune, "prune unreferenced loose objects"), + OPT_BOOLEAN(0, "prune", &prune, "prune unreferenced objects"), OPT_BOOLEAN(0, "aggressive", &aggressive, "be more thorough (increased runtime)"), OPT_BOOLEAN(0, "auto", &auto_gc, "enable auto-gc mode"), OPT_END() From 53b2c823f6e862e0c83a4a25bab43e8c32e9c289 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 5 Nov 2007 13:22:34 -0800 Subject: [PATCH 0451/1490] revision walker: mini clean-up This removes the unnecessary indirection of "revs->prune_fn", since that function is always the same one (or NULL), and there is in fact not even an abstraction reason to make it a function (i.e. its not called from some other file and doesn't allow us to keep the function itself static or anything like that). It then just replaces it with a bit that says "prune or not", and if not pruning, every commit gets TREECHANGE. That in turn means that - if (!revs->prune_fn || (flags & TREECHANGE)) - if (revs->prune_fn && !(flags & TREECHANGE)) just become - if (flags & TREECHANGE) - if (!(flags & TREECHANGE)) respectively. Together with adding the "single_parent()" helper function, the "complex" conditional now becomes if (!(flags & TREECHANGE) && rev->dense && single_parent(commit)) continue; Also indirection of "revs->dense" checking is thrown away the same way, because TREECHANGE bit is set appropriately now. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- builtin-log.c | 10 ++-------- builtin-rev-list.c | 14 +++++++------- commit.h | 5 +++++ revision.c | 27 ++++++++++++++++++++------- revision.h | 5 +---- 5 files changed, 35 insertions(+), 26 deletions(-) diff --git a/builtin-log.c b/builtin-log.c index 981f38872c..d6845bc7f8 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -88,15 +88,9 @@ static int estimate_commit_count(struct rev_info *rev, struct commit_list *list) while (list) { struct commit *commit = list->item; unsigned int flags = commit->object.flags; - list = list->next; - if (flags & UNINTERESTING) - continue; - if (rev->prune_fn && rev->dense && !(flags & TREECHANGE)) { - if (commit->parents && !commit->parents->next) - continue; - } - n++; + if ((flags & TREECHANGE) && !(flags & UNINTERESTING)) + n++; } return n; } diff --git a/builtin-rev-list.c b/builtin-rev-list.c index 697046723f..2dec8873f8 100644 --- a/builtin-rev-list.c +++ b/builtin-rev-list.c @@ -142,7 +142,7 @@ static int count_distance(struct commit_list *entry) if (commit->object.flags & (UNINTERESTING | COUNTED)) break; - if (!revs.prune_fn || (commit->object.flags & TREECHANGE)) + if (commit->object.flags & TREECHANGE) nr++; commit->object.flags |= COUNTED; p = commit->parents; @@ -198,7 +198,7 @@ static inline int halfway(struct commit_list *p, int nr) /* * Don't short-cut something we are not going to return! */ - if (revs.prune_fn && !(p->item->object.flags & TREECHANGE)) + if (!(p->item->object.flags & TREECHANGE)) return 0; if (DEBUG_BISECT) return 0; @@ -268,7 +268,7 @@ static struct commit_list *best_bisection(struct commit_list *list, int nr) int distance; unsigned flags = p->item->object.flags; - if (revs.prune_fn && !(flags & TREECHANGE)) + if (!(flags & TREECHANGE)) continue; distance = weight(p); if (nr - distance < distance) @@ -308,7 +308,7 @@ static struct commit_list *best_bisection_sorted(struct commit_list *list, int n int distance; unsigned flags = p->item->object.flags; - if (revs.prune_fn && !(flags & TREECHANGE)) + if (!(flags & TREECHANGE)) continue; distance = weight(p); if (nr - distance < distance) @@ -362,7 +362,7 @@ static struct commit_list *do_find_bisection(struct commit_list *list, p->item->util = &weights[n++]; switch (count_interesting_parents(commit)) { case 0: - if (!revs.prune_fn || (flags & TREECHANGE)) { + if (flags & TREECHANGE) { weight_set(p, 1); counted++; show_list("bisection 2 count one", @@ -435,7 +435,7 @@ static struct commit_list *do_find_bisection(struct commit_list *list, * add one for p itself if p is to be counted, * otherwise inherit it from q directly. */ - if (!revs.prune_fn || (flags & TREECHANGE)) { + if (flags & TREECHANGE) { weight_set(p, weight(q)+1); counted++; show_list("bisection 2 count one", @@ -482,7 +482,7 @@ static struct commit_list *find_bisection(struct commit_list *list, continue; p->next = last; last = p; - if (!revs.prune_fn || (flags & TREECHANGE)) + if (flags & TREECHANGE) nr++; on_list++; } diff --git a/commit.h b/commit.h index 4ed0c1cf7f..aa679867a9 100644 --- a/commit.h +++ b/commit.h @@ -117,4 +117,9 @@ extern int interactive_add(void); extern void add_files_to_cache(int verbose, const char *prefix, const char **files); extern int rerere(void); +static inline int single_parent(struct commit *commit) +{ + return commit->parents && !commit->parents->next; +} + #endif /* COMMIT_H */ diff --git a/revision.c b/revision.c index 2e6121fa1b..931f978af9 100644 --- a/revision.c +++ b/revision.c @@ -308,6 +308,14 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit) struct commit_list **pp, *parent; int tree_changed = 0, tree_same = 0; + /* + * If we don't do pruning, everything is interesting + */ + if (!revs->prune) { + commit->object.flags |= TREECHANGE; + return; + } + if (!commit->tree) return; @@ -317,6 +325,15 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit) return; } + /* + * Normal non-merge commit? If we don't want to make the + * history dense, we consider it always to be a change.. + */ + if (!revs->dense && !commit->parents->next) { + commit->object.flags |= TREECHANGE; + return; + } + pp = &commit->parents; while ((parent = *pp) != NULL) { struct commit *p = parent->item; @@ -415,8 +432,7 @@ static int add_parents_to_list(struct rev_info *revs, struct commit *commit, str * simplify the commit history and find the parent * that has no differences in the path set if one exists. */ - if (revs->prune_fn) - revs->prune_fn(revs, commit); + try_to_simplify_commit(revs, commit); if (revs->no_walk) return 0; @@ -684,9 +700,6 @@ void init_revisions(struct rev_info *revs, const char *prefix) revs->skip_count = -1; revs->max_count = -1; - revs->prune_fn = NULL; - revs->prune_data = NULL; - revs->commit_format = CMIT_FMT_DEFAULT; diff_setup(&revs->diffopt); @@ -1271,7 +1284,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch diff_tree_setup_paths(revs->prune_data, &revs->pruning); /* Can't prune commits with rename following: the paths change.. */ if (!revs->diffopt.follow_renames) - revs->prune_fn = try_to_simplify_commit; + revs->prune = 1; if (!revs->full_diff) diff_tree_setup_paths(revs->prune_data, &revs->diffopt); } @@ -1412,7 +1425,7 @@ enum commit_action simplify_commit(struct rev_info *revs, struct commit *commit) return commit_ignore; if (!commit_match(commit, revs)) return commit_ignore; - if (revs->prune_fn && revs->dense) { + if (revs->prune && revs->dense) { /* Commit without changes? */ if (!(commit->object.flags & TREECHANGE)) { /* drop merges unless we want parenthood */ diff --git a/revision.h b/revision.h index 2232247be4..a79851449c 100644 --- a/revision.h +++ b/revision.h @@ -15,8 +15,6 @@ struct rev_info; struct log_info; -typedef void (prune_fn_t)(struct rev_info *revs, struct commit *commit); - struct rev_info { /* Starting list */ struct commit_list *commits; @@ -28,12 +26,11 @@ struct rev_info { /* Basic information */ const char *prefix; void *prune_data; - prune_fn_t *prune_fn; - unsigned int early_output; /* Traversal flags */ unsigned int dense:1, + prune:1, no_merges:1, no_walk:1, remove_empty_trees:1, From c67359be45be74e1056d6293c6bb09ee6d00a54a Mon Sep 17 00:00:00 2001 From: Gerrit Pape Date: Mon, 5 Nov 2007 09:16:22 +0000 Subject: [PATCH 0452/1490] git-daemon: fix remote port number in log entry The port number in struct sockaddr_in needs to be converted from network byte order to host byte order (on some architectures). Signed-off-by: Gerrit Pape Signed-off-by: Junio C Hamano --- daemon.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/daemon.c b/daemon.c index 660e1552d4..b8df980dc5 100644 --- a/daemon.c +++ b/daemon.c @@ -540,7 +540,7 @@ static int execute(struct sockaddr *addr) if (addr->sa_family == AF_INET) { struct sockaddr_in *sin_addr = (void *) addr; inet_ntop(addr->sa_family, &sin_addr->sin_addr, addrbuf, sizeof(addrbuf)); - port = sin_addr->sin_port; + port = ntohs(sin_addr->sin_port); #ifndef NO_IPV6 } else if (addr && addr->sa_family == AF_INET6) { struct sockaddr_in6 *sin6_addr = (void *) addr; @@ -550,7 +550,7 @@ static int execute(struct sockaddr *addr) inet_ntop(AF_INET6, &sin6_addr->sin6_addr, buf, sizeof(addrbuf) - 1); strcat(buf, "]"); - port = sin6_addr->sin6_port; + port = ntohs(sin6_addr->sin6_port); #endif } loginfo("Connection from %s:%d", addrbuf, port); From 9b3beb581216fc89972e926574b9d3b243d5e4f4 Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Mon, 5 Nov 2007 13:03:22 +0100 Subject: [PATCH 0453/1490] Some better parse-options documentation. Signed-off-by: Junio C Hamano --- parse-options.h | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/parse-options.h b/parse-options.h index 3a470e5eb8..65bce6eafd 100644 --- a/parse-options.h +++ b/parse-options.h @@ -22,6 +22,41 @@ enum parse_opt_option_flags { struct option; typedef int parse_opt_cb(const struct option *, const char *arg, int unset); +/* + * `type`:: + * holds the type of the option, you must have an OPTION_END last in your + * array. + * + * `short_name`:: + * the character to use as a short option name, '\0' if none. + * + * `long_name`:: + * the long option name, without the leading dashes, NULL if none. + * + * `value`:: + * stores pointers to the values to be filled. + * + * `argh`:: + * token to explain the kind of argument this option wants. Keep it + * homogenous across the repository. + * + * `help`:: + * the short help associated to what the option does. + * Must never be NULL (except for OPTION_END). + * OPTION_GROUP uses this pointer to store the group header. + * + * `flags`:: + * mask of parse_opt_option_flags. + * PARSE_OPT_OPTARG: says that the argument is optionnal (not for BOOLEANs) + * PARSE_OPT_NOARG: says that this option takes no argument, for CALLBACKs + * + * `callback`:: + * pointer to the callback to use for OPTION_CALLBACK. + * + * `defval`:: + * default value to fill (*->value) with for PARSE_OPT_OPTARG. + * CALLBACKS can use it like they want. + */ struct option { enum parse_opt_type type; int short_name; @@ -32,8 +67,6 @@ struct option { int flags; parse_opt_cb *callback; - /* holds default value for PARSE_OPT_OPTARG, - though callbacks can use it like they want */ intptr_t defval; }; From 6eea60f85e92901cfe6ad7ab75e4a070215aedf7 Mon Sep 17 00:00:00 2001 From: David Symonds Date: Tue, 6 Nov 2007 10:04:24 +1100 Subject: [PATCH 0454/1490] Rearrange git-format-patch synopsis to improve clarity. Signed-off-by: David Symonds Signed-off-by: Junio C Hamano --- Documentation/git-format-patch.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt index 92c0ab63b2..9d4bae2f60 100644 --- a/Documentation/git-format-patch.txt +++ b/Documentation/git-format-patch.txt @@ -9,9 +9,10 @@ git-format-patch - Prepare patches for e-mail submission SYNOPSIS -------- [verse] -'git-format-patch' [-n | -N | -k] [-o | --stdout] [--thread] +'git-format-patch' [-k] [-o | --stdout] [--thread] [--attach[=] | --inline[=]] [-s | --signoff] [] + [-n | --numbered | -N | --no-numbered] [--start-number ] [--numbered-files] [--in-reply-to=Message-Id] [--suffix=.] [--ignore-if-in-upstream] From b67a43bb8f4a8ffb64f26b7351c3b0b90239696a Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 5 Nov 2007 17:16:47 -0800 Subject: [PATCH 0455/1490] grep with unmerged index We called flush_grep() every time we saw an unmerged entry in the index. If we happen to find an unmerged entry before we saw more than two paths, we incorrectly declared that the user had too many non-paths options in front. Signed-off-by: Junio C Hamano --- builtin-grep.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin-grep.c b/builtin-grep.c index c7b45c4d58..185876b0a6 100644 --- a/builtin-grep.c +++ b/builtin-grep.c @@ -343,7 +343,7 @@ static int external_grep(struct grep_opt *opt, const char **paths, int cached) memcpy(name + 2, ce->name, len + 1); } argv[argc++] = name; - if (argc < MAXARGS && !ce_stage(ce)) + if (argc < MAXARGS) continue; status = flush_grep(opt, argc, nr, argv, &kept); if (0 < status) From d8e21ba8967f43b61fc2fd50dd749ff8f0c6592a Mon Sep 17 00:00:00 2001 From: Marco Costalba Date: Sun, 4 Nov 2007 15:35:26 +0100 Subject: [PATCH 0456/1490] Remove a couple of duplicated include Signed-off-by: Marco Costalba Signed-off-by: Junio C Hamano --- compat/inet_ntop.c | 1 - compat/inet_pton.c | 1 - 2 files changed, 2 deletions(-) diff --git a/compat/inet_ntop.c b/compat/inet_ntop.c index 4d7ab9d975..f44498258d 100644 --- a/compat/inet_ntop.c +++ b/compat/inet_ntop.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include diff --git a/compat/inet_pton.c b/compat/inet_pton.c index 5704e0d2b6..4078fc0877 100644 --- a/compat/inet_pton.c +++ b/compat/inet_pton.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include From a1f611d5d03d7849f4d7f47f5bd39b5c44808bb5 Mon Sep 17 00:00:00 2001 From: Steffen Prohaska Date: Sun, 4 Nov 2007 09:02:21 +0100 Subject: [PATCH 0457/1490] Fix comment in strbuf.h to use correct name strbuf_avail() Signed-off-by: Steffen Prohaska Signed-off-by: Junio C Hamano --- strbuf.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/strbuf.h b/strbuf.h index 9b9e861d3d..cd7f295b65 100644 --- a/strbuf.h +++ b/strbuf.h @@ -23,12 +23,12 @@ * that way: * * strbuf_grow(sb, SOME_SIZE); - * // ... here the memory areay starting at sb->buf, and of length - * // sb_avail(sb) is all yours, and you are sure that sb_avail(sb) is at - * // least SOME_SIZE + * ... Here, the memory array starting at sb->buf, and of length + * ... strbuf_avail(sb) is all yours, and you are sure that + * ... strbuf_avail(sb) is at least SOME_SIZE. * strbuf_setlen(sb, sb->len + SOME_OTHER_SIZE); * - * Of course, SOME_OTHER_SIZE must be smaller or equal to sb_avail(sb). + * Of course, SOME_OTHER_SIZE must be smaller or equal to strbuf_avail(sb). * * Doing so is safe, though if it has to be done in many places, adding the * missing API to the strbuf module is the way to go. From 34cb704a9b8b45ff3e1342678c5892e1ee6e27f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Steinbrink?= Date: Mon, 5 Nov 2007 20:36:33 +0100 Subject: [PATCH 0458/1490] git-commit.sh: Fix usage checks regarding paths given when they do not make sense MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The checks that looked for paths given to git-commit in addition to --all or --interactive expected only 3 values, while the case statement actually provides 4, so the check was never triggered. The bug was introduced in 6cbf07efc5702351897dee4742525c9b9f7828ac when the case statement was extended to handle --interactive. Signed-off-by: Björn Steinbrink Signed-off-by: Junio C Hamano --- git-commit.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/git-commit.sh b/git-commit.sh index ab43217be4..5e3908f2cb 100755 --- a/git-commit.sh +++ b/git-commit.sh @@ -322,9 +322,9 @@ unset only case "$all,$interactive,$also,$#" in *t,*t,*) die "Cannot use -a, --interactive or -i at the same time." ;; -t,,[1-9]*) +t,,,[1-9]*) die "Paths with -a does not make sense." ;; -,t,[1-9]*) +,t,,[1-9]*) die "Paths with --interactive does not make sense." ;; ,,t,0) die "No paths with -i does not make sense." ;; From 243e0614e0f8783599b20106b50eee56d0a17332 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Mon, 5 Nov 2007 13:15:21 +0000 Subject: [PATCH 0459/1490] parse-options: abbreviation engine fix. When an option could be an ambiguous abbreviation of two options, the code used to error out. Even if an exact match would have occured later. Test and original patch by Pierre Habouzit. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- parse-options.c | 33 +++++++++++++++++++++------------ t/t0040-parse-options.sh | 13 +++++++++++++ test-parse-options.c | 1 + 3 files changed, 35 insertions(+), 12 deletions(-) diff --git a/parse-options.c b/parse-options.c index cc09c98ec3..15b32f741b 100644 --- a/parse-options.c +++ b/parse-options.c @@ -119,8 +119,8 @@ static int parse_long_opt(struct optparse_t *p, const char *arg, const struct option *options) { const char *arg_end = strchr(arg, '='); - const struct option *abbrev_option = NULL; - int abbrev_flags = 0; + const struct option *abbrev_option = NULL, *ambiguous_option = NULL; + int abbrev_flags = 0, ambiguous_flags = 0; if (!arg_end) arg_end = arg + strlen(arg); @@ -137,16 +137,16 @@ static int parse_long_opt(struct optparse_t *p, const char *arg, /* abbreviated? */ if (!strncmp(options->long_name, arg, arg_end - arg)) { is_abbreviated: - if (abbrev_option) - return error("Ambiguous option: %s " - "(could be --%s%s or --%s%s)", - arg, - (flags & OPT_UNSET) ? - "no-" : "", - options->long_name, - (abbrev_flags & OPT_UNSET) ? - "no-" : "", - abbrev_option->long_name); + if (abbrev_option) { + /* + * If this is abbreviated, it is + * ambiguous. So when there is no + * exact match later, we need to + * error out. + */ + ambiguous_option = abbrev_option; + ambiguous_flags = abbrev_flags; + } if (!(flags & OPT_UNSET) && *arg_end) p->opt = arg_end + 1; abbrev_option = options; @@ -176,6 +176,15 @@ static int parse_long_opt(struct optparse_t *p, const char *arg, } return get_value(p, options, flags); } + + if (ambiguous_option) + return error("Ambiguous option: %s " + "(could be --%s%s or --%s%s)", + arg, + (ambiguous_flags & OPT_UNSET) ? "no-" : "", + ambiguous_option->long_name, + (abbrev_flags & OPT_UNSET) ? "no-" : "", + abbrev_option->long_name); if (abbrev_option) return get_value(p, abbrev_option, abbrev_flags); return error("unknown option `%s'", arg); diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh index ae49424aa0..462fdf262f 100755 --- a/t/t0040-parse-options.sh +++ b/t/t0040-parse-options.sh @@ -18,6 +18,7 @@ string options -s, --string get a string --string2 get another string + --st get another string (pervert ordering) EOF @@ -90,4 +91,16 @@ test_expect_failure 'ambiguously abbreviated option' ' test $? != 129 ' +cat > expect << EOF +boolean: 0 +integer: 0 +string: 123 +EOF + +test_expect_success 'non ambiguous option (after two options it abbreviates)' ' + test-parse-options --st 123 > output 2> output.err && + test ! -s output.err && + git diff expect output +' + test_done diff --git a/test-parse-options.c b/test-parse-options.c index 277cfe4d6d..4d3e2ec39e 100644 --- a/test-parse-options.c +++ b/test-parse-options.c @@ -18,6 +18,7 @@ int main(int argc, const char **argv) OPT_GROUP("string options"), OPT_STRING('s', "string", &string, "string", "get a string"), OPT_STRING(0, "string2", &string, "str", "get another string"), + OPT_STRING(0, "st", &string, "st", "get another string (pervert ordering)"), OPT_END(), }; int i; From cdf4a751fa728273030651a769f9f45212ff50c9 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sat, 3 Nov 2007 14:33:01 +0000 Subject: [PATCH 0460/1490] builtin-reset: do not call "ls-files --unmerged" Since reset is a builtin now, it can use the full power of libgit.a and check for unmerged entries itself. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- builtin-reset.c | 28 ++++++++-------------------- t/t7102-reset.sh | 9 +++++++++ 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/builtin-reset.c b/builtin-reset.c index 5467e36c73..79792eebf2 100644 --- a/builtin-reset.c +++ b/builtin-reset.c @@ -46,26 +46,14 @@ static inline int is_merge(void) static int unmerged_files(void) { - char b; - ssize_t len; - struct child_process cmd; - const char *argv_ls_files[] = {"ls-files", "--unmerged", NULL}; - - memset(&cmd, 0, sizeof(cmd)); - cmd.argv = argv_ls_files; - cmd.git_cmd = 1; - cmd.out = -1; - - if (start_command(&cmd)) - die("Could not run sub-command: git ls-files"); - - len = xread(cmd.out, &b, 1); - if (len < 0) - die("Could not read output from git ls-files: %s", - strerror(errno)); - finish_command(&cmd); - - return len; + int i; + read_cache(); + for (i = 0; i < active_nr; i++) { + struct cache_entry *ce = active_cache[i]; + if (ce_stage(ce)) + return 1; + } + return 0; } static int reset_index_file(const unsigned char *sha1, int is_hard_reset) diff --git a/t/t7102-reset.sh b/t/t7102-reset.sh index cea9afb764..506767d2d7 100755 --- a/t/t7102-reset.sh +++ b/t/t7102-reset.sh @@ -59,6 +59,15 @@ test_expect_success 'giving a non existing revision should fail' ' check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc ' +test_expect_success 'reset --soft with unmerged index should fail' ' + touch .git/MERGE_HEAD && + echo "100644 44c5b5884550c17758737edcced463447b91d42b 1 un" | + git update-index --index-info && + ! git reset --soft HEAD && + rm .git/MERGE_HEAD && + git rm --cached -- un +' + test_expect_success \ 'giving paths with options different than --mixed should fail' ' ! git reset --soft -- first && From 620a6cd42ed5ea94684b22714181bf03871733dd Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sat, 3 Nov 2007 15:21:21 +0000 Subject: [PATCH 0461/1490] builtin-reset: avoid forking "update-index --refresh" Instead of forking update-index, call refresh_cache() directly. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- builtin-reset.c | 53 ++++++++++++++++++++++++++---------------------- t/t7102-reset.sh | 10 +++++++++ 2 files changed, 39 insertions(+), 24 deletions(-) diff --git a/builtin-reset.c b/builtin-reset.c index 79792eebf2..44582f23a2 100644 --- a/builtin-reset.c +++ b/builtin-reset.c @@ -95,26 +95,34 @@ static void print_new_head_line(struct commit *commit) printf("\n"); } -static int update_index_refresh(void) +static int update_index_refresh(int fd, struct lock_file *index_lock) { - const char *argv_update_index[] = {"update-index", "--refresh", NULL}; - return run_command_v_opt(argv_update_index, RUN_GIT_CMD); -} + int result; -struct update_cb_data { - int index_fd; - struct lock_file *lock; - int exit_code; -}; + if (!index_lock) { + index_lock = xcalloc(1, sizeof(struct lock_file)); + fd = hold_locked_index(index_lock, 1); + } + + if (read_cache() < 0) + return error("Could not read index"); + result = refresh_cache(0) ? 1 : 0; + if (write_cache(fd, active_cache, active_nr) || + close(fd) || + commit_locked_index(index_lock)) + return error ("Could not refresh index"); + return result; +} static void update_index_from_diff(struct diff_queue_struct *q, struct diff_options *opt, void *data) { int i; - struct update_cb_data *cb = data; + int *discard_flag = data; /* do_diff_cache() mangled the index */ discard_cache(); + *discard_flag = 1; read_cache(); for (i = 0; i < q->nr; i++) { @@ -128,34 +136,33 @@ static void update_index_from_diff(struct diff_queue_struct *q, } else remove_file_from_cache(one->path); } - - cb->exit_code = write_cache(cb->index_fd, active_cache, active_nr) || - close(cb->index_fd) || - commit_locked_index(cb->lock); } static int read_from_tree(const char *prefix, const char **argv, unsigned char *tree_sha1) { + struct lock_file *lock = xcalloc(1, sizeof(struct lock_file)); + int index_fd, index_was_discarded = 0; struct diff_options opt; - struct update_cb_data cb; memset(&opt, 0, sizeof(opt)); diff_tree_setup_paths(get_pathspec(prefix, (const char **)argv), &opt); opt.output_format = DIFF_FORMAT_CALLBACK; opt.format_callback = update_index_from_diff; - opt.format_callback_data = &cb; + opt.format_callback_data = &index_was_discarded; - cb.lock = xcalloc(1, sizeof(struct lock_file)); - cb.index_fd = hold_locked_index(cb.lock, 1); - cb.exit_code = 0; + index_fd = hold_locked_index(lock, 1); + index_was_discarded = 0; read_cache(); if (do_diff_cache(tree_sha1, &opt)) return 1; diffcore_std(&opt); diff_flush(&opt); - return cb.exit_code; + if (!index_was_discarded) + /* The index is still clobbered from do_diff_cache() */ + discard_cache(); + return update_index_refresh(index_fd, lock); } static void prepend_reflog_action(const char *action, char *buf, size_t size) @@ -225,9 +232,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix) else if (reset_type != NONE) die("Cannot do %s reset with paths.", reset_type_names[reset_type]); - if (read_from_tree(prefix, argv + i, sha1)) - return 1; - return update_index_refresh() ? 1 : 0; + return read_from_tree(prefix, argv + i, sha1); } if (reset_type == NONE) reset_type = MIXED; /* by default */ @@ -264,7 +269,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix) case SOFT: /* Nothing else to do. */ break; case MIXED: /* Report what has not been updated. */ - update_index_refresh(); + update_index_refresh(0, NULL); break; } diff --git a/t/t7102-reset.sh b/t/t7102-reset.sh index 506767d2d7..e5c9f30c73 100755 --- a/t/t7102-reset.sh +++ b/t/t7102-reset.sh @@ -418,4 +418,14 @@ test_expect_success 'resetting an unmodified path is a no-op' ' git diff-index --cached --exit-code HEAD ' +cat > expect << EOF +file2: needs update +EOF + +test_expect_success '--mixed refreshes the index' ' + echo 123 >> file2 && + git reset --mixed HEAD > output && + git diff --exit-code expect output +' + test_done From 4c324c00501c2da41987498f8c966b022306b244 Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Sun, 4 Nov 2007 20:46:48 +0100 Subject: [PATCH 0462/1490] upload-pack: Use finish_{command,async}() instead of waitpid(). upload-pack spawns two processes, rev-list and pack-objects, and carefully monitors their status so that it can report failure to the remote end. This change removes the complicated procedures on the grounds of the following observations: - If everything is OK, rev-list closes its output pipe end, upon which pack-objects (which reads from the pipe) sees EOF and terminates itself, closing its output (and error) pipes. upload-pack reads from both until it sees EOF in both. It collects the exit codes of the child processes (which indicate success) and terminates successfully. - If rev-list sees an error, it closes its output and terminates with failure. pack-objects sees EOF in its input and terminates successfully. Again upload-pack reads its inputs until EOF. When it now collects the exit codes of its child processes, it notices the failure of rev-list and signals failure to the remote end. - If pack-objects sees an error, it terminates with failure. Since this breaks the pipe to rev-list, rev-list is killed with SIGPIPE. upload-pack reads its input until EOF, then collects the exit codes of the child processes, notices their failures, and signals failure to the remote end. - If upload-pack itself dies unexpectedly, pack-objects is killed with SIGPIPE, and subsequently also rev-list. The upshot of this is that precise monitoring of child processes is not required because both terminate if either one of them dies unexpectedly. This allows us to use finish_command() and finish_async() instead of an explicit waitpid(2) call. The change is smaller than it looks because most of it only reduces the indentation of a large part of the inner loop. Signed-off-by: Johannes Sixt Signed-off-by: Junio C Hamano --- t/t5530-upload-pack-error.sh | 75 ++++++++++++++ upload-pack.c | 196 ++++++++++++++--------------------- 2 files changed, 154 insertions(+), 117 deletions(-) create mode 100755 t/t5530-upload-pack-error.sh diff --git a/t/t5530-upload-pack-error.sh b/t/t5530-upload-pack-error.sh new file mode 100755 index 0000000000..cc8949e3ef --- /dev/null +++ b/t/t5530-upload-pack-error.sh @@ -0,0 +1,75 @@ +#!/bin/sh + +test_description='errors in upload-pack' + +. ./test-lib.sh + +D=`pwd` + +corrupt_repo () { + object_sha1=$(git rev-parse "$1") && + ob=$(expr "$object_sha1" : "\(..\)") && + ject=$(expr "$object_sha1" : "..\(..*\)") && + rm -f ".git/objects/$ob/$ject" +} + +test_expect_success 'setup and corrupt repository' ' + + echo file >file && + git add file && + git rev-parse :file && + git commit -a -m original && + test_tick && + echo changed >file && + git commit -a -m changed && + corrupt_repo HEAD:file + +' + +test_expect_failure 'fsck fails' ' + + git fsck +' + +test_expect_success 'upload-pack fails due to error in pack-objects' ' + + ! echo "0032want $(git rev-parse HEAD) +00000009done +0000" | git-upload-pack . > /dev/null 2> output.err && + grep "pack-objects died" output.err +' + +test_expect_success 'corrupt repo differently' ' + + git hash-object -w file && + corrupt_repo HEAD^^{tree} + +' + +test_expect_failure 'fsck fails' ' + + git fsck +' +test_expect_success 'upload-pack fails due to error in rev-list' ' + + ! echo "0032want $(git rev-parse HEAD) +00000009done +0000" | git-upload-pack . > /dev/null 2> output.err && + grep "waitpid (async) failed" output.err +' + +test_expect_success 'create empty repository' ' + + mkdir foo && + cd foo && + git init + +' + +test_expect_failure 'fetch fails' ' + + git fetch .. master + +' + +test_done diff --git a/upload-pack.c b/upload-pack.c index 67994680f2..7e04311027 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -144,6 +144,7 @@ static void create_pack_file(void) char abort_msg[] = "aborting due to possible repository " "corruption on the remote side."; int buffered = -1; + ssize_t sz; const char *argv[10]; int arg = 0; @@ -168,22 +169,15 @@ static void create_pack_file(void) pack_objects.git_cmd = 1; pack_objects.argv = argv; - if (start_command(&pack_objects)) { - /* daemon sets things up to ignore TERM */ - kill(rev_list.pid, SIGKILL); + if (start_command(&pack_objects)) die("git-upload-pack: unable to fork git-pack-objects"); - } /* We read from pack_objects.err to capture stderr output for * progress bar, and pack_objects.out to capture the pack data. */ while (1) { - const char *who; struct pollfd pfd[2]; - pid_t pid; - int status; - ssize_t sz; int pe, pu, pollsize; reset_timeout(); @@ -204,123 +198,91 @@ static void create_pack_file(void) pollsize++; } - if (pollsize) { - if (poll(pfd, pollsize, -1) < 0) { - if (errno != EINTR) { - error("poll failed, resuming: %s", - strerror(errno)); - sleep(1); - } - continue; - } - if (0 <= pu && (pfd[pu].revents & (POLLIN|POLLHUP))) { - /* Data ready; we keep the last byte - * to ourselves in case we detect - * broken rev-list, so that we can - * leave the stream corrupted. This - * is unfortunate -- unpack-objects - * would happily accept a valid pack - * data with trailing garbage, so - * appending garbage after we pass all - * the pack data is not good enough to - * signal breakage to downstream. - */ - char *cp = data; - ssize_t outsz = 0; - if (0 <= buffered) { - *cp++ = buffered; - outsz++; - } - sz = xread(pack_objects.out, cp, - sizeof(data) - outsz); - if (0 < sz) - ; - else if (sz == 0) { - close(pack_objects.out); - pack_objects.out = -1; - } - else - goto fail; - sz += outsz; - if (1 < sz) { - buffered = data[sz-1] & 0xFF; - sz--; - } - else - buffered = -1; - sz = send_client_data(1, data, sz); - if (sz < 0) - goto fail; - } - if (0 <= pe && (pfd[pe].revents & (POLLIN|POLLHUP))) { - /* Status ready; we ship that in the side-band - * or dump to the standard error. - */ - sz = xread(pack_objects.err, progress, - sizeof(progress)); - if (0 < sz) - send_client_data(2, progress, sz); - else if (sz == 0) { - close(pack_objects.err); - pack_objects.err = -1; - } - else - goto fail; - } - } + if (!pollsize) + break; - /* See if the children are still there */ - if (rev_list.pid || pack_objects.pid) { - pid = waitpid(-1, &status, WNOHANG); - if (!pid) - continue; - who = ((pid == rev_list.pid) ? "git-rev-list" : - (pid == pack_objects.pid) ? "git-pack-objects" : - NULL); - if (!who) { - if (pid < 0) { - error("git-upload-pack: %s", - strerror(errno)); - goto fail; - } - error("git-upload-pack: we weren't " - "waiting for %d", pid); - continue; + if (poll(pfd, pollsize, -1) < 0) { + if (errno != EINTR) { + error("poll failed, resuming: %s", + strerror(errno)); + sleep(1); } - if (!WIFEXITED(status) || WEXITSTATUS(status) > 0) { - error("git-upload-pack: %s died with error.", - who); - goto fail; - } - if (pid == rev_list.pid) - rev_list.pid = 0; - if (pid == pack_objects.pid) - pack_objects.pid = 0; - if (rev_list.pid || pack_objects.pid) - continue; - } - - /* both died happily */ - if (pollsize) continue; - - /* flush the data */ - if (0 <= buffered) { - data[0] = buffered; - sz = send_client_data(1, data, 1); + } + if (0 <= pu && (pfd[pu].revents & (POLLIN|POLLHUP))) { + /* Data ready; we keep the last byte to ourselves + * in case we detect broken rev-list, so that we + * can leave the stream corrupted. This is + * unfortunate -- unpack-objects would happily + * accept a valid packdata with trailing garbage, + * so appending garbage after we pass all the + * pack data is not good enough to signal + * breakage to downstream. + */ + char *cp = data; + ssize_t outsz = 0; + if (0 <= buffered) { + *cp++ = buffered; + outsz++; + } + sz = xread(pack_objects.out, cp, + sizeof(data) - outsz); + if (0 < sz) + ; + else if (sz == 0) { + close(pack_objects.out); + pack_objects.out = -1; + } + else + goto fail; + sz += outsz; + if (1 < sz) { + buffered = data[sz-1] & 0xFF; + sz--; + } + else + buffered = -1; + sz = send_client_data(1, data, sz); if (sz < 0) goto fail; - fprintf(stderr, "flushed.\n"); } - if (use_sideband) - packet_flush(1); - return; + if (0 <= pe && (pfd[pe].revents & (POLLIN|POLLHUP))) { + /* Status ready; we ship that in the side-band + * or dump to the standard error. + */ + sz = xread(pack_objects.err, progress, + sizeof(progress)); + if (0 < sz) + send_client_data(2, progress, sz); + else if (sz == 0) { + close(pack_objects.err); + pack_objects.err = -1; + } + else + goto fail; + } } + + if (finish_command(&pack_objects)) { + error("git-upload-pack: git-pack-objects died with error."); + goto fail; + } + if (finish_async(&rev_list)) + goto fail; /* error was already reported */ + + /* flush the data */ + if (0 <= buffered) { + data[0] = buffered; + sz = send_client_data(1, data, 1); + if (sz < 0) + goto fail; + fprintf(stderr, "flushed.\n"); + } + if (use_sideband) + packet_flush(1); + return; + fail: - if (pack_objects.pid) - kill(pack_objects.pid, SIGKILL); - if (rev_list.pid) - kill(rev_list.pid, SIGKILL); send_client_data(3, abort_msg, sizeof(abort_msg)); die("git-upload-pack: %s", abort_msg); } From bab8118aff7581364eb5c74472fe7ab4f45f4a12 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Sun, 4 Nov 2007 01:11:14 +0100 Subject: [PATCH 0463/1490] Reuse previous annotation when overwriting a tag When forcing to overwrite an annotated tag, there are good chances one wants to keep the old annotation, or modify it, not start from scratch. This is obviously only triggered for annotated tagging (-a or -s). Signed-off-by: Mike Hommey Signed-off-by: Junio C Hamano --- builtin-tag.c | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/builtin-tag.c b/builtin-tag.c index 66e5a58307..566d123a8d 100644 --- a/builtin-tag.c +++ b/builtin-tag.c @@ -247,9 +247,37 @@ static int git_tag_config(const char *var, const char *value) return git_default_config(var, value); } +static void write_tag_body(int fd, const unsigned char *sha1) +{ + unsigned long size; + enum object_type type; + char *buf, *sp, *eob; + size_t len; + + buf = read_sha1_file(sha1, &type, &size); + if (!buf) + return; + /* skip header */ + sp = strstr(buf, "\n\n"); + + if (!sp || !size || type != OBJ_TAG) { + free(buf); + return; + } + sp += 2; /* skip the 2 LFs */ + eob = strstr(sp, "\n" PGP_SIGNATURE "\n"); + if (eob) + len = eob - sp; + else + len = buf + size - sp; + write_or_die(fd, sp, len); + + free(buf); +} + static void create_tag(const unsigned char *object, const char *tag, struct strbuf *buf, int message, int sign, - unsigned char *result) + unsigned char *prev, unsigned char *result) { enum object_type type; char header_buf[1024]; @@ -282,7 +310,11 @@ static void create_tag(const unsigned char *object, const char *tag, if (fd < 0) die("could not create file '%s': %s", path, strerror(errno)); - write_or_die(fd, tag_template, strlen(tag_template)); + + if (!is_null_sha1(prev)) + write_tag_body(fd, prev); + else + write_or_die(fd, tag_template, strlen(tag_template)); close(fd); launch_editor(path, buf); @@ -419,7 +451,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix) die("tag '%s' already exists", tag); if (annotate) - create_tag(object, tag, &buf, message, sign, object); + create_tag(object, tag, &buf, message, sign, prev, object); lock = lock_any_ref_for_update(ref, prev, 0); if (!lock) From 4d8b1dc850bafdf2304a525a768fbfc7aa5361ae Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Sun, 4 Nov 2007 01:11:15 +0100 Subject: [PATCH 0464/1490] Add tests for git tag These tests check whether git-tag properly sends a comment into the editor, and whether it reuses previous annotation when overwriting an existing tag. Signed-off-by: Mike Hommey Signed-off-by: Junio C Hamano --- t/t7004-tag.sh | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh index 0d07bc39c7..096fe33b07 100755 --- a/t/t7004-tag.sh +++ b/t/t7004-tag.sh @@ -1004,4 +1004,20 @@ test_expect_failure \ 'verify signed tag fails when public key is not present' \ 'git-tag -v signed-tag' +test_expect_success \ + 'message in editor has initial comment' ' + GIT_EDITOR=cat git tag -a initial-comment > actual || true && + test $(sed -n "/^\(#\|\$\)/p" actual | wc -l) -gt 0 +' + +get_tag_header reuse $commit commit $time >expect +echo "An annotation to be reused" >> expect +test_expect_success \ + 'overwriting an annoted tag should use its previous body' ' + git tag -a -m "An annotation to be reused" reuse && + GIT_EDITOR=true git tag -f -a reuse && + get_tag_msg reuse >actual && + git diff expect actual +' + test_done From 59f0f2f33a420e9a14bb8cef20d38f508f0d098e Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Sat, 3 Nov 2007 12:23:11 +0100 Subject: [PATCH 0465/1490] Refactor working tree setup Create a setup_work_tree() that can be used from any command requiring a working tree conditionally. Signed-off-by: Mike Hommey Acked-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- cache.h | 1 + git.c | 11 +++-------- setup.c | 9 +++++++++ 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/cache.h b/cache.h index bfffa05dff..497b9f962d 100644 --- a/cache.h +++ b/cache.h @@ -222,6 +222,7 @@ extern const char *get_git_work_tree(void); #define ALTERNATE_DB_ENVIRONMENT "GIT_ALTERNATE_OBJECT_DIRECTORIES" extern const char **get_pathspec(const char *prefix, const char **pathspec); +extern void setup_work_tree(void); extern const char *setup_git_directory_gently(int *); extern const char *setup_git_directory(void); extern const char *prefix_path(const char *prefix, int len, const char *path); diff --git a/git.c b/git.c index 4e10581101..eb31c93d0f 100644 --- a/git.c +++ b/git.c @@ -249,14 +249,9 @@ static int run_command(struct cmd_struct *p, int argc, const char **argv) prefix = setup_git_directory(); if (p->option & USE_PAGER) setup_pager(); - if (p->option & NEED_WORK_TREE) { - const char *work_tree = get_git_work_tree(); - const char *git_dir = get_git_dir(); - if (!is_absolute_path(git_dir)) - set_git_dir(make_absolute_path(git_dir)); - if (!work_tree || chdir(work_tree)) - die("%s must be run in a work tree", p->cmd); - } + if (p->option & NEED_WORK_TREE) + setup_work_tree(); + trace_argv_printf(argv, argc, "trace: built-in: git"); status = p->fn(argc, argv, prefix); diff --git a/setup.c b/setup.c index 145eca50f4..df006d9c4a 100644 --- a/setup.c +++ b/setup.c @@ -206,6 +206,15 @@ static const char *set_work_tree(const char *dir) return NULL; } +void setup_work_tree(void) { + const char *work_tree = get_git_work_tree(); + const char *git_dir = get_git_dir(); + if (!is_absolute_path(git_dir)) + set_git_dir(make_absolute_path(git_dir)); + if (!work_tree || chdir(work_tree)) + die("This operation must be run in a work tree"); +} + /* * We cannot decide in this function whether we are in the work tree or * not, since the config can only be read _after_ this function was called. From 7d8ae93292e2cd862359f02879a0c954faf8afa8 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Sat, 3 Nov 2007 12:23:12 +0100 Subject: [PATCH 0466/1490] Use setup_work_tree() in builtin-ls-files.c Signed-off-by: Mike Hommey Acked-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- builtin-ls-files.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/builtin-ls-files.c b/builtin-ls-files.c index b70da1863b..e0b856f432 100644 --- a/builtin-ls-files.c +++ b/builtin-ls-files.c @@ -525,11 +525,8 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix) break; } - if (require_work_tree && !is_inside_work_tree()) { - const char *work_tree = get_git_work_tree(); - if (!work_tree || chdir(work_tree)) - die("This operation must be run in a work tree"); - } + if (require_work_tree && !is_inside_work_tree()) + setup_work_tree(); pathspec = get_pathspec(prefix, argv + i); From 271bb08735435b859464c22506ba512f003a4191 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Sat, 3 Nov 2007 12:23:13 +0100 Subject: [PATCH 0467/1490] Don't always require working tree for git-rm This allows to do git rm --cached -r directory, instead of git ls-files -z directory | git update-index --remove -z --stdin. This can be particularly useful for git-filter-branch users. Signed-off-by: Mike Hommey Acked-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- builtin-rm.c | 3 +++ git.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/builtin-rm.c b/builtin-rm.c index bca2bd9703..a3d25e6a57 100644 --- a/builtin-rm.c +++ b/builtin-rm.c @@ -155,6 +155,9 @@ int cmd_rm(int argc, const char **argv, const char *prefix) if (!argc) usage_with_options(builtin_rm_usage, builtin_rm_options); + if (!index_only) + setup_work_tree(); + pathspec = get_pathspec(prefix, argv); seen = NULL; for (i = 0; pathspec[i] ; i++) diff --git a/git.c b/git.c index eb31c93d0f..4a250f7e8b 100644 --- a/git.c +++ b/git.c @@ -340,7 +340,7 @@ static void handle_internal_command(int argc, const char **argv) { "rev-list", cmd_rev_list, RUN_SETUP }, { "rev-parse", cmd_rev_parse, RUN_SETUP }, { "revert", cmd_revert, RUN_SETUP | NEED_WORK_TREE }, - { "rm", cmd_rm, RUN_SETUP | NEED_WORK_TREE }, + { "rm", cmd_rm, RUN_SETUP }, { "runstatus", cmd_runstatus, RUN_SETUP | NEED_WORK_TREE }, { "shortlog", cmd_shortlog, RUN_SETUP | USE_PAGER }, { "show-branch", cmd_show_branch, RUN_SETUP }, From 1981820be20538d7a70f86c5ddbe379566fd5ff2 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Sat, 3 Nov 2007 13:22:55 +0100 Subject: [PATCH 0468/1490] Make git-blame fail when working tree is needed and we're not in one Signed-off-by: Mike Hommey Signed-off-by: Junio C Hamano --- builtin-blame.c | 1 + 1 file changed, 1 insertion(+) diff --git a/builtin-blame.c b/builtin-blame.c index aedc294eac..55a3c0bc5e 100644 --- a/builtin-blame.c +++ b/builtin-blame.c @@ -2342,6 +2342,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix) * do not default to HEAD, but use the working tree * or "--contents". */ + setup_work_tree(); sb.final = fake_working_tree_commit(path, contents_from); add_pending_object(&revs, &(sb.final->object), ":"); } From 21d4783538662143ef52ed6967c948ab27586232 Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Sun, 4 Nov 2007 11:30:53 +0100 Subject: [PATCH 0469/1490] Add a parseopt mode to git-rev-parse to bring parse-options to shell scripts. Signed-off-by: Pierre Habouzit Signed-off-by: Junio C Hamano --- Documentation/git-rev-parse.txt | 76 ++++++++++++++++++- builtin-rev-parse.c | 126 ++++++++++++++++++++++++++++++++ 2 files changed, 200 insertions(+), 2 deletions(-) diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt index 4758c33dee..329fce0aab 100644 --- a/Documentation/git-rev-parse.txt +++ b/Documentation/git-rev-parse.txt @@ -23,6 +23,13 @@ distinguish between them. OPTIONS ------- +--parseopt:: + Use `git-rev-parse` in option parsing mode (see PARSEOPT section below). + +--keep-dash-dash:: + Only meaningful in `--parseopt` mode. Tells the option parser to echo + out the first `--` met instead of skipping it. + --revs-only:: Do not output flags and parameters not meant for `git-rev-list` command. @@ -288,10 +295,75 @@ Here are a handful examples: C^@ I J F F^! D G H D F +PARSEOPT +-------- + +In `--parseopt` mode, `git-rev-parse` helps massaging options to bring to shell +scripts the same facilities C builtins have. It works as an option normalizer +(e.g. splits single switches aggregate values), a bit like `getopt(1)` does. + +It takes on the standard input the specification of the options to parse and +understand, and echoes on the standard output a line suitable for `sh(1)` `eval` +to replace the arguments with normalized ones. In case of error, it outputs +usage on the standard error stream, and exits with code 129. + +Input Format +~~~~~~~~~~~~ + +`git-rev-parse --parseopt` input format is fully text based. It has two parts, +separated by a line that contains only `--`. The lines before the separator +(should be more than one) are used for the usage. +The lines after the separator describe the options. + +Each line of options has this format: + +------------ +? SP+ help LF +------------ + +``:: + its format is the short option character, then the long option name + separated by a comma. Both parts are not required, though at least one + is necessary. `h,help`, `dry-run` and `f` are all three correct + ``. + +``:: + an `` tells the option parser if the option has an argument + (`=`), an optional one (`?` though its use is discouraged) or none + (no `` in that case). + +The remainder of the line, after stripping the spaces, is used +as the help associated to the option. + +Blank lines are ignored, and lines that don't match this specification are used +as option group headers (start the line with a space to create such +lines on purpose). + +Example +~~~~~~~ + +------------ +OPTS_SPEC="\ +some-command [options] ... + +some-command does foo and bar! +-- +h,help show the help + +foo some nifty option --foo +bar= some cool option --bar with an argument + + An option group Header +C? option C with an optional argument" + +eval `echo "$OPTS_SPEC" | git-rev-parse --parseopt -- "$@" || echo exit $?` +------------ + + Author ------ -Written by Linus Torvalds and -Junio C Hamano +Written by Linus Torvalds . +Junio C Hamano and Pierre Habouzit Documentation -------------- diff --git a/builtin-rev-parse.c b/builtin-rev-parse.c index 8d78b69c90..054519bf28 100644 --- a/builtin-rev-parse.c +++ b/builtin-rev-parse.c @@ -8,6 +8,7 @@ #include "refs.h" #include "quote.h" #include "builtin.h" +#include "parse-options.h" #define DO_REVS 1 #define DO_NOREV 2 @@ -209,6 +210,128 @@ static int try_difference(const char *arg) return 0; } +static int parseopt_dump(const struct option *o, const char *arg, int unset) +{ + struct strbuf *parsed = o->value; + if (unset) + strbuf_addf(parsed, " --no-%s", o->long_name); + else if (o->short_name) + strbuf_addf(parsed, " -%c", o->short_name); + else + strbuf_addf(parsed, " --%s", o->long_name); + if (arg) { + strbuf_addch(parsed, ' '); + sq_quote_buf(parsed, arg); + } + return 0; +} + +static const char *skipspaces(const char *s) +{ + while (isspace(*s)) + s++; + return s; +} + +static int cmd_parseopt(int argc, const char **argv, const char *prefix) +{ + static int keep_dashdash = 0; + static char const * const parseopt_usage[] = { + "git-rev-parse --parseopt [options] -- [...]", + NULL + }; + static struct option parseopt_opts[] = { + OPT_BOOLEAN(0, "keep-dashdash", &keep_dashdash, + "keep the `--` passed as an arg"), + OPT_END(), + }; + + struct strbuf sb, parsed; + const char **usage = NULL; + struct option *opts = NULL; + int onb = 0, osz = 0, unb = 0, usz = 0; + + strbuf_init(&parsed, 0); + strbuf_addstr(&parsed, "set --"); + argc = parse_options(argc, argv, parseopt_opts, parseopt_usage, + PARSE_OPT_KEEP_DASHDASH); + if (argc < 1 || strcmp(argv[0], "--")) + usage_with_options(parseopt_usage, parseopt_opts); + + strbuf_init(&sb, 0); + /* get the usage up to the first line with a -- on it */ + for (;;) { + if (strbuf_getline(&sb, stdin, '\n') == EOF) + die("premature end of input"); + ALLOC_GROW(usage, unb + 1, usz); + if (!strcmp("--", sb.buf)) { + if (unb < 1) + die("no usage string given before the `--' separator"); + usage[unb] = NULL; + break; + } + usage[unb++] = strbuf_detach(&sb, NULL); + } + + /* parse: (|,|)[=?]? SP+ */ + while (strbuf_getline(&sb, stdin, '\n') != EOF) { + const char *s; + struct option *o; + + if (!sb.len) + continue; + + ALLOC_GROW(opts, onb + 1, osz); + memset(opts + onb, 0, sizeof(opts[onb])); + + o = &opts[onb++]; + s = strchr(sb.buf, ' '); + if (!s || *sb.buf == ' ') { + o->type = OPTION_GROUP; + o->help = xstrdup(skipspaces(s)); + continue; + } + + o->type = OPTION_CALLBACK; + o->help = xstrdup(skipspaces(s)); + o->value = &parsed; + o->callback = &parseopt_dump; + switch (s[-1]) { + case '=': + s--; + break; + case '?': + o->flags = PARSE_OPT_OPTARG; + s--; + break; + default: + o->flags = PARSE_OPT_NOARG; + break; + } + + if (s - sb.buf == 1) /* short option only */ + o->short_name = *sb.buf; + else if (sb.buf[1] != ',') /* long option only */ + o->long_name = xmemdupz(sb.buf, s - sb.buf); + else { + o->short_name = *sb.buf; + o->long_name = xmemdupz(sb.buf + 2, s - sb.buf - 2); + } + } + strbuf_release(&sb); + + /* put an OPT_END() */ + ALLOC_GROW(opts, onb + 1, osz); + memset(opts + onb, 0, sizeof(opts[onb])); + argc = parse_options(argc, argv, opts, usage, + keep_dashdash ? PARSE_OPT_KEEP_DASHDASH : 0); + + strbuf_addf(&parsed, " --"); + sq_quote_argv(&parsed, argv, argc, 0); + puts(parsed.buf); + return 0; +} + int cmd_rev_parse(int argc, const char **argv, const char *prefix) { int i, as_is = 0, verify = 0; @@ -216,6 +339,9 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) git_config(git_default_config); + if (argc > 1 && !strcmp("--parseopt", argv[1])) + return cmd_parseopt(argc - 1, argv + 1, prefix); + for (i = 1; i < argc; i++) { const char *arg = argv[i]; From bac199b7b17cd12286a7d5393f4789574c2e1dc4 Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Sun, 4 Nov 2007 11:30:54 +0100 Subject: [PATCH 0470/1490] Update git-sh-setup(1) to allow transparent use of git-rev-parse --parseopt If you set OPTIONS_SPEC, git-sh-setups uses git-rev-parse --parseopt automatically. It also diverts usage to re-exec $0 with the -h option as parse-options.c will catch that. If you need git-rev-parse --parseopt to keep the `--` the user may have passed to your command, set OPTIONS_KEEPDASHDASH to a non empty value in your script. Signed-off-by: Pierre Habouzit Signed-off-by: Junio C Hamano --- git-sh-setup.sh | 48 ++++++++++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/git-sh-setup.sh b/git-sh-setup.sh index 86d7d4c4e7..e1cf885983 100755 --- a/git-sh-setup.sh +++ b/git-sh-setup.sh @@ -16,9 +16,36 @@ die() { exit 1 } -usage() { - die "Usage: $0 $USAGE" -} +if test -n "$OPTIONS_SPEC"; then + usage() { + exec "$0" -h + } + + parseopt_extra= + [ -n "$OPTIONS_KEEPDASHDASH" ] && + parseopt_extra="$parseopt_extra --keep-dashdash" + + eval `echo "$OPTIONS_SPEC" | git rev-parse --parseopt $parseopt_extra -- "$@" || echo exit $?` +else + usage() { + die "Usage: $0 $USAGE" + } + + if [ -z "$LONG_USAGE" ] + then + LONG_USAGE="Usage: $0 $USAGE" + else + LONG_USAGE="Usage: $0 $USAGE + +$LONG_USAGE" + fi + + case "$1" in + -h|--h|--he|--hel|--help) + echo "$LONG_USAGE" + exit + esac +fi set_reflog_action() { if [ -z "${GIT_REFLOG_ACTION:+set}" ] @@ -91,21 +118,6 @@ get_author_ident_from_commit () { LANG=C LC_ALL=C sed -ne "$pick_author_script" } -if [ -z "$LONG_USAGE" ] -then - LONG_USAGE="Usage: $0 $USAGE" -else - LONG_USAGE="Usage: $0 $USAGE - -$LONG_USAGE" -fi - -case "$1" in - -h|--h|--he|--hel|--help) - echo "$LONG_USAGE" - exit -esac - # Make sure we are in a valid repository of a vintage we understand. if [ -z "$SUBDIRECTORY_OK" ] then From 27c0d1c7f51dd0b31c8a6283df7a23bdb7de8957 Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Sun, 4 Nov 2007 11:30:55 +0100 Subject: [PATCH 0471/1490] Migrate git-clean.sh to use git-rev-parse --parseopt. Also minor consistency tweaks in how errors are caught. Signed-off-by: Pierre Habouzit Signed-off-by: Junio C Hamano --- git-clean.sh | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/git-clean.sh b/git-clean.sh index 4491738186..35a5142c56 100755 --- a/git-clean.sh +++ b/git-clean.sh @@ -3,16 +3,22 @@ # Copyright (c) 2005-2006 Pavel Roskin # -USAGE="[-d] [-f] [-n] [-q] [-x | -X] [--] ..." -LONG_USAGE='Clean untracked files from the working directory - -d remove directories as well - -f override clean.requireForce and clean anyway - -n don'\''t remove anything, just show what would be done - -q be quiet, only report errors - -x remove ignored files as well - -X remove only ignored files +OPTIONS_KEEPDASHDASH= +OPTIONS_SPEC="\ +git-clean [options] ... + +Clean untracked files from the working directory + When optional ... arguments are given, the paths -affected are further limited to those that match them.' +affected are further limited to those that match them. +-- +d remove directories as well +f override clean.requireForce and clean anyway +n don't remove anything, just show what would be done +q be quiet, only report errors +x remove ignored files as well +X remove only ignored files" + SUBDIRECTORY_OK=Yes . git-sh-setup require_work_tree @@ -55,23 +61,20 @@ do shift break ;; - -*) - usage - ;; *) - break + usage # should not happen + ;; esac shift done if [ "$disabled" = true ]; then - echo "clean.requireForce set and -n or -f not given; refusing to clean" - exit 1 + die "clean.requireForce set and -n or -f not given; refusing to clean" fi -case "$ignored,$ignoredonly" in - 1,1) usage;; -esac +if [ "$ignored,$ignoredonly" = "1,1" ]; then + die "-x and -X cannot be set together" +fi if [ -z "$ignored" ]; then excl="--exclude-per-directory=.gitignore" From 943625998b43ae7b7a4faf840951f0cefb28dc33 Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Sun, 4 Nov 2007 11:30:56 +0100 Subject: [PATCH 0472/1490] Migrate git-clone to use git-rev-parse --parseopt Signed-off-by: Pierre Habouzit Signed-off-by: Junio C Hamano --- git-clone.sh | 101 ++++++++++++++++++++++++++++----------------------- 1 file changed, 56 insertions(+), 45 deletions(-) diff --git a/git-clone.sh b/git-clone.sh index 3f00693608..f216f03a77 100755 --- a/git-clone.sh +++ b/git-clone.sh @@ -8,15 +8,36 @@ # See git-sh-setup why. unset CDPATH +OPTIONS_SPEC="\ +git-clone [options] [--] [] +-- +n,no-checkout don't create a checkout +bare create a bare repository +naked create a bare repository +l,local to clone from a local repository +no-hardlinks don't use local hardlinks, always copy +s,shared setup as a shared repository +template= path to the template directory +q,quiet be quiet +reference= reference repository +o,origin= use instead of 'origin' to track upstream +u,upload-pack= path to git-upload-pack on the remote +depth= create a shallow clone of that depth + +use-separate-remote compatibility, do not use +no-separate-remote compatibility, do not use" + die() { echo >&2 "$@" exit 1 } usage() { - die "Usage: $0 [--template=] [--reference ] [--bare] [-l [-s]] [-q] [-u ] [--origin ] [--depth ] [-n] [--] []" + exec "$0" -h } +eval `echo "$OPTIONS_SPEC" | git rev-parse --parseopt -- "$@" || echo exit $?` + get_repo_base() { ( cd "`/bin/pwd`" && @@ -106,67 +127,57 @@ depth= no_progress= local_explicitly_asked_for= test -t 1 || no_progress=--no-progress -while - case "$#,$1" in - 0,*) break ;; - *,-n|*,--no|*,--no-|*,--no-c|*,--no-ch|*,--no-che|*,--no-chec|\ - *,--no-check|*,--no-checko|*,--no-checkou|*,--no-checkout) - no_checkout=yes ;; - *,--na|*,--nak|*,--nake|*,--naked|\ - *,-b|*,--b|*,--ba|*,--bar|*,--bare) bare=yes ;; - *,-l|*,--l|*,--lo|*,--loc|*,--loca|*,--local) - local_explicitly_asked_for=yes - use_local_hardlink=yes ;; - *,--no-h|*,--no-ha|*,--no-har|*,--no-hard|*,--no-hardl|\ - *,--no-hardli|*,--no-hardlin|*,--no-hardlink|*,--no-hardlinks) - use_local_hardlink=no ;; - *,-s|*,--s|*,--sh|*,--sha|*,--shar|*,--share|*,--shared) - local_shared=yes; ;; - 1,--template) usage ;; - *,--template) + +while test $# != 0 +do + case "$1" in + -n|--no-checkout) + no_checkout=yes ;; + --naked|--bare) + bare=yes ;; + -l|--local) + local_explicitly_asked_for=yes + use_local_hardlink=yes + ;; + --no-hardlinks) + use_local_hardlink=no ;; + -s|--shared) + local_shared=yes ;; + --template) shift; template="--template=$1" ;; - *,--template=*) - template="$1" ;; - *,-q|*,--quiet) quiet=-q ;; - *,--use-separate-remote) ;; - *,--no-separate-remote) + -q|--quiet) + quiet=-q ;; + --use-separate-remote|--no-separate-remote) die "clones are always made with separate-remote layout" ;; - 1,--reference) usage ;; - *,--reference) + --reference) shift; reference="$1" ;; - *,--reference=*) - reference=`expr "z$1" : 'z--reference=\(.*\)'` ;; - *,-o|*,--or|*,--ori|*,--orig|*,--origi|*,--origin) - case "$2" in + -o,--origin) + shift; + case "$1" in '') usage ;; */*) - die "'$2' is not suitable for an origin name" + die "'$1' is not suitable for an origin name" esac - git check-ref-format "heads/$2" || - die "'$2' is not suitable for a branch name" + git check-ref-format "heads/$1" || + die "'$1' is not suitable for a branch name" test -z "$origin_override" || die "Do not give more than one --origin options." origin_override=yes - origin="$2"; shift + origin="$1" ;; - 1,-u|1,--upload-pack) usage ;; - *,-u|*,--upload-pack) + -u|--upload-pack) shift upload_pack="--upload-pack=$1" ;; - *,--upload-pack=*) - upload_pack=--upload-pack=$(expr "z$1" : 'z-[^=]*=\(.*\)') ;; - 1,--depth) usage;; - *,--depth) + --depth) shift - depth="--depth=$1";; - *,--) + depth="--depth=$1" ;; + --) shift break ;; - *,-*) usage ;; - *) break ;; + *) + usage ;; esac -do shift done From 78443d90491c1b82afdffc3d5d2ab8c1a58928b5 Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Sun, 4 Nov 2007 11:30:57 +0100 Subject: [PATCH 0473/1490] Migrate git-am.sh to use git-rev-parse --parseopt Signed-off-by: Pierre Habouzit Signed-off-by: Junio C Hamano --- git-am.sh | 94 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 49 insertions(+), 45 deletions(-) diff --git a/git-am.sh b/git-am.sh index 2514d07de2..876b973a4d 100755 --- a/git-am.sh +++ b/git-am.sh @@ -2,11 +2,26 @@ # # Copyright (c) 2005, 2006 Junio C Hamano -USAGE='[--signoff] [--dotest=] [--keep] [--utf8 | --no-utf8] - [--3way] [--interactive] [--binary] - [--whitespace=