git-multirepo 1.0.0.beta56 → 1.0.0.beta57

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.
Files changed (73) 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 +61 -57
  9. data/Gemfile +4 -4
  10. data/Gemfile.lock +42 -42
  11. data/LICENSE +22 -22
  12. data/README.md +179 -178
  13. data/Rakefile +1 -1
  14. data/bin/multi +11 -11
  15. data/docs/bug-repros/91565510-repro.sh +20 -20
  16. data/git-multirepo.gemspec +31 -31
  17. data/lib/git-multirepo.rb +3 -3
  18. data/lib/multirepo/commands/add-command.rb +51 -51
  19. data/lib/multirepo/commands/branch-command.rb +82 -82
  20. data/lib/multirepo/commands/checkout-command.rb +127 -127
  21. data/lib/multirepo/commands/clone-command.rb +68 -68
  22. data/lib/multirepo/commands/command.rb +87 -87
  23. data/lib/multirepo/commands/commands.rb +15 -15
  24. data/lib/multirepo/commands/do-command.rb +101 -101
  25. data/lib/multirepo/commands/graph-command.rb +43 -43
  26. data/lib/multirepo/commands/init-command.rb +121 -121
  27. data/lib/multirepo/commands/inspect-command.rb +48 -48
  28. data/lib/multirepo/commands/install-command.rb +161 -161
  29. data/lib/multirepo/commands/merge-command.rb +249 -249
  30. data/lib/multirepo/commands/open-command.rb +55 -55
  31. data/lib/multirepo/commands/remove-command.rb +48 -48
  32. data/lib/multirepo/commands/uninit-command.rb +18 -18
  33. data/lib/multirepo/commands/update-command.rb +112 -112
  34. data/lib/multirepo/config.rb +19 -19
  35. data/lib/multirepo/files/config-entry.rb +39 -39
  36. data/lib/multirepo/files/config-file.rb +46 -46
  37. data/lib/multirepo/files/lock-entry.rb +29 -29
  38. data/lib/multirepo/files/lock-file.rb +56 -56
  39. data/lib/multirepo/files/meta-file.rb +41 -41
  40. data/lib/multirepo/files/tracking-file.rb +9 -9
  41. data/lib/multirepo/files/tracking-files.rb +47 -47
  42. data/lib/multirepo/git/branch.rb +32 -32
  43. data/lib/multirepo/git/change.rb +11 -11
  44. data/lib/multirepo/git/commit.rb +7 -7
  45. data/lib/multirepo/git/git-runner.rb +56 -56
  46. data/lib/multirepo/git/git.rb +10 -10
  47. data/lib/multirepo/git/ref.rb +38 -38
  48. data/lib/multirepo/git/remote.rb +17 -17
  49. data/lib/multirepo/git/repo.rb +129 -129
  50. data/lib/multirepo/hooks/post-commit-hook.rb +23 -23
  51. data/lib/multirepo/hooks/pre-commit-hook.rb +35 -35
  52. data/lib/multirepo/info.rb +5 -5
  53. data/lib/multirepo/logic/dependency.rb +6 -6
  54. data/lib/multirepo/logic/merge-descriptor.rb +95 -95
  55. data/lib/multirepo/logic/node.rb +72 -72
  56. data/lib/multirepo/logic/performer.rb +55 -55
  57. data/lib/multirepo/logic/repo-selection.rb +25 -25
  58. data/lib/multirepo/logic/revision-selection.rb +15 -15
  59. data/lib/multirepo/logic/revision-selector.rb +23 -23
  60. data/lib/multirepo/multirepo-exception.rb +6 -6
  61. data/lib/multirepo/output/extra-output.rb +12 -12
  62. data/lib/multirepo/output/teamcity-extra-output.rb +11 -11
  63. data/lib/multirepo/utility/console.rb +52 -52
  64. data/lib/multirepo/utility/popen-runner.rb +27 -27
  65. data/lib/multirepo/utility/system-runner.rb +14 -14
  66. data/lib/multirepo/utility/utils.rb +99 -99
  67. data/lib/multirepo/utility/verbosity.rb +6 -6
  68. data/resources/.gitconfig +2 -2
  69. data/resources/post-commit +6 -6
  70. data/resources/pre-commit +6 -6
  71. data/spec/integration/init_spec.rb +19 -19
  72. data/spec/spec_helper.rb +89 -89
  73. 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
@@ -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 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
+ 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,127 +1,127 @@
1
- require "multirepo/utility/console"
2
- require "multirepo/utility/utils"
3
- require "multirepo/output/extra-output"
4
- require "multirepo/logic/revision-selector"
5
- require "multirepo/logic/performer"
6
-
7
- module MultiRepo
8
- class CheckoutCommand < Command
9
- self.command = "checkout"
10
- self.summary = "Checks out the specified commit or branch of the main repo and checks out matching versions of all dependencies."
11
-
12
- def self.options
13
- [
14
- ['<refname>', 'The main repo tag, branch or commit id to checkout.'],
15
- ['[--latest]', 'Checkout the HEAD of each dependency branch (as recorded in the lock file) instead of the exact required commits.'],
16
- ['[--exact]', 'Checkout the exact specified ref for each repo, regardless of what\'s stored in the lock file.'],
17
- ['[--force]', 'Force checkout even if there are uncommmitted changes.']
18
- ].concat(super)
19
- end
20
-
21
- def initialize(argv)
22
- @ref_name = argv.shift_argument
23
- @checkout_latest = argv.flag?("latest")
24
- @checkout_exact = argv.flag?("exact")
25
- @force = argv.flag?("force")
26
- super
27
- end
28
-
29
- def validate!
30
- super
31
- help! "You must specify a branch or commit id to checkout" unless @ref_name
32
- unless Utils.only_one_true?(@checkout_latest, @checkout_exact)
33
- help! "You can't provide more than one operation modifier (--latest, --exact, etc.)"
34
- end
35
- end
36
-
37
- def run
38
- ensure_in_work_tree
39
-
40
- # Find out the checkout mode based on command-line options
41
- mode = RevisionSelector.mode_for_args(@checkout_latest, @checkout_exact)
42
-
43
- strategy_name = RevisionSelection.name_for_mode(mode)
44
- Console.log_step("Checking out #{@ref_name} and its dependencies using the '#{strategy_name}' strategy...")
45
-
46
- main_repo = Repo.new(".")
47
-
48
- unless proceed_if_merge_commit?(main_repo, @ref_name, mode)
49
- fail MultiRepoException, "Aborting checkout"
50
- end
51
-
52
- checkout_core(main_repo, mode)
53
-
54
- Console.log_step("Done!")
55
- end
56
-
57
- def checkout_core(main_repo, mode)
58
- initial_revision = main_repo.current_revision
59
- begin
60
- # Checkout first because the current ref might not be multirepo-enabled
61
- checkout_main_repo_step(main_repo)
62
- # Only then can we check for dependencies and make sure they are clean
63
- ensure_dependencies_clean_step if !@force
64
- rescue MultiRepoException => e
65
- Console.log_warning("Restoring working copy to #{initial_revision}")
66
- main_repo.checkout(initial_revision)
67
- raise e
68
- end
69
- dependencies_checkout_step(mode, @ref_name)
70
- end
71
-
72
- def checkout_main_repo_step(main_repo)
73
- Performer.perform_main_repo_checkout(main_repo, @ref_name, @force)
74
- end
75
-
76
- def ensure_dependencies_clean_step
77
- unless Utils.dependencies_clean?(ConfigFile.new(".").load_entries)
78
- fail MultiRepoException, "Dependencies are not clean!"
79
- end
80
- end
81
-
82
- def dependencies_checkout_step(mode, ref_name = nil)
83
- Performer.dependencies.each do |dependency|
84
- # Find out the required dependency revision based on the checkout mode
85
- revision = RevisionSelector.revision_for_mode(mode, ref_name, dependency.lock_entry)
86
- perform_dependency_checkout(dependency.config_entry, revision)
87
- end
88
- end
89
-
90
- def proceed_if_merge_commit?(main_repo, ref_name, mode)
91
- return true unless main_repo.ref(ref_name).merge_commit?
92
-
93
- case mode
94
- when RevisionSelection::AS_LOCK
95
- Console.log_error("The specified ref is a merge commit and an \"as-lock\" checkout was requested.")
96
- Console.log_error("The resulting checkout would most probably not result in a valid project state.")
97
- return false
98
- when RevisionSelection::LATEST
99
- Console.log_warning("The specified ref is a merge commit and a \"latest\" checkout was requested.")
100
- Console.log_warning("The work branches recorded in the branch from which the merge was performed will be checked out.")
101
- end
102
-
103
- return true
104
- end
105
-
106
- def perform_dependency_checkout(config_entry, revision)
107
- dependency_name = config_entry.repo.basename
108
-
109
- # Make sure the repo exists on disk, and clone it if it doesn't
110
- # (in case the checked-out revision had an additional dependency)
111
- unless config_entry.repo.exists?
112
- Console.log_substep("Cloning missing dependency '#{config_entry.path}' from #{config_entry.url}")
113
- ExtraOutput.progress("Cloning missing dependency #{config_entry.path}")
114
- config_entry.repo.clone(config_entry.url)
115
- end
116
-
117
- # Checkout!
118
- ExtraOutput.progress("Checking out #{dependency_name} #{revision}")
119
- if config_entry.repo.checkout(revision)
120
- Console.log_substep("Checked out #{dependency_name} '#{revision}'")
121
- else
122
- ExtraOutput.error("Couldn|'t check out dependency #{dependency_name}")
123
- fail MultiRepoException, "Couldn't check out the appropriate version of dependency #{dependency_name}"
124
- end
125
- end
126
- end
127
- end
1
+ require "multirepo/utility/console"
2
+ require "multirepo/utility/utils"
3
+ require "multirepo/output/extra-output"
4
+ require "multirepo/logic/revision-selector"
5
+ require "multirepo/logic/performer"
6
+
7
+ module MultiRepo
8
+ class CheckoutCommand < Command
9
+ self.command = "checkout"
10
+ self.summary = "Checks out the specified commit or branch of the main repo and checks out matching versions of all dependencies."
11
+
12
+ def self.options
13
+ [
14
+ ['<refname>', 'The main repo tag, branch or commit id to checkout.'],
15
+ ['[--latest]', 'Checkout the HEAD of each dependency branch (as recorded in the lock file) instead of the exact required commits.'],
16
+ ['[--exact]', 'Checkout the exact specified ref for each repo, regardless of what\'s stored in the lock file.'],
17
+ ['[--force]', 'Force checkout even if there are uncommmitted changes.']
18
+ ].concat(super)
19
+ end
20
+
21
+ def initialize(argv)
22
+ @ref_name = argv.shift_argument
23
+ @checkout_latest = argv.flag?("latest")
24
+ @checkout_exact = argv.flag?("exact")
25
+ @force = argv.flag?("force")
26
+ super
27
+ end
28
+
29
+ def validate!
30
+ super
31
+ help! "You must specify a branch or commit id to checkout" unless @ref_name
32
+ unless Utils.only_one_true?(@checkout_latest, @checkout_exact)
33
+ help! "You can't provide more than one operation modifier (--latest, --exact, etc.)"
34
+ end
35
+ end
36
+
37
+ def run
38
+ ensure_in_work_tree
39
+
40
+ # Find out the checkout mode based on command-line options
41
+ mode = RevisionSelector.mode_for_args(@checkout_latest, @checkout_exact)
42
+
43
+ strategy_name = RevisionSelection.name_for_mode(mode)
44
+ Console.log_step("Checking out #{@ref_name} and its dependencies using the '#{strategy_name}' strategy...")
45
+
46
+ main_repo = Repo.new(".")
47
+
48
+ unless proceed_if_merge_commit?(main_repo, @ref_name, mode)
49
+ fail MultiRepoException, "Aborting checkout"
50
+ end
51
+
52
+ checkout_core(main_repo, mode)
53
+
54
+ Console.log_step("Done!")
55
+ end
56
+
57
+ def checkout_core(main_repo, mode)
58
+ initial_revision = main_repo.current_revision
59
+ begin
60
+ # Checkout first because the current ref might not be multirepo-enabled
61
+ checkout_main_repo_step(main_repo)
62
+ # Only then can we check for dependencies and make sure they are clean
63
+ ensure_dependencies_clean_step if !@force
64
+ rescue MultiRepoException => e
65
+ Console.log_warning("Restoring working copy to #{initial_revision}")
66
+ main_repo.checkout(initial_revision)
67
+ raise e
68
+ end
69
+ dependencies_checkout_step(mode, @ref_name)
70
+ end
71
+
72
+ def checkout_main_repo_step(main_repo)
73
+ Performer.perform_main_repo_checkout(main_repo, @ref_name, @force)
74
+ end
75
+
76
+ def ensure_dependencies_clean_step
77
+ unless Utils.dependencies_clean?(ConfigFile.new(".").load_entries)
78
+ fail MultiRepoException, "Dependencies are not clean!"
79
+ end
80
+ end
81
+
82
+ def dependencies_checkout_step(mode, ref_name = nil)
83
+ Performer.dependencies.each do |dependency|
84
+ # Find out the required dependency revision based on the checkout mode
85
+ revision = RevisionSelector.revision_for_mode(mode, ref_name, dependency.lock_entry)
86
+ perform_dependency_checkout(dependency.config_entry, revision)
87
+ end
88
+ end
89
+
90
+ def proceed_if_merge_commit?(main_repo, ref_name, mode)
91
+ return true unless main_repo.ref(ref_name).merge_commit?
92
+
93
+ case mode
94
+ when RevisionSelection::AS_LOCK
95
+ Console.log_error("The specified ref is a merge commit and an \"as-lock\" checkout was requested.")
96
+ Console.log_error("The resulting checkout would most probably not result in a valid project state.")
97
+ return false
98
+ when RevisionSelection::LATEST
99
+ Console.log_warning("The specified ref is a merge commit and a \"latest\" checkout was requested.")
100
+ Console.log_warning("The work branches recorded in the branch from which the merge was performed will be checked out.")
101
+ end
102
+
103
+ return true
104
+ end
105
+
106
+ def perform_dependency_checkout(config_entry, revision)
107
+ dependency_name = config_entry.repo.basename
108
+
109
+ # Make sure the repo exists on disk, and clone it if it doesn't
110
+ # (in case the checked-out revision had an additional dependency)
111
+ unless config_entry.repo.exists?
112
+ Console.log_substep("Cloning missing dependency '#{config_entry.path}' from #{config_entry.url}")
113
+ ExtraOutput.progress("Cloning missing dependency #{config_entry.path}")
114
+ config_entry.repo.clone(config_entry.url)
115
+ end
116
+
117
+ # Checkout!
118
+ ExtraOutput.progress("Checking out #{dependency_name} #{revision}")
119
+ if config_entry.repo.checkout(revision)
120
+ Console.log_substep("Checked out #{dependency_name} '#{revision}'")
121
+ else
122
+ ExtraOutput.error("Couldn|'t check out dependency #{dependency_name}")
123
+ fail MultiRepoException, "Couldn't check out the appropriate version of dependency #{dependency_name}"
124
+ end
125
+ end
126
+ end
127
+ end