git-multirepo 1.0.0.beta38 → 1.0.0.beta39

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 422c984238cb4049bcededa9a63ac57ca1d13445
4
- data.tar.gz: f9e95a0941a9160fc5b714d76bd5c3664c35ba67
3
+ metadata.gz: 94c594ab8e4c0338d3e5e70bb31d4315c1b7fbf0
4
+ data.tar.gz: 0a9b1e7b957e605d17a053abc01c262f7c3c56fb
5
5
  SHA512:
6
- metadata.gz: 73835b202c7a7d5e0104cca153488d57bc3173f30efcb04cea4f0a277f4c522215de0e50dcbeab6cd4216987f794268b6e8fd852d4b62bdbdefd6793ad6878ff
7
- data.tar.gz: 7590706f24a5ca82f2275dbeb361fe251223ccdb6797f959a9fbeb941c0f0b7d852958ca2e01586bdac2be10ccd33a2c4627c732b9e7aadc5ccdebf86b405be9
6
+ metadata.gz: 4179388b91395ade82973ab214327ea34560c3a39d06db5eb4bc6e9461309f39f9ab47611bfb82bfd88f27336a758120c24ea520c6e3b3be3a687ea8ce6b7715
7
+ data.tar.gz: 7ab8047c6256c0001a317d19e398bb0d4093e57f6bd9b7d9bf89339bc39603539ab70513d5c032f049b58219d922fe18c289246809d4182ec96b79954c2d977d
data/.multirepo.meta CHANGED
@@ -1,2 +1,2 @@
1
1
  --- !ruby/object:MultiRepo::MetaFile
2
- version: 1.0.0.beta37
2
+ version: 1.0.0.beta38
data/Gemfile.lock CHANGED
@@ -1,10 +1,12 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- git-multirepo (1.0.0.beta25)
4
+ git-multirepo (1.0.0.beta38)
5
5
  claide (~> 0.8, >= 0.8.0)
6
6
  colored (~> 1.2)
7
7
  os (~> 0.9.6)
8
+ ruby-graphviz (~> 1.2.1)
9
+ terminal-table (~> 1.4.5)
8
10
 
9
11
  GEM
10
12
  remote: https://rubygems.org/
@@ -26,6 +28,8 @@ GEM
26
28
  rspec-mocks (3.1.3)
27
29
  rspec-support (~> 3.1.0)
28
30
  rspec-support (3.1.2)
31
+ ruby-graphviz (1.2.2)
32
+ terminal-table (1.4.5)
29
33
 
30
34
  PLATFORMS
31
35
  ruby
data/README.md CHANGED
@@ -123,9 +123,10 @@ Here is a quick rundown of commands available to you in git-multirepo:
123
123
  | clean | Performs a 'git clean -df' on the main repo and all dependencies. |
124
124
  | clone | Clones the specified repository in a subfolder, then installs it. |
125
125
  | fetch | Performs a git fetch on all dependencies. |
126
+ | graph | Graphs the dependency tree from the current repository. |
126
127
  | install | Clones and checks out dependencies as defined in the version-controlled multirepo metadata files and installs git-multirepo's local git hooks. |
127
128
  | merge | Performs a git merge on all dependencies and the main repo, in the proper order. |
128
- | open | Opens all dependencies in the current OS's file explorer. |
129
+ | open | Opens repositories in the OS's file explorer. |
129
130
  | remove | Removes the specified dependency from multirepo. |
130
131
  | update | Force-updates the multirepo tracking files. |
131
132
  | uninit | Removes all traces of multirepo in the current multirepo repository. |
Binary file
@@ -27,4 +27,5 @@ Gem::Specification.new do |spec|
27
27
  spec.add_runtime_dependency "colored", "~> 1.2"
28
28
  spec.add_runtime_dependency "os", "~> 0.9.6"
29
29
  spec.add_runtime_dependency "terminal-table", "~> 1.4.5"
30
+ spec.add_runtime_dependency "ruby-graphviz", "~> 1.2.1"
30
31
  end
