git-bundle 1.0.8 → 1.0.9

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 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