repo_dependency_graph 0.1.4 → 0.1.5

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: 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