Skip to content

Instantly share code, notes, and snippets.

@derak-kilgo
Last active August 10, 2017 22:18
Show Gist options
  • Select an option

  • Save derak-kilgo/1454e44a8cfa98173dceb9ca6272f0c4 to your computer and use it in GitHub Desktop.

Select an option

Save derak-kilgo/1454e44a8cfa98173dceb9ca6272f0c4 to your computer and use it in GitHub Desktop.
A script to load gitolite's bare git repositories into gogs database.
#!/usr/bin/env php
<?php
/* A tool to import repos from gitolite to gogs (db version 17)
*
* Gogs and gitolite use bare repos when hosting your repositories.
* You can add repositories directly into the gogs-repo directory but gogs won't see
* them until they are also added to the database.
*
* This script adds entries into the repository, access, watch and team_repo tables.
* It assumes default settings for a private repository which is owned by a single org.
* gitolite and gogs use bare repos for storage.
*
* Usage:
* Create a repos.txt file with a list of repos. One per line. Assumes each directory will end in .git.
* This is both a gitolite and gogs naming convention.
*
* Then edit these vars the top of this script.
*
* Note: gitolite repos have an update hook. Gogs needs that to be updated.
* Create a test repo and copy that test repos update hook into each one of your imported gitolite repos.
* I used this little bash script:
*/
// "for d in */; do cp ./test.git/hooks/update $d/hooks/update; done"
//The path to your gogs config. This is where we will get db credentials.
$gogsConfig = '/path/to/gogs/custom/conf/app.ini';
//This is a list of all the repos you want to add to gogs.
$repoList = '/path/to/gogs/new-repo-list.txt';
//A default description will be added to every imported repo.
$defaultRepoDescription = 'Migrated from gitolite';
//Owner of this repo in gogs. This can be a user or an org. See the gogs.user table
$defaultRepoOwnerId = -999;
//A list of user ids which should have admin access to a repo. Only choose users. Not orgs here.
$defaultAdminIds = array(-999);
//Gogs will fix this but its nice to have it be correct right off the bat.
$defaultWatchCount = count($defaultAdminIds);
//default branch for repos.
$defaultBranch = 'master';
//Set to true and no changes will be made to your database. Useful for the first run.
$dryRun = true;
/*
* Main
*/
try{
//Use settings from gogs to connect.
$confData = parse_ini_file($gogsConfig,true);
if(isset($confData['database']['DB_TYPE']) && $confData['database']['DB_TYPE'] == 'mysql'){
echo "Using gogs mysql settings. \n";
}else{
throw new RuntimeException("This script only supports MySQL connections. Type detected was {$confData['database']['DB_TYPE']}\n");
}
//Connect to database
$mysqli = new mysqli($confData['database']['HOST'],$confData['database']['USER'],$confData['database']['PASSWD'],$confData['database']['NAME']);
if ($mysqli->connect_errno) {
throw new RuntimeException("Failed to connect to MySQL: ( {$mysqli->connect_errno} ) {$mysqli->connect_error} \n");
}
//Do a quick version check on the database.
$res=$mysqli->query('SELECT version FROM version ORDER BY version DESC LIMIT 1');
$row = $res->fetch_assoc();
if($row['version'] != 17){
throw new RuntimeException("Expected version 17 and got {$row['version']}. This script may harm your gogs db. \n");
}
//Do everything in a single transaction so we rollback if there is a problem.
$mysqli->autocommit(FALSE);
if (!$mysqli->query("START TRANSACTION")){
throw new RuntimeException("Start Transaction Failed. ( {$mysqli->errno} ) {$mysqli->error} \n");
}
//Open our list of repos and add them one by one.
$fh = fopen($repoList, 'r');
//timestamp used for created and updated.
$timeStamp = time();
$defaultRepoDescription = $mysqli->real_escape_string($defaultRepoDescription);
$defaultBranch = $mysqli->real_escape_string($defaultBranch);
while ($repo = fgetcsv($fh)) {
//assumes ".git" doesn't show in elseware in the file name.
$reponame = str_replace('.git','',$repo[0]);
echo "Adding $reponame to gogs \n";
$reponame = $mysqli->real_escape_string($reponame);
$lowerName = strtolower($reponame);
//Insert into repository
$qy = "INSERT INTO `repository` (`owner_id`, `lower_name`, `name`, `description`, `website`, `default_branch`, `size`, `num_watches`, `num_stars`, `num_forks`,
`num_issues`, `num_closed_issues`, `num_pulls`, `num_closed_pulls`, `num_milestones`, `num_closed_milestones`, `is_private`, `is_bare`, `is_mirror`, `enable_wiki`,
`allow_public_wiki`, `enable_external_wiki`, `external_wiki_url`, `enable_issues`, `allow_public_issues`, `enable_external_tracker`, `external_tracker_url`, `external_tracker_format`, `external_tracker_style`, `enable_pulls`,
`is_fork`, `fork_id`, `created_unix`, `updated_unix`)
VALUES ($defaultRepoOwnerId,'$lowerName','$reponame','$defaultRepoDescription','','$defaultBranch',0,$defaultWatchCount,0,0,
0,0,0,0,0,0,1,0,0,1,
0,0,'',1,0,0,'','','numeric',1,
0,0,$timeStamp,$timeStamp)";
if (!$mysqli->query($qy)){
throw new RuntimeException("Insert respository Failed. ( {$mysqli->errno} ) {$mysqli->error} \n");
}
$newRepoId = $mysqli->insert_id;
//Insert into team repo.
$qy = "INSERT INTO `team_repo` (`org_id`, `team_id`, `repo_id`) VALUES ($defaultRepoOwnerId,1,$newRepoId)";
if (!$mysqli->query($qy)){
throw new RuntimeException("Insert team_repo Failed. ( {$mysqli->errno} ) {$mysqli->error} \n");
}
//Insert into access. 4 = admin
$qy = "INSERT INTO `access` (`user_id`, `repo_id`, `mode`) VALUES ";
foreach($defaultAdminIds as $adminId){
$qy .= "($adminId, $newRepoId, 4),";
}
$qy = trim($qy,', ');
if (!$mysqli->query($qy)){
throw new RuntimeException("Insert access Failed. ( {$mysqli->errno} ) {$mysqli->error} \n");
}
//Insert into watch.
$qy = "INSERT INTO `watch` (`user_id`, `repo_id`) VALUES ";
foreach($defaultAdminIds as $adminId){
$qy .= "($adminId, $newRepoId),";
}
$qy = trim($qy,', ');
if (!$mysqli->query($qy)){
throw new RuntimeException("Insert watch Failed. ( {$mysqli->errno} ) {$mysqli->error} \n");
}
}
//script completed without an error.
if($dryRun === true){
$mysqli->rollback();
echo "DryRun - Rolling back changes. No errors during test run. \n";
}else{
$mysqli->commit();
echo "Import completed without errors. \n";
}
return true;
}catch(Exception $e){
echo "A " . get_class($e) . ' occured.' . $e->getMessage() . chr(10);
if(isset($mysqli)){
$mysqli->rollback();
}
return false;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment