
# TCL Library for tkCVS

#
# $Id: merge.tcl,v 1.5 1995/11/15 04:30:11 davide Exp $
#

proc merge_setup {} {
# By: Eugene Lee, Aerospace Corporation, 11/12/95
  global cvsglb cvsroot GetVenModule from_to sel_to
#puts "merge_setup entered"
  toplevel .merge
  
  frame .merge.left
  frame .merge.right
  frame .merge.vendor -relief groove -border 2
  frame .merge.down -relief groove -border 2
  frame .merge.feedback -relief groove -border 2

  pack .merge.feedback -side bottom -fill x -expand yes
  pack .merge.down -side bottom -fill x -expand yes  
  pack .merge.vendor -side bottom -fill x -expand yes
  pack .merge.left   -side left
  pack .merge.right  -side right -fill x -expand yes 
 
  label .merge.left.lcwd      -text "Current Directory"   -anchor w
  label .merge.left.lmodule   -text "Module Location"    -anchor w
  
  entry .merge.right.tcwd      -relief sunken -width 40;  # use with cwd later
  entry .merge.right.tmodule   -width 40;           # use with module_dir later
  
  pack .merge.left.lcwd       -side top   -fill x -pady 3
  pack .merge.left.lmodule    -side top   -fill x
  pack .merge.right.tcwd      -side top   -fill x -pady 3
  pack .merge.right.tmodule   -side top   -fill x
  
  frame .merge.vendor.name 
  pack .merge.vendor.name -side top -fill x -expand yes
  label .merge.vendor.name.l -text "Vendor Module" -anchor w
  entry .merge.vendor.name.e -relief sunken 
  pack .merge.vendor.name.l -side left -fill x -pady 3
  pack .merge.vendor.name.e -side right -anchor w -fill x -pady 3 -expand yes
  .merge.vendor.name.e config -state disabled
#  button .merge.vendor.b -text \
#    "Select Module With Vendor Code From Repository" -anchor w \
#    -command "GVM_selector"
  button .merge.vendor.b -text \
    "Select Module With Vendor Code From Repository" -anchor w \
    -command "venselect_run"
  pack .merge.vendor.b -side top -ipadx 2 -ipady 2  \
    -padx 4 -pady 4  
  frame .merge.vendor.l
  frame .merge.vendor.r
  pack .merge.vendor.l .merge.vendor.r -side left 
  
  foreach i {l r} {
    if { $i == "l" } {
      set x "From"
    } else {
      set x "To"
    }
    label .merge.vendor.$i.rev -text "$x Revision Tags"
    pack .merge.vendor.$i.rev -side top
    
    frame .merge.vendor.$i.scroll 
      eval {listbox .merge.vendor.$i.scroll.list \
      -yscrollcommand [list .merge.vendor.$i.scroll.sy set] \
      -xscrollcommand [list .merge.vendor.$i.scroll.sx set]} \
      -relief sunken -width 40 -height 15
      scrollbar .merge.vendor.$i.scroll.sx -orient horizontal \
        -command [list .merge.vendor.$i.scroll.list xview] \
        -relief sunken
      scrollbar .merge.vendor.$i.scroll.sy -orient vertical \
        -command [list .merge.vendor.$i.scroll.list yview] \
        -relief sunken
        pack .merge.vendor.$i.scroll.sx -side bottom -fill x
        pack .merge.vendor.$i.scroll.sy -side right -fill y
        pack .merge.vendor.$i.scroll.list -side left -fill both -expand true
    pack .merge.vendor.$i.scroll -side top
    
    frame .merge.vendor.$i.f
    pack .merge.vendor.$i.f -side bottom 
    label .merge.vendor.$i.f.l -text $x
    if { $i == "l" } {
    
      label .merge.vendor.$i.f.s -textvariable merge(from) -relief sunken \
        -width 15
    } else {
      label .merge.vendor.$i.f.s -textvariable merge(to) -relief sunken \
        -width 15
    }
    
    pack .merge.vendor.$i.f.l -side left -padx 3 -pady 3
    pack .merge.vendor.$i.f.s -side left -pady 3
  }
    
  button .merge.ok -text "OK" -command do_merge
  button .merge.quit -text "Quit" -command { wm withdraw .merge }
  pack .merge.ok .merge.quit -in .merge.down -side left \
    -ipadx 2 -ipady 2 -padx 4 -pady 4 -fill both -expand 1
    
  entry .merge.feedback.e  
  pack .merge.feedback.e -fill x -expand yes
  .merge.feedback.e configure -text "Hello"
    
  bind .merge.vendor.l.scroll.list <Double-1> {
    get_j .merge.vendor.l.scroll.list left
  }
  bind .merge.vendor.r.scroll.list <Double-1> {
    get_j .merge.vendor.r.scroll.list right
  }
  
  wm withdraw .merge
  wm title .merge "Module Level Merge With Vendor Code" 
  wm minsize .merge 30 10
  
}

