git-bundle 1.0.8 → 1.0.9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 5fd3dff341b34d70c5e00235262bb39cfe394cbf
4
- data.tar.gz: 36f3501f1d8cda04c76e556728bec30c0c305917
2
+ SHA256:
3
+ metadata.gz: ee97fbb6a2aa563b72b0abca619fada133610e53c9a738eca1dd2bcd654e0fd5
4
+ data.tar.gz: bf118e8f68b683b5b860a7ef8019844265c77b99ffbbec8f96d4b33aff090cf3
5
5
  SHA512:
6
- metadata.gz: 852ec697b4e298057ddaffa3e72f9816336496e9aac114fc2f3385ba1e5d9e19147d4921eb0290b1dbc3fc96db98c30fef818cfd2e03b9de2fb7e96c3e32b605
7
- data.tar.gz: 61749820a89a6694db8f698f858ae5f3478666cc5a7cdd4b4897138870e6185095a9658fcded76abe25b66eef703fe6d8597f0b59f8b681920f5021255562774
6
+ metadata.gz: 5c86d25bf251d24b074181fbfa845daa9a159bdb89f19039bdc21461db26c189cdaa08905a1cd83f1639f58dff7973cd731b3182f6f1789b4702f7d5f8764001
7
+ data.tar.gz: 5d7e815ae3385a9825b2ec28c9a956ab861e5444f8d0280afbfcd5a9525f91ea5304772dfb0128f7f7f44f5cc49c3f2201d8b95b030a1129870c04d3ab35e036
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- git-bundle (1.0.7)
4
+ git-bundle (1.0.9)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -15,4 +15,4 @@ DEPENDENCIES
15
15
  git-bundle!
16
16
 
17
17
  BUNDLED WITH
18
- 1.15.3
18
+ 1.16.1
@@ -1,7 +1,10 @@
1
1
  require 'bundler'
2
2
  require 'git_bundle/version'
3
3
  require 'git_bundle/console'
4
+ require 'git_bundle/shell'
4
5
  require 'git_bundle/cli'
5
6
  require 'git_bundle/repository'
7
+ require 'git_bundle/project'
6
8
  require 'git_bundle/commands/generic'
7
- require 'git_bundle/commands/push'
9
+ require 'git_bundle/commands/push'
10
+ require 'git_bundle/commands/version'
@@ -4,7 +4,7 @@ module GitBundle
4
4
 
5
5
  def initialize
6
6
  @errors = []
7
- load_repositories
7
+ @project = GitBundle::Project.new
8
8
  end
9
9
 
10
10
  def invoke(args)
@@ -12,23 +12,14 @@ module GitBundle
12
12
  when nil, '--help', 'help'
13
13
  puts `git #{args.join(' ')}`.gsub('git', 'gitb')
14
14
  when 'push'
15
- GitBundle::Commands::Push.new(@repositories, args[1..-1]).invoke
15
+ GitBundle::Commands::Push.new(@project, args[1..-1]).invoke
16
+ when '--version'
17
+ GitBundle::Commands::Version.new.invoke
16
18
  else
17
- GitBundle::Commands::Generic.new(@repositories, args).invoke
19
+ GitBundle::Commands::Generic.new(@project, args).invoke
18
20
  end
19
- end
20
-
21
- private
22
- def load_repositories
23
- @repositories = []
24
- if Bundler.locked_gems
25
- Bundler.settings.local_overrides.each do |name, path|
26
- spec = Bundler.locked_gems.specs.find { |s| s.name == name }
27
- @repositories << GitBundle::Repository.new_dependant(spec.name, path, spec.source.branch, spec.source.revision) if spec
28
- end
29
- end
30
-
31
- @repositories << GitBundle::Repository.new_main(File.basename(Dir.getwd), Dir.getwd)
21
+ rescue Bundler::GemfileNotFound => e
22
+ puts_error("Could not find Gemfile in the current directory")
32
23
  end
33
24
  end
34
25
  end
@@ -3,50 +3,18 @@ module GitBundle
3
3
  class Generic
4
4
  include GitBundle::Console
5
5
 
6
- def initialize(repositories, args)
7
- @repositories = repositories
6
+ def initialize(project, args)
7
+ @project = project
8
8
  @args = args
9
9
  end
10
10
 
11
- def print_wait_line(names)
12
- STDOUT.print "Waiting for #{names.map {|name| colorize(name, COLORS[:highlight], true)}.join(', ')}"
13
- STDOUT.flush
14
- end
15
-
16
11
  def invoke
17
- repository_results = @repositories.map {|repo| {repository: repo, output: '', error: false, complete: false, thread: nil}}
12
+ @project.load_dependant_repositories
18
13
 
19
- @repositories.each_with_index do |repo, index|
20
- results = repository_results[index]
21
- results[:thread] = Thread.new do
22
- results[:output] = repo.execute_git(@args, color: true)
23
- results[:error] = true unless $?.exitstatus == 0
24
- end
14
+ parallel(@project.repositories) do |repo|
15
+ output = repo.execute_git(@args, color: true)
16
+ ExecutionResult.new($?.exitstatus != 0, output)
25
17
  end
26
-
27
- waiting_for_repositories = @repositories.map(&:name)
28
- print_wait_line(waiting_for_repositories)
29
-
30
- until waiting_for_repositories.empty?
31
- repository_results.each do |result|
32
- next if result[:complete]
33
-
34
- if result[:thread].join(0.1)
35
- result[:complete] = true
36
- clear_line
37
-
38
- puts_repo_heading(result[:repository])
39
- puts result[:output]
40
-
41
- waiting_for_repositories.delete(result[:repository].name)
42
- print_wait_line(waiting_for_repositories) unless waiting_for_repositories.empty?
43
- end
44
- end
45
- end
46
-
47
- puts ''
48
- errors = repository_results.select {|r| r[:error]}.map {|r| r[:repository].name}
49
- puts_error "Command failed in #{errors.join(', ')}." unless errors.empty?
50
18
  end
51
19
  end
52
20
  end
@@ -2,18 +2,31 @@ module GitBundle
2
2
  module Commands
3
3
  class Push
4
4
  include GitBundle::Console
5
+ include GitBundle::Shell
5
6
 
6
- def initialize(repositories, args)
7
- @repositories = repositories
7
+ def initialize(project, args)
8
+ @project = project
8
9
  @args = args
9
10
  end
10
11
 
11
12
  def invoke
13
+ @project.load_dependant_repositories
12
14
  return false unless prompt_confirm
13
15
 
16
+ main_repository = @project.main_repository
17
+
14
18
  lockfile = Bundler.default_lockfile.basename.to_s
15
- stale_repos = @repositories.select { |repo| !repo.main && repo.stale? }
16
- stale_commits_message = stale_repos.map { |repo| "#{repo.name}(#{repo.stale_commits_count})" }.join(', ')
19
+ stale_repos = @project.repositories.select { |repo| !repo.main && repo.stale? }
20
+ stale_commits_message = stale_repos.map do |repo|
21
+ repo.upstream_branch_exists? ? "#{repo.name}(#{repo.stale_commits_count})" : "#{repo.name}(new branch)"
22
+ end.join(', ')
23
+
24
+ stale_commits_description = ''
25
+ stale_repos.select(&:upstream_branch_exists?).each do |repo|
26
+ stale_commits_description << "== #{repo.name} ==\n"
27
+ stale_commits_description << repo.stale_commits
28
+ stale_commits_description << "\n\n"
29
+ end
17
30
 
18
31
  if stale_repos.any?
19
32
  puts "Local gems were updated. Building new #{lockfile} with bundle install."
@@ -31,52 +44,65 @@ module GitBundle
31
44
  message = "Gemfile.lock includes new commits of: #{stale_commits_message}."
32
45
  end
33
46
 
34
- main_repository.commit(message, lockfile)
47
+ main_repository.commit_with_description(message, stale_commits_description, lockfile)
35
48
  puts message
36
49
  end
37
50
 
38
- @repositories.select { |repo| !repo.main && repo.commits_not_pushed_count > 0 }.each do |repo|
51
+ @project.dependant_repositories.select { |repo| repo.commits_not_pushed? }.each do |repo|
39
52
  puts_repo_heading(repo)
40
- unless repo.push(@args)
53
+
54
+ create_upstream = !repo.upstream_branch_exists?
55
+ unless repo.push(@args, create_upstream: create_upstream)
41
56
  puts_error "Failed to push changes of #{repo.name}. Try pulling the latest changes or resolve conflicts first."
42
57
  return false
43
58
  end
44
59
  end
45
60
 
46
61
  puts_repo_heading(main_repository)
47
- unless main_repository.push(@args)
62
+ create_upstream = !main_repository.upstream_branch_exists?
63
+ unless main_repository.push(@args, create_upstream: create_upstream)
48
64
  puts_error "Failed to push changes of #{main_repository.name}. Try pulling the latest changes or resolve conflicts first."
49
65
  end
50
66
  end
51
67
 
52
68
  private
53
69
  def prompt_confirm
54
- if main_repository.file_changed?('Gemfile')
70
+ if @project.main_repository.file_changed?('Gemfile')
55
71
  puts_error 'Your Gemfile has uncommitted changes. Commit them first before pushing.'
56
72
  return false
57
73
  end
58
74
 
59
75
  commits_to_push = false
60
- @repositories.each do |repo|
76
+ upstream_branches_missing = []
77
+ @project.repositories.each do |repo|
61
78
  commits = repo.commits_not_pushed
62
79
  puts_repo_heading(repo)
63
80
 
64
- if commits.empty?
65
- puts 'No changes.'
81
+ if repo.upstream_branch_exists?
82
+ if commits.empty?
83
+ puts 'No changes.'
84
+ else
85
+ commits_to_push = true
86
+ puts commits
87
+ end
66
88
  else
67
- commits_to_push = true
68
- puts commits
89
+ upstream_branches_missing << repo.name
90
+ puts 'Remote branch does not exist yet.'
69
91
  end
70
92
  end
71
93
 
72
- if commits_to_push
94
+ if !upstream_branches_missing.empty?
95
+ puts_prompt("Missing upstream branches (#{upstream_branches_missing.join(', ')}) will be created and changes pushed.")
96
+ puts_prompt('Do you want to continue? (Y/N)')
97
+
98
+ elsif commits_to_push
73
99
  puts_prompt('Are you sure you want to push these changes? (Y/N)')
74
100
 
75
101
  elsif gemfile_lock_stale?
76
102
  puts_prompt('Although you don\'t have any commits to push, your Gemfile.lock needs to be rebuilt, committed and pushed.')
77
103
  puts_prompt('Do you want to continue? (Y/N)')
78
104
 
79
- elsif main_repository.file_changed?('Gemfile.lock')
105
+ elsif @project.main_repository.file_changed?('Gemfile.lock')
80
106
  puts_prompt('Although you don\'t have any commits to push, your Gemfile.lock needs to be committed and pushed.')
81
107
  puts_prompt('Do you want to continue? (Y/N)')
82
108
  else
@@ -86,17 +112,13 @@ module GitBundle
86
112
  STDIN.getch.upcase == 'Y'
87
113
  end
88
114
 
89
- def main_repository
90
- @repositories.find { |repo| repo.main }
91
- end
92
-
93
115
  def gemfile_lock_stale?
94
- @repositories.any? { |repo| repo.stale? }
116
+ @project.repositories.any? { |repo| repo.stale? }
95
117
  end
96
118
 
97
119
  def build_gemfile_lock
98
- Dir.chdir(main_repository.path) do
99
- puts `bundle install --quiet`
120
+ Dir.chdir(@project.main_repository.path) do
121
+ execute_live('bundle', 'install', '--quiet')
100
122
  return $?.exitstatus == 0
101
123
  end
102
124
  end
@@ -0,0 +1,13 @@
1
+ module GitBundle
2
+ module Commands
3
+ class Version
4
+ include GitBundle::Console
5
+
6
+ def invoke
7
+ puts "git-bundle version #{GitBundle::VERSION}"
8
+ puts "bundler version #{Bundler::VERSION}"
9
+ system 'git', '--version'
10
+ end
11
+ end
12
+ end
13
+ end
@@ -1,10 +1,14 @@
1
+ require 'io/console'
2
+
1
3
  module GitBundle
2
4
  module Console
3
- COLORS = {error: 31,
4
- attention: 32,
5
- prompt: 33,
6
- heading: 34,
7
- highlight: 36}
5
+ COLORS = { error: 31,
6
+ attention: 32,
7
+ prompt: 33,
8
+ heading: 34,
9
+ highlight: 36 }
10
+
11
+ ExecutionResult = Struct.new(:error, :output)
8
12
 
9
13
  def clear_line
10
14
  STDOUT.print "\r\e[0K"
@@ -15,6 +19,10 @@ module GitBundle
15
19
  puts colorize("\n=== #{repo.name} (#{repo.branch})", COLORS[:heading], true)
16
20
  end
17
21
 
22
+ def puts_repo_heading_switch(repo, new_branch)
23
+ puts colorize("\n=== #{repo.name} (#{repo.branch} ⇒ #{new_branch})", COLORS[:heading], true)
24
+ end
25
+
18
26
  def puts_heading(text)
19
27
  puts colorize("\n=== #{text}", COLORS[:heading])
20
28
  end
@@ -31,6 +39,54 @@ module GitBundle
31
39
  puts colorize(text, COLORS[:error])
32
40
  end
33
41
 
42
+ def puts_stay_on_line(text)
43
+ STDOUT.print text
44
+ STDOUT.flush
45
+ end
46
+
47
+ def puts_wait_line(names)
48
+ puts_stay_on_line "Waiting for #{names.map { |name| colorize(name, COLORS[:highlight], true) }.join(', ')}"
49
+ end
50
+
51
+ def parallel(items, heading_proc = nil)
52
+ heading_proc ||= -> (item) { puts_repo_heading(item) }
53
+
54
+ item_results = items.map { |item| { item: item, output: '', error: false, complete: false, thread: nil } }
55
+
56
+ items.each_with_index do |item, index|
57
+ results = item_results[index]
58
+ results[:thread] = Thread.new do
59
+ result = yield(item)
60
+ results[:output] = result.output
61
+ results[:error] = result.error
62
+ end
63
+ end
64
+
65
+ waiting_for_items = items.map(&:name)
66
+ puts_wait_line(waiting_for_items)
67
+
68
+ until waiting_for_items.empty?
69
+ item_results.each do |result|
70
+ next if result[:complete]
71
+
72
+ if result[:thread].join(0.1)
73
+ result[:complete] = true
74
+ clear_line
75
+
76
+ heading_proc.call(result[:item])
77
+ puts result[:output]
78
+
79
+ waiting_for_items.delete(result[:item].name)
80
+ puts_wait_line(waiting_for_items) unless waiting_for_items.empty?
81
+ end
82
+ end
83
+ end
84
+
85
+ puts ''
86
+ errors = item_results.select { |item| item[:error] }.map { |item| item[:item].name }
87
+ puts_error "Command failed in #{errors.join(', ')}." unless errors.empty?
88
+ end
89
+
34
90
  private
35
91
  def colorize(text, color_code, bold = false)
36
92
  if bold
