git-multirepo 1.0.0.beta70 → 1.0.0.beta71

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 (72) hide show
  1. checksums.yaml +5 -5
  2. data/.gitattributes +4 -4
  3. data/.gitbugtraq +3 -3
  4. data/.gitignore +38 -38
  5. data/.rspec +2 -2
  6. data/.rubocop.yml +79 -79
  7. data/CHANGELOG.md +116 -112
  8. data/Gemfile +4 -4
  9. data/Gemfile.lock +47 -47
  10. data/LICENSE +22 -22
  11. data/README.md +178 -178
  12. data/Rakefile +1 -1
  13. data/bin/multi +11 -11
  14. data/docs/bug-repros/91565510-repro.sh +20 -20
  15. data/git-multirepo.gemspec +31 -31
  16. data/lib/git-multirepo.rb +3 -3
  17. data/lib/multirepo/commands/add-command.rb +55 -55
  18. data/lib/multirepo/commands/branch-command.rb +88 -88
  19. data/lib/multirepo/commands/checkout-command.rb +127 -127
  20. data/lib/multirepo/commands/clone-command.rb +68 -68
  21. data/lib/multirepo/commands/command.rb +87 -87
  22. data/lib/multirepo/commands/commands.rb +14 -14
  23. data/lib/multirepo/commands/do-command.rb +101 -101
  24. data/lib/multirepo/commands/init-command.rb +121 -121
  25. data/lib/multirepo/commands/inspect-command.rb +48 -48
  26. data/lib/multirepo/commands/install-command.rb +170 -170
  27. data/lib/multirepo/commands/merge-command.rb +249 -249
  28. data/lib/multirepo/commands/open-command.rb +55 -55
  29. data/lib/multirepo/commands/remove-command.rb +48 -48
  30. data/lib/multirepo/commands/uninit-command.rb +18 -18
  31. data/lib/multirepo/commands/update-command.rb +112 -112
  32. data/lib/multirepo/config.rb +19 -19
  33. data/lib/multirepo/files/config-entry.rb +39 -39
  34. data/lib/multirepo/files/config-file.rb +52 -52
  35. data/lib/multirepo/files/lock-entry.rb +29 -29
  36. data/lib/multirepo/files/lock-file.rb +62 -62
  37. data/lib/multirepo/files/meta-file.rb +51 -51
  38. data/lib/multirepo/files/tracking-file.rb +9 -9
  39. data/lib/multirepo/files/tracking-files.rb +64 -64
  40. data/lib/multirepo/git/branch.rb +32 -32
  41. data/lib/multirepo/git/change.rb +11 -11
  42. data/lib/multirepo/git/commit.rb +7 -7
  43. data/lib/multirepo/git/git-runner.rb +56 -56
  44. data/lib/multirepo/git/git.rb +10 -10
  45. data/lib/multirepo/git/ref.rb +38 -38
  46. data/lib/multirepo/git/remote.rb +17 -17
  47. data/lib/multirepo/git/repo.rb +131 -131
  48. data/lib/multirepo/hooks/post-commit-hook.rb +23 -23
  49. data/lib/multirepo/hooks/pre-commit-hook.rb +35 -35
  50. data/lib/multirepo/info.rb +5 -5
  51. data/lib/multirepo/logic/dependency.rb +6 -6
  52. data/lib/multirepo/logic/merge-descriptor.rb +95 -95
  53. data/lib/multirepo/logic/node.rb +75 -75
  54. data/lib/multirepo/logic/performer.rb +62 -62
  55. data/lib/multirepo/logic/repo-selection.rb +25 -25
  56. data/lib/multirepo/logic/revision-selection.rb +15 -15
  57. data/lib/multirepo/logic/revision-selector.rb +23 -23
  58. data/lib/multirepo/logic/version-comparer.rb +10 -10
  59. data/lib/multirepo/multirepo-exception.rb +6 -6
  60. data/lib/multirepo/output/extra-output.rb +12 -12
  61. data/lib/multirepo/output/teamcity-extra-output.rb +11 -11
  62. data/lib/multirepo/utility/console.rb +52 -52
  63. data/lib/multirepo/utility/popen-runner.rb +27 -27
  64. data/lib/multirepo/utility/system-runner.rb +14 -14
  65. data/lib/multirepo/utility/utils.rb +107 -107
  66. data/lib/multirepo/utility/verbosity.rb +6 -6
  67. data/resources/.gitconfig +2 -2
  68. data/resources/post-commit +0 -0
  69. data/resources/pre-commit +0 -0
  70. data/spec/integration/init_spec.rb +19 -19
  71. data/spec/spec_helper.rb +89 -89
  72. metadata +3 -3
