#!/bin/sh
# the next line restarts using tclsh \
exec tclsh "$0" -- ${1+"$@"}


proc cleanup_old {} {

  set oldirs [glob -nocomplain -- rcs_test*]
  foreach od $oldirs {
    puts "Deleting $od"
    file delete -force $od
  }
  puts "==============================="
}

proc checkin_files {topdir} {
  global WD
  
  puts "==============================="
  file mkdir RCS

  puts "IMPORTING FILES $topdir"
  # Check in files
  foreach n {1 2 3 4} {
    set filename File$n.txt
    set rcsfile RCS/$filename,v
    # Escape the spaces in filenames
    regsub -all { } $filename {\ } filename
    regsub -all { } $rcsfile {\ } rcsfile
    set exec_cmd "ci -u -i -t-small_text_file -m\"Initial\\\ checkin\" $filename $rcsfile"
    puts "$exec_cmd"
    set ret [catch {eval "exec $exec_cmd"} out]
    puts $out
  }
  foreach filename { FTags.txt "File Spc.txt" } {
    set rcsfile RCS/$filename,v
    # Escape the spaces in filenames
    regsub -all { } $filename {\ } filename
    regsub -all { } $rcsfile {\ } rcsfile
    set exec_cmd "ci -u -i -t-small_text_file -m\"Initial\\\ checkin\" $filename $rcsfile"
    puts "$exec_cmd"
    set ret [catch {eval "exec $exec_cmd"} out]
    puts $out
  }
  foreach D {Dir1 "Dir 2"} {
    puts $D
    cd $D
    file mkdir RCS
    foreach n {1 2 " 3"} {
      set rcsfile RCS/F$n.txt,v
      # Escape the spaces in filenames
      regsub -all { } F$n.txt {\ } F$n.txt
      regsub -all { } $rcsfile {\ } rcsfile
      set exec_cmd "ci -u -i -t-small_text_file -m\"Initial\\\ checkin\" F$n.txt $rcsfile"
      puts "$exec_cmd"
      set ret [catch {eval "exec $exec_cmd"} out]
      puts $out
    }
    cd $topdir
  }
}

proc checkout_files {topdir} {
  global WD

  cd $topdir
  puts "==============================="
  puts "CHECKING OUT"

  set globpat "RCS/*,v"
  regsub -all { } $globpat {\ } globpat
  set exec_cmd "co -f -l [glob $globpat]"
  puts "$exec_cmd"
  set ret [catch {eval "exec $exec_cmd"} out]
  puts $out

  foreach D {Dir1 "Dir 2"} {
    cd $D
    set globpat "RCS/*,v"
    regsub -all { } $globpat {\ } globpat
    set exec_cmd "co -f -l [glob $globpat]"
    puts "$exec_cmd"
    set ret [catch {eval "exec $exec_cmd"} out]
    puts $out
    cd $topdir
  }
  puts "CHECKOUT FINISHED"
}

proc tag {tag revision obj} {
  set exec_cmd "rcs -n$tag:$revision $obj"
  puts "$exec_cmd"
  set ret [catch {eval "exec $exec_cmd"} out]
  puts $out
}

proc writefile {filename string} {
  puts " append \"$string\" to $filename"
  set fp [open "$filename" a]
  puts $fp $string
  close $fp
}

proc write_funny_files {} {
  puts "Creating utf-8 file"
  set fid1 [open "code-utf-8.txt" w]
  chan configure $fid1 -encoding utf-8
  puts $fid1 "€20" 
  chan close $fid1

  puts "Creating iso8859-1 file"
  set fid2 [open "code-iso8859-1.txt" w]
  chan configure $fid2 -encoding iso8859-1
  puts $fid1 "Copyright © 2025"
  chan close $fid2
}

proc addfile {filename} {

  puts "Add $filename"
  set exec_cmd "ci -u -i -t-small_text_file -m\"Initial\\\ checkin\" $filename"
  puts "$exec_cmd"
  set ret [catch {eval "exec $exec_cmd"} out]
  puts $out
  set exec_cmd "co -l $filename"
  puts "$exec_cmd"
  set ret [catch {eval "exec $exec_cmd"} out]
  puts $out
}

proc delfile {filename} {

  puts "Delete $filename"
  file delete $filename
  file delete RCS/$filename,v
}

proc lock {filename} {

  puts "Lock $filename"
  set exec_cmd "rcs -l $filename"
  set ret [catch {eval "exec $exec_cmd"} out]
  puts $out
}

proc getrev {filename} {
  # Find out current revision

  set exec_cmd "rcs log -b $filename"
  puts "$exec_cmd"
  set ret [catch {eval "exec $exec_cmd"} out]
  #puts $out
  foreach logline [split $out "\n"] {
    if {[string match "revision *" $logline]} {
      set latest [lindex $logline 1]
      break
    }
  }
  puts "latest rev is $latest"
  return $latest
}

