Created
April 25, 2012 07:29
-
-
Save PowerKiKi/2487758 to your computer and use it in GitHub Desktop.
SVN to GitHub mirrors
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* This script should be used with CRON to synchronise read-only mirror of SVN to Github.com. | |
* It will automatically create repositories on github.com | |
* | |
* REQUIREMENT: svn2git from https://github.com/nirvdrum/svn2git | |
* | |
* The configuration file should look similar to: | |
* | |
* $configuration = array( | |
* 'basePath' => '/some/path/svn-mirrors', | |
* 'groups' => array( | |
* 'someGroupName' => array( | |
* 'git' => new RemoteGitHub('githubUsername', 'githubPassword', 'optionalOrganisation'), | |
* 'svn' => array( | |
* 'https://example.com/svn/project1/', | |
* 'https://example.com/svn/project2/', | |
* 'customName' => array('url' => 'https://example.com/svn/project3/', 'args' => '--no-minimize-url'), // Custom svn2git options | |
* ), | |
* ), | |
* ), | |
* ); | |
* | |
*/ | |
/** | |
* Abstract class for remote git repository creation | |
*/ | |
abstract class Remote | |
{ | |
/** | |
* Creates a repository with given name | |
*/ | |
abstract function createRepository($name, $svnUrl); | |
/** | |
* Returns the repository absolute url | |
*/ | |
abstract function getRepositoryUrl($name); | |
} | |
/** | |
* Github implementation for git repository creation | |
*/ | |
class RemoteGitHub extends Remote | |
{ | |
public function __construct($username, $password, $organisation = null) | |
{ | |
$this->username = $username; | |
$this->password = $password; | |
$this->organisation = $organisation; | |
} | |
/** | |
* Creates a repository with given name | |
*/ | |
public function createRepository($name, $svnUrl) | |
{ | |
$data = array( | |
'name' => $name, | |
'description' => "Read-only mirror of $svnUrl. Updated daily with svn2git.", | |
'homepage' => $svnUrl, | |
'has_issues' => false, | |
'has_wiki' => false, | |
'has_downloads' => false, | |
); | |
$data = json_encode($data); | |
$api = $this->organisation ? "https://api.github.com/orgs/$this->organisation/repos" : 'https://api.github.com/user/repos'; | |
$result = `curl --silent -XPOST -u '$this->username:$this->password' $api -d '$data'`; | |
$result = json_decode($result); | |
if (!isset($result->git_url) && $result->errors[0]->code != 'already_exists' && $result->errors[0]->message != 'name already exists on this account') | |
{ | |
throw new Exception('Failed to create repository: ' . $name . PHP_EOL . json_encode($result)); | |
} | |
} | |
/** | |
* Returns the repository absolute url | |
*/ | |
public function getRepositoryUrl($name) | |
{ | |
$prefix = $this->organisation ?: $this->username; | |
return "git@github.com:$prefix/$name.git"; | |
} | |
} | |
/** | |
* Synchronize several SVN repositories to several GIT repositories (on several Github account) | |
*/ | |
class SvnMirror | |
{ | |
/** | |
* Synchronize all respositories | |
* @param array $configuration | |
*/ | |
public function syncAll(array $configuration) | |
{ | |
foreach ($configuration['groups'] as $groupName => $group) | |
{ | |
foreach ($group['svn'] as $name => $svnUrl) | |
{ | |
$args = null; | |
if (is_array($svnUrl)) | |
{ | |
$args = @$svnUrl['args']; | |
$svnUrl = $svnUrl['url']; | |
} | |
if (!is_string($args)) | |
$args = '--metadata --no-minimize-url'; // Default option not to wreak havoc on SVN servers | |
if (!is_string($name)) | |
$name = basename($svnUrl); | |
$localPath = $configuration['basePath'] . '/' . $groupName . '/' . $name . '/'; | |
echo $localPath . PHP_EOL; | |
if (!is_dir($localPath)) | |
$this->init($group['git'], $name, $svnUrl, $localPath, $args); | |
$this->update($localPath); | |
} | |
} | |
} | |
/** | |
* Initialize local and remote repository | |
* @param Remote $remote | |
* @param string $name | |
* @param string $svnUrl | |
* @param string $localPath | |
* @param string $args args for svn2git | |
*/ | |
protected function init(Remote $remote, $name, $svnUrl, $localPath, $args) { | |
$remote->createRepository($name, $svnUrl); | |
$gitUrl = $remote->getRepositoryUrl($name); | |
mkdir($localPath, 0777, true); | |
echo `cd $localPath && svn2git $svnUrl $args && git remote add origin $gitUrl`; | |
} | |
/** | |
* Update repository from SVN and push everything to git | |
* @param string $localPath | |
*/ | |
protected function update($localPath) { | |
// Get everything from SVN | |
echo `cd $localPath && svn2git --rebase`; | |
// Push an exact copy to git server | |
echo `cd $localPath && git push --mirror`; | |
} | |
} | |
// Load configuration file | |
$configurationFile = __DIR__ . '/configuration.php'; | |
if (!is_readable($configurationFile)) | |
die('ERROR: Cannot read configuration file: ' . $configurationFile . PHP_EOL); | |
require_once($configurationFile); | |
// Run the stuff | |
$svnMirror = new SvnMirror(); | |
$svnMirror->syncAll($configuration); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment