Merge branch 'maint'
authorShawn O. Pearce <spearce@spearce.org>
Fri, 5 Sep 2008 04:53:06 +0000 (21:53 -0700)
committerShawn O. Pearce <spearce@spearce.org>
Fri, 5 Sep 2008 04:53:06 +0000 (21:53 -0700)
* maint:
git-gui: Fix diff parsing for lines starting with "--" or "++"

1  2 
lib/diff.tcl
diff --combined lib/diff.tcl
index e2ed262fb3a794dcb6ed2a4b69f973cd6fe9f9c9,1970b601e1ce34af120cfc3ee16e1b2c26c6b19d..a30c80a935b58ce0c783dfffde196a85eadca9a2
@@@ -24,16 -24,10 +24,16 @@@ proc reshow_diff {} 
        set p $current_diff_path
        if {$p eq {}} {
                # No diff is being shown.
 -      } elseif {$current_diff_side eq {}
 -              || [catch {set s $file_states($p)}]
 -              || [lsearch -sorted -exact $file_lists($current_diff_side) $p] == -1} {
 +      } elseif {$current_diff_side eq {}} {
                clear_diff
 +      } elseif {[catch {set s $file_states($p)}]
 +              || [lsearch -sorted -exact $file_lists($current_diff_side) $p] == -1} {
 +
 +              if {[find_next_diff $current_diff_side $p {} {[^O]}]} {
 +                      next_diff
 +              } else {
 +                      clear_diff
 +              }
        } else {
                set save_pos [lindex [$ui_diff yview] 0]
                show_diff $p $current_diff_side {} $save_pos
@@@ -65,7 -59,6 +65,7 @@@ proc show_diff {path w {lno {}} {scroll
        global is_3way_diff diff_active repo_config
        global ui_diff ui_index ui_workdir
        global current_diff_path current_diff_side current_diff_header
 +      global current_diff_queue
  
        if {$diff_active || ![lock_index read]} return
  
        }
        if {$lno >= 1} {
                $w tag add in_diff $lno.0 [expr {$lno + 1}].0
 +              $w see $lno.0
        }
  
        set s $file_states($path)
        set m [lindex $s 0]
 -      set is_3way_diff 0
 -      set diff_active 1
        set current_diff_path $path
        set current_diff_side $w
 -      set current_diff_header {}
 +      set current_diff_queue {}
        ui_status [mc "Loading diff of %s..." [escape_path $path]]
  
 +      if {[string first {U} $m] >= 0} {
 +              merge_load_stages $path [list show_unmerged_diff $scroll_pos]
 +      } elseif {$m eq {_O}} {
 +              show_other_diff $path $w $m $scroll_pos
 +      } else {
 +              start_show_diff $scroll_pos
 +      }
 +}
 +
 +proc show_unmerged_diff {scroll_pos} {
 +      global current_diff_path current_diff_side
 +      global merge_stages ui_diff
 +      global current_diff_queue
 +
 +      if {$merge_stages(2) eq {}} {
 +              lappend current_diff_queue \
 +                      [list "LOCAL: deleted\nREMOTE:\n" d======= \
 +                          [list ":1:$current_diff_path" ":3:$current_diff_path"]]
 +      } elseif {$merge_stages(3) eq {}} {
 +              lappend current_diff_queue \
 +                      [list "REMOTE: deleted\nLOCAL:\n" d======= \
 +                          [list ":1:$current_diff_path" ":2:$current_diff_path"]]
 +      } elseif {[lindex $merge_stages(1) 0] eq {120000}
 +              || [lindex $merge_stages(2) 0] eq {120000}
 +              || [lindex $merge_stages(3) 0] eq {120000}} {
 +              lappend current_diff_queue \
 +                      [list "LOCAL:\n" d======= \
 +                          [list ":1:$current_diff_path" ":2:$current_diff_path"]]
 +              lappend current_diff_queue \
 +                      [list "REMOTE:\n" d======= \
 +                          [list ":1:$current_diff_path" ":3:$current_diff_path"]]
 +      } else {
 +              start_show_diff $scroll_pos
 +              return
 +      }
 +
 +      advance_diff_queue $scroll_pos
 +}
 +
 +proc advance_diff_queue {scroll_pos} {
 +      global current_diff_queue ui_diff
 +
 +      set item [lindex $current_diff_queue 0]
 +      set current_diff_queue [lrange $current_diff_queue 1 end]
 +
 +      $ui_diff conf -state normal
 +      $ui_diff insert end [lindex $item 0] [lindex $item 1]
 +      $ui_diff conf -state disabled
 +
 +      start_show_diff $scroll_pos [lindex $item 2]
 +}
 +
 +proc show_other_diff {path w m scroll_pos} {
 +      global file_states file_lists
 +      global is_3way_diff diff_active repo_config
 +      global ui_diff ui_index ui_workdir
 +      global current_diff_path current_diff_side current_diff_header
 +
        # - Git won't give us the diff, there's nothing to compare to!
        #
        if {$m eq {_O}} {
                ui_ready
                return
        }
 +}
 +
 +proc start_show_diff {scroll_pos {add_opts {}}} {
 +      global file_states file_lists
 +      global is_3way_diff diff_active repo_config
 +      global ui_diff ui_index ui_workdir
 +      global current_diff_path current_diff_side current_diff_header
 +
 +      set path $current_diff_path
 +      set w $current_diff_side
 +
 +      set s $file_states($path)
 +      set m [lindex $s 0]
 +      set is_3way_diff 0
 +      set diff_active 1
 +      set current_diff_header {}
  
        set cmd [list]
        if {$w eq $ui_index} {
                lappend cmd diff-index
                lappend cmd --cached
        } elseif {$w eq $ui_workdir} {
 -              if {[string index $m 0] eq {U}} {
 +              if {[string first {U} $m] >= 0} {
                        lappend cmd diff
                } else {
                        lappend cmd diff-files
        if {$w eq $ui_index} {
                lappend cmd [PARENT]
        }
 -      lappend cmd --
 -      lappend cmd $path
 +      if {$add_opts ne {}} {
 +              eval lappend cmd $add_opts
 +      } else {
 +              lappend cmd --
 +              lappend cmd $path
 +      }
  
        if {[catch {set fd [eval git_read --nice $cmd]} err]} {
                set diff_active 0
                return
        }
  
+       set ::current_diff_inheader 1
        fconfigure $fd \
                -blocking 0 \
                -encoding binary \
  proc read_diff {fd scroll_pos} {
        global ui_diff diff_active
        global is_3way_diff current_diff_header
 +      global current_diff_queue
  
        $ui_diff conf -state normal
        while {[gets $fd line] >= 0} {
                # -- Cleanup uninteresting diff header lines.
                #
-               if {   [string match {diff --git *}      $line]
-                       || [string match {diff --cc *}       $line]
-                       || [string match {diff --combined *} $line]
-                       || [string match {--- *}             $line]
-                       || [string match {+++ *}             $line]} {
-                       append current_diff_header $line "\n"
-                       continue
+               if {$::current_diff_inheader} {
+                       if {   [string match {diff --git *}      $line]
+                           || [string match {diff --cc *}       $line]
+                           || [string match {diff --combined *} $line]
+                           || [string match {--- *}             $line]
+                           || [string match {+++ *}             $line]} {
+                               append current_diff_header $line "\n"
+                               continue
+                       }
                }
                if {[string match {index *} $line]} continue
                if {$line eq {deleted file mode 120000}} {
                        set line "deleted symlink"
                }
+               set ::current_diff_inheader 0
  
                # -- Automatically detect if this is a 3 way diff.
                #
  
        if {[eof $fd]} {
                close $fd
 +
 +              if {$current_diff_queue ne {}} {
 +                      advance_diff_queue $scroll_pos
 +                      return
 +              }
 +
                set diff_active 0
                unlock_index
                if {$scroll_pos ne {}} {
@@@ -457,9 -370,10 +461,9 @@@ proc apply_hunk {x y} 
        }
        unlock_index
        display_file $current_diff_path $mi
 +      # This should trigger shift to the next changed file
        if {$o eq {_}} {
 -              clear_diff
 -      } else {
 -              set current_diff_path $current_diff_path
 +              reshow_diff
        }
  }