git-multirepo 1.0.0.beta51 → 1.0.0.beta52

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +2 -2
  3. data/.gitbugtraq +3 -3
  4. data/.gitignore +38 -38
  5. data/.multirepo.meta +2 -2
  6. data/.rspec +2 -2
  7. data/.rubocop.yml +79 -79
  8. data/CHANGELOG.md +48 -43
  9. data/Gemfile +4 -4
  10. data/Gemfile.lock +42 -42
  11. data/LICENSE +22 -22
  12. data/README.md +178 -154
  13. data/Rakefile +1 -1
  14. data/bin/multi +11 -11
  15. data/docs/bug-repros/91565510-repro.sh +20 -20
  16. data/docs/git-multirepo-cheatsheet.docx +0 -0
  17. data/git-multirepo.gemspec +31 -31
  18. data/lib/git-multirepo.rb +3 -3
  19. data/lib/multirepo/commands/add-command.rb +51 -51
  20. data/lib/multirepo/commands/branch-command.rb +82 -82
  21. data/lib/multirepo/commands/checkout-command.rb +123 -121
  22. data/lib/multirepo/commands/clone-command.rb +68 -68
  23. data/lib/multirepo/commands/command.rb +86 -86
  24. data/lib/multirepo/commands/commands.rb +15 -15
  25. data/lib/multirepo/commands/do-command.rb +101 -101
  26. data/lib/multirepo/commands/graph-command.rb +43 -43
  27. data/lib/multirepo/commands/init-command.rb +121 -121
  28. data/lib/multirepo/commands/inspect-command.rb +48 -39
  29. data/lib/multirepo/commands/install-command.rb +153 -153
  30. data/lib/multirepo/commands/merge-command.rb +249 -249
  31. data/lib/multirepo/commands/open-command.rb +55 -55
  32. data/lib/multirepo/commands/remove-command.rb +48 -48
  33. data/lib/multirepo/commands/uninit-command.rb +18 -18
  34. data/lib/multirepo/commands/update-command.rb +112 -112
  35. data/lib/multirepo/config.rb +16 -16
  36. data/lib/multirepo/files/config-entry.rb +39 -39
  37. data/lib/multirepo/files/config-file.rb +46 -46
  38. data/lib/multirepo/files/lock-entry.rb +29 -29
  39. data/lib/multirepo/files/lock-file.rb +56 -56
  40. data/lib/multirepo/files/meta-file.rb +41 -41
  41. data/lib/multirepo/files/tracking-file.rb +9 -9
  42. data/lib/multirepo/files/tracking-files.rb +47 -47
  43. data/lib/multirepo/git/branch.rb +32 -32
  44. data/lib/multirepo/git/change.rb +11 -11
  45. data/lib/multirepo/git/commit.rb +7 -7
  46. data/lib/multirepo/git/git-runner.rb +56 -56
  47. data/lib/multirepo/git/git.rb +10 -10
  48. data/lib/multirepo/git/ref.rb +38 -38
  49. data/lib/multirepo/git/remote.rb +17 -17
  50. data/lib/multirepo/git/repo.rb +124 -124
  51. data/lib/multirepo/hooks/post-commit-hook.rb +23 -23
  52. data/lib/multirepo/hooks/pre-commit-hook.rb +35 -35
  53. data/lib/multirepo/info.rb +5 -5
  54. data/lib/multirepo/logic/dependency.rb +6 -6
  55. data/lib/multirepo/logic/merge-descriptor.rb +95 -95
  56. data/lib/multirepo/logic/node.rb +72 -72
  57. data/lib/multirepo/logic/performer.rb +55 -55
  58. data/lib/multirepo/logic/repo-selection.rb +25 -25
  59. data/lib/multirepo/logic/revision-selection.rb +15 -15
  60. data/lib/multirepo/logic/revision-selector.rb +23 -23
  61. data/lib/multirepo/multirepo-exception.rb +6 -6
  62. data/lib/multirepo/utility/console.rb +52 -52
  63. data/lib/multirepo/utility/popen-runner.rb +27 -27
  64. data/lib/multirepo/utility/system-runner.rb +14 -14
  65. data/lib/multirepo/utility/utils.rb +99 -99
  66. data/lib/multirepo/utility/verbosity.rb +6 -6
  67. data/resources/.gitconfig +2 -2
  68. data/resources/post-commit +6 -6
  69. data/resources/pre-commit +6 -6
  70. data/spec/integration/init_spec.rb +19 -19
  71. data/spec/spec_helper.rb +89 -89
  72. metadata +3 -3
