git-multirepo 1.0.0.beta42 → 1.0.0.beta43

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 (64) 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/Gemfile +4 -4
  8. data/Gemfile.lock +42 -42
  9. data/LICENSE +22 -22
  10. data/README.md +143 -143
  11. data/Rakefile +2 -2
  12. data/bin/multi +10 -10
  13. data/docs/bug-repros/91565510-repro.sh +20 -20
  14. data/git-multirepo.gemspec +31 -31
  15. data/lib/commands.rb +13 -13
  16. data/lib/git-multirepo.rb +2 -2
  17. data/lib/info.rb +4 -4
  18. data/lib/multirepo/commands/add-command.rb +50 -50
  19. data/lib/multirepo/commands/branch-command.rb +81 -81
  20. data/lib/multirepo/commands/checkout-command.rb +119 -119
  21. data/lib/multirepo/commands/clone-command.rb +67 -67
  22. data/lib/multirepo/commands/command.rb +89 -89
  23. data/lib/multirepo/commands/do-command.rb +100 -100
  24. data/lib/multirepo/commands/graph-command.rb +42 -42
  25. data/lib/multirepo/commands/init-command.rb +119 -119
  26. data/lib/multirepo/commands/install-command.rb +106 -106
  27. data/lib/multirepo/commands/merge-command.rb +225 -225
  28. data/lib/multirepo/commands/open-command.rb +55 -55
  29. data/lib/multirepo/commands/remove-command.rb +47 -47
  30. data/lib/multirepo/commands/uninit-command.rb +17 -17
  31. data/lib/multirepo/commands/update-command.rb +55 -55
  32. data/lib/multirepo/config.rb +15 -15
  33. data/lib/multirepo/files/config-entry.rb +38 -38
  34. data/lib/multirepo/files/config-file.rb +45 -45
  35. data/lib/multirepo/files/lock-entry.rb +28 -28
  36. data/lib/multirepo/files/lock-file.rb +55 -55
  37. data/lib/multirepo/files/meta-file.rb +40 -40
  38. data/lib/multirepo/files/tracking-file.rb +8 -8
  39. data/lib/multirepo/files/tracking-files.rb +46 -46
  40. data/lib/multirepo/git/branch.rb +31 -31
  41. data/lib/multirepo/git/change.rb +10 -10
  42. data/lib/multirepo/git/commit.rb +6 -6
  43. data/lib/multirepo/git/git-runner.rb +46 -46
  44. data/lib/multirepo/git/git.rb +9 -9
  45. data/lib/multirepo/git/ref.rb +37 -37
  46. data/lib/multirepo/git/remote.rb +16 -16
  47. data/lib/multirepo/git/repo.rb +122 -122
  48. data/lib/multirepo/hooks/post-commit-hook.rb +22 -22
  49. data/lib/multirepo/hooks/pre-commit-hook.rb +34 -34
  50. data/lib/multirepo/logic/dependency.rb +5 -5
  51. data/lib/multirepo/logic/merge-descriptor.rb +94 -94
  52. data/lib/multirepo/logic/node.rb +71 -71
  53. data/lib/multirepo/logic/performer.rb +56 -56
  54. data/lib/multirepo/logic/revision-selector.rb +34 -34
  55. data/lib/multirepo/multirepo-exception.rb +5 -5
  56. data/lib/multirepo/utility/console.rb +51 -51
  57. data/lib/multirepo/utility/runner.rb +34 -34
  58. data/lib/multirepo/utility/utils.rb +94 -94
  59. data/resources/.gitconfig +2 -2
  60. data/resources/post-commit +5 -5
  61. data/resources/pre-commit +5 -5
  62. data/spec/integration/init_spec.rb +18 -18
  63. data/spec/spec_helper.rb +89 -89
  64. metadata +2 -2
@@ -1,57 +1,57 @@
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
- raise 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
- raise 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.is_multirepo_tracked(".")
23
- raise 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
- pair = dependencies.find { |d| d.config_entry.path == node.path }
36
- end
37
- end
38
-
39
- private
40
-
41
- def self.build_dependencies(config_entries, lock_entries)
42
- lock_entries.map do |lock_entry|
43
- config_entry = config_entry_for_lock_entry(config_entries, lock_entry)
44
-
45
- dependency = Dependency.new
46
- dependency.config_entry = config_entry
47
- dependency.lock_entry = lock_entry
48
-
49
- next dependency
50
- end
51
- end
52
-
53
- def self.config_entry_for_lock_entry(config_entries, lock_entry)
54
- config_entries.find { |config_entry| config_entry.id == lock_entry.id }
55
- end
56
- 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
+ raise 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
+ raise 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.is_multirepo_tracked(".")
23
+ raise 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
+ pair = dependencies.find { |d| d.config_entry.path == node.path }
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ def self.build_dependencies(config_entries, lock_entries)
42
+ lock_entries.map do |lock_entry|
43
+ config_entry = config_entry_for_lock_entry(config_entries, lock_entry)
44
+
45
+ dependency = Dependency.new
46
+ dependency.config_entry = config_entry
47
+ dependency.lock_entry = lock_entry
48
+
49
+ next dependency
50
+ end
51
+ end
52
+
53
+ def self.config_entry_for_lock_entry(config_entries, lock_entry)
54
+ config_entries.find { |config_entry| config_entry.id == lock_entry.id }
55
+ end
56
+ end
57
57
  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; "as-lock"
