repo_dependency_graph 0.1.4 → 0.1.5

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: 6cd55bcfea32f568e9450a23f2496fb0e0c603d7
4
- data.tar.gz: fb684fa3c33308e42467b2451509890f012dae8e
3
+ metadata.gz: 578cc8fe75735e91415c393a959f0aad7df3a510
4
+ data.tar.gz: f2201b99a11c80a5d7d8d7b870c416dc1181c99b
5
5
  SHA512:
6
- metadata.gz: 71fafed2fa51e1af31de3c1d0ac7e95d8f463083429c51f0d65012a0ca3745f3bdeb9917eaeeffe3db8837d663d985dc93d947410d15ef6652efb79f1e93ba72
7
- data.tar.gz: 8caafa830b237599f26ac12ea60877a81cb0b4cca0332230d7184d8471427650af028777cc4e64a89381ea9415849ec7f037605d6589d486e1b839439236199c
6
+ metadata.gz: 6245f4ab5d69260041e10ec63614c78d5079eae348f19450d444f3a8bf2a7772daa8a40e5dd14791ed538cf2659766333ed4d057943257e75fd36bc928adc4c6
7
+ data.tar.gz: 9d3d92fe452b30a8d38cf7c23ab17345b60542dd58fafd53329883ff6107d0f1194fb3bea2fc5d64a658b68aebe27937f87e16516706a6c3603be610cd12c4e3
@@ -1,3 +1,3 @@
1
1
  module RepoDependencyGraph
2
- VERSION = "0.1.4"
2
+ VERSION = "0.1.5"
3
3
  end
@@ -7,7 +7,8 @@ module RepoDependencyGraph
7
7
  MAX_HEX = 255
8
8
 
9
9
  def run(argv)
10
- draw(dependencies(parse_options(argv)))
10
+ options = parse_options(argv)
11
+ draw(dependencies(options), options)
11
12
  0
12
13
  end
13
14
 
@@ -28,6 +29,7 @@ module RepoDependencyGraph
28
29
  BANNER
29
30
  opts.on("--token TOKEN", "Use token") { |token| options[:token] = token }
30
31
  opts.on("--user USER", "Use user") { |user| options[:user] = user }
32
+ opts.on("--draw TYPE", "png, html, table (default: png)") { |draw| options[:draw] = draw }
31
33
  opts.on("--organization ORGANIZATION", "Use organization") { |organization| options[:organization] = organization }
32
34
  opts.on("--private", "Only show private repos") { options[:private] = true }
33
35
  opts.on("--external", "Also include external projects in graph (can get super-messy)") { options[:external] = true }
@@ -42,6 +44,12 @@ module RepoDependencyGraph
42
44
  opts.on("-h", "--help", "Show this.") { puts opts; exit }
43
45
  opts.on("-v", "--version", "Show Version"){ puts RepoDependencyGraph::VERSION; exit}
44
46
  end.parse!(argv)
47
+
48
+ options[:token] ||= begin
49
+ token = `git config github.token`.strip
50
+ token if $?.success?
51
+ end
52
+
45
53
  options
46
54
  end
47
55
 
@@ -50,26 +58,119 @@ module RepoDependencyGraph
50
58
  result.empty? ? nil : result
51
59
  end
52
60
 
53
- def draw(dependencies)
54
- require 'graphviz'
61
+ def draw(dependencies, options)
62
+ case options[:draw]
63
+ when "html"
64
+ nodes, edges = convert_to_graphviz(dependencies)
65
+ html = <<-HTML.gsub(/^ /, "")
66
+ <!doctype html>
67
+ <html>
68
+ <head>
69
+ <title>Network</title>
70
+ <style>
71
+ #mynetwork {
72
+ width: 2000px;
73
+ height: 2000px;
74
+ border: 1px solid lightgray;
75
+ background: #F3F3F3;
76
+ }
77
+ </style>
55
78
 
56
- g = GraphViz.new(:G, :type => :digraph)
79
+ <script type="text/javascript" src="http://visjs.org/dist/vis.js"></script>
80
+ <link href="http://visjs.org/dist/vis.css" rel="stylesheet" type="text/css" />
57
81
 