data/lib/commands.rb CHANGED
@@ -5,6 +5,7 @@ require_relative "multirepo/commands/checkout-command"
5
5
  require_relative "multirepo/commands/clean-command"
6
6
  require_relative "multirepo/commands/clone-command"
7
7
  require_relative "multirepo/commands/fetch-command"
8
+ require_relative "multirepo/commands/graph-command"
8
9
  require_relative "multirepo/commands/init-command"
9
10
  require_relative "multirepo/commands/install-command"
10
11
  require_relative "multirepo/commands/merge-command"
data/lib/info.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module MultiRepo
2
2
  NAME = "git-multirepo"
3
- VERSION = "1.0.0.beta38"
3
+ VERSION = "1.0.0.beta39"
4
4
  DESCRIPTION = "Track multiple Git repositories side-by-side."
5
5
  end
@@ -1,6 +1,7 @@
1
1
  require "multirepo/utility/console"
2
2
  require "multirepo/files/config-file"
3
3
  require "multirepo/files/tracking-files"
4
+ require "multirepo/logic/performer"
4
5
 
5
6
  module MultiRepo
6
7
  class BranchCommand < Command
@@ -11,14 +12,14 @@ module MultiRepo
11
12
  [
12
13
  ['<branch name>', 'The name of the branch to create and checkout.'],
13
14
  ['[--force]', 'Force creating the branch even if the repos contain uncommmitted changes.'],
14
- ['[--no-track]', 'Do not configure as a remote-tracking branch on creation.']
15
+ ['[--no-push]', 'Do not push the branch on creation.']
15
16
  ].concat(super)
16
17
  end
17
18
 
18
19
  def initialize(argv)
19
20
  @branch_name = argv.shift_argument
20
21
  @force = argv.flag?("force")
21
- @remote_tracking = argv.flag?("track", true)
22
+ @remote_tracking = argv.flag?("push", true)
22
23
  super
23
24
  end
24
25
 
@@ -35,32 +36,48 @@ module MultiRepo
35
36
  Console.log_step("Branching...")
36
37
 
37
38
  main_repo = Repo.new(".")
38
- config_file = ConfigFile.new(".")
39
- repos = config_file.load_entries.map{ |entry| entry.repo }.push(main_repo)
40
39
 
41
- if !Utils.ensure_working_copies_clean(repos) && !@force
42
- raise MultiRepoException, "Can't branch because not all repos are clean"
40
+ # Ensure the main repo is clean
41
+ raise MultiRepoException, "Main repo is not clean; multi branch aborted" unless main_repo.clean?
42
+
43
+ # Ensure dependencies are clean
44
+ config_entries = ConfigFile.new(".").load_entries
45
+ unless Utils.ensure_dependencies_clean(config_entries)
46
+ raise MultiRepoException, "Dependencies are not clean; multi branch aborted"
43
47
  end
44
48
 
45
- repos.each do |repo|
46
- if @remote_tracking
47
- Console.log_substep("Branching, checking out and pushing '#{repo.path}' #{@branch_name} ...")
48
- else
49
- Console.log_substep("Branching and checking out '#{repo.path}' #{@branch_name} (not pushed) ...")
50
- end
51
-
52
- branch = repo.branch(@branch_name)
53
- branch.create(@remote_tracking) unless branch.exists?
54
- branch.checkout
49
+ # Branch dependencies
50
+ Performer.perform_on_dependencies do |config_entry, lock_entry|
51
+ perform_branch(config_entry.repo)
55
52
  end
56
-
57
- Console.log_substep("Updating and committing tracking files")
58
- TrackingFiles.update
59
- TrackingFiles.commit("[multirepo] Post-branch tracking files update")
60
-
53
+
54
+ # Branch the main repo
55
+ perform_branch(main_repo)
56
+
61
57
  Console.log_step("Done!")
62
58
  rescue MultiRepoException => e
63
59
  Console.log_error(e.message)
64
60
  end
61
+
62
+ def perform_branch(repo)
63
+ Console.log_substep("Branching '#{repo.path}' ...")
64
+ Console.log_info("Creating and checking out branch #{@branch_name} ...")
65
+
66
+ branch = repo.branch(@branch_name)
67
+ branch.create unless branch.exists?
68
+ branch.checkout
69
+
70
+ if Utils.is_multirepo_enabled(repo.path)
71
+ Console.log_info("Updating and committing tracking files")
72
+ tracking_files = TrackingFiles.new(repo.path)
73
+ tracking_files.update
74
+ tracking_files.commit("[multirepo] Post-branch tracking files update")
75
+ end
76
+
77
+ if @remote_tracking
78
+ Console.log_info("Pushing #{@branch_name} to origin/#{@branch_name}")
79
+ repo.branch(@branch_name).push
80
+ end
81
+ end
65
82
  end
66
83
  end
@@ -25,7 +25,9 @@ module MultiRepo
25
25
  def validate!
26
26
  super
27
27
  help! "You must specify a branch or commit id to checkout" unless @ref
28
- help! "You can't provide more than one operation modifier (--latest, --exact, etc.)" if @checkout_latest && @checkout_exact
28
+ unless validate_only_one_flag(@checkout_latest, @checkout_exact)
29
+ help! "You can't provide more than one operation modifier (--latest, --exact, etc.)"
30
+ end
29
31
  end
30
32
 
31
33
  def run
@@ -54,6 +54,10 @@ module MultiRepo
54
54
  def multirepo_enabled_dependencies
55
55
  ConfigFile.new(".").load_entries.select { |e| Utils.is_multirepo_enabled(e.repo.path) }
56
56
  end
57
+
58
+ def validate_only_one_flag(*flags)
59
+ flags.reduce(0) { |count, flag| count += 1 if flag; count } <= 1
60
+ end
57
61
 
58
62
  def ensure_in_work_tree
59
63
  repo = Repo.new(".")
@@ -0,0 +1,46 @@
1
+ require "os"
2
+ require "graphviz"
3
+
4
+ require "multirepo/utility/utils"
5
+ require "multirepo/utility/console"
6
+ require "multirepo/logic/node"
7
+
8
+ module MultiRepo
9
+ class GraphCommand < Command
10
+ self.command = "graph"
11
+ self.summary = "Graphs the dependency tree from the current repository."
12
+
13
+ def run
14
+ super
15
+ ensure_in_work_tree
16
+ ensure_multirepo_enabled
17
+
18
+ root = Node.new(".")
19
+ graph = GraphViz.new(:G, :type => :digraph)
20
+ build_graph_recursive(graph, root)
21
+
22
+ path = File.expand_path("~/Desktop/#{root.name}-graph.png")
23
+
24
+ begin
25
+ graph.output(:png => path)
26
+ Utils.open_in_default_app(path)
27
+ rescue StandardError => e
28
+ Console.log_error(e.message)
29
+ raise MultiRepoException, "Could not generate graph image because an error occurred during graph generation"
30
+ end
31
+
32
+ Console.log_step("Generated graph image #{path}")
33
+ rescue MultiRepoException => e
34
+ Console.log_error(e.message)
35
+ end
36
+
37
+ def build_graph_recursive(graph, node)
38
+ parent_graph_node = graph.add_nodes(node.name)
39
+ node.children.each do |child_node|
40
+ child_graph_node = graph.add_nodes(child_node.name)
41
+ graph.add_edges(parent_graph_node, child_graph_node)
42
+ build_graph_recursive(graph, child_node)
43
+ end
44
+ end
45
+ end
46
+ end
@@ -77,7 +77,7 @@ module MultiRepo
77
77
  end
78
78
 
79
79
  def update_gitattributes_step
80
- TrackingFiles::FILES.each do |f|
80
+ TrackingFiles.new(".").files.each do |f|
81
81
  filename = f.filename
82
82
  regex_escaped_filename = Regexp.quote(filename)
