-
-
Save benoitzohar/57a93f8edc2a679e360e to your computer and use it in GitHub Desktop.
#!/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 |
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 !
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!!
Hi,
I'm trying to use that to migrate but I get a "An error occured : Could not curl https://git.local/api/v3/projects httpcode=400"
Do you have any idea why ? May be the API changed since you did that script ?
Thanks a lot