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.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +38 -38
  3. data/.rspec +2 -2
  4. data/Gemfile +4 -4
  5. data/Gemfile.lock +37 -37
  6. data/LICENSE +22 -22
  7. data/README.md +141 -139
  8. data/Rakefile +2 -2
  9. data/bin/multi +10 -10
  10. data/docs/git-multirepo-cheatsheet.docx +0 -0
  11. data/git-multirepo.gemspec +29 -29
  12. data/lib/commands.rb +11 -11
  13. data/lib/git-multirepo.rb +2 -2
  14. data/lib/info.rb +4 -4
  15. data/lib/multirepo/commands/add-command.rb +51 -51
  16. data/lib/multirepo/commands/branch-command.rb +52 -52
  17. data/lib/multirepo/commands/checkout-command.rb +119 -119
  18. data/lib/multirepo/commands/clone-command.rb +69 -69
  19. data/lib/multirepo/commands/command.rb +58 -50
  20. data/lib/multirepo/commands/fetch-command.rb +23 -23
  21. data/lib/multirepo/commands/init-command.rb +51 -51
  22. data/lib/multirepo/commands/install-command.rb +87 -87
  23. data/lib/multirepo/commands/open-command.rb +25 -25
  24. data/lib/multirepo/commands/remove-command.rb +48 -48
  25. data/lib/multirepo/commands/uninit-command.rb +20 -20
  26. data/lib/multirepo/commands/update-command.rb +47 -47
  27. data/lib/multirepo/config.rb +15 -12
  28. data/lib/multirepo/files/config-entry.rb +34 -34
  29. data/lib/multirepo/files/config-file.rb +37 -37
  30. data/lib/multirepo/files/lock-entry.rb +25 -25
  31. data/lib/multirepo/files/lock-file.rb +39 -39
  32. data/lib/multirepo/git/branch.rb +27 -27
  33. data/lib/multirepo/git/change.rb +10 -10
  34. data/lib/multirepo/git/git.rb +42 -38
  35. data/lib/multirepo/git/remote.rb +15 -15
  36. data/lib/multirepo/git/repo.rb +66 -66
  37. data/lib/multirepo/hooks/post-merge-hook.rb +19 -19
  38. data/lib/multirepo/hooks/pre-commit-hook.rb +25 -25
  39. data/lib/multirepo/hooks/prepare-commit-msg-hook.rb +27 -27
  40. data/lib/multirepo/multirepo-exception.rb +5 -5
  41. data/lib/multirepo/utility/console.rb +51 -51
  42. data/lib/multirepo/utility/runner.rb +32 -32
  43. data/lib/multirepo/utility/utils.rb +51 -51
  44. data/resources/post-merge +5 -5
  45. data/resources/pre-commit +5 -5
  46. data/resources/prepare-commit-msg +5 -5
  47. data/spec/integration/init_spec.rb +22 -22
  48. data/spec/spec_helper.rb +89 -89
  49. metadata +4 -3
@@ -1,70 +1,70 @@
1
- require "multirepo/utility/console"
2
- require "multirepo/utility/utils"
3
- require "multirepo/git/repo"
4
- require_relative "install-command"
5
-
6
- module MultiRepo
7
- class CloneCommand < Command
8
- self.command = "clone"
9
- self.summary = "Clones the specified repository in a subfolder, then installs it."
10
-
11
- def self.options
12
- [
13
- ['[url]', 'The repository to clone.'],
14
- ['[name]', 'The name of the containing folder that will be created.'],
15
- ['[ref]', 'The branch, tag or commit id to checkout. Checkout will use "master" if unspecified.']
16
- ].concat(super)
17
- end
18
-
19
- def initialize(argv)
20
- @url = argv.shift_argument
21
- @name = argv.shift_argument
22
- @ref = argv.shift_argument || "master"
23
- super
24
- end
25
-
26
- def validate!
27
- super
28
- help! "You must specify a repository to clone" unless @url
29
- help! "You must specify a containing folder name" unless @name
30
- end
31
-
32
- def run
33
- Console.log_step("Cloning #{@url} ...")
34
-
35
- raise MultiRepoException, "A directory named #{@name} already exists" if Dir.exists?(@name)
36
-
37
- main_repo_path = "#{@name}/#{@name}"
38
- main_repo = Repo.new(main_repo_path)
39
-
40
- # Recursively create the directory where we'll clone the main repo
41
- FileUtils.mkpath(main_repo_path)
42
-
43
- # Clone the specified remote in the just-created directory
44
- raise MultiRepoException, "Could not clone repo from #{@url}" unless main_repo.clone(@url)
45
-
46
- # Checkout the specified main repo ref so that install reads the proper config file
47
- unless main_repo.checkout(@ref)
48
- raise MultiRepoException, "Couldn't perform checkout of main repo #{@ref}!"
49
- end
50
-
51
- Console.log_substep("Checked out main repo #{@ref}")
52
-
53
- # Make sure the ref we just checked out is multirepo-enabled
54
- unless Utils.is_multirepo_enabled(main_repo_path)
55
- raise MultiRepoException, "Ref #{@ref} is not multirepo-enabled"
56
- end
57
-
58
- # Install
59
- original_path = Dir.pwd
60
- Dir.chdir(main_repo_path)
61
- install_command = InstallCommand.new(CLAide::ARGV.new([]))
62
- install_command.install_dependencies_step
63
- Dir.chdir(original_path)
64
-
65
- Console.log_step("Done!")
66
- rescue MultiRepoException => e
67
- Console.log_error(e.message)
68
- end
69
- end
1
+ require "multirepo/utility/console"
2
+ require "multirepo/utility/utils"
3
+ require "multirepo/git/repo"
4
+ require_relative "install-command"
5
+
6
+ module MultiRepo
7
+ class CloneCommand < Command
8
+ self.command = "clone"
9
+ self.summary = "Clones the specified repository in a subfolder, then installs it."
10
+
11
+ def self.options
12
+ [
13
+ ['<url>', 'The repository to clone.'],
14
+ ['<name>', 'The name of the containing folder that will be created.'],
15
+ ['[<ref>]', 'The branch, tag or commit id to checkout. Checkout will use "master" if unspecified.']
16
+ ].concat(super)
17
+ end
18
+
19
+ def initialize(argv)
20
+ @url = argv.shift_argument
21
+ @name = argv.shift_argument
22
+ @ref = argv.shift_argument || "master"
23
+ super
24
+ end
25
+
26
+ def validate!
27
+ super
28
+ help! "You must specify a repository to clone" unless @url
29
+ help! "You must specify a containing folder name" unless @name
30
+ end
31
+
32
+ def run
33
+ Console.log_step("Cloning #{@url} ...")
34
+
35
+ raise MultiRepoException, "A directory named #{@name} already exists" if Dir.exists?(@name)
36
+
37
+ main_repo_path = "#{@name}/#{@name}"
38
+ main_repo = Repo.new(main_repo_path)
39
+
40
+ # Recursively create the directory where we'll clone the main repo
41
+ FileUtils.mkpath(main_repo_path)
42
+
43
+ # Clone the specified remote in the just-created directory
44
+ raise MultiRepoException, "Could not clone repo from #{@url}" unless main_repo.clone(@url)
45
+
46
+ # Checkout the specified main repo ref so that install reads the proper config file
47
+ unless main_repo.checkout(@ref)
48
+ raise MultiRepoException, "Couldn't perform checkout of main repo #{@ref}!"
49
+ end
50
+
51
+ Console.log_substep("Checked out main repo #{@ref}")
52
+
53
+ # Make sure the ref we just checked out is multirepo-enabled
54
+ unless Utils.is_multirepo_enabled(main_repo_path)
55
+ raise MultiRepoException, "Ref #{@ref} is not multirepo-enabled"
56
+ end
57
+
58
+ # Install
59
+ original_path = Dir.pwd
60
+ Dir.chdir(main_repo_path)
61
+ install_command = InstallCommand.new(CLAide::ARGV.new([]))
62
+ install_command.install_dependencies_step
63
+ Dir.chdir(original_path)
64
+
65
+ Console.log_step("Done!")
66
+ rescue MultiRepoException => e
67
+ Console.log_error(e.message)
68
+ end
69
+ end
70
70
  end