83
83
  Utils.append_if_missing("./.gitattributes", /^#{regex_escaped_filename} .*/, "#{filename} merge=ours")
@@ -29,7 +29,9 @@ module MultiRepo
29
29
  def validate!
30
30
  super
31
31
  help! "You must specify a ref to merge" unless @ref
32
- help! "You can't provide more than one operation modifier (--latest, --exact, etc.)" if @checkout_latest && @checkout_exact
32
+ unless validate_only_one_flag(@checkout_latest, @checkout_exact)
33
+ help! "You can't provide more than one operation modifier (--latest, --exact, etc.)"
34
+ end
33
35
  end
34
36
 
35
37
  def run
@@ -6,22 +6,53 @@ require "multirepo/utility/utils"
6
6
  module MultiRepo
7
7
  class OpenCommand < Command
8
8
  self.command = "open"
9
- self.summary = "Opens all dependencies in the current OS's file explorer."
9
+ self.summary = "Opens repositories in the OS's file explorer."
10
+
11
+ def self.options
12
+ [
13
+ ['[--main]', 'Open the main repository.'],
14
+ ['[--all]', 'Open the main repository and all dependencies.'],
15
+ ].concat(super)
16
+ end
17
+
18
+ def initialize(argv)
19
+ @main_only = argv.flag?("main")
20
+ @all = argv.flag?("all")
21
+ super
22
+ end
23
+
24
+ def validate!
25
+ super
26
+ unless validate_only_one_flag(@main_only, @all)
27
+ help! "You can't provide more than one operation modifier (--deps, --main, etc.)"
28
+ end
29
+ end
10
30
 
11
31
  def run
12
32
  super
13
33
  ensure_in_work_tree
14
34
  ensure_multirepo_enabled
15
35
 
16
- ConfigFile.new(".").load_entries.each do |entry|
17
- if OS.osx?
18
- `open "#{entry.repo.path}"`
19
- elsif OS.windows?
20
- `explorer "#{Utils.convert_to_windows_path(entry.repo.path)}"`
21
- end
36
+ if @main_only
37
+ open_main
38
+ elsif @all
39
+ open_dependencies
40
+ open_main
41
+ else
42
+ open_dependencies
22
43
  end
23
44
  rescue MultiRepoException => e
24
45
  Console.log_error(e.message)
25
46
  end
47
+
48
+ def open_main
49
+ Utils.reveal_in_default_file_browser(".")
50
+ end
51
+
52
+ def open_dependencies
53
+ ConfigFile.new(".").load_entries.each do |entry|
54
+ Utils.reveal_in_default_file_browser(entry.repo.path)
55
+ end
56
+ end
26
57
  end
27
58
  end
@@ -10,7 +10,7 @@ module MultiRepo
10
10
  ensure_in_work_tree
11
11
 
12
12
  FileUtils.rm_f(".multirepo")
13
- TrackingFiles.delete
13
+ TrackingFiles.new(".").delete
14
14
  uninstall_hooks
15
15
 
16
16
  Console.log_step("All traces of multirepo have been removed from this repository")
@@ -41,7 +41,8 @@ module MultiRepo
41
41
  end
42
42
 
43
43
  def update_lock_file_step(log_message)
44
- changed = TrackingFiles.update
44
+ tracking_files = TrackingFiles.new(".")
45
+ changed = tracking_files.update
45
46
 
46
47
  if changed
47
48
  Console.log_substep("Updated tracking files")
@@ -50,7 +51,7 @@ module MultiRepo
50
51
  end
51
52
 
52
53
  if @commit
53
- committed = TrackingFiles.commit("[multirepo] Updated tracking files manually")
54
+ committed = tracking_files.commit("[multirepo] Updated tracking files manually")
54
55
  Console.log_substep("Committed tracking files") if committed
55
56
  elsif changed
56
57
  Console.log_substep(log_message)
@@ -4,39 +4,44 @@ require_relative "lock-file"
4
4
 
5
5
  module MultiRepo
6
6
  class TrackingFiles
7
- FILES = [MetaFile.new("."), LockFile.new(".")]
7
+ attr_accessor :files
8
8
 
9
- def self.update
9
+ def initialize(path)
10
+ @path = path
11
+ @files = [MetaFile.new(path), LockFile.new(path)]
12
+ end
13
+
14
+ def update
10
15
  updated = false
11
- FILES.each { |f| updated |= f.update }
16
+ files.each { |f| updated |= f.update }
12
17
  return updated
13
18
  end
14
19
 
15
- def self.stage
16
- GitRunner.run_in_current_dir("add --force -- #{files_pathspec}", Runner::Verbosity::OUTPUT_ON_ERROR)
20
+ def stage
21
+ GitRunner.run_in_working_dir(@path, "add --force -- #{files_pathspec}", Runner::Verbosity::OUTPUT_ON_ERROR)
17
22
  end
18
23
 
19
- def self.commit(message)
24
+ def commit(message)
20
25
  stage
21
26
 
22
- output = GitRunner.run_in_current_dir("ls-files --modified --others -- #{files_pathspec}", Runner::Verbosity::OUTPUT_NEVER)
27
+ output = GitRunner.run_in_working_dir(@path, "ls-files --modified --others -- #{files_pathspec}", Runner::Verbosity::OUTPUT_NEVER)
23
28
  files_are_untracked_or_modified = output.strip != ""
24
29
 
25
- output = GitRunner.run_in_current_dir("diff --name-only --cached -- #{files_pathspec}", Runner::Verbosity::OUTPUT_NEVER)
30
+ output = GitRunner.run_in_working_dir(@path, "diff --name-only --cached -- #{files_pathspec}", Runner::Verbosity::OUTPUT_NEVER)
26
31
  files_are_staged = output.strip != ""
27
32
 
28
33
  must_commit = files_are_untracked_or_modified || files_are_staged
29
- GitRunner.run_in_current_dir("commit -m \"#{message}\" --only -- #{files_pathspec}", Runner::Verbosity::OUTPUT_ON_ERROR) if must_commit
30
-
34
+ GitRunner.run_in_working_dir(@path, "commit --no-verify -m \"#{message}\" --only -- #{files_pathspec}", Runner::Verbosity::OUTPUT_ON_ERROR) if must_commit
35
+
31
36
  return must_commit
32
37
  end
33
38
 
34
- def self.delete
35
- FILES.each { |f| FileUtils.rm_f(f.file) }
39
+ def delete
40
+ files.each { |f| FileUtils.rm_f(f.file) }
36
41
  end
37
42
 
38
- def self.files_pathspec
39
- FILES.map{ |f| f.file }.join(" ")
43
+ def files_pathspec
44
+ files.map{ |f| File.basename(f.file) }.join(" ")
40
45
  end
41
46
  end
42
47
  end
@@ -15,9 +15,12 @@ module MultiRepo
15
15
  branch_names.include?(@name)
16
16
  end
17
17
 
18
- def create(remote_tracking = false)
18
+ def create
19
19
  GitRunner.run_in_working_dir(@repo.path, "branch #{@name}", Runner::Verbosity::OUTPUT_ON_ERROR)
20
- GitRunner.run_in_working_dir(@repo.path, "push -u origin #{name}", Runner::Verbosity::OUTPUT_ON_ERROR) if remote_tracking
20
+ end
21
+
22
+ def push
23
+ GitRunner.run_in_working_dir(@repo.path, "push -u origin #{@name}", Runner::Verbosity::OUTPUT_ON_ERROR)
21
24
  end
22
25
 
23
26
  def checkout
@@ -13,7 +13,15 @@ module MultiRepo
13
13
  end
14
14
 
15
15
  def self.run_in_working_dir(path, git_command, verbosity)
16
- full_command = "#{git_executable} -C \"#{path}\" #{git_command}";
16
+ if path == "."
17
+ # It is always better to skip -C when running git commands in the
18
+ # current directory (especially in hooks). Doing this prevents
19
+ # any future issues because we automatically fallback to non-"-C" for ".".
20
+ # Fixes bug: https://www.pivotaltracker.com/story/show/94505654
21
+ return run_in_current_dir(git_command, verbosity)
22
+ else
23
+ full_command = "#{git_executable} -C \"#{path}\" #{git_command}";
24
+ end
17
25
 
18
26
  # True fix for the -C flag issue in pre-commit hook where the status command would
19
27
  # fail to provide correct results if a pathspec was provided when performing a commit.
@@ -11,7 +11,7 @@ module MultiRepo
11
11
  Console.log_step("Performing post-commit operations...")
12
12
 
13
13
  # Works around bug #91565510 (https://www.pivotaltracker.com/story/show/91565510)
14
- TrackingFiles.stage
14
+ TrackingFiles.new(".").stage
15
15
  Console.log_info("Cleaned-up staging area")
16
16
 
17
17
  exit 0 # Success!
@@ -17,8 +17,10 @@ module MultiRepo
17
17
  exit 1
18
18
  end
19
19
 
20
- TrackingFiles.update
21
- TrackingFiles.stage
20
+ tracking_files = TrackingFiles.new(".")
21
+ tracking_files.update
22
+ tracking_files.stage
23
+
22
24
  Console.log_info("Updated and staged tracking files")
23
25
 
24
26
  exit 0 # Success!
@@ -10,6 +10,10 @@ module MultiRepo
10
10
  @depth = depth
11
11
  end
12
12
 
13
+ def name
14
+ Pathname.new(File.expand_path(@path)).basename.to_s
15
+ end
16
+
13
17
  def children
14
18
  return [] unless Utils.is_multirepo_enabled(@path)
15
19
  config_entries = ConfigFile.new(@path).load_entries
@@ -54,6 +54,22 @@ module MultiRepo
54
54
  components.join(File::ALT_SEPARATOR)
55
55
  end
56
56
 
57
+ def self.reveal_in_default_file_browser(unix_path)
58
+ if OS.osx?
59
+ system %{open "#{unix_path}"}
60
+ elsif OS.windows?
61
+ system %{explorer "#{Utils.convert_to_windows_path(unix_path)}"}
62
+ end
63
+ end
64
+
65
+ def self.open_in_default_app(unix_path)
66
+ if OS.osx?
67
+ system %{open "#{unix_path}"}
68
+ elsif OS.windows?
69
+ system %{cmd /c "start C:\\#{Utils.convert_to_windows_path(unix_path)}"}
70
+ end
71
+ end
72
+
57
73
  def self.append_if_missing(path, pattern, string_to_append)
58
74
  unless File.exists?(path)
59
75
  File.open(path, 'w') { |f| f.puts(string_to_append) }
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.beta38
4
+ version: 1.0.0.beta39
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-05-12 00:00:00.000000000 Z
11
+ date: 2015-05-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -114,6 +114,20 @@ dependencies:
114
114
  - - ~>
115
115
  - !ruby/object:Gem::Version
116
116
  version: 1.4.5
117
+ - !ruby/object:Gem::Dependency
118
+ name: ruby-graphviz
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ~>
122
+ - !ruby/object:Gem::Version
123
+ version: 1.2.1
124
+ type: :runtime
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ~>
129
+ - !ruby/object:Gem::Version
130
+ version: 1.2.1
117
131
  description: Track multiple Git repositories side-by-side.
118
132
  email:
119
133
  - fortinmike@irradiated.net
@@ -151,6 +165,7 @@ files:
151
165
  - lib/multirepo/commands/clone-command.rb
152
166
  - lib/multirepo/commands/command.rb
153
167
  - lib/multirepo/commands/fetch-command.rb
168
+ - lib/multirepo/commands/graph-command.rb
154
169
  - lib/multirepo/commands/init-command.rb
155
170
  - lib/multirepo/commands/install-command.rb
156
171
  - lib/multirepo/commands/merge-command.rb