f166b0a63c 2007-08-31 aku: #!/bin/sh f166b0a63c 2007-08-31 aku: # -*- tcl -*- \ f166b0a63c 2007-08-31 aku: exec tclsh "$0" ${1+"$@"} f166b0a63c 2007-08-31 aku: f166b0a63c 2007-08-31 aku: # ----------------------------------------------------------------------------- df91d389d5 2007-09-04 aku: df91d389d5 2007-09-04 aku: # Import the trunk of a CVS repository wholesale into a fossil repository. df91d389d5 2007-09-04 aku: df91d389d5 2007-09-04 aku: # Limitations implicitly mentioned: df91d389d5 2007-09-04 aku: # - No incremental import. df91d389d5 2007-09-04 aku: # - No import of branches. df91d389d5 2007-09-04 aku: df91d389d5 2007-09-04 aku: # WIBNI features (beyond eliminating the limitations): df91d389d5 2007-09-04 aku: # - Restrict import to specific directory subtrees (SF projects use df91d389d5 2007-09-04 aku: # one repository for several independent modules. Examples: tcllib df91d389d5 2007-09-04 aku: # -> tcllib, tklib, tclapps, etc.). The restriction would allow import df91d389d5 2007-09-04 aku: # of only a specific module. df91d389d5 2007-09-04 aku: # - Related to the previous, strip elements from the base path to keep df91d389d5 2007-09-04 aku: # it short. df91d389d5 2007-09-04 aku: # - Export to CVS, trunk, possibly branches. I.e. extend the system to be df91d389d5 2007-09-04 aku: # a full bridge. Either Fossil or CVS could be the master repository. df91d389d5 2007-09-04 aku: df91d389d5 2007-09-04 aku: # HACKS. I.e. I do not know if the 'fixes' I use are the correct way df91d389d5 2007-09-04 aku: # of handling the encountered situations. df91d389d5 2007-09-04 aku: # df91d389d5 2007-09-04 aku: # - File F has archives F,v and Attic/F,v. Currently I will ignore the df91d389d5 2007-09-04 aku: # file in the Attic. df91d389d5 2007-09-04 aku: # Examples: sqlite/os_unix.h df91d389d5 2007-09-04 aku: # df91d389d5 2007-09-04 aku: # - A specific revision of a file F cannot be checked out (reported df91d389d5 2007-09-04 aku: # error is 'invalid change text'). This indicates a corrupt RCS df91d389d5 2007-09-04 aku: # file, one or more delta are bad. We report but ignore the problem df91d389d5 2007-09-04 aku: # in a best-effort attempt at getting as much history as possible. df91d389d5 2007-09-04 aku: # Examples: tcllib/tklib/modules/tkpiechart/pie.tcl df91d389d5 2007-09-04 aku: df91d389d5 2007-09-04 aku: # ----------------------------------------------------------------------------- f166b0a63c 2007-08-31 aku: # Make private packages accessible. f166b0a63c 2007-08-31 aku: f166b0a63c 2007-08-31 aku: lappend auto_path [file join [file dirname [info script]] lib] df91d389d5 2007-09-04 aku: df91d389d5 2007-09-04 aku: # ----------------------------------------------------------------------------- df91d389d5 2007-09-04 aku: # Requirements df91d389d5 2007-09-04 aku: 7003caa982 2007-09-04 aku: package require Tcl 8.4 df91d389d5 2007-09-04 aku: package require cvs ; # Frontend, reading from source repository df91d389d5 2007-09-04 aku: package require fossil ; # Backend, writing to destination repository. f166b0a63c 2007-08-31 aku: f166b0a63c 2007-08-31 aku: # ----------------------------------------------------------------------------- df91d389d5 2007-09-04 aku: df91d389d5 2007-09-04 aku: proc main {} { 8469631cc9 2007-09-08 aku: global argv tot nto cvs fossil ntrunk stopat df91d389d5 2007-09-04 aku: df91d389d5 2007-09-04 aku: commandline df91d389d5 2007-09-04 aku: df91d389d5 2007-09-04 aku: fossil::feedback Write ; # Setup progress feedback from the libraries df91d389d5 2007-09-04 aku: cvs::feedback Write df91d389d5 2007-09-04 aku: df91d389d5 2007-09-04 aku: cvs::at $cvs ; # Define location of CVS repository df91d389d5 2007-09-04 aku: cvs::scan ; # Gather revision data from the archives df91d389d5 2007-09-04 aku: cvs::csets ; # Group changes into sets df91d389d5 2007-09-04 aku: cvs::rtree ; # Build revision tree (trunk only right now). df91d389d5 2007-09-04 aku: df91d389d5 2007-09-04 aku: set tot 0.0 df91d389d5 2007-09-04 aku: set nto 0 df91d389d5 2007-09-04 aku: df91d389d5 2007-09-04 aku: Write info {Importing ...} df91d389d5 2007-09-04 aku: Write info { Setting up cvs workspace and temporary fossil repository} df91d389d5 2007-09-04 aku: df91d389d5 2007-09-04 aku: cvs::workspace ; # cd's to workspace df91d389d5 2007-09-04 aku: fossil::new ; # Uses cwd as workspace to connect to. df91d389d5 2007-09-04 aku: df91d389d5 2007-09-04 aku: set ntrunk [cvs::ntrunk] df91d389d5 2007-09-04 aku: cvs::foreach_cset cset [cvs::root] { df91d389d5 2007-09-04 aku: import $cset 8469631cc9 2007-09-08 aku: if {$stopat == $cset} exit f166b0a63c 2007-08-31 aku: } df91d389d5 2007-09-04 aku: cvs::wsclear df91d389d5 2007-09-04 aku: df91d389d5 2007-09-04 aku: Write info " ========= [string repeat = 61]" df91d389d5 2007-09-04 aku: Write info " Imported $nto [expr {($nto == 1) ? "changeset" : "changesets"}]" df91d389d5 2007-09-04 aku: Write info " Within [format %.2f $tot] seconds (avg [format %.2f [expr {$tot/$nto}]] seconds/changeset)" df91d389d5 2007-09-04 aku: df91d389d5 2007-09-04 aku: Write info { Moving to final destination} df91d389d5 2007-09-04 aku: df91d389d5 2007-09-04 aku: fossil::destination $fossil df91d389d5 2007-09-04 aku: df91d389d5 2007-09-04 aku: Write info Ok. f166b0a63c 2007-08-31 aku: return f166b0a63c 2007-08-31 aku: } f166b0a63c 2007-08-31 aku: df91d389d5 2007-09-04 aku: df91d389d5 2007-09-04 aku: # ----------------------------------------------------------------------------- df91d389d5 2007-09-04 aku: df91d389d5 2007-09-04 aku: proc commandline {} { 8469631cc9 2007-09-08 aku: global argv cvs fossil nosign log debugcommit stopat df91d389d5 2007-09-04 aku: df91d389d5 2007-09-04 aku: set nosign 0 492531e3a8 2007-09-04 aku: set debugcommit 0 8469631cc9 2007-09-08 aku: set stopat {} 492531e3a8 2007-09-04 aku: df91d389d5 2007-09-04 aku: while {[string match "-*" [set opt [lindex $argv 0]]]} { df91d389d5 2007-09-04 aku: if {$opt eq "--nosign"} { df91d389d5 2007-09-04 aku: set nosign 1 df91d389d5 2007-09-04 aku: set argv [lrange $argv 1 end] 492531e3a8 2007-09-04 aku: continue 492531e3a8 2007-09-04 aku: } 492531e3a8 2007-09-04 aku: if {$opt eq "--debugcommit"} { 492531e3a8 2007-09-04 aku: set debugcommit 1 492531e3a8 2007-09-04 aku: set argv [lrange $argv 1 end] 8469631cc9 2007-09-08 aku: continue f166b0a63c 2007-08-31 aku: } 8469631cc9 2007-09-08 aku: if {$opt eq "--stopat"} { 8469631cc9 2007-09-08 aku: set stopat [lindex $argv 1] 8469631cc9 2007-09-08 aku: set argv [lrange $argv 2 end] df91d389d5 2007-09-04 aku: continue f166b0a63c 2007-08-31 aku: } df91d389d5 2007-09-04 aku: usage df91d389d5 2007-09-04 aku: } df91d389d5 2007-09-04 aku: if {[llength $argv] != 2} usage df91d389d5 2007-09-04 aku: foreach {cvs fossil} $argv break df91d389d5 2007-09-04 aku: df91d389d5 2007-09-04 aku: if { df91d389d5 2007-09-04 aku: ![file exists $cvs] || df91d389d5 2007-09-04 aku: ![file readable $cvs] || df91d389d5 2007-09-04 aku: ![file isdirectory $cvs] df91d389d5 2007-09-04 aku: } { df91d389d5 2007-09-04 aku: usage "CVS directory missing, not readable, or not a directory." df91d389d5 2007-09-04 aku: } elseif {[file exists $fossil]} { df91d389d5 2007-09-04 aku: usage "Fossil destination repository exists already." f166b0a63c 2007-08-31 aku: } f166b0a63c 2007-08-31 aku: df91d389d5 2007-09-04 aku: set log [open ${fossil}.log w] 492531e3a8 2007-09-04 aku: 492531e3a8 2007-09-04 aku: fossil::debugcommit $debugcommit df91d389d5 2007-09-04 aku: return f166b0a63c 2007-08-31 aku: } f166b0a63c 2007-08-31 aku: df91d389d5 2007-09-04 aku: proc usage {{text {}}} { df91d389d5 2007-09-04 aku: global argv0 df91d389d5 2007-09-04 aku: puts stderr "Usage: $argv0 ?--nosign? cvs-repository fossil-rpeository" df91d389d5 2007-09-04 aku: if {$text eq ""} return df91d389d5 2007-09-04 aku: puts stderr " $text" df91d389d5 2007-09-04 aku: exit f166b0a63c 2007-08-31 aku: } f166b0a63c 2007-08-31 aku: df91d389d5 2007-09-04 aku: proc import {cset} { 8469631cc9 2007-09-08 aku: global tot nto nosign ntrunk stopat df91d389d5 2007-09-04 aku: Write info " Importing $cset [string repeat = [expr {60 - [string length $cset]}]]" 734febe649 2007-09-05 aku: Write info " At $nto/$ntrunk ([format %.2f [expr {$nto*100.0/$ntrunk}]]%)" 734febe649 2007-09-05 aku: 8469631cc9 2007-09-08 aku: if {$stopat == $cset} { 8469631cc9 2007-09-08 aku: fossil::commit 1 cvs2fossil $nosign \ 8469631cc9 2007-09-08 aku: [cvs::wssetup $cset] \ 8469631cc9 2007-09-08 aku: ::cvs::wsignore 8469631cc9 2007-09-08 aku: Write info " %% STOP" 8469631cc9 2007-09-08 aku: return f166b0a63c 2007-08-31 aku: } f166b0a63c 2007-08-31 aku: df91d389d5 2007-09-04 aku: set usec [lindex [time { 8469631cc9 2007-09-08 aku: foreach {uuid ad rm ch} [fossil::commit 0 cvs2fossil $nosign \ df91d389d5 2007-09-04 aku: [cvs::wssetup $cset] \ df91d389d5 2007-09-04 aku: ::cvs::wsignore] break df91d389d5 2007-09-04 aku: } 1] 0] df91d389d5 2007-09-04 aku: cvs::uuid $cset $uuid df91d389d5 2007-09-04 aku: df91d389d5 2007-09-04 aku: set sec [expr {$usec/1e6}] df91d389d5 2007-09-04 aku: set tot [expr {$tot + $sec}] df91d389d5 2007-09-04 aku: incr nto df91d389d5 2007-09-04 aku: df91d389d5 2007-09-04 aku: Write info " == $uuid +${ad}-${rm}*${ch}" df91d389d5 2007-09-04 aku: Write info " in $sec seconds" df91d389d5 2007-09-04 aku: df91d389d5 2007-09-04 aku: set avg [expr {$tot/$nto}] df91d389d5 2007-09-04 aku: set max [expr {$ntrunk * $avg}] df91d389d5 2007-09-04 aku: set rem [expr {$max - $tot}] df91d389d5 2007-09-04 aku: df91d389d5 2007-09-04 aku: Write info " st avg [format %.2f $avg]" df91d389d5 2007-09-04 aku: Write info " st run [format %7.2f $tot] sec [format %6.2f [expr {$tot/60}]] min [format %5.2f [expr {$tot/3600}]] hr" df91d389d5 2007-09-04 aku: Write info " st end [format %7.2f $max] sec [format %6.2f [expr {$max/60}]] min [format %5.2f [expr {$max/3600}]] hr" df91d389d5 2007-09-04 aku: Write info " st rem [format %7.2f $rem] sec [format %6.2f [expr {$rem/60}]] min [format %5.2f [expr {$rem/3600}]] hr" df91d389d5 2007-09-04 aku: return f166b0a63c 2007-08-31 aku: } f166b0a63c 2007-08-31 aku: df91d389d5 2007-09-04 aku: # ----------------------------------------------------------------------------- df91d389d5 2007-09-04 aku: df91d389d5 2007-09-04 aku: array set fl { df91d389d5 2007-09-04 aku: debug {DEBUG } df91d389d5 2007-09-04 aku: info { } df91d389d5 2007-09-04 aku: warning {Warning} df91d389d5 2007-09-04 aku: error {ERROR } f166b0a63c 2007-08-31 aku: } f166b0a63c 2007-08-31 aku: df91d389d5 2007-09-04 aku: proc Write {l t} { df91d389d5 2007-09-04 aku: global fl log f166b0a63c 2007-08-31 aku: df91d389d5 2007-09-04 aku: if {[string index $t 0] eq "\r"} { df91d389d5 2007-09-04 aku: puts -nonewline stdout "\r$fl($l) [string range $t 0 end-1]" df91d389d5 2007-09-04 aku: } else { df91d389d5 2007-09-04 aku: puts stdout "$fl($l) $t" df91d389d5 2007-09-04 aku: puts $log "$fl($l) $t" f166b0a63c 2007-08-31 aku: } df91d389d5 2007-09-04 aku: flush stdout df91d389d5 2007-09-04 aku: return f166b0a63c 2007-08-31 aku: } f166b0a63c 2007-08-31 aku: f166b0a63c 2007-08-31 aku: # ----------------------------------------------------------------------------- f166b0a63c 2007-08-31 aku: df91d389d5 2007-09-04 aku: main df91d389d5 2007-09-04 aku: exit