git-multirepo 1.0.0.beta45 → 1.0.0.beta46
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 +21 -21
- data/.multirepo.lock +26 -26
- data/.multirepo.meta +2 -2
- data/.rspec +2 -2
- data/Gemfile +4 -4
- data/Gemfile.lock +42 -42
- data/LICENSE +22 -22
- data/README.md +154 -144
- data/Rakefile +2 -2
- data/bin/multi +10 -10
- data/docs/bug-repros/91565510-repro.sh +20 -20
- data/docs/git-multirepo-cheatsheet.docx +0 -0
- data/git-multirepo.gemspec +31 -31
- data/lib/commands.rb +14 -14
- data/lib/git-multirepo.rb +2 -2
- data/lib/info.rb +4 -4
- data/lib/multirepo/commands/add-command.rb +50 -50
- data/lib/multirepo/commands/branch-command.rb +81 -81
- data/lib/multirepo/commands/checkout-command.rb +119 -119
- data/lib/multirepo/commands/clone-command.rb +67 -67
- data/lib/multirepo/commands/command.rb +89 -89
- data/lib/multirepo/commands/do-command.rb +102 -100
- data/lib/multirepo/commands/graph-command.rb +42 -42
- data/lib/multirepo/commands/init-command.rb +119 -119
- data/lib/multirepo/commands/inspect-command.rb +38 -39
- data/lib/multirepo/commands/install-command.rb +146 -137
- data/lib/multirepo/commands/merge-command.rb +225 -225
- data/lib/multirepo/commands/open-command.rb +56 -55
- data/lib/multirepo/commands/remove-command.rb +47 -47
- data/lib/multirepo/commands/uninit-command.rb +17 -17
- data/lib/multirepo/commands/update-command.rb +55 -55
- data/lib/multirepo/config.rb +15 -15
- data/lib/multirepo/files/config-entry.rb +38 -38
- data/lib/multirepo/files/config-file.rb +45 -45
- data/lib/multirepo/files/lock-entry.rb +28 -28
- data/lib/multirepo/files/lock-file.rb +55 -55
- data/lib/multirepo/files/meta-file.rb +40 -40
- data/lib/multirepo/files/tracking-file.rb +8 -8
- data/lib/multirepo/files/tracking-files.rb +46 -46
- data/lib/multirepo/git/branch.rb +31 -31
- data/lib/multirepo/git/change.rb +10 -10
- data/lib/multirepo/git/commit.rb +6 -6
- data/lib/multirepo/git/git-runner.rb +46 -46
- data/lib/multirepo/git/git.rb +9 -9
- data/lib/multirepo/git/ref.rb +37 -37
- data/lib/multirepo/git/remote.rb +16 -16
- data/lib/multirepo/git/repo.rb +122 -122
- data/lib/multirepo/hooks/post-commit-hook.rb +22 -22
- data/lib/multirepo/hooks/pre-commit-hook.rb +34 -34
- data/lib/multirepo/logic/dependency.rb +5 -5
- data/lib/multirepo/logic/merge-descriptor.rb +94 -94
- data/lib/multirepo/logic/node.rb +71 -71
- data/lib/multirepo/logic/performer.rb +56 -56
- data/lib/multirepo/logic/revision-selector.rb +34 -34
- data/lib/multirepo/multirepo-exception.rb +5 -5
- data/lib/multirepo/utility/console.rb +51 -51
- data/lib/multirepo/utility/runner.rb +34 -34
- data/lib/multirepo/utility/utils.rb +94 -94
- data/resources/.gitconfig +2 -2
- data/resources/post-commit +5 -5
- data/resources/pre-commit +5 -5
- data/spec/integration/init_spec.rb +18 -18
- data/spec/spec_helper.rb +89 -89
- metadata +2 -2
@@ -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
|
-
raise 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.exists?(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.is_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
|
-
raise MultiRepoException, "Not a git repository" unless repo.exists?
|
76
|
-
raise MultiRepoException, "HEAD is unborn (you must perform at least one commit)" unless repo.head_born?
|
77
|
-
end
|
78
|
-
|
79
|
-
def ensure_multirepo_enabled
|
80
|
-
raise MultiRepoException, "multirepo is not initialized in this repository." unless Utils.is_multirepo_enabled(".")
|
81
|
-
end
|
82
|
-
|
83
|
-
def ensure_multirepo_tracked
|
84
|
-
raise MultiRepoException, "Revision is not tracked by multirepo." unless Utils.is_multirepo_tracked(".")
|
85
|
-
|
86
|
-
lock_file_valid = LockFile.new(".").validate!
|
87
|
-
raise MultiRepoException, "Revision is multirepo-enabled but contains a corrupted lock file!" unless lock_file_valid
|
88
|
-
end
|
89
|
-
end
|
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
|
+
raise 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.exists?(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.is_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
|
+
raise MultiRepoException, "Not a git repository" unless repo.exists?
|
76
|
+
raise MultiRepoException, "HEAD is unborn (you must perform at least one commit)" unless repo.head_born?
|
77
|
+
end
|
78
|
+
|
79
|
+
def ensure_multirepo_enabled
|
80
|
+
raise MultiRepoException, "multirepo is not initialized in this repository." unless Utils.is_multirepo_enabled(".")
|
81
|
+
end
|
82
|
+
|
83
|
+
def ensure_multirepo_tracked
|
84
|
+
raise MultiRepoException, "Revision is not tracked by multirepo." unless Utils.is_multirepo_tracked(".")
|
85
|
+
|
86
|
+
lock_file_valid = LockFile.new(".").validate!
|
87
|
+
raise MultiRepoException, "Revision is multirepo-enabled but contains a corrupted lock file!" unless lock_file_valid
|
88
|
+
end
|
89
|
+
end
|
90
90
|
end
|
@@ -1,101 +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
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
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_in_working_dir(path, operation, Runner::Verbosity::OUTPUT_ALWAYS)
|
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
|
+
raise 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
|
+
raise 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
|
101
103
|
end
|
@@ -1,43 +1,43 @@
|
|
1
|
-
require "os"
|
2
|
-
require "graphviz"
|
3
|
-
|
4
|
-
require "multirepo/utility/utils"
|
5
|
-
require "multirepo/utility/console"
|
6
|
-
require "multirepo/logic/node"
|
7
|
-
|
8
|
-
module MultiRepo
|
9
|
-
class GraphCommand < Command
|
10
|
-
self.command = "graph"
|
11
|
-
self.summary = "Graphs the dependency tree from the current repository."
|
12
|
-
|
13
|
-
def run
|
14
|
-
ensure_in_work_tree
|
15
|
-
ensure_multirepo_enabled
|
16
|
-
|
17
|
-
root = Node.new(".")
|
18
|
-
graph = GraphViz.new(:G, :type => :digraph)
|
19
|
-
build_graph_recursive(graph, root)
|
20
|
-
|
21
|
-
path = File.expand_path("~/Desktop/#{root.name}-graph.png")
|
22
|
-
|
23
|
-
begin
|
24
|
-
graph.output(:png => path)
|
25
|
-
Utils.open_in_default_app(path)
|
26
|
-
rescue StandardError => e
|
27
|
-
Console.log_error(e.message)
|
28
|
-
raise MultiRepoException, "Could not generate graph image because an error occurred during graph generation"
|
29
|
-
end
|
30
|
-
|
31
|
-
Console.log_step("Generated graph image #{path}")
|
32
|
-
end
|
33
|
-
|
34
|
-
def build_graph_recursive(graph, node)
|
35
|
-
parent_graph_node = graph.add_nodes(node.name)
|
36
|
-
node.children.each do |child_node|
|
37
|
-
child_graph_node = graph.add_node(child_node.name)
|
38
|
-
graph.add_edge(parent_graph_node, child_graph_node)
|
39
|
-
build_graph_recursive(graph, child_node)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
1
|
+
require "os"
|
2
|
+
require "graphviz"
|
3
|
+
|
4
|
+
require "multirepo/utility/utils"
|
5
|
+
require "multirepo/utility/console"
|
6
|
+
require "multirepo/logic/node"
|
7
|
+
|
8
|
+
module MultiRepo
|
9
|
+
class GraphCommand < Command
|
10
|
+
self.command = "graph"
|
11
|
+
self.summary = "Graphs the dependency tree from the current repository."
|
12
|
+
|
13
|
+
def run
|
14
|
+
ensure_in_work_tree
|
15
|
+
ensure_multirepo_enabled
|
16
|
+
|
17
|
+
root = Node.new(".")
|
18
|
+
graph = GraphViz.new(:G, :type => :digraph)
|
19
|
+
build_graph_recursive(graph, root)
|
20
|
+
|
21
|
+
path = File.expand_path("~/Desktop/#{root.name}-graph.png")
|
22
|
+
|
23
|
+
begin
|
24
|
+
graph.output(:png => path)
|
25
|
+
Utils.open_in_default_app(path)
|
26
|
+
rescue StandardError => e
|
27
|
+
Console.log_error(e.message)
|
28
|
+
raise MultiRepoException, "Could not generate graph image because an error occurred during graph generation"
|
29
|
+
end
|
30
|
+
|
31
|
+
Console.log_step("Generated graph image #{path}")
|
32
|
+
end
|
33
|
+
|
34
|
+
def build_graph_recursive(graph, node)
|
35
|
+
parent_graph_node = graph.add_nodes(node.name)
|
36
|
+
node.children.each do |child_node|
|
37
|
+
child_graph_node = graph.add_node(child_node.name)
|
38
|
+
graph.add_edge(parent_graph_node, child_graph_node)
|
39
|
+
build_graph_recursive(graph, child_node)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
43
|
end
|