Last active
October 8, 2024 14:45
-
-
Save rbellamy/3c5033ba605a090824e8 to your computer and use it in GitHub Desktop.
Bulk import Bitbucket repos to Github
This file contains 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 ruby | |
require 'fileutils' | |
# Originally -- Dave Deriso -- [email protected] | |
# Contributor -- G. Richard Bellamy -- [email protected] | |
# If you contribute, put your name here! | |
# To get your team ID: | |
# 1. Go to your GitHub profile, select 'Personal Access Tokens', and create an Access token | |
# 2. curl -H "Authorization: token <very-long-access-token>" https://api.github.com/orgs/<org-name>/teams | |
# 3. Find the team name, and grabulate the Team ID | |
# 4. PROFIT! | |
#---------------------------------------------------------------------- | |
#your particulars | |
@access_token = '' | |
@team_id = '' | |
@org = '' | |
#---------------------------------------------------------------------- | |
#the verison of this app | |
@version = "0.2" | |
#---------------------------------------------------------------------- | |
#some global params | |
@create = false | |
@add = false | |
@migrate = false | |
@debug = false | |
@done = false | |
@error = false | |
#---------------------------------------------------------------------- | |
#fancy schmancy color scheme | |
class String; def c(cc); "\e[#{cc}m#{self}\e[0m" end end | |
#200.to_i.times{ |i| print i.to_s.c(i) + " " }; puts | |
@sep = "-".c(90)*95 | |
@sep_pref = ".".c(90)*95 | |
@sep_thick = "+".c(90)*95 | |
#---------------------------------------------------------------------- | |
# greetings | |
def hello | |
puts @sep | |
puts "BitBucket to GitHub migrator -- v.#{@version}".c(95) | |
#puts @sep_thick | |
end | |
def goodbye | |
puts @sep | |
puts "done!".c(95) | |
puts @sep | |
exit | |
end | |
def puts_title(text) | |
puts @sep, "#{text}".c(36), @sep | |
end | |
#---------------------------------------------------------------------- | |
# helper methods | |
def get_options | |
require 'optparse' | |
n_options = 0 | |
show_options = false | |
OptionParser.new do |opts| | |
opts.banner = @sep +"\nUsage: gitter [options]\n".c(36) | |
opts.version = @version | |
opts.on('-n', '--name [name]', String, 'Set the name of the new repo') { |value| @repo_name = value; n_options+=1 } | |
opts.on('-c', '--create', String, 'Create new repo') { @create = true; n_options+=1 } | |
opts.on('-m', '--migrate', String, 'Migrate the repo') { @migrate = true; n_options+=1 } | |
opts.on('-a', '--add', String, 'Add repo to team') { @add = true; n_options+=1 } | |
opts.on('-l', '--language [language]', String, 'Set language of the new repo') { |value| @language = value.strip.downcase; n_options+=1 } | |
opts.on('-d', '--debug', 'Print commands for inspection, doesn\'t actually run them') { @debug = true; n_options+=1 } | |
opts.on_tail('-h', '--help', 'Prints this little guide') { show_options = true; n_options+=1 } | |
@opts = opts | |
end.parse! | |
if show_options || n_options == 0 | |
puts @opts | |
puts "\nExamples:".c(36) | |
puts 'create new repo: ' + "\t\tgitter -c -l javascript -n node_app".c(93) | |
puts 'migrate existing to GitHub: ' + "\tgitter -m -n node_app".c(93) | |
puts 'create repo and migrate to it: ' + "\tgitter -c -m -l javascript -n node_app".c(93) | |
puts 'create repo, migrate to it, and add it to a team: ' + "\tgitter -c -m -a -l javascript -n node_app".c(93) | |
puts "\nNotes:".c(36) | |
puts "Access Token for repo is #{@access_token} - change this on line 13" | |
puts "Team ID for repo is #{@team_id} - change this on line 14" | |
puts "Organization for repo is #{@org} - change this on line 15" | |
puts 'The assumption is that the person running the script has SSH access to BitBucket,' | |
puts 'and GitHub, and that if the current directory contains a directory with the same' | |
puts 'name as the repo to migrated, it will deleted and recreated, or created if it' | |
puts 'doesn\'t exist - the repo to migrate is mirrored locally, and then created on' | |
puts 'GitHub and pushed from that local clone.' | |
puts 'New repos are private by default' | |
puts "Doesn\'t like symbols for language (ex. use \'c\' instead of \'c++\')" | |
puts @sep | |
exit | |
end | |
end | |
#---------------------------------------------------------------------- | |
# git helper methods | |
def gitter_create(repo) | |
if @language | |
%q[curl https://api.github.com/orgs/] + @org + %q[/repos -H "Authorization: token ] + @access_token + %q[" -d '{"name":"] + repo + %q[","private":true,"language":"] + @language + %q["}'] | |
else | |
%q[curl https://api.github.com/orgs/] + @org + %q[/repos -H "Authorization: token ] + @access_token + %q[" -d '{"name":"] + repo + %q[","private":true}'] | |
end | |
end | |
def gitter_add(repo) | |
if @language | |
%q[curl https://api.github.com/teams/] + @team_id + %q[/repos/] + @org + %q[/] + repo + %q[ -H "Accept: application/vnd.github.v3+json" -H "Authorization: token ] + @access_token + %q[" -d '{"permission":"pull","language":"] + @language + %q["}'] | |
else | |
%q[curl https://api.github.com/teams/] + @team_id + %q[/repos/] + @org + %q[/] + repo + %q[ -H "Accept: application/vnd.github.v3+json" -H "Authorization: token ] + @access_token + %q[" -d '{"permission":"pull"}'] | |
end | |
end | |
def git_clone_mirror(bitbucket_origin, path) | |
"git clone --mirror #{bitbucket_origin}" | |
end | |
def git_push_mirror(github_origin, path) | |
"(cd './#{path}' && git push --mirror #{github_origin} && cd ..)" | |
end | |
def show_pwd | |
if @debug | |
Dir.getwd() | |
end | |
end | |
def git_list_origin(path) | |
"(cd './#{path}' && git config remote.origin.url && cd ..)" | |
end | |
# error checks | |
def has_repo | |
File.exist?('.git') | |
end | |
def has_repo_or_error(show_error) | |
@repo_exists = has_repo | |
if !@repo_exists | |
puts 'Error: no .git folder in current directory'.c(91) if show_error | |
@error = true | |
end | |
"has repo: #{@repo_exists}" | |
end | |
def has_repo_name_or_error(show_error) | |
@repo_name_exists = !(defined?(@repo_name)).nil? | |
if !@repo_name_exists | |
puts 'Error: repo name missing (-n your_name_here)'.c(91) if show_error | |
@error = true | |
end | |
end | |
#---------------------------------------------------------------------- | |
# main methods | |
def run(commands) | |
if @debug | |
commands.each { |x| puts(x) } | |
else | |
commands.each { |x| system(x) } | |
end | |
end | |
def set_globals | |
puts_title 'Parameters' | |
@git_bitbucket_origin = "[email protected]:#{@org}/#{@repo_name}.git" | |
@git_github_origin = "[email protected]:#{@org}/#{@repo_name}.git" | |
puts 'debug: ' + @debug.to_s.c(93) | |
puts 'working in: ' + Dir.pwd.c(93) | |
puts 'create: ' + @create.to_s.c(93) | |
puts 'migrate: ' + @migrate.to_s.c(93) | |
puts 'add: ' + @add.to_s.c(93) | |
puts 'language: ' + @language.to_s.c(93) | |
puts 'repo name: '+ @repo_name.to_s.c(93) | |
puts 'bitbucket: ' + @git_bitbucket_origin.to_s.c(93) | |
puts 'github: ' + @git_github_origin.to_s.c(93) | |
puts 'team_id: ' + @team_id.to_s.c(93) | |
puts 'org: ' + @org.to_s.c(93) | |
end | |
def create_repo | |
puts_title 'Creating' | |
#error checks | |
has_repo_name_or_error(true) | |
goodbye if @error | |
puts @sep | |
commands = [ | |
gitter_create(@repo_name) | |
] | |
run commands | |
end | |
def add_repo | |
puts_title 'Adding repo to team' | |
#error checks | |
has_repo_name_or_error(true) | |
goodbye if @error | |
puts @sep | |
commands = [ | |
gitter_add(@repo_name) | |
] | |
run commands | |
end | |
def migrate_repo | |
puts_title "Migrating Repo to #{@repo_provider}" | |
#error checks | |
has_repo_name_or_error(true) | |
goodbye if @error | |
if Dir.exists?("#{@repo_name}.git") | |
puts "#{@repo_name} already exists... recursively deleting." | |
FileUtils.rm_r("#{@repo_name}.git") | |
end | |
path = "#{@repo_name}.git" | |
commands = [ | |
git_clone_mirror(@git_bitbucket_origin, path), | |
git_list_origin(path), | |
git_push_mirror(@git_github_origin, path) | |
] | |
run commands | |
end | |
#---------------------------------------------------------------------- | |
#sequence control | |
hello | |
get_options | |
#do stuff | |
set_globals | |
create_repo if @create | |
migrate_repo if @migrate | |
add_repo if @add | |
#peace out | |
goodbye |
This file contains 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
# create a list of repos | |
foo | |
bar | |
baz | |
# execute the script, iterating over your list | |
while read p; do ./bitbucket-to-github.rb -a -n $p; done<repos | |
# good nuff |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment