git_multicast 0.1.0 → 0.2.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.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +17 -1
  3. data/README.md +1 -1
  4. data/git_multicast.gemspec +1 -0
  5. data/lib/git_multicast.rb +3 -8
  6. data/lib/git_multicast/adapter.rb +2 -0
  7. data/lib/git_multicast/{adapters → adapter}/bitbucket.rb +1 -1
  8. data/lib/git_multicast/{adapters → adapter}/github.rb +1 -1
  9. data/lib/git_multicast/cli.rb +38 -6
  10. data/lib/git_multicast/formatter.rb +6 -0
  11. data/lib/git_multicast/formatter/full.rb +18 -0
  12. data/lib/git_multicast/formatter/quiet.rb +13 -0
  13. data/lib/git_multicast/formatter/standard.rb +29 -0
  14. data/lib/git_multicast/formatter/status.rb +17 -0
  15. data/lib/git_multicast/multicaster.rb +31 -0
  16. data/lib/git_multicast/multicaster/clone.rb +35 -0
  17. data/lib/git_multicast/multicaster/pull.rb +30 -0
  18. data/lib/git_multicast/multicaster/status.rb +30 -0
  19. data/lib/git_multicast/repository_fetcher.rb +5 -2
  20. data/lib/git_multicast/task.rb +5 -3
  21. data/lib/git_multicast/task/result.rb +13 -0
  22. data/lib/git_multicast/task/runner.rb +38 -0
  23. data/lib/git_multicast/version.rb +1 -1
  24. data/spec/git_multicast/{adapters → adapter}/bitbucket_spec.rb +7 -3
  25. data/spec/git_multicast/cli_spec.rb +3 -3
  26. data/spec/git_multicast/formatter/full_spec.rb +32 -0
  27. data/spec/git_multicast/formatter/quiet_spec.rb +30 -0
  28. data/spec/git_multicast/formatter/standard_spec.rb +31 -0
  29. data/spec/git_multicast/formatter/status_spec.rb +32 -0
  30. data/spec/git_multicast/multicaster/clone_spec.rb +97 -0
  31. data/spec/git_multicast/multicaster/pull_spec.rb +41 -0
  32. data/spec/git_multicast/multicaster/status_spec.rb +41 -0
  33. data/spec/git_multicast/repository_fetcher_spec.rb +3 -3
  34. data/spec/git_multicast/task/runner_spec.rb +44 -0
  35. data/spec/git_multicast/task_spec.rb +8 -5
  36. metadata +39 -18
  37. data/lib/git_multicast/.rubocop.yml +0 -11
  38. data/lib/git_multicast/adapters.rb +0 -7
  39. data/lib/git_multicast/cloner.rb +0 -36
  40. data/lib/git_multicast/output_formatter.rb +0 -30
  41. data/lib/git_multicast/puller.rb +0 -28
  42. data/lib/git_multicast/statuser.rb +0 -28
  43. data/lib/git_multicast/task_result.rb +0 -7
  44. data/lib/git_multicast/task_runner.rb +0 -40
  45. data/spec/git_multicast/cloner_spec.rb +0 -94
  46. data/spec/git_multicast/output_formatter_spec.rb +0 -30
  47. data/spec/git_multicast/puller_spec.rb +0 -39
  48. data/spec/git_multicast/statuser_spec.rb +0 -39
  49. data/spec/git_multicast/task_runner_spec.rb +0 -53
@@ -0,0 +1,44 @@
1
+ module GitMulticast
2
+ class Task
3
+ describe Runner do
4
+ subject(:runner) { described_class.new(tasks) }
5
+
6
+ let(:tasks) { [hey_task, ho_task] }
7
+
8
+ # Since tasks quack like lambdas, I will be using them here.
9
+ let(:hey_task) { ->() { first_result } }
10
+ let(:ho_task) { ->() { second_result } }
11
+
12
+ let!(:first_result) { Task::Result.new(:one, 'Hey!', 1) }
13
+ let!(:second_result) { Task::Result.new(:two, 'Ho!', 1) }
14
+
15
+ let(:formatter) { Formatter::Standard.new }
16
+
17
+ before do
18
+ allow(Formatter::Standard).to receive(:new)
19
+ .and_return(formatter)
20
+ end
21
+
22
+ describe '#run!' do
23
+ subject(:run!) { runner.run! }
24
+
25
+ it 'creates a thread for each task'do
26
+ expect(Thread).to receive(:new)
27
+ .exactly(tasks.size).times
28
+ .and_call_original
29
+
30
+ run!
31
+ end
32
+
33
+ it 'calls each task' do
34
+ expect(hey_task).to receive(:call)
35
+ .and_call_original
36
+ expect(ho_task).to receive(:call)
37
+ .and_call_original
38
+
39
+ run!
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -1,10 +1,11 @@
1
1
  describe GitMulticast::Task do