10
- when LATEST; "latest"
11
- when EXACT; "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 then
19
- RevisionSelectionMode::LATEST
20
- elsif checkout_exact then
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; lock_entry.head
30
- when RevisionSelectionMode::LATEST; lock_entry.branch
31
- when RevisionSelectionMode::EXACT; ref_name
32
- end
33
- end
34
- 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; "as-lock"
10
+ when LATEST; "latest"
11
+ when EXACT; "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 then
19
+ RevisionSelectionMode::LATEST
20
+ elsif checkout_exact then
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; lock_entry.head
30
+ when RevisionSelectionMode::LATEST; lock_entry.branch
31
+ when RevisionSelectionMode::EXACT; ref_name
32
+ end
33
+ end
34
+ end
35
35
  end
@@ -1,6 +1,6 @@
1
- require "claide/informative_error"
2
-
3
- module MultiRepo
4
- class MultiRepoException < StandardError
5
- end
1
+ require "claide/informative_error"
2
+
3
+ module MultiRepo
4
+ class MultiRepoException < StandardError
5
+ end
6
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
- while !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
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
+ while !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
52
  end
@@ -1,35 +1,35 @@
1
- require "open3"
2
- require "multirepo/utility/console"
3
-
4
- module MultiRepo
5
- class Runner
6
- class Verbosity
7
- OUTPUT_NEVER = 0
8
- OUTPUT_ALWAYS = 1
9
- OUTPUT_ON_ERROR = 2
10
- end
11
-
12
- class << self
13
- attr_accessor :last_command_succeeded
14
- end
15
-
16
- def self.run(cmd, verbosity)
17
- Console.log_info("Command: #{cmd}") if Config.instance.verbose
18
-
19
- lines = []
20
- Open3.popen2e(cmd) do |stdin, stdout_and_stderr, thread|
21
- stdout_and_stderr.each do |line|
22
- Console.log_info("#{line.rstrip}") if verbosity == Verbosity::OUTPUT_ALWAYS || Config.instance.verbose
23
- lines << line
24
- end
25
- @last_command_succeeded = thread.value.success?
26
- end
27
-
28
- output = lines.join("").rstrip
29
-
30
- Console.log_error(output) if !@last_command_succeeded && verbosity == Verbosity::OUTPUT_ON_ERROR
31
-
32
- return output
33
- end
34
- end
1
+ require "open3"
2
+ require "multirepo/utility/console"
3
+
4
+ module MultiRepo
5
+ class Runner
6
+ class Verbosity
7
+ OUTPUT_NEVER = 0
8
+ OUTPUT_ALWAYS = 1
9
+ OUTPUT_ON_ERROR = 2
10
+ end
11
+
12
+ class << self
13
+ attr_accessor :last_command_succeeded
14
+ end
15
+
16
+ def self.run(cmd, verbosity)
17
+ Console.log_info("Command: #{cmd}") if Config.instance.verbose
18
+
19
+ lines = []
20
+ Open3.popen2e(cmd) do |stdin, stdout_and_stderr, thread|
21
+ stdout_and_stderr.each do |line|
22
+ Console.log_info("#{line.rstrip}") if verbosity == Verbosity::OUTPUT_ALWAYS || Config.instance.verbose
23
+ lines << line
24
+ end
25
+ @last_command_succeeded = thread.value.success?
26
+ end
27
+
28
+ output = lines.join("").rstrip
29
+
30
+ Console.log_error(output) if !@last_command_succeeded && verbosity == Verbosity::OUTPUT_ON_ERROR
31
+
32
+ return output
33
+ end
34
+ end
35
35
  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.is_multirepo_enabled(path)
12
- File.exists?(File.join(path, ".multirepo"))
13
- end
14
-
15
- def self.is_multirepo_tracked(path)
16
- is_multirepo_enabled(path) && File.exists?(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{ |r| r.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
- raise 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
- unless File.exists?(path)
88
- File.open(path, 'w') { |f| f.puts(string_to_append) }
89
- else
90
- string_located = File.readlines(path).grep(pattern).any?
91
- File.open(path, 'a') { |f| f.puts(string_to_append) } unless string_located
92
- end
93
- end
94
- 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.is_multirepo_enabled(path)
12
+ File.exists?(File.join(path, ".multirepo"))
13
+ end
14
+
15
+ def self.is_multirepo_tracked(path)
16
+ is_multirepo_enabled(path) && File.exists?(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{ |r| r.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
+ raise 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
+ unless File.exists?(path)
88
+ File.open(path, 'w') { |f| f.puts(string_to_append) }
89
+ else
90
+ string_located = File.readlines(path).grep(pattern).any?
91
+ File.open(path, 'a') { |f| f.puts(string_to_append) } unless string_located
92
+ end
93
+ end
94
+ end
95
95
  end