-
-
Save j3j5/57b68b9fdb7aadb165b314340e726ebc to your computer and use it in GitHub Desktop.
Migrate repositories from Gitolite to GitLab.
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
#!/usr/bin/php -qC | |
<?php | |
/****************************************************************************** | |
* | |
* @file gitolab.php | |
* @author Benoit Zohar | |
* @link http://benoitzohar.fr/ | |
* @last-edited 2015-01-09 | |
* @description Migrate projects from Gitolite to GitLab | |
* @requisite cURL library for PHP | |
* @usage 1. Change the value of the private variables of the GitoLab class | |
* 2. Launch "php gitolab.php" to start the process | |
* 3. Enter Y or N to import each pre-specified project | |
* | |
******************************************************************************/ | |
error_reporting(E_ALL ^ E_NOTICE); | |
class GitoLab { | |
//Gitolite prefix url (you'll need to have you ssh key configured to make this work) | |
private $gitolite_url = 'ssh://[email protected]/'; | |
//Gitlab API url prefix | |
private $gitlab_url = 'https://gitlab.example.com/'; | |
//Gitlab ssh access prefoex | |
private $gitlab_ssh = '[email protected]'; | |
//Gitlab private token (see Gitlab documentation) | |
private $gitlab_private_token = '1234567890AZERTY'; | |
private $projects = array( | |
//there are two ways of defining the repositories you want to import: | |
//first: use the very nice long keys of an associative array: | |
array( | |
//Name of the project in gitolite (name of the repository) | |
'liteProjectName' => 'example', | |
//Complete name of the project in GitLab | |
'labProjectName' => 'ExampleLab', | |
//Repository name of the project in GitLab | |
'labProjectPath' => 'exampleLab', | |
//Namespace in GitLab (must already exist !) | |
'labNamespace' => 'NameSpaceEx', | |
//Namespace ID in GitLab (must already exist !) use the _ID_ (check GET http://example.com/api/v3/groups to get it) | |
'labNamespaceId' => '10', | |
//[Optionnal] : description of the project in gitlab | |
'labDescription' => 'DescriptionExample' | |
), | |
//second: use the quick'n'dirty "no-key" of a standard array: (the keys are in the same order.) | |
array( | |
'example','ExampleLab','exampleLab','NameSpaceEx','DescriptionExample' | |
) | |
); | |
//Root of temporary directory used to clone repositories | |
private $root_dir = ''; | |
public function __construct() { | |
//init variables | |
if (empty($this->root_dir)) { | |
//if the temporary directory is not set: use the current directory of the script | |
$this->root_dir = getcwd(); | |
} | |
//start Migration process | |
try { | |
$this->checkRights(); | |
$this->startMigration(); | |
} | |
catch(Exception $e) { | |
$this->cleanTemporaryDirectory(); | |
die("An error occured : ".$e->getMessage()."\n\n"); | |
} | |
$this->cleanTemporaryDirectory(); | |
echo "\n\n"; | |
} | |
private function checkRights() { | |
echo "Checking rights for directory ".$this->root_dir." ...\n"; | |
if (!is_dir($this->root_dir)) throw new Exception("'".$this->root_dir."' is not a directory"); | |
if (!is_writable($this->root_dir)) throw new Exception("'".$this->root_dir."' is not a writable"); | |
} | |
private function startMigration() { | |
echo "Starting migration ... \n"; | |
$autoyes = false; //set to true to automatically accept every repository | |
foreach($this->projects as $project) { | |
if (!$autoyes) $r = readline("Migrate project ".($project['liteProjectName'] ? $project['liteProjectName'] : $project[0])." (Y/N) ? "); | |
//set to auto true if the user uses YYY once. | |
if ($r === 'YYY') $autoyes = true; | |
if ($autoyes || empty($r) || strtolower($r) == 'y') { | |
if (array_key_exists('liteProjectName', $project)) { | |
$this->migrateProject( | |
$project['liteProjectName'], | |
$project['labProjectName'], | |
$project['labProjectPath'], | |
$project['labNamespace'], | |
$project['labNamespaceId'], | |
$project['labDescription'] | |
); | |
} else if (!empty($project[0])) { | |
$this->migrateProject( | |
$project[0], | |
$project[1], | |
$project[2], | |
$project[3], | |
$project[4], | |
$project[5] | |
); | |
} | |
} | |
} | |
} | |
private function migrateProject($liteProjectName,$labProjectName,$labProjectPath,$labNamespace,$labNamespaceId,$labDescription = '') { | |
echo "Migrating project ".$liteProjectName." ...\n"; | |
//create the projet on gitlab | |
$url = $this->gitlab_url.'api/v3/projects'; | |
$data = array( | |
'name' => $labProjectName, | |
'path' => $labProjectPath, | |
'namespace_id' => $labNamespaceId | |
); | |
if (!empty($labDescription)) { | |
$data['description'] = $labDescription; | |
} | |
$ch = curl_init($url); | |
curl_setopt($ch, CURLOPT_HTTPHEADER, array("PRIVATE-TOKEN: ".$this->gitlab_private_token)); | |
curl_setopt($ch, CURLOPT_HEADER, 0); | |
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); | |
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); | |
curl_setopt($ch, CURLOPT_POST, 1); | |
curl_setopt($ch, CURLOPT_POSTFIELDS, $data); | |
$head = curl_exec($ch); | |
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); | |
curl_close($ch); | |
if(!$head) { | |
throw new Exception("Could not curl ".$url); | |
} | |
if($httpCode != 201) { //201 for "created" for GitLab API | |
throw new Exception("Could not curl ".$url." httpcode=".$httpCode); | |
} | |
$path = 'gitolab-tmp/'.$labProjectPath; | |
//clone the project from gitolite | |
echo "> 'git clone --mirror ".$this->gitolite_url.$liteProjectName.".git \"".$path."\"'\n"; | |
exec('git clone --mirror '.$this->gitolite_url.$liteProjectName.'.git "'.$path.'"'); | |
//move inside temporary path | |
chdir($path); | |
//clean gitolite remote | |
echo "> 'git remote rm origin'\n"; | |
exec('git remote rm origin'); | |
//add gitlab remote | |
echo "> 'git remote add origin ".$this->gitlab_ssh.":".$labNamespace."/".$labProjectPath.".git'\n"; | |
exec('git remote add origin '.$this->gitlab_ssh.':'.$labNamespace.'/'.$labProjectPath.'.git'); | |
//push all branches to the new remote | |
echo "> 'git push --all'\n"; | |
exec("git push --all"); | |
//push all tags to the new remote | |
echo "> 'git push --tags'\n"; | |
exec("git push --tags"); | |
//go back to original dir | |
chdir($this->root_dir); | |
} | |
private function cleanTemporaryDirectory() { | |
echo "Cleaning temporary directory ...\n"; | |
$this->rrmdir($this->root_dir."/gitolab-tmp"); | |
} | |
//recursively remove directory | |
private function rrmdir($dir) { | |
if (is_dir($dir)) { | |
$objects = scandir($dir); | |
foreach ($objects as $object) { | |
if ($object != "." && $object != "..") { | |
if (filetype($dir."/".$object) == "dir") $this->rrmdir($dir."/".$object); else unlink($dir."/".$object); | |
} | |
} | |
reset($objects); | |
rmdir($dir); | |
} | |
} | |
} | |
new GitoLab(); // launch migration |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment