blob: f6f4ae889d99f2071f853532d1d043afd65f3e7f [file] [log] [blame]
#!/usr/bin/python
#
# Copyright 2011 James Purser, Christian Ohler, Michael MacFadden
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
""" This script imports issues from Code.Google and builds a csv file.
The intent is to imported the csv file into JIRA.
In order to run the script you will need the following library:
GData: http://code.google.com/p/gdata-python-client/"""
import gdata.projecthosting.client
import os
""" Configuration Values """
project_name = "wave-protocol"
export_file_name = "exported_issues.csv"
"""Mappings between Google Code Values and Jira Values"""
types = {}
types["Defect"] = "Bug"
types["Enhancement"] = "Improvemnet"
types["Patch"] = "Bug"
types["Review"] = "Bug"
types["Task"] = "Task"
priorities = {}
priorities["Critical"] = "Critical"
priorities["High"] = "Major"
priorities["Medium"] = "Minor"
priorities["Low"] = "Trivial"
statuses = {}
statuses["New"] = "Open"
statuses["Accepted"] = "Open"
statuses["Started"] = "In Progress"
statuses["Fixed"] = "Closed"
statuses["Invalid"] = "Closed"
statuses["Duplicate"] = "Closed"
statuses["WontFix"] = "Closed"
resolutions = {}
resolutions["New"] = ""
resolutions["Accepted"] = ""
resolutions["Started"] = ""
resolutions["Fixed"] = "Fixed"
resolutions["Invalid"] = "Invalid"
resolutions["Duplicate"] = "Duplicate"
resolutions["WontFix"] = "Won't Fix"
""" Helper Functions """
def get_comments(issue_id):
comments = []
while True:
comments_query = gdata.projecthosting.client.Query(start_index=len(comments) + 1)
comments_feed = hosting_client.get_comments(project_name, issue_id, query=comments_query)
if not comments_feed.entry:
break
comments.extend(comments_feed.entry)
comments_text = ""
if len(comments) > 0:
for comment in comments:
if len(comments_text) > 0:
comments_text += "---\n"
comments_text += "%s:\n%s\n\n" % (comment.title.text, comment.content.text)
updates = comment.updates
if updates:
if updates.summary:
comments_text += "Summary: %s\n\n" % updates.summary.text
if updates.status:
comments_text += "Status: %s\n\n" % updates.status.text
if updates.ownerUpdate:
comments_text += "OwnerUpdate: %s\n\n" % updates.ownerUpdate.text
for label in updates.label:
comments_text += "Label: %s\n\n" % label.text
for ccUpdate in updates.ccUpdate:
comments_text += "CcUpdate: %s\n\n" % ccUpdate.text
return comments_text
def escape(s):
return '"' + s.encode('utf-8').replace('"', '""') + '"'
def get_id(issue):
return issue.get_id().split('/')[-1]
def get_link(issue):
return "http://code.google.com/p/%s/issues/detail?id=%s" % (project_name, get_id(issue))
def get_description(issue):
# TODO: The content seems to be HTML, I'm not sure if that's what JIRA expects.
description = issue.content.text
description += "\n\n---\nIssue imported from %s\n\n" % issue_link
if issue.owner:
description += "Owner: %s\n" % issue.owner.username.text
for cc in issue.cc:
description += "Cc: %s\n" % cc.username.text
for label in issue.label:
description += "Label: %s\n" % label.text
if issue.stars:
description += "Stars: %s\n" % issue.stars.text
if issue.state:
description += "State: %s\n" % issue.state.text
if issue.status:
description += "Status: %s\n" % issue.status.text
return description
def convert_value(list,value):
if len(value) > 0:
return list[value]
else:
return ""
""" Export Process """
hosting_client = gdata.projecthosting.client.ProjectHostingClient()
export_file = open(export_file_name, "w")
# First row with column titles
export_file.write("Id,Summary,Issue Type,Priority,Status,Resolution,Description,Comment Body\n")
print "Exporting issues to: " + os.path.abspath(export_file_name)
issues_total = 0
while True:
issues_query = gdata.projecthosting.client.Query(start_index=issues_total + 1)
issues_feed = hosting_client.get_issues(project_name, query=issues_query)
if not issues_feed.entry:
break
for issue in issues_feed.entry:
issue_id = get_id(issue)
issue_link = get_link(issue)
print "Exporting Issue %s: %s" % (issue_id, issue_link)
# Append one row per issue
# Id, e.g. http://code.google.com/feeds/issues/p/wave-protocol/issues/full/1
row = escape(issue_id) + ","
# Title
row += escape(issue.title.text) + ","
# Fetch the type and priority from the labels
# There are any number of labels, but we are only interested in two. Namely
# Type-* and Priority-*
type = "";
priority = "";
for label in issue.label:
if label.text.startswith("Type-"):
type = label.text[5:]
elif label.text.startswith("Priority-"):
priority = label.text[9:]
row += escape(convert_value(types,type)) + ","
row += escape(convert_value(priorities,priority)) + ","
# Google Code only has the concept of status, while Jira has status and resolution.
# Status, e.g. Open or Closed
row += escape(convert_value(statuses,issue.status.text)) + ","
# Status, e.g. Fixed, Invalid, etc
row += escape(convert_value(resolutions,issue.status.text)) + ","
# Fetch the description text
description = get_description(issue)
row += escape(description) + ","
# Fetch all the comments and put them in a single column
comments = get_comments(issue_id)
row += escape(comments)
export_file.write(row + "\n")
issues_total += len(issues_feed.entry)
export_file.close()
print "\n%s issues exported" % issues_total