git-multirepo 1.0.0.beta49 → 1.0.0.beta50

Sign up to get free protection for your applications and to get access to all the features.
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,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}/#{@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,90 +1,90 @@
1
- require "claide"
2
-
3
- require "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.git_executable = argv.option("git-exe", "git")
28
- super
29
- end
30
-
31
- def run
32
- help!
33
- end
34
-
35
- def validate!
36
- super
37
- path = Config.instance.git_executable
38
- is_git_exe = path =~ /.*(git)|(git.exe)$/
39
- file_exists = path == "git" || File.exist?(path)
40
- help! "Invalid git executable '#{path}'" unless is_git_exe && file_exists
41
- end
42
-
43
- def install_hooks(path)
44
- actual_path = path || "."
45
- Utils.install_hook("pre-commit", actual_path)
46
- Utils.install_hook("post-commit", actual_path)
47
- end
48
-
49
- def uninstall_hooks
50
- FileUtils.rm_f(".git/hooks/pre-commit")
51
- FileUtils.rm_f(".git/hooks/post-commit")
52
- end
53
-
54
- def update_gitconfig(path)
55
- actual_path = path || "."
56
- resource_file = Utils.path_for_resource(".gitconfig")
57
- target_file = File.join(actual_path, '.git/config')
58
-
59
- template = File.read(resource_file)
60
- first_template_line = template.lines.first
61
-
62
- Utils.append_if_missing(target_file, Regexp.new(Regexp.quote(first_template_line)), template)
63
- end
64
-
65
- def multirepo_enabled_dependencies
66
- ConfigFile.new(".").load_entries.select { |e| Utils.multirepo_enabled?(e.repo.path) }
67
- end
68
-
69
- def validate_only_one_flag(*flags)
70
- flags.reduce(0) { |count, flag| count += 1 if flag; count } <= 1
71
- end
72
-
73
- def ensure_in_work_tree
74
- repo = Repo.new(".")
75
- fail MultiRepoException, "Not a git repository" unless repo.exists?
76
- fail MultiRepoException, "HEAD is unborn (you must perform at least one commit)" unless repo.head_born?
77
- end
78
-
79
- def ensure_multirepo_enabled
80
- fail MultiRepoException, "multirepo is not initialized in this repository." unless Utils.multirepo_enabled?(".")
81
- end
82
-
83
- def ensure_multirepo_tracked
84
- fail MultiRepoException, "Revision is not tracked by multirepo." unless Utils.multirepo_tracked?(".")
85
-
86
- lock_file_valid = LockFile.new(".").validate!
87
- fail MultiRepoException, "Revision is multirepo-enabled but contains a corrupted lock file!" unless lock_file_valid
88
- end
89
- end
90
- 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.git_executable = argv.option("git-exe", "git")
28
+ super
29
+ end
30
+
31
+ def run
32
+ help!
33
+ end
34
+
35
+ def validate!
36
+ super
37
+ path = Config.instance.git_executable
38
+ is_git_exe = path =~ /.*(git)|(git.exe)$/
39
+ file_exists = path == "git" || File.exist?(path)
40
+ help! "Invalid git executable '#{path}'" unless is_git_exe && file_exists
41
+ end
42
+
43
+ def install_hooks(path)
44
+ actual_path = path || "."
45
+ Utils.install_hook("pre-commit", actual_path)
46
+ Utils.install_hook("post-commit", actual_path)
47
+ end
48
+
49
+ def uninstall_hooks
50
+ FileUtils.rm_f(".git/hooks/pre-commit")
51
+ FileUtils.rm_f(".git/hooks/post-commit")
52
+ end
53
+
54
+ def update_gitconfig(path)
55
+ actual_path = path || "."
56
+ resource_file = Utils.path_for_resource(".gitconfig")
57
+ target_file = File.join(actual_path, '.git/config')
58
+
59
+ template = File.read(resource_file)
60
+ first_template_line = template.lines.first
61
+
62
+ Utils.append_if_missing(target_file, Regexp.new(Regexp.quote(first_template_line)), template)
63
+ end
64
+
65
+ def multirepo_enabled_dependencies
66
+ ConfigFile.new(".").load_entries.select { |e| Utils.multirepo_enabled?(e.repo.path) }
67
+ end
68
+
69
+ def validate_only_one_flag(*flags)
70
+ flags.reduce(0) { |count, flag| count += 1 if flag; count } <= 1
71
+ end
72
+
73
+ def ensure_in_work_tree
74
+ repo = Repo.new(".")
75
+ fail MultiRepoException, "Not a git repository" unless repo.exists?
76
+ fail MultiRepoException, "HEAD is unborn (you must perform at least one commit)" unless repo.head_born?
77
+ end
78
+
79
+ def ensure_multirepo_enabled
80
+ fail MultiRepoException, "multirepo is not initialized in this repository." unless Utils.multirepo_enabled?(".")
81
+ end
82
+
83
+ def ensure_multirepo_tracked
84
+ fail MultiRepoException, "Revision is not tracked by multirepo." unless Utils.multirepo_tracked?(".")
85
+
86
+ lock_file_valid = LockFile.new(".").validate!
87
+ fail MultiRepoException, "Revision is multirepo-enabled but contains a corrupted lock file!" unless lock_file_valid
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,15 @@
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 "graph-command"
8
+ require_relative "init-command"
9
+ require_relative "inspect-command"
10
+ require_relative "install-command"
11
+ require_relative "merge-command"
12
+ require_relative "open-command"
13
+ require_relative "remove-command"
14
+ require_relative "uninit-command"
15
+ require_relative "update-command"
@@ -1,103 +1,103 @@
1
- require_relative "command"
2
- require "multirepo/utility/utils"
3
- require "multirepo/utility/console"
4
- require "multirepo/files/config-file"
5
- require "multirepo/git/repo"
6
- require "multirepo/git/git-runner"
7
- require "multirepo/logic/performer"
8
-
9
- module MultiRepo
10
- class DoCommand < Command
11
- self.command = "do"
12
- self.summary = "Perform an arbitrary Git operation in the main repository, dependency repositories or all repositories."
13
-
14
- def self.options
15
- [
16
- ['"<operation>"', 'The git command to perform, between quotes, omitting the executable name (ex: "reset --hard HEAD")'],
17
- ['[--main]', 'Perform the operation in the main repository only.'],
18
- ['[--deps]', 'Perform the operation in dependencies only.'],
19
- ['[--all]', 'Perform the operation in the main repository and all dependencies.']
20
- ].concat(super)
21
- end
22
-
23
- def initialize(argv)
24
- @operation = argv.shift_argument
25
- @all = argv.flag?("all")
26
- @main_only = argv.flag?("main")
27
- @deps_only = argv.flag?("deps")
28
- super
29
- end
30
-
31
- def validate!
32
- super
33
- help! "You must provide a git operation to perform" unless @operation
34
- unless validate_only_one_flag(@all, @main_only, @deps_only)
35
- help! "You can't provide more than one operation modifier (--deps, --main, etc.)"
36
- end
37
- end
38
-
39
- def run
40
- ensure_in_work_tree
41
- ensure_multirepo_enabled
42
-
43
- @operation = @operation.sub(/^git /, "")
44
-
45
- success = true
46
- if @main_only
47
- confirm_main_repo_operation
48
- success &= perform_operation_on_main(@operation)
49
- elsif @deps_only
50
- confirm_dependencies_operation
51
- success &= perform_operation_on_dependencies(@operation)
52
- else
53
- confirm_main_repo_operation
54
- confirm_dependencies_operation
55
- success &= perform_operation_on_dependencies(@operation) # Ordered dependencies first
56
- success &= perform_operation_on_main(@operation) # Main last
57
- end
58
-
59
- Console.log_warning("Some operations finished with non-zero exit status. Please review the above.") unless success
60
- end
61
-
62
- def perform_operation_on_main(operation)
63
- perform_operation(".", operation)
64
- end
65
-
66
- def perform_operation_on_dependencies(operation)
67
- success = true
68
- Performer.dependencies.each do |dependency|
69
- success &= perform_operation(dependency.config_entry.repo.path, operation)
70
- end
71
- return success
72
- end
73
-
74
- def perform_operation(path, operation)
75
- Console.log_step("Performing operation on '#{path}'")
76
- GitRunner.run_as_system(path, operation)
77
- GitRunner.last_command_succeeded
78
- end
79
-
80
- def confirm_main_repo_operation
81
- unless main_repo_clean?
82
- Console.log_warning("Main repo contains uncommitted changes")
83
- fail MultiRepoException, "Aborted" unless Console.ask_yes_no("Proceed anyway?")
84
- end
85
- end
86
-
87
- def confirm_dependencies_operation
88
- unless dependencies_clean?
89
- Console.log_warning("Some dependencies contain uncommitted changes")
90
- fail MultiRepoException, "Aborted" unless Console.ask_yes_no("Proceed anyway?")
91
- end
92
- end
93
-
94
- def main_repo_clean?
95
- Repo.new(".").clean?
96
- end
97
-
98
- def dependencies_clean?
99
- config_entries = ConfigFile.new(".").load_entries
100
- return Utils.dependencies_clean?(config_entries)
101
- end
102
- end
103
- end
1
+ require_relative "command"
2
+ require "multirepo/utility/utils"
3
+ require "multirepo/utility/console"
4
+ require "multirepo/files/config-file"
5
+ require "multirepo/git/repo"
6
+ require "multirepo/git/git-runner"
7
+ require "multirepo/logic/performer"
8
+
9
+ module MultiRepo
10
+ class DoCommand < Command
11
+ self.command = "do"
12
+ self.summary = "Perform an arbitrary Git operation in the main repository, dependency repositories or all repositories."
13
+
14
+ def self.options
15
+ [
16
+ ['"<operation>"', 'The git command to perform, between quotes, omitting the executable name (ex: "reset --hard HEAD")'],
17
+ ['[--main]', 'Perform the operation in the main repository only.'],
18
+ ['[--deps]', 'Perform the operation in dependencies only.'],
19
+ ['[--all]', 'Perform the operation in the main repository and all dependencies.']
20
+ ].concat(super)
21
+ end
22
+
23
+ def initialize(argv)
24
+ @operation = argv.shift_argument
25
+ @all = argv.flag?("all")
26
+ @main_only = argv.flag?("main")
27
+ @deps_only = argv.flag?("deps")
28
+ super
29
+ end
30
+
31
+ def validate!
32
+ super
33
+ help! "You must provide a git operation to perform" unless @operation
34
+ unless validate_only_one_flag(@all, @main_only, @deps_only)
35
+ help! "You can't provide more than one operation modifier (--deps, --main, etc.)"
36
+ end
37
+ end
38
+
39
+ def run
40
+ ensure_in_work_tree
41
+ ensure_multirepo_enabled
42
+
43
+ @operation = @operation.sub(/^git /, "")
44
+
45
+ success = true
46
+ if @main_only
47
+ confirm_main_repo_operation
48
+ success &= perform_operation_on_main(@operation)
49
+ elsif @deps_only
50
+ confirm_dependencies_operation
51
+ success &= perform_operation_on_dependencies(@operation)
52
+ else
53
+ confirm_main_repo_operation
54
+ confirm_dependencies_operation
55
+ success &= perform_operation_on_dependencies(@operation) # Ordered dependencies first
56
+ success &= perform_operation_on_main(@operation) # Main last
57
+ end
58
+
59
+ Console.log_warning("Some operations finished with non-zero exit status. Please review the above.") unless success
60
+ end
61
+
62
+ def perform_operation_on_main(operation)
63
+ perform_operation(".", operation)
64
+ end
65
+
66
+ def perform_operation_on_dependencies(operation)
67
+ success = true
68
+ Performer.dependencies.each do |dependency|
69
+ success &= perform_operation(dependency.config_entry.repo.path, operation)
70
+ end
71
+ return success
72
+ end
73
+
74
+ def perform_operation(path, operation)
75
+ Console.log_step("Performing operation on '#{path}'")
76
+ GitRunner.run_as_system(path, operation)
77
+ GitRunner.last_command_succeeded
78
+ end
79
+
80
+ def confirm_main_repo_operation
81
+ unless main_repo_clean?
82
+ Console.log_warning("Main repo contains uncommitted changes")
83
+ fail MultiRepoException, "Aborted" unless Console.ask("Proceed anyway?")
84
+ end
85
+ end
86
+
87
+ def confirm_dependencies_operation
88
+ unless dependencies_clean?
89
+ Console.log_warning("Some dependencies contain uncommitted changes")
90
+ fail MultiRepoException, "Aborted" unless Console.ask("Proceed anyway?")
91
+ end
92
+ end
93
+
94
+ def main_repo_clean?
95
+ Repo.new(".").clean?
96
+ end
97
+
98
+ def dependencies_clean?
99
+ config_entries = ConfigFile.new(".").load_entries
100
+ return Utils.dependencies_clean?(config_entries)
101
+ end
102
+ end
103
+ end