git-multirepo 1.0.0.beta21 → 1.0.0.beta24
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/.gitignore +38 -38
- data/.rspec +2 -2
- data/Gemfile +4 -4
- data/Gemfile.lock +37 -37
- data/LICENSE +22 -22
- data/README.md +141 -139
- data/Rakefile +2 -2
- data/bin/multi +10 -10
- data/docs/git-multirepo-cheatsheet.docx +0 -0
- data/git-multirepo.gemspec +29 -29
- data/lib/commands.rb +11 -11
- data/lib/git-multirepo.rb +2 -2
- data/lib/info.rb +4 -4
- data/lib/multirepo/commands/add-command.rb +51 -51
- data/lib/multirepo/commands/branch-command.rb +52 -52
- data/lib/multirepo/commands/checkout-command.rb +119 -119
- data/lib/multirepo/commands/clone-command.rb +69 -69
- data/lib/multirepo/commands/command.rb +58 -50
- data/lib/multirepo/commands/fetch-command.rb +23 -23
- data/lib/multirepo/commands/init-command.rb +51 -51
- data/lib/multirepo/commands/install-command.rb +87 -87
- data/lib/multirepo/commands/open-command.rb +25 -25
- data/lib/multirepo/commands/remove-command.rb +48 -48
- data/lib/multirepo/commands/uninit-command.rb +20 -20
- data/lib/multirepo/commands/update-command.rb +47 -47
- data/lib/multirepo/config.rb +15 -12
- data/lib/multirepo/files/config-entry.rb +34 -34
- data/lib/multirepo/files/config-file.rb +37 -37
- data/lib/multirepo/files/lock-entry.rb +25 -25
- data/lib/multirepo/files/lock-file.rb +39 -39
- data/lib/multirepo/git/branch.rb +27 -27
- data/lib/multirepo/git/change.rb +10 -10
- data/lib/multirepo/git/git.rb +42 -38
- data/lib/multirepo/git/remote.rb +15 -15
- data/lib/multirepo/git/repo.rb +66 -66
- data/lib/multirepo/hooks/post-merge-hook.rb +19 -19
- data/lib/multirepo/hooks/pre-commit-hook.rb +25 -25
- data/lib/multirepo/hooks/prepare-commit-msg-hook.rb +27 -27
- data/lib/multirepo/multirepo-exception.rb +5 -5
- data/lib/multirepo/utility/console.rb +51 -51
- data/lib/multirepo/utility/runner.rb +32 -32
- data/lib/multirepo/utility/utils.rb +51 -51
- data/resources/post-merge +5 -5
- data/resources/pre-commit +5 -5
- data/resources/prepare-commit-msg +5 -5
- data/spec/integration/init_spec.rb +22 -22
- data/spec/spec_helper.rb +89 -89
- metadata +4 -3
data/Rakefile
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
require "bundler/gem_tasks"
|
2
|
-
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
|
data/bin/multi
CHANGED
@@ -1,11 +1,11 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require "claide"
|
4
|
-
require "commands"
|
5
|
-
|
6
|
-
trap("INT") do
|
7
|
-
puts "\rAbort, abort!!" # \r hides the interrupt control characters
|
8
|
-
exit
|
9
|
-
end
|
10
|
-
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "claide"
|
4
|
+
require "commands"
|
5
|
+
|
6
|
+
trap("INT") do
|
7
|
+
puts "\rAbort, abort!!" # \r hides the interrupt control characters
|
8
|
+
exit
|
9
|
+
end
|
10
|
+
|
11
11
|
MultiRepo::Command.run(ARGV)
|
Binary file
|
data/git-multirepo.gemspec
CHANGED
@@ -1,29 +1,29 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require 'info'
|
5
|
-
|
6
|
-
Gem::Specification.new do |spec|
|
7
|
-
spec.name = MultiRepo::NAME
|
8
|
-
spec.version = MultiRepo::VERSION
|
9
|
-
spec.authors = ["Michaël Fortin"]
|
10
|
-
spec.email = ["fortinmike@irradiated.net"]
|
11
|
-
spec.summary = %q{Track multiple Git repositories side-by-side}
|
12
|
-
spec.description = MultiRepo::DESCRIPTION
|
13
|
-
spec.homepage = "https://github.com/fortinmike/git-multirepo"
|
14
|
-
spec.license = "MIT"
|
15
|
-
|
16
|
-
spec.required_ruby_version = '~> 2.0'
|
17
|
-
spec.files = `git ls-files -z`.split("\x0")
|
18
|
-
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
|
-
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
|
-
spec.require_paths = ["lib"]
|
21
|
-
|
22
|
-
spec.add_development_dependency "bundler", "~> 1.7"
|
23
|
-
spec.add_development_dependency "rake", "~> 10.0"
|
24
|
-
spec.add_development_dependency "rspec", "~> 3.1.0"
|
25
|
-
|
26
|
-
spec.add_runtime_dependency "claide", "~> 0.8", ">= 0.8.0"
|
27
|
-
spec.add_runtime_dependency "colored", "~> 1.2"
|
28
|
-
spec.add_runtime_dependency "os", "~> 0.9.6"
|
29
|
-
end
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'info'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = MultiRepo::NAME
|
8
|
+
spec.version = MultiRepo::VERSION
|
9
|
+
spec.authors = ["Michaël Fortin"]
|
10
|
+
spec.email = ["fortinmike@irradiated.net"]
|
11
|
+
spec.summary = %q{Track multiple Git repositories side-by-side}
|
12
|
+
spec.description = MultiRepo::DESCRIPTION
|
13
|
+
spec.homepage = "https://github.com/fortinmike/git-multirepo"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.required_ruby_version = '~> 2.0'
|
17
|
+
spec.files = `git ls-files -z`.split("\x0")
|
18
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
23
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
24
|
+
spec.add_development_dependency "rspec", "~> 3.1.0"
|
25
|
+
|
26
|
+
spec.add_runtime_dependency "claide", "~> 0.8", ">= 0.8.0"
|
27
|
+
spec.add_runtime_dependency "colored", "~> 1.2"
|
28
|
+
spec.add_runtime_dependency "os", "~> 0.9.6"
|
29
|
+
end
|
data/lib/commands.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
|
-
require_relative "multirepo/commands/command"
|
2
|
-
require_relative "multirepo/commands/add-command"
|
3
|
-
require_relative "multirepo/commands/branch-command"
|
4
|
-
require_relative "multirepo/commands/checkout-command"
|
5
|
-
require_relative "multirepo/commands/clone-command"
|
6
|
-
require_relative "multirepo/commands/fetch-command"
|
7
|
-
require_relative "multirepo/commands/init-command"
|
8
|
-
require_relative "multirepo/commands/install-command"
|
9
|
-
require_relative "multirepo/commands/open-command"
|
10
|
-
require_relative "multirepo/commands/remove-command"
|
11
|
-
require_relative "multirepo/commands/uninit-command"
|
1
|
+
require_relative "multirepo/commands/command"
|
2
|
+
require_relative "multirepo/commands/add-command"
|
3
|
+
require_relative "multirepo/commands/branch-command"
|
4
|
+
require_relative "multirepo/commands/checkout-command"
|
5
|
+
require_relative "multirepo/commands/clone-command"
|
6
|
+
require_relative "multirepo/commands/fetch-command"
|
7
|
+
require_relative "multirepo/commands/init-command"
|
8
|
+
require_relative "multirepo/commands/install-command"
|
9
|
+
require_relative "multirepo/commands/open-command"
|
10
|
+
require_relative "multirepo/commands/remove-command"
|
11
|
+
require_relative "multirepo/commands/uninit-command"
|
12
12
|
require_relative "multirepo/commands/update-command"
|
data/lib/git-multirepo.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
require "multirepo/hooks/pre-commit-hook.rb"
|
2
|
-
require "multirepo/hooks/prepare-commit-msg-hook.rb"
|
1
|
+
require "multirepo/hooks/pre-commit-hook.rb"
|
2
|
+
require "multirepo/hooks/prepare-commit-msg-hook.rb"
|
3
3
|
require "multirepo/hooks/post-merge-hook.rb"
|
data/lib/info.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
module MultiRepo
|
2
|
-
NAME = "git-multirepo"
|
3
|
-
VERSION = "1.0.0.
|
4
|
-
DESCRIPTION = "Track multiple Git repositories side-by-side."
|
1
|
+
module MultiRepo
|
2
|
+
NAME = "git-multirepo"
|
3
|
+
VERSION = "1.0.0.beta24"
|
4
|
+
DESCRIPTION = "Track multiple Git repositories side-by-side."
|
5
5
|
end
|
@@ -1,52 +1,52 @@
|
|
1
|
-
require "multirepo/utility/console"
|
2
|
-
require "multirepo/files/config-file"
|
3
|
-
|
4
|
-
module MultiRepo
|
5
|
-
class AddCommand < Command
|
6
|
-
self.command = "add"
|
7
|
-
self.summary = "Track an additional dependency with multirepo."
|
8
|
-
|
9
|
-
def self.options
|
10
|
-
[['
|
11
|
-
end
|
12
|
-
|
13
|
-
def initialize(argv)
|
14
|
-
@path = argv.shift_argument
|
15
|
-
super
|
16
|
-
end
|
17
|
-
|
18
|
-
def validate!
|
19
|
-
super
|
20
|
-
help! "You must specify a repository to add as a dependency" unless @path
|
21
|
-
end
|
22
|
-
|
23
|
-
def run
|
24
|
-
validate_in_work_tree
|
25
|
-
ensure_multirepo_initialized
|
26
|
-
ensure_repo_valid
|
27
|
-
|
28
|
-
entry = ConfigEntry.new(Repo.new(@path))
|
29
|
-
if ConfigFile.entry_exists?(entry)
|
30
|
-
Console.log_info("There is already an entry for '#{@path}' in the .multirepo file")
|
31
|
-
else
|
32
|
-
ConfigFile.add_entry(entry)
|
33
|
-
ConfigFile.stage
|
34
|
-
Console.log_step("Added '#{@path}' to the .multirepo file")
|
35
|
-
end
|
36
|
-
rescue MultiRepoException => e
|
37
|
-
Console.log_error(e.message)
|
38
|
-
end
|
39
|
-
|
40
|
-
def ensure_repo_valid
|
41
|
-
raise MultiRepoException, "The provided path is not a direct sibling of the main repository" unless validate_is_sibling_repo(@path)
|
42
|
-
raise MultiRepoException, "There is no folder at path '#{@path}'" unless Dir.exists?(@path)
|
43
|
-
raise MultiRepoException, "'#{@path}' is not a repository" unless Repo.new(@path).exists?
|
44
|
-
end
|
45
|
-
|
46
|
-
def validate_is_sibling_repo(path)
|
47
|
-
parent_dir = File.expand_path("..")
|
48
|
-
path = File.expand_path("..", path)
|
49
|
-
return parent_dir == path
|
50
|
-
end
|
51
|
-
end
|
1
|
+
require "multirepo/utility/console"
|
2
|
+
require "multirepo/files/config-file"
|
3
|
+
|
4
|
+
module MultiRepo
|
5
|
+
class AddCommand < Command
|
6
|
+
self.command = "add"
|
7
|
+
self.summary = "Track an additional dependency with multirepo."
|
8
|
+
|
9
|
+
def self.options
|
10
|
+
[['<path>', 'The relative path to the new dependency (e.g. ../MyNewDependency)']].concat(super)
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(argv)
|
14
|
+
@path = argv.shift_argument
|
15
|
+
super
|
16
|
+
end
|
17
|
+
|
18
|
+
def validate!
|
19
|
+
super
|
20
|
+
help! "You must specify a repository to add as a dependency" unless @path
|
21
|
+
end
|
22
|
+
|
23
|
+
def run
|
24
|
+
validate_in_work_tree
|
25
|
+
ensure_multirepo_initialized
|
26
|
+
ensure_repo_valid
|
27
|
+
|
28
|
+
entry = ConfigEntry.new(Repo.new(@path))
|
29
|
+
if ConfigFile.entry_exists?(entry)
|
30
|
+
Console.log_info("There is already an entry for '#{@path}' in the .multirepo file")
|
31
|
+
else
|
32
|
+
ConfigFile.add_entry(entry)
|
33
|
+
ConfigFile.stage
|
34
|
+
Console.log_step("Added '#{@path}' to the .multirepo file")
|
35
|
+
end
|
36
|
+
rescue MultiRepoException => e
|
37
|
+
Console.log_error(e.message)
|
38
|
+
end
|
39
|
+
|
40
|
+
def ensure_repo_valid
|
41
|
+
raise MultiRepoException, "The provided path is not a direct sibling of the main repository" unless validate_is_sibling_repo(@path)
|
42
|
+
raise MultiRepoException, "There is no folder at path '#{@path}'" unless Dir.exists?(@path)
|
43
|
+
raise MultiRepoException, "'#{@path}' is not a repository" unless Repo.new(@path).exists?
|
44
|
+
end
|
45
|
+
|
46
|
+
def validate_is_sibling_repo(path)
|
47
|
+
parent_dir = File.expand_path("..")
|
48
|
+
path = File.expand_path("..", path)
|
49
|
+
return parent_dir == path
|
50
|
+
end
|
51
|
+
end
|
52
52
|
end
|
@@ -1,53 +1,53 @@
|
|
1
|
-
require "multirepo/utility/console"
|
2
|
-
require "multirepo/files/config-file"
|
3
|
-
|
4
|
-
module MultiRepo
|
5
|
-
class BranchCommand < Command
|
6
|
-
self.command = "branch"
|
7
|
-
self.summary = "Create and/or checkout a new branch for all repos."
|
8
|
-
|
9
|
-
def self.options
|
10
|
-
[
|
11
|
-
['
|
12
|
-
['--force', 'Force creating the branch even if the repos contain uncommmitted changes.'],
|
13
|
-
['--no-track', 'Do not configure as a remote-tracking branch on creation.']
|
14
|
-
].concat(super)
|
15
|
-
end
|
16
|
-
|
17
|
-
def initialize(argv)
|
18
|
-
@branch_name = argv.shift_argument
|
19
|
-
@force = argv.flag?("force")
|
20
|
-
@remote_tracking = !argv.flag?("no-track")
|
21
|
-
super
|
22
|
-
end
|
23
|
-
|
24
|
-
def validate!
|
25
|
-
super
|
26
|
-
help! "You must specify a branch name" unless @branch_name
|
27
|
-
end
|
28
|
-
|
29
|
-
def run
|
30
|
-
validate_in_work_tree
|
31
|
-
ensure_multirepo_initialized
|
32
|
-
|
33
|
-
Console.log_step("Branching and checking out #{@branch_name}...")
|
34
|
-
|
35
|
-
main_repo = main_repo = Repo.new(".")
|
36
|
-
repos = ConfigFile.load.map{ |entry| entry.repo }.push(main_repo)
|
37
|
-
|
38
|
-
if !Utils.ensure_working_copies_clean(repos) && !@force
|
39
|
-
raise MultiRepoException, "Can't branch because not all repos are clean"
|
40
|
-
end
|
41
|
-
|
42
|
-
repos.each do |repo|
|
43
|
-
branch = repo.branch(@branch_name)
|
44
|
-
branch.create(@remote_tracking) unless branch.exists?
|
45
|
-
branch.checkout
|
46
|
-
end
|
47
|
-
|
48
|
-
Console.log_step("Done!")
|
49
|
-
rescue MultiRepoException => e
|
50
|
-
Console.log_error(e.message)
|
51
|
-
end
|
52
|
-
end
|
1
|
+
require "multirepo/utility/console"
|
2
|
+
require "multirepo/files/config-file"
|
3
|
+
|
4
|
+
module MultiRepo
|
5
|
+
class BranchCommand < Command
|
6
|
+
self.command = "branch"
|
7
|
+
self.summary = "Create and/or checkout a new branch for all repos."
|
8
|
+
|
9
|
+
def self.options
|
10
|
+
[
|
11
|
+
['<branch name>', 'The name of the branch to create and checkout.'],
|
12
|
+
['[--force]', 'Force creating the branch even if the repos contain uncommmitted changes.'],
|
13
|
+
['[--no-track]', 'Do not configure as a remote-tracking branch on creation.']
|
14
|
+
].concat(super)
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(argv)
|
18
|
+
@branch_name = argv.shift_argument
|
19
|
+
@force = argv.flag?("force")
|
20
|
+
@remote_tracking = !argv.flag?("no-track")
|
21
|
+
super
|
22
|
+
end
|
23
|
+
|
24
|
+
def validate!
|
25
|
+
super
|
26
|
+
help! "You must specify a branch name" unless @branch_name
|
27
|
+
end
|
28
|
+
|
29
|
+
def run
|
30
|
+
validate_in_work_tree
|
31
|
+
ensure_multirepo_initialized
|
32
|
+
|
33
|
+
Console.log_step("Branching and checking out #{@branch_name}...")
|
34
|
+
|
35
|
+
main_repo = main_repo = Repo.new(".")
|
36
|
+
repos = ConfigFile.load.map{ |entry| entry.repo }.push(main_repo)
|
37
|
+
|
38
|
+
if !Utils.ensure_working_copies_clean(repos) && !@force
|
39
|
+
raise MultiRepoException, "Can't branch because not all repos are clean"
|
40
|
+
end
|
41
|
+
|
42
|
+
repos.each do |repo|
|
43
|
+
branch = repo.branch(@branch_name)
|
44
|
+
branch.create(@remote_tracking) unless branch.exists?
|
45
|
+
branch.checkout
|
46
|
+
end
|
47
|
+
|
48
|
+
Console.log_step("Done!")
|
49
|
+
rescue MultiRepoException => e
|
50
|
+
Console.log_error(e.message)
|
51
|
+
end
|
52
|
+
end
|
53
53
|
end
|
@@ -1,120 +1,120 @@
|
|
1
|
-
require "multirepo/utility/console"
|
2
|
-
|
3
|
-
module MultiRepo
|
4
|
-
class CheckoutCommand < Command
|
5
|
-
self.command = "checkout"
|
6
|
-
self.summary = "Checks out the specified commit or branch of the main repo and checks out matching versions of all dependencies."
|
7
|
-
|
8
|
-
class CheckoutMode
|
9
|
-
AS_LOCK = 0
|
10
|
-
LATEST = 1
|
11
|
-
EXACT = 2
|
12
|
-
end
|
13
|
-
|
14
|
-
def self.options
|
15
|
-
[
|
16
|
-
['
|
17
|
-
['--latest', 'Checkout the HEAD of each dependency branch (as recorded in the lock file) instead of the exact required commits.'],
|
18
|
-
['--exact', 'Checkout the exact specified ref for each repo, regardless of what\'s stored in the lock file.']
|
19
|
-
].concat(super)
|
20
|
-
end
|
21
|
-
|
22
|
-
def initialize(argv)
|
23
|
-
@ref = argv.shift_argument
|
24
|
-
@checkout_latest = argv.flag?("latest")
|
25
|
-
@checkout_exact = argv.flag?("exact")
|
26
|
-
super
|
27
|
-
end
|
28
|
-
|
29
|
-
def validate!
|
30
|
-
super
|
31
|
-
help! "You must specify a branch or commit id to checkout" unless @ref
|
32
|
-
help! "You can't provide more than one operation modifier (--latest, --exact, etc.)" if @checkout_latest && @checkout_exact
|
33
|
-
end
|
34
|
-
|
35
|
-
def run
|
36
|
-
validate_in_work_tree
|
37
|
-
ensure_multirepo_initialized
|
38
|
-
|
39
|
-
Console.log_step("Checking out #{@ref} and its dependencies...")
|
40
|
-
|
41
|
-
# Find out the checkout mode based on command-line options
|
42
|
-
mode = if @checkout_latest then
|
43
|
-
CheckoutMode::LATEST
|
44
|
-
elsif @checkout_exact then
|
45
|
-
CheckoutMode::EXACT
|
46
|
-
else
|
47
|
-
CheckoutMode::AS_LOCK
|
48
|
-
end
|
49
|
-
|
50
|
-
main_repo = Repo.new(".")
|
51
|
-
initial_revision = main_repo.current_branch || main_repo.head_hash
|
52
|
-
|
53
|
-
main_repo_checkout_step(main_repo, initial_revision, @ref)
|
54
|
-
ensure_dependencies_clean_step(initial_revision)
|
55
|
-
dependencies_checkout_step(mode, @ref)
|
56
|
-
|
57
|
-
Console.log_step("Done!")
|
58
|
-
rescue MultiRepoException => e
|
59
|
-
Console.log_error(e.message)
|
60
|
-
end
|
61
|
-
|
62
|
-
def main_repo_checkout_step(main_repo, initial_revision, ref)
|
63
|
-
# Make sure the main repo is clean before attempting a checkout
|
64
|
-
unless main_repo.is_clean?
|
65
|
-
raise MultiRepoException, "Can't checkout #{ref} because the main repo contains uncommitted changes"
|
66
|
-
end
|
67
|
-
|
68
|
-
# Checkout the specified ref
|
69
|
-
unless main_repo.checkout(ref)
|
70
|
-
raise MultiRepoException, "Couldn't perform checkout of main repo #{ref}!"
|
71
|
-
end
|
72
|
-
|
73
|
-
Console.log_substep("Checked out main repo #{ref}")
|
74
|
-
|
75
|
-
# After checkout, make sure we're working with a multirepo-enabled ref
|
76
|
-
unless Utils.is_multirepo_enabled(".")
|
77
|
-
main_repo.checkout(initial_revision)
|
78
|
-
raise MultiRepoException, "This revision is not managed by multirepo. Checkout reverted."
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
def ensure_dependencies_clean_step(initial_revision)
|
83
|
-
unless Utils.ensure_dependencies_clean(ConfigFile.load)
|
84
|
-
main_repo.checkout(initial_revision)
|
85
|
-
raise MultiRepoException, "Checkout reverted."
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
def dependencies_checkout_step(mode, ref = nil)
|
90
|
-
config_entries = ConfigFile.load # Post-main-repo checkout config entries might be different than pre-checkout
|
91
|
-
LockFile.load.each { |lock_entry| perform_dependency_checkout(config_entries, lock_entry, ref, mode) }
|
92
|
-
end
|
93
|
-
|
94
|
-
def perform_dependency_checkout(config_entries, lock_entry, ref, mode)
|
95
|
-
# Find the config entry that matches the given lock entry
|
96
|
-
config_entry = config_entries.select{ |config_entry| config_entry.id == lock_entry.id }.first
|
97
|
-
|
98
|
-
# Make sure the repo exists on disk, and clone it if it doesn't
|
99
|
-
# (in case the checked-out revision had an additional dependency)
|
100
|
-
unless config_entry.repo.exists?
|
101
|
-
Console.log_substep("Cloning missing dependency '#{config_entry.path}' from #{config_entry.url}")
|
102
|
-
config_entry.repo.clone(config_entry.url)
|
103
|
-
end
|
104
|
-
|
105
|
-
# Find out the proper revision to checkout based on the checkout mode
|
106
|
-
revision = case mode
|
107
|
-
when CheckoutMode::AS_LOCK; lock_entry.head
|
108
|
-
when CheckoutMode::LATEST; lock_entry.branch
|
109
|
-
when CheckoutMode::EXACT; ref
|
110
|
-
end
|
111
|
-
|
112
|
-
# Checkout!
|
113
|
-
if config_entry.repo.checkout(revision)
|
114
|
-
Console.log_substep("Checked out #{lock_entry.name} #{revision}")
|
115
|
-
else
|
116
|
-
raise MultiRepoException, "Couldn't check out the appropriate version of dependency #{lock_entry.name}"
|
117
|
-
end
|
118
|
-
end
|
119
|
-
end
|
1
|
+
require "multirepo/utility/console"
|
2
|
+
|
3
|
+
module MultiRepo
|
4
|
+
class CheckoutCommand < Command
|
5
|
+
self.command = "checkout"
|
6
|
+
self.summary = "Checks out the specified commit or branch of the main repo and checks out matching versions of all dependencies."
|
7
|
+
|
8
|
+
class CheckoutMode
|
9
|
+
AS_LOCK = 0
|
10
|
+
LATEST = 1
|
11
|
+
EXACT = 2
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.options
|
15
|
+
[
|
16
|
+
['<ref>', 'The main repo tag, branch or commit id to checkout.'],
|
17
|
+
['[--latest]', 'Checkout the HEAD of each dependency branch (as recorded in the lock file) instead of the exact required commits.'],
|
18
|
+
['[--exact]', 'Checkout the exact specified ref for each repo, regardless of what\'s stored in the lock file.']
|
19
|
+
].concat(super)
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize(argv)
|
23
|
+
@ref = argv.shift_argument
|
24
|
+
@checkout_latest = argv.flag?("latest")
|
25
|
+
@checkout_exact = argv.flag?("exact")
|
26
|
+
super
|
27
|
+
end
|
28
|
+
|
29
|
+
def validate!
|
30
|
+
super
|
31
|
+
help! "You must specify a branch or commit id to checkout" unless @ref
|
32
|
+
help! "You can't provide more than one operation modifier (--latest, --exact, etc.)" if @checkout_latest && @checkout_exact
|
33
|
+
end
|
34
|
+
|
35
|
+
def run
|
36
|
+
validate_in_work_tree
|
37
|
+
ensure_multirepo_initialized
|
38
|
+
|
39
|
+
Console.log_step("Checking out #{@ref} and its dependencies...")
|
40
|
+
|
41
|
+
# Find out the checkout mode based on command-line options
|
42
|
+
mode = if @checkout_latest then
|
43
|
+
CheckoutMode::LATEST
|
44
|
+
elsif @checkout_exact then
|
45
|
+
CheckoutMode::EXACT
|
46
|
+
else
|
47
|
+
CheckoutMode::AS_LOCK
|
48
|
+
end
|
49
|
+
|
50
|
+
main_repo = Repo.new(".")
|
51
|
+
initial_revision = main_repo.current_branch || main_repo.head_hash
|
52
|
+
|
53
|
+
main_repo_checkout_step(main_repo, initial_revision, @ref)
|
54
|
+
ensure_dependencies_clean_step(initial_revision)
|
55
|
+
dependencies_checkout_step(mode, @ref)
|
56
|
+
|
57
|
+
Console.log_step("Done!")
|
58
|
+
rescue MultiRepoException => e
|
59
|
+
Console.log_error(e.message)
|
60
|
+
end
|
61
|
+
|
62
|
+
def main_repo_checkout_step(main_repo, initial_revision, ref)
|
63
|
+
# Make sure the main repo is clean before attempting a checkout
|
64
|
+
unless main_repo.is_clean?
|
65
|
+
raise MultiRepoException, "Can't checkout #{ref} because the main repo contains uncommitted changes"
|
66
|
+
end
|
67
|
+
|
68
|
+
# Checkout the specified ref
|
69
|
+
unless main_repo.checkout(ref)
|
70
|
+
raise MultiRepoException, "Couldn't perform checkout of main repo #{ref}!"
|
71
|
+
end
|
72
|
+
|
73
|
+
Console.log_substep("Checked out main repo #{ref}")
|
74
|
+
|
75
|
+
# After checkout, make sure we're working with a multirepo-enabled ref
|
76
|
+
unless Utils.is_multirepo_enabled(".")
|
77
|
+
main_repo.checkout(initial_revision)
|
78
|
+
raise MultiRepoException, "This revision is not managed by multirepo. Checkout reverted."
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def ensure_dependencies_clean_step(initial_revision)
|
83
|
+
unless Utils.ensure_dependencies_clean(ConfigFile.load)
|
84
|
+
main_repo.checkout(initial_revision)
|
85
|
+
raise MultiRepoException, "Checkout reverted."
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def dependencies_checkout_step(mode, ref = nil)
|
90
|
+
config_entries = ConfigFile.load # Post-main-repo checkout config entries might be different than pre-checkout
|
91
|
+
LockFile.load.each { |lock_entry| perform_dependency_checkout(config_entries, lock_entry, ref, mode) }
|
92
|
+
end
|
93
|
+
|
94
|
+
def perform_dependency_checkout(config_entries, lock_entry, ref, mode)
|
95
|
+
# Find the config entry that matches the given lock entry
|
96
|
+
config_entry = config_entries.select{ |config_entry| config_entry.id == lock_entry.id }.first
|
97
|
+
|
98
|
+
# Make sure the repo exists on disk, and clone it if it doesn't
|
99
|
+
# (in case the checked-out revision had an additional dependency)
|
100
|
+
unless config_entry.repo.exists?
|
101
|
+
Console.log_substep("Cloning missing dependency '#{config_entry.path}' from #{config_entry.url}")
|
102
|
+
config_entry.repo.clone(config_entry.url)
|
103
|
+
end
|
104
|
+
|
105
|
+
# Find out the proper revision to checkout based on the checkout mode
|
106
|
+
revision = case mode
|
107
|
+
when CheckoutMode::AS_LOCK; lock_entry.head
|
108
|
+
when CheckoutMode::LATEST; lock_entry.branch
|
109
|
+
when CheckoutMode::EXACT; ref
|
110
|
+
end
|
111
|
+
|
112
|
+
# Checkout!
|
113
|
+
if config_entry.repo.checkout(revision)
|
114
|
+
Console.log_substep("Checked out #{lock_entry.name} #{revision}")
|
115
|
+
else
|
116
|
+
raise MultiRepoException, "Couldn't check out the appropriate version of dependency #{lock_entry.name}"
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
120
|
end
|