@@ -1,31 +1,31 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require "multirepo/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 = "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
- spec.add_runtime_dependency "terminal-table", "~> 1.4.5"
30
- spec.add_runtime_dependency "ruby-graphviz", "~> 1.2.1"
31
- end
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "multirepo/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 = "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
+ spec.add_runtime_dependency "terminal-table", "~> 1.4.5"
30
+ spec.add_runtime_dependency "ruby-graphviz", "~> 1.2.1"
31
+ end
data/lib/git-multirepo.rb CHANGED
@@ -1,3 +1,3 @@
1
- require "multirepo/utility/console"
2
- require "multirepo/hooks/pre-commit-hook"
3
- require "multirepo/hooks/post-commit-hook"
1
+ require "multirepo/utility/console"
2
+ require "multirepo/hooks/pre-commit-hook"
3
+ require "multirepo/hooks/post-commit-hook"
@@ -1,51 +1,51 @@
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
- ensure_in_work_tree
25
- ensure_multirepo_enabled
26
- ensure_repo_valid
27
-
28
- config_file = ConfigFile.new(".")
29
- entry = ConfigEntry.new(Repo.new(@path))
30
-
31
- if config_file.entry_exists?(entry)
32
- Console.log_info("There is already an entry for '#{@path}' in the .multirepo file")
33
- else
34
- config_file.add_entry(entry)
35
- Console.log_step("Added '#{@path}' to the .multirepo file")
36
- end
37
- end
38
-
39
- def ensure_repo_valid
40
- fail MultiRepoException, "The provided path is not a direct sibling of the main repository" unless validate_is_sibling_repo(@path)
41
- fail MultiRepoException, "There is no folder at path '#{@path}'" unless Dir.exist?(@path)
42
- fail MultiRepoException, "'#{@path}' is not a repository" unless Repo.new(@path).exists?
43
- end
44
-
45
- def validate_is_sibling_repo(path)
46
- parent_dir = File.expand_path("..")
47
- path = File.expand_path("..", path)
48
- return parent_dir == path
49
- end
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
+ ensure_in_work_tree
25
+ ensure_multirepo_enabled
26
+ ensure_repo_valid
27
+
28
+ config_file = ConfigFile.new(".")
29
+ entry = ConfigEntry.new(Repo.new(@path))
30
+
31
+ if config_file.entry_exists?(entry)
32
+ Console.log_info("There is already an entry for '#{@path}' in the .multirepo file")
33
+ else
34
+ config_file.add_entry(entry)
35
+ Console.log_step("Added '#{@path}' to the .multirepo file")
36
+ end
37
+ end
38
+
39
+ def ensure_repo_valid
40
+ fail MultiRepoException, "The provided path is not a direct sibling of the main repository" unless validate_is_sibling_repo(@path)
41
+ fail MultiRepoException, "There is no folder at path '#{@path}'" unless Dir.exist?(@path)
42
+ fail MultiRepoException, "'#{@path}' is not a repository" unless Repo.new(@path).exists?
43
+ end
44
+
45
+ def validate_is_sibling_repo(path)
46
+ parent_dir = File.expand_path("..")
47
+ path = File.expand_path("..", path)
48
+ return parent_dir == path
49
+ end
50
+ end
51
+ end
@@ -1,82 +1,82 @@
1
- require "multirepo/utility/console"
2
- require "multirepo/git/git"
3
- require "multirepo/files/config-file"
4
- require "multirepo/files/tracking-files"
5
- require "multirepo/logic/performer"
6
-
7
- module MultiRepo
8
- class BranchCommand < Command
9
- self.command = "branch"
10
- self.summary = "Create and/or checkout a new branch for all repos."
11
-
12
- def self.options
13
- [
14
- ['<branch name>', 'The name of the branch to create and checkout.'],
15
- ['[--force]', 'Force creating the branch even if the repos contain uncommmitted changes.'],
16
- ['[--no-push]', 'Do not push the branch on creation.']
17
- ].concat(super)
18
- end
19
-
20
- def initialize(argv)
21
- @branch_name = argv.shift_argument
22
- @force = argv.flag?("force")
23
- @remote_tracking = argv.flag?("push", true)
24
- super
25
- end
26
-
27
- def validate!
28
- super
29
- help! "You must specify a branch name" unless @branch_name
30
- help! "Please provide a valid branch name" unless Git.valid_branch_name?(@branch_name)
31
- end
32
-
33
- def run
34
- ensure_in_work_tree
35
- ensure_multirepo_enabled
36
-
37
- Console.log_step("Branching...")
38
-
39
- main_repo = Repo.new(".")
40
-
41
- # Ensure the main repo is clean
42
- fail MultiRepoException, "Main repo is not clean; multi branch aborted" unless main_repo.clean?
43
-
44
- # Ensure dependencies are clean
45
- config_entries = ConfigFile.new(".").load_entries
46
- unless Utils.dependencies_clean?(config_entries)
47
- fail MultiRepoException, "Dependencies are not clean; multi branch aborted"
48
- end
49
-
50
- # Branch dependencies
51
- Performer.dependencies.each do |dependency|
52
- perform_branch(dependency.config_entry.repo)
53
- end
54
-
55
- # Branch the main repo
56
- perform_branch(main_repo)
57
-
58
- Console.log_step("Done!")
59
- end
60
-
61
- def perform_branch(repo)
62
- Console.log_substep("Branching '#{repo.path}' ...")
63
- Console.log_info("Creating and checking out branch #{@branch_name} ...")
64
-
65
- branch = repo.branch(@branch_name)
66
- branch.create unless branch.exists?
67
- branch.checkout
68
-
69
- if Utils.multirepo_enabled?(repo.path)
70
- Console.log_info("Updating and committing tracking files")
71
- tracking_files = TrackingFiles.new(repo.path)
72
- tracking_files.update
73
- tracking_files.commit("[multirepo] Post-branch tracking files update")
74
- end
75
-
76
- return unless @remote_tracking
77
-
78
- Console.log_info("Pushing #{@branch_name} to origin/#{@branch_name}")
79
- repo.branch(@branch_name).push
80
- end
81
- end
82
- end
1
+ require "multirepo/utility/console"
2
+ require "multirepo/git/git"
3
+ require "multirepo/files/config-file"
4
+ require "multirepo/files/tracking-files"
5
+ require "multirepo/logic/performer"
6
+
7
+ module MultiRepo
8
+ class BranchCommand < Command
9
+ self.command = "branch"
10
+ self.summary = "Create and/or checkout a new branch for all repos."
11
+
12
+ def self.options
13
+ [
14
+ ['<branch name>', 'The name of the branch to create and checkout.'],
15
+ ['[--force]', 'Force creating the branch even if there are uncommmitted changes.'],
16
+ ['[--no-push]', 'Do not push the branch on creation.']
17
+ ].concat(super)
18
+ end
19
+
20
+ def initialize(argv)
21
+ @branch_name = argv.shift_argument
22
+ @force = argv.flag?("force")
23
+ @remote_tracking = argv.flag?("push", true)
24
+ super
25
+ end
26
+
27
+ def validate!
28
+ super
29
+ help! "You must specify a branch name" unless @branch_name
30
+ help! "Please provide a valid branch name" unless Git.valid_branch_name?(@branch_name)
31
+ end
32
+
33
+ def run
34
+ ensure_in_work_tree
35
+ ensure_multirepo_enabled
36
+
37
+ Console.log_step("Branching...")
38
+
39
+ main_repo = Repo.new(".")
40
+
41
+ # Ensure the main repo is clean
42
+ fail MultiRepoException, "Main repo is not clean; multi branch aborted" unless main_repo.clean?
43
+
44
+ # Ensure dependencies are clean
45
+ config_entries = ConfigFile.new(".").load_entries
46
+ unless Utils.dependencies_clean?(config_entries)
47
+ fail MultiRepoException, "Dependencies are not clean; multi branch aborted"
48
+ end
49
+
50
+ # Branch dependencies
51
+ Performer.dependencies.each do |dependency|
52
+ perform_branch(dependency.config_entry.repo)
53
+ end
54
+
55
+ # Branch the main repo
56
+ perform_branch(main_repo)
57
+
58
+ Console.log_step("Done!")
59
+ end
60
+
61
+ def perform_branch(repo)
62
+ Console.log_substep("Branching '#{repo.path}' ...")
63
+ Console.log_info("Creating and checking out branch #{@branch_name} ...")
64
+
65
+ branch = repo.branch(@branch_name)
66
+ branch.create unless branch.exists?
67
+ branch.checkout
68
+
69
+ if Utils.multirepo_enabled?(repo.path)
70
+ Console.log_info("Updating and committing tracking files")
71
+ tracking_files = TrackingFiles.new(repo.path)
72
+ tracking_files.update
73
+ tracking_files.commit("[multirepo] Post-branch tracking files update")
74
+ end
75
+
76
+ return unless @remote_tracking
77
+
78
+ Console.log_info("Pushing #{@branch_name} to origin/#{@branch_name}")
79
+ repo.branch(@branch_name).push
80
+ end
81
+ end
82
+ end
@@ -1,121 +1,123 @@
1
- require "multirepo/utility/console"
2
- require "multirepo/utility/utils"
3
- require "multirepo/logic/revision-selector"
4
- require "multirepo/logic/performer"
5
-
6
- module MultiRepo
7
- class CheckoutCommand < Command
8
- self.command = "checkout"
9
- self.summary = "Checks out the specified commit or branch of the main repo and checks out matching versions of all dependencies."
10
-
11
- def self.options
12
- [
13
- ['<refname>', 'The main repo tag, branch or commit id to checkout.'],
14
- ['[--latest]', 'Checkout the HEAD of each dependency branch (as recorded in the lock file) instead of the exact required commits.'],
15
- ['[--exact]', 'Checkout the exact specified ref for each repo, regardless of what\'s stored in the lock file.']
16
- ].concat(super)
17
- end
18
-
19
- def initialize(argv)
20
- @ref_name = argv.shift_argument
21
- @checkout_latest = argv.flag?("latest")
22
- @checkout_exact = argv.flag?("exact")
23
- super
24
- end
25
-
26
- def validate!
27
- super
28
- help! "You must specify a branch or commit id to checkout" unless @ref_name
29
- unless Utils.only_one_true?(@checkout_latest, @checkout_exact)
30
- help! "You can't provide more than one operation modifier (--latest, --exact, etc.)"
31
- end
32
- end
33
-
34
- def run
35
- ensure_in_work_tree
36
-
37
- # Find out the checkout mode based on command-line options
38
- mode = RevisionSelector.mode_for_args(@checkout_latest, @checkout_exact)
39
-
40
- strategy_name = RevisionSelection.name_for_mode(mode)
41
- Console.log_step("Checking out #{@ref_name} and its dependencies using the '#{strategy_name}' strategy...")
42
-
43
- main_repo = Repo.new(".")
44
-
45
- unless proceed_if_merge_commit?(main_repo, @ref_name, mode)
46
- fail MultiRepoException, "Aborting checkout"
47
- end
48
-
49
- checkout_core(main_repo, mode)
50
-
51
- Console.log_step("Done!")
52
- end
53
-
54
- def checkout_core(main_repo, mode)
55
- initial_revision = main_repo.current_revision
56
- begin
57
- # Checkout first because the current ref might not be multirepo-enabled
58
- checkout_main_repo_step(main_repo)
59
- # Only then can we check for dependencies and make sure they are clean
60
- ensure_dependencies_clean_step
61
- rescue MultiRepoException => e
62
- Console.log_warning("Restoring working copy to #{initial_revision}")
63
- main_repo.checkout(initial_revision)
64
- raise e
65
- end
66
- dependencies_checkout_step(mode, @ref_name)
67
- end
68
-
69
- def checkout_main_repo_step(main_repo)
70
- Performer.perform_main_repo_checkout(main_repo, @ref_name)
71
- end
72
-
73
- def ensure_dependencies_clean_step
74
- unless Utils.dependencies_clean?(ConfigFile.new(".").load_entries)
75
- fail MultiRepoException, "Dependencies are not clean!"
76
- end
77
- end
78
-
79
- def dependencies_checkout_step(mode, ref_name = nil)
80
- Performer.dependencies.each do |dependency|
81
- # Find out the required dependency revision based on the checkout mode
82
- revision = RevisionSelector.revision_for_mode(mode, ref_name, dependency.lock_entry)
83
- perform_dependency_checkout(dependency.config_entry, revision)
84
- end
85
- end
86
-
87
- def proceed_if_merge_commit?(main_repo, ref_name, mode)
88
- return true unless main_repo.ref(ref_name).merge_commit?
89
-
90
- case mode
91
- when RevisionSelection::AS_LOCK
92
- Console.log_error("The specified ref is a merge commit and an \"as-lock\" checkout was requested.")
93
- Console.log_error("The resulting checkout would most probably not result in a valid project state.")
94
- return false
95
- when RevisionSelection::LATEST
96
- Console.log_warning("The specified ref is a merge commit and a \"latest\" checkout was requested.")
97
- Console.log_warning("The work branches recorded in the branch from which the merge was performed will be checked out.")
98
- end
99
-
100
- return true
101
- end
102
-
103
- def perform_dependency_checkout(config_entry, revision)
104
- dependency_name = config_entry.repo.basename
105
-
106
- # Make sure the repo exists on disk, and clone it if it doesn't
107
- # (in case the checked-out revision had an additional dependency)
108
- unless config_entry.repo.exists?
109
- Console.log_substep("Cloning missing dependency '#{config_entry.path}' from #{config_entry.url}")
110
- config_entry.repo.clone(config_entry.url)
111
- end
112
-
113
- # Checkout!
114
- if config_entry.repo.checkout(revision)
115
- Console.log_substep("Checked out #{dependency_name} '#{revision}'")
116
- else
117
- fail MultiRepoException, "Couldn't check out the appropriate version of dependency #{dependency_name}"
118
- end
119
- end
120
- end
121
- end
1
+ require "multirepo/utility/console"
2
+ require "multirepo/utility/utils"
3
+ require "multirepo/logic/revision-selector"
4
+ require "multirepo/logic/performer"
5
+
6
+ module MultiRepo
7
+ class CheckoutCommand < Command
8
+ self.command = "checkout"
9
+ self.summary = "Checks out the specified commit or branch of the main repo and checks out matching versions of all dependencies."
10
+
11
+ def self.options
12
+ [
13
+ ['<refname>', 'The main repo tag, branch or commit id to checkout.'],
14
+ ['[--latest]', 'Checkout the HEAD of each dependency branch (as recorded in the lock file) instead of the exact required commits.'],
15
+ ['[--exact]', 'Checkout the exact specified ref for each repo, regardless of what\'s stored in the lock file.'],
16
+ ['[--force]', 'Force checkout even if there are uncommmitted changes.']
17
+ ].concat(super)
18
+ end
19
+
20
+ def initialize(argv)
21
+ @ref_name = argv.shift_argument
22
+ @checkout_latest = argv.flag?("latest")
23
+ @checkout_exact = argv.flag?("exact")
24
+ @force = argv.flag?("force")
25
+ super
26
+ end
27
+
28
+ def validate!
29
+ super
30
+ help! "You must specify a branch or commit id to checkout" unless @ref_name
31
+ unless Utils.only_one_true?(@checkout_latest, @checkout_exact)
32
+ help! "You can't provide more than one operation modifier (--latest, --exact, etc.)"
33
+ end
34
+ end
35
+
36
+ def run
37
+ ensure_in_work_tree
38
+
39
+ # Find out the checkout mode based on command-line options
40
+ mode = RevisionSelector.mode_for_args(@checkout_latest, @checkout_exact)
41
+
42
+ strategy_name = RevisionSelection.name_for_mode(mode)
43
+ Console.log_step("Checking out #{@ref_name} and its dependencies using the '#{strategy_name}' strategy...")
44
+
45
+ main_repo = Repo.new(".")
46
+
47
+ unless proceed_if_merge_commit?(main_repo, @ref_name, mode)
48
+ fail MultiRepoException, "Aborting checkout"
49
+ end
50
+
51
+ checkout_core(main_repo, mode)
52
+
53
+ Console.log_step("Done!")
54
+ end
55
+
56
+ def checkout_core(main_repo, mode)
57
+ initial_revision = main_repo.current_revision
58
+ begin
59
+ # Checkout first because the current ref might not be multirepo-enabled
60
+ checkout_main_repo_step(main_repo)
61
+ # Only then can we check for dependencies and make sure they are clean
62
+ ensure_dependencies_clean_step if !@force
63
+ rescue MultiRepoException => e
64
+ Console.log_warning("Restoring working copy to #{initial_revision}")
65
+ main_repo.checkout(initial_revision)
66
+ raise e
67
+ end
68
+ dependencies_checkout_step(mode, @ref_name)
69
+ end
70
+
71
+ def checkout_main_repo_step(main_repo)
72
+ Performer.perform_main_repo_checkout(main_repo, @ref_name, @force)
73
+ end
74
+
75
+ def ensure_dependencies_clean_step
76
+ unless Utils.dependencies_clean?(ConfigFile.new(".").load_entries)
77
+ fail MultiRepoException, "Dependencies are not clean!"
78
+ end
79
+ end
80
+
81
+ def dependencies_checkout_step(mode, ref_name = nil)
82
+ Performer.dependencies.each do |dependency|
83
+ # Find out the required dependency revision based on the checkout mode
84
+ revision = RevisionSelector.revision_for_mode(mode, ref_name, dependency.lock_entry)
85
+ perform_dependency_checkout(dependency.config_entry, revision)
86
+ end
87
+ end
88
+
89
+ def proceed_if_merge_commit?(main_repo, ref_name, mode)
90
+ return true unless main_repo.ref(ref_name).merge_commit?
91
+
92
+ case mode
93
+ when RevisionSelection::AS_LOCK
94
+ Console.log_error("The specified ref is a merge commit and an \"as-lock\" checkout was requested.")
95
+ Console.log_error("The resulting checkout would most probably not result in a valid project state.")
96
+ return false
97
+ when RevisionSelection::LATEST
98
+ Console.log_warning("The specified ref is a merge commit and a \"latest\" checkout was requested.")
99
+ Console.log_warning("The work branches recorded in the branch from which the merge was performed will be checked out.")
100
+ end
101
+
102
+ return true
103
+ end
104
+
105
+ def perform_dependency_checkout(config_entry, revision)
106
+ dependency_name = config_entry.repo.basename
107
+
108
+ # Make sure the repo exists on disk, and clone it if it doesn't
109
+ # (in case the checked-out revision had an additional dependency)
110
+ unless config_entry.repo.exists?
111
+ Console.log_substep("Cloning missing dependency '#{config_entry.path}' from #{config_entry.url}")
112
+ config_entry.repo.clone(config_entry.url)
113
+ end
114
+
115
+ # Checkout!
116
+ if config_entry.repo.checkout(revision)
117
+ Console.log_substep("Checked out #{dependency_name} '#{revision}'")
118
+ else
119
+ fail MultiRepoException, "Couldn't check out the appropriate version of dependency #{dependency_name}"
120
+ end
121
+ end
122
+ end
123
+ end