Fossil

Check-in [7208c7ac]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Changes to cvs2fossil to import tcllib CVS into fossil on Win32

* using [::file] instead of [file] in snit methods to get the core file command * taking care of files that only differ in case in the Attic and the repo on case insensitive FS * passing platform specific

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:7208c7ac4d1562657ecad27e7bc3e6e81405d460
User & Date: mjanssen 2008-01-28 23:57:27
Context
2008-01-29
00:12
cvs2fossil: add -nocomplain flag to glob to prevent an error if no files/dirs match check-in: 6625739e user: mjanssen tags: trunk
2008-01-28
23:57
Changes to cvs2fossil to import tcllib CVS into fossil on Win32

* using [::file] instead of [file] in snit methods to get the core file command * taking care of files that only differ in case in the Attic and the repo on case insensitive FS * passing platform specific check-in: 7208c7ac user: mjanssen tags: trunk

18:29
REPLACE into the event table rather than INSERT. check-in: 7aa9a2e2 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to tools/cvs2fossil/lib/c2f_file.tcl.

262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
...
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
	struct::list assign [$self Expand $ws] filemap revmap
	# filemap = dict (path -> uuid)
	# revmap  = dict (path -> rid)

	array set idmap [$repository importfiles $filemap]

	# Wipe workspace clean of the imported files.
	foreach x [glob -directory $ws r*] { file delete $x }

	foreach {path rid} $revmap {
	    set uuid $idmap($path)
	    state run {
		INSERT INTO revuuid (rid,  uuid)
		VALUES              ($rid, $uuid)
	    }
................................................................................

	foreach {from to} $earcs { $ex arc insert $from $to }
	foreach {from to} $zarcs { $zp arc insert $from $to }

	# Phase III: Traverse the graphs, expand the file, and
	#            generate import instructions.

	set archive [file join [$myproject fullpath] $mypath]
	set ac      [open $archive r]
	fconfigure $ac -translation binary

	# First traverse the expansion graph, this gives us the
	# revisions in the order we have to expand them, which we do.

	set max [llength [$ex nodes]]







|







 







|







262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
...
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
	struct::list assign [$self Expand $ws] filemap revmap
	# filemap = dict (path -> uuid)
	# revmap  = dict (path -> rid)

	array set idmap [$repository importfiles $filemap]

	# Wipe workspace clean of the imported files.
	foreach x [glob -directory $ws r*] { ::file delete $x }

	foreach {path rid} $revmap {
	    set uuid $idmap($path)
	    state run {
		INSERT INTO revuuid (rid,  uuid)
		VALUES              ($rid, $uuid)
	    }
................................................................................

	foreach {from to} $earcs { $ex arc insert $from $to }
	foreach {from to} $zarcs { $zp arc insert $from $to }

	# Phase III: Traverse the graphs, expand the file, and
	#            generate import instructions.

	set archive [::file join [$myproject fullpath] $mypath]
	set ac      [open $archive r]
	fconfigure $ac -translation binary

	# First traverse the expansion graph, this gives us the
	# revisions in the order we have to expand them, which we do.

	set max [llength [$ex nodes]]

Changes to tools/cvs2fossil/lib/c2f_fossil.tcl.

28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
..
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
snit::type ::vc::fossil::import::cvs::fossil {
    # # ## ### ##### ######## #############
    ## Public API

    constructor {} {
	set myrepository [fileutil::tempfile cvs2fossil_repo_]
	set myworkspace  [fileutil::tempfile cvs2fossil_wspc_]
	file delete $myworkspace
	file mkdir  $myworkspace

	Do new $myrepository
	$self InWorkspace ; Do open $myrepository
	$self RestorePwd
	return
    }

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

................................................................................
	$self RestorePwd

	log write 3 fossil Done.
	return [array get id]
    }

    method finalize {destination} {
	file rename -force $myrepository $destination
	file delete -force $myworkspace
	$self destroy
	return
    }

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








|
|

|
|







 







|
|







28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
..
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
snit::type ::vc::fossil::import::cvs::fossil {
    # # ## ### ##### ######## #############
    ## Public API

    constructor {} {
	set myrepository [fileutil::tempfile cvs2fossil_repo_]
	set myworkspace  [fileutil::tempfile cvs2fossil_wspc_]
	::file delete $myworkspace
	::file mkdir  $myworkspace

	Do new [::file nativename $myrepository]
	$self InWorkspace ; Do open [::file nativename $myrepository]
	$self RestorePwd
	return
    }

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

................................................................................
	$self RestorePwd

	log write 3 fossil Done.
	return [array get id]
    }

    method finalize {destination} {
	::file rename -force $myrepository $destination
	::file delete -force $myworkspace
	$self destroy
	return
    }

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

Changes to tools/cvs2fossil/lib/c2f_patopsort.tcl.

115
116
117
118
119
120
121
122
123
124
125
126
127
128
129

    proc IsBySymbol {cset} { $cset bysymbol }

    proc SaveTimestamps {graph at cset} {
	set cid [$cset id]

	set date [GetTime [lindex [$graph node get $cset timerange] 1] \
		      [struct::set contain $mysymchangesets $cset] \
		     message]

	log write 4 atopsort "Changeset @ [format $myatfmt $at]: [format $mycsfmt [$cset str]]$message"

	state run {
	    INSERT INTO cstimestamp (cid,  pos, date)
	    VALUES                  ($cid, $at, $date)







|







115
116
117
118
119
120
121
122
123
124
125
126
127
128
129

    proc IsBySymbol {cset} { $cset bysymbol }

    proc SaveTimestamps {graph at cset} {
	set cid [$cset id]

	set date [GetTime [lindex [$graph node get $cset timerange] 1] \
		      [struct::set contains $mysymchangesets $cset] \
		     message]

	log write 4 atopsort "Changeset @ [format $myatfmt $at]: [format $mycsfmt [$cset str]]$message"

	state run {
	    INSERT INTO cstimestamp (cid,  pos, date)
	    VALUES                  ($cid, $at, $date)

Changes to tools/cvs2fossil/lib/c2f_pcollar.tcl.

94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
...
110
111
112
113
114
115
116

117
118
119

120
121
122
123
124
125
126
...
216
217
218
219
220
221
222
223


224
225
226
227
228
229
230

    typemethod run {} {
	# Pass manager interface. Executed to perform the
	# functionality of the pass.

	set rbase [repository base?]
	foreach project [repository projects] {
	    set base [file join $rbase [$project base]]
	    log write 1 collar "Scan $base"

	    set traverse [fileutil::traverse %AUTO% $base \
			      -prefilter [myproc FilterAtticSubdir $base]]
	    set n 0
	    set r {}

................................................................................
		set rcs [fileutil::stripPath $base $path]
		if {[IsCVSAdmin    $rcs]}  continue
		if {![IsRCSArchive $path]} continue

		set usr [UserPath $rcs isattic]
		if {[IsSuperceded $base $rcs $usr $isattic]} continue


		if {
		    [file exists      $base/$usr] &&
		    [file isdirectory $base/$usr]

		} {
		    trouble fatal "Directory name conflicts with filename."
		    trouble fatal "Please remove or rename one of the following:"
		    trouble fatal "    $base/$usr"
		    trouble fatal "    $base/$rcs"
		    continue
		}
................................................................................
	return $f
    }

    proc IsSuperceded {base rcs usr isattic} {
	::variable myignore

	if {!$isattic}                   {return 0}
	if {![file exists $base/$usr,v]} {return 0}



	# We have a regular archive and an Attic archive refering to
	# the same user visible file. Ignore the file in the Attic.
	#
	# By default this is a problem causing an abort after the pass
	# has completed. The user can however force us to ignore it.
	# In that case the warning is still printed, but will not







|







 







>

<
|
>







 







|
>
>







94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
...
110
111
112
113
114
115
116
117
118

119
120
121
122
123
124
125
126
127
...
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233

    typemethod run {} {
	# Pass manager interface. Executed to perform the
	# functionality of the pass.

	set rbase [repository base?]
	foreach project [repository projects] {
	    set base [::file join $rbase [$project base]]
	    log write 1 collar "Scan $base"

	    set traverse [fileutil::traverse %AUTO% $base \
			      -prefilter [myproc FilterAtticSubdir $base]]
	    set n 0
	    set r {}

................................................................................
		set rcs [fileutil::stripPath $base $path]
		if {[IsCVSAdmin    $rcs]}  continue
		if {![IsRCSArchive $path]} continue

		set usr [UserPath $rcs isattic]
		if {[IsSuperceded $base $rcs $usr $isattic]} continue

		# XXX Checkme: not sure if this will still fail in the case where a directory does conflict with a file XXX
		if {

		    [lsearch [glob -tail -types f -directory $base *] $usr] != -1 &&
		    [lsearch [glob -tail -types d -directory $base *] $usr] != -1 
		} {
		    trouble fatal "Directory name conflicts with filename."
		    trouble fatal "Please remove or rename one of the following:"
		    trouble fatal "    $base/$usr"
		    trouble fatal "    $base/$rcs"
		    continue
		}
................................................................................
	return $f
    }

    proc IsSuperceded {base rcs usr isattic} {
	::variable myignore

	if {!$isattic}                   {return 0}

	# use glob to account for case insensitive file systems 
	if {[lsearch [glob -tail -directory $base *] $usr,v] == -1} {return 0}

	# We have a regular archive and an Attic archive refering to
	# the same user visible file. Ignore the file in the Attic.
	#
	# By default this is a problem causing an abort after the pass
	# has completed. The user can however force us to ignore it.
	# In that case the warning is still printed, but will not

Changes to tools/cvs2fossil/lib/c2f_pcollrev.tcl.

314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335

    typemethod run {} {
	# Pass manager interface. Executed to perform the
	# functionality of the pass.

	set rbase [repository base?]
	foreach project [repository projects] {
	    set base [file join $rbase [$project base]]
	    log write 1 collrev "Processing $base"

	    foreach file [$project files] {
		set path [$file path]
		log write 2 collrev "Parsing $path"
		if {[catch {
		    parser process [file join $base $path] $file
		} msg]} {
		    global errorCode
		    if {$errorCode eq "vc::rcs::parser"} {
			trouble fatal "$path is not a valid RCS archive ($msg)"
		    } else {
			global errorInfo
			trouble internal $errorInfo







|






|







314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335

    typemethod run {} {
	# Pass manager interface. Executed to perform the
	# functionality of the pass.

	set rbase [repository base?]
	foreach project [repository projects] {
	    set base [::file join $rbase [$project base]]
	    log write 1 collrev "Processing $base"

	    foreach file [$project files] {
		set path [$file path]
		log write 2 collrev "Parsing $path"
		if {[catch {
		    parser process [::file join $base $path] $file
		} msg]} {
		    global errorCode
		    if {$errorCode eq "vc::rcs::parser"} {
			trouble fatal "$path is not a valid RCS archive ($msg)"
		    } else {
			global errorInfo
			trouble internal $errorInfo

Changes to tools/cvs2fossil/lib/c2f_state.tcl.

40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

56
57
58
59
60
61
62
..
78
79
80
81
82
83
84

85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
	# regarding the required tables will be done later, by the
	# passes, during their setup.

	# In the second case we have to be able to create the file,
	# and check that. This is done by opening it, sqlite will then
	# try to create it, and may fail.

	if {[file exists $path]} {
	    if {![fileutil::test $path frw msg {cvs2fossil state}]} {
		trouble fatal $msg
		return
	    }
	}

	if {[catch {
	    sqlite3 ${type}::TEMP $path

	} res]} {
	    trouble fatal $res
	    return
	}

	# A previously defined state database is closed before
	# committing to the new definition. We do not store the path
................................................................................
	# then it is now the time to create our own using a tempfile.

	if {$mystate ne ""} return

	set mypath  [fileutil::tempfile cvs2fossil_state_]
	set mystate ${type}::STATE
	sqlite3 $mystate $mypath


	log write 2 state "using $mypath"
	return
    }

    typemethod release {} {
	log write 2 state release
	${type}::STATE close
	if {$mypath eq ""} return
	file delete $mypath
	return
    }

    # Declare a table needed for the storing of persistent state, and
    # its structure. A possibly previously existing definition is
    # dropped. To be used when a table is needed and not assumed to
    # exist from previous passes.







|








>







 







>









|







40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
..
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
	# regarding the required tables will be done later, by the
	# passes, during their setup.

	# In the second case we have to be able to create the file,
	# and check that. This is done by opening it, sqlite will then
	# try to create it, and may fail.

	if {[::file exists $path]} {
	    if {![fileutil::test $path frw msg {cvs2fossil state}]} {
		trouble fatal $msg
		return
	    }
	}

	if {[catch {
	    sqlite3 ${type}::TEMP $path
	    ${type}::TEMP eval {PRAGMA synchronous=OFF;}
	} res]} {
	    trouble fatal $res
	    return
	}

	# A previously defined state database is closed before
	# committing to the new definition. We do not store the path
................................................................................
	# then it is now the time to create our own using a tempfile.

	if {$mystate ne ""} return

	set mypath  [fileutil::tempfile cvs2fossil_state_]
	set mystate ${type}::STATE
	sqlite3 $mystate $mypath
        $mystate eval {PRAGMA synchronous=OFF;}

	log write 2 state "using $mypath"
	return
    }

    typemethod release {} {
	log write 2 state release
	${type}::STATE close
	if {$mypath eq ""} return
	::file delete $mypath
	return
    }

    # Declare a table needed for the storing of persistent state, and
    # its structure. A possibly previously existing definition is
    # dropped. To be used when a table is needed and not assumed to
    # exist from previous passes.

Changes to tools/cvs2fossil/lib/dot.tcl.

56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
	return
    }

    typemethod layout {format g name file} {
	set f [fileutil::tempfile c2fdot_]
	$type write $g $name $f
	exec dot -T $format -o $file $f
	file delete $f
	return
    }

    # # ## ### ##### ######## #############
    ## Internal, state

    proc Style {graph x y dict} {







|







56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
	return
    }

    typemethod layout {format g name file} {
	set f [fileutil::tempfile c2fdot_]
	$type write $g $name $f
	exec dot -T $format -o $file $f
	::file delete $f
	return
    }

    # # ## ### ##### ######## #############
    ## Internal, state

    proc Style {graph x y dict} {

Changes to tools/cvs2fossil/lib/misc.tcl.

79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
	return
    }

    # Delete item from list by name

    proc striptrailingslash {path} {
	# split and rejoin gets rid of a traling / character.
	return [eval [linsert [file split $path] 0 file join]]
    }

    # # ## ### ##### ######## #############
}

namespace eval ::vc::tools::misc {
    namespace export sp nsp max min max2 min2 ldelete striptrailingslash







|







79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
	return
    }

    # Delete item from list by name

    proc striptrailingslash {path} {
	# split and rejoin gets rid of a traling / character.
	return [eval [linsert [file split $path] 0 ::file join]]
    }

    # # ## ### ##### ######## #############
}

namespace eval ::vc::tools::misc {
    namespace export sp nsp max min max2 min2 ldelete striptrailingslash