Skip to content

Instantly share code, notes, and snippets.

@PowerKiKi
Created April 25, 2012 07:29
Show Gist options
  • Save PowerKiKi/2487758 to your computer and use it in GitHub Desktop.
Save PowerKiKi/2487758 to your computer and use it in GitHub Desktop.
SVN to GitHub mirrors
<?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