proc conflict {filename} {
  # Create a conflict

  set latest [getrev $filename]
  # Save a copy
  file copy $filename Ftmp.txt
  # Make a change
  set exec_cmd "rcs -l $filename"
  puts "$exec_cmd"
  set ret [catch {eval "exec $exec_cmd"} out]
  file attributes $filename -permissions u+w
  writefile $filename "Conflict A"
  set exec_cmd "ci -m\"change1\" $filename"
  puts "$exec_cmd"
  set ret [catch {eval "exec $exec_cmd"} out]
  puts $out
  # Check out previous revision
  set exec_cmd "co -l -r$latest $filename"
  puts "$exec_cmd"
  set ret [catch {eval "exec $exec_cmd"} out]
  puts $out
  # Make a different change (we hope)
  file delete -force -- $filename
  file rename Ftmp.txt $filename
  file attributes $filename -permissions u+w
  writefile $filename "Conflict B"
  # When we check in a conflicting version, it creates
  # a branch
  set exec_cmd "ci -m\"change2\\\ conflicting\" $filename"
  puts "$exec_cmd"
  set ret [catch {eval "exec $exec_cmd"} out]
  puts $out
  # Check out the branch
  set exec_cmd "co -r1.2.1 $filename"
  puts "$exec_cmd"
  set ret [catch {eval "exec $exec_cmd"} out]
  puts $out
}

proc commit {comment} {
  puts "COMMIT"
  puts [pwd]
  set tmpfile "list.tmp"
  file delete -force $tmpfile

  puts "Finding RCS files"
  if {[ info exists env(SystemDrive) ]} {
    puts "Must be a PC"
    set ret [catch {eval "exec [auto_execok dir] /b F*.txt /s > $tmpfile"} out]
  } else {
    set ret [catch {eval "exec find . -name F*.txt -o -name RCS -prune -a -type f > $tmpfile"} out]
  }
  if {$ret} {
    puts $out
    puts "Find failed"
    exit 1
  }
  puts "CHECKING IN FILES"
  regsub -all { } $comment {_} comment
  set fl [open $tmpfile r]
  while { [gets $fl item] >= 0} {
    regsub -all { } $item {\ } filename
    regsub -all { } $comment {\\\ } comment
    #set exec_cmd "ci -u -t-small_text_file -m\"$comment\" $filename"
puts " $filename"
    set exec_cmd "ci -u -m\"$comment\" \"$filename\""
    puts $exec_cmd
    set ret [catch {eval "exec $exec_cmd"} out]
    puts $out
  }
  close $fl
  file delete -force $tmpfile
}

proc mkfiles {topdir} {
  global WD

  puts "MAKING FILETREE"
  file mkdir "$topdir"
  cd $topdir

  # Make some files each containing a random word
  foreach n {1 2 3 4} {
    writefile File$n.txt "Initial"
  }
  writefile "File Spc.txt" "Initial"
  writefile FTags.txt "Initial"
  write_funny_files
  foreach D {Dir1 "Dir 2"} {
    puts $D
    file mkdir $D
    cd $D
    foreach n {1 2 " 3"} {
      writefile F$n.txt "Initial"
    }
    cd $topdir
  }
  # Plain, empty directory
  file mkdir Dir3
  file mkdir "Dir1/New dir"
}

proc modfiles {string} {
  global tcl_platform

  puts "MODIFYING FILES"
  set tmpfile "list.tmp"
  file delete -force $tmpfile

  puts "Finding RCS files"
  if {$tcl_platform(platform) eq "windows"} {
    puts "Must be a PC"
    set ret [catch {eval "exec [auto_execok dir] /b F*.txt /s > $tmpfile"} out]
  } else {
    set ret [catch {eval "exec find . -name F*.txt -o -name RCS -prune -a -type f > $tmpfile"} out]
  }
  if {$ret} {
    puts $out
    puts "Find failed"
    exit 1
  }
  set fl [open $tmpfile r]
  while { [gets $fl item] >= 0} {
    # Why didn't co -l make it writeable?
    file attributes $item -permissions u+w
    writefile $item "$string"
  }
  close $fl
  file delete -force $tmpfile
}

##############################################

if [file isdirectory RCS] {
  puts "Please don't do that here.  There's already an RCS directory."
  exit 1
}

set WD [pwd]
set testdir "$WD/rcs_test"
cleanup_old
mkfiles $testdir
checkin_files $testdir
checkout_files $testdir

puts "==============================="
puts "First revision"
puts "** modfiles"
modfiles "Main 1"
puts "** commit"
commit "First Revision"
puts "** writefile"
writefile Fnew.txt "Main 1"
puts "** addfile"
addfile Fnew.txt

puts "==============================="
puts "Second revision"
checkout_files $testdir
modfiles "Main 2"
commit "Second revision"
foreach t {one ten one_hundred one_thousand ten_thousand one_hundred_thousand} {
  tag "tag_$t" 1.2 FTags.txt
}
tag "one" 1.2 "Dir1/F1.txt"

puts "==============================="
puts "Making Uncommitted changes"
#Local only
writefile FileLocal.txt "Pending"
# Deleted
delfile File3.txt
# Modify
file attributes File2.txt -permissions u+w
writefile File2.txt "Pending"
file attributes F-utf-8.txt -permissions u+w
writefile "F-utf-8.txt" "\xA53378" "utf-8"
file attributes F-iso8859-1.txt -permissions u+w
writefile "F-iso8859-1.txt" "\xA9 2022-2024" "iso8859-1"
lock File2.txt
# Conflict
puts "** conflict"
conflict Fnew.txt
cd $WD

