git_duplicator 0.0.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|