Git 1.6.6.3
[gitweb.git] / git-gui / lib / diff.tcl
index 94ee38cccc1ee9a43f8dd1309353609b283d8af5..066755b864b587e073a820aa2eb729a6c930d7b0 100644 (file)
@@ -16,7 +16,7 @@ proc clear_diff {} {
        $ui_workdir tag remove in_diff 0.0 end
 }
 
-proc reshow_diff {} {
+proc reshow_diff {{after {}}} {
        global file_states file_lists
        global current_diff_path current_diff_side
        global ui_diff
@@ -30,13 +30,13 @@ proc reshow_diff {} {
                || [lsearch -sorted -exact $file_lists($current_diff_side) $p] == -1} {
 
                if {[find_next_diff $current_diff_side $p {} {[^O]}]} {
-                       next_diff
+                       next_diff $after
                } else {
                        clear_diff
                }
        } else {
                set save_pos [lindex [$ui_diff yview] 0]
-               show_diff $p $current_diff_side {} $save_pos
+               show_diff $p $current_diff_side {} $save_pos $after
        }
 }
 
@@ -51,11 +51,16 @@ proc force_diff_encoding {enc} {
 
 proc handle_empty_diff {} {
        global current_diff_path file_states file_lists
+       global diff_empty_count
 
        set path $current_diff_path
        set s $file_states($path)
        if {[lindex $s 0] ne {_M}} return
 
+       # Prevent infinite rescan loops
+       incr diff_empty_count
+       if {$diff_empty_count > 1} return
+
        info_popup [mc "No differences detected.
 
 %s has no changes.
@@ -250,7 +255,7 @@ proc show_other_diff {path w m cont_info} {
 
 proc start_show_diff {cont_info {add_opts {}}} {
        global file_states file_lists
-       global is_3way_diff diff_active repo_config
+       global is_3way_diff is_submodule_diff diff_active repo_config
        global ui_diff ui_index ui_workdir
        global current_diff_path current_diff_side current_diff_header
 
@@ -260,6 +265,7 @@ proc start_show_diff {cont_info {add_opts {}}} {
        set s $file_states($path)
        set m [lindex $s 0]
        set is_3way_diff 0
+       set is_submodule_diff 0
        set diff_active 1
        set current_diff_header {}
 
@@ -290,6 +296,16 @@ proc start_show_diff {cont_info {add_opts {}}} {
                lappend cmd $path
        }
 
+       if {[string match {160000 *} [lindex $s 2]]
+        || [string match {160000 *} [lindex $s 3]]} {
+               set is_submodule_diff 1
+               if {$w eq $ui_index} {
+                       set cmd [list submodule summary --cached -- $path]
+               } else {
+                       set cmd [list submodule summary --files -- $path]
+               }
+       }
+
        if {[catch {set fd [eval git_read --nice $cmd]} err]} {
                set diff_active 0
                unlock_index
@@ -307,9 +323,10 @@ proc start_show_diff {cont_info {add_opts {}}} {
 }
 
 proc read_diff {fd cont_info} {
-       global ui_diff diff_active
+       global ui_diff diff_active is_submodule_diff
        global is_3way_diff is_conflict_diff current_diff_header
        global current_diff_queue
+       global diff_empty_count
 
        $ui_diff conf -state normal
        while {[gets $fd line] >= 0} {
@@ -368,6 +385,23 @@ proc read_diff {fd cont_info} {
                                set tags {}
                        }
                        }
+               } elseif {$is_submodule_diff} {
+                       if {$line == ""} continue
+                       if {[regexp {^\* } $line]} {
+                               set line [string replace $line 0 1 {Submodule }]
+                               set tags d_@
+                       } else {
+                               set op [string range $line 0 2]
+                               switch -- $op {
+                               {  <} {set tags d_-}
+                               {  >} {set tags d_+}
+                               {  W} {set tags {}}
+                               default {
+                                       puts "error: Unhandled submodule diff marker: {$op}"
+                                       set tags {}
+                               }
+                               }
+                       }
                } else {
                        set op [string index $line 0]
                        switch -- $op {
@@ -415,7 +449,10 @@ proc read_diff {fd cont_info} {
 
                if {[$ui_diff index end] eq {2.0}} {
                        handle_empty_diff
+               } else {
+                       set diff_empty_count 0
                }
+
                set callback [lindex $cont_info 1]
                if {$callback ne {}} {
                        eval $callback
@@ -627,6 +664,7 @@ proc apply_line {x y} {
                }
                set i_l $next_l
        }
+       set patch "$patch$pre_context"
        set patch "@@ -$hln,$n +$hln,[eval expr $n $sign 1] @@\n$patch"
 
        if {[catch {