proc get_j { list side} {
# Written by Eugene A. Lee, Aerospace Corp., 12/20/94
    global merge
    if {[string compare [$list curselection] ""] \
       == 0} return

    set Sel [$list get [$list curselection]]
#puts "side=$side"
    if {$side == "left"} {
       set merge(from) [lindex [split $Sel] 0]
    } else {
       set merge(to) [lindex [split $Sel] 0]
    }
}

proc put_rev_tags {} {
# Written by Eugene A. Lee, Aerospace Corp., 11/12/95
  #Called by button .venselect.ok in venget.tcl 
    global cvsroot merge venselect_mcode location
    set tmpwdir [eval pwd]
#puts "tmpwdir=$tmpwdir"
#puts "venselect_mcode=$venselect_mcode"
    .merge.vendor.l.scroll.list delete 0 end
    .merge.vendor.r.scroll.list delete 0 end
    # Find directory where venselect_mcode is.
    set dir $cvsroot/$location($venselect_mcode)
#puts "From put_rev_tags, dir=$dir"
    cd $dir
    get_rv_tags r_tag_list v_tag_list
#puts "r_tag_list=$r_tag_list"
    cd $tmpwdir
    if { [info exists r_tag_list] == 0 } {
      foreach i {l r} {
        .merge.vendor.$i.scroll.list insert end "No revision tags found"
      }
    } else {
      for {set i 0} {$i < [llength $r_tag_list]} {incr i} {
        set tmp [lindex $r_tag_list $i]
        .merge.vendor.l.scroll.list insert end $tmp
        .merge.vendor.r.scroll.list insert end $tmp
      }
    }
}
proc merge_run {} {
  global cwd module_dir
#puts "merge_run invoked"
#puts "cwd=$cwd"
#puts "module_dir=$module_dir"
  if {$module_dir == "Not a CVS directory."} {
    cvserror $module_dir
    return
  }
  .merge.right.tcwd configure -text cwd
  .merge.right.tmodule configure -text module_dir
  wm deiconify .merge
} 

proc do_merge {} {
  global merge
#  puts "Entered do_merge"
#  puts "pwd=[exec pwd]"
  set merge(3rd_party) [.merge.vendor.name.e get]
  if { $merge(3rd_party) == "" } {
    puts "Vendor Module not specified"
    return
  }
#puts "merge(3rd_party)=$merge(3rd_party)"
  if { $merge(from) == "" || \
       $merge(to) == "" } {
    puts "not all entries filled"
    return
  }
#  puts "merge(from)=$merge(from)"
#  puts "merge(to)=$merge(to)"
  set merge(mod_dir) [exec pwd]
  
  set mess "This will merge differences between $merge(from) and\
    $merge(to) of $merge(3rd_party) into $merge(mod_dir)
    
Are you sure?"
  set confirm [tk_dialog .message {Confirm!} $mess warning 0 OK Quit]
  
  if {$confirm == 0} {  
    set mktemp "/tmp/[exec whoami][pid]"
    set mktemp_dir $mktemp.dir
#puts "mktemp_dir=$mktemp_dir"
    catch {exec cvs checkout -d $mktemp_dir -r$merge(from) $merge(3rd_party)} \
      view_this
    view_output "CVS Checkout of temp file for $merge(3rd_party)" $view_this
  
    catch {rm -rf CVS_save}
    eval exec mv CVS CVS_save
    eval exec cp -R $mktemp_dir/CVS .
    eval exec rm -rf $mktemp_dir
  
#puts "merge(mod_dir)=$merge(mod_dir)"
#puts "merge(3rd_party)=$merge(3rd_party)"
    catch {eval exec cvs checkout -d $merge(mod_dir) -j$merge(from) \
      -j$merge(to) $merge(3rd_party) } view_this
    view_output "CVS Module Level Merge of $merge(3rd_party) into $merge(mod_dir)" \
      $view_this
  
    eval exec rm -rf CVS
    eval exec mv CVS_save CVS
  
  wm withdraw .merge 
  }     
  
}

