#!/pro/bin/perl use strict; use warnings; use VCS::SCCS; my @sccs = sort glob ("SCCS/s.*") or die "No SCCS source files to convert\n"; -d ".git" and die ".git already exists\n"; system "git init"; # http://www.kernel.org/pub/software/scm/git/docs/gitattributes.html # could be explored to write checkout hooks that translate SCCS # keywords to actual content. Would be hard to translate back sub pr_date { my @dt = localtime shift; sprintf "%s %02d-%02d-%4d %02d:%02d:%02d", (qw( Sun Mon Tue Wed Thu Fri Sat ))[$dt[6]], $dt[3], $dt[4] + 1, $dt[5] + 1900, $dt[2], $dt[1], $dt[0]; } # pr_date # GFI implementation by Sam Vilain # fire up GFI chomp (my $branchname = qx(git symbolic-ref HEAD)); open my $gfi, "|-", qw(git fast-import --quiet); my $mark; # use a best guess at user, hostname, etc. FIXME: add authors map :) use Socket; use Sys::Hostname; use Time::Local; my $domain = $ENV{YPDOMAIN} || (gethostbyname hostname)[0]; my %tzoffset; my $tzoffset = sub { my $offset_s = timegm (localtime ($_[0])) - $_[0]; $tzoffset{$offset_s} ||= ( $offset_s >= 0 ? "+" : "-" ) . sprintf "%.4d", abs $offset_s; }; # Submit in the same sequence as the original my %sccs; my %file; foreach my $f (@sccs) { my $sccs = VCS::SCCS->new ($f) or die "Cannot convert $f\n"; # GIT supports get-hooks, to translate on retrieval # But it will be useless as you cannot translate back $sccs->set_translate ("SCCS"); my $fn = $sccs->file (); $file{$fn}++; foreach my $rm (@{$sccs->revision_map ()}) { my ($rev, $vsn) = @{$rm}; my $delta = $sccs->delta ($rev); $sccs{pack "NA*", $delta->{stamp}, $fn} = [ $sccs, $rev, ++$mark ]; my $data = scalar $sccs->body ($rev); print { $gfi } "blob\nmark :", $mark, "\ndata ", length ($data), "\n", $data, "\n"; printf STDERR "%-20s %3d %8s %s\r", $fn, $rev, $vsn, pr_date ($delta->{stamp}); } print STDERR "\n"; } foreach my $c (sort keys %sccs) { my ($sccs, $rev, $mark) = @{$sccs{$c}}; my $fn = $sccs->file (); my %delta = %{$sccs->delta ($rev)}; my $stamp = pr_date ($delta{stamp}); my $vsn = $delta{version}; printf STDERR "%-20s %3d %6s %s %s %s\n", $fn, $rev, $vsn, $stamp, $delta{date}, $delta{"time"}; print { $gfi } "commit ", $branchname, "\n"; print { $gfi } "committer ", $delta{committer}, " <", ($delta{committer}, "@", $domain, "> ", $delta{stamp}, " ", $tzoffset->($delta{stamp}), "\n"); # tradition is to save all potentially useful but # uncategorized metadata as RFC822-style headers in the commit # message my $mr = $delta{mr} || ""; $mr =~ s/^-$//; $mr and $mr = "SCCS-mr: $mr"; $vsn and $vsn = "SCCS-vsn: $vsn"; my $cmnt = $delta{comment} || ""; $cmnt ||= "(no message)"; $cmnt .= "\n"; my $msg = join "\n", $cmnt, grep m/\S/, $mr, $vsn; print { $gfi } "data ", length ($msg), "\n$msg\n"; my $mode = $delta{flags}{x} ? "755" : "644"; print { $gfi } "M $mode :$mark $fn\n"; print { $gfi } "\n"; } print { $gfi } "checkpoint\n"; close $gfi; system "git-checkout"; system "git", "reset", "--hard"; # Add personalized generation of .gitignore here ... open my $gi, ">", ".gitignore"; print $gi <