git_duplicator 0.0.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +94 -16
- data/lib/git_duplicator.rb +9 -3
- data/lib/git_duplicator/{duplicator.rb → duplicator/duplicator.rb} +16 -13
- data/lib/git_duplicator/duplicator/mirror_duplicator.rb +18 -0
- data/lib/git_duplicator/duplicator/update_duplicator.rb +17 -0
- data/lib/git_duplicator/duplicators.rb +5 -0
- data/lib/git_duplicator/errors.rb +4 -0
- data/lib/git_duplicator/repositories.rb +1 -0
- data/lib/git_duplicator/repository/repository.rb +86 -10
- data/lib/git_duplicator/repository/service_repository.rb +3 -2
- data/lib/git_duplicator/services/bitbucket.rb +18 -17
- data/lib/git_duplicator/services/github.rb +15 -16
- data/lib/git_duplicator/version.rb +2 -2
- data/spec/git_duplicator/duplicator/duplicator_spec.rb +112 -0
- data/spec/git_duplicator/duplicator/mirror_duplicator_spec.rb +35 -0
- data/spec/git_duplicator/duplicator/update_duplicator_spec.rb +39 -0
- data/spec/git_duplicator/git_duplicator_acceptance_spec.rb +188 -0
- data/spec/git_duplicator/git_duplicator_spec.rb +22 -92
- data/spec/git_duplicator/helpers/authorization_header_spec.rb +29 -0
- data/spec/git_duplicator/repository/repository_spec.rb +81 -33
- data/spec/git_duplicator/repository/service_repository_spec.rb +17 -15
- data/spec/git_duplicator/services/bitbucket_spec.rb +48 -44
- data/spec/git_duplicator/services/github_spec.rb +50 -44
- metadata +11 -4
- data/spec/git_duplicator/duplicator_spec.rb +0 -82
@@ -0,0 +1,29 @@
|
|
1
|
+
require_relative '../../helper'
|
2
|
+
|
3
|
+
module GitDuplicator
|
4
|
+
module Helpers
|
5
|
+
describe AuthorizationHeader do
|
6
|
+
let(:credentials) { { username: 'user', password: 'password' } }
|
7
|
+
let(:request) { { method: :post, url: 'onetwo' } }
|
8
|
+
let(:header) { described_class.new(credentials, request) }
|
9
|
+
|
10
|
+
describe '#basic_authenticaion_header' do
|
11
|
+
it 'should have the right value' do
|
12
|
+
result = header.send :basic_authenticaion_header
|
13
|
+
encode64 = Base64.encode64("#{credentials[:username]}" \
|
14
|
+
":#{credentials[:password]}")
|
15
|
+
expect(result).to eq("Basic #{encode64}")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '#basic_authenticaion_header' do
|
20
|
+
it 'should have the right value' do
|
21
|
+
result = header.send :base64_username_password
|
22
|
+
encode64 = Base64.encode64("#{credentials[:username]}" \
|
23
|
+
":#{credentials[:password]}")
|
24
|
+
expect(result).to eq(encode64)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -1,47 +1,95 @@
|
|
1
1
|
require_relative '../../helper'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
3
|
+
module GitDuplicator
|
4
|
+
describe Repository do
|
5
|
+
let(:path) { 'somepath' }
|
6
|
+
let(:name) { 'something' }
|
7
|
+
let(:url) { 'someurl' }
|
8
|
+
let(:to_url) { 'someurl' }
|
9
|
+
let(:repo) { described_class.new(name, url) }
|
10
|
+
|
11
|
+
# describe '#working_directory=' do
|
12
|
+
# it 'assignes the attribute' do
|
13
|
+
# val = 'somepath'
|
14
|
+
# repo.working_directory = val
|
15
|
+
# expect(repo.working_directory).to eq(val)
|
16
|
+
# end
|
17
|
+
|
18
|
+
# it 'assignes the repo attribute' do
|
19
|
+
# val = 'somepath'
|
20
|
+
# repo.working_directory = val
|
21
|
+
# expect(repo.working_directory).to eq(val)
|
22
|
+
# end
|
16
23
|
|
17
|
-
|
18
|
-
|
24
|
+
# end
|
25
|
+
|
26
|
+
describe '#bare_clone' do
|
27
|
+
it 'clones a repo' do
|
28
|
+
expect(Git).to receive(:clone).with(url, name, path: path, bare: true)
|
29
|
+
repo.bare_clone(path)
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'raises an exception in case of failure' do
|
33
|
+
expect { repo.bare_clone('') }
|
34
|
+
.to raise_error(GitDuplicator::RepositoryCloningError)
|
35
|
+
end
|
19
36
|
end
|
20
|
-
end
|
21
37
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
38
|
+
describe '#mirror_clone' do
|
39
|
+
it 'clones a repo' do
|
40
|
+
allow(Git).to receive(:bare)
|
41
|
+
wd = File.join(path, repo.name)
|
42
|
+
expect(repo).to receive(:command)
|
43
|
+
.with('clone', '--mirror', repo.url, wd)
|
44
|
+
repo.mirror_clone(path)
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'raises an exception in case of failure' do
|
48
|
+
expect { repo.mirror_clone('') }
|
49
|
+
.to raise_error(GitDuplicator::RepositoryCloningError)
|
50
|
+
end
|
27
51
|
end
|
28
52
|
|
29
|
-
|
30
|
-
|
31
|
-
|
53
|
+
describe '#mirror' do
|
54
|
+
it 'mirrors a repo' do
|
55
|
+
repo.send(:repo=, Git::Base.new)
|
56
|
+
expect(repo.send(:repo)).to receive(:push).with(to_url, '--mirror')
|
57
|
+
repo.mirror(to_url)
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'raises an exception in case of failure' do
|
61
|
+
expect { repo.mirror('') }
|
62
|
+
.to raise_error(GitDuplicator::RepositoryMirorringError)
|
63
|
+
end
|
32
64
|
end
|
33
|
-
end
|
34
65
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
66
|
+
describe '#update_mirrored' do
|
67
|
+
|
68
|
+
it 'fetchs and pushes data' do
|
69
|
+
repo.send(:repo=, Git::Base.new)
|
70
|
+
expect(repo).to receive(:command).with('fetch', '-p', 'origin')
|
71
|
+
expect(repo).to receive(:command).with('push', '--mirror')
|
72
|
+
repo.update_mirrored
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'raises an exception in case of failure' do
|
76
|
+
expect { repo.update_mirrored }
|
77
|
+
.to raise_error(GitDuplicator::RepositoryMirorredUpdatingError)
|
78
|
+
end
|
40
79
|
end
|
41
80
|
|
42
|
-
|
43
|
-
|
44
|
-
|
81
|
+
describe '#set_mirrored_remote' do
|
82
|
+
it 'sets mirrored as remote' do
|
83
|
+
repo.send(:repo=, Git::Base.new)
|
84
|
+
expect(repo).to receive(:command)
|
85
|
+
.with('remote', 'set-url', '--push', 'origin', to_url)
|
86
|
+
repo.set_mirrored_remote(to_url)
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'raises an exception in case of failure' do
|
90
|
+
expect { repo.set_mirrored_remote('') }
|
91
|
+
.to raise_error(GitDuplicator::RepositorySettingRemoteError)
|
92
|
+
end
|
45
93
|
end
|
46
94
|
end
|
47
95
|
end
|
@@ -1,25 +1,27 @@
|
|
1
1
|
require_relative '../../helper'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
module GitDuplicator
|
4
|
+
describe ServiceRepository do
|
5
|
+
let(:name) { 'something' }
|
6
|
+
let(:owner) { 'someone' }
|
7
|
+
let(:repo) { described_class.new(name, owner) }
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
9
|
+
describe '#delete' do
|
10
|
+
it 'raises an exception in case of not defined' do
|
11
|
+
expect { repo.delete }.to raise_error(NotImplementedError)
|
12
|
+
end
|
11
13
|
end
|
12
|
-
end
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
15
|
+
describe '#create' do
|
16
|
+
it 'raises an exception in case of not defined' do
|
17
|
+
expect { repo.create }.to raise_error(NotImplementedError)
|
18
|
+
end
|
17
19
|
end
|
18
|
-
end
|
19
20
|
|
20
|
-
|
21
|
-
|
22
|
-
|
21
|
+
describe '#url' do
|
22
|
+
it 'raises an exception in case of not defined' do
|
23
|
+
expect { repo.url }.to raise_error(NotImplementedError)
|
24
|
+
end
|
23
25
|
end
|
24
26
|
end
|
25
27
|
end
|
@@ -1,51 +1,55 @@
|
|
1
1
|
require_relative '../../helper'
|
2
|
+
module GitDuplicator
|
3
|
+
module Services
|
4
|
+
describe BitbucketRepository do
|
5
|
+
let(:credentials) do
|
6
|
+
{ consumer_key: ENV['BITBUCKET_CONSUMER_KEY'],
|
7
|
+
consumer_secret: ENV['BITBUCKET_CONSUMER_SECRET'],
|
8
|
+
token: ENV['BITBUCKET_TOKEN'],
|
9
|
+
token_secret: ENV['BITBUCKET_TOKEN_SECRET'] }
|
10
|
+
end
|
11
|
+
let(:name) { ENV['TESTING_REPO'] }
|
12
|
+
let(:owner) { ENV['BITBUCKET_USER'] }
|
13
|
+
let(:remote_options) do
|
14
|
+
{ scm: 'git', is_private: true, fork_policy: 'no_public_forks' }
|
15
|
+
end
|
16
|
+
let(:options) { { credentials: credentials, remote_options: remote_options } }
|
17
|
+
let(:repo) { described_class.new(name, owner, options) }
|
2
18
|
|
3
|
-
describe
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
19
|
+
describe '#delete' do
|
20
|
+
it 'deletes the repo in case it exists' do
|
21
|
+
stub_request(:delete, described_class::BASE_URI +
|
22
|
+
"/repositories/#{owner}/#{name}")
|
23
|
+
.to_return(body: '', status: 204)
|
24
|
+
expect { repo.delete }.not_to raise_error
|
25
|
+
end
|
26
|
+
it 'raises an exception in case of unknow problem' do
|
27
|
+
stub_request(:delete, described_class::BASE_URI +
|
28
|
+
"/repositories/#{owner}/#{name}")
|
29
|
+
.to_return(body: 'something wrong', status: 401)
|
30
|
+
expect { repo.delete }
|
31
|
+
.to raise_error(GitDuplicator::RepositoryDeletionError, /something wrong/)
|
32
|
+
end
|
33
|
+
end
|
16
34
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
stub_request(:delete, described_class::BASE_URI +
|
26
|
-
"/repositories/#{owner}/#{name}")
|
27
|
-
.to_return(body: 'something wrong', status: 401)
|
28
|
-
expect { repo.delete }
|
29
|
-
.to raise_error(GitDuplicator::RepositoryDeletionError, /something wrong/)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
describe '#create' do
|
34
|
-
it 'creates the repository in case of not defined' do
|
35
|
-
stub_request(:post, described_class::BASE_URI +
|
36
|
-
"/repositories/#{owner}/#{name}")
|
37
|
-
.with(body: options.to_json)
|
38
|
-
.to_return(body: '', status: 200)
|
39
|
-
expect { repo.create }.not_to raise_error
|
40
|
-
end
|
35
|
+
describe '#create' do
|
36
|
+
it 'creates the repository in case of not defined' do
|
37
|
+
stub_request(:post, described_class::BASE_URI +
|
38
|
+
"/repositories/#{owner}/#{name}")
|
39
|
+
.with(body: remote_options.to_json)
|
40
|
+
.to_return(body: '', status: 200)
|
41
|
+
expect { repo.create }.not_to raise_error
|
42
|
+
end
|
41
43
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
44
|
+
it 'raises an exception in case of errors' do
|
45
|
+
stub_request(:post, described_class::BASE_URI +
|
46
|
+
"/repositories/#{owner}/#{name}")
|
47
|
+
.with(body: remote_options.to_json)
|
48
|
+
.to_return(body: 'something wrong', status: 401)
|
49
|
+
expect { repo.create }
|
50
|
+
.to raise_error(GitDuplicator::RepositoryCreationError, /something wrong/)
|
51
|
+
end
|
52
|
+
end
|
49
53
|
end
|
50
54
|
end
|
51
55
|
end
|
@@ -1,52 +1,58 @@
|
|
1
1
|
require_relative '../../helper'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
3
|
+
module GitDuplicator
|
4
|
+
module Services
|
5
|
+
describe GitDuplicator::Services::GithubRepository do
|
6
|
+
let(:credentials) do
|
7
|
+
{ oauth2_token: ENV['GITHUB_ACCESS_TOKEN'] }
|
8
|
+
end
|
9
|
+
let(:name) { ENV['TESTING_REPO'] }
|
10
|
+
let(:owner) { ENV['GITHUB_USER'] }
|
11
|
+
let(:remote_options) do
|
12
|
+
{ has_issues: false, has_wiki: false }
|
13
|
+
end
|
14
|
+
let(:options) { { credentials: credentials, remote_options: remote_options } }
|
15
|
+
let(:repo) { described_class.new(name, owner, options) }
|
13
16
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
17
|
+
describe '#delete' do
|
18
|
+
it 'deletes the repo in case it exists' do
|
19
|
+
stub_request(:delete, described_class::BASE_URI +
|
20
|
+
"/repos/#{owner}/#{name}")
|
21
|
+
.with(
|
22
|
+
headers: { 'Authorization' => "token #{credentials[:oauth2_token]}" }
|
23
|
+
)
|
24
|
+
.to_return(body: '', status: 204)
|
25
|
+
expect { repo.delete }.not_to raise_error
|
26
|
+
end
|
27
|
+
it 'raises an exception in case of unknow problem' do
|
28
|
+
stub_request(:delete, described_class::BASE_URI +
|
29
|
+
"/repos/#{owner}/#{name}")
|
30
|
+
.to_return(body: 'something wrong', status: 401)
|
31
|
+
expect { repo.delete }
|
32
|
+
.to raise_error(GitDuplicator::RepositoryDeletionError)
|
33
|
+
end
|
34
|
+
end
|
32
35
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
36
|
+
describe '#create' do
|
37
|
+
it 'creates the repository in case of not defined' do
|
38
|
+
stub_request(:post, described_class::BASE_URI + '/user/repos')
|
39
|
+
.with(
|
40
|
+
body: remote_options.merge(name: name).to_json,
|
41
|
+
headers: { 'Authorization' =>
|
42
|
+
"token #{credentials[:oauth2_token]}" }
|
43
|
+
)
|
44
|
+
.to_return(body: '', status: 201)
|
45
|
+
expect { repo.create }.not_to raise_error
|
46
|
+
end
|
43
47
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
48
|
+
it 'raises an exception in case of errors' do
|
49
|
+
stub_request(:post, described_class::BASE_URI + '/user/repos')
|
50
|
+
.with(body: remote_options.merge(name: name).to_json)
|
51
|
+
.to_return(body: 'something wrong', status: 401)
|
52
|
+
expect { repo.create }
|
53
|
+
.to raise_error(GitDuplicator::RepositoryCreationError)
|
54
|
+
end
|
55
|
+
end
|
50
56
|
end
|
51
57
|
end
|
52
58
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: git_duplicator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Khaled alHabache
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-09-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: http
|
@@ -71,7 +71,10 @@ files:
|
|
71
71
|
- Rakefile
|
72
72
|
- git_duplicator.gemspec
|
73
73
|
- lib/git_duplicator.rb
|
74
|
-
- lib/git_duplicator/duplicator.rb
|
74
|
+
- lib/git_duplicator/duplicator/duplicator.rb
|
75
|
+
- lib/git_duplicator/duplicator/mirror_duplicator.rb
|
76
|
+
- lib/git_duplicator/duplicator/update_duplicator.rb
|
77
|
+
- lib/git_duplicator/duplicators.rb
|
75
78
|
- lib/git_duplicator/errors.rb
|
76
79
|
- lib/git_duplicator/helpers/authorization_header.rb
|
77
80
|
- lib/git_duplicator/null_logger.rb
|
@@ -82,8 +85,12 @@ files:
|
|
82
85
|
- lib/git_duplicator/services/bitbucket.rb
|
83
86
|
- lib/git_duplicator/services/github.rb
|
84
87
|
- lib/git_duplicator/version.rb
|
85
|
-
- spec/git_duplicator/duplicator_spec.rb
|
88
|
+
- spec/git_duplicator/duplicator/duplicator_spec.rb
|
89
|
+
- spec/git_duplicator/duplicator/mirror_duplicator_spec.rb
|
90
|
+
- spec/git_duplicator/duplicator/update_duplicator_spec.rb
|
91
|
+
- spec/git_duplicator/git_duplicator_acceptance_spec.rb
|
86
92
|
- spec/git_duplicator/git_duplicator_spec.rb
|
93
|
+
- spec/git_duplicator/helpers/authorization_header_spec.rb
|
87
94
|
- spec/git_duplicator/repository/repository_spec.rb
|
88
95
|
- spec/git_duplicator/repository/service_repository_spec.rb
|
89
96
|
- spec/git_duplicator/services/bitbucket_spec.rb
|
@@ -1,82 +0,0 @@
|
|
1
|
-
require_relative '../helper'
|
2
|
-
|
3
|
-
describe GitDuplicator::Duplicator do
|
4
|
-
let(:path) { '/somepath' }
|
5
|
-
let(:from) do
|
6
|
-
double(name: 'somename', bare_clone: nil, mirror: nil, url: 'somewhere1')
|
7
|
-
end
|
8
|
-
let(:to) { double(delete: nil, create: nil, url: 'somewhere2') }
|
9
|
-
let(:duplicator) { GitDuplicator::Duplicator.new(from, to, options) }
|
10
|
-
|
11
|
-
describe '#perform' do
|
12
|
-
context 'force_create_destination is set' do
|
13
|
-
let(:options) { { clone_path: path, force_create_destination: true } }
|
14
|
-
|
15
|
-
it 'deletes existing destination repo' do
|
16
|
-
expect(to).to receive(:delete)
|
17
|
-
duplicator.perform
|
18
|
-
end
|
19
|
-
|
20
|
-
it 'creates the destination repo' do
|
21
|
-
expect(to).to receive(:create)
|
22
|
-
duplicator.perform
|
23
|
-
end
|
24
|
-
|
25
|
-
it 'bare clones the source repo' do
|
26
|
-
expect(from).to receive(:bare_clone).with(path)
|
27
|
-
duplicator.perform
|
28
|
-
end
|
29
|
-
|
30
|
-
it 'mirrors from bare clone to destination' do
|
31
|
-
expect(from).to receive(:mirror).with(to.url)
|
32
|
-
duplicator.perform
|
33
|
-
end
|
34
|
-
|
35
|
-
it 'cleans up' do
|
36
|
-
expect(FileUtils).to receive(:rm_rf)
|
37
|
-
.with("#{duplicator.clone_path}/#{from.name}")
|
38
|
-
duplicator.perform
|
39
|
-
end
|
40
|
-
|
41
|
-
it 'logs 5 times' do
|
42
|
-
expect(duplicator.logger).to receive(:info).exactly(5).times
|
43
|
-
duplicator.perform
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
context 'force_create_destination is false' do
|
48
|
-
let(:options) { { clone_path: path } }
|
49
|
-
|
50
|
-
it 'deletes existing destination repo' do
|
51
|
-
expect(to).not_to receive(:delete)
|
52
|
-
duplicator.perform
|
53
|
-
end
|
54
|
-
|
55
|
-
it 'creates the destination repo' do
|
56
|
-
expect(to).not_to receive(:create)
|
57
|
-
duplicator.perform
|
58
|
-
end
|
59
|
-
|
60
|
-
it 'bare clones the source repo' do
|
61
|
-
expect(from).to receive(:bare_clone).with(path)
|
62
|
-
duplicator.perform
|
63
|
-
end
|
64
|
-
|
65
|
-
it 'mirrors from bare clone to destination' do
|
66
|
-
expect(from).to receive(:mirror).with(to.url)
|
67
|
-
duplicator.perform
|
68
|
-
end
|
69
|
-
|
70
|
-
it 'cleans up' do
|
71
|
-
expect(FileUtils).to receive(:rm_rf)
|
72
|
-
.with("#{duplicator.clone_path}/#{from.name}")
|
73
|
-
duplicator.perform
|
74
|
-
end
|
75
|
-
|
76
|
-
it 'logs 3 times' do
|
77
|
-
expect(duplicator.logger).to receive(:info).exactly(3).times
|
78
|
-
duplicator.perform
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|