@@ -1,68 +1,68 @@
1
- require "multirepo/utility/console"
2
- require "multirepo/utility/utils"
3
- require "multirepo/git/repo"
4
- require_relative "install-command"
5
-
6
- module MultiRepo
7
- class CloneCommand < Command
8
- self.command = "clone"
9
- self.summary = "Clones the specified repository in a subfolder, then installs it."
10
-
11
- def self.options
12
- [
13
- ['<url>', 'The repository to clone.'],
14
- ['<name>', 'The name of the containing folder that will be created.'],
15
- ['[<refname>]', 'The branch, tag or commit id to checkout. Checkout will use "master" if unspecified.']
16
- ].concat(super)
17
- end
18
-
19
- def initialize(argv)
20
- @url = argv.shift_argument
21
- @name = argv.shift_argument
22
- @ref_name = argv.shift_argument || "master"
23
- super
24
- end
25
-
26
- def validate!
27
- super
28
- help! "You must specify a repository to clone" unless @url
29
- help! "You must specify a containing folder name" unless @name
30
- end
31
-
32
- def run
33
- Console.log_step("Cloning #{@url} ...")
34
-
35
- fail MultiRepoException, "A directory named #{@name} already exists" if Dir.exist?(@name)
36
-
37
- main_repo_path = "#{@name}/#{@name}"
38
- main_repo = Repo.new(main_repo_path)
39
-
40
- # Recursively create the directory where we'll clone the main repo
41
- FileUtils.mkpath(main_repo_path)
42
-
43
- # Clone the specified remote in the just-created directory
44
- fail MultiRepoException, "Could not clone repo from #{@url}" unless main_repo.clone(@url)
45
-
46
- # Checkout the specified main repo ref so that install reads the proper config file
47
- unless main_repo.checkout(@ref_name)
48
- fail MultiRepoException, "Couldn't perform checkout of main repo #{@ref_name}!"
49
- end
50
-
51
- Console.log_substep("Checked out main repo #{@ref_name}")
52
-
53
- # Make sure the ref we just checked out is tracked by multirepo
54
- unless Utils.multirepo_tracked?(main_repo_path)
55
- fail MultiRepoException, "Ref #{@ref_name} is not tracked by multirepo"
56
- end
57
-
58
- # Install
59
- original_path = Dir.pwd
60
- Dir.chdir(main_repo_path)
61
- install_command = InstallCommand.new(CLAide::ARGV.new([]))
62
- install_command.full_install
63
- Dir.chdir(original_path)
64
-
65
- Console.log_step("Done!")
66
- end
67
- end
68
- end
1
+ require "multirepo/utility/console"
2
+ require "multirepo/utility/utils"
3
+ require "multirepo/git/repo"
4
+ require_relative "install-command"
5
+
6
+ module MultiRepo
7
+ class CloneCommand < Command
8
+ self.command = "clone"
9
+ self.summary = "Clones the specified repository in a subfolder, then installs it."
10
+
11
+ def self.options
12
+ [
13
+ ['<url>', 'The repository to clone.'],
14
+ ['<name>', 'The name of the containing folder that will be created.'],
15
+ ['[<refname>]', 'The branch, tag or commit id to checkout. Checkout will use "master" if unspecified.']
16
+ ].concat(super)
17
+ end
18
+
19
+ def initialize(argv)
20
+ @url = argv.shift_argument
21
+ @name = argv.shift_argument
22
+ @ref_name = argv.shift_argument || "master"
23
+ super
24
+ end
25
+
26
+ def validate!
27
+ super
28
+ help! "You must specify a repository to clone" unless @url
29
+ help! "You must specify a containing folder name" unless @name
30
+ end
31
+
32
+ def run
33
+ Console.log_step("Cloning #{@url} ...")
34
+
35
+ fail MultiRepoException, "A directory named #{@name} already exists" if Dir.exist?(@name)
36
+
37
+ main_repo_path = "#{@name}"
38
+ main_repo = Repo.new(main_repo_path)
39
+
40
+ # Recursively create the directory where we'll clone the main repo
41
+ FileUtils.mkpath(main_repo_path)
42
+
43
+ # Clone the specified remote in the just-created directory
44
+ fail MultiRepoException, "Could not clone repo from #{@url}" unless main_repo.clone(@url)
45
+
46
+ # Checkout the specified main repo ref so that install reads the proper config file
47
+ unless main_repo.checkout(@ref_name)
48
+ fail MultiRepoException, "Couldn't perform checkout of main repo #{@ref_name}!"
49
+ end
50
+
51
+ Console.log_substep("Checked out main repo #{@ref_name}")
52
+
53
+ # Make sure the ref we just checked out is tracked by multirepo
54
+ unless Utils.multirepo_tracked?(main_repo_path)
55
+ fail MultiRepoException, "Ref #{@ref_name} is not tracked by multirepo"
56
+ end
57
+
58
+ # Install
59
+ original_path = Dir.pwd
60
+ Dir.chdir(main_repo_path)
61
+ install_command = InstallCommand.new(CLAide::ARGV.new([]))
62
+ install_command.full_install
63
+ Dir.chdir(original_path)
64
+
65
+ Console.log_step("Done!")
66
+ end
67
+ end
68
+ end
@@ -1,87 +1,87 @@
1
- require "claide"
2
-
3
- require "multirepo/info"
4
- require "multirepo/multirepo-exception"
5
- require "multirepo/config"
6
- require "multirepo/files/config-file"
7
- require "multirepo/files/lock-file"
8
-
9
- module MultiRepo
10
- class Command < CLAide::Command
11
- self.abstract_command = true
12
- self.command = "multi"
13
- self.version = VERSION
14
- self.description = DESCRIPTION
15
-
16
- def self.report_error(exception)
17
- if exception.instance_of?(MultiRepoException)
18
- Console.log_error(exception.message)
19
- exit 1
20
- end
21
- fail exception
22
- end
23
-
24
- def initialize(argv)
25
- @argv = argv
26
- Config.instance.verbose |= argv.flag?("verbose") ? true : false
27
- Config.instance.extra_output ||= argv.option("extra-output")
28
- Config.instance.git_executable ||= argv.option("git-exe", "git")
29
- super
30
- end
31
-
32
- def run
33
- help!
34
- end
35
-
36
- def validate!
37
- super
38
- path = Config.instance.git_executable
39
- is_git_exe = path =~ /.*(git)|(git.exe)$/
40
- file_exists = path == "git" || File.exist?(path)
41
- help! "Invalid git executable '#{path}'" unless is_git_exe && file_exists
42
- end
43
-
44
- def install_hooks(path)
45
- actual_path = path || "."
46
- Utils.install_hook("pre-commit", actual_path)
47
- Utils.install_hook("post-commit", actual_path)
48
- end
49
-
50
- def uninstall_hooks
51
- FileUtils.rm_f(".git/hooks/pre-commit")
52
- FileUtils.rm_f(".git/hooks/post-commit")
53
- end
54
-
55
- def update_gitconfig(path)
56
- actual_path = path || "."
57
- resource_file = Utils.path_for_resource(".gitconfig")
58
- target_file = File.join(actual_path, '.git/config')
59
-
60
- template = File.read(resource_file)
61
- first_template_line = template.lines.first
62
-
63
- Utils.append_if_missing(target_file, Regexp.new(Regexp.quote(first_template_line)), template)
64
- end
65
-
66
- def multirepo_enabled_dependencies
67
- ConfigFile.new(".").load_entries.select { |e| Utils.multirepo_enabled?(e.repo.path) }
68
- end
69
-
70
- def ensure_in_work_tree
71
- repo = Repo.new(".")
72
- fail MultiRepoException, "Not a git repository" unless repo.exists?
73
- fail MultiRepoException, "HEAD is unborn (you must perform at least one commit)" unless repo.head_born?
74
- end
75
-
76
- def ensure_multirepo_enabled
77
- fail MultiRepoException, "multirepo is not initialized in this repository." unless Utils.multirepo_enabled?(".")
78
- end
79
-
80
- def ensure_multirepo_tracked
81
- fail MultiRepoException, "Revision is not tracked by multirepo." unless Utils.multirepo_tracked?(".")
82
-
83
- lock_file_valid = LockFile.new(".").validate!
84
- fail MultiRepoException, "Revision is multirepo-enabled but contains a corrupted lock file!" unless lock_file_valid
85
- end
86
- end
87
- end
1
+ require "claide"
2
+
3
+ require "multirepo/info"
4
+ require "multirepo/multirepo-exception"
5
+ require "multirepo/config"
6
+ require "multirepo/files/config-file"
7
+ require "multirepo/files/lock-file"
8
+
9
+ module MultiRepo
10
+ class Command < CLAide::Command
11
+ self.abstract_command = true
12
+ self.command = "multi"
13
+ self.version = VERSION
14
+ self.description = DESCRIPTION
15
+
16
+ def self.report_error(exception)
17
+ if exception.instance_of?(MultiRepoException)
18
+ Console.log_error(exception.message)
19
+ exit 1
20
+ end
21
+ fail exception
22
+ end
23
+
24
+ def initialize(argv)
25
+ @argv = argv
26
+ Config.instance.verbose |= argv.flag?("verbose") ? true : false
27
+ Config.instance.extra_output ||= argv.option("extra-output")
28
+ Config.instance.git_executable ||= argv.option("git-exe", "git")
29
+ super
30
+ end
31
+
32
+ def run
33
+ help!
34
+ end
35
+
36
+ def validate!
37
+ super
38
+ path = Config.instance.git_executable
39
+ is_git_exe = path =~ /.*(git)|(git.exe)$/
40
+ file_exists = path == "git" || File.exist?(path)
41
+ help! "Invalid git executable '#{path}'" unless is_git_exe && file_exists
42
+ end
43
+
44
+ def install_hooks(path)
45
+ actual_path = path || "."
46
+ Utils.install_hook("pre-commit", actual_path)
47
+ Utils.install_hook("post-commit", actual_path)
48
+ end
49
+
50
+ def uninstall_hooks
51
+ FileUtils.rm_f(".git/hooks/pre-commit")
52
+ FileUtils.rm_f(".git/hooks/post-commit")
53
+ end
54
+
55
+ def update_gitconfig(path)
56
+ actual_path = path || "."
57
+ resource_file = Utils.path_for_resource(".gitconfig")
58
+ target_file = File.join(actual_path, '.git/config')
59
+
60
+ template = File.read(resource_file)
61
+ first_template_line = template.lines.first
62
+
63
+ Utils.append_if_missing(target_file, Regexp.new(Regexp.quote(first_template_line)), template)
64
+ end
65
+
66
+ def multirepo_enabled_dependencies
67
+ ConfigFile.new(".").load_entries.select { |e| Utils.multirepo_enabled?(e.repo.path) }
68
+ end
69
+
70
+ def ensure_in_work_tree
71
+ repo = Repo.new(".")
72
+ fail MultiRepoException, "Not a git repository" unless repo.exists?
73
+ fail MultiRepoException, "HEAD is unborn (you must perform at least one commit)" unless repo.head_born?
74
+ end
75
+
76
+ def ensure_multirepo_enabled
77
+ fail MultiRepoException, "multirepo is not initialized in this repository." unless Utils.multirepo_enabled?(".")
78
+ end
79
+
80
+ def ensure_multirepo_tracked
81
+ fail MultiRepoException, "Revision is not tracked by multirepo." unless Utils.multirepo_tracked?(".")
82
+
83
+ lock_file_valid = LockFile.new(".").validate!
84
+ fail MultiRepoException, "Revision is multirepo-enabled but contains a corrupted lock file!" unless lock_file_valid
85
+ end
86
+ end
87
+ end
@@ -1,14 +1,14 @@
1
- require_relative "command"
2
- require_relative "add-command"
3
- require_relative "branch-command"
4
- require_relative "checkout-command"
5
- require_relative "clone-command"
6
- require_relative "do-command"
7
- require_relative "init-command"
8
- require_relative "inspect-command"
9
- require_relative "install-command"
10
- require_relative "merge-command"
11
- require_relative "open-command"
12
- require_relative "remove-command"
13
- require_relative "uninit-command"
14
- require_relative "update-command"
1
+ require_relative "command"
2
+ require_relative "add-command"
3
+ require_relative "branch-command"
4
+ require_relative "checkout-command"
5
+ require_relative "clone-command"
6
+ require_relative "do-command"
7
+ require_relative "init-command"
8
+ require_relative "inspect-command"
9
+ require_relative "install-command"
10
+ require_relative "merge-command"
11
+ require_relative "open-command"
12
+ require_relative "remove-command"
13
+ require_relative "uninit-command"
14
+ require_relative "update-command"
@@ -1,101 +1,101 @@
1
- require_relative "command"
2
- require "multirepo/utility/console"
3
- require "multirepo/utility/utils"
4
- require "multirepo/files/config-file"
5
- require "multirepo/git/repo"
6
- require "multirepo/git/git-runner"
7
- require "multirepo/logic/performer"
8
- require "multirepo/logic/repo-selection"
9
-
10
- module MultiRepo
11
- class DoCommand < Command
12
- self.command = "do"
13
- self.summary = "Perform an arbitrary Git operation in the main repository, dependency repositories or all repositories."
14
-
15
- def self.options
16
- [
17
- ['"<operation>"', 'The git command to perform, between quotes, omitting the executable name (ex: "reset --hard HEAD")'],
18
- ['[--main]', 'Perform the operation in the main repository only.'],
19
- ['[--deps]', 'Perform the operation in dependencies only.'],
20
- ['[--all]', 'Perform the operation in the main repository and all dependencies.']
21
- ].concat(super)
22
- end
23
-
24
- def initialize(argv)
25
- @operation = argv.shift_argument
26
- @repo_selection = RepoSelection.new(argv)
27
- super
28
- end
29
-
30
- def validate!
31
- super
32
- help! "You must provide a git operation to perform" unless @operation
33
- help! "You can't provide more than one operation modifier (--deps, --main, etc.)" unless @repo_selection.valid?
34
- end
35
-
36
- def run
37
- ensure_in_work_tree
38
- ensure_multirepo_enabled
39
-
40
- @operation = @operation.sub(/^git /, "")
41
-
42
- success = true
43
- case @repo_selection.value
44
- when RepoSelection::MAIN
45
- confirm_main_repo_operation
46
- success &= perform_operation_on_main(@operation)
47
- when RepoSelection::DEPS
48
- confirm_dependencies_operation
49
- success &= perform_operation_on_dependencies(@operation)
50
- when RepoSelection::ALL
51
- confirm_main_repo_operation
52
- confirm_dependencies_operation
53
- success &= perform_operation_on_dependencies(@operation) # Ordered dependencies first
54
- success &= perform_operation_on_main(@operation) # Main last
55
- end
56
-
57
- Console.log_warning("Some operations finished with non-zero exit status. Please review the above.") unless success
58
- end
59
-
60
- def perform_operation_on_main(operation)
61
- perform_operation(".", operation)
62
- end
63
-
64
- def perform_operation_on_dependencies(operation)
65
- success = true
66
- Performer.depth_ordered_dependencies.each do |dependency|
67
- success &= perform_operation(dependency.config_entry.repo.path, operation)
68
- end
69
- return success
70
- end
71
-
72
- def perform_operation(path, operation)
73
- Console.log_step("Performing operation on '#{path}'")
74
- GitRunner.run_as_system(path, operation)
75
- GitRunner.last_command_succeeded
76
- end
77
-
78
- def confirm_main_repo_operation
79
- unless main_repo_clean?
80
- Console.log_warning("Main repo contains uncommitted changes")
81
- fail MultiRepoException, "Aborted" unless Console.ask("Proceed anyway?")
82
- end
83
- end
84
-
85
- def confirm_dependencies_operation
86
- unless dependencies_clean?
87
- Console.log_warning("Some dependencies contain uncommitted changes")
88
- fail MultiRepoException, "Aborted" unless Console.ask("Proceed anyway?")
89
- end
90
- end
91
-
92
- def main_repo_clean?
93
- Repo.new(".").clean?
94
- end
95
-
96
- def dependencies_clean?
97
- config_entries = ConfigFile.new(".").load_entries
98
- return Utils.dependencies_clean?(config_entries)
99
- end
100
- end
101
- end
1
+ require_relative "command"
2
+ require "multirepo/utility/console"
3
+ require "multirepo/utility/utils"
4
+ require "multirepo/files/config-file"
5
+ require "multirepo/git/repo"
6
+ require "multirepo/git/git-runner"
7
+ require "multirepo/logic/performer"
8
+ require "multirepo/logic/repo-selection"
9
+
10
+ module MultiRepo
11
+ class DoCommand < Command
12
+ self.command = "do"
13
+ self.summary = "Perform an arbitrary Git operation in the main repository, dependency repositories or all repositories."
14
+
15
+ def self.options
16
+ [
17
+ ['"<operation>"', 'The git command to perform, between quotes, omitting the executable name (ex: "reset --hard HEAD")'],
18
+ ['[--main]', 'Perform the operation in the main repository only.'],
19
+ ['[--deps]', 'Perform the operation in dependencies only.'],
20
+ ['[--all]', 'Perform the operation in the main repository and all dependencies.']
21
+ ].concat(super)
22
+ end
23
+
24
+ def initialize(argv)
25
+ @operation = argv.shift_argument
26
+ @repo_selection = RepoSelection.new(argv)
27
+ super
28
+ end
29
+
30
+ def validate!
31
+ super
32
+ help! "You must provide a git operation to perform" unless @operation
33
+ help! "You can't provide more than one operation modifier (--deps, --main, etc.)" unless @repo_selection.valid?
34
+ end
35
+
36
+ def run
37
+ ensure_in_work_tree
38
+ ensure_multirepo_enabled
39
+
40
+ @operation = @operation.sub(/^git /, "")
41
+
42
+ success = true
43
+ case @repo_selection.value
44
+ when RepoSelection::MAIN
45
+ confirm_main_repo_operation
46
+ success &= perform_operation_on_main(@operation)
47
+ when RepoSelection::DEPS
48
+ confirm_dependencies_operation
49
+ success &= perform_operation_on_dependencies(@operation)
50
+ when RepoSelection::ALL
51
+ confirm_main_repo_operation
52
+ confirm_dependencies_operation
53
+ success &= perform_operation_on_dependencies(@operation) # Ordered dependencies first
54
+ success &= perform_operation_on_main(@operation) # Main last
55
+ end
56
+
57
+ Console.log_warning("Some operations finished with non-zero exit status. Please review the above.") unless success
58
+ end
59
+
60
+ def perform_operation_on_main(operation)
61
+ perform_operation(".", operation)
62
+ end
63
+
64
+ def perform_operation_on_dependencies(operation)
65
+ success = true
66
+ Performer.depth_ordered_dependencies.each do |dependency|
67
+ success &= perform_operation(dependency.config_entry.repo.path, operation)
68
+ end
69
+ return success
70
+ end
71
+
72
+ def perform_operation(path, operation)
73
+ Console.log_step("Performing operation on '#{path}'")
74
+ GitRunner.run_as_system(path, operation)
75
+ GitRunner.last_command_succeeded
76
+ end
77
+
78
+ def confirm_main_repo_operation
79
+ unless main_repo_clean?
80
+ Console.log_warning("Main repo contains uncommitted changes")
81
+ fail MultiRepoException, "Aborted" unless Console.ask("Proceed anyway?")
82
+ end
83
+ end
84
+
85
+ def confirm_dependencies_operation
86
+ unless dependencies_clean?
87
+ Console.log_warning("Some dependencies contain uncommitted changes")
88
+ fail MultiRepoException, "Aborted" unless Console.ask("Proceed anyway?")
89
+ end
90
+ end
91
+
92
+ def main_repo_clean?
93
+ Repo.new(".").clean?
94
+ end
95
+
96
+ def dependencies_clean?
97
+ config_entries = ConfigFile.new(".").load_entries
98
+ return Utils.dependencies_clean?(config_entries)
99
+ end
100
+ end
101
+ end