David Gravereaux <[EMAIL PROTECTED]> wrote:

>I can't seem to get the right combination with the following scenario:
>
>  1) I only have read access to the repository.
>  2) I want to create a diff that will contain the new files along with
>     diffs against the modified ones to email to the maintainer.

never mind.  I figured it out.  Here's the macro to do it.
--
* David Gravereaux *
Tomahawk Software Group

If knowlege is power, how come the more I learn, the more I realize how much I don't 
know?
That isn't very empowering.
#!CVSGUI1.0 --selection  --name "Prepare patch from [pwd]"
# --------------------------------------------------------------------
#  prep_patch.tcl  --
#
#  A macro for WinCVS to generate error-free(tm) diffs all set to
#  email the maintainer of the module.
#
#  New files are diff'ed against a nul target to make a pure add
#  difference with an external diff program.  Modified repository
#  files are diff'd with CVS.  Paths are modified in the patchfile
#  to ensure patch.exe understands what goes where without error.
#
#  The directory patch.txt is written to coresponds (exactly) to the
#  directory patch.exe should be run by the maintainer and will only
#  require 2 switches:
#
#    C:\Some\Path\To\A\CVSWorkingCopy\> patch.exe -c < patch.txt
#  or                   "               patch.exe -c -i patch.txt
#
#  you may even drop -c if you want.
#
#  UNIX users of patch.txt may need to correct for <EOL> or add
#  --ignore-whitespace to the patch commandline.
#
#  author: David Gravereaux <[EMAIL PROTECTED]>  3:36 PM 4/6/2000
#
#  RCS: @(#) $Id: prep_patch.tcl,v 1.4 2000/04/07 02:49:27 davygrvy Exp $
# --------------------------------------------------------------------

set newFiles [list]
set cvsFiles [list]
set root [pwd]
set outFile [file join $root patch.txt]

# diff.exe included with WinCVS 1.1b12 is broken.
# It crashes with the -N switch and nul as target1.
# ex.  c:\> diff -c -N nul somefile.c > patchfile
#
# WinCVS's patch.exe is even more screwed, too.
#
set ourDiffApp "C:/cygnus/cygwin-b20/H-i586-cygwin32/bin/diff.exe"


proc iterate {dirName relativeDir {ignoreFile ""}} {
  global newFiles cvsFiles
  set toRecurse [list]

  cvsentries $dirName browsit

  foreach file [browsit get] {
    browsit info $file fileInfo

    # an odd form of mental logic tells me that if a .cvsignore
    # file exists and is not under version control, we would not
    # want to diff it with this script.
    #
    if {![string compare $fileInfo(kind) "file"] &&
        !$fileInfo(ignored)  &&
        [string compare $ignoreFile $fileInfo(name)] != 0} {

      if {$fileInfo(modified)} {
        lappend cvsFiles [file join $relativeDir $fileInfo(name)]
      } elseif {$fileInfo(unknown) && [string compare $fileInfo(name) ".cvsignore"] != 
0} {
        lappend newFiles [file join $relativeDir $fileInfo(name)]
      }
    }

    if {![string compare $fileInfo(kind) "folder"] &&
        !$fileInfo(missing) &&
        !$fileInfo(ignored)} {
      lappend toRecurse [list $file [file join $relativeDir $fileInfo(name)]]
    }
  }

  foreach dir $toRecurse {
    set cmdline "iterate $dir"
    eval $cmdline
  }
}


proc diffNEW {fileName} {
  global ourDiffApp out
  set lines [list]
  set diffPipe [open "|$ourDiffApp -c -N nul $fileName" r]
  fconfigure $diffPipe -buffering line
  while {![eof $diffPipe]} {
    lappend lines [gets $diffPipe]
  }

  # diff.exe returns an errorcode.  Ignore it with catch.
  catch {close $diffPipe}

  if {[llength $lines] == 2} {
    # must have been a binary file by accident...
    return
  }

  cvsout "  Added: $fileName\n"
  set lines [lreplace $lines 0 0 "*** [lindex [lindex $lines 1] 1]\tWed Dec 31 
14:00:00 1969"]

  foreach line $lines {
    puts $out $line
  }
  flush $out
}


proc diffCVS {fileName} {
  global out
  set lines [list]
  set diffPipe [open "|cvs.exe diff -c $fileName" r]
  fconfigure $diffPipe -buffering line
  while {![eof $diffPipe]} {
    lappend lines [gets $diffPipe]
  }
  catch {close $diffPipe}

  cvsout "  Added: $fileName\n"

  # strip most of the header 'cause it's junk.
  set lines [lreplace $lines 0 4]

  # replace the filenames with the relative path one.
  # the form is: "*** <filename>\t<timestamp>[\t<revision>]
  #
  set f_t_rList1 [split [lindex $lines 0] \t]
  set firstline  "*** [join [lreplace $f_t_rList1 0 0 $fileName] \t]"

  set f_t_rList2 [split [lindex $lines 1] \t]
  set secondline "--- [join [lreplace $f_t_rList2 0 0 $fileName] \t]"

  set lines [lreplace $lines 0 1 $firstline $secondline]

  # write it out.
  foreach line $lines {
    puts $out $line
  }
  flush $out
}

cvsout "Iterating directories...\n"
iterate $root "" [file tail $outFile]

cd $root
set out [open $outFile w]

cvsout "Diff'ing new files locally...\n"
foreach newFile $newFiles {
  diffNEW $newFile
}

cvsout "Diff'ing modified files...\n"
foreach cvsFile $cvsFiles {
  diffCVS $cvsFile
}
close $out

cvsout "$outFile created. Done!\n"

Reply via email to