-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathsccs2git-r-noignore
executable file
·153 lines (130 loc) · 4.22 KB
/
sccs2git-r-noignore
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#!/usr/bin/perl
# This is the recursive version of sccs2git
# Combining all SCCS repos to one single git repo
use strict;
use warnings;
use VCS::SCCS;
use File::Find;
my %sccs_ext;
my @sccs;
find (sub { $File::Find::dir =~ m{(?:^|/)SCCS$} and m/^s\./ or return;
push @sccs, $File::Find::name;
m/\.(\w+)$/ and $sccs_ext{$1}++;
}, glob "*");
@sccs 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
# 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 Time::Local;
use Net::Domain;
my $domain = "ucbvax.Berkeley.EDU";
$ENV{TZ} = "US/Pacific";
POSIX::tzset();
my %tzoffset;
my $tzoffset = sub {
use integer;
my $offset_s = timegm (localtime ($_[0])) - $_[0];
my $off = abs $offset_s / 60;
my ($off_h, $off_m) = ($off / 60, $off % 60);
$tzoffset{$offset_s} ||= ( $offset_s >= 0 ? "+" : "-" )
. sprintf "%02d%02d", $off_h, $off_m;
};
open(my $fh, '<', 'map') or die "could not open 'map' file";
my %authors = ();
while (<$fh>) {
if ($_ =~ m/([^ ]*) (.*) <.*$/) {
$authors{$1} = $2;
}
}
# Submit in the same sequence as the original
my %sccs;
my %file;
my @fail;
foreach my $f (sort @sccs) {
my $sccs;
eval { $sccs = VCS::SCCS->new ($f) };
unless ($sccs) {
warn "Cannot convert $f\n";
push @fail, $f;
next;
}
# 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"};
my $realname = $delta{committer};
if (defined($authors{$delta{committer}})) {
$realname = $authors{$delta{committer}};
}
# bill joy's last commit Wed Dec 10 20:01:30 1980 -0800
# bill jolitz's first commit Mon Mar 12 15:47:40 1990 -0800
if ($delta{committer} eq "bill") {
my @dt = localtime($delta{stamp});
if ($dt[5] < 85) {
$realname = $authors{wnj};
} else {
$realname = $authors{william};
}
}
print { $gfi } "commit ", $branchname, "\n";
print { $gfi } "committer ", $realname,
" <", $delta{committer}, "> ",
$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";
@fail and print STDERR join "\n ",
"The following files could not be converted and were skipped:", @fail, "\r";