git_multicast 0.3.0 → 0.4.0.pre
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/.rubocop.yml +6 -4
- data/.travis.yml +1 -0
- data/Gemfile.lock +2 -2
- data/README.md +25 -3
- data/lib/git_multicast/cli.rb +1 -1
- data/lib/git_multicast/multicaster/clone.rb +20 -6
- data/lib/git_multicast/task/pool.rb +39 -0
- data/lib/git_multicast/task/runner.rb +16 -18
- data/lib/git_multicast/task.rb +3 -0
- data/lib/git_multicast/version.rb +1 -1
- data/spec/git_multicast/multicaster/clone_spec.rb +4 -5
- data/spec/git_multicast/task/pool_spec.rb +46 -0
- data/spec/git_multicast/task/runner_spec.rb +12 -19
- data/spec/git_multicast/task_spec.rb +8 -0
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3aab03f01067ec2e758af176a40fcf275e2ec41d
|
4
|
+
data.tar.gz: 38e9dea36b46da178e404c17f928f62ef483c4fd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: de31fbdcd6ef73569320441bbb90d20a72d3e205c9d87e7418e0c55674bbdf7dbec255cb2b7fce5874e1ce73f2f42c05c94003183a903ff331e258a9d7f3c031
|
7
|
+
data.tar.gz: 343ce413175a6e587206ad2f618dcb02a0f98d5b83ad9ece2374c907dce4490b6f1806484385df5d3bfa11276897135f9ca1ce59dd8d388f1ef56248c13e3501
|
data/.rubocop.yml
CHANGED
@@ -1,11 +1,13 @@
|
|
1
1
|
Documentation:
|
2
2
|
Enabled: false
|
3
3
|
|
4
|
+
Style/Encoding:
|
5
|
+
Enabled: false
|
6
|
+
|
7
|
+
Style/MultilineOperationIndentation:
|
8
|
+
Enabled: false
|
9
|
+
|
4
10
|
AllCops:
|
5
|
-
# Include gemspec and Rakefile
|
6
11
|
Include:
|
7
12
|
- '**/*.gemspec'
|
8
13
|
- '**/Rakefile'
|
9
|
-
|
10
|
-
Style/Encoding:
|
11
|
-
Enabled: false
|
data/.travis.yml
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
git_multicast (0.
|
4
|
+
git_multicast (0.4.0.pre)
|
5
5
|
colorize (~> 0.7)
|
6
6
|
recursive-open-struct (~> 0.5.0)
|
7
7
|
thor (~> 0.19)
|
@@ -14,7 +14,7 @@ GEM
|
|
14
14
|
astrolabe (1.3.0)
|
15
15
|
parser (>= 2.2.0.pre.3, < 3.0)
|
16
16
|
coderay (1.1.0)
|
17
|
-
colorize (0.7.
|
17
|
+
colorize (0.7.4)
|
18
18
|
crack (0.4.2)
|
19
19
|
safe_yaml (~> 1.0.0)
|
20
20
|
diff-lcs (1.2.5)
|
data/README.md
CHANGED
@@ -18,11 +18,33 @@ just as long as cloning the larger one, and nothing more.
|
|
18
18
|
Actions currently supported:
|
19
19
|
|
20
20
|
* Git clone all repositories of an user or organization (github & bitbucket).
|
21
|
+
|
22
|
+
```sh
|
23
|
+
git_multicast clone username
|
24
|
+
```
|
25
|
+
|
21
26
|
* Git pull all repositories in a directory.
|
27
|
+
|
28
|
+
```sh
|
29
|
+
git_multicast clone username
|
30
|
+
```
|
31
|
+
|
22
32
|
* Git status all repositories in a directory.
|
23
33
|
|
34
|
+
```sh
|
35
|
+
git_multicast status
|
36
|
+
```
|
37
|
+
|
38
|
+
|
39
|
+
* Sends a custom git command to all repositories in a directory.
|
40
|
+
|
41
|
+
```sh
|
42
|
+
git_multicast cast "push --force origin master" # don't do this at home.
|
43
|
+
```
|
44
|
+
|
45
|
+
All actions allow for both `--verbose` and `--quiet` options that will control
|
46
|
+
how much output is shown for each command execution.
|
47
|
+
|
24
48
|
Actions to be supported:
|
25
49
|
|
26
|
-
* Git clone repositories from Gitlab
|
27
|
-
* Pass options to git pull. (e.g., force, rebase, dry-run, etc.)
|
28
|
-
* Pass options to git status. (e.g., show only those that have modifications)
|
50
|
+
* Git clone repositories from `Gitlab`.
|
data/lib/git_multicast/cli.rb
CHANGED
@@ -14,22 +14,36 @@ module GitMulticast
|
|
14
14
|
|
15
15
|
attr_reader :username, :dir
|
16
16
|
|
17
|
+
private
|
18
|
+
|
17
19
|
def tasks
|
18
20
|
RepositoryFetcher
|
19
21
|
.get_all_repos_from_user(username)
|
20
|
-
.map { |repo| Task.new(repo
|
22
|
+
.map { |repo| Task.new(description(repo), command(repo)) }
|
23
|
+
end
|
24
|
+
|
25
|
+
def description(repo)
|
26
|
+
"Cloning #{repo.name}..."
|
21
27
|
end
|
22
28
|
|
23
29
|
def command(repo)
|
24
30
|
if repo.fork
|
25
|
-
|
26
|
-
"git clone #{repo.ssh_url} #{File.join(dir, repo.name)} && \
|
27
|
-
git -C \"#{File.join(dir, repo.name)}\" remote add upstream \
|
28
|
-
#{parent_repo.ssh_url} --fetch"
|
31
|
+
clone_repo_with_parent(repo)
|
29
32
|
else
|
30
|
-
|
33
|
+
clone(repo)
|
31
34
|
end
|
32
35
|
end
|
36
|
+
|
37
|
+
def clone_repo_with_parent(repo)
|
38
|
+
parent_repo = RepositoryFetcher.get_repo_parent(repo.url)
|
39
|
+
"git clone #{repo.ssh_url} #{File.join(dir, repo.name)} && \
|
40
|
+
git -C \"#{File.join(dir, repo.name)}\" remote add upstream \
|
41
|
+
#{parent_repo.ssh_url} --fetch"
|
42
|
+
end
|
43
|
+
|
44
|
+
def clone(repo)
|
45
|
+
"git clone #{repo.ssh_url} #{File.join(dir, repo.name)}"
|
46
|
+
end
|
33
47
|
end
|
34
48
|
end
|
35
49
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'thread'
|
2
|
+
|
3
|
+
module GitMulticast
|
4
|
+
class Task
|
5
|
+
class Pool
|
6
|
+
def initialize(size)
|
7
|
+
@size = size
|
8
|
+
@queue = Queue.new
|
9
|
+
@pool = (1..size).map { Thread.new(&job_loop) }
|
10
|
+
end
|
11
|
+
|
12
|
+
def schedule(*args, &blk)
|
13
|
+
queue << [blk, args]
|
14
|
+
end
|
15
|
+
|
16
|
+
def shutdown
|
17
|
+
size.times { schedule { throw :exit } }
|
18
|
+
pool.map(&:join)
|
19
|
+
end
|
20
|
+
|
21
|
+
protected
|
22
|
+
|
23
|
+
attr_reader :size, :queue, :pool
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def job_loop
|
28
|
+
-> { catch(:exit) { loop(&run_job) } }
|
29
|
+
end
|
30
|
+
|
31
|
+
def run_job
|
32
|
+
lambda do
|
33
|
+
job, args = queue.pop
|
34
|
+
job.call(*args)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -1,37 +1,35 @@
|
|
1
1
|
module GitMulticast
|
2
2
|
class Task
|
3
3
|
class Runner
|
4
|
-
def initialize(tasks)
|
4
|
+
def initialize(tasks, pool_size: 20, pool: Pool.new(pool_size))
|
5
5
|
@tasks = tasks
|
6
|
+
@pool = pool
|
7
|
+
@result_queue = Queue.new
|
6
8
|
end
|
7
9
|
|
8
10
|
def run!
|
9
11
|
tasks
|
10
|
-
.map(&
|
11
|
-
.map(
|
12
|
+
.map(&wrap_with_notify)
|
13
|
+
.map(&schedule)
|
14
|
+
.map(&await)
|
12
15
|
end
|
13
16
|
|
14
17
|
protected
|
15
18
|
|
16
|
-
attr_reader :tasks
|
19
|
+
attr_reader :tasks, :result_queue, :pool
|
17
20
|
|
18
|
-
|
19
|
-
PoorMansFuture.new { task.call }
|
20
|
-
end
|
21
|
+
private
|
21
22
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
Thread.current[:output] = yield
|
26
|
-
end
|
27
|
-
end
|
23
|
+
def wrap_with_notify
|
24
|
+
-> (task) { -> (*) { result_queue << task.call } }
|
25
|
+
end
|
28
26
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
end
|
27
|
+
def schedule
|
28
|
+
-> (task) { pool.schedule([], &task) }
|
29
|
+
end
|
33
30
|
|
34
|
-
|
31
|
+
def await
|
32
|
+
-> (_) { result_queue.pop }
|
35
33
|
end
|
36
34
|
end
|
37
35
|
end
|
data/lib/git_multicast/task.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require_relative 'task/result'
|
2
2
|
require_relative 'task/runner'
|
3
|
+
require_relative 'task/pool'
|
3
4
|
|
4
5
|
module GitMulticast
|
5
6
|
class Task
|
@@ -10,6 +11,8 @@ module GitMulticast
|
|
10
11
|
end
|
11
12
|
|
12
13
|
def run!
|
14
|
+
puts description
|
15
|
+
|
13
16
|
r, w = IO.pipe
|
14
17
|
pid = spawn(command, out: w, err: w)
|
15
18
|
|
@@ -67,7 +67,7 @@ module GitMulticast
|
|
67
67
|
' /kifita/git_multicast'
|
68
68
|
|
69
69
|
expect(Task).to receive(:new)
|
70
|
-
.with(repo_name, command)
|
70
|
+
.with("Cloning #{repo_name}...", command)
|
71
71
|
|
72
72
|
execute!
|
73
73
|
end
|
@@ -78,14 +78,13 @@ module GitMulticast
|
|
78
78
|
|
79
79
|
it 'adds upstream remote' do
|
80
80
|
VCR.use_cassette('clone_repos') do
|
81
|
-
expect(Task).to receive(:new)
|
82
|
-
|
83
|
-
repo_name,
|
81
|
+
expect(Task).to receive(:new).with(
|
82
|
+
"Cloning #{repo_name}...",
|
84
83
|
"git clone git@github.com:rranelli/#{repo_name}.git " \
|
85
84
|
"/kifita/#{repo_name} && git -C \"/kifita/#{repo_name}\"" \
|
86
85
|
' remote add upstream ' \
|
87
86
|
"git@github.com:purcell/#{repo_name}.git --fetch"
|
88
|
-
|
87
|
+
)
|
89
88
|
|
90
89
|
execute!
|
91
90
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
describe GitMulticast::Task::Pool do
|
2
|
+
subject(:pool) { described_class.new(size) }
|
3
|
+
|
4
|
+
let(:size) { 5 }
|
5
|
+
|
6
|
+
it { is_expected.to be_truthy }
|
7
|
+
|
8
|
+
describe '#schedule' do
|
9
|
+
subject(:schedule) { pool.schedule(1, &appender) }
|
10
|
+
|
11
|
+
let(:result) { [] }
|
12
|
+
let(:appender) { -> (x) { result << x } }
|
13
|
+
|
14
|
+
it do
|
15
|
+
schedule
|
16
|
+
sleep(0.3)
|
17
|
+
|
18
|
+
expect(result).to eq([1])
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'when scheduling many jobs' do
|
22
|
+
subject(:schedule) do
|
23
|
+
jobs.each { |(*args, job)| pool.schedule(*args, &job) }
|
24
|
+
end
|
25
|
+
|
26
|
+
let(:append_and_sleep) { -> (x) { (result << x) && sleep(0.5) } }
|
27
|
+
|
28
|
+
let(:jobs) do
|
29
|
+
[
|
30
|
+
[1, append_and_sleep],
|
31
|
+
[2, append_and_sleep],
|
32
|
+
[3, append_and_sleep],
|
33
|
+
[4, append_and_sleep],
|
34
|
+
[5, append_and_sleep]
|
35
|
+
]
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'runs them in parallel' do
|
39
|
+
schedule
|
40
|
+
sleep(0.2)
|
41
|
+
|
42
|
+
expect(result).to contain_exactly(1, 2, 3, 4, 5)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -6,30 +6,15 @@ module GitMulticast
|
|
6
6
|
let(:tasks) { [hey_task, ho_task] }
|
7
7
|
|
8
8
|
# Since tasks quack like lambdas, I will be using them here.
|
9
|
-
let(:hey_task) { ->() { first_result } }
|
10
|
-
let(:ho_task) { ->() { second_result } }
|
9
|
+
let(:hey_task) { ->() { sleep(0.3) && first_result } }
|
10
|
+
let(:ho_task) { ->() { sleep(0.3) && second_result } }
|
11
11
|
|
12
|
-
let
|
13
|
-
let
|
14
|
-
|
15
|
-
let(:formatter) { Formatter::Standard.new }
|
16
|
-
|
17
|
-
before do
|
18
|
-
allow(Formatter::Standard).to receive(:new)
|
19
|
-
.and_return(formatter)
|
20
|
-
end
|
12
|
+
let(:first_result) { Task::Result.new(:one, 'Hey!', 1) }
|
13
|
+
let(:second_result) { Task::Result.new(:two, 'Ho!', 1) }
|
21
14
|
|
22
15
|
describe '#run!' do
|
23
16
|
subject(:run!) { runner.run! }
|
24
17
|
|
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
18
|
it 'calls each task' do
|
34
19
|
expect(hey_task).to receive(:call)
|
35
20
|
.and_call_original
|
@@ -37,6 +22,14 @@ module GitMulticast
|
|
37
22
|
.and_call_original
|
38
23
|
|
39
24
|
run!
|
25
|
+
|
26
|
+
sleep(0.5)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'returns an array with task results' do
|
30
|
+
timeout(0.5) do
|
31
|
+
expect(run!).to contain_exactly(first_result, second_result)
|
32
|
+
end
|
40
33
|
end
|
41
34
|
end
|
42
35
|
end
|
@@ -12,6 +12,8 @@ describe GitMulticast::Task do
|
|
12
12
|
let(:w) { pipe[1] }
|
13
13
|
|
14
14
|
before do
|
15
|
+
allow(STDOUT).to receive(:write)
|
16
|
+
|
15
17
|
allow(task).to receive(:spawn)
|
16
18
|
.and_return(pid)
|
17
19
|
allow(task).to receive(:wait2)
|
@@ -55,5 +57,11 @@ describe GitMulticast::Task do
|
|
55
57
|
|
56
58
|
run!
|
57
59
|
end
|
60
|
+
|
61
|
+
it 'writes description to STDOUT' do
|
62
|
+
expect(STDOUT).to receive(:write).with(description)
|
63
|
+
|
64
|
+
run!
|
65
|
+
end
|
58
66
|
end
|
59
67
|
end
|
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.
|
4
|
+
version: 0.4.0.pre
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Renan Ranelli
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-04-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: recursive-open-struct
|
@@ -217,6 +217,7 @@ files:
|
|
217
217
|
- lib/git_multicast/repository_fetcher/bitbucket.rb
|
218
218
|
- lib/git_multicast/repository_fetcher/github.rb
|
219
219
|
- lib/git_multicast/task.rb
|
220
|
+
- lib/git_multicast/task/pool.rb
|
220
221
|
- lib/git_multicast/task/result.rb
|
221
222
|
- lib/git_multicast/task/runner.rb
|
222
223
|
- lib/git_multicast/version.rb
|
@@ -240,6 +241,7 @@ files:
|
|
240
241
|
- spec/git_multicast/repository_fetcher/bitbucket_spec.rb
|
241
242
|
- spec/git_multicast/repository_fetcher/github_spec.rb
|
242
243
|
- spec/git_multicast/repository_fetcher_spec.rb
|
244
|
+
- spec/git_multicast/task/pool_spec.rb
|
243
245
|
- spec/git_multicast/task/runner_spec.rb
|
244
246
|
- spec/git_multicast/task_spec.rb
|
245
247
|
- spec/spec_helper.rb
|
@@ -258,9 +260,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
258
260
|
version: '2.0'
|
259
261
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
260
262
|
requirements:
|
261
|
-
- - "
|
263
|
+
- - ">"
|
262
264
|
- !ruby/object:Gem::Version
|
263
|
-
version:
|
265
|
+
version: 1.3.1
|
264
266
|
requirements: []
|
265
267
|
rubyforge_project:
|
266
268
|
rubygems_version: 2.2.2
|