@@ -1,51 +1,59 @@
1
- require "claide"
2
-
3
- require "info"
4
- require "multirepo/multirepo-exception"
5
- require "multirepo/config"
6
-
7
- module MultiRepo
8
- class Command < CLAide::Command
9
- self.abstract_command = true
10
- self.command = "multi"
11
- self.version = VERSION
12
- self.description = DESCRIPTION
13
-
14
- def initialize(argv)
15
- Config.instance.verbose = argv.flag?("verbose") ? true : false
16
- super
17
- end
18
-
19
- def validate_in_work_tree
20
- raise MultiRepoException, "Not a git repository" unless Git.is_inside_git_repo(".")
21
- end
22
-
23
- def install_hooks_in_multirepo_enabled_dependencies
24
- # Install the local git hooks in dependency repos
25
- # if they are themselves tracked with multirepo
26
- ConfigFile.load.each do |entry|
27
- if Utils.is_multirepo_enabled(entry.repo.path)
28
- install_hooks(entry.repo.path)
29
- Console.log_substep("Installed hooks in multirepo-enabled dependency '#{entry.repo.path}'")
30
- end
31
- end
32
- end
33
-
34
- def install_hooks(path = nil)
35
- actual_path = path || "."
36
- Utils.install_hook("pre-commit", actual_path)
37
- Utils.install_hook("prepare-commit-msg", actual_path)
38
- Utils.install_hook("post-merge", actual_path)
39
- end
40
-
41
- def uninstall_hooks
42
- File.delete(".git/hooks/pre-commit")
43
- File.delete(".git/hooks/prepare-commit-msg")
44
- File.delete(".git/hooks/post-merge")
45
- end
46
-
47
- def ensure_multirepo_initialized
48
- raise MultiRepoException, "multirepo is not initialized in this repository." unless Utils.is_multirepo_enabled(".")
49
- end
50
- end
1
+ require "claide"
2
+
3
+ require "info"
4
+ require "multirepo/multirepo-exception"
5
+ require "multirepo/config"
6
+
7
+ module MultiRepo
8
+ class Command < CLAide::Command
9
+ self.abstract_command = true
10
+ self.command = "multi"
11
+ self.version = VERSION
12
+ self.description = DESCRIPTION
13
+
14
+ def initialize(argv)
15
+ Config.instance.verbose = argv.flag?("verbose") ? true : false
16
+ Config.instance.git_executable = argv.option("git-exe", "git")
17
+ super
18
+ end
19
+
20
+ def validate!
21
+ path = Config.instance.git_executable
22
+ is_git_exe = path =~ /.*(git)|(git.exe)$/
23
+ file_exists = path == "git" || File.exists?(path)
24
+ help! "Invalid git executable '#{path}'" unless is_git_exe && file_exists
25
+ end
26
+
27
+ def validate_in_work_tree
28
+ raise MultiRepoException, "Not a git repository" unless Git.is_inside_git_repo(".")
29
+ end
30
+
31
+ def install_hooks_in_multirepo_enabled_dependencies
32
+ # Install the local git hooks in dependency repos
33
+ # if they are themselves tracked with multirepo
34
+ ConfigFile.load.each do |entry|
35
+ if Utils.is_multirepo_enabled(entry.repo.path)
36
+ install_hooks(entry.repo.path)
37
+ Console.log_substep("Installed hooks in multirepo-enabled dependency '#{entry.repo.path}'")
38
+ end
39
+ end
40
+ end
41
+
42
+ def install_hooks(path = nil)
43
+ actual_path = path || "."
44
+ Utils.install_hook("pre-commit", actual_path)
45
+ Utils.install_hook("prepare-commit-msg", actual_path)
46
+ Utils.install_hook("post-merge", actual_path)
47
+ end
48
+
49
+ def uninstall_hooks
50
+ File.delete(".git/hooks/pre-commit")
51
+ File.delete(".git/hooks/prepare-commit-msg")
52
+ File.delete(".git/hooks/post-merge")
53
+ end
54
+
55
+ def ensure_multirepo_initialized
56
+ raise MultiRepoException, "multirepo is not initialized in this repository." unless Utils.is_multirepo_enabled(".")
57
+ end
58
+ end
51
59
  end
