vcs-svn: Extend svndump to parse version 3 format
[svn-fe.git] / replay.pl
blobbe5289ec117c8ea64ef89b69b4f6981589d67b99
1 #!/usr/bin/perl
3 use SVN::Core;
4 use SVN::Repos;
5 use SVN::Fs;
7 use Date::Parse;
8 use File::Temp;
10 my $pool = SVN::Pool->new_default;
12 my $mirror = '/path/to/mirror';
14 my $repos = SVN::Repos::open($mirror);
15 my $fs = $repos->fs();
17 my $uuid = $fs->revision_prop(0, 'svn:sync-from-uuid');
18 my $url = $fs->revision_prop(0, 'svn:sync-from-url');
19 my $maxrev = int($fs->revision_prop(0, 'svn:sync-last-merged-rev'));
21 print "# SVN_UUID: $uuid\n";
22 print "# SVN_URL: $url\n";
23 print "# MAX_REV: $maxrev\n";
25 my $commitlog;
26 my $nextmark = 1;
27 my $marks;
29 $repos->get_logs([''], 1, $maxrev, 1, 0, sub {
30 my ($paths, $rev, $author, $date, $log, $pool) = @_;
31 my $pool = SVN::Pool->new_default_sub;
33 print "# SVN_AUTHOR: $author\n";
34 print "# SVN_DATE: $date\n";
36 my $GIT_COMMITTER_NAME=$author;
37 my $GIT_COMMITTER_EMAIL=$author.'@'.$uuid;
38 my $GIT_COMMITTER_DATE=int(str2time($date)).' +0000';
40 my @commitlogfile = File::Temp->new();
41 $commitlog = $commitlogfile[FH];
43 print $commitlog "commit refs/heads/master\n";
44 print $commitlog "committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE\n";
45 print $commitlog 'data '.length($log)."\n$log\n";
47 my $root = $fs->revision_root($rev, $pool);
49 my $lastdir;
51 for my $file (sort keys %$paths) {
52 if ($lastdir && index($file, $lastdir) == 0) {
53 next;
54 } else {
55 undef $lastdir;
58 my $path = substr($file, 1);
59 print $commitlog "D $path\n";
61 if ($SVN::Node::none == $root->check_path($file, $pool)) {
62 next;
65 if ($root->is_dir($file, $pool) ) {
66 modifydir($root, $file, $pool);
67 $lastdir = $file.'/';
68 } else {
69 modifyfile($root, $file, $pool);
73 seek $commitlog, 0, 0;
74 local $/ = \16384;
75 while (<$commitlog>) {
76 print $_;
78 close $commitlog;
80 print "progress to revision $rev\n"
81 });
83 sub modifydir {
84 my ($root, $dir, $pool) = @_;
85 my $pool = SVN::Pool->new_default_sub;
87 my $dirents = $root->dir_entries($dir, $pool);
88 for my $name (keys %$dirents) {
89 my $entry = $dirents->{$name};
90 if ($entry->kind == $SVN::Node::dir) {
91 modifydir($root, $dir.'/'.$name, $pool);
92 } else {
93 modifyfile($root, $dir.'/'.$name, $pool);
98 sub modifyfile {
99 my ($root, $file, $pool) = @_;
100 my $pool = SVN::Pool->new_default_sub;
102 my $proplist = $root->node_proplist($file, $pool);
103 my $md5 = $root->file_md5_checksum($file, $pool);
104 # Strip the leading slash from the path for git
105 my $path = substr($file, 1);
107 my $mode;
109 if (defined $proplist->{'svn:special'}) {
110 $mode = '120000';
111 $md5 .= 'L';
112 } else {
113 $mode = defined $proplist->{'svn:executable'} ? '100755' : '100644';
116 my $mark = $marks->{$md5};
117 if (!defined $mark) {
118 $mark = $nextmark++;
119 $marks->{$md5} = $mark;
120 my $length = $root->file_length($file, $pool);
121 $length -= 5 if $mode == '120000';
122 my $contents = $root->file_contents($file, $pool);
123 print "# MD5: $md5\n";
124 print "blob\nmark :$mark\n";
125 print "data $length\n";
126 local $/ = \16384;
127 my $linkprefix;
128 read $contents, $linkprefix, 5 if $mode == '120000';
129 while (<$contents>) {
130 print $_;
132 close $contents;
133 print "\n";
135 print $commitlog "M $mode :$mark $path\n";