Merge branch 'dr/ru' into pu
[gitweb.git] / lib / diff.tcl
index 22909194d97477febb94291a55a4b8f438bf6c68..4cae10a4c7f197aab9ae0bc145254a8d4a1bae50 100644 (file)
@@ -1,6 +1,19 @@
 # git-gui diff viewer
 # Copyright (C) 2006, 2007 Shawn Pearce
 
+proc apply_tab_size {{firsttab {}}} {
+       global have_tk85 repo_config ui_diff
+
+       set w [font measure font_diff "0"]
+       if {$have_tk85 && $firsttab != 0} {
+               $ui_diff configure -tabs [list [expr {$firsttab * $w}] [expr {($firsttab + $repo_config(gui.tabsize)) * $w}]]
+       } elseif {$have_tk85 || $repo_config(gui.tabsize) != 8} {
+               $ui_diff configure -tabs [expr {$repo_config(gui.tabsize) * $w}]
+       } else {
+               $ui_diff configure -tabs {}
+       }
+}
+
 proc clear_diff {} {
        global ui_diff current_diff_path current_diff_header
        global ui_index ui_workdir
@@ -105,6 +118,8 @@ proc show_diff {path w {lno {}} {scroll_pos {}} {callback {}}} {
 
        set cont_info [list $scroll_pos $callback]
 
+       apply_tab_size 0
+
        if {[string first {U} $m] >= 0} {
                merge_load_stages $path [list show_unmerged_diff $cont_info]
        } elseif {$m eq {_O}} {
@@ -112,6 +127,9 @@ proc show_diff {path w {lno {}} {scroll_pos {}} {callback {}}} {
        } else {
                start_show_diff $cont_info
        }
+
+       global current_diff_path selected_paths
+       set selected_paths($current_diff_path) 1
 }
 
 proc show_unmerged_diff {cont_info} {
@@ -205,10 +223,9 @@ proc show_other_diff {path w m cont_info} {
                }
                $ui_diff conf -state normal
                if {$type eq {submodule}} {
-                       $ui_diff insert end [append \
-                               "* " \
-                               [mc "Git Repository (subproject)"] \
-                               "\n"] d_info
+                       $ui_diff insert end \
+                               "* [mc "Git Repository (subproject)"]\n" \
+                               d_info
                } elseif {![catch {set type [exec file $path]}]} {
                        set n [string length $path]
                        if {[string equal -length $n $path $type]} {
@@ -287,6 +304,9 @@ proc start_show_diff {cont_info {add_opts {}}} {
        if {$w eq $ui_index} {
                lappend cmd diff-index
                lappend cmd --cached
+               if {[git-version >= "1.7.2"]} {
+                       lappend cmd --ignore-submodules=dirty
+               }
        } elseif {$w eq $ui_workdir} {
                if {[string first {U} $m] >= 0} {
                        lappend cmd diff
@@ -309,6 +329,7 @@ proc start_show_diff {cont_info {add_opts {}}} {
 
        lappend cmd -p
        lappend cmd --color
+       set cmd [concat $cmd $repo_config(gui.diffopts)]
        if {$repo_config(gui.diffcontext) >= 1} {
                lappend cmd "-U$repo_config(gui.diffcontext)"
        }
@@ -382,6 +403,8 @@ proc read_diff {fd conflict_size cont_info} {
                foreach {line markup} [parse_color_line $line] break
                set line [string map {\033 ^} $line]
 
+               set tags {}
+
                # -- Check for start of diff header.
                if {   [string match {diff --git *}      $line]
                    || [string match {diff --cc *}       $line]
@@ -395,10 +418,20 @@ proc read_diff {fd conflict_size cont_info} {
 
                # -- Automatically detect if this is a 3 way diff.
                #
-               if {[string match {@@@ *} $line]} {set is_3way_diff 1}
+               if {[string match {@@@ *} $line]} {
+                       set is_3way_diff 1
+                       apply_tab_size 1
+               }
 
                if {$::current_diff_inheader} {
-                       append current_diff_header $line "\n"
+
+                       # -- These two lines stop a diff header and shouldn't be in there
+                       if {   [string match {Binary files * and * differ} $line]
+                           || [regexp {^\* Unmerged path }                $line]} {
+                               set ::current_diff_inheader 0
+                       } else {
+                               append current_diff_header $line "\n"
+                       }
 
                        # -- Cleanup uninteresting diff header lines.
                        #
@@ -414,19 +447,9 @@ proc read_diff {fd conflict_size cont_info} {
                        # -- Name it symlink, not 120000
                        #    Note, that the original line is in $current_diff_header
                        regsub {^(deleted|new) file mode 120000} $line {\1 symlink} line
-               }
-
-
 
-               if {[string match {new file *} $line]
-                       || [regexp {^(old|new) mode *} $line]
-                       || [string match {deleted file *} $line]
-                       || [string match {deleted symlink} $line]
-                       || [string match {new symlink} $line]
-                       || [string match {Binary files * and * differ} $line]
-                       || $line eq {\ No newline at end of file}
-                       || [regexp {^\* Unmerged path } $line]} {
-                       set tags {}
+               } elseif {   $line eq {\ No newline at end of file}} {
+                       # -- Handle some special lines
                } elseif {$is_3way_diff} {
                        set op [string range $line 0 1]
                        switch -- $op {
@@ -503,9 +526,9 @@ proc read_diff {fd conflict_size cont_info} {
 
                foreach {posbegin colbegin posend colend} $markup {
                        set prefix clr
-                       foreach style [split $colbegin ";"] {
+                       foreach style [lsort -integer [split $colbegin ";"]] {
                                if {$style eq "7"} {append prefix i; continue}
-                               if {$style < 30 || $style > 47} {continue}
+                               if {$style != 4 && ($style < 30 || $style > 47)} {continue}
                                set a "$mark linestart + $posbegin chars"
                                set b "$mark linestart + $posend chars"
                                catch {$ui_diff tag add $prefix$style $a $b}
@@ -587,7 +610,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 [append $failed_msg "\n\n$err"]
+               error_popup "$failed_msg\n\n$err"
                unlock_index
                return
        }
@@ -764,8 +787,15 @@ proc apply_range_or_line {x y} {
                                # context line
                                set ln [$ui_diff get $i_l $next_l]
                                set patch "$patch$pre_context$ln"
-                               set n [expr $n+1]
-                               set m [expr $m+1]
+                               # Skip the "\ No newline at end of
+                               # file". Depending on the locale setting
+                               # we don't know what this line looks
+                               # like exactly. The only thing we do
+                               # know is that it starts with "\ "
+                               if {![string match {\\ *} $ln]} {
+                                       set n [expr $n+1]
+                                       set m [expr $m+1]
+                               }
                                set pre_context {}
                        } elseif {$c1 eq $to_context} {
                                # turn change line into context line
@@ -798,7 +828,7 @@ proc apply_range_or_line {x y} {
                puts -nonewline $p $current_diff_header
                puts -nonewline $p $wholepatch
                close $p} err]} {
-               error_popup [append $failed_msg "\n\n$err"]
+               error_popup "$failed_msg\n\n$err"
        }
 
        unlock_index