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,55 +1,55 @@
|
|
1
|
-
require "multirepo/files/config-file"
|
2
|
-
require "multirepo/files/lock-file"
|
3
|
-
|
4
|
-
require_relative "dependency"
|
5
|
-
|
6
|
-
module MultiRepo
|
7
|
-
class Performer
|
8
|
-
def self.perform_main_repo_checkout(main_repo, ref_name, message = nil)
|
9
|
-
# Make sure the main repo is clean before attempting a checkout
|
10
|
-
unless main_repo.clean?
|
11
|
-
fail MultiRepoException, "Can't checkout #{ref_name} because the main repo contains uncommitted changes"
|
12
|
-
end
|
13
|
-
|
14
|
-
# Checkout the specified ref
|
15
|
-
unless main_repo.checkout(ref_name)
|
16
|
-
fail MultiRepoException, "Couldn't perform checkout of main repo #{ref_name}!"
|
17
|
-
end
|
18
|
-
|
19
|
-
Console.log_substep(message || "Checked out main repo #{ref_name}")
|
20
|
-
|
21
|
-
# After checkout, make sure we're working with a multirepo-enabled ref
|
22
|
-
unless Utils.multirepo_tracked?(".")
|
23
|
-
fail MultiRepoException, "Revision #{ref_name} is not tracked by multirepo!"
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def self.dependencies
|
28
|
-
config_entries = ConfigFile.new(".").load_entries
|
29
|
-
lock_entries = LockFile.new(".").load_entries
|
30
|
-
|
31
|
-
dependencies = build_dependencies(config_entries, lock_entries)
|
32
|
-
dependency_ordered_nodes = Node.new(".").ordered_descendants
|
33
|
-
|
34
|
-
return dependency_ordered_nodes.map do |node|
|
35
|
-
dependencies.find { |d| d.config_entry.path == node.path }
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def self.build_dependencies(config_entries, lock_entries)
|
40
|
-
lock_entries.map do |lock_entry|
|
41
|
-
config_entry = config_entry_for_lock_entry(config_entries, lock_entry)
|
42
|
-
|
43
|
-
dependency = Dependency.new
|
44
|
-
dependency.config_entry = config_entry
|
45
|
-
dependency.lock_entry = lock_entry
|
46
|
-
|
47
|
-
next dependency
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def self.config_entry_for_lock_entry(config_entries, lock_entry)
|
52
|
-
config_entries.find { |config_entry| config_entry.id == lock_entry.id }
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
1
|
+
require "multirepo/files/config-file"
|
2
|
+
require "multirepo/files/lock-file"
|
3
|
+
|
4
|
+
require_relative "dependency"
|
5
|
+
|
6
|
+
module MultiRepo
|
7
|
+
class Performer
|
8
|
+
def self.perform_main_repo_checkout(main_repo, ref_name, message = nil)
|
9
|
+
# Make sure the main repo is clean before attempting a checkout
|
10
|
+
unless main_repo.clean?
|
11
|
+
fail MultiRepoException, "Can't checkout #{ref_name} because the main repo contains uncommitted changes"
|
12
|
+
end
|
13
|
+
|
14
|
+
# Checkout the specified ref
|
15
|
+
unless main_repo.checkout(ref_name)
|
16
|
+
fail MultiRepoException, "Couldn't perform checkout of main repo #{ref_name}!"
|
17
|
+
end
|
18
|
+
|
19
|
+
Console.log_substep(message || "Checked out main repo #{ref_name}")
|
20
|
+
|
21
|
+
# After checkout, make sure we're working with a multirepo-enabled ref
|
22
|
+
unless Utils.multirepo_tracked?(".")
|
23
|
+
fail MultiRepoException, "Revision #{ref_name} is not tracked by multirepo!"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.dependencies
|
28
|
+
config_entries = ConfigFile.new(".").load_entries
|
29
|
+
lock_entries = LockFile.new(".").load_entries
|
30
|
+
|
31
|
+
dependencies = build_dependencies(config_entries, lock_entries)
|
32
|
+
dependency_ordered_nodes = Node.new(".").ordered_descendants
|
33
|
+
|
34
|
+
return dependency_ordered_nodes.map do |node|
|
35
|
+
dependencies.find { |d| d.config_entry.path == node.path }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.build_dependencies(config_entries, lock_entries)
|
40
|
+
lock_entries.map do |lock_entry|
|
41
|
+
config_entry = config_entry_for_lock_entry(config_entries, lock_entry)
|
42
|
+
|
43
|
+
dependency = Dependency.new
|
44
|
+
dependency.config_entry = config_entry
|
45
|
+
dependency.lock_entry = lock_entry
|
46
|
+
|
47
|
+
next dependency
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.config_entry_for_lock_entry(config_entries, lock_entry)
|
52
|
+
config_entries.find { |config_entry| config_entry.id == lock_entry.id }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -1,35 +1,35 @@
|
|
1
|
-
module MultiRepo
|
2
|
-
class RevisionSelectionMode
|
3
|
-
AS_LOCK = 0
|
4
|
-
LATEST = 1
|
5
|
-
EXACT = 2
|
6
|
-
|
7
|
-
def self.name_for_mode(mode)
|
8
|
-
case mode
|
9
|
-
when AS_LOCK then "as-lock"
|
10
|
-
when LATEST then "latest"
|
11
|
-
when EXACT then "exact"
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
class RevisionSelector
|
17
|
-
def self.mode_for_args(checkout_latest, checkout_exact)
|
18
|
-
if checkout_latest
|
19
|
-
RevisionSelectionMode::LATEST
|
20
|
-
elsif checkout_exact
|
21
|
-
RevisionSelectionMode::EXACT
|
22
|
-
else
|
23
|
-
RevisionSelectionMode::AS_LOCK
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def self.revision_for_mode(mode, ref_name, lock_entry)
|
28
|
-
case mode
|
29
|
-
when RevisionSelectionMode::AS_LOCK then lock_entry.head
|
30
|
-
when RevisionSelectionMode::LATEST then lock_entry.branch
|
31
|
-
when RevisionSelectionMode::EXACT then ref_name
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
1
|
+
module MultiRepo
|
2
|
+
class RevisionSelectionMode
|
3
|
+
AS_LOCK = 0
|
4
|
+
LATEST = 1
|
5
|
+
EXACT = 2
|
6
|
+
|
7
|
+
def self.name_for_mode(mode)
|
8
|
+
case mode
|
9
|
+
when AS_LOCK then "as-lock"
|
10
|
+
when LATEST then "latest"
|
11
|
+
when EXACT then "exact"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class RevisionSelector
|
17
|
+
def self.mode_for_args(checkout_latest, checkout_exact)
|
18
|
+
if checkout_latest
|
19
|
+
RevisionSelectionMode::LATEST
|
20
|
+
elsif checkout_exact
|
21
|
+
RevisionSelectionMode::EXACT
|
22
|
+
else
|
23
|
+
RevisionSelectionMode::AS_LOCK
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.revision_for_mode(mode, ref_name, lock_entry)
|
28
|
+
case mode
|
29
|
+
when RevisionSelectionMode::AS_LOCK then lock_entry.head
|
30
|
+
when RevisionSelectionMode::LATEST then lock_entry.branch
|
31
|
+
when RevisionSelectionMode::EXACT then ref_name
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
|
-
require "claide/informative_error"
|
2
|
-
|
3
|
-
module MultiRepo
|
4
|
-
class MultiRepoException < StandardError
|
5
|
-
end
|
6
|
-
end
|
1
|
+
require "claide/informative_error"
|
2
|
+
|
3
|
+
module MultiRepo
|
4
|
+
class MultiRepoException < StandardError
|
5
|
+
end
|
6
|
+
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.
|
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,95 +1,95 @@
|
|
1
|
-
require "multirepo/multirepo-exception"
|
2
|
-
require "fileutils"
|
3
|
-
|
4
|
-
module MultiRepo
|
5
|
-
class Utils
|
6
|
-
def self.path_for_resource(resource_name)
|
7
|
-
gem_path = Gem::Specification.find_by_name("git-multirepo").gem_dir
|
8
|
-
File.join(gem_path, "resources/#{resource_name}")
|
9
|
-
end
|
10
|
-
|
11
|
-
def self.multirepo_enabled?(path)
|
12
|
-
File.exist?(File.join(path, ".multirepo"))
|
13
|
-
end
|
14
|
-
|
15
|
-
def self.multirepo_tracked?(path)
|
16
|
-
multirepo_enabled?(path) && File.exist?(File.join(path, ".multirepo.lock"))
|
17
|
-
end
|
18
|
-
|
19
|
-
def self.install_hook(name, path)
|
20
|
-
destination_path = File.join(path, ".git/hooks")
|
21
|
-
destination_file = File.join(destination_path, name)
|
22
|
-
FileUtils.cp(path_for_resource(name), destination_file)
|
23
|
-
FileUtils.chmod(0755, destination_file) # -rwxr-xr-x
|
24
|
-
end
|
25
|
-
|
26
|
-
def self.sibling_repos
|
27
|
-
sibling_directories = Dir['../*/']
|
28
|
-
sibling_repos = sibling_directories.map{ |d| Repo.new(d) }.select(&:exists?)
|
29
|
-
sibling_repos.delete_if{ |r| Pathname.new(r.path).realpath == Pathname.new(".").realpath }
|
30
|
-
end
|
31
|
-
|
32
|
-
def self.dependencies_clean?(config_entries)
|
33
|
-
clean = true
|
34
|
-
missing = false
|
35
|
-
config_entries.each do |e|
|
36
|
-
# Ensure the dependency exists
|
37
|
-
unless e.repo.exists?
|
38
|
-
Console.log_error("Dependency '#{e.path}' does not exist on disk")
|
39
|
-
missing |= true
|
40
|
-
next
|
41
|
-
end
|
42
|
-
|
43
|
-
# Ensure it contains no uncommitted changes
|
44
|
-
dependency_clean = e.repo.clean?
|
45
|
-
clean &= dependency_clean
|
46
|
-
Console.log_warning("Dependency '#{e.repo.path}' contains uncommitted changes") unless dependency_clean
|
47
|
-
end
|
48
|
-
|
49
|
-
fail MultiRepoException, "Some dependencies are not present on this machine." \
|
50
|
-
" Run \"multi install\" to clone missing dependencies." if missing
|
51
|
-
|
52
|
-
return clean
|
53
|
-
end
|
54
|
-
|
55
|
-
def self.ensure_working_copies_clean(repos)
|
56
|
-
clean = true
|
57
|
-
repos.each do |repo|
|
58
|
-
dependency_clean = repo.clean?
|
59
|
-
clean &= dependency_clean
|
60
|
-
Console.log_warning("Repo '#{repo.path}' contains uncommitted changes") unless dependency_clean
|
61
|
-
end
|
62
|
-
return clean
|
63
|
-
end
|
64
|
-
|
65
|
-
def self.convert_to_windows_path(unix_path)
|
66
|
-
components = Pathname.new(unix_path).each_filename.to_a
|
67
|
-
components.join(File::ALT_SEPARATOR)
|
68
|
-
end
|
69
|
-
|
70
|
-
def self.reveal_in_default_file_browser(unix_path)
|
71
|
-
if OS.osx?
|
72
|
-
system %(open "#{unix_path}")
|
73
|
-
elsif OS.windows?
|
74
|
-
system %(explorer "#{Utils.convert_to_windows_path(unix_path)}")
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
def self.open_in_default_app(unix_path)
|
79
|
-
if OS.osx?
|
80
|
-
system %(open "#{unix_path}")
|
81
|
-
elsif OS.windows?
|
82
|
-
system %(cmd /c "start C:\\#{Utils.convert_to_windows_path(unix_path)}")
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
def self.append_if_missing(path, pattern, string_to_append)
|
87
|
-
if File.exist?(path)
|
88
|
-
string_located = File.readlines(path).grep(pattern).any?
|
89
|
-
File.open(path, 'a') { |f| f.puts(string_to_append) } unless string_located
|
90
|
-
else
|
91
|
-
File.open(path, 'w') { |f| f.puts(string_to_append) }
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
1
|
+
require "multirepo/multirepo-exception"
|
2
|
+
require "fileutils"
|
3
|
+
|
4
|
+
module MultiRepo
|
5
|
+
class Utils
|
6
|
+
def self.path_for_resource(resource_name)
|
7
|
+
gem_path = Gem::Specification.find_by_name("git-multirepo").gem_dir
|
8
|
+
File.join(gem_path, "resources/#{resource_name}")
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.multirepo_enabled?(path)
|
12
|
+
File.exist?(File.join(path, ".multirepo"))
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.multirepo_tracked?(path)
|
16
|
+
multirepo_enabled?(path) && File.exist?(File.join(path, ".multirepo.lock"))
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.install_hook(name, path)
|
20
|
+
destination_path = File.join(path, ".git/hooks")
|
21
|
+
destination_file = File.join(destination_path, name)
|
22
|
+
FileUtils.cp(path_for_resource(name), destination_file)
|
23
|
+
FileUtils.chmod(0755, destination_file) # -rwxr-xr-x
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.sibling_repos
|
27
|
+
sibling_directories = Dir['../*/']
|
28
|
+
sibling_repos = sibling_directories.map{ |d| Repo.new(d) }.select(&:exists?)
|
29
|
+
sibling_repos.delete_if{ |r| Pathname.new(r.path).realpath == Pathname.new(".").realpath }
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.dependencies_clean?(config_entries)
|
33
|
+
clean = true
|
34
|
+
missing = false
|
35
|
+
config_entries.each do |e|
|
36
|
+
# Ensure the dependency exists
|
37
|
+
unless e.repo.exists?
|
38
|
+
Console.log_error("Dependency '#{e.path}' does not exist on disk")
|
39
|
+
missing |= true
|
40
|
+
next
|
41
|
+
end
|
42
|
+
|
43
|
+
# Ensure it contains no uncommitted changes
|
44
|
+
dependency_clean = e.repo.clean?
|
45
|
+
clean &= dependency_clean
|
46
|
+
Console.log_warning("Dependency '#{e.repo.path}' contains uncommitted changes") unless dependency_clean
|
47
|
+
end
|
48
|
+
|
49
|
+
fail MultiRepoException, "Some dependencies are not present on this machine." \
|
50
|
+
" Run \"multi install\" to clone missing dependencies." if missing
|
51
|
+
|
52
|
+
return clean
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.ensure_working_copies_clean(repos)
|
56
|
+
clean = true
|
57
|
+
repos.each do |repo|
|
58
|
+
dependency_clean = repo.clean?
|
59
|
+
clean &= dependency_clean
|
60
|
+
Console.log_warning("Repo '#{repo.path}' contains uncommitted changes") unless dependency_clean
|
61
|
+
end
|
62
|
+
return clean
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.convert_to_windows_path(unix_path)
|
66
|
+
components = Pathname.new(unix_path).each_filename.to_a
|
67
|
+
components.join(File::ALT_SEPARATOR)
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.reveal_in_default_file_browser(unix_path)
|
71
|
+
if OS.osx?
|
72
|
+
system %(open "#{unix_path}")
|
73
|
+
elsif OS.windows?
|
74
|
+
system %(explorer "#{Utils.convert_to_windows_path(unix_path)}")
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.open_in_default_app(unix_path)
|
79
|
+
if OS.osx?
|
80
|
+
system %(open "#{unix_path}")
|
81
|
+
elsif OS.windows?
|
82
|
+
system %(cmd /c "start C:\\#{Utils.convert_to_windows_path(unix_path)}")
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.append_if_missing(path, pattern, string_to_append)
|
87
|
+
if File.exist?(path)
|
88
|
+
string_located = File.readlines(path).grep(pattern).any?
|
89
|
+
File.open(path, 'a') { |f| f.puts(string_to_append) } unless string_located
|
90
|
+
else
|
91
|
+
File.open(path, 'w') { |f| f.puts(string_to_append) }
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|