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.
- checksums.yaml +5 -5
- data/.gitattributes +4 -4
- data/.gitbugtraq +3 -3
- data/.gitignore +38 -38
- data/.rspec +2 -2
- data/.rubocop.yml +79 -79
- data/CHANGELOG.md +116 -112
- data/Gemfile +4 -4
- data/Gemfile.lock +47 -47
- data/LICENSE +22 -22
- data/README.md +178 -178
- 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 +55 -55
- data/lib/multirepo/commands/branch-command.rb +88 -88
- data/lib/multirepo/commands/checkout-command.rb +127 -127
- data/lib/multirepo/commands/clone-command.rb +68 -68
- data/lib/multirepo/commands/command.rb +87 -87
- data/lib/multirepo/commands/commands.rb +14 -14
- data/lib/multirepo/commands/do-command.rb +101 -101
- data/lib/multirepo/commands/init-command.rb +121 -121
- data/lib/multirepo/commands/inspect-command.rb +48 -48
- data/lib/multirepo/commands/install-command.rb +170 -170
- data/lib/multirepo/commands/merge-command.rb +249 -249
- data/lib/multirepo/commands/open-command.rb +55 -55
- 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 +112 -112
- data/lib/multirepo/config.rb +19 -19
- data/lib/multirepo/files/config-entry.rb +39 -39
- data/lib/multirepo/files/config-file.rb +52 -52
- data/lib/multirepo/files/lock-entry.rb +29 -29
- data/lib/multirepo/files/lock-file.rb +62 -62
- data/lib/multirepo/files/meta-file.rb +51 -51
- data/lib/multirepo/files/tracking-file.rb +9 -9
- data/lib/multirepo/files/tracking-files.rb +64 -64
- 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 +131 -131
- data/lib/multirepo/hooks/post-commit-hook.rb +23 -23
- data/lib/multirepo/hooks/pre-commit-hook.rb +35 -35
- data/lib/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 +75 -75
- data/lib/multirepo/logic/performer.rb +62 -62
- data/lib/multirepo/logic/repo-selection.rb +25 -25
- data/lib/multirepo/logic/revision-selection.rb +15 -15
- data/lib/multirepo/logic/revision-selector.rb +23 -23
- data/lib/multirepo/logic/version-comparer.rb +10 -10
- data/lib/multirepo/multirepo-exception.rb +6 -6
- data/lib/multirepo/output/extra-output.rb +12 -12
- data/lib/multirepo/output/teamcity-extra-output.rb +11 -11
- 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 +107 -107
- data/lib/multirepo/utility/verbosity.rb +6 -6
- data/resources/.gitconfig +2 -2
- data/resources/post-commit +0 -0
- data/resources/pre-commit +0 -0
- data/spec/integration/init_spec.rb +19 -19
- data/spec/spec_helper.rb +89 -89
- metadata +3 -3
@@ -1,11 +1,11 @@
|
|
1
|
-
module MultiRepo
|
2
|
-
class TeamCityExtraOutput
|
3
|
-
def progress(message)
|
4
|
-
puts "##teamcity[progressMessage '#{message}']"
|
5
|
-
end
|
6
|
-
|
7
|
-
def error(message)
|
8
|
-
puts "##teamcity[buildProblem description='#{message}']"
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|
1
|
+
module MultiRepo
|
2
|
+
class TeamCityExtraOutput
|
3
|
+
def progress(message)
|
4
|
+
puts "##teamcity[progressMessage '#{message}']"
|
5
|
+
end
|
6
|
+
|
7
|
+
def error(message)
|
8
|
+
puts "##teamcity[buildProblem description='#{message}']"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
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(message)
|
31
|
-
answered = false
|
32
|
-
until 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
|
-
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(message)
|
31
|
+
answered = false
|
32
|
+
until 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
|
+
end
|
@@ -1,27 +1,27 @@
|
|
1
|
-
require "open3"
|
2
|
-
|
3
|
-
require "multirepo/utility/console"
|
4
|
-
|
5
|
-
module MultiRepo
|
6
|
-
class PopenRunner
|
7
|
-
def self.run(cmd, verbosity)
|
8
|
-
Console.log_info("Command: #{cmd}") if Config.instance.verbose
|
9
|
-
|
10
|
-
lines = []
|
11
|
-
last_command_succeeded = false
|
12
|
-
Open3.popen2e(cmd) do |_stdin, stdout_and_stderr, thread|
|
13
|
-
stdout_and_stderr.each do |line|
|
14
|
-
print line if Config.instance.verbose
|
15
|
-
lines << line
|
16
|
-
end
|
17
|
-
last_command_succeeded = thread.value.success?
|
18
|
-
end
|
19
|
-
|
20
|
-
output = lines.join("").rstrip
|
21
|
-
|
22
|
-
Console.log_error(output) if !last_command_succeeded && verbosity == Verbosity::OUTPUT_ON_ERROR
|
23
|
-
|
24
|
-
return output, last_command_succeeded
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
1
|
+
require "open3"
|
2
|
+
|
3
|
+
require "multirepo/utility/console"
|
4
|
+
|
5
|
+
module MultiRepo
|
6
|
+
class PopenRunner
|
7
|
+
def self.run(cmd, verbosity)
|
8
|
+
Console.log_info("Command: #{cmd}") if Config.instance.verbose
|
9
|
+
|
10
|
+
lines = []
|
11
|
+
last_command_succeeded = false
|
12
|
+
Open3.popen2e(cmd) do |_stdin, stdout_and_stderr, thread|
|
13
|
+
stdout_and_stderr.each do |line|
|
14
|
+
print line if Config.instance.verbose
|
15
|
+
lines << line
|
16
|
+
end
|
17
|
+
last_command_succeeded = thread.value.success?
|
18
|
+
end
|
19
|
+
|
20
|
+
output = lines.join("").rstrip
|
21
|
+
|
22
|
+
Console.log_error(output) if !last_command_succeeded && verbosity == Verbosity::OUTPUT_ON_ERROR
|
23
|
+
|
24
|
+
return output, last_command_succeeded
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -1,14 +1,14 @@
|
|
1
|
-
require "multirepo/utility/console"
|
2
|
-
|
3
|
-
module MultiRepo
|
4
|
-
class SystemRunner
|
5
|
-
def self.run(cmd)
|
6
|
-
Console.log_info("Command: #{cmd}") if Config.instance.verbose
|
7
|
-
|
8
|
-
output = system(cmd)
|
9
|
-
last_command_succeeded = ($?.exitstatus == 0)
|
10
|
-
|
11
|
-
return output, last_command_succeeded
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
1
|
+
require "multirepo/utility/console"
|
2
|
+
|
3
|
+
module MultiRepo
|
4
|
+
class SystemRunner
|
5
|
+
def self.run(cmd)
|
6
|
+
Console.log_info("Command: #{cmd}") if Config.instance.verbose
|
7
|
+
|
8
|
+
output = system(cmd)
|
9
|
+
last_command_succeeded = ($?.exitstatus == 0)
|
10
|
+
|
11
|
+
return output, last_command_succeeded
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -1,107 +1,107 @@
|
|
1
|
-
require "multirepo/multirepo-exception"
|
2
|
-
require "fileutils"
|
3
|
-
require "uri"
|
4
|
-
|
5
|
-
module MultiRepo
|
6
|
-
class Utils
|
7
|
-
def self.standard_path(p)
|
8
|
-
path = URI.parse(p).path
|
9
|
-
path.insert(0, '/') if (path[0] != '/')
|
10
|
-
path.chomp!('/') if (path > '/')
|
11
|
-
path
|
12
|
-
end
|
13
|
-
|
14
|
-
def self.only_one_true?(*flags)
|
15
|
-
flags.reduce(0) { |count, flag| count += 1 if flag; count } <= 1
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.path_for_resource(resource_name)
|
19
|
-
gem_path = Gem::Specification.find_by_name("git-multirepo").gem_dir
|
20
|
-
File.join(gem_path, "resources/#{resource_name}")
|
21
|
-
end
|
22
|
-
|
23
|
-
def self.multirepo_enabled?(path)
|
24
|
-
File.exist?(File.join(path, ".multirepo"))
|
25
|
-
end
|
26
|
-
|
27
|
-
def self.multirepo_tracked?(path)
|
28
|
-
multirepo_enabled?(path) && File.exist?(File.join(path, ".multirepo.lock"))
|
29
|
-
end
|
30
|
-
|
31
|
-
def self.install_hook(name, path)
|
32
|
-
destination_path = File.join(path, ".git/hooks")
|
33
|
-
destination_file = File.join(destination_path, name)
|
34
|
-
FileUtils.cp(path_for_resource(name), destination_file)
|
35
|
-
FileUtils.chmod(0755, destination_file) # -rwxr-xr-x
|
36
|
-
end
|
37
|
-
|
38
|
-
def self.sibling_repos
|
39
|
-
sibling_directories = Dir['../*/']
|
40
|
-
sibling_repos = sibling_directories.map{ |d| Repo.new(d) }.select(&:exists?)
|
41
|
-
sibling_repos.delete_if{ |r| Pathname.new(r.path).realpath == Pathname.new(".").realpath }
|
42
|
-
end
|
43
|
-
|
44
|
-
def self.dependencies_clean?(config_entries)
|
45
|
-
clean = true
|
46
|
-
missing = false
|
47
|
-
config_entries.each do |e|
|
48
|
-
# Ensure the dependency exists
|
49
|
-
unless e.repo.exists?
|
50
|
-
Console.log_error("Dependency '#{e.path}' does not exist on disk")
|
51
|
-
missing |= true
|
52
|
-
next
|
53
|
-
end
|
54
|
-
|
55
|
-
# Ensure it contains no uncommitted changes
|
56
|
-
dependency_clean = e.repo.clean?
|
57
|
-
clean &= dependency_clean
|
58
|
-
Console.log_warning("Dependency '#{e.repo.path}' contains uncommitted changes") unless dependency_clean
|
59
|
-
end
|
60
|
-
|
61
|
-
fail MultiRepoException, "Some dependencies are not present on this machine." \
|
62
|
-
" Run \"multi install\" to clone missing dependencies." if missing
|
63
|
-
|
64
|
-
return clean
|
65
|
-
end
|
66
|
-
|
67
|
-
def self.ensure_working_copies_clean(repos)
|
68
|
-
clean = true
|
69
|
-
repos.each do |repo|
|
70
|
-
dependency_clean = repo.clean?
|
71
|
-
clean &= dependency_clean
|
72
|
-
Console.log_warning("Repo '#{repo.path}' contains uncommitted changes") unless dependency_clean
|
73
|
-
end
|
74
|
-
return clean
|
75
|
-
end
|
76
|
-
|
77
|
-
def self.convert_to_windows_path(unix_path)
|
78
|
-
components = Pathname.new(unix_path).each_filename.to_a
|
79
|
-
components.join(File::ALT_SEPARATOR)
|
80
|
-
end
|
81
|
-
|
82
|
-
def self.reveal_in_default_file_browser(unix_path)
|
83
|
-
if OS.osx?
|
84
|
-
system %(open "#{unix_path}")
|
85
|
-
elsif OS.windows?
|
86
|
-
system %(explorer "#{Utils.convert_to_windows_path(unix_path)}")
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
def self.open_in_default_app(unix_path)
|
91
|
-
if OS.osx?
|
92
|
-
system %(open "#{unix_path}")
|
93
|
-
elsif OS.windows?
|
94
|
-
system %(cmd /c "start C:\\#{Utils.convert_to_windows_path(unix_path)}")
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
def self.append_if_missing(path, pattern, string_to_append)
|
99
|
-
if File.exist?(path)
|
100
|
-
string_located = File.readlines(path).grep(pattern).any?
|
101
|
-
File.open(path, 'a') { |f| f.puts(string_to_append) } unless string_located
|
102
|
-
else
|
103
|
-
File.open(path, 'w') { |f| f.puts(string_to_append) }
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
107
|
-
end
|
1
|
+
require "multirepo/multirepo-exception"
|
2
|
+
require "fileutils"
|
3
|
+
require "uri"
|
4
|
+
|
5
|
+
module MultiRepo
|
6
|
+
class Utils
|
7
|
+
def self.standard_path(p)
|
8
|
+
path = URI.parse(p).path
|
9
|
+
path.insert(0, '/') if (path[0] != '/')
|
10
|
+
path.chomp!('/') if (path > '/')
|
11
|
+
path
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.only_one_true?(*flags)
|
15
|
+
flags.reduce(0) { |count, flag| count += 1 if flag; count } <= 1
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.path_for_resource(resource_name)
|
19
|
+
gem_path = Gem::Specification.find_by_name("git-multirepo").gem_dir
|
20
|
+
File.join(gem_path, "resources/#{resource_name}")
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.multirepo_enabled?(path)
|
24
|
+
File.exist?(File.join(path, ".multirepo"))
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.multirepo_tracked?(path)
|
28
|
+
multirepo_enabled?(path) && File.exist?(File.join(path, ".multirepo.lock"))
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.install_hook(name, path)
|
32
|
+
destination_path = File.join(path, ".git/hooks")
|
33
|
+
destination_file = File.join(destination_path, name)
|
34
|
+
FileUtils.cp(path_for_resource(name), destination_file)
|
35
|
+
FileUtils.chmod(0755, destination_file) # -rwxr-xr-x
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.sibling_repos
|
39
|
+
sibling_directories = Dir['../*/']
|
40
|
+
sibling_repos = sibling_directories.map{ |d| Repo.new(d) }.select(&:exists?)
|
41
|
+
sibling_repos.delete_if{ |r| Pathname.new(r.path).realpath == Pathname.new(".").realpath }
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.dependencies_clean?(config_entries)
|
45
|
+
clean = true
|
46
|
+
missing = false
|
47
|
+
config_entries.each do |e|
|
48
|
+
# Ensure the dependency exists
|
49
|
+
unless e.repo.exists?
|
50
|
+
Console.log_error("Dependency '#{e.path}' does not exist on disk")
|
51
|
+
missing |= true
|
52
|
+
next
|
53
|
+
end
|
54
|
+
|
55
|
+
# Ensure it contains no uncommitted changes
|
56
|
+
dependency_clean = e.repo.clean?
|
57
|
+
clean &= dependency_clean
|
58
|
+
Console.log_warning("Dependency '#{e.repo.path}' contains uncommitted changes") unless dependency_clean
|
59
|
+
end
|
60
|
+
|
61
|
+
fail MultiRepoException, "Some dependencies are not present on this machine." \
|
62
|
+
" Run \"multi install\" to clone missing dependencies." if missing
|
63
|
+
|
64
|
+
return clean
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.ensure_working_copies_clean(repos)
|
68
|
+
clean = true
|
69
|
+
repos.each do |repo|
|
70
|
+
dependency_clean = repo.clean?
|
71
|
+
clean &= dependency_clean
|
72
|
+
Console.log_warning("Repo '#{repo.path}' contains uncommitted changes") unless dependency_clean
|
73
|
+
end
|
74
|
+
return clean
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.convert_to_windows_path(unix_path)
|
78
|
+
components = Pathname.new(unix_path).each_filename.to_a
|
79
|
+
components.join(File::ALT_SEPARATOR)
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.reveal_in_default_file_browser(unix_path)
|
83
|
+
if OS.osx?
|
84
|
+
system %(open "#{unix_path}")
|
85
|
+
elsif OS.windows?
|
86
|
+
system %(explorer "#{Utils.convert_to_windows_path(unix_path)}")
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def self.open_in_default_app(unix_path)
|
91
|
+
if OS.osx?
|
92
|
+
system %(open "#{unix_path}")
|
93
|
+
elsif OS.windows?
|
94
|
+
system %(cmd /c "start C:\\#{Utils.convert_to_windows_path(unix_path)}")
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.append_if_missing(path, pattern, string_to_append)
|
99
|
+
if File.exist?(path)
|
100
|
+
string_located = File.readlines(path).grep(pattern).any?
|
101
|
+
File.open(path, 'a') { |f| f.puts(string_to_append) } unless string_located
|
102
|
+
else
|
103
|
+
File.open(path, 'w') { |f| f.puts(string_to_append) }
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
|
-
module MultiRepo
|
2
|
-
class Verbosity
|
3
|
-
OUTPUT_NEVER = 0
|
4
|
-
OUTPUT_ON_ERROR = 1
|
5
|
-
end
|
6
|
-
end
|
1
|
+
module MultiRepo
|
2
|
+
class Verbosity
|
3
|
+
OUTPUT_NEVER = 0
|
4
|
+
OUTPUT_ON_ERROR = 1
|
5
|
+
end
|
6
|
+
end
|
data/resources/.gitconfig
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
[merge "ours"]
|
2
|
-
name = "Always keep ours"
|
1
|
+
[merge "ours"]
|
2
|
+
name = "Always keep ours"
|
3
3
|
driver = true
|