git-multirepo 1.0.0.beta19 → 1.0.0.beta20

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0f47b8911b32d25d5daa1fe087296860ff278b04
4
- data.tar.gz: 2a9aea7aadbfa5e2ba7ebd20f41048eae806180a
3
+ metadata.gz: 292c05d1335e888a82eeaea12ca7170378669a90
4
+ data.tar.gz: d8c27f7671954a3aeab46ddb9ad55461dfbac529
5
5
  SHA512:
6
- metadata.gz: dc2f4849e897410cda0164e1d3e14dbaf1c821a3777f599e6569c24e43492a1dca53f6260ea5623d64a8f1b561b868db940d17b26650b51eb4b7a16cb244f692
7
- data.tar.gz: b8d457f08acceb627267ac30d6c33efa454989457d7e69d337735016a1619d050684c2dc448afe367a5dfee13083b41a147bbafd2fb9c01272f30b1b6faf4a6d
6
+ metadata.gz: 088543b1a14197625ed68c3aed17bbd8a6b959f638cad894da37f94bca89896249c8152914b9a265727aaf3daee0761a986d213826591ff41ea91ac35e74af59
7
+ data.tar.gz: d98eb47bc0c08028b255f4f229981d2d2608c2ddfc96710706249e4198a7470e17d4c3415f8b906ed987e500630878ccccadab5070e28c34b642f2d9413dc12d
data/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # git-multirepo
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/git-multirepo.svg)](http://badge.fury.io/rb/git-multirepo)
4
+ [![Code Climate](https://codeclimate.com/github/fortinmike/git-multirepo/badges/gpa.svg)](https://codeclimate.com/github/fortinmike/git-multirepo)
5
+ [![License](http://img.shields.io/:license-mit-blue.svg)](https://github.com/fortinmike/git-multirepo/blob/master/LICENSE)
4
6
 
5
7
  Track multiple Git repositories side-by-side.
6
8
 
@@ -64,9 +66,9 @@ Say you want to track an existing project with git-multirepo:
64
66
  2. `cd` into the *AwesomeApp* directory (aka the "main repo").
65
67
  3. Run `multi init`.
66
68
  4. You will get prompted to add *Dependency1* and *Dependency2* to multirepo; do so.
67
- 5. git-multirepo reads all required information from dependency repos and initializes itself, storing its metadata files in the main repo, under version control.
69
+ 5. git-multirepo reads all required information from dependency repos and initializes itself, storing its metadata in the main repo, under version control.
68
70
 
69
- From now on, each time you commit the main repo git-multirepo tracks — using a pre-commit hook — which revision of each dependency is required for that main repo revision, and where to get them. The pre-commit hook also ensures that you won't commit the main repo before its dependencies so that you always get a valid state stored under version control.
71
+ From now on, each time you commit the main repo git-multirepo tracks — using local git hooks — which revision of each dependency is required for that main repo revision, and where to get them. The hooks also ensure that you won't commit the main repo before its dependencies so that you always get a valid state stored under version control.
70
72
 
71
73
  If you want to add another dependency later on, you can run `multi add ../NewDependency` and you can do the opposite with `multi remove ../SomeOtherDependency`.
72
74
 
@@ -78,13 +80,14 @@ If you want to stop using git-multirepo, run `multi uninit`. This will remove al
78
80
 
79
81
  ## Advantages
80
82
 
81
- - Makes setting up the project on a new machine a breeze.
82
- - Works really well for multiple projects that share a common set of constantly evolving dependencies.
83
+ - Makes setting up a project on a new machine a breeze.
84
+ - Really effective when working on multiple projects that share a common set of constantly evolving dependencies.
83
85
  - Each dependency's repository is totally independent from the main repository, which simplifies a lot of things (merges, contributing upstream, etc.) and works well with git GUIs.
84
86
  - While the repositories are independent, git-multirepo makes sure to track everything that's required to bring back a previous version of your project in a valid state.
87
+ - It supports sub-dependencies (e.g. dependencies that have dependencies of their own) so that you can bring back any subset of your project in a valid state at will.
85
88
  - Much more approachable to novice developers than submodules or subtrees.
86
89
  - Once setup, there is little need for git-multirepo commands, so you are free to use whatever tools you like to work with your git repos.
87
- - Low possibility of human error (such as forgetting to contribute dependency changes back to the appropriate remotes, forgetting to commit dependencies before committing the main project, etc.)
90
+ - Low possibility of human error (such as forgetting to contribute changes to dependencies back to the appropriate remotes, forgetting to commit dependencies in the proper order, etc.)
88
91
  - You're not stuck with git-multirepo. It stores its metadata as [YAML](http://www.yaml.org) in the main repo. You can clone and checkout appropriate revisions of your dependencies by hand without git-multirepo if you need to. The information is there, in human-readable form.
89
92
 
90
93
  | How It Handles... | git-multirepo | git submodules | git subtrees |
@@ -100,8 +103,8 @@ If you want to stop using git-multirepo, run `multi uninit`. This will remove al
100
103
 
101
104
  ## Limitations
102
105
 
103
- - git-multirepo should be considered beta at the moment. All of the core features work as described, though. Suggestions and contributions are welcome.
104
- - The project and its dependencies must live beside each other on disk (for now).
106
+ - git-multirepo should be considered beta at the moment. Suggestions and contributions are welcome.
107
+ - The project and its dependencies must live beside each other on disk.
105
108
  - Some more commands need to be implemented to facilitate branch-heavy workflows.
106
109
  - You must (ideally) install the tool on your CI server: `gem install git-multirepo`
107
110
 
@@ -116,7 +119,6 @@ Here is a quick rundown of commands available to you in git-multirepo:
116
119
  | branch | Create and/or checkout a new branch for all repos. |
117
120
  | checkout | Checks out the specified commit or branch of the main repo and checks out matching versions of all dependencies. |
118
121
  | clone | Clones the specified repository in a subfolder, then installs it. |
119
- | edit | Opens the .multirepo file in the default text editor. |
120
122
  | fetch | Performs a git fetch on all dependencies. |
121
123
  | install | Clones and checks out dependencies as defined in the version-controlled multirepo metadata files and installs git-multirepo's local git hooks. |
122
124
  | open | Opens all dependencies in the current OS's file explorer. |
data/bin/multi CHANGED
@@ -3,4 +3,9 @@
3
3
  require "claide"
4
4
  require "commands"
5
5
 
6
+ trap("INT") do
7
+ puts "\rAbort, abort!!" # \r hides the interrupt control characters
8
+ exit
9
+ end
10
+
6
11
  MultiRepo::Command.run(ARGV)
data/lib/commands.rb CHANGED
@@ -3,7 +3,6 @@ require_relative "multirepo/commands/add-command"
3
3
  require_relative "multirepo/commands/branch-command"
4
4
  require_relative "multirepo/commands/checkout-command"
5
5
  require_relative "multirepo/commands/clone-command"
6
- require_relative "multirepo/commands/edit-command"
7
6
  require_relative "multirepo/commands/fetch-command"
8
7
  require_relative "multirepo/commands/init-command"
9
8
  require_relative "multirepo/commands/install-command"
data/lib/info.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module MultiRepo
2
2
  NAME = "git-multirepo"
3
- VERSION = "1.0.0.beta19"
3
+ VERSION = "1.0.0.beta20"
4
4
  DESCRIPTION = "Track multiple Git repositories side-by-side."
5
5
  end
@@ -47,61 +47,73 @@ module MultiRepo
47
47
  CheckoutMode::AS_LOCK
48
48
  end
49
49
 
50
- checkout_core(@ref, mode)
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)
51
56
 
52
57
  Console.log_step("Done!")
53
58
  rescue MultiRepoException => e
54
59
  Console.log_error(e.message)
55
60
  end
56
-
57
- def checkout_core(ref, mode)
58
- main_repo = Repo.new(".")
59
- initial_revision = main_repo.current_branch || main_repo.head_hash
60
-
61
+
62
+ def main_repo_checkout_step(main_repo, initial_revision, ref)
63
+ # Make sure the main repo is clean before attempting a checkout
61
64
  unless main_repo.is_clean?
62
65
  raise MultiRepoException, "Can't checkout #{ref} because the main repo contains uncommitted changes"
63
66
  end
64
67
 
68
+ # Checkout the specified ref
65
69
  unless main_repo.checkout(ref)
66
70
  raise MultiRepoException, "Couldn't perform checkout of main repo #{ref}!"
67
71
  end
68
72
 
69
73
  Console.log_substep("Checked out main repo #{ref}")
70
74
 
71
- unless LockFile.exists?
75
+ # After checkout, make sure we're working with a multirepo-enabled ref
76
+ unless Utils.is_multirepo_enabled(".")
72
77
  main_repo.checkout(initial_revision)
73
- raise MultiRepoException, "The specified revision was not managed by multirepo. Checkout reverted."
78
+ raise MultiRepoException, "This revision is not managed by multirepo. Checkout reverted."
74
79
  end
75
-
80
+ end
81
+
82
+ def ensure_dependencies_clean_step(initial_revision)
76
83
  unless Utils.ensure_dependencies_clean(ConfigFile.load)
77
84
  main_repo.checkout(initial_revision)
78
- raise MultiRepoException, "'#{e.path}' contains uncommitted changes. Checkout reverted."
85
+ raise MultiRepoException, "Checkout reverted."
79
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
80
97
 
81
- config_entries = ConfigFile.load # Load the post-checkout config entries, which might be different than pre-checkout
82
- LockFile.load.each do |lock_entry|
83
- config_entry = config_entries.select{ |config_entry| config_entry.id == lock_entry.id }.first
84
-
85
- # First, make sure the repo exists on disk, and clone it if it doesn't
86
- # (in case the checked-out revision had an additional dependency)
87
- unless config_entry.repo.exists?
88
- Console.log_substep("Cloning missing dependency '#{config_entry.path}' from #{config_entry.url}")
89
- config_entry.repo.clone(config_entry.url)
90
- end
91
-
92
- # Find out the proper revision to checkout based on the checkout mode
93
- revision = case mode
94
- when CheckoutMode::AS_LOCK; lock_entry.head
95
- when CheckoutMode::LATEST; lock_entry.branch
96
- when CheckoutMode::EXACT; ref
97
- end
98
-
99
- # Checkout!
100
- if config_entry.repo.checkout(revision)
101
- Console.log_substep("Checked out #{lock_entry.name} #{revision}")
102
- else
103
- raise MultiRepoException, "Couldn't check out the appropriate version of dependency #{lock_entry.name}"
104
- end
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}"
105
117
  end
106
118
  end
107
119
  end
@@ -19,7 +19,7 @@ module MultiRepo
19
19
  def initialize(argv)
20
20
  @url = argv.shift_argument
21
21
  @name = argv.shift_argument
22
- @ref = argv.shift_argument
22
+ @ref = argv.shift_argument || "master"
23
23
  super
24
24
  end
25
25
 
@@ -35,20 +35,33 @@ module MultiRepo
35
35
  raise MultiRepoException, "A directory named #{@name} already exists" if Dir.exists?(@name)
36
36
 
37
37
  main_repo_path = "#{@name}/#{@name}"
38
-
39
- FileUtils.mkpath(main_repo_path)
40
-
41
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
42
44
  raise MultiRepoException, "Could not clone repo from #{@url}" unless main_repo.clone(@url)
43
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
44
59
  original_path = Dir.pwd
45
60
  Dir.chdir(main_repo_path)
46
-
47
61
  install_command = InstallCommand.new(CLAide::ARGV.new([]))
48
- install_command.install_core(@ref)
49
-
62
+ install_command.install_dependencies_step
50
63
  Dir.chdir(original_path)
51
-
64
+
52
65
  Console.log_step("Done!")
53
66
  rescue MultiRepoException => e
54
67
  Console.log_error(e.message)
@@ -9,11 +9,11 @@ module MultiRepo
9
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
10
 
11
11
  def self.options
12
- [['[ref]', 'The branch, tag or commit id to checkout. Checkout will use "master" if unspecified.']].concat(super)
12
+ [['-hooks', 'Only install local git hooks.']].concat(super)
13
13
  end
14
14
 
15
15
  def initialize(argv)
16
- @ref = argv.shift_argument
16
+ @hooks = argv.flag?("hooks")
17
17
  super
18
18
  end
19
19
 
@@ -21,27 +21,35 @@ module MultiRepo
21
21
  validate_in_work_tree
22
22
  ensure_multirepo_initialized
23
23
 
24
- Console.log_step("Cloning dependencies and installing hook...")
25
-
26
- install_core(@ref)
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
27
31
 
28
32
  Console.log_step("Done!")
29
33
  rescue MultiRepoException => e
30
34
  Console.log_error(e.message)
31
35
  end
32
36
 
33
- def install_core(ref)
37
+ def install_dependencies_step
38
+ # Read config entries as-is on disk, without prior checkout
34
39
  config_entries = ConfigFile.load
35
-
36
40
  Console.log_substep("Installing #{config_entries.count} dependencies...");
37
41
 
38
- # Clone or fetch all configured dependencies
42
+ # Clone or fetch all configured dependencies to make sure nothing is missing locally
39
43
  config_entries.each { |entry| clone_or_fetch(entry) }
40
44
 
41
45
  # Checkout the appropriate branches as specified in the lock file
42
46
  checkout_command = CheckoutCommand.new(CLAide::ARGV.new([]))
43
- checkout_command.checkout_core(ref || "master", CheckoutCommand::CheckoutMode::LATEST)
47
+ checkout_command.dependencies_checkout_step(CheckoutCommand::CheckoutMode::LATEST)
44
48
 
49
+ install_hooks_step
50
+ end
51
+
52
+ def install_hooks_step
45
53
  install_hooks
46
54
  Console.log_substep("Installed git hooks in main repo")
47
55
 
@@ -69,12 +77,6 @@ module MultiRepo
69
77
  raise MultiRepoException, "Could not clone remote #{entry.url}" unless entry.repo.clone(entry.url)
70
78
  end
71
79
 
72
- def checkout_branch(entry)
73
- branch = entry.repo.branch(entry.branch);
74
- raise MultiRepoException, "Could not checkout branch #{branch.name}" unless branch.checkout
75
- Console.log_substep("Checked out branch #{branch.name} -> origin/#{branch.name}")
76
- end
77
-
78
80
  # Validation
79
81
 
80
82
  def check_repo_validity(entry)
@@ -24,11 +24,6 @@ module MultiRepo
24
24
 
25
25
  Console.log_step("Updating...")
26
26
 
27
- install_hooks
28
- Console.log_substep("Installed git hooks in main repo")
29
-
30
- install_hooks_in_multirepo_enabled_dependencies
31
-
32
27
  dependencies_clean = Utils.ensure_dependencies_clean(ConfigFile.load)
33
28
  if dependencies_clean
34
29
  LockFile.update
@@ -8,7 +8,8 @@ module MultiRepo
8
8
  end
9
9
 
10
10
  def self.is_multirepo_enabled(path)
11
- File.exists?(File.join(path, ".multirepo"))
11
+ File.exists?(File.join(path, ".multirepo")) &&
12
+ File.exists?(File.join(path, ".multirepo.lock"))
12
13
  end
13
14
 
14
15
  def self.install_hook(name, path)
@@ -22,21 +23,25 @@ module MultiRepo
22
23
  end
23
24
 
24
25
  def self.ensure_dependencies_clean(config_entries)
25
- config_entries.all? do |e|
26
- next true unless e.repo.exists?
27
- clean = e.repo.is_clean?
28
- Console.log_info("Dependency '#{e.repo.path}' is clean") if clean
29
- Console.log_warning("Dependency '#{e.repo.path}' contains uncommitted changes") unless clean
30
- next clean
26
+ clean = true
27
+ config_entries.each do |e|
28
+ next unless e.repo.exists?
29
+ dependency_clean = e.repo.is_clean?
30
+ clean &= dependency_clean
31
+ Console.log_info("Dependency '#{e.repo.path}' is clean") if dependency_clean
32
+ Console.log_warning("Dependency '#{e.repo.path}' contains uncommitted changes") unless dependency_clean
31
33
  end
34
+ return clean
32
35
  end
33
36
 
34
37
  def self.ensure_working_copies_clean(repos)
35
- repos.all? do |repo|
36
- clean = repo.is_clean?
37
- Console.log_warning("Repo '#{repo.path}' contains uncommitted changes") unless clean
38
- next clean
38
+ clean = true
39
+ repos.each do |repo|
40
+ dependency_clean = e.repo.is_clean?
41
+ clean &= dependency_clean
42
+ Console.log_warning("Repo '#{repo.path}' contains uncommitted changes") unless dependency_clean
39
43
  end
44
+ return clean
40
45
  end
41
46
 
42
47
  def self.convert_to_windows_path(unix_path)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: git-multirepo
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.beta19
4
+ version: 1.0.0.beta20
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michaël Fortin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-04-01 00:00:00.000000000 Z
11
+ date: 2015-04-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -127,7 +127,6 @@ files:
127
127
  - lib/multirepo/commands/checkout-command.rb
128
128
  - lib/multirepo/commands/clone-command.rb
129
129
  - lib/multirepo/commands/command.rb
130
- - lib/multirepo/commands/edit-command.rb
131
130
  - lib/multirepo/commands/fetch-command.rb
132
131
  - lib/multirepo/commands/init-command.rb
133
132
  - lib/multirepo/commands/install-command.rb
@@ -1,22 +0,0 @@
1
- require "os"
2
-
3
- module MultiRepo
4
- class EditCommand < Command
5
- self.command = "edit"
6
- self.summary = "Opens the .multirepo file in the default text editor."
7
-
8
- def run
9
- validate_in_work_tree
10
- ensure_multirepo_initialized
11
-
12
- if OS.posix?
13
- editor = `echo ${FCEDIT:-${VISUAL:-${EDITOR:-vi}}}`.strip
14
- system(editor, ".multirepo")
15
- elsif OS.windows?
16
- raise MultiRepoException, "The edit command is not implemented on Window yet."
17
- end
18
- rescue MultiRepoException => e
19
- Console.log_error(e.message)
20
- end
21
- end
22
- end