Created
June 20, 2012 13:09
-
-
Save tbonfort/2959820 to your computer and use it in GitHub Desktop.
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
<?php | |
/** | |
* | |
* highly modified for mapserver import | |
* orig author Vladimir Sibirov | |
*/ | |
// Edit configuration below | |
$username = 'mapserver-trac-importer'; | |
$password = 'XXX'; | |
$project = 'mapserver'; | |
$repo = 'mapserver'; | |
$mysqlhost_trac = 'localhost'; | |
$mysqluser_trac = 'trac'; | |
$mysqlpassword_trac = 'trac'; | |
$mysqldb_trac = 'trac'; | |
// All users must be valid github logins! | |
$users_list = array( | |
'tbonfort' => 'tbonfort', | |
'hobu' => 'hobu', | |
'aboudreault' => 'aboudreault', | |
'sdlime' => 'sdlime', | |
'tamas' => 'szekerest', | |
'tomkralidis' => 'tomkralidis', | |
'jmckenna' => 'jmckenna', | |
'assefa' => 'assefay', | |
'pramsey' => 'pramsey', | |
'unicoletti' => 'unicolet', | |
'warmerdam' => 'warmerdam', | |
'schpidi' => 'schpidi', | |
'dmorissette' => 'dmorissette' | |
); | |
//$users_list = array(); | |
//github_add_collaborators(); | |
$component_filter="1 = 1 "; | |
//$component_filter="component like 'Doc%'"; | |
// Do not convert milestones at this run | |
$skip_milestones = true; | |
$skip_components = true; | |
$skip_attachments = true; | |
$skip_resolution = true; | |
$skip_version = true; | |
$skip_assignee = false; | |
// Do not convert tickets | |
$skip_tickets = true; | |
$ticket_min = 0; | |
$ticket_max = 5000; | |
// Paths to milestone/ticket cache if you run it multiple times with skip/offset | |
$save_milestones = '/tmp/trac_milestones.list'; | |
$save_tickets = '/tmp/trac_tickets.list'; | |
$dateformat = 'Y/m/d - H:i'; | |
// Uncomment to refresh cache | |
// @unlink($save_milestones); | |
// @unlink($save_tickets); | |
// DO NOT EDIT BELOW | |
$svn2gitorig = array(); | |
$svn2gitms = array(); | |
$svn2gitdocs = array(); | |
$svn2gitauto = array(); | |
function svn2gitrevs($text) { | |
global $svn2gitorig,$svn2gitms,$svn2gitdocs,$svn2gitauto; | |
// replace {{{ }}} by ``` ``` | |
$text = str_replace("{{{","\n```",$text); | |
$text = str_replace("}}}","```\n",$text); | |
//does the text contain something like r1234 | |
if(preg_match_all("/\\b(r[0-9]+)\\b/",$text,$matches)) { | |
$rrevs = $matches[1]; | |
foreach($rrevs as $rrev) { | |
preg_match("/([0-9]+)/",$rrev,$rev); | |
$rev = $rev[1]; | |
if($rev != "1") { /* skip r1.xx cvs revision format */ | |
if(array_key_exists($rev,$svn2gitms)) { | |
$gitrev = $svn2gitms[$rev]; | |
$text = str_replace("r$rev","$gitrev (r$rev)",$text); | |
} else { | |
if(array_key_exists($rev,$svn2gitdocs)) { | |
$gitrev = $svn2gitdocs[$rev]; | |
$text = str_replace("r$rev","mapserver/docs@$gitrev (r$rev)",$text); | |
} else { | |
if(array_key_exists($rev,$svn2gitauto)) { | |
$gitrev = $svn2gitauto[$rev]; | |
$text = str_replace("r$rev","mapserver/msautotest@$gitrev (r$rev)",$text); | |
} else { | |
//failed lookup | |
} | |
} | |
} | |
} | |
} | |
} | |
return $text; | |
} | |
error_reporting(E_ALL ^ E_NOTICE); | |
ini_set('display_errors', 1); | |
set_time_limit(0); | |
$trac_db = new PDO('pgsql:host='.$mysqlhost_trac.';dbname='.$mysqldb_trac, $mysqluser_trac, $mysqlpassword_trac); | |
// Create the lookup table | |
$lines = file("lookup-orig.txt"); | |
foreach ($lines as $line) | |
{ | |
if (empty($line)) continue; | |
list ($svnID, $gitID) = explode("\t", trim($line)); | |
$svn2gitorig[$svnID] = $gitID; | |
} | |
$lines = file("lookup-mapserver.txt"); | |
foreach ($lines as $line) | |
{ | |
if (empty($line)) continue; | |
list ($svnID, $gitID) = explode("\t", trim($line)); | |
$svn2gitms[$svnID] = $gitID; | |
} | |
$lines = file("lookup-docs.txt"); | |
foreach ($lines as $line) | |
{ | |
if (empty($line)) continue; | |
list ($svnID, $gitID) = explode("\t", trim($line)); | |
$svn2gitdocs[$svnID] = $gitID; | |
} | |
$lines = file("lookup-autotests.txt"); | |
foreach ($lines as $line) | |
{ | |
if (empty($line)) continue; | |
list ($svnID, $gitID) = explode("\t", trim($line)); | |
$svn2gitauto[$svnID] = $gitID; | |
} | |
echo 'Connected to Trac'; | |
if(!$skip_components) { | |
$res = $trac_db->query("SELECT distinct component FROM ticket where $component_filter"); | |
$mnum = 1; | |
foreach ($res->fetchAll() as $row) { | |
$resp = github_add_component(array( | |
'name' => $row['component'], | |
'color' => 'ffffff')); | |
if (isset($resp['url'])) { | |
// OK | |
echo "Component {$row['component']} converted to label {$resp['url']}\n"; | |
} else { | |
// Error | |
echo "Failed to convert component {$row['component']}: $error\n"; | |
} | |
} | |
} | |
$milestones = array(); | |
if (file_exists($save_milestones)) { | |
$milestones = unserialize(file_get_contents($save_milestones)); | |
} | |
if (!$skip_milestones) { | |
// Export all milestones | |
$res = $trac_db->query("SELECT * FROM milestone ORDER BY due"); | |
$mnum = 1; | |
foreach ($res->fetchAll() as $row) { | |
//$milestones[$row['name']] = ++$mnum; | |
$resp = github_add_milestone(array( | |
'title' => $row['name'], | |
'state' => $row['completed'] == 0 ? 'open' : 'closed', | |
'description' => empty($row['description']) ? 'None' : $row['description'], | |
'due_on' => date('Y-m-d\TH:i:s\Z', (int) $row['due']) | |
)); | |
if (isset($resp['number'])) { | |
// OK | |
$milestones[crc32($row['name'])] = (int) $resp['number']; | |
echo "Milestone {$row['name']} converted to {$resp['number']}\n"; | |
} else { | |
// Error | |
$error = print_r($resp, 1); | |
echo "Failed to convert milestone {$row['name']}: $error\n"; | |
} | |
} | |
// Serialize to restore in future | |
file_put_contents($save_milestones, serialize($milestones)); | |
} | |
// Try get previously fetched tickets | |
$tickets = array(); | |
if (file_exists($save_tickets)) { | |
$tickets = unserialize(file_get_contents($save_tickets)); | |
} | |
if (!$skip_tickets) { | |
// Export tickets | |
$limit = ($ticket_min != 0 && $ticket_max != 0) ? "id>=$ticket_min and id<=$ticket_max": '1=1'; | |
$res = $trac_db->query("SELECT * FROM ticket where $limit and $component_filter ORDER BY id"); | |
foreach ($res->fetchAll() as $row) { | |
if($row['component'] == 'Security/Vulnerability (Private)') { | |
$issue = array( | |
'title' => 'scrubbed on import', | |
'body' => "imported from http://trac.osgeo.org/mapserver/ticket/$row[id]"); | |
if(!empty($row['milestone'])) { | |
$issue['milestone']= $milestones[crc32($row['milestone'])]; | |
} | |
$resp = github_add_issue($issue); | |
if (isset($resp['number'])) { | |
// OK | |
echo "Scrubbed Ticket #{$row['id']}->#{$resp['number']}\n"; | |
} | |
continue; | |
} | |
$description=''; | |
if(!empty($row['description'])) { | |
$description = svn2gitrevs($row['description']); | |
} | |
/* add reporter and date to ticket body */ | |
$date = date($dateformat,$row['time']); | |
$description = '**Reporter: '.$row['reporter']."**\n**Date: ".$date."**\n**Trac URL:** http://trac.osgeo.org/mapserver/ticket/$row[id]\n".$description; | |
$labels = array($row['component']); | |
if(!empty($row['type'])) { | |
if($row['type']=='defect') | |
array_push($labels,"bug"); | |
else if($row['type']=='enhancement') | |
array_push($labels,"enhancement"); | |
} | |
$issue = array( | |
'title' => $row['summary'], | |
'body' => $description, | |
'labels' => $labels); | |
if(!empty($row['milestone'])) { | |
$issue['milestone']= $milestones[crc32($row['milestone'])]; | |
} | |
$resp = github_add_issue($issue); | |
if (isset($resp['number'])) { | |
// OK | |
echo "Ticket #{$row['id']} converted to issue #{$resp['number']}\n"; | |
$tickets[$row['id']] = (int) $resp['number']; | |
// now import ticket comments | |
if(!$skipcomments) { | |
$cres = $trac_db->query("SELECT * FROM ticket_change where ticket='".$row['id']."' and field = 'comment' AND newvalue != '' ORDER BY time ASC"); | |
foreach ($cres->fetchAll() as $crow) { | |
$text = $crow['newvalue']; | |
$text = svn2gitrevs($text); | |
$date = date($dateformat,$crow['time']); | |
$text = '**Date: '.$date."**\n".$text; | |
if(strtolower($crow['author']) != strtolower($username)) { | |
$text = '**Author: ' . $crow['author'] . "**\n" . $text; | |
} | |
$cresp = github_add_comment($tickets[$crow['ticket']], $text); | |
if (isset($cresp['url'])) { | |
//echo "Added comment {$cresp['url']} to ticket #{$resp['number']}\n"; | |
} else { | |
// Error | |
$error = print_r($cresp, 1); | |
echo "Failed to add a comment: $error\n"; | |
exit(); | |
} | |
} | |
} | |
if ($row['status'] == 'closed' || !empty($row['owner']) ) { | |
$update = array(); | |
if(!empty($row['owner']) && isset($users_list[$row['owner']])) { | |
$update['assignee']= $users_list[$row['owner']]; | |
//echo "Assigning issue #{$resp['number']} to {$users_list[$row['owner']]}\n"; | |
} | |
if ($row['status'] == 'closed') { | |
$update['state']= 'closed'; | |
//echo "Closing issue #{$resp['number']}\n"; | |
} | |
if(!empty($update)) { | |
$sresp = github_update_issue($resp['number'], $update); | |
if (!isset($sresp['url'])) { | |
$error = print_r($cresp, 1); | |
echo "Failed to update status or assignee: $error\n"; | |
exit(); | |
} | |
} | |
} | |
} else { | |
// Error | |
$error = print_r($resp, 1); | |
echo "Failed to convert a ticket #{$row['id']}: $error\n"; | |
exit(); | |
} | |
} | |
// Serialize to restore in future | |
file_put_contents($save_tickets, serialize($tickets)); | |
} | |
if(!$skip_attachments) { | |
$res = $trac_db->query("SELECT * FROM attachment where type='ticket' and id::integer>=$ticket_min and id::integer<=$ticket_max"); | |
foreach ($res->fetchAll() as $row) { | |
$update = array(); | |
$tid = $row['id']; | |
$fname=$row['filename']; | |
$com = $row['description']; | |
$text = "attachment http://trac.osgeo.org/mapserver/attachment/ticket/$tid/$fname : | |
``` | |
$com | |
```"; | |
$cresp = github_add_comment($tid, $text); | |
if (isset($cresp['url'])) { | |
echo "Added attachment {$cresp['url']} to ticket $tid\n"; | |
} else { | |
// Error | |
$error = print_r($cresp, 1); | |
echo "Failed to add a comment: $error\n"; | |
exit(); | |
} | |
//http://trac.osgeo.org/mapserver/raw-attachment/ticket/15/mswms_gmap.gif | |
} | |
} | |
if(!$skip_resolution) { | |
$limit = ($ticket_min != 0 && $ticket_max != 0) ? "id>=$ticket_min and id<=$ticket_max": '1=1'; | |
$res = $trac_db->query("SELECT * FROM ticket where $limit and resolution != '' ORDER BY id"); | |
foreach ($res->fetchAll() as $row) { | |
$resol = $row['resolution']; | |
$tid = $row['id']; | |
if($resol == "duplicate" || | |
$resol == "invalid" || | |
$resol == "worksforme" || | |
$resol == "wontfix") { | |
$alabel = array($resol); | |
$sresp = github_add_label($row['id'], array($resol)); | |
if (!isset($sresp[0]['url'])) { | |
$error = print_r($sresp, 1); | |
echo "Failed to add label: $error\n"; | |
exit(); | |
} else { | |
echo "added label $resol to $tid\n"; | |
} | |
} | |
} | |
} | |
if(!$skip_assignee) { | |
$limit = ($ticket_min != 0 && $ticket_max != 0) ? "id>=$ticket_min and id<=$ticket_max": '1=1'; | |
$res = $trac_db->query("SELECT * FROM ticket where $limit and owner != '' ORDER BY id"); | |
foreach ($res->fetchAll() as $row) { | |
if (!empty($row['owner']) ) { | |
$update = array(); | |
if(isset($users_list[$row['owner']])) { | |
$update['assignee']= $users_list[$row['owner']]; | |
echo "Assigning issue #{$row['id']} to {$users_list[$row['owner']]}\n"; | |
} | |
if(!empty($update)) { | |
$sresp = github_update_issue($row['id'], $update); | |
if (!isset($sresp['url'])) { | |
$error = print_r($sresp, 1); | |
echo "Failed to update status or assignee: $error\n"; | |
exit(); | |
} | |
} | |
} | |
} | |
} | |
if(!$skip_version) { | |
$res = $trac_db->query("SELECT distinct version FROM ticket where version != '' and version != 'unspecified'"); | |
foreach ($res->fetchAll() as $row) { | |
$ver = $row['version']; | |
if($ver == "svn-trunk (development)") { | |
$ver = "master"; | |
} | |
$ver = "version-$ver"; | |
$resp = github_add_component(array( | |
'name' => $ver, | |
'color' => 'ffffff')); | |
if (isset($resp['url'])) { | |
// OK | |
echo "Component {$row['version']} converted to label $ver\n"; | |
} else { | |
// Error | |
$error = print_r($resp, 1); | |
echo "Failed to convert version {$row['version']}: $error\n"; | |
} | |
} | |
$limit = ($ticket_min != 0 && $ticket_max != 0) ? "id>=$ticket_min and id<=$ticket_max": '1=1'; | |
$res = $trac_db->query("SELECT * FROM ticket where $limit and version != '' and version != 'unspecified' ORDER BY id"); | |
foreach ($res->fetchAll() as $row) { | |
$ver = $row['version']; | |
if($ver == "svn-trunk (development)") { | |
$ver = "master"; | |
} | |
$ver = "version-$ver"; | |
$tid = $row['id']; | |
$sresp = github_add_label($row['id'], array($ver)); | |
if (!isset($sresp[0]['url'])) { | |
print_r($sresp); | |
echo "Failed to add label $ver: $error\n"; | |
exit(); | |
} else { | |
echo "added label $ver to $tid\n"; | |
} | |
} | |
} | |
echo "Done whatever possible, sorry if not.\n"; | |
$lastrequest = 0; | |
function github_post($url, $json, $patch = false, $method='post') { | |
global $username, $password,$lastrequest; | |
$ch = curl_init(); | |
curl_setopt($ch, CURLOPT_USERPWD, "$username:$password"); | |
curl_setopt($ch, CURLOPT_URL, "https://api.github.com$url"); | |
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); | |
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); | |
curl_setopt($ch, CURLOPT_HEADER, false); | |
$putData = tmpfile(); | |
fwrite($putData, "ignore=1"); | |
fseek($putData, 0); | |
if($method=='post') { | |
curl_setopt($ch, CURLOPT_POST, true); | |
curl_setopt($ch, CURLOPT_POSTFIELDS, $json); | |
} else if($method=='put') { | |
curl_setopt($ch, CURLOPT_PUT, true); | |
curl_setopt($ch, CURLOPT_INFILE, $putData); | |
curl_setopt($ch, CURLOPT_INFILESIZE, strlen("ignore=1")); | |
} | |
if ($patch) { | |
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PATCH'); | |
} | |
$now = microtime(true); | |
if($lastrequest>0 && $now-$lastrequest<1) { | |
//printf("rate limit: sleeping for %f\n",1-($now-$lastrequest)); | |
usleep((1-($now-$lastrequest))*1000000); | |
} | |
$lastrequest = $now; | |
$ret = curl_exec($ch); | |
if(!$ret) { | |
trigger_error(curl_error($ch)); | |
} | |
curl_close($ch); | |
fclose($putData); | |
return $ret; | |
} | |
function github_add_milestone($data) { | |
global $project, $repo; | |
return json_decode(github_post("/repos/$project/$repo/milestones", json_encode($data)), true); | |
} | |
function github_add_component($data) { | |
global $project, $repo; | |
return json_decode(github_post("/repos/$project/$repo/labels", json_encode($data)), true); | |
} | |
function github_add_issue($data) { | |
global $project, $repo; | |
return json_decode(github_post("/repos/$project/$repo/issues", json_encode($data)), true); | |
} | |
function github_add_comment($issue, $body) { | |
global $project, $repo; | |
return json_decode(github_post("/repos/$project/$repo/issues/$issue/comments", json_encode(array('body' => $body))), true); | |
} | |
function github_add_label($issue, $labels) { | |
global $project, $repo; | |
//echo "/repos/$project/$repo/issues/$issue/labels\n"; | |
//print_r(json_encode($labels)); return; | |
return json_decode(github_post("/repos/$project/$repo/issues/$issue/labels", json_encode($labels)), true); | |
} | |
function github_update_issue($issue, $data) { | |
global $project, $repo; | |
return json_decode(github_post("/repos/$project/$repo/issues/$issue", json_encode($data), true), true); | |
} | |
function github_add_collaborators() { | |
global $project, $repo, $users_list; | |
foreach($users_list as $key => $collab) { | |
json_decode(github_post("/repos/$project/$repo/collaborators/$collab", '', false,'put'), true); | |
} | |
} | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment