git-multirepo 1.0.0.beta49 → 1.0.0.beta50

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 (70) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +2 -2
  3. data/.gitbugtraq +3 -3
  4. data/.gitignore +38 -38
  5. data/.multirepo.meta +2 -2
  6. data/.rspec +2 -2
  7. data/.rubocop.yml +79 -79
  8. data/CHANGELOG.md +29 -25
  9. data/Gemfile +4 -4
  10. data/Gemfile.lock +42 -42
  11. data/LICENSE +22 -22
  12. data/README.md +154 -154
  13. data/Rakefile +1 -1
  14. data/bin/multi +11 -11
  15. data/docs/bug-repros/91565510-repro.sh +20 -20
  16. data/git-multirepo.gemspec +31 -31
  17. data/lib/git-multirepo.rb +3 -3
  18. data/lib/multirepo/commands/add-command.rb +51 -51
  19. data/lib/multirepo/commands/branch-command.rb +82 -82
  20. data/lib/multirepo/commands/checkout-command.rb +120 -120
  21. data/lib/multirepo/commands/clone-command.rb +68 -68
  22. data/lib/multirepo/commands/command.rb +90 -90
  23. data/lib/multirepo/commands/commands.rb +15 -0
  24. data/lib/multirepo/commands/do-command.rb +103 -103
  25. data/lib/multirepo/commands/graph-command.rb +43 -43
  26. data/lib/multirepo/commands/init-command.rb +121 -121
  27. data/lib/multirepo/commands/inspect-command.rb +39 -39
  28. data/lib/multirepo/commands/install-command.rb +153 -153
  29. data/lib/multirepo/commands/merge-command.rb +249 -225
  30. data/lib/multirepo/commands/open-command.rb +57 -57
  31. data/lib/multirepo/commands/remove-command.rb +48 -48
  32. data/lib/multirepo/commands/uninit-command.rb +18 -18
  33. data/lib/multirepo/commands/update-command.rb +106 -94
  34. data/lib/multirepo/config.rb +16 -16
  35. data/lib/multirepo/files/config-entry.rb +39 -39
  36. data/lib/multirepo/files/config-file.rb +46 -46
  37. data/lib/multirepo/files/lock-entry.rb +29 -29
  38. data/lib/multirepo/files/lock-file.rb +56 -56
  39. data/lib/multirepo/files/meta-file.rb +41 -41
  40. data/lib/multirepo/files/tracking-file.rb +9 -9
  41. data/lib/multirepo/files/tracking-files.rb +47 -47
  42. data/lib/multirepo/git/branch.rb +32 -32
  43. data/lib/multirepo/git/change.rb +11 -11
  44. data/lib/multirepo/git/commit.rb +7 -7
  45. data/lib/multirepo/git/git-runner.rb +56 -56
  46. data/lib/multirepo/git/git.rb +10 -10
  47. data/lib/multirepo/git/ref.rb +38 -38
  48. data/lib/multirepo/git/remote.rb +17 -17
  49. data/lib/multirepo/git/repo.rb +124 -124
  50. data/lib/multirepo/hooks/post-commit-hook.rb +23 -23
  51. data/lib/multirepo/hooks/pre-commit-hook.rb +35 -35
  52. data/lib/{info.rb → multirepo/info.rb} +5 -5
  53. data/lib/multirepo/logic/dependency.rb +6 -6
  54. data/lib/multirepo/logic/merge-descriptor.rb +95 -95
  55. data/lib/multirepo/logic/node.rb +72 -72
  56. data/lib/multirepo/logic/performer.rb +55 -55
  57. data/lib/multirepo/logic/revision-selector.rb +35 -35
  58. data/lib/multirepo/multirepo-exception.rb +6 -6
  59. data/lib/multirepo/utility/console.rb +52 -52
  60. data/lib/multirepo/utility/popen-runner.rb +27 -27
  61. data/lib/multirepo/utility/system-runner.rb +14 -14
  62. data/lib/multirepo/utility/utils.rb +95 -95
  63. data/lib/multirepo/utility/verbosity.rb +6 -6
  64. data/resources/.gitconfig +2 -2
  65. data/resources/post-commit +6 -6
  66. data/resources/pre-commit +6 -6
  67. data/spec/integration/init_spec.rb +19 -19
  68. data/spec/spec_helper.rb +89 -89
  69. metadata +33 -33
  70. data/lib/commands.rb +0 -15
@@ -1,55 +1,55 @@
1
- require "multirepo/files/config-file"
2
- require "multirepo/files/lock-file"
3
-
4
- require_relative "dependency"
5
-
6
- module MultiRepo
7
- class Performer
8
- def self.perform_main_repo_checkout(main_repo, ref_name, message = nil)
9
- # Make sure the main repo is clean before attempting a checkout
10
- unless main_repo.clean?
11
- fail MultiRepoException, "Can't checkout #{ref_name} because the main repo contains uncommitted changes"
12
- end
13
-
14
- # Checkout the specified ref
15
- unless main_repo.checkout(ref_name)
16
- fail MultiRepoException, "Couldn't perform checkout of main repo #{ref_name}!"
17
- end
18
-
19
- Console.log_substep(message || "Checked out main repo #{ref_name}")
20
-
21
- # After checkout, make sure we're working with a multirepo-enabled ref
22
- unless Utils.multirepo_tracked?(".")
23
- fail MultiRepoException, "Revision #{ref_name} is not tracked by multirepo!"
24
- end
25
- end
26
-
27
- def self.dependencies
28
- config_entries = ConfigFile.new(".").load_entries
29
- lock_entries = LockFile.new(".").load_entries
30
-
31
- dependencies = build_dependencies(config_entries, lock_entries)
32
- dependency_ordered_nodes = Node.new(".").ordered_descendants
33
-
34
- return dependency_ordered_nodes.map do |node|
35
- dependencies.find { |d| d.config_entry.path == node.path }
36
- end
37
- end
38
-
39
- def self.build_dependencies(config_entries, lock_entries)
40
- lock_entries.map do |lock_entry|
41
- config_entry = config_entry_for_lock_entry(config_entries, lock_entry)
42
-
43
- dependency = Dependency.new
44
- dependency.config_entry = config_entry
45
- dependency.lock_entry = lock_entry
46
-
47
- next dependency
48
- end
49
- end
50
-
51
- def self.config_entry_for_lock_entry(config_entries, lock_entry)
52
- config_entries.find { |config_entry| config_entry.id == lock_entry.id }
53
- end
54
- end
55
- end
1
+ require "multirepo/files/config-file"
2
+ require "multirepo/files/lock-file"
3
+
4
+ require_relative "dependency"
5
+
6
+ module MultiRepo
7
+ class Performer
8
+ def self.perform_main_repo_checkout(main_repo, ref_name, message = nil)
9
+ # Make sure the main repo is clean before attempting a checkout
10
+ unless main_repo.clean?
11
+ fail MultiRepoException, "Can't checkout #{ref_name} because the main repo contains uncommitted changes"
12
+ end
13
+
14
+ # Checkout the specified ref
15
+ unless main_repo.checkout(ref_name)
16
+ fail MultiRepoException, "Couldn't perform checkout of main repo #{ref_name}!"
17
+ end
18
+
19
+ Console.log_substep(message || "Checked out main repo #{ref_name}")
20
+
21
+ # After checkout, make sure we're working with a multirepo-enabled ref
22
+ unless Utils.multirepo_tracked?(".")
23
+ fail MultiRepoException, "Revision #{ref_name} is not tracked by multirepo!"
24
+ end
25
+ end
26
+
27
+ def self.dependencies
28
+ config_entries = ConfigFile.new(".").load_entries
29
+ lock_entries = LockFile.new(".").load_entries
30
+
31
+ dependencies = build_dependencies(config_entries, lock_entries)
32
+ dependency_ordered_nodes = Node.new(".").ordered_descendants
33
+
34
+ return dependency_ordered_nodes.map do |node|
35
+ dependencies.find { |d| d.config_entry.path == node.path }
36
+ end
37
+ end
38
+
39
+ def self.build_dependencies(config_entries, lock_entries)
40
+ lock_entries.map do |lock_entry|
41
+ config_entry = config_entry_for_lock_entry(config_entries, lock_entry)
42
+
43
+ dependency = Dependency.new
44
+ dependency.config_entry = config_entry
45
+ dependency.lock_entry = lock_entry
46
+
47
+ next dependency
48
+ end
49
+ end
50
+
51
+ def self.config_entry_for_lock_entry(config_entries, lock_entry)
52
+ config_entries.find { |config_entry| config_entry.id == lock_entry.id }
53
+ end
54
+ end
55
+ end
@@ -1,35 +1,35 @@
1
- module MultiRepo
2
- class RevisionSelectionMode
3
- AS_LOCK = 0
4
- LATEST = 1
5
- EXACT = 2
6
-
7
- def self.name_for_mode(mode)
8
- case mode
9
- when AS_LOCK then "as-lock"
10
- when LATEST then "latest"
11
- when EXACT then "exact"
12
- end
13
- end
14
- end
15
-
16
- class RevisionSelector
17
- def self.mode_for_args(checkout_latest, checkout_exact)
18
- if checkout_latest
19
- RevisionSelectionMode::LATEST
20
- elsif checkout_exact
21
- RevisionSelectionMode::EXACT
22
- else
23
- RevisionSelectionMode::AS_LOCK
24
- end
25
- end
26
-
27
- def self.revision_for_mode(mode, ref_name, lock_entry)
28
- case mode
29
- when RevisionSelectionMode::AS_LOCK then lock_entry.head
30
- when RevisionSelectionMode::LATEST then lock_entry.branch
31
- when RevisionSelectionMode::EXACT then ref_name
32
- end
33
- end
34
- end
35
- end
1
+ module MultiRepo
2
+ class RevisionSelectionMode
3
+ AS_LOCK = 0
4
+ LATEST = 1
5
+ EXACT = 2
6
+
7
+ def self.name_for_mode(mode)
8
+ case mode
9
+ when AS_LOCK then "as-lock"
10
+ when LATEST then "latest"
11
+ when EXACT then "exact"
12
+ end
13
+ end
14
+ end
15
+
16
+ class RevisionSelector
17
+ def self.mode_for_args(checkout_latest, checkout_exact)
18
+ if checkout_latest
19
+ RevisionSelectionMode::LATEST
20
+ elsif checkout_exact
21
+ RevisionSelectionMode::EXACT
22
+ else
23
+ RevisionSelectionMode::AS_LOCK
24
+ end
25
+ end
26
+
27
+ def self.revision_for_mode(mode, ref_name, lock_entry)
28
+ case mode
29
+ when RevisionSelectionMode::AS_LOCK then lock_entry.head
30
+ when RevisionSelectionMode::LATEST then lock_entry.branch
31
+ when RevisionSelectionMode::EXACT then ref_name
32
+ end
33
+ end
34
+ end
35
+ end
@@ -1,6 +1,6 @@
1
- require "claide/informative_error"
2
-
3
- module MultiRepo
4
- class MultiRepoException < StandardError
5
- end
6
- end
1
+ require "claide/informative_error"
2
+
3
+ module MultiRepo
4
+ class MultiRepoException < StandardError
5
+ end
6
+ end
@@ -1,52 +1,52 @@
1
- require "colored"
2
-
3
- module MultiRepo
4
- class Console
5
- def self.log_step(message)
6
- print_prefix
7
- puts $stdout.isatty ? message.bold.green : message
8
- end
9
-
10
- def self.log_substep(message)
11
- print_prefix
12
- puts $stdout.isatty ? message.blue : message
13
- end
14
-
15
- def self.log_info(message)
16
- print_prefix
17
- puts $stdout.isatty ? message.white : message
18
- end
19
-
20
- def self.log_warning(message)
21
- print_prefix
22
- puts $stdout.isatty ? message.yellow : message
23
- end
24
-
25
- def self.log_error(message)
26
- print_prefix
27
- puts $stdout.isatty ? message.red : message
28
- end
29
-
30
- def self.ask_yes_no(message)
31
- answered = false
32
- until answered
33
- print_prefix
34
- print message
35
- print " (y/n) "
36
-
37
- case $stdin.gets.strip.downcase
38
- when "y", "yes"
39
- answered = true
40
- return true
41
- when "n", "no"
42
- answered = true
43
- return false
44
- end
45
- end
46
- end
47
-
48
- def self.print_prefix
49
- print $stdout.isatty ? "> ".white : "[multirepo] "
50
- end
51
- end
52
- end
1
+ require "colored"
2
+
3
+ module MultiRepo
4
+ class Console
5
+ def self.log_step(message)
6
+ print_prefix
7
+ puts $stdout.isatty ? message.bold.green : message
8
+ end
9
+
10
+ def self.log_substep(message)
11
+ print_prefix
12
+ puts $stdout.isatty ? message.blue : message
13
+ end
14
+
15
+ def self.log_info(message)
16
+ print_prefix
17
+ puts $stdout.isatty ? message.white : message
18
+ end
19
+
20
+ def self.log_warning(message)
21
+ print_prefix
22
+ puts $stdout.isatty ? message.yellow : message
23
+ end
24
+
25
+ def self.log_error(message)
26
+ print_prefix
27
+ puts $stdout.isatty ? message.red : message
28
+ end
29
+
30
+ def self.ask(message)
31
+ answered = false
32
+ until answered
33
+ print_prefix
34
+ print message
35
+ print " (y/n) "
36
+
37
+ case $stdin.gets.strip.downcase
38
+ when "y", "yes"
39
+ answered = true
40
+ return true
41
+ when "n", "no"
42
+ answered = true
43
+ return false
44
+ end
45
+ end
46
+ end
47
+
48
+ def self.print_prefix
49
+ print $stdout.isatty ? "> ".white : "[multirepo] "
50
+ end
51
+ end
52
+ end
@@ -1,27 +1,27 @@
1
- require "open3"
2
-
3
- require "multirepo/utility/console"
4
-
5
- module MultiRepo
6
- class PopenRunner
7
- def self.run(cmd, verbosity)
8
- Console.log_info("Command: #{cmd}") if Config.instance.verbose
9
-
10
- lines = []
11
- last_command_succeeded = false
12
- Open3.popen2e(cmd) do |_stdin, stdout_and_stderr, thread|
13
- stdout_and_stderr.each do |line|
14
- print line if Config.instance.verbose
15
- lines << line
16
- end
17
- last_command_succeeded = thread.value.success?
18
- end
19
-
20
- output = lines.join("").rstrip
21
-
22
- Console.log_error(output) if !last_command_succeeded && verbosity == Verbosity::OUTPUT_ON_ERROR
23
-
24
- return output, last_command_succeeded
25
- end
26
- end
27
- end
1
+ require "open3"
2
+
3
+ require "multirepo/utility/console"
4
+
5
+ module MultiRepo
6
+ class PopenRunner
7
+ def self.run(cmd, verbosity)
8
+ Console.log_info("Command: #{cmd}") if Config.instance.verbose
9
+
10
+ lines = []
11
+ last_command_succeeded = false
12
+ Open3.popen2e(cmd) do |_stdin, stdout_and_stderr, thread|
13
+ stdout_and_stderr.each do |line|
14
+ print line if Config.instance.verbose
15
+ lines << line
16
+ end
17
+ last_command_succeeded = thread.value.success?
18
+ end
19
+
20
+ output = lines.join("").rstrip
21
+
22
+ Console.log_error(output) if !last_command_succeeded && verbosity == Verbosity::OUTPUT_ON_ERROR
23
+
24
+ return output, last_command_succeeded
25
+ end
26
+ end
27
+ end
@@ -1,14 +1,14 @@
1
- require "multirepo/utility/console"
2
-
3
- module MultiRepo
4
- class SystemRunner
5
- def self.run(cmd)
6
- Console.log_info("Command: #{cmd}") if Config.instance.verbose
7
-
8
- output = system(cmd)
9
- last_command_succeeded = ($?.exitstatus == 0)
10
-
11
- return output, last_command_succeeded
12
- end
13
- end
14
- end
1
+ require "multirepo/utility/console"
2
+
3
+ module MultiRepo
4
+ class SystemRunner
5
+ def self.run(cmd)
6
+ Console.log_info("Command: #{cmd}") if Config.instance.verbose
7
+
8
+ output = system(cmd)
9
+ last_command_succeeded = ($?.exitstatus == 0)
10
+
11
+ return output, last_command_succeeded
12
+ end
13
+ end
14
+ end
@@ -1,95 +1,95 @@
1
- require "multirepo/multirepo-exception"
2
- require "fileutils"
3
-
4
- module MultiRepo
5
- class Utils
6
- def self.path_for_resource(resource_name)
7
- gem_path = Gem::Specification.find_by_name("git-multirepo").gem_dir
8
- File.join(gem_path, "resources/#{resource_name}")
9
- end
10
-
11
- def self.multirepo_enabled?(path)
12
- File.exist?(File.join(path, ".multirepo"))
13
- end
14
-
15
- def self.multirepo_tracked?(path)
16
- multirepo_enabled?(path) && File.exist?(File.join(path, ".multirepo.lock"))
17
- end
18
-
19
- def self.install_hook(name, path)
20
- destination_path = File.join(path, ".git/hooks")
21
- destination_file = File.join(destination_path, name)
22
- FileUtils.cp(path_for_resource(name), destination_file)
23
- FileUtils.chmod(0755, destination_file) # -rwxr-xr-x
24
- end
25
-
26
- def self.sibling_repos
27
- sibling_directories = Dir['../*/']
28
- sibling_repos = sibling_directories.map{ |d| Repo.new(d) }.select(&:exists?)
29
- sibling_repos.delete_if{ |r| Pathname.new(r.path).realpath == Pathname.new(".").realpath }
30
- end
31
-
32
- def self.dependencies_clean?(config_entries)
33
- clean = true
34
- missing = false
35
- config_entries.each do |e|
36
- # Ensure the dependency exists
37
- unless e.repo.exists?
38
- Console.log_error("Dependency '#{e.path}' does not exist on disk")
39
- missing |= true
40
- next
41
- end
42
-
43
- # Ensure it contains no uncommitted changes
44
- dependency_clean = e.repo.clean?
45
- clean &= dependency_clean
46
- Console.log_warning("Dependency '#{e.repo.path}' contains uncommitted changes") unless dependency_clean
47
- end
48
-
49
- fail MultiRepoException, "Some dependencies are not present on this machine." \
50
- " Run \"multi install\" to clone missing dependencies." if missing
51
-
52
- return clean
53
- end
54
-
55
- def self.ensure_working_copies_clean(repos)
56
- clean = true
57
- repos.each do |repo|
58
- dependency_clean = repo.clean?
59
- clean &= dependency_clean
60
- Console.log_warning("Repo '#{repo.path}' contains uncommitted changes") unless dependency_clean
61
- end
62
- return clean
63
- end
64
-
65
- def self.convert_to_windows_path(unix_path)
66
- components = Pathname.new(unix_path).each_filename.to_a
67
- components.join(File::ALT_SEPARATOR)
68
- end
69
-
70
- def self.reveal_in_default_file_browser(unix_path)
71
- if OS.osx?
72
- system %(open "#{unix_path}")
73
- elsif OS.windows?
74
- system %(explorer "#{Utils.convert_to_windows_path(unix_path)}")
75
- end
76
- end
77
-
78
- def self.open_in_default_app(unix_path)
79
- if OS.osx?
80
- system %(open "#{unix_path}")
81
- elsif OS.windows?
82
- system %(cmd /c "start C:\\#{Utils.convert_to_windows_path(unix_path)}")
83
- end
84
- end
85
-
86
- def self.append_if_missing(path, pattern, string_to_append)
87
- if File.exist?(path)
88
- string_located = File.readlines(path).grep(pattern).any?
89
- File.open(path, 'a') { |f| f.puts(string_to_append) } unless string_located
90
- else
91
- File.open(path, 'w') { |f| f.puts(string_to_append) }
92
- end
93
- end
94
- end
95
- end
1
+ require "multirepo/multirepo-exception"
2
+ require "fileutils"
3
+
4
+ module MultiRepo
5
+ class Utils
6
+ def self.path_for_resource(resource_name)
7
+ gem_path = Gem::Specification.find_by_name("git-multirepo").gem_dir
8
+ File.join(gem_path, "resources/#{resource_name}")
9
+ end
10
+
11
+ def self.multirepo_enabled?(path)
12
+ File.exist?(File.join(path, ".multirepo"))
13
+ end
14
+
15
+ def self.multirepo_tracked?(path)
16
+ multirepo_enabled?(path) && File.exist?(File.join(path, ".multirepo.lock"))
17
+ end
18
+
19
+ def self.install_hook(name, path)
20
+ destination_path = File.join(path, ".git/hooks")
21
+ destination_file = File.join(destination_path, name)
22
+ FileUtils.cp(path_for_resource(name), destination_file)
23
+ FileUtils.chmod(0755, destination_file) # -rwxr-xr-x
24
+ end
25
+
26
+ def self.sibling_repos
27
+ sibling_directories = Dir['../*/']
28
+ sibling_repos = sibling_directories.map{ |d| Repo.new(d) }.select(&:exists?)
29
+ sibling_repos.delete_if{ |r| Pathname.new(r.path).realpath == Pathname.new(".").realpath }
30
+ end
31
+
32
+ def self.dependencies_clean?(config_entries)
33
+ clean = true
34
+ missing = false
35
+ config_entries.each do |e|
36
+ # Ensure the dependency exists
37
+ unless e.repo.exists?
38
+ Console.log_error("Dependency '#{e.path}' does not exist on disk")
39
+ missing |= true
40
+ next
41
+ end
42
+
43
+ # Ensure it contains no uncommitted changes
44
+ dependency_clean = e.repo.clean?
45
+ clean &= dependency_clean
46
+ Console.log_warning("Dependency '#{e.repo.path}' contains uncommitted changes") unless dependency_clean
47
+ end
48
+
49
+ fail MultiRepoException, "Some dependencies are not present on this machine." \
50
+ " Run \"multi install\" to clone missing dependencies." if missing
51
+
52
+ return clean
53
+ end
54
+
55
+ def self.ensure_working_copies_clean(repos)
56
+ clean = true
57
+ repos.each do |repo|
58
+ dependency_clean = repo.clean?
59
+ clean &= dependency_clean
60
+ Console.log_warning("Repo '#{repo.path}' contains uncommitted changes") unless dependency_clean
61
+ end
62
+ return clean
63
+ end
64
+
65
+ def self.convert_to_windows_path(unix_path)
66
+ components = Pathname.new(unix_path).each_filename.to_a
67
+ components.join(File::ALT_SEPARATOR)
68
+ end
69
+
70
+ def self.reveal_in_default_file_browser(unix_path)
71
+ if OS.osx?
72
+ system %(open "#{unix_path}")
73
+ elsif OS.windows?
74
+ system %(explorer "#{Utils.convert_to_windows_path(unix_path)}")
75
+ end
76
+ end
77
+
78
+ def self.open_in_default_app(unix_path)
79
+ if OS.osx?
80
+ system %(open "#{unix_path}")
81
+ elsif OS.windows?
82
+ system %(cmd /c "start C:\\#{Utils.convert_to_windows_path(unix_path)}")
83
+ end
84
+ end
85
+
86
+ def self.append_if_missing(path, pattern, string_to_append)
87
+ if File.exist?(path)
88
+ string_located = File.readlines(path).grep(pattern).any?
89
+ File.open(path, 'a') { |f| f.puts(string_to_append) } unless string_located
90
+ else
91
+ File.open(path, 'w') { |f| f.puts(string_to_append) }
92
+ end
93
+ end
94
+ end
95
+ end