proc unpack_tag_word { tag_word type tag_message} {
  ##############################################################################
  # Unpacks vendor and release tag information obtained from an RCS ,v file.
  # In an RCS ,v file, between the keywords "symbols" and "locks" keywords,
  # there are packed words with the following format:
  #
  #            tag_info:tag_ident
  #
  # where: tag_info is either the vendortag or releasetag which was entered
  #        when a cvs checkin or import command was invoked. 
  #        tag_ident is of the form: 
  #          x.y.z for a vendor tag (3 subfields or 2 dots)
  #          x.y,  x.y.z.w, or x.y.z.w.u.v for a release tag
  #
  # Called by:
  #
  # input: tag_word - word from a RCS ,v file between the "symbols" and "locks"
  #                   keywords
  # output: type - 0 if tag_word contains packed info on a release tag
  #                1 if tag_word contains packed info on a vendor tag
  # output: tag_message - a vendortag or releasetag as entered when a cvs 
  #         checkin or import command was invoked
  # 
  # By: Eugene A. Lee, Aerospace Corporation
  # Date: Sept 15, 1995
  ##############################################################################
  upvar $type typ $tag_message tag_m
  set fields [split $tag_word :]
  set tag_m [string trimleft [lindex $fields 0]]
  set tag_num [string trimleft [lindex $fields 1]]
#puts "tag_num=$tag_num"
  # strip off any trailing ; character
  regsub {;$} $tag_num "" tag_num
#puts "   tag_num=$tag_num"
#set xx [split $tag_num . ]
#puts "xx=$xx $"
#set len [llength $xx]
#puts "len=$len"
  if { [llength [split $tag_num . ]]  == 3 } {
    set typ 1; # release tag
  } else {
    set typ 0; # vendor tag
  }
#puts "typ=$typ"
}
proc get_sort_list { in_list a_switch } {
  ##################################################################################
  # Compute a list which contains indices pointing to the order in which
  # the input list is sorted. Sorted list is not returned.
  # 
  # input: in_list - input list
  # input: a_switch - one switch to be used with the lsort command, i.e., -ascii, 
  #                   -integer, -real, -increasing, -decreasing
  #
  # Called by: get_rv_tags
  # return: indx_list - list of indices pointing to the order in which a local
  #         copy of in_list is sorted
  #
  # By: Eugene Lee, Aerospace Corporation, Sept. 16, 1995
  ###################################################################################
  set tmp_list $in_list
  set s_list [lsort $a_switch $tmp_list]
  set xx_pat "#!#!"; # any pattern which will never be an element of in_list
  set n [llength $in_list]

  for {set i 0} {$i < $n} {incr i} {
  # Step through sorted list and look for a match with an element of in_list
    set tmpi [lindex $s_list $i]
    set j 0
    while {$j < $n} {
      # Step through input list
      set tmpj [lindex $tmp_list $j]
      set k $j
      incr j
      if {$tmpj == $xx_pat} {continue}
      if {[string compare $tmpj $tmpi] == 0 } {
        # found one
        lappend index_list $k
        set tmp_list [lreplace $tmp_list $k $k $xx_pat]
        break
      }
    }
  }
#  puts "From get_sort_list, lindex_list=$index_list"
  return $index_list
}

proc sort_with_index_list { list s_list } {
  # Called by get_rv_tag
#puts "entered sort_with_index_list, list=$list  s_list=$s_list"
  set n [llength $list]
  if { $n != [llength $s_list] } {
    puts "Error in sort_with_index_list, length of list & s_list are not equal"
  }
  for {set i 0} {$i < $n} {incr i} {
    set j [lindex $s_list $i]
    lappend sorted_list [lindex $list $j]
  }
#puts "sorted_list=$sorted_list"
  return $sorted_list
}