@@ -0,0 +1,37 @@
1
+ module GitBundle
2
+ class Project
3
+ attr_reader :main_repository, :dependant_repositories
4
+
5
+ def initialize
6
+ # TODO: Find out how to set Bundler's directory so that the directory can be an argument
7
+ @directory = Dir.getwd
8
+ @main_repository = GitBundle::Repository.new_main(File.basename(@directory), @directory)
9
+ end
10
+
11
+ def load_dependant_repositories(locked_branches: true)
12
+ @dependant_repositories = []
13
+
14
+ if Bundler.locked_gems
15
+ if locked_branches
16
+ specs = Bundler.locked_gems.specs
17
+ else
18
+ old_value = Bundler.settings[:disable_local_branch_check]
19
+ Bundler.settings[:disable_local_branch_check] = true
20
+ specs = Bundler.definition.specs
21
+ Bundler.settings[:disable_local_branch_check] = old_value
22
+ end
23
+
24
+ Bundler.settings.local_overrides.each do |name, path|
25
+ spec = specs.find { |s| s.name == name }
26
+ if spec && spec.source.respond_to?(:branch)
27
+ @dependant_repositories << GitBundle::Repository.new_dependant(spec.name, path, spec.source.branch, spec.source.revision)
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ def repositories
34
+ @dependant_repositories + [@main_repository]
35
+ end
36
+ end
37
+ end
@@ -1,8 +1,12 @@
1
1
  module GitBundle
2
2
  class Repository
3
+ include GitBundle::Shell
4
+
3
5
  attr_reader :name,
4
6
  :path,
5
- :main
7
+ :main,
8
+ :branch,
9
+ :locked_branch
6
10
 
7
11
  def self.new_main(name, path)
8
12
  GitBundle::Repository.new(name, path, true, nil, nil)
@@ -16,12 +20,13 @@ module GitBundle
16
20
  @name = name
17
21
  @path = path
18
22
  @main = main_repository
23
+ @branch = fetch_branch
19
24
  @locked_branch = locked_branch
20
25
  @locked_revision = locked_revision
21
26
  end
22
27
 
23
- def branch
24
- @branch ||= execute_git('rev-parse', '--abbrev-ref', 'HEAD').chomp
28
+ def fetch_branch
29
+ execute_git('rev-parse', '--abbrev-ref', 'HEAD').chomp
25
30
  end
26
31
 
27
32
  def locked_branch
@@ -40,6 +45,15 @@ module GitBundle
40
45
  revision != locked_revision
41
46
  end
42
47
 
48
+ def reference_exists?(reference)
49
+ execute_git('cat-file', '-e', reference)
50
+ $?.exitstatus == 0
51
+ end
52
+
53
+ def upstream_branch_exists?
54
+ reference_exists?("origin/#{branch}")
55
+ end
56
+
43
57
  def stale_commits
44
58
  execute_git('rev-list', '--pretty=oneline', '--abbrev-commit', "#{locked_revision}..#{revision}")
45
59
  end
@@ -48,6 +62,11 @@ module GitBundle
48
62
  execute_git('rev-list', '--pretty=oneline', '--abbrev-commit', '--count', "#{locked_revision}..#{revision}").to_i
49
63
  end
50
64
 
65
+ def commits_not_pushed?
66
+ return true unless upstream_branch_exists?
67
+ commits_not_pushed_count > 0
68
+ end
69
+
51
70
  def commits_not_pushed
52
71
  execute_git('rev-list', '--pretty=oneline', '--abbrev-commit', "origin/#{branch}..#{branch}")
53
72
  end
@@ -56,8 +75,14 @@ module GitBundle
56
75
  execute_git('rev-list', '--pretty=oneline', '--abbrev-commit', '--count', "origin/#{branch}..#{branch}").to_i
57
76
  end
58
77
 
