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.
- checksums.yaml +4 -4
- data/.gitattributes +2 -2
- data/.gitbugtraq +3 -3
- data/.gitignore +38 -38
- data/.multirepo.meta +2 -2
- data/.rspec +2 -2
- data/.rubocop.yml +79 -79
- data/CHANGELOG.md +29 -25
- data/Gemfile +4 -4
- data/Gemfile.lock +42 -42
- data/LICENSE +22 -22
- data/README.md +154 -154
- data/Rakefile +1 -1
- data/bin/multi +11 -11
- data/docs/bug-repros/91565510-repro.sh +20 -20
- data/git-multirepo.gemspec +31 -31
- data/lib/git-multirepo.rb +3 -3
- data/lib/multirepo/commands/add-command.rb +51 -51
- data/lib/multirepo/commands/branch-command.rb +82 -82
- data/lib/multirepo/commands/checkout-command.rb +120 -120
- data/lib/multirepo/commands/clone-command.rb +68 -68
- data/lib/multirepo/commands/command.rb +90 -90
- data/lib/multirepo/commands/commands.rb +15 -0
- data/lib/multirepo/commands/do-command.rb +103 -103
- data/lib/multirepo/commands/graph-command.rb +43 -43
- data/lib/multirepo/commands/init-command.rb +121 -121
- data/lib/multirepo/commands/inspect-command.rb +39 -39
- data/lib/multirepo/commands/install-command.rb +153 -153
- data/lib/multirepo/commands/merge-command.rb +249 -225
- data/lib/multirepo/commands/open-command.rb +57 -57
- data/lib/multirepo/commands/remove-command.rb +48 -48
- data/lib/multirepo/commands/uninit-command.rb +18 -18
- data/lib/multirepo/commands/update-command.rb +106 -94
- data/lib/multirepo/config.rb +16 -16
- data/lib/multirepo/files/config-entry.rb +39 -39
- data/lib/multirepo/files/config-file.rb +46 -46
- data/lib/multirepo/files/lock-entry.rb +29 -29
- data/lib/multirepo/files/lock-file.rb +56 -56
- data/lib/multirepo/files/meta-file.rb +41 -41
- data/lib/multirepo/files/tracking-file.rb +9 -9
- data/lib/multirepo/files/tracking-files.rb +47 -47
- data/lib/multirepo/git/branch.rb +32 -32
- data/lib/multirepo/git/change.rb +11 -11
- data/lib/multirepo/git/commit.rb +7 -7
- data/lib/multirepo/git/git-runner.rb +56 -56
- data/lib/multirepo/git/git.rb +10 -10
- data/lib/multirepo/git/ref.rb +38 -38
- data/lib/multirepo/git/remote.rb +17 -17
- data/lib/multirepo/git/repo.rb +124 -124
- data/lib/multirepo/hooks/post-commit-hook.rb +23 -23
- data/lib/multirepo/hooks/pre-commit-hook.rb +35 -35
- data/lib/{info.rb → multirepo/info.rb} +5 -5
- data/lib/multirepo/logic/dependency.rb +6 -6
- data/lib/multirepo/logic/merge-descriptor.rb +95 -95
- data/lib/multirepo/logic/node.rb +72 -72
- data/lib/multirepo/logic/performer.rb +55 -55
- data/lib/multirepo/logic/revision-selector.rb +35 -35
- data/lib/multirepo/multirepo-exception.rb +6 -6
- data/lib/multirepo/utility/console.rb +52 -52
- data/lib/multirepo/utility/popen-runner.rb +27 -27
- data/lib/multirepo/utility/system-runner.rb +14 -14
- data/lib/multirepo/utility/utils.rb +95 -95
- data/lib/multirepo/utility/verbosity.rb +6 -6
- data/resources/.gitconfig +2 -2
- data/resources/post-commit +6 -6
- data/resources/pre-commit +6 -6
- data/spec/integration/init_spec.rb +19 -19
- data/spec/spec_helper.rb +89 -89
- metadata +33 -33
- 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.
|
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.
|
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
|