git2bit 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ .DS_Store
2
+ results.html
3
+ pkg
4
+ html
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in git2bit.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,76 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ git2bit (1.0.1)
5
+ bitbucket_rest_api
6
+ github_api
7
+ methadone (~> 1.2.4)
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ aruba (0.5.1)
13
+ childprocess (~> 0.3.6)
14
+ cucumber (>= 1.1.1)
15
+ rspec-expectations (>= 2.7.0)
16
+ bitbucket_rest_api (0.1.1)
17
+ faraday (~> 0.8.1)
18
+ faraday_middleware (~> 0.8.1)
19
+ hashie (~> 1.2.0)
20
+ multi_json (~> 1.3)
21
+ nokogiri (~> 1.5.2)
22
+ simple_oauth
23
+ builder (3.1.4)
24
+ childprocess (0.3.6)
25
+ ffi (~> 1.0, >= 1.0.6)
26
+ cucumber (1.2.1)
27
+ builder (>= 2.1.2)
28
+ diff-lcs (>= 1.1.3)
29
+ gherkin (~> 2.11.0)
30
+ json (>= 1.4.6)
31
+ diff-lcs (1.1.3)
32
+ faraday (0.8.4)
33
+ multipart-post (~> 1.1)
34
+ faraday_middleware (0.8.8)
35
+ faraday (>= 0.7.4, < 0.9)
36
+ ffi (1.2.0)
37
+ gherkin (2.11.5)
38
+ json (>= 1.4.6)
39
+ github_api (0.8.6)
40
+ faraday (~> 0.8.1)
41
+ hashie (~> 1.2.0)
42
+ multi_json (~> 1.4)
43
+ nokogiri (~> 1.5.2)
44
+ oauth2
45
+ hashie (1.2.0)
46
+ httpauth (0.2.0)
47
+ json (1.7.5)
48
+ jwt (0.1.5)
49
+ multi_json (>= 1.0)
50
+ methadone (1.2.4)
51
+ bundler
52
+ multi_json (1.5.0)
53
+ multipart-post (1.1.5)
54
+ nokogiri (1.5.6)
55
+ oauth2 (0.8.0)
56
+ faraday (~> 0.8)
57
+ httpauth (~> 0.1)
58
+ jwt (~> 0.1.4)
59
+ multi_json (~> 1.0)
60
+ rack (~> 1.2)
61
+ rack (1.4.1)
62
+ rake (0.9.2.2)
63
+ rdoc (3.12)
64
+ json (~> 1.4)
65
+ rspec-expectations (2.12.1)
66
+ diff-lcs (~> 1.1.3)
67
+ simple_oauth (0.2.0)
68
+
69
+ PLATFORMS
70
+ ruby
71
+
72
+ DEPENDENCIES
73
+ aruba
74
+ git2bit!
75
+ rake (~> 0.9.2)
76
+ rdoc
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Joe Workman
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,77 @@
1
+ # git2bit
2
+
3
+ There are many people out there that have migrated their private repositories from Github to BitBucket. BitBucket has a goo utility that will clone your entire repository over, however, there is no way to migrate any existing issues that you have on Github.
4
+
5
+ git2bit is a CLI that solves this by migrating all your issues along with their comments and milestones from Github into your new BitBucket repo.
6
+
7
+ **Important Tip**: I recommend that you create a new blank repo in Bitbucket to run intial migration tests with. Once you are happy with the migration results, you can delete this repository and proceed with migrating issues to the production repo.
8
+
9
+ ## Installation
10
+
11
+ Install it via the gem command in terminal:
12
+
13
+ $ gem install git2bit
14
+
15
+ You can now execute it:
16
+
17
+ $ git2bit --help
18
+
19
+ ## Usage
20
+
21
+ Here is an overview of the options available to git2bit along with some helpful examples. See below for how to set these values using a `.git2bit.rc` config file.
22
+
23
+ <pre>
24
+ Usage: git2bit [options]
25
+
26
+ Options:
27
+ -h, --help Show command line help
28
+ --version Show help/version info
29
+ --[no-]closed [Do not] migrate closed issues
30
+ --issue ISSUE_NUMBER Process only a single Github issue number
31
+ --guser USER Github username
32
+ --gpass PASSWORD Github password
33
+ --grepo REPO Github repo name
34
+ --buser USER BitBucket username
35
+ --bpass PASSWORD BitBucket password
36
+ --brepo REPO BitBucket repo name
37
+ --log-level LEVEL Set the logging level
38
+ (debug|info|warn|error|fatal)
39
+ (Default: info)
40
+ </pre>
41
+
42
+ The following examples assume that you have the following options configured in your `.git2bit.rc` file: guser, gpass, grepo, buser, bpass, brepo
43
+
44
+ Move *all* issues (open and closed):
45
+
46
+ $ git2bit
47
+
48
+ Move only *open* issues:
49
+
50
+ $ git2bit --no-close
51
+
52
+ Move a single issue:
53
+
54
+ $ git2bit -i 532
55
+
56
+ ### .git2bit.rc
57
+
58
+ Instead of passing a ton of options via command line, you can setup the configuration values in a file named **.git2bit.rc**. This file should live in your home directory.
59
+
60
+ Here is a sample file to get you going.
61
+
62
+ guser: joeworkman
63
+ gpass: p@ssw0rd
64
+ grepo: myrepo
65
+
66
+ buser: joeworkman
67
+ bpass: p@ssw0rd
68
+ brepo: newrepo
69
+
70
+
71
+ ## Contributing
72
+
73
+ 1. Fork it
74
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
75
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
76
+ 4. Push to the branch (`git push origin my-new-feature`)
77
+ 5. Create new Pull Request
data/README.rdoc ADDED
@@ -0,0 +1,19 @@
1
+ = git2bit - DESCRIBE YOUR GEM
2
+
3
+ Author:: YOUR NAME (YOUR EMAIL)
4
+ Copyright:: Copyright (c) 2013 YOUR NAME
5
+
6
+
7
+ DESCRIBE YOUR GEM HERE
8
+
9
+ == Links
10
+
11
+ * {Source on Github}[LINK TO GITHUB]
12
+ * RDoc[LINK TO RDOC.INFO]
13
+
14
+ == Install
15
+
16
+ == Examples
17
+
18
+ == Contributing
19
+
data/Rakefile ADDED
@@ -0,0 +1,61 @@
1
+ def dump_load_path
2
+ puts $LOAD_PATH.join("\n")
3
+ found = nil
4
+ $LOAD_PATH.each do |path|
5
+ if File.exists?(File.join(path,"rspec"))
6
+ puts "Found rspec in #{path}"
7
+ if File.exists?(File.join(path,"rspec","core"))
8
+ puts "Found core"
9
+ if File.exists?(File.join(path,"rspec","core","rake_task"))
10
+ puts "Found rake_task"
11
+ found = path
12
+ else
13
+ puts "!! no rake_task"
14
+ end
15
+ else
16
+ puts "!!! no core"
17
+ end
18
+ end
19
+ end
20
+ if found.nil?
21
+ puts "Didn't find rspec/core/rake_task anywhere"
22
+ else
23
+ puts "Found in #{path}"
24
+ end
25
+ end
26
+ require 'bundler'
27
+ require 'rake/clean'
28
+
29
+ require 'rake/testtask'
30
+
31
+ require 'cucumber'
32
+ require 'cucumber/rake/task'
33
+ gem 'rdoc' # we need the installed RDoc gem, not the system one
34
+ require 'rdoc/task'
35
+
36
+ include Rake::DSL
37
+
38
+ Bundler::GemHelper.install_tasks
39
+
40
+
41
+ Rake::TestTask.new do |t|
42
+ t.pattern = 'test/tc_*.rb'
43
+ end
44
+
45
+
46
+ CUKE_RESULTS = 'results.html'
47
+ CLEAN << CUKE_RESULTS
48
+ Cucumber::Rake::Task.new(:features) do |t|
49
+ t.cucumber_opts = "features --format html -o #{CUKE_RESULTS} --format pretty --no-source -x"
50
+ t.fork = false
51
+ end
52
+
53
+ Rake::RDocTask.new do |rd|
54
+
55
+ rd.main = "README.rdoc"
56
+
57
+ rd.rdoc_files.include("README.rdoc","lib/**/*.rb","bin/**/*")
58
+ end
59
+
60
+ task :default => [:test,:features]
61
+
data/bin/git2bit ADDED
@@ -0,0 +1,127 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'date'
4
+ require 'optparse'
5
+ require 'methadone'
6
+ require 'git2bit'
7
+
8
+ class App
9
+ include Methadone::Main
10
+ include Methadone::CLILogging
11
+
12
+ main do
13
+ help_now!("'guser' is required") unless options[:guser]
14
+ help_now!("'gpass' is required") unless options[:gpass]
15
+ help_now!("'grepo' is required") unless options[:grepo]
16
+
17
+ help_now!("'buser' is required") unless options[:buser]
18
+ help_now!("'bpass' is required") unless options[:bpass]
19
+ help_now!("'brepo' is required") unless options[:brepo]
20
+
21
+ debug "Configuration Used: " + options.inspect
22
+
23
+ # Connect to Bitbucket and Github
24
+ bitbucket = Git2bit::BitbucketProxy.new({:user => options[:buser], :pass => options[:bpass],:repo => options[:brepo]})
25
+ github = Git2bit::GithubProxy.new({:user => options[:guser], :pass => options[:gpass], :repo => options[:grepo]})
26
+
27
+ if options[:issue]
28
+ info "Will only process Github issue ##{options[:issue]}"
29
+ else
30
+ if options[:closed]
31
+ info "Starting to process through ALL Github issues"
32
+ else
33
+ info "Starting to process through only the OPENED Github issues"
34
+ end
35
+ end
36
+
37
+ # Start processing each issue in Github
38
+ github.each_issue(options[:closed]) { |issue|
39
+
40
+ # Go to the next iteration if the issue number does not match option provided
41
+ next if options[:issue] and options[:issue].to_i != issue.number
42
+
43
+ info "Processing Github issue ##{issue.number}"
44
+
45
+ if issue.milestone and !bitbucket.milestones.find_index(issue.milestone.title)
46
+ # If there is a milestone and it does not already exist, then create it
47
+ bitbucket.create_milestone(issue.milestone.title)
48
+ end
49
+
50
+ # Analyze the Github labels in an attempt to find the BitBucket data we need
51
+ tags = bitbucket.analyze_labels issue.labels.map{|x| x.name}
52
+
53
+ if tags[:status].nil? or issue.state == 'closed'
54
+ # If a status was not defined in the github labels, then set to open/resolved
55
+ # If the Github state is closed, we want to ignore the labels and set the ticket to resolved
56
+ tags[:status] = issue.state == 'open' ? 'open' : 'resolved'
57
+ end
58
+
59
+ issue_date = DateTime.parse(issue.created_at)
60
+ issue_body = "_Github issue **##{issue.number}** created by **#{issue.user.login}** on #{issue_date.strftime('%F %T')}_\n\n#{issue[:body]}"
61
+
62
+ # Create the Bitbucket issue
63
+ new_issue = bitbucket.create_issue({
64
+ :title => issue.title,
65
+ :content => issue_body,
66
+ :responsible => issue.assignee,
67
+ :milestone => issue.milestone ? issue.milestone.title : nil,
68
+ :component => tags[:component],
69
+ :priority => tags[:priority],
70
+ :status => tags[:status],
71
+ :kind => tags[:kind]
72
+ })
73
+
74
+ # Add the Github labels as a comment so the data is not lost
75
+ bitbucket.create_comment new_issue, "**Github labels**: " + tags[:labels].join(', ')
76
+
77
+ # Process Comments if the Github issue has any
78
+ if issue.comments > 1
79
+ # Get the Github comments
80
+ comments = github.get_comments issue.number
81
+
82
+ comments.each do |comment|
83
+ comment_date = DateTime.parse(comment.created_at)
84
+ # Add the comment into the newly created bitbucket issue
85
+ bitbucket.create_comment new_issue, "_Github comment by **#{comment.user.login}** on #{comment_date.strftime('%F %T')}_\n\n#{comment[:body]}"
86
+ end
87
+ end
88
+ }
89
+ info "Processing Complete."
90
+ end
91
+
92
+ # Declare command-line interface here
93
+ version Git2bit::VERSION
94
+
95
+ description 'git2bit migrates issues with their comments and milestones from a github repo to a bitbucket repo'
96
+
97
+ on("--[no-]closed","[Do not] migrate closed issues")
98
+
99
+ on("--issue ISSUE_NUMBER","Process only a single Github issue number")
100
+
101
+ on("--guser USER","Github username")
102
+ on("--gpass PASSWORD","Github password")
103
+ on("--grepo REPO","Github repo name")
104
+
105
+ on("--buser USER","BitBucket username")
106
+ on("--bpass PASSWORD","BitBucket password")
107
+ on("--brepo REPO","BitBucket repo name")
108
+
109
+ use_log_level_option
110
+ defaults_from_config_file '.git2bit.rc'
111
+
112
+ go!
113
+ end
114
+
115
+ __END__
116
+
117
+ # Sample .git2bit.rc file
118
+
119
+ closed: true
120
+
121
+ guser: joeworkman
122
+ gpass: p@ssw0rd
123
+ grepo: myrepo
124
+
125
+ buser: joeworkman
126
+ bpass: p@ssw0rd
127
+ brepo: newrepo
@@ -0,0 +1,13 @@
1
+ Feature: My bootstrapped app kinda works
2
+ In order to get going on coding my awesome app
3
+ I want to have aruba and cucumber setup
4
+ So I don't have to do it myself
5
+
6
+ Scenario: App just runs
7
+ When I get help for "git2bit"
8
+ Then the exit status should be 0
9
+ And the banner should be present
10
+ And the banner should document that this app takes options
11
+ And the following options should be documented:
12
+ |--version|
13
+ And the banner should document that this app takes no arguments
@@ -0,0 +1 @@
1
+ # Put your step definitions here
@@ -0,0 +1,16 @@
1
+ require 'aruba/cucumber'
2
+ require 'methadone/cucumber'
3
+
4
+ ENV['PATH'] = "#{File.expand_path(File.dirname(__FILE__) + '/../../bin')}#{File::PATH_SEPARATOR}#{ENV['PATH']}"
5
+ LIB_DIR = File.join(File.expand_path(File.dirname(__FILE__)),'..','..','lib')
6
+
7
+ Before do
8
+ # Using "announce" causes massive warnings on 1.9.2
9
+ @puts = true
10
+ @original_rubylib = ENV['RUBYLIB']
11
+ ENV['RUBYLIB'] = LIB_DIR + File::PATH_SEPARATOR + ENV['RUBYLIB'].to_s
12
+ end
13
+
14
+ After do
15
+ ENV['RUBYLIB'] = @original_rubylib
16
+ end
data/git2bit.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'git2bit/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "git2bit"
8
+ gem.version = Git2bit::VERSION
9
+ gem.authors = ["Joe Workman"]
10
+ gem.email = ["joe at workmanmail.com"]
11
+ gem.description = %q{git2bit migrates issues with their comments and milestones from a github repo to a bitbucket repo}
12
+ gem.summary = %q{git2bit migrates issues with their comments and milestones from a github repo to a bitbucket repo}
13
+ gem.homepage = "https://bitbucket.org/joeworkman/git2bit"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+ gem.add_development_dependency('rdoc')
20
+ gem.add_development_dependency('aruba')
21
+ gem.add_development_dependency('rake', '~> 0.9.2')
22
+ gem.add_dependency('methadone', '~> 1.2.4')
23
+ gem.add_dependency('github_api')
24
+ gem.add_dependency('bitbucket_rest_api')
25
+ end
data/git2bit.rb ADDED
@@ -0,0 +1,133 @@
1
+ require 'date'
2
+ require 'github_api'
3
+ require 'bitbucket_rest_api'
4
+
5
+ bb_owner = 'joeworkman'
6
+ bb_repo = 'testinggit2bit'
7
+ bb_user = 'joeworkman'
8
+ bb_pass = 'dopey09'
9
+
10
+ # Possible values from BitBucket
11
+ BB_STATUS = ['new','open','resolved','on hold','invalid','duplicate','wontfix']
12
+ BB_KINDS = ['bug','enhancement','proposal','task']
13
+ BB_PRIORITIES = ['trivial','minor','major','critical','blocker']
14
+
15
+ gh_repo = 'stacks'
16
+ gh_user = 'joeworkman'
17
+ gh_pass = 'dopey09'
18
+
19
+
20
+ def analyze_labels(labels,components)
21
+ # The tag values that we are going to try to discover
22
+ tags = { :component => nil, :priority => nil, :kind => nil, :status => nil, :labels => Array.new }
23
+
24
+ labels.each do |label|
25
+ # Store the label name
26
+ tags[:labels].push label.name
27
+
28
+ name = label.name.downcase
29
+
30
+ # Look for a priority in available fields in BB_PRIORITIES
31
+ if tags[:priority].nil? and BB_PRIORITIES.find_index(name)
32
+ tags[:priority] = name
33
+ next
34
+ end
35
+
36
+ # Look for a kind in available fields in BB_KINDS
37
+ if tags[:kind].nil? and BB_KINDS.find_index(name)
38
+ tags[:kind] = name
39
+ next
40
+ end
41
+
42
+ # Look for a status in available fields in BB_STATUS
43
+ if tags[:status].nil? and BB_STATUS.find_index(name)
44
+ tags[:status] = name
45
+ next
46
+ end
47
+
48
+ # Look for a component. Need to do case insensitive match on each known component.
49
+ if tags[:component].nil?
50
+ components.each do |c|
51
+ if c.match(/#{name}/i)
52
+ tags[:component] = c
53
+ break
54
+ end
55
+ end
56
+ end
57
+ end
58
+ tags
59
+ end
60
+
61
+
62
+ # Connect to BitBucket
63
+ bitbucket = BitBucket.new :basic_auth => "#{bb_user}:#{bb_pass}", :user => bb_user, :repo => bb_repo
64
+ # Store Milestones to search upon later on
65
+ bb_milestones = Array.new
66
+ bitbucket.issues.milestones.list(bb_owner, bb_repo).each {|m| bb_milestones.push m.name}
67
+ # Store Components to search upon later on
68
+ bb_components = Array.new
69
+ bitbucket.issues.components.list(bb_owner, bb_repo).each {|c| bb_components.push c.name}
70
+
71
+
72
+ # Setup Github connection
73
+ github = Github.new :basic_auth => "#{gh_user}:#{gh_pass}"
74
+ # Get all open and closed issues
75
+ github_data = Array.new
76
+ github_data.push github.issues.list :filter => 'all', :state => 'open', :user => gh_user, :repo => gh_repo
77
+ github_data.push github.issues.list :filter => 'all', :state => 'closed', :user => gh_user, :repo => gh_repo
78
+
79
+ # Process through each page of github issues and then through each issue per page
80
+ github_data.each do |result_set|
81
+ result_set.each_page do |page|
82
+ page.each do |issue|
83
+
84
+ if issue.milestone and !bb_milestones.find_index(issue.milestone.title)
85
+ # If there is a milestone and it does not already exist, then create it
86
+ milestone = bitbucket.issues.milestones.create bb_owner, bb_repo, { :name => issue.milestone.title }
87
+ # Add new milestone to array so its not created again
88
+ bb_milestones.push milestone.name
89
+ end
90
+
91
+ # Analyze the Github labels in an attempt to find the BitBucket data we need
92
+ tags = analyze_labels issue.labels, bb_components
93
+
94
+ if tags[:status].nil? or issue.state == 'closed'
95
+ # If a status was not defined in the github labels, then set to open/resolved
96
+ # If the Github state is closed, we want to ignore the labels and set the ticket to resolved
97
+ tags[:status] = issue.state == 'open' ? 'open' : 'resolved'
98
+ end
99
+
100
+ issue_date = DateTime.parse(issue.created_at)
101
+ issue_body = "_Github issue **##{issue.number}** created by **#{issue.user.login}** on #{issue_date.strftime('%F %T')}_\n\n#{issue[:body]}"
102
+
103
+ # Create the Bitbucket issue
104
+ bb_issue = bitbucket.issues.create bb_owner, bb_repo, {
105
+ :title => issue.title,
106
+ :content => issue_body,
107
+ :responsible => issue.assignee,
108
+ :milestone => issue.milestone ? issue.milestone.title : nil,
109
+ :component => tags[:component],
110
+ :priority => tags[:priority],
111
+ :status => tags[:status],
112
+ :kind => tags[:kind]
113
+ }
114
+
115
+ labels = "**Github labels**: " + tags[:labels].join(', ')
116
+ bitbucket.issues.comments.create bb_owner, bb_repo, bb_issue.local_id, {:content => labels}
117
+
118
+ # Process Comments if the Github issue has any
119
+ if issue.comments > 1
120
+ # Get the Github comments
121
+ comments = github.issues.comments.all gh_user, gh_repo, issue_id: issue.number
122
+
123
+ comments.each do |comment|
124
+ comment_date = DateTime.parse(comment.created_at)
125
+ content = "_Github comment by **#{comment.user.login}** on #{comment_date.strftime('%F %T')}_\n\n#{comment[:body]}"
126
+ # Add the comment into the newly created bitbucket issue
127
+ bitbucket.issues.comments.create bb_owner, bb_repo, bb_issue.local_id, {:content => content}
128
+ end
129
+ end
130
+ end
131
+ exit
132
+ end
133
+ end
@@ -0,0 +1,140 @@
1
+ require 'date'
2
+ require 'bitbucket_rest_api'
3
+ require 'methadone'
4
+
5
+ module Git2bit
6
+ class BitbucketProxy
7
+ include Methadone::Main
8
+ include Methadone::CLILogging
9
+
10
+ attr_reader :components, :milestones
11
+
12
+ # Possible values from BitBucket
13
+ STATUS = ['new','open','resolved','on hold','invalid','duplicate','wontfix']
14
+ KINDS = ['bug','enhancement','proposal','task']
15
+ PRIORITIES = ['trivial','minor','major','critical','blocker']
16
+
17
+ def initialize(args)
18
+ @repo = args[:repo]
19
+ @user = args[:user]
20
+ @owner = args[:user]
21
+
22
+ # Connect to BitBucket
23
+ begin
24
+ @conn = BitBucket.new :basic_auth => "#{@user}:#{args[:pass]}", :user => @user, :repo => @repo
25
+
26
+ # Store Milestones to search upon later on
27
+ @milestones = Array.new
28
+ @conn.issues.milestones.list(@owner, @repo).each {|m| @milestones.push m.name}
29
+ debug "BitBucket Milestones:\n - " + @milestones.join("\n - ")
30
+
31
+ # Store Components to search upon later on
32
+ @components = Array.new
33
+ @conn.issues.components.list(@owner, @repo).each {|c| @components.push c.name}
34
+ debug "BitBucket Components:\n - " + @components.join("\n - ")
35
+
36
+ info "Successfully connected to BitBucket #{@user}/#{@repo}"
37
+ rescue Exception => e
38
+ error = ["Error: Unable to connect to BitBucket #{@user}/#{@repo}", e.message].push e.backtrace
39
+ exit_now!(error.join("\n"))
40
+ end
41
+ end
42
+
43
+ def create_milestone(title)
44
+ begin
45
+ # Create the milestone in BitBucket
46
+ milestone = @conn.issues.milestones.create @owner, @repo, { :name => title }
47
+
48
+ # Add it to known milestones
49
+ @milestones.push title
50
+
51
+ info "BitBucket: created milestone '#{title}'"
52
+ rescue Exception => e
53
+ error "Error: Unable to create to BitBucket milestone '#{title}' - " + e.message
54
+ debug e.backtrace.join("\n")
55
+ end
56
+ milestone
57
+ end
58
+
59
+ def create_issue(args)
60
+ begin
61
+ # Create the Bitbucket issue
62
+ issue = @conn.issues.create @owner, @repo, {
63
+ :title => args[:title],
64
+ :content => args[:content],
65
+ :responsible => args[:responsible],
66
+ :milestone => args[:milestone],
67
+ :component => args[:component],
68
+ :priority => args[:priority],
69
+ :status => args[:status],
70
+ :kind => args[:kind]
71
+ }
72
+ info "BitBucket: created issue ##{issue.local_id} '#{args[:title]}'"
73
+ rescue Exception => e
74
+ error "Error: Unable to create to BitBucket issue '#{args[:title]}' - " + e.message
75
+ debug e.backtrace.join("\n")
76
+ end
77
+ issue.local_id
78
+ end
79
+
80
+ def create_comment(id,content)
81
+ begin
82
+ # Create the Bitbucket comment
83
+ comment = @conn.issues.comments.create @owner, @repo, id, {:content => content}
84
+ info "BitBucket: created comment for issue ##{id}"
85
+ rescue Exception => e
86
+ error "Error: Unable to create to BitBucket comment for issue ##{id} - " + e.message
87
+ debug e.backtrace.join("\n")
88
+ end
89
+ comment
90
+ end
91
+
92
+ def analyze_labels(labels)
93
+ debug "Analyzing labels: " + labels.inspect
94
+
95
+ # The tag values that we are going to try to discover
96
+ tags = { :component => nil, :priority => nil, :kind => nil, :status => nil, :labels => Array.new }
97
+
98
+ labels.each do |label|
99
+ # Store the label name
100
+ tags[:labels].push label
101
+
102
+ name = label.downcase
103
+
104
+ # Look for a priority in available fields in BB_PRIORITIES
105
+ if tags[:priority].nil? and PRIORITIES.find_index(name)
106
+ tags[:priority] = name
107
+ next
108
+ end
109
+
110
+ # Look for a kind in available fields in BB_KINDS
111
+ if tags[:kind].nil? and KINDS.find_index(name)
112
+ tags[:kind] = name
113
+ next
114
+ end
115
+
116
+ # Look for a status in available fields in BB_STATUS
117
+ if tags[:status].nil? and STATUS.find_index(name)
118
+ tags[:status] = name
119
+ next
120
+ end
121
+
122
+ # Look for a component. Need to do case insensitive match on each known component.
123
+ if tags[:component].nil?
124
+ components.each do |c|
125
+ if c.match(/#{name}/i)
126
+ tags[:component] = c
127
+ break
128
+ end
129
+ end
130
+ end
131
+
132
+ end
133
+ debug "Built Tags: " + tags.inspect
134
+
135
+ tags
136
+ end
137
+
138
+
139
+ end
140
+ end
@@ -0,0 +1,50 @@
1
+ require 'date'
2
+ require 'github_api'
3
+ require 'methadone'
4
+
5
+ module Git2bit
6
+ class GithubProxy
7
+ include Methadone::Main
8
+ include Methadone::CLILogging
9
+
10
+ def initialize(args)
11
+ @repo = args[:repo]
12
+ @user = args[:user]
13
+ begin
14
+ @conn = Github.new :basic_auth => "#{@user}:#{args[:pass]}"
15
+ @conn.repos.list user: @user
16
+ info "Successfully connected to Github #{@user}/#{@repo}"
17
+ rescue Exception => e
18
+ error = ["Error: Unable to connect to Github #{@user}/#{@repo}", e.message].push e.backtrace
19
+ exit_now!(error.join("\n"))
20
+ end
21
+ end
22
+
23
+ def each_issue(process_closed = true)
24
+ data = Array.new
25
+ data.push @conn.issues.list :filter => 'all', :state => 'open', :user => @user, :repo => @repo
26
+ if process_closed
27
+ data.push @conn.issues.list :filter => 'all', :state => 'closed', :user => @user, :repo => @repo
28
+ end
29
+
30
+ data.each do |result_set|
31
+ result_set.each_page do |page|
32
+ page.each {|issue| yield(issue)}
33
+ end
34
+ end
35
+ end
36
+
37
+ def get_comments(issue_id)
38
+ begin
39
+ # Get Github comments for issue ID
40
+ comments = @conn.issues.comments.all @user, @repo, issue_id: issue_id
41
+ debug "Github: got comments for issue ##{issue_id}: " + comments.inspect
42
+ rescue Exception => e
43
+ error "Error: Unable to get comments for Github issue ##{issue_id} - " + e.message
44
+ debug e.backtrace.join("\n")
45
+ end
46
+ comments
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,3 @@
1
+ module Git2bit
2
+ VERSION = "1.0.1"
3
+ end
data/lib/git2bit.rb ADDED
@@ -0,0 +1,3 @@
1
+ require "git2bit/version"
2
+ require "git2bit/bitbucket"
3
+ require "git2bit/github"
@@ -0,0 +1,7 @@
1
+ require 'test/unit'
2
+
3
+ class TestSomething < Test::Unit::TestCase
4
+ def test_truth
5
+ assert true
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,172 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: git2bit
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Joe Workman
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-01-09 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rdoc
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: aruba
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rake
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: 0.9.2
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 0.9.2
62
+ - !ruby/object:Gem::Dependency
63
+ name: methadone
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: 1.2.4
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 1.2.4
78
+ - !ruby/object:Gem::Dependency
79
+ name: github_api
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :runtime
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: bitbucket_rest_api
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :runtime
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ description: git2bit migrates issues with their comments and milestones from a github
111
+ repo to a bitbucket repo
112
+ email:
113
+ - joe at workmanmail.com
114
+ executables:
115
+ - git2bit
116
+ extensions: []
117
+ extra_rdoc_files: []
118
+ files:
119
+ - .gitignore
120
+ - Gemfile
121
+ - Gemfile.lock
122
+ - LICENSE.txt
123
+ - README.md
124
+ - README.rdoc
125
+ - Rakefile
126
+ - bin/git2bit
127
+ - features/git2bit.feature
128
+ - features/step_definitions/git2bit_steps.rb
129
+ - features/support/env.rb
130
+ - git2bit.gemspec
131
+ - git2bit.rb
132
+ - lib/git2bit.rb
133
+ - lib/git2bit/bitbucket.rb
134
+ - lib/git2bit/github.rb
135
+ - lib/git2bit/version.rb
136
+ - test/tc_something.rb
137
+ homepage: https://bitbucket.org/joeworkman/git2bit
138
+ licenses: []
139
+ post_install_message:
140
+ rdoc_options: []
141
+ require_paths:
142
+ - lib
143
+ required_ruby_version: !ruby/object:Gem::Requirement
144
+ none: false
145
+ requirements:
146
+ - - ! '>='
147
+ - !ruby/object:Gem::Version
148
+ version: '0'
149
+ segments:
150
+ - 0
151
+ hash: -4585294509181792167
152
+ required_rubygems_version: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ! '>='
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
158
+ segments:
159
+ - 0
160
+ hash: -4585294509181792167
161
+ requirements: []
162
+ rubyforge_project:
163
+ rubygems_version: 1.8.24
164
+ signing_key:
165
+ specification_version: 3
166
+ summary: git2bit migrates issues with their comments and milestones from a github
167
+ repo to a bitbucket repo
168
+ test_files:
169
+ - features/git2bit.feature
170
+ - features/step_definitions/git2bit_steps.rb
171
+ - features/support/env.rb
172
+ - test/tc_something.rb