59
- def push(args)
60
- puts execute_git('push', args)
78
+ def push(args, create_upstream: false)
79
+ args = args.dup + ['--set-upstream', 'origin', branch] if create_upstream
80
+ execute_git_output('push', args)
81
+ $?.exitstatus == 0
82
+ end
83
+
84
+ def checkout(args)
85
+ execute_git_output('checkout', args)
61
86
  $?.exitstatus == 0
62
87
  end
63
88
 
@@ -75,20 +100,23 @@ module GitBundle
75
100
  $?.exitstatus == 0
76
101
  end
77
102
 
78
- def execute_git(*args, **options)
103
+ def commit_with_description(message, description, *files)
104
+ execute_git('commit', '-m', message, '-m', description, files)
105
+ $?.exitstatus == 0
106
+ end
107
+
108
+ def git_command(*args, **options)
79
109
  git_command = ['git', '-C', @path]
80
110
  git_command += %w(-c color.status=always -c color.ui=always) if options.fetch(:color, false)
81
- git_command += args.flatten
82
- execute(*git_command)
111
+ git_command + args.flatten
83
112
  end
84
113
 
85
- def execute(*args)
86
- puts args.map{ |arg| "'#{arg}'" }.join(' ') if ENV['DEBUG'] == 'true'
114
+ def execute_git(*args, **options)
115
+ execute(*git_command(*args, **options))
116
+ end
87
117
 
88
- pipe_out, pipe_in = IO.pipe
89
- system *args, out: pipe_in, err: pipe_in
90
- pipe_in.close
91
- pipe_out.read
118
+ def execute_git_output(*args, **options)
119
+ execute_live(*git_command(*args, **options))
92
120
  end
93
121
  end
94
122
  end
@@ -0,0 +1,29 @@
1
+ require 'io/console'
2
+
3
+ module GitBundle
4
+ module Shell
5
+ def execute_pipe(*args)
6
+ puts args.map { |arg| "'#{arg}'" }.join(' ') if ENV['DEBUG'] == 'true'
7
+
8
+ pipe_out, pipe_in = IO.pipe
9
+ fork do
10
+ system *args, out: pipe_in, err: pipe_in
11
+ end
12
+ pipe_in.close
13
+ pipe_out
14
+ end
15
+
16
+ def execute_live(*args)
17
+ execute_pipe(*args).each_line { |line| puts line.chomp }
18
+ end
19
+
20
+ def execute(*args)
21
+ puts args.map { |arg| "'#{arg}'" }.join(' ') if ENV['DEBUG'] == 'true'
22
+
23
+ pipe_out, pipe_in = IO.pipe
24
+ system *args, out: pipe_in, err: pipe_in
25
+ pipe_in.close
26
+ pipe_out.read
27
+ end
28
+ end
29
+ end
@@ -1,3 +1,3 @@
1
1
  module GitBundle
2
- VERSION = '1.0.8'
2
+ VERSION = '1.0.9'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: git-bundle
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.8
4
+ version: 1.0.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pierre Pretorius
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-10-18 00:00:00.000000000 Z
11
+ date: 2018-08-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -46,8 +46,11 @@ files:
46
46
  - lib/git_bundle/cli.rb
47
47
  - lib/git_bundle/commands/generic.rb
48
48
  - lib/git_bundle/commands/push.rb
49
+ - lib/git_bundle/commands/version.rb
49
50
  - lib/git_bundle/console.rb
51
+ - lib/git_bundle/project.rb
50
52
  - lib/git_bundle/repository.rb
53
+ - lib/git_bundle/shell.rb
51
54
  - lib/git_bundle/version.rb
52
55
  homepage: https://github.com/EPI-USE-Labs/git-bundle
53
56
  licenses:
@@ -69,7 +72,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
69
72
  version: '0'
70
73
  requirements: []
71
74
  rubyforge_project:
72
- rubygems_version: 2.5.1
75
+ rubygems_version: 2.7.6
73
76
  signing_key:
74
77
  specification_version: 4
75
78
  summary: Simplifies working with gems from git repositories in combination with local