58
- counts = dependency_counts(dependencies)
59
- range = counts.values.min..counts.values.max
82
+ <script type="text/javascript">
83
+ var nodes = null;
84
+ var edges = null;
85
+ var network = null;
60
86
 
61
- nodes = Hash[counts.map do |name, count|
62
- node = g.add_node(name, :color => color(count, range), :style => "filled")
63
- [name, node]
64
- end]
87
+ function draw() {
88
+ nodes = #{nodes.values.to_json};
89
+ edges = #{edges.to_json};
90
+
91
+ var container = document.getElementById('mynetwork');
92
+ var data = {
93
+ nodes: nodes,
94
+ edges: edges
95
+ };
96
+ var options = {stabilize: false};
97
+
98
+ new vis.Network(container, data, options);
99
+ }
100
+ </script>
101
+ </head>
102
+
103
+ <body onload="draw()">
104
+ <div id="mynetwork"></div>
105
+ </body>
106
+ </html>
107
+ HTML
108
+ File.write("out.html", html)
109
+ when "table"
110
+ tables = dependencies.map do |name, uses|
111
+ used = dependencies.map do |d, uses|
112
+ used = uses.detect { |d| d.first == name }
113
+ [d, used.last] if used
114
+ end.compact
115
+ size = [used.size, uses.size, 1].max
116
+ table = []
117
+ size.times do |i|
118
+ table[i] = [
119
+ (used[i] || []).join(": "),
120
+ (name if i == 0),
121
+ (uses[i] || []).join(": ")
122
+ ]
123
+ end
124
+ table.unshift ["Used", "", "Uses"]
125
+ table
126
+ end
127
+ tables.map!{ |t| "<table>\n#{t.map{|t| "<tr>#{t.map{|t| "<td>#{t}</td>" }.join("")}</tr>" }.join("\n")}\n</table>" }
128
+
129
+ html = <<-HTML.gsub(/^ /, "")
130
+ <!doctype html>
131
+ <html>
132
+ <head>
133
+ <title>Network</title>
134
+ <style>
135
+ table { width: 600px; }
136
+ </style>
137
+ </head>
138
+ <body>
139
+ #{tables.join("<br>\n<br>\n")}
140
+ </body>
141
+ </html>
142
+ HTML
143
+ File.write("out.html", html)
144
+ else
145
+ nodes, edges = convert_to_graphviz(dependencies)
146
+ require 'graphviz'
147
+ g = GraphViz.new(:G, :type => :digraph)
148
+
149
+ nodes = Hash[nodes.map do |_, data|
150
+ node = g.add_node(data[:id], :color => data[:color], :style => "filled")
151
+ [data[:id], node]
152
+ end]
65
153
 
66
- dependencies.each do |name, dependencies|
67
- dependencies.each do |dependency|
68
- g.add_edge(nodes[name], nodes[dependency])
154
+ edges.each do |edge|
155
+ g.add_edge(nodes[edge[:from]], nodes[edge[:to]], :label => edge[:label])
69
156
  end
157
+
158
+ g.output(:png => "out.png")
70
159
  end
160
+ end
71
161
 
72
- g.output(:png => "out.png")
162
+ def convert_to_graphviz(dependencies)
163
+ counts = dependency_counts(dependencies)
164
+ range = counts.values.min..counts.values.max
165
+ nodes = Hash[counts.each_with_index.map do |(name, count), i|
166
+ [name, {:id => name, :color => color(count, range)}]
167
+ end]
168
+ edges = dependencies.map do |name, dependencies|
169
+ dependencies.map do |dependency, version|
170
+ {:from => nodes[name][:id], :to => nodes[dependency][:id], :label => (version || '')}
171
+ end
172
+ end.flatten
173
+ [nodes, edges]
73
174
  end
74
175
 
75
176
  def dependencies(options)
@@ -87,9 +188,9 @@ module RepoDependencyGraph
87
188
 
88
189
  dependencies = all.map do |repo|
89
190
  found = dependent_repos(repo, options) || []
90
- found = found & possible unless options[:external]
191
+ found.select! { |f| possible.include?(f.first) } unless options[:external]
91
192
  next if found.empty?
92
- puts "#{repo.name}: #{found.join(", ")}"
193
+ puts "#{repo.name}: #{found.map { |n,v| "#{n}: #{v}" }.join(", ")}"
93
194
  [repo.name, found]
94
195
  end.compact
95
196
  Hash[dependencies]
@@ -98,19 +199,35 @@ module RepoDependencyGraph
98
199
  def dependent_repos(repo, options)
99
200
  if options[:chef]
100
201
  if content = repo.content("metadata.rb")
101
- content.scan(/^\s*depends ['"](.*?)['"]/).flatten
202
+ scan_chef_metadata(content)
102
203
  end
103
204
  else
104
205
  if repo.gem? && spec = load_spec(repo.gemspec_content)
105
- spec.runtime_dependencies.map(&:name)
206
+ spec.runtime_dependencies.map do |d|
207
+ r = d.requirement.to_s
208
+ r = nil if r == ">= 0"
209
+ [d.name, r].compact
210
+ end
106
211
  elsif content = repo.content("Gemfile.lock")
107
- Bundler::LockfileParser.new(content).specs.map(&:name)
212
+ scan_gemfile_lock(content)
108
213
  elsif content = repo.content("Gemfile")
109
- content.scan(/^\s*gem ['"](.*?)['"]/).flatten
214
+ scan_gemfile(content)
110
215
  end
111
216
  end
112
217
  end
113
218
 
219
+ def scan_chef_metadata(content)
220
+ content.scan(/^\s*depends ['"](.*?)['"](?:,\s?['"](.*?)['"])?/).map(&:compact)
221
+ end
222
+
223
+ def scan_gemfile(content)
224
+ content.scan(/^\s*gem ['"](.*?)['"](?:,\s?['"](.*?)['"]|.*\bref(?::|\s*=>)\s*['"](.*)['"])?/).map(&:compact)
225
+ end
226
+
227
+ def scan_gemfile_lock(content)
228
+ Bundler::LockfileParser.new(content).specs.map { |d| [d.name, d.version.to_s] }
229
+ end
230
+
114
231
  def load_spec(content)
115
232
  eval content.
116
233
  gsub(/^\s*require .*$/, "").
@@ -119,7 +236,7 @@ module RepoDependencyGraph
119
236
  gsub(/(File|IO)\.read\(['"]VERSION.*?\)/, '"1.2.3"').
120
237
  gsub(/(File|IO)\.read\(.*?\)/, '\' VERSION = "1.2.3"\'')
121
238
  rescue Exception
122
- puts "Error when parsing content:\n#{content}\n\n#{$!}"
239
+ $stderr.puts "Error when parsing content:\n#{content}\n\n#{$!}"
123
240
  nil
124
241
  end
125
242
 
@@ -135,9 +252,9 @@ module RepoDependencyGraph
135
252
  end
136
253
 
137
254
  def dependency_counts(dependencies)
138
- all = (dependencies.keys + dependencies.values.flatten).uniq
255
+ all = (dependencies.keys + dependencies.values.map { |v| v.map(&:first) }).flatten.uniq
139
256
  Hash[all.map do |k|
140
- [k, dependencies.values.count { |v| v.include?(k) } ]
257
+ [k, dependencies.values.map(&:first).count { |name, _| name == k } ]
141
258
  end]
142
259
  end
143
260
  end
metadata CHANGED
@@ -1,49 +1,27 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: repo_dependency_graph
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Grosser
8
8
  autorequire:
9
9
  bindir: bin
10
- cert_chain:
11
- - |
12
- -----BEGIN CERTIFICATE-----
13
- MIIDcDCCAligAwIBAgIBATANBgkqhkiG9w0BAQUFADA/MRAwDgYDVQQDDAdtaWNo
14
- YWVsMRcwFQYKCZImiZPyLGQBGRYHZ3Jvc3NlcjESMBAGCgmSJomT8ixkARkWAml0
15
- MB4XDTE0MDIwNDIwMjk0MVoXDTE1MDIwNDIwMjk0MVowPzEQMA4GA1UEAwwHbWlj
16
- aGFlbDEXMBUGCgmSJomT8ixkARkWB2dyb3NzZXIxEjAQBgoJkiaJk/IsZAEZFgJp
17
- dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMorXo/hgbUq97+kII9H
18
- MsQcLdC/7wQ1ZP2OshVHPkeP0qH8MBHGg6eYisOX2ubNagF9YTCZWnhrdKrwpLOO
19
- cPLaZbjUjljJ3cQR3B8Yn1veV5IhG86QseTBjymzJWsLpqJ1UZGpfB9tXcsFtuxO
20
- 6vHvcIHdzvc/OUkICttLbH+1qb6rsHUceqh+JrH4GrsJ5H4hAfIdyS2XMK7YRKbh
21
- h+IBu6dFWJJByzFsYmV1PDXln3UBmgAt65cmCu4qPfThioCGDzbSJrGDGLmw/pFX
22
- FPpVCm1zgYSb1v6Qnf3cgXa2f2wYGm17+zAVyIDpwryFru9yF/jJxE38z/DRsd9R
23
- /88CAwEAAaN3MHUwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFLIj
24
- Z1x7SnjGGHK+MiVZkFjjS/iMMB0GA1UdEQQWMBSBEm1pY2hhZWxAZ3Jvc3Nlci5p
25
- dDAdBgNVHRIEFjAUgRJtaWNoYWVsQGdyb3NzZXIuaXQwDQYJKoZIhvcNAQEFBQAD
26
- ggEBAExBcUWfGuamYn+IddOA0Ws8jUKwB14RXoZRDrTiTAlMm3Bkg2OKyxS3uJXa
27
- 6Z+LwFiZwVYk62yHXqNzEJycQk4SEmY+xDWLj0p7X6qEeU4QZKwR1TwJ5z3PTrZ6
28
- irJgM3q7NIBRvmTzRaAghWcQn+Eyr5YLOfMksjVBMUMnzh5/ZDgq53LphgJbGwvz
29
- ScJAgfNclLHnjk9q1mT1s0e1FPWbiAL3siBIR5HpH8qtSEiivTf2ntciebOqS93f
30
- F5etKHZg0j3eHO31/i2HnswY04lqGImUu6aM5EnijFTB7PPW2KwKKM4+kKDYFdlw
31
- /0WV1Ng2/Y6qsHwmqGg2VlYj2h4=
32
- -----END CERTIFICATE-----
33
- date: 2014-02-04 00:00:00.000000000 Z
10
+ cert_chain: []
11
+ date: 2014-09-06 00:00:00.000000000 Z
34
12
  dependencies:
35
13
  - !ruby/object:Gem::Dependency
36
14
  name: organization_audit
37
15
  requirement: !ruby/object:Gem::Requirement
38
16
  requirements:
39
- - - '>='
17
+ - - ">="
40
18
  - !ruby/object:Gem::Version
41
19
  version: '0'
42
20
  type: :runtime
43
21
  prerelease: false
44
22
  version_requirements: !ruby/object:Gem::Requirement
45
23
  requirements:
46
- - - '>='
24
+ - - ">="
47
25
  - !ruby/object:Gem::Version
48
26
  version: '0'
49
27
  description:
@@ -66,17 +44,17 @@ require_paths:
66
44
  - lib
67
45
  required_ruby_version: !ruby/object:Gem::Requirement
68
46
  requirements:
69
- - - '>='
47
+ - - ">="
70
48
  - !ruby/object:Gem::Version
71
49
  version: '0'
72
50
  required_rubygems_version: !ruby/object:Gem::Requirement
73
51
  requirements:
74
- - - '>='
52
+ - - ">="
75
53
  - !ruby/object:Gem::Version
76
54
  version: '0'
77
55
  requirements: []
78
56
  rubyforge_project:
79
- rubygems_version: 2.0.14
57
+ rubygems_version: 2.2.2
80
58
  signing_key:
81
59
  specification_version: 4
82
60
  summary: Show the dependencies of your private repos
checksums.yaml.gz.sig DELETED
Binary file
data.tar.gz.sig DELETED
Binary file
metadata.gz.sig DELETED
Binary file