mkCTM revision 7463
16563Sphk#!/usr/local/bin/tcl
22886Sphk
36563Sphk#############################################################################
46563Sphk### Add something
56563Sphk#############################################################################
66563Sphk# Type Name Mode User Group Barf Size Hash
72926Sphk
86563Sphkproc CTMadd {t n m u g b s h} {
96563Sphk    global fo_files fo_mkdir changes CTMref
102886Sphk
116563Sphk    puts stderr "A $b  $t  $n"
126563Sphk    incr changes
133833Sphk
146563Sphk    if {$t == "d"} {
156563Sphk	puts $fo_mkdir "CTMDM $n $u $g $m"
166563Sphk    } elseif {$t == "f"} {
176563Sphk	puts $fo_files "CTMFM $n $u $g $m $h $s"
186563Sphk	flush $fo_files
196563Sphk	exec cat $CTMref/$n >@ $fo_files
206563Sphk	puts $fo_files ""
216563Sphk    } else {
226563Sphk	puts "confused in CTMadd"
236563Sphk	exit 0
246553Sphk    }
256553Sphk}
265014Sphk
276563Sphk#############################################################################
286563Sphk### Delete something
296563Sphk#############################################################################
302886Sphk# Type Name Mode User Group Barf Size Hash
312886Sphk
322886Sphkproc CTMdel {t n m u g b s h} {
337463Sphk    global fo_del fo_rmdir changes damage max_damage CTMlock
346563Sphk
352886Sphk    puts stderr "D $b  $t  $n"
366563Sphk    incr damage 
376563Sphk    incr changes
386563Sphk
396563Sphk    if {$damage > $max_damage} {
407463Sphk	exec rm -f $CTMlock
417463Sphk	return
426563Sphk    }
432886Sphk    if {$t == "d"} {
442886Sphk	puts $fo_rmdir "CTMDR $n"
456563Sphk    } elseif {$t == "f"} {
466563Sphk	puts $fo_del "CTMFR $n $h"
476563Sphk    } else {
486563Sphk	puts "confused in CTMdel"
496563Sphk	exit 0
502886Sphk    }
512886Sphk}
526563Sphk
536563Sphk#############################################################################
546563Sphk### Change something
556563Sphk#############################################################################
566563Sphk# Type Name Mode User Group Barf Size Hash
576563Sphk
582886Sphkproc CTMchg {t1 n1 m1 u1 g1 b1 s1 h1 t2 n2 m2 u2 g2 b2 s2 h2} {
596563Sphk    global fo_files CTMref CTMcopy changes damage CTMscratch
606563Sphk
616563Sphk    # Ignore attribute changes for directories
626563Sphk    if {$t1 == "d" && $t2 == "d"} return
636563Sphk
646563Sphk    # turn file into dir or vice versa...
656563Sphk    if {$t1 != $t2} {
662886Sphk	CTMdel $t1 $n1 $m1 $u1 $g1 $b1 $s1 $h1
672886Sphk	CTMadd $t2 $n2 $m2 $u2 $g2 $b2 $s2 $h2
682886Sphk	return
692886Sphk    }
706563Sphk
716563Sphk    # only files allowed past this poing...
726563Sphk    if {$t1 != "f" && $t2 != "f"} {
736563Sphk        puts "confused in CTMchg"
746563Sphk        exit 0
752886Sphk    }
766563Sphk
776563Sphk    # Ignore attribute changes for files
786563Sphk    if {"x$h1" == "x$h2" && $s1 == $s2} return
796563Sphk
806563Sphk    if {$s2 == 0} { incr damage }
816563Sphk    incr changes
826563Sphk
836563Sphk    # If diff will deal with it...
842948Sphk    if {$b1 == "0" && $b2 == "0"} {
856563Sphk	set i [catch "exec diff -n $CTMcopy/$n1 $CTMref/$n2 > $CTMscratch" j]
866563Sphk	set s [file size $CTMscratch]
872926Sphk	if {$s < $s2} {
883112Sphk	    puts stderr "E $b1$b2 $t1$t2 $n1"
892971Sphk	    puts $fo_files "CTMFN $n1 $u2 $g2 $m2 $h1 $h2 $s"
902926Sphk	    flush $fo_files
916563Sphk	    exec cat $CTMscratch >@ $fo_files
922926Sphk	    puts $fo_files ""
932926Sphk	    return
942926Sphk	}
956563Sphk    } 
962926Sphk    puts stderr "R $b1$b2 $t1$t2 $n1"
972926Sphk    puts $fo_files "CTMFS $n2 $u2 $g2 $m2 $h1 $h2 $s2"
982886Sphk    flush $fo_files
996563Sphk    exec cat $CTMref/$n2 >@ $fo_files
1002886Sphk    puts $fo_files ""
1012886Sphk}
1022886Sphk
1036563Sphk#############################################################################
1046563Sphk### Do we already have this delta ?
1056563Sphk#############################################################################
1066563Sphk
1076563Sphkproc find_delta {nbr} {
1086563Sphk    global CTMname CTMdest
1096563Sphk    if {[file exists [format "%s/$CTMname.%04d" $CTMdest $nbr]]} { return 1 }
1106563Sphk    if {[file exists [format "%s/$CTMname.%04d.gz" $CTMdest $nbr]]} { return 1 }
1116563Sphk    return 0
1126563Sphk}
1136563Sphk
1146563Sphk#############################################################################
1156563Sphk### The top level code...
1166563Sphk#############################################################################
1176563Sphk
1186563Sphkset CTMSW	/home/ctm/SW
1196563Sphk
1206563Sphkcd $CTMSW
1216563Sphk
1226563Sphk# Defaults...
1236563Sphkset CTMapply 1
1246563Sphkset CTMdont {^///}
1256563Sphkset CTMmail {}
1266563Sphkset CTMsuff {}
1276563Sphkset CTMdate     [exec date -u +%Y%m%d%H%M%SZ]
1286563Sphkset CTMtmp  {}
1296563Sphkset CTMcopy  {}
1306563Sphkset CTMdest  {}
1316563Sphkset CTMprefix  .
1326563Sphkset CTMtest 0
1336777Sphkset CTMspecial 0
1347463Sphkset CTMscan .
1357463Sphkset CTMfirst 0
1367463Sphkset max_damage 1200
1376563Sphk
1386563Sphkset damage 0
1396563Sphkset changes 0
1406563Sphk
1416563Sphksource $argv
1426563Sphk
1436563Sphkif {$CTMtmp == ""} {
1446563Sphk    set CTMtmp $CTMSW/../tmp/${CTMname}_${CTMsuff}
1456563Sphk}
1466563Sphkif {$CTMcopy == ""} {
1476563Sphk    set CTMcopy $CTMSW/../$CTMname
1486563Sphk}
1496563Sphkif {$CTMdest == ""} {
1506563Sphk    set CTMdest $CTMSW/../CTM-pub/$CTMname
1516563Sphk}
1526563Sphk
1536788Sphk# Make sure we only run one at a time...
1546788Sphk
1556788Sphkset CTMlock Lck.${CTMname}.${CTMdate}.[id process]
1566788Sphkexec rm -f ${CTMlock}
1576788Sphkexec echo starting > ${CTMlock}
1587463Sphkif {[catch "exec ln $CTMlock LCK.$CTMname" a]} {
1596788Sphk	puts "Not going, lock exists..."
1606788Sphk	exec rm -f $CTMlock
1617463Sphk	exit 0
1626788Sphk}
1636788Sphkexec rm -f $CTMlock
1646788Sphkset CTMlock LCK.$CTMname
1656788Sphk
1666563Sphkset CTMscratch ${CTMtmp}.tmp
1676563Sphk
1682886Sphkwhile 1 {
1696777Sphk    if { ! $CTMspecial} {
1707463Sphk	if {$CTMfirst} {
1717463Sphk		set CTMnbr 0
1727463Sphk	} else {
1737463Sphk		set CTMnbr [lindex [exec cat $CTMcopy/.ctm_status] 1]
1747463Sphk	}
1752886Sphk
1767463Sphk	if {$CTMnbr > 0 && ![find_delta $CTMnbr]} {
1776563Sphk	    puts "$CTMname delta $CTMnbr doesn't exist..."
1786788Sphk	    exec rm -f $CTMlock
1796788Sphk	    exit 0
1806563Sphk	}
1812886Sphk
1826563Sphk	incr CTMnbr
1832886Sphk
1846563Sphk	if {[find_delta $CTMnbr]} {
1856563Sphk	    puts "$CTMname delta $CTMnbr does already exist..."
1866788Sphk	    exec rm -f $CTMlock
1876563Sphk	    exit 0
1886563Sphk	}
1892886Sphk
1906563Sphk	set fo [open $CTMref/.ctm_status w]
1916563Sphk	puts $fo "$CTMname $CTMnbr"
1926563Sphk	close $fo
1936563Sphk	incr changes -1
1943833Sphk
1956563Sphk    } else {
1966563Sphk	set CTMnbr [lindex [exec cat $CTMref/.ctm_status] 1]
1976777Sphk    }
1986777Sphk
1996777Sphk    if {"$CTMcopy" == "" } { 
2006563Sphk	set f1 [open /dev/null]
2016777Sphk    } else {
2027463Sphk	set f1 [open "| ./ctm_scan $CTMcopy $CTMscan"]
2032926Sphk    }
2042926Sphk
2056777Sphk    puts "Doing CTMname $CTMname CTMnbr $CTMnbr$CTMsuff CTMdate $CTMdate"
2066563Sphk    flush stdout
2076563Sphk    exec sh -c "rm -f ${CTMtmp}.* ${CTMtmp}:*" >&@ stdout
2082886Sphk
2097463Sphk    set f2 [open "| ./ctm_scan $CTMref $CTMscan"]
2102886Sphk
2116563Sphk    set fo_del   [open $CTMtmp.del w]
2126563Sphk    set fo_rmdir [open $CTMtmp.rmdir w]
2136563Sphk    set fo_mkdir [open $CTMtmp.mkdir w]
2146563Sphk    set fo_files [open $CTMtmp.files w]
2155014Sphk
2166563Sphk    set l1 ""
2176563Sphk    set l2 ""
2185014Sphk
2196563Sphk    while 1 {
2206563Sphk
2216563Sphk	if {$l1 == ""} {gets $f1 l1}
2226563Sphk
2236563Sphk	if {$l2 == ""} {gets $f2 l2}
2246563Sphk	
2256563Sphk	if {$l1 == "" && $l2 == ""} break
2266563Sphk
2276563Sphk	set n1 [lindex $l1 1]
2286563Sphk	set n2 [lindex $l2 1]
2296563Sphk
2306563Sphk	if {[regexp $CTMdont /$n1]} { set l1 "" ; continue }
2316563Sphk	if {[regexp $CTMdont /$n2]} { set l2 "" ; continue }
2326563Sphk
2336563Sphk	# they're all the same...
2346563Sphk	if {$l1 == $l2}  { set l1 "" ; set l2 "" ; continue }
2356563Sphk
2366563Sphk	if {$l1 == "" }   { eval CTMadd $l2 ; set l2 "" ; continue }
2376563Sphk
2386563Sphk	if {$l2 == "" }   { eval CTMdel $l1 ; set l1 "" ; continue }
2396563Sphk
2406563Sphk	# if the name is the same we're safe...
2416563Sphk	if {$n1 == $n2}  { 
2426563Sphk	    eval CTMchg $l1 $l2
2436563Sphk	    set l1 ""
2446563Sphk	    set l2 "" 
2456563Sphk	    continue 
2466563Sphk	}
2476563Sphk
2486563Sphk	# To avoid this anomaly:
2496563Sphk	# A -  d  src/gnu/lib/libreadline/readline/Attic
2506563Sphk	# A 0  f  src/gnu/lib/libreadline/readline/Attic/readline.h,v
2516563Sphk	# A 0  f  src/gnu/lib/libreadline/readline.c,v
2526563Sphk	# D 0  f  src/gnu/lib/libreadline/readline/readline.h,v
2536563Sphk	# D 0  f  src/gnu/lib/libreadline/readline.c,v
2546563Sphk	# we have to make things somewhat complicated...
2556563Sphk
2566563Sphk	# if they have the same number of components...
2576563Sphk	set ll1 [llength [split $n1 /]]
2586563Sphk	set ll2 [llength [split $n2 /]]
2596563Sphk	if {$ll1 == $ll2} {
2606563Sphk	    if {$n1 < $n2 } { 
2616563Sphk		eval CTMdel $l1 ; set l1 "" ; continue 
2626563Sphk	    } else {
2636563Sphk		eval CTMadd $l2 ; set l2 "" ; continue 
2646563Sphk	    }
2656563Sphk	} 
2666563Sphk	if {$ll1 < $ll2} {
2676563Sphk		eval CTMadd $l2 ; set l2 "" ; continue 
2685014Sphk	} else {
2696563Sphk		eval CTMdel $l1 ; set l1 "" ; continue 
2705014Sphk	}
2715014Sphk    }
2725014Sphk
2736563Sphk    close $fo_del
2746563Sphk    close $fo_rmdir
2756563Sphk    close $fo_mkdir
2766563Sphk    close $fo_files
2772886Sphk
2786563Sphk    if {$damage > $max_damage} {
2796563Sphk	puts "Too much damage: $damage deletes"
2806563Sphk	exec sh -c "rm -f ${CTMtmp}.*"
2816788Sphk        exec rm -f $CTMlock
2826563Sphk	exit 0
2836563Sphk    }
2842886Sphk
2856563Sphk    if {!$changes} {
2866563Sphk	puts "no changes"
2876563Sphk	exec sh -c "rm -f ${CTMtmp}.*"
2886788Sphk        exec rm -f $CTMlock
2896563Sphk	exit 0
2906563Sphk    }
2912886Sphk
2926563Sphk    exec echo CTM_BEGIN 2.0 $CTMname $CTMnbr $CTMdate $CTMprefix > $CTMtmp.begin
2932886Sphk
2946563Sphk    puts "Assembling delta"
2956563Sphk    flush stdout
2966563Sphk    set  nm [format "%s.%04d%s" $CTMname $CTMnbr $CTMsuff]
2972886Sphk
2986777Sphk    set fdout [open "| /sbin/md5 -p | gzip -9 > ${CTMtmp}:${nm}.gz" w]
2993112Sphk
3006563Sphk    foreach i {begin del rmdir mkdir files} {
3016563Sphk	exec cat $CTMtmp.$i >@$fdout
3026563Sphk    }
3036563Sphk    puts $fdout "CTM_END " nonewline
3046563Sphk    close $fdout ; unset fdout
3053112Sphk
3066563Sphk    exec sh -x -c "rm -f ${CTMtmp}.*" >&@ stdout
3075014Sphk
3086563Sphk    if {$CTMtest} {
3096563Sphk	puts "testing, stopping now."
3106788Sphk        exec rm -f $CTMlock
3116563Sphk	exit 0
3126563Sphk    }
3136563Sphk    if {$CTMapply} {
3146563Sphk	    puts "Applying delta"
3156563Sphk	    flush stdout
3166788Sphk	    exec echo now applying > $CTMlock
3176563Sphk	    exec sh -e -x -c "cd $CTMcopy ; $CTMSW/ctm -v -v -v ${CTMtmp}:${nm}.gz" >&@ stdout
3186788Sphk	    exec echo did apply > $CTMlock
3196563Sphk    }
3206563Sphk    puts "Moving delta"
3216563Sphk    flush stdout
3226563Sphk    exec mv ${CTMtmp}:${nm}.gz $CTMdest/.CTMtmp_${nm}.gz >&@ stdout
3236563Sphk    exec mv $CTMdest/.CTMtmp_${nm}.gz $CTMdest/${nm}.gz >&@ stdout
3246788Sphk    exec echo moved > $CTMlock
3256563Sphk
3266563Sphk    if {$CTMmail != ""} {
3276563Sphk	puts "Mailing delta"
3286563Sphk	flush stdout
3296777Sphk	exec $CTMSW/ctm_smail -m 100000 -c 3000000 $CTMdest/${nm}.gz $CTMmail >&@ stdout
3306563Sphk    }
3316788Sphk    exec echo mailed > $CTMlock
3326563Sphk
3336563Sphk    # If we did an absolute delta: stop.
3346563Sphk    if {$CTMsuff != ""} break
3356563Sphk
3366563Sphk    # Make a absolute delta (!) every 100 deltas
3377463Sphk    if {$CTMnbr == 0 || ($CTMnbr % 100)} break
3386563Sphk
3396563Sphk    # Make an absolute delta too...
3406563Sphk    set CTMref $CTMcopy
3416563Sphk    set CTMsuff A
3426563Sphk    set CTMcopy ""
3436563Sphk    set CTMmail ""
3446563Sphk    set CTMapply 0
3456777Sphk    set CTMspecial 1
3467463Sphk    exec rm -f $CTMlock
3475014Sphk}
3486563Sphkputs "done."
3496788Sphkexec rm -f $CTMlock
350