gitpusher 0.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,3 @@
1
+ config/default.yml
2
+ pkg
3
+ Gemfile.lock
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
data/README.md ADDED
@@ -0,0 +1,33 @@
1
+ # gitpusher
2
+
3
+ gitpusher is a command line tool for replicating git repositories from one service to another.
4
+
5
+ ```
6
+ $ gitpusher -c default.yml
7
+ ```
8
+
9
+ default.yaml is like this.
10
+
11
+ ```
12
+ :base_dir: /var/repos
13
+ :src:
14
+ :type: github
15
+ :dest:
16
+ :type: bitbucket
17
+ ```
18
+
19
+ With this settings, All of your repositories on GitHub will be replicated to BitBucket.
20
+ (User name and password of each service are asked when you run the command first.)
21
+
22
+ If you would like to replicate GitHub organization's repos instead of your own repos, settings are like this.
23
+
24
+ ```
25
+ :base_dir: /var/repos
26
+ :src:
27
+ :type: github
28
+ :organization: github
29
+ :dest:
30
+ :type: bitbucket
31
+ ```
32
+
33
+ Now this tool support only replicating from GitHub to BitBucket.
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/gitpusher ADDED
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'gitpusher'
4
+ require 'optparse'
5
+
6
+ options = {}
7
+ op = OptionParser.new do |opts|
8
+ opts.on('-c', '--config FILE') do |file|
9
+ options[:config] = file
10
+ end
11
+ end
12
+
13
+ op.parse!
14
+
15
+ options[:config] ||= 'config/default.yml'
16
+
17
+ context = GitPusher::Context.instance
18
+ context.home = File.join(File.dirname(__FILE__), '..')
19
+
20
+ GitPusher::Config.load(options)
21
+
22
+ GitPusher::Runner.run
23
+
@@ -0,0 +1,6 @@
1
+ :base_dir: /var/repos
2
+ :src:
3
+ :type: github
4
+ :dest:
5
+ :type: bitbucket
6
+
data/gitpusher.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "gitpusher/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "gitpusher"
7
+ s.version = GitPusher::VERSION
8
+ s.authors = ["Gosuke Miyashita"]
9
+ s.email = ["gosukenator@gmail.com"]
10
+ s.homepage = "https://github.com/mizzy/gitpusher"
11
+ s.summary = %q{A command line tool for replicating git repositories from one service to another.}
12
+
13
+ s.files = `git ls-files`.split("\n")
14
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
15
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
16
+ s.require_paths = ["lib"]
17
+
18
+ # dependencies
19
+ s.add_dependency 'grit'
20
+ s.add_dependency 'octokit'
21
+ s.add_dependency 'pit'
22
+ s.add_dependency 'grit'
23
+ end
@@ -0,0 +1,10 @@
1
+ require 'yaml'
2
+ module GitPusher
3
+ class Config
4
+ def self.load(options)
5
+ context = GitPusher::Context.instance
6
+ context.config = YAML.load_file(File.join(options[:config]))
7
+ end
8
+ end
9
+ end
10
+
@@ -0,0 +1,7 @@
1
+ require 'singleton'
2
+ module GitPusher
3
+ class Context
4
+ include Singleton
5
+ attr_accessor :home, :config
6
+ end
7
+ end
@@ -0,0 +1,17 @@
1
+ module GitPusher
2
+ class Helper
3
+
4
+ =begin いらないかも
5
+ def self.git_config_value(name, trim = true)
6
+ res = `git config issue.#{name}`
7
+ trim ? res.strip : res
8
+ end
9
+
10
+ def self.git_global_config_value(name)
11
+ res = `git config --global #{name}`
12
+ res.strip
13
+ end
14
+ =end
15
+
16
+ end
17
+ end
@@ -0,0 +1,8 @@
1
+ module GitPusher
2
+ module Repo
3
+ class Base
4
+ def initialize(config)
5
+ end
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,6 @@
1
+ module GitPusher
2
+ module Repo
3
+ class BitBucket < Base
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,14 @@
1
+ module GitPusher
2
+ module Repo
3
+ class Factory
4
+ def self.create(config)
5
+ case config[:type]
6
+ when /github/i then GitPusher::Repo::GitHub.new(config)
7
+ when /bitbucket/i then GitPusher::Repo::BitBucket.new(config)
8
+ else
9
+ raise "unknown issue tracker type : #{its_type}"
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,36 @@
1
+ require 'octokit'
2
+ require 'pit'
3
+
4
+ module GitPusher
5
+ module Repo
6
+ class GitHub < Base
7
+ attr :user, :password, :organization
8
+
9
+ def initialize(config)
10
+ super(config)
11
+ @user = Pit.get(
12
+ 'github', :require => { 'user' => 'Your user name of GitHub' }
13
+ )['user']
14
+ @password = Pit.get(
15
+ 'github', :require => { 'password' => 'Your user password of GitHub' }
16
+ )['password']
17
+ @organization = config[:organization]
18
+ end
19
+
20
+ def repos
21
+ repos = []
22
+ octokit.repos(self.organization||self.user).each do |repo|
23
+ p repo
24
+ break
25
+ end
26
+ repos
27
+ end
28
+
29
+ private
30
+ def octokit
31
+ Octokit::Client.new(:login => self.user, :password => self.password)
32
+ end
33
+
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,8 @@
1
+ module GitPusher
2
+ class Repo
3
+ attr :url
4
+ def initialize(url)
5
+ @url = url
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,64 @@
1
+ require 'grit'
2
+
3
+ module GitPusher
4
+ class Runner
5
+ def self.run
6
+ context = GitPusher::Context.instance
7
+
8
+ src = GitPusher::Service::Factory.create(context.config[:src])
9
+ dest = GitPusher::Service::Factory.create(context.config[:dest])
10
+
11
+ base_dir = context.config[:base_dir]
12
+ src.repos.each do |src_repo|
13
+ puts "Cheking #{src_repo.url} ..."
14
+ repo_name = File.basename(src_repo.url).gsub(/.git$/, '')
15
+ repo_path = File.join(base_dir, repo_name)
16
+ unless File.exist?(repo_path)
17
+ Dir.chdir(base_dir) do
18
+ p src_repo.url
19
+ `git clone #{src_repo.url}`
20
+ end
21
+ end
22
+
23
+ local_repo = Grit::Repo.new(repo_path)
24
+
25
+ # local repo の git remote で mirror があるかどうかチェック
26
+ has_remote_mirror = false
27
+ local_repo.remote_list.each do |remote|
28
+ has_remote_mirror = true if remote === 'mirror'
29
+ end
30
+
31
+ unless has_remote_mirror
32
+ mirror_repo = dest.repo(repo_name) || dest.create_repo(repo_name)
33
+ local_repo.git.remote({}, 'add', 'mirror', mirror_repo.url)
34
+ end
35
+
36
+ local_repo.remotes.each do |remote|
37
+ next if remote.name == 'origin/HEAD'
38
+ next if remote.name =~ %r!mirror/.+!
39
+ branch = remote.name.gsub(%r!^origin/!, '')
40
+
41
+ matched = false
42
+ local_repo.branches.each do |x|
43
+ matched = true if x.name === branch
44
+ end
45
+
46
+ unless matched
47
+ local_repo.git.branch({}, branch, remote.name)
48
+ end
49
+
50
+ # pull する
51
+ puts "Pulling #{branch} ..."
52
+ local_repo.git.pull({}, 'origin', branch)
53
+
54
+ # git push mirror #{branch} する
55
+ puts "Pushing #{branch} ..."
56
+ local_repo.git.push({ :timeout => 300 }, 'mirror', branch)
57
+ end
58
+
59
+ end
60
+
61
+
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,8 @@
1
+ module GitPusher
2
+ module Service
3
+ class Base
4
+ def initialize(config)
5
+ end
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,63 @@
1
+ require 'open-uri'
2
+ require 'net/http'
3
+
4
+ module GitPusher
5
+ module Service
6
+ class BitBucket < Base
7
+
8
+ def initialize(config)
9
+ super(config)
10
+ @user = Pit.get(
11
+ 'bitbucket', :require => { 'user' => 'Your user name of BitBucket' }
12
+ )['user']
13
+ @password = Pit.get(
14
+ 'bitbucket', :require => { 'password' => 'Your user password of BitBucket' }
15
+ )['password']
16
+ end
17
+
18
+ def repo(name)
19
+ url = sprintf 'https://api.bitbucket.org/1.0/repositories/%s/%s', @user, name
20
+ opt = {"Authorization" => "Basic " + Base64.encode64("#{@user}:#{@password}")}
21
+ opt[:ssl_verify_mode] = OpenSSL::SSL::VERIFY_NONE
22
+ begin
23
+ json = open(url, opt) {|io|
24
+ JSON.parse(io.read)
25
+ }
26
+ rescue OpenURI::HTTPError => e
27
+ if e.message === '404 NOT FOUND'
28
+ return nil
29
+ else
30
+ raise e
31
+ end
32
+ end
33
+
34
+ GitPusher::Repo.new(ssh_url(name))
35
+ end
36
+
37
+ def create_repo(name)
38
+ puts "Creating repository #{name} on the mirror ..."
39
+ https = Net::HTTP.new('api.bitbucket.org', 443)
40
+ https.use_ssl = true
41
+ https.verify_mode = OpenSSL::SSL::VERIFY_NONE
42
+ https.start{|http|
43
+ request = Net::HTTP::Post.new('/1.0/repositories/')
44
+ request.basic_auth @user, @password
45
+ request.set_form_data({
46
+ :name => name,
47
+ :scm => 'git',
48
+ :is_private => 'True',
49
+ })
50
+ response = http.request(request)
51
+ }
52
+
53
+ GitPusher::Repo.new(ssh_url(name))
54
+ end
55
+
56
+ private
57
+ def ssh_url(name)
58
+ sprintf "git@bitbucket.org:%s/%s.git", @user, name
59
+ end
60
+
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,14 @@
1
+ module GitPusher
2
+ module Service
3
+ class Factory
4
+ def self.create(config)
5
+ case config[:type]
6
+ when /github/i then GitPusher::Service::GitHub.new(config)
7
+ when /bitbucket/i then GitPusher::Service::BitBucket.new(config)
8
+ else
9
+ raise "unknown issue tracker type : #{its_type}"
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,36 @@
1
+ require 'octokit'
2
+ require 'pit'
3
+
4
+ module GitPusher
5
+ module Service
6
+ class GitHub < Base
7
+ attr :user, :password, :organization
8
+
9
+ def initialize(config)
10
+ super(config)
11
+ @user = Pit.get(
12
+ 'github', :require => { 'user' => 'Your user name of GitHub' }
13
+ )['user']
14
+ @password = Pit.get(
15
+ 'github', :require => { 'password' => 'Your user password of GitHub' }
16
+ )['password']
17
+ @organization = config[:organization]
18
+ end
19
+
20
+ def repos
21
+ repos = []
22
+ github_repos = self.organization ? octokit.org_repos(self.organization) : octokit.repos(self.user)
23
+ github_repos.each do |repo|
24
+ repos << GitPusher::Repo.new(repo[:ssh_url])
25
+ end
26
+ repos
27
+ end
28
+
29
+ private
30
+ def octokit
31
+ Octokit::Client.new(:login => self.user, :password => self.password)
32
+ end
33
+
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,3 @@
1
+ module GitPusher
2
+ VERSION = "0.0.1"
3
+ end
data/lib/gitpusher.rb ADDED
@@ -0,0 +1,10 @@
1
+ require 'bundler/setup'
2
+ require 'gitpusher/context'
3
+ require 'gitpusher/config'
4
+ require 'gitpusher/runner'
5
+ require 'gitpusher/helper'
6
+ require 'gitpusher/service/base'
7
+ require 'gitpusher/service/factory'
8
+ require 'gitpusher/service/github'
9
+ require 'gitpusher/service/bitbucket'
10
+ require 'gitpusher/repo'
metadata ADDED
@@ -0,0 +1,133 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gitpusher
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Gosuke Miyashita
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-04-20 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: grit
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
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: octokit
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
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: pit
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: grit
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
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: '0'
78
+ description:
79
+ email:
80
+ - gosukenator@gmail.com
81
+ executables:
82
+ - gitpusher
83
+ extensions: []
84
+ extra_rdoc_files: []
85
+ files:
86
+ - .gitignore
87
+ - Gemfile
88
+ - README.md
89
+ - Rakefile
90
+ - bin/gitpusher
91
+ - config/git_to_bitbucket.yml
92
+ - gitpusher.gemspec
93
+ - lib/gitpusher.rb
94
+ - lib/gitpusher/config.rb
95
+ - lib/gitpusher/context.rb
96
+ - lib/gitpusher/helper.rb
97
+ - lib/gitpusher/repo.rb
98
+ - lib/gitpusher/repo/base.rb
99
+ - lib/gitpusher/repo/bitbucket.rb
100
+ - lib/gitpusher/repo/factory.rb
101
+ - lib/gitpusher/repo/github.rb
102
+ - lib/gitpusher/runner.rb
103
+ - lib/gitpusher/service/base.rb
104
+ - lib/gitpusher/service/bitbucket.rb
105
+ - lib/gitpusher/service/factory.rb
106
+ - lib/gitpusher/service/github.rb
107
+ - lib/gitpusher/version.rb
108
+ homepage: https://github.com/mizzy/gitpusher
109
+ licenses: []
110
+ post_install_message:
111
+ rdoc_options: []
112
+ require_paths:
113
+ - lib
114
+ required_ruby_version: !ruby/object:Gem::Requirement
115
+ none: false
116
+ requirements:
117
+ - - ! '>='
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ required_rubygems_version: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ requirements: []
127
+ rubyforge_project:
128
+ rubygems_version: 1.8.23
129
+ signing_key:
130
+ specification_version: 3
131
+ summary: A command line tool for replicating git repositories from one service to
132
+ another.
133
+ test_files: []