├── README ├── README.markdown └── git_svn_externals.pl /README: -------------------------------------------------------------------------------- 1 | Introduction 2 | ------------------------------------------------------------ 3 | This script can be used to clone an SVN repository with externals. 4 | 5 | Usage 6 | ------------------------------------------------------------ 7 | 1. Run 'perl git_svn_externals.pl' in the root of git-svn cloned repository 8 | 2. profit :) 9 | 10 | Features 11 | ------------------------------------------------------------ 12 | 1. Script fetches all svn externals specified recursively. 13 | 2. On subseqent runs script fetches new externals and updates existing ones. 14 | 3. Svn externals with revision specified will be updated to apropriate 15 | revisions everytime the revision specified changes in svn repository. 16 | 4. Running 'git svn dcommit' is possible due to all fetched svn externals 17 | being excluded from the "root" git repository. 18 | 19 | Known problems 20 | ------------------------------------------------------------ 21 | None known. 22 | 23 | Author 24 | ------------------------------------------------------------ 25 | Dmitry Sushko 26 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | git svn externals 2 | ====== 3 | 4 | Introduction 5 | ---------- 6 | 7 | This script can be used to clone an SVN repository with externals. 8 | 9 | Usage 10 | ---------- 11 | 12 | 1. Run 'perl git_svn_externals.pl' in the root of git-svn cloned repository 13 | 2. profit :) 14 | 15 | Features 16 | ---------- 17 | 18 | 1. Script fetches all svn externals specified recursively. 19 | 2. On subseqent runs script fetches new externals and updates existing ones. 20 | 3. Svn externals with revision specified will be updated to apropriate 21 | revisions everytime the revision specified changes in svn repository. 22 | 4. Running 'git svn dcommit' is possible due to all fetched svn externals 23 | being excluded from the "root" git repository. 24 | 25 | Known problems 26 | ---------- 27 | 28 | None known. 29 | 30 | Author 31 | ---------- 32 | 33 | Dmitry Sushko 34 | -------------------------------------------------------------------------------- /git_svn_externals.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | 3 | # 4 | # git_svn_externals.pl 5 | # 6 | # Author: 7 | # Dmitry Sushko 8 | # 9 | 10 | use strict; 11 | use warnings; 12 | use Cwd; 13 | use File::Path; 14 | use File::Basename; 15 | use Term::ANSIColor; 16 | 17 | my $git_executable = "git"; 18 | my $git_directory = ".git"; 19 | my $git_externals_dir = ".git_externals"; 20 | my $show_externals_command = "$git_executable svn show-externals"; 21 | my $clone_external_command = "$git_executable svn clone"; 22 | my $git_svn_fetch_command = "$git_executable svn fetch"; 23 | my $git_svn_rebase_command = "$git_executable svn rebase"; 24 | 25 | sub removeListHeaders { 26 | my @externalsList = @_; 27 | return grep(!/^# \// && !/^$/, @externalsList); 28 | } 29 | 30 | sub parseExternal { 31 | my $externalLine = $_; 32 | my @external; 33 | 34 | if ($externalLine =~ 35 | m/(.+\S)\s+-r\s*(\S+)\s+((?:file:|http:|https:|svn:|svn\+ssh:)\S+.*)/) { 36 | @external = [$1, $2, $3]; 37 | } 38 | elsif ($externalLine =~ 39 | m/(.+\S)\s+((?:file:|http:|https:|svn:|svn\+ssh:)\S+.*)/) { 40 | @external = [$1, "0", $2]; 41 | } 42 | else { 43 | @external = ["", "0", ""]; 44 | } 45 | 46 | return @external; 47 | } 48 | 49 | sub isGitRepository { 50 | my $ext_path = $_[0]; 51 | my $directory = join("/", $ext_path, $git_directory); 52 | if (-d $directory) { 53 | return 1; 54 | } 55 | else { 56 | return 0; 57 | } 58 | } 59 | 60 | sub excludeExternal { 61 | my $directory = $_[0]; 62 | 63 | open GITEXCLUDE, "<", ".git/info/exclude" or die "Error: $!\n"; 64 | if (grep {$_ =~ m/^$directory\n$/} ) { 65 | close GITEXCLUDE; 66 | return; 67 | } 68 | close GITEXCLUDE; 69 | 70 | open GITEXCLUDE, ">>", ".git/info/exclude" or die "Error: $!\n"; 71 | print GITEXCLUDE "$directory\n"; 72 | close GITEXCLUDE; 73 | } 74 | 75 | sub switchExternalRevision { 76 | my $ext_rev = $_[0]; 77 | 78 | my $git_sha = qx/git svn find-rev r$ext_rev/; 79 | $git_sha =~ s/\n//; 80 | 81 | qx/$git_executable checkout master/; 82 | qx/$git_executable branch -f __git_ext_br $git_sha/; 83 | qx/$git_executable checkout __git_ext_br/; 84 | } 85 | 86 | sub updateExternal { 87 | my ($ext_path, $ext_rev, $ext_url) = @_; 88 | 89 | my $command = $git_svn_fetch_command; 90 | qx/$command/; 91 | 92 | $command = $git_svn_rebase_command; 93 | qx/$command/; 94 | 95 | if ($ext_rev ne "0") { 96 | switchExternalRevision($ext_rev); 97 | } 98 | 99 | getExternals(); 100 | } 101 | 102 | sub cloneExternal { 103 | my ($ext_path, $ext_rev, $ext_url) = @_; 104 | 105 | my $command = join(" ", $clone_external_command, $ext_url, "."); 106 | qx/$command/; 107 | 108 | if ($ext_rev ne "0") { 109 | switchExternalRevision($ext_rev); 110 | } 111 | 112 | getExternals(); 113 | } 114 | 115 | sub makeSymlinkToExternal { 116 | my $ext_path = $_[0]; 117 | 118 | if (basename($ext_path) ne $ext_path) { 119 | mkpath dirname($ext_path); 120 | } 121 | 122 | my $path_to_repo_root = qx/git rev-parse --show-cdup/; 123 | $path_to_repo_root =~ s/\n$//; 124 | my $externals_relative_dir = $path_to_repo_root . $git_externals_dir; 125 | 126 | symlink(join("/", $externals_relative_dir, $ext_path), $ext_path); 127 | } 128 | 129 | sub getExternal { 130 | my ($ext_path, $ext_rev, $ext_url) = @{$_}; 131 | 132 | $ext_path =~ s/%20/ /g; 133 | $ext_path =~ s/\\//g; 134 | $ext_path =~ s/^\///g; 135 | 136 | print colored ['green'], "==============================================\n"; 137 | print colored ['cyan'], 138 | "External found:\n" . 139 | " path: $ext_path\n" . 140 | " rev : $ext_rev\n" . 141 | " url : $ext_url\n"; 142 | 143 | my $working_dir = cwd(); 144 | 145 | chdir $git_externals_dir or die "Error: $!\n"; 146 | 147 | mkpath $ext_path or die "Error: $!\n" unless -d $ext_path; 148 | 149 | if (isGitRepository($ext_path)) { 150 | chdir $ext_path or die "Error: $!\n"; 151 | updateExternal($ext_path, $ext_rev, $ext_url); 152 | } 153 | else { 154 | chdir $ext_path or die "Error: $!\n"; 155 | cloneExternal($ext_path, $ext_rev, $ext_url); 156 | } 157 | 158 | chdir $working_dir or die "Error: $!\n"; 159 | excludeExternal($ext_path); 160 | 161 | makeSymlinkToExternal($ext_path); 162 | } 163 | 164 | sub getExternals { 165 | my @show_externals_output = qx/$show_externals_command/; 166 | my @externalsList = grep(!/^# \// && !/^$/, @show_externals_output); 167 | my @externals = map(parseExternal, @externalsList); 168 | 169 | mkpath $git_externals_dir or die "Error: $!\n" unless -d $git_externals_dir; 170 | excludeExternal($git_externals_dir); 171 | 172 | map(getExternal, @externals); 173 | } 174 | 175 | getExternals(); 176 | --------------------------------------------------------------------------------