The attached script imports an RCS repository into Fossil. It doesn't support branching nor symbolic names, and it has a few peculiarities designed to accommodate the RCS repository I just processed.

--
Andy Goth | <andrew.m.goth/at/gmail/dot/com>
#!/usr/bin/env tclsh

package require Tcl 8.6

# Confirm command line arguments.
if {[llength $argv] != 2} {
    puts stderr "Usage: [file tail $argv0] INPUT_RCS OUTPUT_FOSSIL"
    exit 1
}
set input [file normalize [lindex $argv 0]]
set output [file normalize [lindex $argv 1]]

# Executes a program after printing the command line.
proc run {args} {
    puts $args
    exec {*}$args
}

# Formats timestamps the way Fossil likes them.
proc fossilTime {timestamp} {
    clock format $timestamp -format "%Y-%m-%d %T"
}

# Find all RCS files and load their logs into $database.
set dirs [list $input]
set database {}
while {[llength $dirs]} {
    # Dequeue the first directory off the list and enqueue its subdirectories.
    set dirs [concat [lassign $dirs dir] [glob -nocomplain -dir $dir -type d *]]

    # Process all RCS files inside the directory.
    foreach file [glob -nocomplain -directory $dir -type f *,v] {
        # Determine the working file name by stripping the input root path, the
        # ",v" suffix, and (if present) the RCS subdirectory component.
        regsub {/RCS/(?=[^/]*$)} [regsub {,v$} [string range $file\
                [expr {[string length $input] + 1}] end] {}] / name

        # Obtain the log, sans header.
        regsub {.*?\n-{28}\n} [run rlog $file] {} data

        # Process each revision.
        set start 0
        while {[regexp -start $start -indices {\n-{28}\n|\n={77}$} $data sep]} {
            # Get the revision body text, and find the start of the next block.
            set body [string range $data $start [expr {[lindex $sep 0] - 1}]]
            set start [expr {[lindex $sep 1] + 1}]

            # Extract the fields from the revision body.
            regexp -expanded {
                ^revision\ ([\d.]+)[^\n]*\n
                date:\ ([\d/ :]+);\ *
                author:\ ([^;]+);\ *
                state:\ [^;]+;\ *
                (?:lines:\ [^\n]+)?\n
                (.*)$
            } $body _ revision date author message
            set date [clock scan $date -format "%Y/%m/%d %T"]

            # Process the message.
            if {[set sep [string first "\n@:" $message]] >= 0} {
                set extra [string trim [regsub -line -all {^@: *}\
                        [string range $message $sep end] {}]]
                set message [string trim [string range $message\
                        0 [expr {$sep - 1}]]]
                if {$extra ne {} && $extra ne $message} {
                    append message \n $extra
                }
            } else {
                set message [string trim $message]
            }

            # Store the revision data in the database.
            lappend database $date $name $revision $author $message
        }
    }
}

# Sort the database so the oldest entry is first.
set database [lsort -integer -stride 5 $database]

# Create the Fossil repository.
set lastDate [expr {[lindex $database 0] - 1}]
run fossil new --date-override [fossilTime $lastDate] $output
file mkdir tmp
cd tmp
run fossil open $output

# Process all revision data from oldest to newest.
set users [dict create [run fossil user default] {}]
foreach {date name revision author message} $database {
    # Forbid equal timestamps.
    if {[info exists lastDate] && $date <= $lastDate} {
        set date [expr {$lastDate + 1}]
    }

    # Create users as they are first encountered.
    if {![dict exists $users $author]} {
        dict set users $author {}
        run fossil user new $author {} {}
    }

    # Extract the file from RCS and place into the temporary directory.
    run co -r$revision [file join $input $name] 2> /dev/null
    if {![set exists [file exists $name]]} {
        file mkdir [file dirname $name]
    }
    file rename -force [file join $input $name] $name
    file attributes $name -permissions\
            [expr {[file attributes $name -permissions] | 0600}]

    # Make sure the file has Unix line endings.
    if {[regexp {, with CRLF line terminators$} [run file $name]]} {
        set chan [open $name]
        chan configure $chan -translation crlf
        set data [chan read $chan]
        chan close $chan
        set chan [open $name w]
        chan puts -nonewline $chan $data
        chan close $chan
    }

    # Add or update the file in the Fossil repository.
    if {!$exists} {
        run fossil add $name
    }
    run fossil commit --sha1sum --no-warnings --allow-empty\
            --user-override $author --date-override [fossilTime $date]\
            --comment $message
}
run fossil close

# vim: set sts=4 sw=4 tw=80 et ft=tcl:
_______________________________________________
fossil-users mailing list
fossil-users@lists.fossil-scm.org
http://lists.fossil-scm.org:8080/cgi-bin/mailman/listinfo/fossil-users

Reply via email to