git-multirepo 1.0.0.beta21 → 1.0.0.beta24

Sign up to get free protection for your applications and to get access to all the features.
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