@@ -1,24 +1,24 @@
1
- require "multirepo/utility/console"
2
-
3
- module MultiRepo
4
- class FetchCommand < Command
5
- self.command = "fetch"
6
- self.summary = "Performs a git fetch on all dependencies."
7
-
8
- def run
9
- validate_in_work_tree
10
- ensure_multirepo_initialized
11
-
12
- Console.log_step("Fetching dependencies...")
13
-
14
- ConfigFile.load.each do |entry|
15
- Console.log_substep("Fetching from #{entry.repo.remote('origin').url}...")
16
- entry.repo.fetch
17
- end
18
-
19
- Console.log_step("Done!")
20
- rescue MultiRepoException => e
21
- Console.log_error(e.message)
22
- end
23
- end
1
+ require "multirepo/utility/console"
2
+
3
+ module MultiRepo
4
+ class FetchCommand < Command
5
+ self.command = "fetch"
6
+ self.summary = "Performs a git fetch on all dependencies."
7
+
8
+ def run
9
+ validate_in_work_tree
10
+ ensure_multirepo_initialized
11
+
12
+ Console.log_step("Fetching dependencies...")
13
+
14
+ ConfigFile.load.each do |entry|
15
+ Console.log_substep("Fetching from #{entry.repo.remote('origin').url}...")
16
+ entry.repo.fetch
17
+ end
18
+
19
+ Console.log_step("Done!")
20
+ rescue MultiRepoException => e
21
+ Console.log_error(e.message)
22
+ end
23
+ end
24
24
  end
@@ -1,52 +1,52 @@
1
- require "multirepo/utility/console"
2
- require "multirepo/utility/utils"
3
- require "multirepo/files/config-file"
4
- require "multirepo/files/lock-file"
5
- require "multirepo/commands/command"
6
-
7
- module MultiRepo
8
- class InitCommand < Command
9
- self.command = "init"
10
- self.summary = "Initialize the current repository as a multirepo project."
11
-
12
- def run
13
- validate_in_work_tree
14
- Console.log_step("Initializing new multirepo config...")
15
-
16
- if ConfigFile.exists?
17
- return unless Console.ask_yes_no(".multirepo file already exists. Reinitialize?")
18
- end
19
-
20
- sibling_repos = Utils.sibling_repos
21
-
22
- if sibling_repos.any?
23
- entries = []
24
- sibling_repos.each do |repo|
25
- origin_desc = repo.remote('origin').url || "[none]"
26
- current_branch = repo.current_branch
27
- if Console.ask_yes_no("Do you want to add '#{repo.path}' as a dependency?\n [origin: '#{origin_desc}', branch: #{current_branch}]")
28
- entries.push(ConfigEntry.new(repo))
29
- Console.log_substep("Added the repository '#{repo.path}' to the .multirepo file")
30
- end
31
- end
32
-
33
- ConfigFile.save(entries)
34
- ConfigFile.stage
35
- else
36
- Console.log_info("There are no sibling repositories to add")
37
- end
38
-
39
- install_hooks
40
- Console.log_substep("Installed git hooks")
41
-
42
- Console.log_step("Done!")
43
- rescue MultiRepoException => e
44
- Console.log_error(e.message)
45
- end
46
-
47
- def check_repo_exists
48
- if !Dir.exists?(@repo.path) then raise MultiRepoException, "There is no folder at path '#{@repo.path}'" end
49
- if !@repo.exists? then raise MultiRepoException, "'#{@repo.path}' is not a repository" end
50
- end
51
- end
1
+ require "multirepo/utility/console"
2
+ require "multirepo/utility/utils"
3
+ require "multirepo/files/config-file"
4
+ require "multirepo/files/lock-file"
5
+ require "multirepo/commands/command"
6
+
7
+ module MultiRepo
8
+ class InitCommand < Command
9
+ self.command = "init"
10
+ self.summary = "Initialize the current repository as a multirepo project."
11
+
12
+ def run
13
+ validate_in_work_tree
14
+ Console.log_step("Initializing new multirepo config...")
15
+
16
+ if ConfigFile.exists?
17
+ return unless Console.ask_yes_no(".multirepo file already exists. Reinitialize?")
18
+ end
19
+
20
+ sibling_repos = Utils.sibling_repos
21
+
22
+ if sibling_repos.any?
23
+ entries = []
24
+ sibling_repos.each do |repo|
25
+ origin_desc = repo.remote('origin').url || "[none]"
26
+ current_branch = repo.current_branch
27
+ if Console.ask_yes_no("Do you want to add '#{repo.path}' as a dependency?\n [origin: '#{origin_desc}', branch: #{current_branch}]")
28
+ entries.push(ConfigEntry.new(repo))
29
+ Console.log_substep("Added the repository '#{repo.path}' to the .multirepo file")
30
+ end
31
+ end
32
+
33
+ ConfigFile.save(entries)
34
+ ConfigFile.stage
35
+ else
36
+ Console.log_info("There are no sibling repositories to add")
37
+ end
38
+
39
+ install_hooks
40
+ Console.log_substep("Installed git hooks")
41
+
42
+ Console.log_step("Done!")
43
+ rescue MultiRepoException => e
44
+ Console.log_error(e.message)
45
+ end
46
+
47
+ def check_repo_exists
48
+ if !Dir.exists?(@repo.path) then raise MultiRepoException, "There is no folder at path '#{@repo.path}'" end
49
+ if !@repo.exists? then raise MultiRepoException, "'#{@repo.path}' is not a repository" end
50
+ end
51
+ end
52
52
  end