proc get_rv_tags { r_tag_list v_tag_list } {
  #########################################################################
  # Read all ,v files in a CVS repository module and extract all packed
  # releasetag and vendortag words which are between the keywords "symbols"
  # "locks".
  #
  # Packed releasetag word has the format:
  #                releasetag:branch_id
  #   where: releasetag was specified when the cvs import command was invoked. 
  #          branch_id is of the forms: x.y, x.y.z.w, x.y.z.w.u.v, etc,
  #          (odd number or subfields)
  #
  # Packed vendortag word has the format:
  #                vendortag:branch_id 
  #   where: vendortag was specified when the cvs import command was invoked. 
  #          branch_id is of the forms: x.y.z (3 subfields or 2 dots)
  #
  # The output lists are created by processing each ,v file and appending to
  # the appropriate output list only if the releasetag or vendortag information
  # is new to the output list.
  #
  # Output: r_tag_list    - sorted releasetag list for the CVS module
  # Output: v_tag_list    - sorted vendortag list for the CVS module
  #
  # Note: v_tag_list has no planned use for tkcvs yet. They are returned just
  #       because this information was available.
  #         
  # By: Eugene A. Lee, Aerospace Corporation, November 12, 1995
  #########################################################################
  global merge
  upvar $v_tag_list vtag_list
  upvar $r_tag_list rtag_list
  set first_module 1
#puts "from get_rv_tags, pwd=[exec pwd]"
  foreach module [glob *,v] {
#puts ""
#puts "module=$module"
    set file [open $module r]
#puts "file=$file"
    while { [eof $file] == 0 } {
      set line [gets $file]
#puts "line=$line"
      if {[string range $line 0 6] == "symbols" } { 
        # Start of packed releasetag/vendortag
        set line_list [split $line]
        set nfields [llength $line_list]
        catch {unset rlist};   # rlist = releasetag of current file
        catch {unset vlist};   # vlist = vendortag for current file

        if {$nfields > 1 } {
          # release and vendor tags are on the same line that "symbol" is on.
          # (Assumes that next line will be "locks")
#puts "format 1 line=$line"
          for {set i 1} {$i < 3} {incr i} {
            set tmp [string trimleft [lindex $line_list [expr $nfields - $i]]]
            unpack_tag_word $tmp type tag_message
#puts "tmp=$tmp"
#puts "type=$type"
            lappend tlist $type
            if {$type == 0 } {
              lappend rlist $tag_message
#puts "rlist=$rlist"
            }
            if {$type == 1 } {
              lappend vlist $tag_message
            }
          }
          break; # Assumes that next line will be "locks"
        } else {
          # release and vendor tags on separate lines following the symbol line
#puts "format 2"
          while { 1 > 0 } {
            set line [gets $file]
#puts "line=$line"
            if { [string range $line 0 4 ] == "locks" } {break}
            unpack_tag_word $line type tag_message
#puts "type=$type"
            lappend tlist $type
            if {$type == 0 } {
              lappend rlist $tag_message
            } else {
              lappend vlist $tag_message
            }
          }
        }          
      }
    }
    close $file
    # Compile master list of all releasetag and vendortag info for the CVS
    # module
    if {$first_module == 1 } {
#puts "first_module entered"

      if { [info exists rlist] == 1 } {
        set mrlist $rlist;     # mrlist = master releasetag list
#puts "mrlist=$mrlist"
      }
      if { [info exists vlist] == 1 } {
#puts "vlist=$vlist"
        set mvlist $vlist;     # vrlist = master vendortag list
      }
#puts "mvlist=$mvlist"
      set first_module 0
    } else {
      # Add to rtag_list only if it is a new release tag 
      if { [info exists rlist] == 1 } {
        for {set i 0} {$i < [llength $rlist] } {incr i} {
          set tmp_rel [lindex $rlist $i]
          set new_rel 1
          foreach rel $mrlist {
#puts "tmp_rel=$tmp_rel   rel=$rel"
            if { [string compare $tmp_rel $rel ] == 0 } {
              set new_rel 0
              break
            }
          }
          if { $new_rel == 1 } {
            # Found a new release tag
#puts "       $tmp_rel is a new release tag"
             lappend mrlist [lindex $rlist $i]
#puts "       mrlist=$mrlist"
          }
        }
      }
      # Add to vtag_list only if it is a new vendor tag 

      if { [info exists vlist] == 1 } {
        for {set i 0} {$i < [llength $vlist] } {incr i} {
          set tmp_ven [lindex $vlist $i]
          set new_ven 1
          foreach ven $mvlist {
#puts "tmp_ven=$tmp_ven   ven=$ven"
            if { [string compare $tmp_ven $ven ] == 0 } {
              set new_ven 0
              break
            }
          }
          if { $new_ven == 1 } {
            # Found a new vendor tag
#puts "       $tmp_ven is a new vendor tag"
             lappend mvlist [lindex $vlist $i]
#puts "       mvlist=$mvlist"
          }
        }
      }
    }  
  }
  # Unsorteded master releasetag and versiontag lists have been found.
#puts "unsorted release and version tag list have been found"
  if { [info exists mrlist] == 1 } {
    set rtag_list [lsort $mrlist]
#puts "rtag_list=$rtag_list"
  } else {
    puts "no mrlist created"
  }
  if { [info exists mvlist] == 1 } {
    set vtag_list [lsort $mvlist]
#puts "vtag_list=$vtag_list"
  } else {
    puts "no mvlist created"
  }
  
}

