ruber 0.0.9 → 0.0.10
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +42 -1
- data/lib/ruber/application/application.rb +25 -5
- data/lib/ruber/application/plugin.yaml +2 -10
- data/lib/ruber/component_manager.rb +2 -2
- data/lib/ruber/document_project.rb +5 -3
- data/lib/ruber/editor/document.rb +5 -4
- data/lib/ruber/editor/ktexteditor_wrapper.rb +1 -1
- data/lib/ruber/exception_widgets.rb +1 -1
- data/lib/ruber/main_window/main_window.rb +4 -3
- data/lib/ruber/main_window/main_window_actions.rb +2 -2
- data/lib/ruber/main_window/main_window_internal.rb +1 -1
- data/lib/ruber/output_widget.rb +17 -5
- data/lib/ruber/project.rb +34 -3
- data/lib/ruber/project_dir_scanner.rb +171 -0
- data/lib/ruber/settings_container.rb +7 -7
- data/lib/ruber/settings_dialog.rb +24 -24
- data/lib/ruber/version.rb +1 -1
- data/lib/ruber/world/environment.rb +1 -0
- data/lib/ruber/world/plugin.yaml +7 -2
- data/lib/ruber/{application → world}/project_files_widget.rb +0 -0
- data/lib/ruber/{application → world}/ui/project_files_rule_chooser_widget.rb +2 -2
- data/lib/ruber/{application → world}/ui/project_files_rule_chooser_widget.ui +0 -0
- data/lib/ruber/{application → world}/ui/project_files_widget.rb +2 -2
- data/lib/ruber/{application → world}/ui/project_files_widget.ui +0 -0
- data/plugins/auto_end/auto_end.rb +21 -18
- data/plugins/autosave/autosave.rb +1 -1
- data/plugins/find_in_files/find_in_files.rb +1 -1
- data/plugins/irb/irb.png +0 -0
- data/plugins/irb/irb.rb +142 -0
- data/plugins/irb/irb.svg +240 -0
- data/plugins/irb/irb_controller.rb +541 -0
- data/plugins/irb/irbrc.rb +21 -0
- data/plugins/irb/plugin.yaml +19 -0
- data/plugins/irb/ui/irb_config_widget.rb +151 -0
- data/plugins/irb/ui/irb_config_widget.ui +123 -0
- data/plugins/irb/ui/irb_tool_widget.rb +97 -0
- data/plugins/irb/ui/irb_tool_widget.ui +86 -0
- data/plugins/project_browser/project_browser.rb +1 -1
- data/plugins/rspec/plugin.yaml +6 -3
- data/plugins/rspec/rspec.rb +172 -473
- data/plugins/rspec/tool_widget.rb +462 -0
- data/plugins/rspec/ui/rspec_project_widget.rb +58 -38
- data/plugins/rspec/ui/rspec_project_widget.ui +68 -64
- data/plugins/ruberri/class_formatter.rb +126 -0
- data/plugins/ruberri/method_formatter.rb +90 -0
- data/plugins/ruberri/plugin.yaml +13 -0
- data/plugins/ruberri/ruberri.rb +226 -0
- data/plugins/ruberri/search.rb +111 -0
- data/plugins/ruberri/ui/tool_widget.rb +73 -0
- data/plugins/ruberri/ui/tool_widget.ui +49 -0
- data/plugins/ruby_runner/ruby_runner.rb +2 -2
- data/plugins/ruby_syntax_checker/plugin.yaml +11 -0
- data/plugins/ruby_syntax_checker/ruby_syntax_checker.rb +147 -0
- data/plugins/syntax_checker/plugin.yaml +10 -6
- data/plugins/syntax_checker/syntax_checker.rb +216 -520
- data/plugins/syntax_checker/ui/config_widget.rb +61 -0
- data/plugins/syntax_checker/ui/config_widget.ui +44 -0
- data/plugins/yaml_syntax_checker/plugin.yaml +11 -0
- data/plugins/yaml_syntax_checker/yaml_syntax_checker.rb +62 -0
- data/ruber.desktop +0 -0
- data/spec/auto_end_spec.rb +224 -186
- data/spec/document_project_spec.rb +9 -1
- data/spec/document_spec.rb +9 -0
- data/spec/environment_spec.rb +12 -0
- data/spec/output_widget_spec.rb +69 -2
- data/spec/project_dir_scanner_spec.rb +195 -0
- data/spec/project_spec.rb +43 -73
- data/spec/ruby_syntax_checker_spec.rb +361 -0
- data/spec/syntax_checker_spec.rb +1132 -0
- data/spec/yaml_syntax_checker_spec.rb +130 -0
- metadata +232 -225
- data/lib/ruber/application/project_files_list.rb +0 -320
- data/spec/project_files_list_spec.rb +0 -411
@@ -1,320 +0,0 @@
|
|
1
|
-
=begin
|
2
|
-
Copyright (C) 2010 by Stefano Crocco
|
3
|
-
stefano.crocco@alice.it
|
4
|
-
|
5
|
-
This program is free software; you can redistribute it andor modify
|
6
|
-
it under the terms of the GNU General Public License as published by
|
7
|
-
the Free Software Foundation; either version 2 of the License, or
|
8
|
-
(at your option) any later version.
|
9
|
-
|
10
|
-
This program is distributed in the hope that it will be useful,
|
11
|
-
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
-
GNU General Public License for more details.
|
14
|
-
|
15
|
-
You should have received a copy of the GNU General Public License
|
16
|
-
along with this program; if not, write to the
|
17
|
-
Free Software Foundation, Inc.,
|
18
|
-
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
19
|
-
=end
|
20
|
-
|
21
|
-
require 'thread'
|
22
|
-
require 'facets/kernel/deep_copy'
|
23
|
-
require 'find'
|
24
|
-
|
25
|
-
require 'ruber/project'
|
26
|
-
|
27
|
-
module Ruber
|
28
|
-
|
29
|
-
=begin rdoc
|
30
|
-
Project extension to access the name of the files belonging to the project.
|
31
|
-
|
32
|
-
The file belonging to the projects are determined using the contents of the @general/project_files@
|
33
|
-
project option. This option is a hash which contains rules (in the form of hashes)
|
34
|
-
telling which files are part of the project and which aren't.
|
35
|
-
|
36
|
-
Files are kept up to date, both regarding the contents of the filesystem (using a
|
37
|
-
KDE::DirWatch) and the rules specified in the project.
|
38
|
-
|
39
|
-
To avoid needlessly freezing the application in case projects with a large number of files,
|
40
|
-
this class only scans the project directory when a list of project files is actually
|
41
|
-
requested, that is when one of the methods {#each}, {#abs}, {#rel} and {#project_files}
|
42
|
-
is called. Even in that case, the project directory is only scanned if a file has
|
43
|
-
been added or removed since the last scan, or if the rules have changed since then.
|
44
|
-
A scan can be forced by using the {#update} method, but you usually don't need this.
|
45
|
-
|
46
|
-
h3. Rules
|
47
|
-
|
48
|
-
The @general/project_files@ setting is a hash containing the rules to use to decide
|
49
|
-
whether a given file belongs to the project or not. There are two groups of rules:
|
50
|
-
inclusive rules and exclusive rules. Inclusive rules specify files which belong
|
51
|
-
to the project, while exclusive rules specify files which do not belong to the
|
52
|
-
project. Exclusive rules have precedence on inclusive rules, meaning that if a
|
53
|
-
file matches both an inclusive and an exclusive rule, it's excluded from the project.
|
54
|
-
|
55
|
-
There are three kinds of rules:
|
56
|
-
|
57
|
-
|
58
|
-
Project extension which scans the project directory and finds out which files belong
|
59
|
-
to the project and which don't (according to rules specified by the user in the
|
60
|
-
project options), returning an array of the former.
|
61
|
-
|
62
|
-
It also watches the project directory to update the list of project files when a
|
63
|
-
file in the project directory is added or removed.
|
64
|
-
|
65
|
-
This class provides an {#each} method, which yields all the project files to the
|
66
|
-
block or, if called without a block, returns an <tt>Enumerable::Enumerator</tt>
|
67
|
-
which does the same.
|
68
|
-
|
69
|
-
<b>Note:</b> the list of project files is created lazily, only when a method
|
70
|
-
explicitly needs it and a file or directory (or the rules) have changed since
|
71
|
-
the last time it was generated. A <tt>KDE::DirWatch</tt> object is used to find
|
72
|
-
out when a file or directory changes. Also, after a file has changed, the watcher
|
73
|
-
is stopped until the list is updated again (a single change is enough to rebuild
|
74
|
-
the whole list, so there's no point in keeping watching).
|
75
|
-
|
76
|
-
The methods which can cause the list to be rebuild are: +each+, +abs+, +rel+ and
|
77
|
-
<tt>project_files</tt>.
|
78
|
-
|
79
|
-
===Rules
|
80
|
-
To decide whether a file belongs to the project or not, ProjectFilesList uses
|
81
|
-
the general/project_files project option. It is a hash made of three keys, each
|
82
|
-
specifying a rule telling whether a file is part of the project or not. In application
|
83
|
-
order, they are
|
84
|
-
<tt>extensions</tt>::
|
85
|
-
an array of shell globs. Any file matching one of them (according to <tt>File.fnmatch</tt>)
|
86
|
-
will be considered a project file, unless another rule says otherwise
|
87
|
-
<tt>include</tt>::
|
88
|
-
an array of strings and/or regexps corresponding to files which belong to the
|
89
|
-
project. Each string entry is the name (relative to the project directory) of
|
90
|
-
a file which belongs to the project. Each regexp is a pattern which should be
|
91
|
-
tested against all the names (still relative to the project directory) of the
|
92
|
-
files in the project directory (and its subdirectories). Each matching file will
|
93
|
-
be a project file (unless another rule says otherwise).
|
94
|
-
<tt>exclude</tt>::
|
95
|
-
as the <tt>include</tt> entry, but the matching files will *not* be project
|
96
|
-
files. This entry has the precedence with respect to the other two. This means
|
97
|
-
that if a file is a project file according to one of them but also matches a
|
98
|
-
rule here, it <i>won't</i> be considered a project file.
|
99
|
-
=end
|
100
|
-
class ProjectFilesList < Qt::Object
|
101
|
-
|
102
|
-
include Enumerable
|
103
|
-
|
104
|
-
include Extension
|
105
|
-
|
106
|
-
=begin rdoc
|
107
|
-
Creates a new ProjectFilesList for the Project _prj_.
|
108
|
-
|
109
|
-
The new object will read the <tt>general/project_files</tt> option from the project
|
110
|
-
and immediately scan the project directory to find the all the project files.
|
111
|
-
Besides, it will start monitoring the directory for changes, so as to be
|
112
|
-
able to update the list of project files when a new file is created or a file
|
113
|
-
is deleted.
|
114
|
-
=end
|
115
|
-
def initialize prj
|
116
|
-
super
|
117
|
-
@lock = Mutex.new
|
118
|
-
@project = prj
|
119
|
-
@project_files = nil
|
120
|
-
@watcher = KDE::DirWatch.new self
|
121
|
-
@watcher.add_dir @project.project_dir, KDE::DirWatch::WatchSubDirs
|
122
|
-
@up_to_date = false
|
123
|
-
make_rules
|
124
|
-
@project_files = []
|
125
|
-
@watcher.connect(SIGNAL('dirty(QString)')) do
|
126
|
-
@up_to_date = false
|
127
|
-
@watcher.stop_scan
|
128
|
-
end
|
129
|
-
@project.connect(SIGNAL('option_changed(QString, QString)')) do |g, n|
|
130
|
-
if g == 'general' and n == 'project_files'
|
131
|
-
if @project[:general, :project_files] != @rules
|
132
|
-
@up_to_date = false
|
133
|
-
make_rules
|
134
|
-
scan_project
|
135
|
-
end
|
136
|
-
end
|
137
|
-
end
|
138
|
-
@watcher.start_scan false
|
139
|
-
end
|
140
|
-
|
141
|
-
=begin rdoc
|
142
|
-
Returns an array with the name of the files in the project (in arbitrary order).
|
143
|
-
If _abs_ is *false*, the file names will be relative to the project directory;
|
144
|
-
if it is *true* they'll be absolute. It is the same as calling <tt>list.abs.to_a</tt>
|
145
|
-
or <tt>list.rel.to_a</tt>
|
146
|
-
|
147
|
-
<b>Note:</b> if the list isn't up to date, the project will be re-scanned
|
148
|
-
=end
|
149
|
-
def project_files abs = true
|
150
|
-
refresh unless @up_to_date
|
151
|
-
if abs
|
152
|
-
dir = @project.project_dir
|
153
|
-
@project_files.map{|f| File.join dir, f}
|
154
|
-
else @project_files.deep_copy
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
=begin rdoc
|
159
|
-
If called with a block, calls the block yielding the names of the files in the
|
160
|
-
project. If _abs_ is true, absolute file names will be used, otherwise the file
|
161
|
-
names will be relative to the project directory.
|
162
|
-
|
163
|
-
If called without a block, returns an <tt>Enumerable::Enumerator</tt> which does
|
164
|
-
the same as above.
|
165
|
-
|
166
|
-
<b>Note:</b> when called with a block and the list isn't up to date,
|
167
|
-
the project will be re-scanned
|
168
|
-
=end
|
169
|
-
def each abs = true
|
170
|
-
if block_given?
|
171
|
-
refresh unless @up_to_date
|
172
|
-
dir = @project.project_dir
|
173
|
-
@project_files.each do |f|
|
174
|
-
yield abs ? File.join( dir, f) : f
|
175
|
-
end
|
176
|
-
self
|
177
|
-
else
|
178
|
-
return self.to_enum(:each, abs)
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
|
-
=begin rdoc
|
183
|
-
Returns an enumerator as that yields the names of the project files relative to
|
184
|
-
the project directory. It's just a shortcut for <tt>each(false)</tt>.
|
185
|
-
|
186
|
-
<b>Note:</b> if the list isn't up to date, the project will be re-scanned when
|
187
|
-
any enumerable method returned by the object is called
|
188
|
-
=end
|
189
|
-
def rel
|
190
|
-
self.each false
|
191
|
-
end
|
192
|
-
alias_method :relative_paths, :rel
|
193
|
-
|
194
|
-
=begin rdoc
|
195
|
-
Returns an enumerator as that yields the absolute names of the project files.
|
196
|
-
It's just a shortcut for <tt>each(true)</tt>.
|
197
|
-
|
198
|
-
<b>Note:</b> if the list isn't up to date, the project will be re-scanned when
|
199
|
-
any enumerable method returned by the object is called
|
200
|
-
=end
|
201
|
-
def abs
|
202
|
-
self.each true
|
203
|
-
end
|
204
|
-
alias_method :absolute_paths, :abs
|
205
|
-
|
206
|
-
=begin rdoc
|
207
|
-
Updates the list, so that it reflects the current status of the project directory.
|
208
|
-
|
209
|
-
Usually you don't need to call this method, as it's automatically called as needed.
|
210
|
-
=end
|
211
|
-
def refresh
|
212
|
-
scan_project
|
213
|
-
@up_to_date = true
|
214
|
-
@watcher.start_scan
|
215
|
-
end
|
216
|
-
|
217
|
-
=begin rdoc
|
218
|
-
Tells whether the list is up to date or needs to be rebuilt.
|
219
|
-
|
220
|
-
Usually you don't need this method, as the list is automatically updated when needed.
|
221
|
-
=end
|
222
|
-
def up_to_date?
|
223
|
-
@up_to_date
|
224
|
-
end
|
225
|
-
|
226
|
-
=begin rdoc
|
227
|
-
Tells whether the given file belongs to the project or not. If _file_ is a relative
|
228
|
-
path, it is considered relative to the project directory.
|
229
|
-
|
230
|
-
Returns *true* if _file_ belongs to the project and *false* otherwise. As this method
|
231
|
-
doesn't access the filesystem, the behaviour in the case _file_ is a directory will
|
232
|
-
be undefined. If _file_ ends with a slash (which makes it clear it represents a
|
233
|
-
directory) then *nil* will be returned
|
234
|
-
<b>Note:</b> this method doesn't use the file list to tell whether the file is in
|
235
|
-
the project. Rather, it compares the file name with the include and exclude rules
|
236
|
-
and the extensions.
|
237
|
-
=end
|
238
|
-
def file_in_project? file
|
239
|
-
if file.match %r{^([\w+-.]+)://(.+)}
|
240
|
-
if $1 != 'file' then return false
|
241
|
-
else
|
242
|
-
file = $2
|
243
|
-
end
|
244
|
-
end
|
245
|
-
file = file.sub %r[^#{Regexp.quote(@project.project_directory)}/], ''
|
246
|
-
return false if file.start_with? '/'
|
247
|
-
return nil if file.end_with? '/'
|
248
|
-
# I don't know why I added the following line
|
249
|
-
# file = File.basename(file)
|
250
|
-
|
251
|
-
return false if @exclude_files.include? file
|
252
|
-
return true if @include_files.any?{|f| f == file}
|
253
|
-
|
254
|
-
if @exclude_regexp.match(file) then false
|
255
|
-
elsif @include_regexp.match file then true
|
256
|
-
elsif @extensions.any?{|e| File.fnmatch?(e, file, File::FNM_DOTMATCH)} then true
|
257
|
-
else false
|
258
|
-
end
|
259
|
-
end
|
260
|
-
|
261
|
-
private
|
262
|
-
|
263
|
-
=begin rdoc
|
264
|
-
Applies the rules stored in the <tt>general/project_files</tt> project option
|
265
|
-
to all the files in the project directory and fills the internal cache with the
|
266
|
-
project files.
|
267
|
-
|
268
|
-
---
|
269
|
-
The <tt>@lock</tt> instance variable is used to (hopefully) avoid issues with
|
270
|
-
two threads calling this method together, since Dir.chdir doesn't nest inside
|
271
|
-
threads. This created problems with syntax checker, for example.
|
272
|
-
=end
|
273
|
-
def scan_project
|
274
|
-
@lock.synchronize do
|
275
|
-
Dir.chdir(@project.project_dir) do
|
276
|
-
res = @include_files.select{|f| File.exist?(f) and File.file?(f)}
|
277
|
-
# remove the leading ./ from the names of the files
|
278
|
-
res.map!{|f| f.sub(%r{^./}, '')}
|
279
|
-
Find.find('.') do |f|
|
280
|
-
# let's skip the current directory, least it somehow matches one of
|
281
|
-
# the exclude rules
|
282
|
-
next if f == '.'
|
283
|
-
if File.directory?(f)
|
284
|
-
f = File.join(f, '')
|
285
|
-
Find.prune if f.match @exclude_regexp
|
286
|
-
else
|
287
|
-
# We remove the leading ./
|
288
|
-
f = f[2..-1]
|
289
|
-
next if f.match @exclude_regexp or @exclude_files.include?(f)
|
290
|
-
res << f if @extensions.any?{|ext| File.fnmatch?(ext, f, File::FNM_DOTMATCH)} or
|
291
|
-
f.match(@include_regexp)
|
292
|
-
end
|
293
|
-
end
|
294
|
-
res.uniq!
|
295
|
-
@project_files = res
|
296
|
-
end
|
297
|
-
end
|
298
|
-
end
|
299
|
-
|
300
|
-
=begin rdoc
|
301
|
-
Creates an internal version of the rules from the values in the
|
302
|
-
<tt>general/project_files</tt> project option
|
303
|
-
=end
|
304
|
-
def make_rules
|
305
|
-
rules = @project[:general, :project_files]
|
306
|
-
@include_regexp = Regexp.union(*(rules[:include].select{|r| r.is_a?(Regexp)}))
|
307
|
-
@exclude_regexp = Regexp.union(*(rules[:exclude].select{|r| r.is_a?(Regexp)}))
|
308
|
-
@exclude_files = rules[:exclude].select{|rule| rule.is_a? String}.map{|f| f.sub(%r{^\./}, '')}
|
309
|
-
@include_files = rules[:include].select{|rule| rule.is_a? String}.map{|f| f.sub(%r{^\./}, '')}
|
310
|
-
@include_files-= @exclude_files
|
311
|
-
@extensions = rules[:extensions]
|
312
|
-
@rules = YAML.load(YAML.dump rules)
|
313
|
-
# TODO Uncomment the following line and remove the previous when found out why Marshal
|
314
|
-
# fails
|
315
|
-
# @rules = rules.deep_copy
|
316
|
-
end
|
317
|
-
|
318
|
-
end
|
319
|
-
|
320
|
-
end
|
@@ -1,411 +0,0 @@
|
|
1
|
-
require 'spec/common'
|
2
|
-
|
3
|
-
require 'tempfile'
|
4
|
-
require 'fileutils'
|
5
|
-
require 'flexmock'
|
6
|
-
require 'forwardable'
|
7
|
-
|
8
|
-
require 'ruber/projects/project_files_list'
|
9
|
-
require 'ruber/project'
|
10
|
-
|
11
|
-
|
12
|
-
class SimpleProject < Qt::Object
|
13
|
-
signals 'option_changed(QString, QString)'
|
14
|
-
end
|
15
|
-
|
16
|
-
describe 'Ruber::ProjectFilesList' do
|
17
|
-
|
18
|
-
before do
|
19
|
-
@app = Qt::Object.new
|
20
|
-
@comp = Qt::Object.new do
|
21
|
-
class << self
|
22
|
-
extend Forwardable
|
23
|
-
def_delegators :@data, :[], :<<
|
24
|
-
def_delegator :@data, :each, :each_component
|
25
|
-
end
|
26
|
-
@data = []
|
27
|
-
end
|
28
|
-
@projects = Qt::Object.new
|
29
|
-
flexmock(Ruber).should_receive(:[]).with(:app).and_return(@app).by_default
|
30
|
-
flexmock(Ruber).should_receive(:[]).with(:components).and_return(@comp).by_default
|
31
|
-
flexmock(Ruber).should_receive(:[]).with(:projects).and_return(@projects).by_default
|
32
|
-
dir = File.dirname __FILE__
|
33
|
-
@prj = Ruber::Project.new File.join(dir, 'test.ruprj'), 'Test'
|
34
|
-
@prj.add_option(OS.new({:group => :general, :name => :project_files, :default => {:include => [], :exclude => [], :extensions => []} }))
|
35
|
-
@l = Ruber::ProjectFilesList.new @prj
|
36
|
-
@prj.add_extension :file_lister, @l
|
37
|
-
end
|
38
|
-
|
39
|
-
it 'should be an Enumerable' do
|
40
|
-
Ruber::ProjectFilesList.ancestors.should include(Enumerable)
|
41
|
-
end
|
42
|
-
|
43
|
-
it 'should not be up to date when created' do
|
44
|
-
@l.should_not be_up_to_date
|
45
|
-
end
|
46
|
-
|
47
|
-
it 'should not attempt to scan the project when created' do
|
48
|
-
flexmock(Find).should_receive(:find).never
|
49
|
-
l = Ruber::ProjectFilesList.new @prj
|
50
|
-
end
|
51
|
-
|
52
|
-
it 'should mark the list as not up to date when the project_files option changes' do
|
53
|
-
@prj.add_option(OS.new({:group => :general, :name => :xyz, :default => 3}))
|
54
|
-
@prj[:general, :project_files][:extensions] = ['*.rb']
|
55
|
-
@l.instance_variable_set :@up_to_date, true
|
56
|
-
@prj.instance_eval{emit option_changed('general', 'xyz')}
|
57
|
-
@prj[:general, :project_files] = {:include => [], :exclude => [], :extensions => %w[*.rb *.ui]}
|
58
|
-
@l.should_not be_up_to_date
|
59
|
-
end
|
60
|
-
|
61
|
-
describe ', when a file or directory changes' do
|
62
|
-
|
63
|
-
before do
|
64
|
-
@files = YAML.load('[f1.rb, f1.yaml, README, COPYING, [d2, f21.rb, f22.rb, f21.yaml, f22.yaml, CHANGELOG], [d3, f31.rb, f32.rb]]')
|
65
|
-
@dir = make_dir_tree @files
|
66
|
-
@prj = Ruber::Project.new File.join(@dir, 'test.ruprj'), 'Test'
|
67
|
-
@prj.add_option(OS.new({:group => :general, :name => :project_files, :default => {:include => [], :exclude => [], :extensions => []} }))
|
68
|
-
@list = Ruber::ProjectFilesList.new @prj
|
69
|
-
@prj.add_extension :file_lister, @list
|
70
|
-
end
|
71
|
-
|
72
|
-
it 'should mark itself as not up to date' do
|
73
|
-
@list.instance_variable_set :@up_to_date, true
|
74
|
-
w = @list.instance_variable_get :@watcher
|
75
|
-
dir = @prj.project_directory
|
76
|
-
w.instance_eval{emit dirty(dir)}
|
77
|
-
@list.instance_variable_get(:@up_to_date).should be_false
|
78
|
-
end
|
79
|
-
|
80
|
-
it 'should stop the watcher' do
|
81
|
-
w = @list.instance_variable_get :@watcher
|
82
|
-
flexmock(w).should_receive(:stop_scan).once
|
83
|
-
dir = @prj.project_directory
|
84
|
-
w.instance_eval{emit dirty(dir)}
|
85
|
-
end
|
86
|
-
|
87
|
-
end
|
88
|
-
|
89
|
-
describe Ruber::ProjectFilesList, '#refresh' do
|
90
|
-
|
91
|
-
before do
|
92
|
-
dir = File.dirname __FILE__
|
93
|
-
@prj = Ruber::Project.new File.join(dir, 'test.ruprj'), 'Test'
|
94
|
-
@prj.add_option(OS.new({:group => :general, :name => :project_files, :default => {:include => [], :exclude => [], :extensions => []} }))
|
95
|
-
@list = Ruber::ProjectFilesList.new @prj
|
96
|
-
@prj.add_extension :file_lister, @list
|
97
|
-
end
|
98
|
-
|
99
|
-
it 'should call the scan_project method' do
|
100
|
-
flexmock(@list).should_receive(:scan_project).once
|
101
|
-
@list.refresh
|
102
|
-
end
|
103
|
-
|
104
|
-
it 'should set the file list as up to date' do
|
105
|
-
flexmock(@list).should_receive(:scan_project)
|
106
|
-
@list.refresh
|
107
|
-
@list.should be_up_to_date
|
108
|
-
end
|
109
|
-
|
110
|
-
it 'should restart the watcher' do
|
111
|
-
flexmock(@list).should_receive(:scan_project)
|
112
|
-
w = @list.instance_variable_get(:@watcher)
|
113
|
-
flexmock(w).should_receive(:start_scan).once
|
114
|
-
@list.refresh
|
115
|
-
end
|
116
|
-
|
117
|
-
end
|
118
|
-
|
119
|
-
describe 'Ruber::ProjectFilesList#project_files' do
|
120
|
-
|
121
|
-
before do
|
122
|
-
@files = YAML.load('[f1.rb, f1.yaml, README, COPYING, [d2, f21.rb, f22.rb, f21.yaml, f22.yaml, CHANGELOG], [d3, f31.rb, f32.rb]]')
|
123
|
-
@dir = make_dir_tree @files
|
124
|
-
@prj = Ruber::Project.new File.join(@dir, 'test.ruprj'), 'Test'
|
125
|
-
@prj.add_option(OS.new({:group => :general, :name => :project_files, :default => {:include => [], :exclude => [], :extensions => []} }))
|
126
|
-
@list = Ruber::ProjectFilesList.new @prj
|
127
|
-
@prj.add_extension :file_lister, @list
|
128
|
-
end
|
129
|
-
|
130
|
-
after do
|
131
|
-
FileUtils.rm_f @dir
|
132
|
-
end
|
133
|
-
|
134
|
-
it 'updates the cache if it\'s not up to date' do
|
135
|
-
@list.instance_variable_set :@up_to_date, false
|
136
|
-
flexmock(@list).should_receive(:refresh).once
|
137
|
-
@list.project_files
|
138
|
-
end
|
139
|
-
|
140
|
-
it 'doesn\'t update the cache if it\'s already up to date' do
|
141
|
-
@list.instance_variable_set :@up_to_date, true
|
142
|
-
flexmock(@list).should_receive(:refresh).never
|
143
|
-
@list.project_files
|
144
|
-
end
|
145
|
-
|
146
|
-
it 'returns an array containing all the files corresponding to include rules of type path unless they also correspond to an exclude rule of type path' do
|
147
|
-
@prj[:general, :project_files] = {:include => ['README', 'COPYING', 'f1.rb', 'd2/CHANGELOG', 'd2/f21.rb'], :exclude => ['COPYING', 'd2/f21.rb'], :extensions => []}
|
148
|
-
@list.project_files(false).should =~ %w[README f1.rb d2/CHANGELOG]
|
149
|
-
end
|
150
|
-
|
151
|
-
it 'doesn\'t include in the returned array files which don\'t exist' do
|
152
|
-
@prj[:general, :project_files] = {:include => ['README1', 'COPYING', 'f1.rb', 'd2/CHANGELOG', 'd2/f211.rb'], :exclude => ['COPYING'], :extensions => []}
|
153
|
-
@list.project_files(false).should =~ %w[f1.rb d2/CHANGELOG]
|
154
|
-
end
|
155
|
-
|
156
|
-
it 'skips include rules of type path corresponding to directories' do
|
157
|
-
@prj[:general, :project_files] = {:include => ['README', 'COPYING', 'f1.rb', 'd2/CHANGELOG', 'd2/f21.rb', 'd3'], :exclude => ['COPYING', 'd2/f21.rb'], :extensions => []}
|
158
|
-
@list.project_files(false).should =~ %w[README f1.rb d2/CHANGELOG]
|
159
|
-
end
|
160
|
-
|
161
|
-
it 'includes all the files in the project directory which correspond to one of the extensions in the returned array, unless they match one of the exclude rule' do
|
162
|
-
@prj[:general, :project_files] = {:include => [], :exclude => ['COPYING', 'd2/f21.rb'], :extensions => %w[*.rb]}
|
163
|
-
@list.project_files(false).should =~ %w[f1.rb d2/f22.rb d3/f31.rb d3/f32.rb]
|
164
|
-
end
|
165
|
-
|
166
|
-
it 'includes all the files in the project directory which match one of the include rules of type regexp and don\'t match any exclude rule' do
|
167
|
-
@prj[:general, :project_files] = {:include => [%r{d3/.*}, %r{.*\.yaml}], :exclude => [%r{d3/.*2.*}, %r{.*1.*\.rb}], :extensions => []}
|
168
|
-
@list.project_files(false).should =~ %w[d2/f22.yaml f1.yaml d2/f21.yaml]
|
169
|
-
end
|
170
|
-
|
171
|
-
it 'doesn\'t include duplicate elements' do
|
172
|
-
@prj[:general, :project_files] = {:include => [%r{d2/.*}, 'f1.rb'], :exclude => [], :extensions => ['*.rb']}
|
173
|
-
@list.project_files(false).should =~ %w[f1.rb d2/f21.rb d2/f22.rb d2/f21.yaml d2/f22.yaml d2/CHANGELOG d3/f31.rb d3/f32.rb]
|
174
|
-
end
|
175
|
-
|
176
|
-
it 'returns a deep copy of the cache object' do
|
177
|
-
@prj[:general, :project_files] = {:include => [%r{d2/.*}, 'f1.rb'], :exclude => [], :extensions => ['*.rb']}
|
178
|
-
old_cache = @list.instance_variable_get(:@project_files).deep_copy
|
179
|
-
res = @list.project_files(false)
|
180
|
-
res.should == old_cache
|
181
|
-
res << 'x'
|
182
|
-
@list.instance_variable_get(:@project_files).should == old_cache
|
183
|
-
end
|
184
|
-
|
185
|
-
it 'returns full paths if the argument is true' do
|
186
|
-
@prj[:general, :project_files] = {:include => [%r{d2/.*}, 'f1.rb'], :exclude => [], :extensions => ['*.rb']}
|
187
|
-
@list.project_files(true).should =~ %w[f1.rb d2/f21.rb d2/f22.rb d2/f21.yaml d2/f22.yaml d2/CHANGELOG d3/f31.rb d3/f32.rb].map{|i| File.join @dir, i}
|
188
|
-
end
|
189
|
-
|
190
|
-
it 'returns the correct list if a file or directory is added or deleted after the file watcher has been created' do
|
191
|
-
@prj[:general, :project_files] = {:include => [], :exclude => [], :extensions => ['*.rb']}
|
192
|
-
# Experiments show that KDE::DirWatch needs an event loop to work. Since we don't have one running, we'll have to make it emit the 'dirty' signal manually
|
193
|
-
watcher = @list.instance_variable_get(:@watcher)
|
194
|
-
`touch #@dir/f2.rb`
|
195
|
-
watcher.instance_eval{emit dirty( @dir)}
|
196
|
-
`touch #@dir/d2/f23.rb`
|
197
|
-
watcher.instance_eval{emit dirty( @dir)}
|
198
|
-
@list.project_files(false).should include('f2.rb')
|
199
|
-
@list.project_files(false).should include('d2/f23.rb')
|
200
|
-
FileUtils.mkdir("#@dir/d4")
|
201
|
-
watcher.instance_eval{emit dirty( @dir)}
|
202
|
-
`touch #@dir/d4/f41.rb`
|
203
|
-
watcher.instance_eval{emit dirty( @dir)}
|
204
|
-
`touch #@dir/d4/f42.rb`
|
205
|
-
watcher.instance_eval{emit dirty( @dir)}
|
206
|
-
@list.project_files(false).should include('d4/f41.rb')
|
207
|
-
@list.project_files(false).should include('d4/f42.rb')
|
208
|
-
FileUtils.rm_rf "#@dir/d2"
|
209
|
-
watcher.instance_eval{emit dirty( @dir)}
|
210
|
-
@list.project_files(false).should_not include("#@dir/d2/f21.rb")
|
211
|
-
@list.project_files(false).should_not include("#@dir/d2/f22.rb")
|
212
|
-
FileUtils.rm "#@dir/f1.rb"
|
213
|
-
watcher.instance_eval{emit dirty( @dir)}
|
214
|
-
@list.project_files(false).should_not include("f1.rb")
|
215
|
-
end
|
216
|
-
|
217
|
-
end
|
218
|
-
|
219
|
-
describe 'Ruber::ProjectFilesList#each' do
|
220
|
-
|
221
|
-
before do
|
222
|
-
@files = YAML.load('[f1.rb, f1.yaml, README, COPYING, [d2, f21.rb, f22.rb, f21.yaml, f22.yaml, CHANGELOG], [d3, f31.rb, f32.rb]]')
|
223
|
-
@dir = make_dir_tree @files
|
224
|
-
@prj = Ruber::Project.new File.join(@dir, 'test.ruprj'), 'Test'
|
225
|
-
@prj.add_option(OS.new({:group => :general, :name => :project_files, :default => {:include => %w[README f1.yaml], :exclude => %w[d2/f22.rb], :extensions => %w[*.rb]} }))
|
226
|
-
@list = Ruber::ProjectFilesList.new @prj
|
227
|
-
@prj.add_extension :file_lister, @list
|
228
|
-
end
|
229
|
-
|
230
|
-
it 'should update the cache if it\'s not up to date and a block is given' do
|
231
|
-
@list.instance_variable_set :@up_to_date, false
|
232
|
-
flexmock(@list).should_receive(:refresh).once
|
233
|
-
@list.each{}
|
234
|
-
end
|
235
|
-
|
236
|
-
it 'should not update the cache if it\'s already up to date and a block is given' do
|
237
|
-
@list.instance_variable_set :@up_to_date, true
|
238
|
-
flexmock(@list).should_receive(:refresh).never
|
239
|
-
@list.each{}
|
240
|
-
end
|
241
|
-
|
242
|
-
it 'should call the associated block passing the full file name of each project file if called with a block and the argument is true' do
|
243
|
-
exp = %w[f1.rb f1.yaml README d2/f21.rb d3/f31.rb d3/f32.rb].map{|f| File.join @dir, f}
|
244
|
-
m = flexmock do |mk|
|
245
|
-
exp.each{|f| mk.should_receive(:test).once.with(f)}
|
246
|
-
end
|
247
|
-
@list.each(true){|f| m.test f}
|
248
|
-
end
|
249
|
-
|
250
|
-
it 'should call the associated block passing the file name of each project file relative to the project directory if called with a block and the argument is false' do
|
251
|
-
exp = %w[f1.rb f1.yaml README d2/f21.rb d3/f31.rb d3/f32.rb]
|
252
|
-
m = flexmock do |mk|
|
253
|
-
exp.each{|f| mk.should_receive(:test).once.with(f)}
|
254
|
-
end
|
255
|
-
@list.each(false){|f| m.test f}
|
256
|
-
end
|
257
|
-
|
258
|
-
it 'should return an enumerator which yields the full file name of each project file if called without a block and the argument is true' do
|
259
|
-
enum = @list.each(true)
|
260
|
-
enum.should be_a(Enumerable)
|
261
|
-
exp = %w[f1.rb f1.yaml README d2/f21.rb d3/f31.rb d3/f32.rb].map{|f| File.join @dir, f}
|
262
|
-
m = flexmock do |mk|
|
263
|
-
exp.each{|f| mk.should_receive(:test).once.with(f)}
|
264
|
-
end
|
265
|
-
enum.each{|f| m.test f}
|
266
|
-
end
|
267
|
-
|
268
|
-
it 'should return an enumerator which yields the file name of each project file relative to the project directory if called without a block and the argument is false' do
|
269
|
-
enum = @list.each(false)
|
270
|
-
enum.should be_a(Enumerable)
|
271
|
-
exp = %w[f1.rb f1.yaml README d2/f21.rb d3/f31.rb d3/f32.rb]
|
272
|
-
m = flexmock do |mk|
|
273
|
-
exp.each{|f| mk.should_receive(:test).once.with(f)}
|
274
|
-
end
|
275
|
-
enum.each{|f| m.test f}
|
276
|
-
end
|
277
|
-
|
278
|
-
it 'should never update the cache if no block is given' do
|
279
|
-
@list.instance_variable_set :@up_to_date, false
|
280
|
-
flexmock(@list).should_receive(:refresh).never
|
281
|
-
@list.each
|
282
|
-
@list.instance_variable_set :@up_to_date, true
|
283
|
-
@list.each
|
284
|
-
end
|
285
|
-
|
286
|
-
end
|
287
|
-
|
288
|
-
describe 'Ruber::ProjectFilesList#rel' do
|
289
|
-
|
290
|
-
before do
|
291
|
-
@files = YAML.load('[f1.rb, f1.yaml, README, COPYING, [d2, f21.rb, f22.rb, f21.yaml, f22.yaml, CHANGELOG], [d3, f31.rb, f32.rb]]')
|
292
|
-
@dir = make_dir_tree @files
|
293
|
-
@prj = Ruber::Project.new File.join(@dir, 'test.ruprj'), 'Test'
|
294
|
-
@prj.add_option(OS.new({:group => :general, :name => :project_files, :default => {:include => %w[README f1.yaml], :exclude => %w[d2/f22.rb], :extensions => %w[*.rb]} }))
|
295
|
-
@list = Ruber::ProjectFilesList.new @prj
|
296
|
-
@prj.add_extension :file_lister, @list
|
297
|
-
end
|
298
|
-
|
299
|
-
it 'should work as the each method with no block and a false argument' do
|
300
|
-
enum = @list.rel
|
301
|
-
enum.should be_a(Enumerable)
|
302
|
-
exp = %w[f1.rb f1.yaml README d2/f21.rb d3/f31.rb d3/f32.rb]
|
303
|
-
m = flexmock do |mk|
|
304
|
-
exp.each{|f| mk.should_receive(:test).once.with(f)}
|
305
|
-
end
|
306
|
-
enum.each{|f| m.test f}
|
307
|
-
end
|
308
|
-
|
309
|
-
end
|
310
|
-
|
311
|
-
describe 'Ruber::ProjectFilesList#abs' do
|
312
|
-
|
313
|
-
before do
|
314
|
-
@files = YAML.load('[f1.rb, f1.yaml, README, COPYING, [d2, f21.rb, f22.rb, f21.yaml, f22.yaml, CHANGELOG], [d3, f31.rb, f32.rb]]')
|
315
|
-
@dir = make_dir_tree @files
|
316
|
-
@prj = Ruber::Project.new File.join(@dir, 'test.ruprj'), 'Test'
|
317
|
-
@prj.add_option(OS.new({:group => :general, :name => :project_files, :default => {:include => %w[README f1.yaml], :exclude => %w[d2/f22.rb], :extensions => %w[*.rb]} }))
|
318
|
-
@list = Ruber::ProjectFilesList.new @prj
|
319
|
-
@prj.add_extension :file_lister, @list
|
320
|
-
end
|
321
|
-
|
322
|
-
it 'should work as the each method with no block and a true argument' do
|
323
|
-
enum = @list.abs
|
324
|
-
enum.should be_a(Enumerable)
|
325
|
-
exp = %w[f1.rb f1.yaml README d2/f21.rb d3/f31.rb d3/f32.rb].map{|f| File.join @dir, f}
|
326
|
-
m = flexmock do |mk|
|
327
|
-
exp.each{|f| mk.should_receive(:test).once.with(f)}
|
328
|
-
end
|
329
|
-
enum.each{|f| m.test f}
|
330
|
-
end
|
331
|
-
|
332
|
-
|
333
|
-
end
|
334
|
-
|
335
|
-
describe Ruber::ProjectFilesList do
|
336
|
-
|
337
|
-
describe '#file_in_project?' do
|
338
|
-
|
339
|
-
before do
|
340
|
-
@dir = File.dirname __FILE__
|
341
|
-
@prj = Ruber::Project.new File.join(@dir, 'test.ruprj'), 'Test'
|
342
|
-
@prj.add_option(OS.new({:group => :general, :name => :project_files, :default => {:include => %w[], :exclude => %w[], :extensions => []} }))
|
343
|
-
@list = Ruber::ProjectFilesList.new @prj
|
344
|
-
@prj.add_extension :file_lister, @list
|
345
|
-
end
|
346
|
-
|
347
|
-
it 'returns true if the argument matches one of the exact include rules' do
|
348
|
-
@prj[:general, :project_files] = {:include => %w[./xyz ./abc ./123], :exclude => [], :extensions => ['*.rb']}
|
349
|
-
@list.file_in_project?(File.join(@prj.project_dir, 'abc')).should be_true
|
350
|
-
end
|
351
|
-
|
352
|
-
it 'returns true if the argument matches one of the regexp include rules' do
|
353
|
-
@prj[:general, :project_files] = {:include => [/a/, /x/], :exclude => [], :extensions => ['*.rb']}
|
354
|
-
@list.file_in_project?(File.join(@prj.project_dir, 'xyz')).should be_true
|
355
|
-
end
|
356
|
-
|
357
|
-
it 'returns true if the argument matches one of the include extensions' do
|
358
|
-
@prj[:general, :project_files] = {:include => [], :exclude => [], :extensions => ['*.rb', '*.yaml']}
|
359
|
-
@list.file_in_project?(File.join(@prj.project_dir, 'abc.rb')).should be_true
|
360
|
-
end
|
361
|
-
|
362
|
-
it 'returns false if the file isn\'t in the project directory' do
|
363
|
-
@prj[:general, :project_files] = {:include => %w[xyz abc 123], :exclude => [], :extensions => ['*.rb']}
|
364
|
-
@list.file_in_project?('/usr/abc').should be_false
|
365
|
-
end
|
366
|
-
|
367
|
-
it 'treats the argument as a path relative to the project directory if it isn\'t an absolute path' do
|
368
|
-
@prj[:general, :project_files] = {:include => %w[xyz abc 123], :exclude => [], :extensions => ['*.rb']}
|
369
|
-
@list.file_in_project?('abc').should be_true
|
370
|
-
end
|
371
|
-
|
372
|
-
it 'returns false if the file doesn\'t match any include rule' do
|
373
|
-
@list.file_in_project?(File.join(@prj.project_dir, 'abc.rb')).should be_false
|
374
|
-
end
|
375
|
-
|
376
|
-
it 'returns false if the file matches one of the file exclude rules' do
|
377
|
-
@prj[:general, :project_files] = {:include => %w[xyz abc 123], :exclude => ['abc'], :extensions => ['*.rb']}
|
378
|
-
@list.file_in_project?(File.join(@prj.project_dir, 'abc')).should be_false
|
379
|
-
end
|
380
|
-
|
381
|
-
it 'returns false if the file matches one of the exclude regexps' do
|
382
|
-
@prj[:general, :project_files] = {:include => [/a/], :exclude => [/a/], :extensions => []}
|
383
|
-
@list.file_in_project?(File.join(@prj.project_dir, 'abc')).should be_false
|
384
|
-
end
|
385
|
-
|
386
|
-
it 'it considers the whole path of the file, not just the filename' do
|
387
|
-
@prj[:general, :project_files] = {:include => [%r{a/.*}], :exclude => [%r{b/.*}], :extensions => ['*.rb']}
|
388
|
-
@list.file_in_project?(File.join(@prj.project_dir, 'a', 'xyz')).should be_true
|
389
|
-
@list.file_in_project?(File.join(@prj.project_dir, 'b', 'xyz.rb')).should be_false
|
390
|
-
end
|
391
|
-
|
392
|
-
it 'returns nil if the file name ends with a slash' do
|
393
|
-
@prj[:general, :project_files] = {:include => [%r{a/.*}], :exclude => [%r{b/.*}], :extensions => ['*.rb']}
|
394
|
-
@list.file_in_project?('xyz/').should be_nil
|
395
|
-
end
|
396
|
-
|
397
|
-
it 'returns false if the path represents a remote URL' do
|
398
|
-
@prj[:general, :project_files] = {:include => [], :exclude => [], :extensions => ['*.rb']}
|
399
|
-
@list.file_in_project?("http://#{@dir}/abc.xyz.rb").should be_false
|
400
|
-
end
|
401
|
-
|
402
|
-
it 'works normally if the path represents a local url' do
|
403
|
-
@prj[:general, :project_files] = {:include => [], :exclude => [], :extensions => ['*.rb']}
|
404
|
-
@list.file_in_project?("file://#{@dir}/abc.xyz.rb").should be_true
|
405
|
-
end
|
406
|
-
|
407
|
-
end
|
408
|
-
|
409
|
-
end
|
410
|
-
|
411
|
-
end
|