@@ -1,88 +1,88 @@
1
- require "multirepo/utility/console"
2
- require "multirepo/utility/utils"
3
- require "multirepo/git/repo"
4
- require "multirepo/commands/checkout-command"
5
-
6
- module MultiRepo
7
- class InstallCommand < Command
8
- self.command = "install"
9
- self.summary = "Clones and checks out dependencies as defined in the version-controlled multirepo metadata files and installs git-multirepo's local git hooks."
10
-
11
- def self.options
12
- [['-hooks', 'Only install local git hooks.']].concat(super)
13
- end
14
-
15
- def initialize(argv)
16
- @hooks = argv.flag?("hooks")
17
- super
18
- end
19
-
20
- def run
21
- validate_in_work_tree
22
- ensure_multirepo_initialized
23
-
24
- if @hooks
25
- Console.log_step("Installing hooks in main repo and all dependencies...")
26
- install_hooks_step
27
- else
28
- Console.log_step("Cloning dependencies and installing hooks...")
29
- install_dependencies_step
30
- end
31
-
32
- Console.log_step("Done!")
33
- rescue MultiRepoException => e
34
- Console.log_error(e.message)
35
- end
36
-
37
- def install_dependencies_step
38
- # Read config entries as-is on disk, without prior checkout
39
- config_entries = ConfigFile.load
40
- Console.log_substep("Installing #{config_entries.count} dependencies...");
41
-
42
- # Clone or fetch all configured dependencies to make sure nothing is missing locally
43
- config_entries.each { |entry| clone_or_fetch(entry) }
44
-
45
- # Checkout the appropriate branches as specified in the lock file
46
- checkout_command = CheckoutCommand.new(CLAide::ARGV.new([]))
47
- checkout_command.dependencies_checkout_step(CheckoutCommand::CheckoutMode::LATEST)
48
-
49
- install_hooks_step
50
- end
51
-
52
- def install_hooks_step
53
- install_hooks
54
- Console.log_substep("Installed git hooks in main repo")
55
-
56
- install_hooks_in_multirepo_enabled_dependencies
57
- end
58
-
59
- def clone_or_fetch(entry)
60
- if entry.repo.exists?
61
- check_repo_validity(entry)
62
- fetch_repo(entry)
63
- else
64
- clone_repo(entry)
65
- end
66
- end
67
-
68
- # Repo operations
69
-
70
- def fetch_repo(entry)
71
- Console.log_substep("Working copy '#{entry.repo.path}' already exists, fetching instead...")
72
- raise MultiRepoException, "Could not fetch from remote #{entry.repo.remote('origin').url}" unless entry.repo.fetch
73
- end
74
-
75
- def clone_repo(entry)
76
- Console.log_substep("Cloning #{entry.url} into '#{entry.repo.path}'")
77
- raise MultiRepoException, "Could not clone remote #{entry.url}" unless entry.repo.clone(entry.url)
78
- end
79
-
80
- # Validation
81
-
82
- def check_repo_validity(entry)
83
- unless entry.repo.remote("origin").url == entry.url
84
- raise MultiRepoException, "'#{entry.path}' origin URL (#{entry.repo.remote('origin').url}) does not match entry (#{entry.url})!"
85
- end
86
- end
87
- end
1
+ require "multirepo/utility/console"
2
+ require "multirepo/utility/utils"
3
+ require "multirepo/git/repo"
4
+ require "multirepo/commands/checkout-command"
5
+
6
+ module MultiRepo
7
+ class InstallCommand < Command
8
+ self.command = "install"
9
+ self.summary = "Clones and checks out dependencies as defined in the version-controlled multirepo metadata files and installs git-multirepo's local git hooks."
10
+
11
+ def self.options
12
+ [['[--hooks]', 'Only install local git hooks.']].concat(super)
13
+ end
14
+
15
+ def initialize(argv)
16
+ @hooks = argv.flag?("hooks")
17
+ super
18
+ end
19
+
20
+ def run
21
+ validate_in_work_tree
22
+ ensure_multirepo_initialized
23
+
24
+ if @hooks
25
+ Console.log_step("Installing hooks in main repo and all dependencies...")
26
+ install_hooks_step
27
+ else
28
+ Console.log_step("Cloning dependencies and installing hooks...")
29
+ install_dependencies_step
30
+ end
31
+
32
+ Console.log_step("Done!")
33
+ rescue MultiRepoException => e
34
+ Console.log_error(e.message)
35
+ end
36
+
37
+ def install_dependencies_step
38
+ # Read config entries as-is on disk, without prior checkout
39
+ config_entries = ConfigFile.load
40
+ Console.log_substep("Installing #{config_entries.count} dependencies...");
41
+
42
+ # Clone or fetch all configured dependencies to make sure nothing is missing locally
43
+ config_entries.each { |entry| clone_or_fetch(entry) }
44
+
45
+ # Checkout the appropriate branches as specified in the lock file
46
+ checkout_command = CheckoutCommand.new(CLAide::ARGV.new([]))
47
+ checkout_command.dependencies_checkout_step(CheckoutCommand::CheckoutMode::LATEST)
48
+
49
+ install_hooks_step
50
+ end
51
+
52
+ def install_hooks_step
53
+ install_hooks
54
+ Console.log_substep("Installed git hooks in main repo")
55
+
56
+ install_hooks_in_multirepo_enabled_dependencies
57
+ end
58
+
59
+ def clone_or_fetch(entry)
60
+ if entry.repo.exists?
61
+ check_repo_validity(entry)
62
+ fetch_repo(entry)
63
+ else
64
+ clone_repo(entry)
65
+ end
66
+ end
67
+
68
+ # Repo operations
69
+
70
+ def fetch_repo(entry)
71
+ Console.log_substep("Working copy '#{entry.repo.path}' already exists, fetching instead...")
72
+ raise MultiRepoException, "Could not fetch from remote #{entry.repo.remote('origin').url}" unless entry.repo.fetch
73
+ end
74
+
75
+ def clone_repo(entry)
76
+ Console.log_substep("Cloning #{entry.url} into '#{entry.repo.path}'")
77
+ raise MultiRepoException, "Could not clone remote #{entry.url}" unless entry.repo.clone(entry.url)
78
+ end
79
+
80
+ # Validation
81
+
82
+ def check_repo_validity(entry)
83
+ unless entry.repo.remote("origin").url == entry.url
84
+ raise MultiRepoException, "'#{entry.path}' origin URL (#{entry.repo.remote('origin').url}) does not match entry (#{entry.url})!"
85
+ end
86
+ end
87
+ end
88
88
  end