mkCTM revision 6788
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} {
336563Sphk    global fo_del fo_rmdir changes damage max_damage
346563Sphk
352886Sphk    puts stderr "D $b  $t  $n"
366563Sphk    incr damage 
376563Sphk    incr changes
386563Sphk
396563Sphk    if {$damage > $max_damage} {
406563Sphk	puts "Too much damage"
416563Sphk	exit 0
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
1346563Sphkset max_damage 100
1356563Sphk
1366563Sphkset damage 0
1376563Sphkset changes 0
1386563Sphk
1396563Sphksource $argv
1406563Sphk
1416563Sphkif {$CTMtmp == ""} {
1426563Sphk    set CTMtmp $CTMSW/../tmp/${CTMname}_${CTMsuff}
1436563Sphk}
1446563Sphkif {$CTMcopy == ""} {
1456563Sphk    set CTMcopy $CTMSW/../$CTMname
1466563Sphk}
1476563Sphkif {$CTMdest == ""} {
1486563Sphk    set CTMdest $CTMSW/../CTM-pub/$CTMname
1496563Sphk}
1506563Sphk
1516788Sphk# Make sure we only run one at a time...
1526788Sphk
1536788Sphkset CTMlock Lck.${CTMname}.${CTMdate}.[id process]
1546788Sphkexec rm -f ${CTMlock}
1556788Sphkexec echo starting > ${CTMlock}
1566788Sphkif {[catch "ln $CTMlock LCK.$CTMname" a]} {
1576788Sphk	puts "Not going, lock exists..."
1586788Sphk	exec rm -f $CTMlock
1596788Sphk}
1606788Sphkexec rm -f $CTMlock
1616788Sphkset CTMlock LCK.$CTMname
1626788Sphk
1636563Sphkset CTMscratch ${CTMtmp}.tmp
1646563Sphk
1652886Sphkwhile 1 {
1666777Sphk    if { ! $CTMspecial} {
1676563Sphk	set CTMnbr [lindex [exec cat $CTMcopy/.ctm_status] 1]
1682886Sphk
1696563Sphk	if {![find_delta $CTMnbr]} {
1706563Sphk	    puts "$CTMname delta $CTMnbr doesn't exist..."
1716788Sphk	    exec rm -f $CTMlock
1726788Sphk	    exit 0
1736563Sphk	}
1742886Sphk
1756563Sphk	incr CTMnbr
1762886Sphk
1776563Sphk	if {[find_delta $CTMnbr]} {
1786563Sphk	    puts "$CTMname delta $CTMnbr does already exist..."
1796788Sphk	    exec rm -f $CTMlock
1806563Sphk	    exit 0
1816563Sphk	}
1822886Sphk
1836563Sphk	set fo [open $CTMref/.ctm_status w]
1846563Sphk	puts $fo "$CTMname $CTMnbr"
1856563Sphk	close $fo
1866563Sphk	incr changes -1
1873833Sphk
1886563Sphk    } else {
1896563Sphk	set CTMnbr [lindex [exec cat $CTMref/.ctm_status] 1]
1906777Sphk    }
1916777Sphk
1926777Sphk    if {"$CTMcopy" == "" } { 
1936563Sphk	set f1 [open /dev/null]
1946777Sphk    } else {
1956777Sphk	set f1 [open "| ./ctm_scan $CTMcopy"]
1962926Sphk    }
1972926Sphk
1986777Sphk    puts "Doing CTMname $CTMname CTMnbr $CTMnbr$CTMsuff CTMdate $CTMdate"
1996563Sphk    flush stdout
2006563Sphk    exec sh -c "rm -f ${CTMtmp}.* ${CTMtmp}:*" >&@ stdout
2012886Sphk
2026563Sphk    set f2 [open "| ./ctm_scan $CTMref"]
2032886Sphk
2046563Sphk    set fo_del   [open $CTMtmp.del w]
2056563Sphk    set fo_rmdir [open $CTMtmp.rmdir w]
2066563Sphk    set fo_mkdir [open $CTMtmp.mkdir w]
2076563Sphk    set fo_files [open $CTMtmp.files w]
2085014Sphk
2096563Sphk    set l1 ""
2106563Sphk    set l2 ""
2115014Sphk
2126563Sphk    while 1 {
2136563Sphk
2146563Sphk	if {$l1 == ""} {gets $f1 l1}
2156563Sphk
2166563Sphk	if {$l2 == ""} {gets $f2 l2}
2176563Sphk	
2186563Sphk	if {$l1 == "" && $l2 == ""} break
2196563Sphk
2206563Sphk	set n1 [lindex $l1 1]
2216563Sphk	set n2 [lindex $l2 1]
2226563Sphk
2236563Sphk	if {[regexp $CTMdont /$n1]} { set l1 "" ; continue }
2246563Sphk	if {[regexp $CTMdont /$n2]} { set l2 "" ; continue }
2256563Sphk
2266563Sphk	# they're all the same...
2276563Sphk	if {$l1 == $l2}  { set l1 "" ; set l2 "" ; continue }
2286563Sphk
2296563Sphk	if {$l1 == "" }   { eval CTMadd $l2 ; set l2 "" ; continue }
2306563Sphk
2316563Sphk	if {$l2 == "" }   { eval CTMdel $l1 ; set l1 "" ; continue }
2326563Sphk
2336563Sphk	# if the name is the same we're safe...
2346563Sphk	if {$n1 == $n2}  { 
2356563Sphk	    eval CTMchg $l1 $l2
2366563Sphk	    set l1 ""
2376563Sphk	    set l2 "" 
2386563Sphk	    continue 
2396563Sphk	}
2406563Sphk
2416563Sphk	# To avoid this anomaly:
2426563Sphk	# A -  d  src/gnu/lib/libreadline/readline/Attic
2436563Sphk	# A 0  f  src/gnu/lib/libreadline/readline/Attic/readline.h,v
2446563Sphk	# A 0  f  src/gnu/lib/libreadline/readline.c,v
2456563Sphk	# D 0  f  src/gnu/lib/libreadline/readline/readline.h,v
2466563Sphk	# D 0  f  src/gnu/lib/libreadline/readline.c,v
2476563Sphk	# we have to make things somewhat complicated...
2486563Sphk
2496563Sphk	# if they have the same number of components...
2506563Sphk	set ll1 [llength [split $n1 /]]
2516563Sphk	set ll2 [llength [split $n2 /]]
2526563Sphk	if {$ll1 == $ll2} {
2536563Sphk	    if {$n1 < $n2 } { 
2546563Sphk		eval CTMdel $l1 ; set l1 "" ; continue 
2556563Sphk	    } else {
2566563Sphk		eval CTMadd $l2 ; set l2 "" ; continue 
2576563Sphk	    }
2586563Sphk	} 
2596563Sphk	if {$ll1 < $ll2} {
2606563Sphk		eval CTMadd $l2 ; set l2 "" ; continue 
2615014Sphk	} else {
2626563Sphk		eval CTMdel $l1 ; set l1 "" ; continue 
2635014Sphk	}
2645014Sphk    }
2655014Sphk
2666563Sphk    close $fo_del
2676563Sphk    close $fo_rmdir
2686563Sphk    close $fo_mkdir
2696563Sphk    close $fo_files
2702886Sphk
2716563Sphk    if {$damage > $max_damage} {
2726563Sphk	puts "Too much damage: $damage deletes"
2736563Sphk	exec sh -c "rm -f ${CTMtmp}.*"
2746788Sphk        exec rm -f $CTMlock
2756563Sphk	exit 0
2766563Sphk    }
2772886Sphk
2786563Sphk    if {!$changes} {
2796563Sphk	puts "no changes"
2806563Sphk	exec sh -c "rm -f ${CTMtmp}.*"
2816788Sphk        exec rm -f $CTMlock
2826563Sphk	exit 0
2836563Sphk    }
2842886Sphk
2856563Sphk    exec echo CTM_BEGIN 2.0 $CTMname $CTMnbr $CTMdate $CTMprefix > $CTMtmp.begin
2862886Sphk
2876563Sphk    puts "Assembling delta"
2886563Sphk    flush stdout
2896563Sphk    set  nm [format "%s.%04d%s" $CTMname $CTMnbr $CTMsuff]
2902886Sphk
2916777Sphk    set fdout [open "| /sbin/md5 -p | gzip -9 > ${CTMtmp}:${nm}.gz" w]
2923112Sphk
2936563Sphk    foreach i {begin del rmdir mkdir files} {
2946563Sphk	exec cat $CTMtmp.$i >@$fdout
2956563Sphk    }
2966563Sphk    puts $fdout "CTM_END " nonewline
2976563Sphk    close $fdout ; unset fdout
2983112Sphk
2996563Sphk    exec sh -x -c "rm -f ${CTMtmp}.*" >&@ stdout
3005014Sphk
3016563Sphk    if {$CTMtest} {
3026563Sphk	puts "testing, stopping now."
3036788Sphk        exec rm -f $CTMlock
3046563Sphk	exit 0
3056563Sphk    }
3066563Sphk    if {$CTMapply} {
3076563Sphk	    puts "Applying delta"
3086563Sphk	    flush stdout
3096788Sphk	    exec echo now applying > $CTMlock
3106563Sphk	    exec sh -e -x -c "cd $CTMcopy ; $CTMSW/ctm -v -v -v ${CTMtmp}:${nm}.gz" >&@ stdout
3116788Sphk	    exec echo did apply > $CTMlock
3126563Sphk    }
3136563Sphk    puts "Moving delta"
3146563Sphk    flush stdout
3156563Sphk    exec mv ${CTMtmp}:${nm}.gz $CTMdest/.CTMtmp_${nm}.gz >&@ stdout
3166563Sphk    exec mv $CTMdest/.CTMtmp_${nm}.gz $CTMdest/${nm}.gz >&@ stdout
3176788Sphk    exec echo moved > $CTMlock
3186563Sphk
3196563Sphk    if {$CTMmail != ""} {
3206563Sphk	puts "Mailing delta"
3216563Sphk	flush stdout
3226777Sphk	exec $CTMSW/ctm_smail -m 100000 -c 3000000 $CTMdest/${nm}.gz $CTMmail >&@ stdout
3236563Sphk    }
3246788Sphk    exec echo mailed > $CTMlock
3256563Sphk
3266563Sphk    # If we did an absolute delta: stop.
3276563Sphk    if {$CTMsuff != ""} break
3286563Sphk
3296563Sphk    # Make a absolute delta (!) every 100 deltas
3306563Sphk    if {$CTMnbr % 100} break
3316563Sphk
3326563Sphk    # Make an absolute delta too...
3336563Sphk    set CTMref $CTMcopy
3346563Sphk    set CTMsuff A
3356563Sphk    set CTMcopy ""
3366563Sphk    set CTMmail ""
3376563Sphk    set CTMapply 0
3386777Sphk    set CTMspecial 1
3395014Sphk}
3406563Sphkputs "done."
3416788Sphkexec rm -f $CTMlock
342