librariesio-gem-parser 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,38 @@
1
+ module Gemnasium
2
+ module Parser
3
+ class Podspec
4
+ attr_reader :content
5
+
6
+ def initialize(content)
7
+ @content = content
8
+ end
9
+
10
+ def dependencies
11
+ @dependencies ||= [].tap do |deps|
12
+ runtime_matches.each do |match|
13
+ dep = dependency(match)
14
+ deps << dep
15
+ end
16
+ end
17
+ end
18
+
19
+ private
20
+ def runtime_matches
21
+ @runtime_matches ||= matches(Patterns::ADD_POD_DEPENDENCY_CALL)
22
+ end
23
+
24
+ def matches(pattern)
25
+ [].tap{|m| content.scan(pattern){ m << Regexp.last_match } }
26
+ end
27
+
28
+ def dependency(match)
29
+ name, reqs = match["name"], [match["req1"], match["req2"]].compact
30
+ type = :runtime
31
+ Bundler::Dependency.new(name, reqs, "type" => type).tap do |dep|
32
+ line = content.slice(0, match.begin(0)).count("\n") + 1
33
+ dep.instance_variable_set(:@line, line)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,20 @@
1
+ # encoding: utf-8
2
+
3
+ Gem::Specification.new do |gem|
4
+ gem.name = "librariesio-gem-parser"
5
+ gem.version = "1.0.0"
6
+
7
+ gem.authors = "Andrew Nesbitt"
8
+ gem.email = "andrewnez@gmail.com"
9
+ gem.description = "Fork of gemnasium-parser"
10
+ gem.summary = gem.description
11
+ gem.homepage = "https://github.com/librariesio/gemnasium-parser"
12
+
13
+ gem.add_development_dependency "bundler", "~> 1.0"
14
+ gem.add_development_dependency "rake", ">= 0.8.7"
15
+ gem.add_development_dependency "rspec", "~> 2.4"
16
+
17
+ gem.files = `git ls-files`.split($\)
18
+ gem.test_files = gem.files.grep(/^spec\//)
19
+ gem.require_paths = ["lib"]
20
+ end
@@ -0,0 +1,294 @@
1
+ require "spec_helper"
2
+
3
+ describe Gemnasium::Parser::Gemfile do
4
+ def content(string)
5
+ @content ||= begin
6
+ indent = string.scan(/^[ \t]*(?=\S)/)
7
+ n = indent ? indent.size : 0
8
+ string.gsub(/^[ \t]{#{n}}/, "")
9
+ end
10
+ end
11
+
12
+ def gemfile
13
+ @gemfile ||= Gemnasium::Parser::Gemfile.new(@content)
14
+ end
15
+
16
+ def dependencies
17
+ @dependencies ||= gemfile.dependencies
18
+ end
19
+
20
+ def dependency
21
+ dependencies.size.should == 1
22
+ dependencies.first
23
+ end
24
+
25
+ def reset
26
+ @content = @gemfile = @dependencies = nil
27
+ end
28
+
29
+ it "parses double quotes" do
30
+ content(%(gem "rake", ">= 0.8.7"))
31
+ dependency.name.should == "rake"
32
+ dependency.requirement.as_list.should == [">= 0.8.7"]
33
+ end
34
+
35
+ it "parses single quotes" do
36
+ content(%(gem 'rake', '>= 0.8.7'))
37
+ dependency.name.should == "rake"
38
+ dependency.requirement.as_list.should == [">= 0.8.7"]
39
+ end
40
+
41
+ it "ignores mixed quotes" do
42
+ content(%(gem "rake', ">= 0.8.7"))
43
+ dependencies.size.should == 0
44
+ end
45
+
46
+ it "parses gems with a period in the name" do
47
+ content(%(gem "pygment.rb", ">= 0.8.7"))
48
+ dependency.name.should == "pygment.rb"
49
+ dependency.requirement.as_list.should == [">= 0.8.7"]
50
+ end
51
+
52
+ it "parses non-requirement gems" do
53
+ content(%(gem "rake"))
54
+ dependency.name.should == "rake"
55
+ dependency.requirement.as_list.should == [">= 0"]
56
+ end
57
+
58
+ it "parses multi-requirement gems" do
59
+ content(%(gem "rake", ">= 0.8.7", "<= 0.9.2"))
60
+ dependency.name.should == "rake"
61
+ dependency.requirement.as_list.should == ["<= 0.9.2", ">= 0.8.7"]
62
+ end
63
+
64
+ it "parses gems with options" do
65
+ content(%(gem "rake", ">= 0.8.7", :require => false))
66
+ dependency.name.should == "rake"
67
+ dependency.requirement.as_list.should == [">= 0.8.7"]
68
+ end
69
+
70
+ it "listens for gemspecs" do
71
+ content(%(gemspec))
72
+ gemfile.should be_gemspec
73
+ gemfile.gemspec.should == "*.gemspec"
74
+ reset
75
+ content(%(gem "rake"))
76
+ gemfile.should_not be_gemspec
77
+ gemfile.gemspec.should be_nil
78
+ end
79
+
80
+ it "parses gemspecs with a name option" do
81
+ content(%(gemspec :name => "gemnasium-parser"))
82
+ gemfile.gemspec.should == "gemnasium-parser.gemspec"
83
+ end
84
+
85
+ it "parses gemspecs with a path option" do
86
+ content(%(gemspec :path => "lib/gemnasium"))
87
+ gemfile.gemspec.should == "lib/gemnasium/*.gemspec"
88
+ end
89
+
90
+ it "parses gemspecs with name and path options" do
91
+ content(%(gemspec :name => "parser", :path => "lib/gemnasium"))
92
+ gemfile.gemspec.should == "lib/gemnasium/parser.gemspec"
93
+ end
94
+
95
+ it "parses gemspecs with parentheses" do
96
+ content(%(gemspec(:name => "gemnasium-parser")))
97
+ gemfile.should be_gemspec
98
+ end
99
+
100
+ it "parses gems of a type" do
101
+ content(%(gem "rake"))
102
+ dependency.type.should == :runtime
103
+ reset
104
+ content(%(gem "rake", :type => :development))
105
+ dependency.type.should == :development
106
+ end
107
+
108
+ it "parses gems of a group" do
109
+ content(%(gem "rake"))
110
+ dependency.groups.should == [:default]
111
+ reset
112
+ content(%(gem "rake", :group => :development))
113
+ dependency.groups.should == [:development]
114
+ end
115
+
116
+ it "parses gems of multiple groups" do
117
+ content(%(gem "rake", :group => [:development, :test]))
118
+ dependency.groups.should == [:development, :test]
119
+ end
120
+
121
+ it "recognizes :groups" do
122
+ content(%(gem "rake", :groups => [:development, :test]))
123
+ dependency.groups.should == [:development, :test]
124
+ end
125
+
126
+ it "parses gems in a group" do
127
+ content(<<-EOF)
128
+ gem "rake"
129
+ group :production do
130
+ gem "pg"
131
+ end
132
+ group :development do
133
+ gem "sqlite3"
134
+ end
135
+ EOF
136
+ dependencies[0].groups.should == [:default]
137
+ dependencies[1].groups.should == [:production]
138
+ dependencies[2].groups.should == [:development]
139
+ end
140
+
141
+ it "parses gems in a group with parentheses" do
142
+ content(<<-EOF)
143
+ group(:production) do
144
+ gem "pg"
145
+ end
146
+ EOF
147
+ dependency.groups.should == [:production]
148
+ end
149
+
150
+ it "parses gems in multiple groups" do
151
+ content(<<-EOF)
152
+ group :development, :test do
153
+ gem "sqlite3"
154
+ end
155
+ EOF
156
+ dependency.groups.should == [:development, :test]
157
+ end
158
+
159
+ it "parses multiple gems in a group" do
160
+ content(<<-EOF)
161
+ group :development do
162
+ gem "rake"
163
+ gem "sqlite3"
164
+ end
165
+ EOF
166
+ dependencies[0].groups.should == [:development]
167
+ dependencies[1].groups.should == [:development]
168
+ end
169
+
170
+ it "parses multiple gems in multiple groups" do
171
+ content(<<-EOF)
172
+ group :development, :test do
173
+ gem "rake"
174
+ gem "sqlite3"
175
+ end
176
+ EOF
177
+ dependencies[0].groups.should == [:development, :test]
178
+ dependencies[1].groups.should == [:development, :test]
179
+ end
180
+
181
+ it "ignores h4x" do
182
+ path = File.expand_path("../h4x.txt", __FILE__)
183
+ content(%(gem "h4x", :require => "\#{`touch #{path}`}"))
184
+ dependencies.size.should == 0
185
+ begin
186
+ File.should_not exist(path)
187
+ ensure
188
+ FileUtils.rm_f(path)
189
+ end
190
+ end
191
+
192
+ it "ignores gems with a git option" do
193
+ content(%(gem "rails", :git => "https://github.com/rails/rails.git"))
194
+ dependencies.size.should == 1
195
+ end
196
+
197
+ it "ignores gems with a github option" do
198
+ content(%(gem "rails", :github => "rails/rails"))
199
+ dependencies.size.should == 1
200
+ end
201
+
202
+ it "ignores gems with a path option" do
203
+ content(%(gem "rails", :path => "vendor/rails"))
204
+ dependencies.size.should == 1
205
+ end
206
+
207
+ it "ignores gems in a git block" do
208
+ content(<<-EOF)
209
+ git "https://github.com/rails/rails.git" do
210
+ gem "rails"
211
+ end
212
+ EOF
213
+ dependencies.size.should == 1
214
+ end
215
+
216
+ it "ignores gems in a git block with parentheses" do
217
+ content(<<-EOF)
218
+ git("https://github.com/rails/rails.git") do
219
+ gem "rails"
220
+ end
221
+ EOF
222
+ dependencies.size.should == 1
223
+ end
224
+
225
+ it "ignores gems in a path block" do
226
+ content(<<-EOF)
227
+ path "vendor/rails" do
228
+ gem "rails"
229
+ end
230
+ EOF
231
+ dependencies.size.should == 1
232
+ end
233
+
234
+ it "ignores gems in a path block with parentheses" do
235
+ content(<<-EOF)
236
+ path("vendor/rails") do
237
+ gem "rails"
238
+ end
239
+ EOF
240
+ dependencies.size.should == 1
241
+ end
242
+
243
+ it "records dependency line numbers" do
244
+ content(<<-EOF)
245
+ gem "rake"
246
+
247
+ gem "rails"
248
+ EOF
249
+ dependencies[0].instance_variable_get(:@line).should == 1
250
+ dependencies[1].instance_variable_get(:@line).should == 3
251
+ end
252
+
253
+ it "maps groups to types" do
254
+ content(<<-EOF)
255
+ gem "rake"
256
+ gem "pg", :group => :production
257
+ gem "mysql2", :group => :staging
258
+ gem "sqlite3", :group => :development
259
+ EOF
260
+ dependencies[0].type.should == :runtime
261
+ dependencies[1].type.should == :runtime
262
+ dependencies[2].type.should == :development
263
+ dependencies[3].type.should == :development
264
+ reset
265
+ Gemnasium::Parser.runtime_groups << :staging
266
+ content(<<-EOF)
267
+ gem "rake"
268
+ gem "pg", :group => :production
269
+ gem "mysql2", :group => :staging
270
+ gem "sqlite3", :group => :development
271
+ EOF
272
+ dependencies[0].type.should == :runtime
273
+ dependencies[1].type.should == :runtime
274
+ dependencies[2].type.should == :runtime
275
+ dependencies[3].type.should == :development
276
+ end
277
+
278
+ it "parses parentheses" do
279
+ content(%(gem("rake", ">= 0.8.7")))
280
+ dependency.name.should == "rake"
281
+ dependency.requirement.as_list.should == [">= 0.8.7"]
282
+ end
283
+
284
+ it "parses gems followed by inline comments" do
285
+ content(%(gem "rake", ">= 0.8.7" # Comment))
286
+ dependency.name.should == "rake"
287
+ dependency.requirement.as_list.should == [">= 0.8.7"]
288
+ end
289
+
290
+ it "parses oddly quoted gems" do
291
+ content(%(gem %q<rake>))
292
+ dependency.name.should == "rake"
293
+ end
294
+ end
@@ -0,0 +1,159 @@
1
+ require "spec_helper"
2
+
3
+ describe Gemnasium::Parser::Gemspec do
4
+ def content(string)
5
+ @content ||= begin
6
+ indent = string.scan(/^[ \t]*(?=\S)/)
7
+ n = indent ? indent.size : 0
8
+ string.gsub(/^[ \t]{#{n}}/, "")
9
+ end
10
+ end
11
+
12
+ def gemspec
13
+ @gemspec ||= Gemnasium::Parser::Gemspec.new(@content)
14
+ end
15
+
16
+ def dependencies
17
+ @dependencies ||= gemspec.dependencies
18
+ end
19
+
20
+ def dependency
21
+ dependencies.size.should == 1
22
+ dependencies.first
23
+ end
24
+
25
+ def reset
26
+ @content = @gemspec = @dependencies = nil
27
+ end
28
+
29
+ it "parses double quotes" do
30
+ content(<<-EOF)
31
+ Gem::Specification.new do |gem|
32
+ gem.add_dependency "rake", ">= 0.8.7"
33
+ end
34
+ EOF
35
+ dependency.name.should == "rake"
36
+ dependency.requirement.as_list.should == [">= 0.8.7"]
37
+ end
38
+
39
+ it "parses single quotes" do
40
+ content(<<-EOF)
41
+ Gem::Specification.new do |gem|
42
+ gem.add_dependency 'rake', '>= 0.8.7'
43
+ end
44
+ EOF
45
+ dependency.name.should == "rake"
46
+ dependency.requirement.as_list.should == [">= 0.8.7"]
47
+ end
48
+
49
+ it "ignores mixed quotes" do
50
+ content(<<-EOF)
51
+ Gem::Specification.new do |gem|
52
+ gem.add_dependency "rake', ">= 0.8.7"
53
+ end
54
+ EOF
55
+ dependencies.size.should == 0
56
+ end
57
+
58
+ it "parses gems with a period in the name" do
59
+ content(<<-EOF)
60
+ Gem::Specification.new do |gem|
61
+ gem.add_dependency "pygment.rb", ">= 0.8.7"
62
+ end
63
+ EOF
64
+ dependency.name.should == "pygment.rb"
65
+ dependency.requirement.as_list.should == [">= 0.8.7"]
66
+ end
67
+
68
+ it "parses non-requirement gems" do
69
+ content(<<-EOF)
70
+ Gem::Specification.new do |gem|
71
+ gem.add_dependency "rake"
72
+ end
73
+ EOF
74
+ dependency.name.should == "rake"
75
+ dependency.requirement.as_list.should == [">= 0"]
76
+ end
77
+
78
+ it "parses multi-requirement gems" do
79
+ content(<<-EOF)
80
+ Gem::Specification.new do |gem|
81
+ gem.add_dependency "rake", ">= 0.8.7", "<= 0.9.2"
82
+ end
83
+ EOF
84
+ dependency.name.should == "rake"
85
+ dependency.requirement.as_list.should == ["<= 0.9.2", ">= 0.8.7"]
86
+ end
87
+
88
+ it "parses single-element array requirement gems" do
89
+ content(<<-EOF)
90
+ Gem::Specification.new do |gem|
91
+ gem.add_dependency "rake", [">= 0.8.7"]
92
+ end
93
+ EOF
94
+ dependency.name.should == "rake"
95
+ dependency.requirement.as_list.should == [">= 0.8.7"]
96
+ end
97
+
98
+ it "parses multi-element array requirement gems" do
99
+ content(<<-EOF)
100
+ Gem::Specification.new do |gem|
101
+ gem.add_dependency "rake", [">= 0.8.7", "<= 0.9.2"]
102
+ end
103
+ EOF
104
+ dependency.name.should == "rake"
105
+ dependency.requirement.as_list.should == ["<= 0.9.2", ">= 0.8.7"]
106
+ end
107
+
108
+ it "parses runtime gems" do
109
+ content(<<-EOF)
110
+ Gem::Specification.new do |gem|
111
+ gem.add_dependency "rake"
112
+ gem.add_runtime_dependency "rails"
113
+ end
114
+ EOF
115
+ dependencies[0].type.should == :runtime
116
+ dependencies[1].type.should == :runtime
117
+ end
118
+
119
+ it "parses dependency gems" do
120
+ content(<<-EOF)
121
+ Gem::Specification.new do |gem|
122
+ gem.add_development_dependency "rake"
123
+ end
124
+ EOF
125
+ dependency.type.should == :development
126
+ end
127
+
128
+ it "records dependency line numbers" do
129
+ content(<<-EOF)
130
+ Gem::Specification.new do |gem|
131
+ gem.add_dependency "rake"
132
+
133
+ gem.add_dependency "rails"
134
+ end
135
+ EOF
136
+ dependencies[0].instance_variable_get(:@line).should == 2
137
+ dependencies[1].instance_variable_get(:@line).should == 4
138
+ end
139
+
140
+ it "parses parentheses" do
141
+ content(<<-EOF)
142
+ Gem::Specification.new do |gem|
143
+ gem.add_dependency("rake", ">= 0.8.7")
144
+ end
145
+ EOF
146
+ dependency.name.should == "rake"
147
+ dependency.requirement.as_list.should == [">= 0.8.7"]
148
+ end
149
+
150
+ it "parses gems followed by inline comments" do
151
+ content(<<-EOF)
152
+ Gem::Specification.new do |gem|
153
+ gem.add_dependency "rake", ">= 0.8.7" # Comment
154
+ end
155
+ EOF
156
+ dependency.name.should == "rake"
157
+ dependency.requirement.as_list.should == [">= 0.8.7"]
158
+ end
159
+ end