Last active
September 3, 2017 09:29
-
-
Save benoitzohar/57a93f8edc2a679e360e to your computer and use it in GitHub Desktop.
Migrate repositories from Gitolite to GitLab.
This file contains hidden or 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 |
Note: The quick'n'dirty "no-key" example has 5 elements in the array, but should have 6. It is missing the Gitlab Namespace ID ('labNamespaceId' => '10' in the associative array example).
Should look like:
//second: use the quick'n'dirty "no-key" of a standard array: (the keys are in the same order.)
array(
'example','ExampleLab','exampleLab','NameSpaceEx','10','DescriptionExample'
)
trying to use this script and I keep getting:
fatal: The remote end hung up unexpectedly
error: failed to push some refs to 'git@mygitlaburl:adminID/testing.git
Any ideas? cloning works fine... via commandline but "--clone" does not work inside the script.
CentOS 7 is the platform I have it running on?
Figured out my issues... it was a firewall issues with the gitlab and gitolite... working now. Great Script!!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Okay my bad, the repository is created by the script, if it exists it does an error 400. Works fine now ! Thanks a lot for that script !