Permalink
Browse files

Export to new Bitbucket Issues Data Format instead of using the API

  • Loading branch information...
1 parent af35505 commit 7886967f96e726538dd4a66cde053a7535908feb @sorich87 committed Mar 27, 2013
View
@@ -1,4 +1,5 @@
-source :rubygems
+source 'https://rubygems.org'
gem 'octokit'
-gem 'httparty'
+gem 'rubyzip'
+
View
@@ -1,28 +1,27 @@
GEM
- remote: http://rubygems.org/
+ remote: https://rubygems.org/
specs:
- addressable (2.3.2)
- faraday (0.8.4)
+ addressable (2.3.3)
+ faraday (0.8.7)
multipart-post (~> 1.1)
- faraday_middleware (0.8.8)
+ faraday_middleware (0.9.0)
faraday (>= 0.7.4, < 0.9)
- hashie (1.2.0)
- httparty (0.9.0)
- multi_json (~> 1.0)
- multi_xml
- multi_json (1.3.6)
- multi_xml (0.5.1)
- multipart-post (1.1.5)
- octokit (1.17.1)
+ hashie (2.0.3)
+ multi_json (1.7.2)
+ multipart-post (1.2.0)
+ netrc (0.7.7)
+ octokit (1.24.0)
addressable (~> 2.2)
faraday (~> 0.8)
- faraday_middleware (~> 0.8)
- hashie (~> 1.2)
+ faraday_middleware (~> 0.9)
+ hashie (~> 2.0)
multi_json (~> 1.3)
+ netrc (~> 0.7.7)
+ rubyzip (0.9.9)
PLATFORMS
ruby
DEPENDENCIES
- httparty
octokit
+ rubyzip
View
@@ -1,9 +1,10 @@
-Export issues from a Github repo to a Bitbucket one
+Export issues from a Github repository to the
+(https://confluence.atlassian.com/display/BITBUCKET/Export+or+Import+Issue+Data)[Bitbucket
+Issue Data Format]
-Usage:
-Modify example.config.yml and rename it to config.yml, then:
+## Usage
```
bundle install
-bundle exec ruby cli.rb githubuser/repo bitbucketuser/repo
+bundle exec ruby cli.rb githubuser/repo username password exportfilename.zip
```
View
20 cli.rb
@@ -1,4 +1,18 @@
-require './migration'
+require './lib/github-to-bitbucket-issues'
+
+if ARGV.size <= 2
+ options = {
+ :repository => ARGV[0],
+ :filename => ARGV[1] || "export.zip"
+ }
+else
+ options = {
+ :repository => ARGV[0],
+ :username => ARGV[1],
+ :password => ARGV[2],
+ :filename => ARGV[3] || "export.zip"
+ }
+end
+
+GTBI::Export.new(options).generate
-migration = Migration.new(ARGV[0], ARGV[1])
-migration.perform!
View
@@ -1,6 +0,0 @@
-github:
- username: example
- password: example
-bitbucket:
- username: example
- password: example
@@ -0,0 +1,2 @@
+require_relative 'github-to-bitbucket-issues/export'
+
@@ -0,0 +1,33 @@
+module GTBI
+ module Downloaders
+ class Base
+ def initialize(client, repository, options = {})
+ @client = client
+ @repository = repository
+ @options = options
+ end
+
+ def fetch
+ items = []
+ page = 1
+ one_page = []
+
+ loop do
+ @options.merge!({:page => page})
+ one_page = @client.send(client_method, @repository, @options)
+ items += one_page
+ page += 1
+ break if one_page.empty?
+ end
+
+ items
+ end
+
+ protected
+
+ def client_method
+ end
+ end
+ end
+end
+
@@ -0,0 +1,10 @@
+module GTBI
+ module Downloaders
+ class Comment < Base
+ def client_method
+ "issues_comments"
+ end
+ end
+ end
+end
+
@@ -0,0 +1,10 @@
+module GTBI
+ module Downloaders
+ class Issue < Base
+ def client_method
+ "list_issues"
+ end
+ end
+ end
+end
+
@@ -0,0 +1,10 @@
+module GTBI
+ module Downloaders
+ class Milestone < Base
+ def client_method
+ "list_milestones"
+ end
+ end
+ end
+end
+
@@ -0,0 +1,98 @@
+require 'octokit'
+require 'zip/zip'
+require 'json'
+
+require_relative 'formatters/base'
+require_relative 'formatters/issue'
+require_relative 'formatters/comment'
+require_relative 'formatters/milestone'
+require_relative 'downloaders/base'
+require_relative 'downloaders/issue'
+require_relative 'downloaders/comment'
+require_relative 'downloaders/milestone'
+
+module GTBI
+ class Export
+ attr_reader :issues, :comments, :milestones
+
+ def initialize(options)
+ return unless options[:repository]
+
+ @github_client = Octokit::Client.new({
+ :login => options[:username],
+ :password => options[:password]
+ })
+ @repository = options[:repository]
+ @filename = options[:filename]
+ @issues = []
+ @comments = []
+ @milestones = []
+ end
+
+ def generate
+ download_issues
+ download_comments
+ download_milestones
+ generate_archive
+ end
+
+ def to_json
+ JSON.pretty_generate({
+ :issues => @issues,
+ :comments => @comments,
+ :milestones => @milestones,
+ :attachments => [],
+ :logs => [],
+ :meta => {
+ :default_assignee => nil,
+ :default_component => nil,
+ :default_kind => "bug",
+ :default_milestone => nil,
+ :default_version => nil
+ },
+ :components => [],
+ :versions => []
+ })
+ end
+
+ private
+
+ def download_issues
+ %w(open closed).each do |state|
+ @issues += download_all_of("issue", {:state => state})
+ end
+ end
+
+ def download_comments
+ @comments = download_all_of("comment")
+ end
+
+ def download_milestones
+ @milestones = download_all_of("milestone")
+ end
+
+ def download_all_of(type, options = {})
+ items = downloader(type).new(@github_client, @repository, options).fetch
+ items.map do |item|
+ formatter(type).new(item).formatted
+ end
+ end
+
+ def downloader(type)
+ Object.const_get("GTBI::Downloaders::#{type.capitalize}")
+ end
+
+ def formatter(type)
+ Object.const_get("GTBI::Formatters::#{type.capitalize}")
+ end
+
+ def generate_archive
+ Zip::ZipFile.open(@filename, Zip::ZipFile::CREATE) do |zipfile|
+ zipfile.get_output_stream("db-1.0.json") do |f|
+ f.puts to_json
+ end
+ end
+ end
+ end
+end
+
@@ -0,0 +1,9 @@
+module GTBI
+ module Formatters
+ class Base
+ def initialize(raw)
+ @raw = raw
+ end
+ end
+ end
+end
@@ -0,0 +1,24 @@
+module GTBI
+ module Formatters
+ class Comment < Base
+ def formatted
+ {
+ :content => @raw.body,
+ :created_on => @raw.created_at,
+ :id => @raw.id,
+ :issue => get_issue(@raw),
+ :updated_on => @raw.updated_at,
+ :user => @raw.user.login
+ }
+ end
+
+ private
+
+ def get_issue(comment)
+ comment.issue_url.split('/').last
+ end
+
+ end
+ end
+end
+
@@ -0,0 +1,75 @@
+module GTBI
+ module Formatters
+ class Issue < Base
+ def formatted
+ {
+ :assignee => get_assignee(@raw),
+ :component => nil,
+ :content => @raw.body || " ",
+ :content_updated_on => @raw.updated_at,
+ :created_on => @raw.updated_at,
+ :edited_on => @raw.updated_at,
+ :id => @raw.number,
+ :kind => get_kind(@raw),
+ :milestone => get_milestone(@raw),
+ :priority => get_priority(@raw),
+ :reporter => @raw.user.login,
+ :status => get_status(@raw),
+ :title => @raw.title,
+ :updated_on => @raw.updated_at,
+ :version => nil,
+ :watchers => []
+ }
+ end
+
+ private
+
+ def get_assignee(issue)
+ issue.assignee.login if issue.assignee && issue.assignee.login
+ end
+
+ def get_status(issue)
+ if issue.state == 'closed'
+ 'resolved'
+ else
+ 'new'
+ end
+ end
+
+ def get_kind(issue)
+ if issue.labels.to_s =~ /enhancement/i
+ 'enhancement'
+ elsif issue.labels.to_s =~ /proposal/i
+ 'proposal'
+ elsif issue.labels.to_s =~ /task/i
+ 'task'
+ else
+ 'bug'
+ end
+ end
+
+ def get_priority(issue)
+ if issue.labels.to_s =~ /trivial/i
+ 'trivial'
+ elsif issue.labels.to_s =~ /minor/i
+ 'minor'
+ elsif issue.labels.to_s =~ /critical/i
+ 'critical'
+ elsif issue.labels.to_s =~ /blocker/i
+ 'blocker'
+ else
+ 'major'
+ end
+ end
+
+ def get_milestone(issue)
+ if issue.milestone
+ milestone = issue.milestone.title
+ end
+
+ milestone
+ end
+ end
+ end
+end
+
@@ -0,0 +1,12 @@
+module GTBI
+ module Formatters
+ class Milestone < Base
+ def formatted
+ {
+ :name => @raw.title
+ }
+ end
+ end
+ end
+end
+
Oops, something went wrong.

0 comments on commit 7886967

Please sign in to comment.