2
2
  subject(:task) { described_class.new(description, command) }
3
3
 
4
- let(:description) { 'some_repo' }
5
- let(:command) { 'git clone some_repo' }
4
+ let(:description) { 'some echo' }
5
+ let(:command) { 'echo hi' }
6
6
 
7
7
  let(:pid) { 42 }
8
+ let(:status) { instance_double(Process::Status, exitstatus: 0) }
8
9
 
9
10
  let(:pipe) { IO.pipe }
10
11
  let(:r) { pipe.first }
@@ -13,6 +14,8 @@ describe GitMulticast::Task do
13
14
  before do
14
15
  allow(task).to receive(:spawn)
15
16
  .and_return(pid)
17
+ allow(task).to receive(:wait2)
18
+ .and_return([0, status])
16
19
  allow(task).to receive(:wait)
17
20
  .and_return(['', 0])
18
21
 
@@ -40,14 +43,14 @@ describe GitMulticast::Task do
40
43
  end
41
44
 
42
45
  it 'waits for its process to finish' do
43
- expect(task).to receive(:wait)
46
+ expect(task).to receive(:wait2)
44
47
  .with(pid)
45
48
 
46
49
  run!
47
50
  end
48
51
 
49
- it 'wraps its result in a TaskResult object' do
50
- expect(GitMulticast::TaskResult).to receive(:new)
52
+ it 'wraps its result in a Task::Result object' do
53
+ expect(GitMulticast::Task::Result).to receive(:new)
51
54
  .with(description, 'I be output!', 0)
52
55
 
53
56
  run!
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: git_multicast
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Renan Ranelli
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-08 00:00:00.000000000 Z
11
+ date: 2014-12-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: recursive-open-struct
@@ -108,6 +108,20 @@ dependencies:
108
108
  - - ">="
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubocop
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
111
125
  - !ruby/object:Gem::Dependency
112
126
  name: webmock
113
127
  requirement: !ruby/object:Gem::Requirement
@@ -185,21 +199,25 @@ files:
185
199
  - bin/git_multicast
186
200
  - git_multicast.gemspec
187
201
  - lib/git_multicast.rb
188
- - lib/git_multicast/.rubocop.yml
189
- - lib/git_multicast/adapters.rb
190
- - lib/git_multicast/adapters/bitbucket.rb
191
- - lib/git_multicast/adapters/github.rb
202
+ - lib/git_multicast/adapter.rb
203
+ - lib/git_multicast/adapter/bitbucket.rb
204
+ - lib/git_multicast/adapter/github.rb
192
205
  - lib/git_multicast/cli.rb
193
- - lib/git_multicast/cloner.rb
194
- - lib/git_multicast/output_formatter.rb
195
- - lib/git_multicast/puller.rb
206
+ - lib/git_multicast/formatter.rb
207
+ - lib/git_multicast/formatter/full.rb
208
+ - lib/git_multicast/formatter/quiet.rb
209
+ - lib/git_multicast/formatter/standard.rb
210
+ - lib/git_multicast/formatter/status.rb
211
+ - lib/git_multicast/multicaster.rb
212
+ - lib/git_multicast/multicaster/clone.rb
213
+ - lib/git_multicast/multicaster/pull.rb
214
+ - lib/git_multicast/multicaster/status.rb
196
215
  - lib/git_multicast/repository_fetcher.rb
197
216
  - lib/git_multicast/repository_fetcher/bitbucket.rb
198
217
  - lib/git_multicast/repository_fetcher/github.rb
199
- - lib/git_multicast/statuser.rb
200
218
  - lib/git_multicast/task.rb
201
- - lib/git_multicast/task_result.rb
202
- - lib/git_multicast/task_runner.rb
219
+ - lib/git_multicast/task/result.rb
220
+ - lib/git_multicast/task/runner.rb
203
221
  - lib/git_multicast/version.rb
204
222
  - spec/fixtures/vcr_cassettes/bitbucket_all_user_repos.yml
205
223
  - spec/fixtures/vcr_cassettes/bitbucket_repo.yml
@@ -208,16 +226,19 @@ files:
208
226
  - spec/fixtures/vcr_cassettes/github_repo.yml
209
227
  - spec/fixtures/vcr_cassettes/github_repo_parent.yml
210
228
  - spec/fixtures/vcr_cassettes/repos_from_all_services.yml
211
- - spec/git_multicast/adapters/bitbucket_spec.rb
229
+ - spec/git_multicast/adapter/bitbucket_spec.rb
212
230
  - spec/git_multicast/cli_spec.rb
