Last active
August 10, 2017 22:18
-
-
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.
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/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