213
- - spec/git_multicast/cloner_spec.rb
214
- - spec/git_multicast/output_formatter_spec.rb
215
- - spec/git_multicast/puller_spec.rb
231
+ - spec/git_multicast/formatter/full_spec.rb
232
+ - spec/git_multicast/formatter/quiet_spec.rb
233
+ - spec/git_multicast/formatter/standard_spec.rb
234
+ - spec/git_multicast/formatter/status_spec.rb
235
+ - spec/git_multicast/multicaster/clone_spec.rb
236
+ - spec/git_multicast/multicaster/pull_spec.rb
237
+ - spec/git_multicast/multicaster/status_spec.rb
216
238
  - spec/git_multicast/repository_fetcher/bitbucket_spec.rb
217
239
  - spec/git_multicast/repository_fetcher/github_spec.rb
218
240
  - spec/git_multicast/repository_fetcher_spec.rb
219
- - spec/git_multicast/statuser_spec.rb
220
- - spec/git_multicast/task_runner_spec.rb
241
+ - spec/git_multicast/task/runner_spec.rb
221
242
  - spec/git_multicast/task_spec.rb
222
243
  - spec/spec_helper.rb
223
244
  homepage: http://github.com/rranelli/git_multicast
@@ -1,11 +0,0 @@
1
- Documentation:
2
- Enabled: false
3
-
4
- AllCops:
5
- # Include gemspec and Rakefile
6
- Include:
7
- - '**/*.gemspec'
8
- - '**/Rakefile'
9
-
10
- Style/Encoding:
11
- Enabled: false
@@ -1,7 +0,0 @@
1
- require_relative 'adapters/bitbucket'
2
- require_relative 'adapters/github'
3
-
4
- module GitMulticast
5
- module Adapters
6
- end
7
- end
@@ -1,36 +0,0 @@
1
- require 'net/http'
2
- require 'json'
3
-
4
- module GitMulticast
5
- class Cloner
6
- def initialize(username, dir)
7
- @username = username
8
- @dir = dir
9
- end
10
-
11
- def clone!
12
- repos = RepositoryFetcher.get_all_repos_from_user(username)
13
-
14
- tasks = repos.map do |repo|
15
- Task.new(repo.name, command(repo))
16
- end
17
-
18
- TaskRunner.new(tasks).run!
19
- end
20
-
21
- protected
22
-
23
- attr_reader :username, :dir
24
-
25
- def command(repo)
26
- if repo.fork
27
- parent_repo = RepositoryFetcher.get_repo_parent(repo.url)
28
- "git clone #{repo.ssh_url} #{File.join(dir, repo.name)} && \
29
- git -C \"#{File.join(dir, repo.name)}\" remote add upstream \
30
- #{parent_repo.ssh_url} --fetch"
31
- else
32
- "git clone #{repo.ssh_url} #{File.join(dir, repo.name)}"
33
- end
34
- end
35
- end
36
- end
@@ -1,30 +0,0 @@
1
- require 'colorize'
2
-
3
- module GitMulticast
4
- class OutputFormatter
5
- def initialize(start_time = nil)
6
- @start_time = start_time
7
- end
8
-
9
- def single_format(task_result)
10
- case task_result.exit_status
11
- when 0
12
- '[Success]'.green + " #{task_result.name} #{time_report}"
13
- else
14
- <<EOF
15
- #{'[Error]'.red} #{task_result.name}
16
- #{task_result.result}
17
- #{'-' * 25}
18
- EOF
19
- end
20
- end
21
-
22
- protected
23
-
24
- attr_reader :start_time
25
-
26
- def time_report
27
- "in #{Time.now - start_time} seconds" unless start_time.nil?
28
- end
29
- end
30
- end
@@ -1,28 +0,0 @@
1
- module GitMulticast
2
- class Puller
3
- def initialize(dir)
4
- @dir = dir
5
- end
6
-
7
- def pull!
8
- tasks = Dir.entries(dir)
9
- .select { |f| File.directory? f }
10
- .reject { |f| f =~ /^\./ } # ., .. and .git and the like
11
- .map { |dir| Task.new(description(dir), command(dir)) }
12
-
13
- TaskRunner.new(tasks).run!
14
- end
15
-
16
- protected
17
-
18
- attr_reader :dir
19
-
20
- def command(dir)
21
- "git -C #{dir} pull -r origin"
22
- end
23
-
24
- def description(dir)
25
- File.basename(dir)
26
- end
27
- end
28
- end
@@ -1,28 +0,0 @@
1
- module GitMulticast
2
- class Statuser
3
- def initialize(dir)
4
- @dir = dir
5
- end
6
-
7
- def statuses!
8
- tasks = Dir.entries(dir)
9
- .select { |f| File.directory? f }
10
- .reject { |f| f =~ /^\./ } # ., .. and .git and the like
11
- .map { |dir| Task.new(description(dir), command(dir)) }
12
-
13
- TaskRunner.new(tasks).run!
14
- end
15
-
16
- protected
17
-
18
- attr_reader :dir
19
-
20
- def command(dir)
21
- "cd #{dir} && git status"
22
- end
23
-
24
- def description(dir)
25
- File.basename(dir)
26
- end
27
- end
28
- end
@@ -1,7 +0,0 @@
1
- module GitMulticast
2
- TaskResult = Struct.new(:name, :result, :exit_status) do
3
- def to_s
4
- result
5
- end
6
- end
7
- end
@@ -1,40 +0,0 @@
1
- module GitMulticast
2
- class TaskRunner
3
- include Process
4
-
5
- def initialize(tasks, formatter = OutputFormatter.new(Time.now))
6
- @tasks = tasks
7
- @formatter = formatter
8
- end
9
-
10
- def run!
11
- tasks
12
- .map(&method(:future))
13
- .map(&:get)
14
- .inject('', &:+)
15
- end
16
-
17
- protected
18
-
19
- attr_reader :tasks, :formatter
20
-
21
- def future(task)
22
- PoorMansFuture.new { formatter.single_format(task.call) }
23
- end
24
-
25
- class PoorMansFuture
26
- def initialize(&block)
27
- @thread = Thread.new do
28
- Thread.current[:output] = block.call
29
- end
30
- end
31
-
32
- def get
33
- thread.join
34
- thread[:output]
35
- end
36
-
37
- attr_reader :thread
38
- end
39
- end
40
- end
@@ -1,94 +0,0 @@
1
- module GitMulticast
2
- describe Cloner do
3
- subject(:cloner) { described_class.new(username, dir) }
4
-
5
- let(:username) { 'rranelli' }
6
- let(:dir) { '/kifita/' }
7
-
8
- let(:repo_name) { 'git_multicast' }
9
-
10
- before do
11
- allow(task).to receive(:spawn)
12
- .and_return(pid)
13
- allow(task).to receive(:wait)
14
- .and_return(['', 0])
15
-
16
- allow(Task).to receive(:new)
17
- .and_return(task)
18
- end
19
-
20
- let(:task) { instance_double(Task, call: result) }
21
- let(:result) { TaskResult.new(repo_name, 'success', 0) }
22
-
23
- let(:pid) { 42 }
24
-
25
- describe '#clone!' do
26
- subject(:clone!) { cloner.clone! }
27
-
28
- it do
29
- VCR.use_cassette('clone_repos') do
30
- expect(RepositoryFetcher).to receive(:get_all_repos_from_user)
31
- .with(username)
32
- .and_call_original
33
-
34
- clone!
35
- end
36
- end
37
-
38
- it 'creates a task for each fetched repository' do
39
- VCR.use_cassette('clone_repos') do
40
- expect(Task).to receive(:new).exactly(43).times
41
-
42
- clone!
43
- end
44
- end
45
-
46
- it 'creates a task runner and asks it to run all tasks' do
47
- VCR.use_cassette('clone_repos') do
48
- expect(TaskRunner).to receive_message_chain(:new, :run!)
49
-
50
- clone!
51
- end
52
- end
53
-
54
- it 'spawns a clone job for each repo' do
55
- VCR.use_cassette('clone_repos') do
56
- expect(task).to receive(:call).exactly(43).times
57
-
58
- clone!
59
- end
60
- end
61
-
62
- it 'spawns a clone with the right parameters' do
63
- VCR.use_cassette('clone_repos') do
64
- clone_command = "git clone git@github.com:rranelli/#{repo_name}.git" \
65
- ' /kifita/git_multicast'
66
-
67
- expect(Task).to receive(:new)
68
- .with(repo_name, clone_command)
69
-
70
- clone!
71
- end
72
- end
73
-
74
- context 'when repo is a fork'do
75
- let(:repo_name) { 'emacs.d' }
76
-
77
- it 'adds upstream remote' do
78
- VCR.use_cassette('clone_repos') do
79
- expect(Task).to receive(:new)
80
- .with(
81
- repo_name,
82
- "git clone git@github.com:rranelli/#{repo_name}.git " \
83
- "/kifita/#{repo_name} && git -C \"/kifita/#{repo_name}\"" \
84
- ' remote add upstream ' \
85
- "git@github.com:purcell/#{repo_name}.git --fetch"
86
- )
87
-
88
- clone!
89
- end
90
- end
91
- end
92
- end
93
- end
94
- end