maid 0.2.1 → 0.2.2.beta.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,4 @@
1
1
  rvm:
2
2
  - 1.8.7
3
3
  - 1.9.3
4
+ - 2.0.0
data/ChangeLog CHANGED
@@ -1,3 +1,12 @@
1
+ maid (0.2.2.beta.1) unstable; urgency=low
2
+
3
+ * Added better documentation (Closes: #91)
4
+ * Safely escape shell commands (Closes: #70)
5
+ * Made gem version dependencies less strict
6
+ * Started experimental Ruby 2.0 support
7
+
8
+ -- Benjamin Oakes <hello@benjaminoakes.com> Sun, 17 Feb 2013 00:00:00 +0000
9
+
1
10
  maid (0.2.1) stable; urgency=low
2
11
 
3
12
  * Fix YARD generation for http://rubydoc.info/. (Otherwise identical to
data/Guardfile CHANGED
@@ -1,6 +1,4 @@
1
- # A sample Guardfile
2
1
  # More info at https://github.com/guard/guard#readme
3
-
4
2
  guard 'rspec' do
5
3
  watch(%r{^spec/.+_spec\.rb$})
6
4
  watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{ m[1] }_spec.rb" }
data/README.md CHANGED
@@ -2,8 +2,8 @@
2
2
 
3
3
  Be lazy! Let Maid clean up after you, based on rules you define.
4
4
 
5
- [Installation](https://github.com/benjaminoakes/maid#installation)
6
- | [Tutorial](https://github.com/benjaminoakes/maid#tutorial)
5
+ [Installation](#installation)
6
+ | [Tutorial](#tutorial)
7
7
  | [Example](https://github.com/benjaminoakes/maid-example)
8
8
  | [User Community](https://github.com/benjaminoakes/maid/wiki)
9
9
  | [Documentation][]
@@ -1,4 +1,5 @@
1
1
  require 'deprecated'
2
+ require 'escape'
2
3
  Deprecated.set_action(:warn)
3
4
 
4
5
  # Must be in this order:
@@ -12,6 +12,7 @@ require 'time'
12
12
  # Some methods are not available on all platforms. An `ArgumentError` is raised when a command is not available. See
13
13
  # tags such as: [Mac OS X]
14
14
  module Maid::Tools
15
+ # For showing deprecation notices
15
16
  include Deprecated
16
17
 
17
18
  # Move from `sources` to `destination`
@@ -35,10 +36,10 @@ module Maid::Tools
35
36
  target = File.join(destination, File.basename(source))
36
37
 
37
38
  unless File.exist?(target)
38
- log("mv #{ source.inspect } #{ destination.inspect }")
39
+ log("mv #{ sh_escape(source) } #{ sh_escape(destination) }")
39
40
  FileUtils.mv(source, destination, @file_options)
40
41
  else
41
- warn("skipping #{ source.inspect } because #{ target.inspect } already exists")
42
+ warn("skipping #{ sh_escape(source) } because #{ sh_escape(target) } already exists")
42
43
  end
43
44
  end
44
45
  end
@@ -136,7 +137,7 @@ module Maid::Tools
136
137
  expand_all(paths).each do |path|
137
138
  options = @file_options.merge(options)
138
139
 
139
- log("Removing #{ path.inspect }")
140
+ log("Removing #{ sh_escape(path) }")
140
141
  FileUtils.rm_r(path, options)
141
142
  end
142
143
  end
@@ -164,6 +165,10 @@ module Maid::Tools
164
165
  # dir(%w(~/Downloads/*.zip ~/Dropbox/*.zip))
165
166
  # dir('~/{Downloads,Dropbox}/*.zip')
166
167
  #
168
+ # Recursing into subdirectories (see also: `find`):
169
+ #
170
+ # dir('~/Music/**/*.m4a')
171
+ #
167
172
  def dir(globs)
168
173
  expand_all(globs).
169
174
  map { |glob| Dir.glob(glob) }.
@@ -192,7 +197,7 @@ module Maid::Tools
192
197
  # move('~/Downloads/Pink Floyd*.mp3', mkdir('~/Music/Pink Floyd/'))
193
198
  def mkdir(path, options = {})
194
199
  path = expand(path)
195
- log("mkdir -p #{ path.inspect }")
200
+ log("mkdir -p #{ sh_escape(path) }")
196
201
  FileUtils.mkdir_p(path, @file_options.merge(options))
197
202
  path
198
203
  end
@@ -239,7 +244,7 @@ module Maid::Tools
239
244
  #
240
245
  # locate('foo.zip') # => ['/a/foo.zip', '/b/foo.zip']
241
246
  def locate(name)
242
- cmd("mdfind -name #{ name.inspect }").split("\n")
247
+ cmd("mdfind -name #{ sh_escape(name) }").split("\n")
243
248
  end
244
249
 
245
250
  # [Mac OS X] Use Spotlight metadata to determine the site from which a file was downloaded.
@@ -248,7 +253,7 @@ module Maid::Tools
248
253
  #
249
254
  # downloaded_from('foo.zip') # => ['http://www.site.com/foo.zip', 'http://www.site.com/']
250
255
  def downloaded_from(path)
251
- raw = cmd("mdls -raw -name kMDItemWhereFroms #{ path.inspect }")
256
+ raw = cmd("mdls -raw -name kMDItemWhereFroms #{ sh_escape(path) }")
252
257
  clean = raw[1, raw.length - 2]
253
258
  clean.split(/,\s+/).map { |s| t = s.strip; t[1, t.length - 2] }
254
259
  end
@@ -259,7 +264,7 @@ module Maid::Tools
259
264
  #
260
265
  # duration_s('foo.mp3') # => 235.705
261
266
  def duration_s(path)
262
- cmd("mdls -raw -name kMDItemDurationSeconds #{ path.inspect }").to_f
267
+ cmd("mdls -raw -name kMDItemDurationSeconds #{ sh_escape(path) }").to_f
263
268
  end
264
269
 
265
270
  # List the contents of a zip file.
@@ -268,7 +273,7 @@ module Maid::Tools
268
273
  #
269
274
  # zipfile_contents('foo.zip') # => ['foo/foo.exe', 'foo/README.txt']
270
275
  def zipfile_contents(path)
271
- raw = cmd("unzip -Z1 #{ path.inspect }")
276
+ raw = cmd("unzip -Z1 #{ sh_escape(path) }")
272
277
  raw.split("\n")
273
278
  end
274
279
 
@@ -280,7 +285,7 @@ module Maid::Tools
280
285
  #
281
286
  # disk_usage('foo.zip') # => 136
282
287
  def disk_usage(path)
283
- raw = cmd("du -s #{ path.inspect }")
288
+ raw = cmd("du -s #{ sh_escape(path) }")
284
289
  # FIXME: This reports in kilobytes, but should probably report in bytes.
285
290
  usage_kb = raw.split(/\s+/).first.to_i
286
291
 
@@ -345,8 +350,8 @@ module Maid::Tools
345
350
  # git_piston('~/code/projectname')
346
351
  def git_piston(path)
347
352
  full_path = expand(path)
348
- stdout = cmd("cd #{full_path.inspect} && git pull && git push 2>&1")
349
- log("Fired git piston on #{full_path.inspect}. STDOUT:\n\n#{stdout}")
353
+ stdout = cmd("cd #{ sh_escape(full_path) } && git pull && git push 2>&1")
354
+ log("Fired git piston on #{ sh_escape(full_path) }. STDOUT:\n\n#{ stdout }")
350
355
  end
351
356
 
352
357
  deprecated :git_piston, 'SparkleShare (http://sparkleshare.org/)'
@@ -394,16 +399,20 @@ module Maid::Tools
394
399
  ops << '-n' if @file_options[:noop]
395
400
 
396
401
  Array(options[:exclude]).each do |path|
397
- ops << "--exclude=#{ path.inspect }"
402
+ ops << "--exclude=#{ sh_escape(path) }"
398
403
  end
399
404
 
400
405
  ops << '--delete' if options[:delete]
401
- stdout = cmd("rsync #{ ops.join(' ') } #{ from.inspect } #{ to.inspect } 2>&1")
402
- log("Fired sync from #{ from.inspect } to #{ to.inspect }. STDOUT:\n\n#{ stdout }")
406
+ stdout = cmd("rsync #{ ops.join(' ') } #{ sh_escape(from) } #{ sh_escape(to) } 2>&1")
407
+ log("Fired sync from #{ sh_escape(from) } to #{ sh_escape(to) }. STDOUT:\n\n#{ stdout }")
403
408
  end
404
409
 
405
410
  private
406
411
 
412
+ def sh_escape(array)
413
+ Escape.shell_command(Array(array))
414
+ end
415
+
407
416
  def log(message)
408
417
  @logger.info(message)
409
418
  end
@@ -1,3 +1,3 @@
1
1
  module Maid
2
- VERSION = '0.2.1'
2
+ VERSION = '0.2.2.beta.1'
3
3
  end
@@ -16,26 +16,29 @@ Gem::Specification.new do |s|
16
16
 
17
17
  s.rubyforge_project = 'maid'
18
18
 
19
- s.add_dependency('thor', '~> 0.16.0')
20
- s.add_dependency('deprecated', '~> 3.0.1')
21
- s.add_dependency('ohai', '~> 6.14.0')
22
- s.add_dependency('xdg', '~> 2.2.3')
23
- s.add_development_dependency('fakefs', '~> 0.4.1')
24
- s.add_development_dependency('guard', '~> 1.5.4')
25
- s.add_development_dependency('guard-rspec', '~> 2.3.0')
26
- s.add_development_dependency('rb-readline', '~> 0.4.2') # To get guard file change detection working properly
27
- s.add_development_dependency('rake', '~> 10.0.2')
19
+ # Strategy: if possible, use ranges (so there are fewer chances of version conflicts)
20
+ s.add_dependency('escape', '>= 0.0.1', '< 0.1.0') # Used for better Ruby 1.8.7 support
21
+ s.add_dependency('thor', '>= 0.14.0', '< 0.18.0')
22
+ s.add_dependency('deprecated', '~> 3.0.0')
23
+ s.add_dependency('ohai', '>= 6.14.0', '< 6.17.0')
24
+ s.add_dependency('xdg', '~> 2.2.3') # previous versions had bugs
25
+
26
+ # Strategy: specific versions (since they're just for development)
27
+ s.add_development_dependency('fakefs', '~> 0.4.2')
28
+ s.add_development_dependency('guard', '~> 1.6.2')
29
+ s.add_development_dependency('guard-rspec', '~> 2.4.0')
30
+ s.add_development_dependency('rake', '~> 10.0.3')
28
31
  s.add_development_dependency('redcarpet', '~> 2.2.2') # Soft dependency of `yard`
29
32
  s.add_development_dependency('rspec', '~> 2.12.0')
30
- s.add_development_dependency('timecop', '~> 0.5.3')
31
- s.add_development_dependency('yard', '~> 0.8.3')
33
+ s.add_development_dependency('timecop', '~> 0.5.9.1')
34
+ s.add_development_dependency('yard', '~> 0.8.4')
32
35
 
33
36
  # In Vagrant, polling won't cross over the OS boundary if you develop in the host OS but run your tests in the
34
37
  # guest. One way around this is to force polling instead:
35
38
  #
36
39
  # bundle exec guard --force-polling
37
40
  #
38
- s.add_development_dependency('rb-inotify', '~> 0.8.8')
41
+ s.add_development_dependency('rb-inotify', '~> 0.9.0')
39
42
  s.add_development_dependency('rb-fsevent', '~> 0.9.2')
40
43
 
41
44
  s.files = `git ls-files`.split("\n")
@@ -196,6 +196,10 @@ module Maid
196
196
  it 'lists files in directories when using regexp-like glob patterns' do
197
197
  @maid.dir('~/{Desktop,Downloads}/*.zip').should == [@other_file, @file]
198
198
  end
199
+
200
+ it 'lists files in directories when using recursive glob patterns' do
201
+ @maid.dir('~/**/*.zip').should == [@other_file, @file]
202
+ end
199
203
  end
200
204
  end
201
205
 
@@ -334,7 +338,7 @@ module Maid
334
338
  end
335
339
 
336
340
  it 'should pull and push the given git repository, logging the action' do
337
- @maid.should_receive(:cmd).with(%(cd "#@home/code/projectname" && git pull && git push 2>&1))
341
+ @maid.should_receive(:cmd).with(%(cd #@home/code/projectname && git pull && git push 2>&1))
338
342
  @logger.should_receive(:info)
339
343
  @maid.git_piston('~/code/projectname')
340
344
  end
@@ -347,7 +351,7 @@ module Maid
347
351
  end
348
352
 
349
353
  it 'should sync the expanded paths, retaining backslash' do
350
- @maid.should_receive(:cmd).with(%(rsync -a -u "#@home/Downloads/" "#@home/Reference" 2>&1))
354
+ @maid.should_receive(:cmd).with(%(rsync -a -u #@home/Downloads/ #@home/Reference 2>&1))
351
355
  @maid.sync(@src_dir, @dst_dir)
352
356
  end
353
357
 
@@ -357,25 +361,25 @@ module Maid
357
361
  end
358
362
 
359
363
  it 'should have no options' do
360
- @maid.should_receive(:cmd).with(%(rsync "#@home/Downloads/" "#@home/Reference" 2>&1))
364
+ @maid.should_receive(:cmd).with(%(rsync #@home/Downloads/ #@home/Reference 2>&1))
361
365
  @maid.sync(@src_dir, @dst_dir, :archive => false, :update => false)
362
366
  end
363
367
 
364
368
  it 'should add all options' do
365
- @maid.should_receive(:cmd).with(%(rsync -a -v -u -m --exclude=".git" --delete "#@home/Downloads/" "#@home/Reference" 2>&1))
369
+ @maid.should_receive(:cmd).with(%(rsync -a -v -u -m --exclude=.git --delete #@home/Downloads/ #@home/Reference 2>&1))
366
370
  @maid.sync(@src_dir, @dst_dir, :archive => true, :update => true, :delete => true, :verbose => true, :prune_empty => true, :exclude => '.git')
367
371
  end
368
372
 
369
373
  it 'should add multiple exlcude options' do
370
374
  @maid.
371
375
  should_receive(:cmd).
372
- with(%(rsync -a -u --exclude=".git" --exclude=".rvmrc" "#@home/Downloads/" "#@home/Reference" 2>&1))
376
+ with(%(rsync -a -u --exclude=.git --exclude=.rvmrc #@home/Downloads/ #@home/Reference 2>&1))
373
377
  @maid.sync(@src_dir, @dst_dir, :exclude => ['.git', '.rvmrc'])
374
378
  end
375
379
 
376
380
  it 'should add noop option' do
377
381
  @maid.file_options[:noop] = true
378
- @maid.should_receive(:cmd).with(%(rsync -a -u -n "#@home/Downloads/" "#@home/Reference" 2>&1))
382
+ @maid.should_receive(:cmd).with(%(rsync -a -u -n #@home/Downloads/ #@home/Reference 2>&1))
379
383
  @maid.sync(@src_dir, @dst_dir)
380
384
  end
381
385
  end
metadata CHANGED
@@ -1,52 +1,72 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: maid
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
5
- prerelease:
4
+ version: 0.2.2.beta.1
5
+ prerelease: 6
6
6
  platform: ruby
7
7
  authors:
8
8
  - Benjamin Oakes
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-12-25 00:00:00.000000000 Z
12
+ date: 2013-02-17 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: escape
16
+ requirement: &7714060 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 0.0.1
22
+ - - <
23
+ - !ruby/object:Gem::Version
24
+ version: 0.1.0
25
+ type: :runtime
26
+ prerelease: false
27
+ version_requirements: *7714060
14
28
  - !ruby/object:Gem::Dependency
15
29
  name: thor
16
- requirement: &9942340 !ruby/object:Gem::Requirement
30
+ requirement: &7704680 !ruby/object:Gem::Requirement
17
31
  none: false
18
32
  requirements:
19
- - - ~>
33
+ - - ! '>='
34
+ - !ruby/object:Gem::Version
35
+ version: 0.14.0
36
+ - - <
20
37
  - !ruby/object:Gem::Version
21
- version: 0.16.0
38
+ version: 0.18.0
22
39
  type: :runtime
23
40
  prerelease: false
24
- version_requirements: *9942340
41
+ version_requirements: *7704680
25
42
  - !ruby/object:Gem::Dependency
26
43
  name: deprecated
27
- requirement: &10005180 !ruby/object:Gem::Requirement
44
+ requirement: &7703240 !ruby/object:Gem::Requirement
28
45
  none: false
29
46
  requirements:
30
47
  - - ~>
31
48
  - !ruby/object:Gem::Version
32
- version: 3.0.1
49
+ version: 3.0.0
33
50
  type: :runtime
34
51
  prerelease: false
35
- version_requirements: *10005180
52
+ version_requirements: *7703240
36
53
  - !ruby/object:Gem::Dependency
37
54
  name: ohai
38
- requirement: &10003340 !ruby/object:Gem::Requirement
55
+ requirement: &7702440 !ruby/object:Gem::Requirement
39
56
  none: false
40
57
  requirements:
41
- - - ~>
58
+ - - ! '>='
42
59
  - !ruby/object:Gem::Version
43
60
  version: 6.14.0
61
+ - - <
62
+ - !ruby/object:Gem::Version
63
+ version: 6.17.0
44
64
  type: :runtime
45
65
  prerelease: false
46
- version_requirements: *10003340
66
+ version_requirements: *7702440
47
67
  - !ruby/object:Gem::Dependency
48
68
  name: xdg
49
- requirement: &10001860 !ruby/object:Gem::Requirement
69
+ requirement: &7701440 !ruby/object:Gem::Requirement
50
70
  none: false
51
71
  requirements:
52
72
  - - ~>
@@ -54,65 +74,54 @@ dependencies:
54
74
  version: 2.2.3
55
75
  type: :runtime
56
76
  prerelease: false
57
- version_requirements: *10001860
77
+ version_requirements: *7701440
58
78
  - !ruby/object:Gem::Dependency
59
79
  name: fakefs
60
- requirement: &10001120 !ruby/object:Gem::Requirement
80
+ requirement: &7700740 !ruby/object:Gem::Requirement
61
81
  none: false
62
82
  requirements:
63
83
  - - ~>
64
84
  - !ruby/object:Gem::Version
65
- version: 0.4.1
85
+ version: 0.4.2
66
86
  type: :development
67
87
  prerelease: false
68
- version_requirements: *10001120
88
+ version_requirements: *7700740
69
89
  - !ruby/object:Gem::Dependency
70
90
  name: guard
71
- requirement: &10000560 !ruby/object:Gem::Requirement
91
+ requirement: &7700040 !ruby/object:Gem::Requirement
72
92
  none: false
73
93
  requirements:
74
94
  - - ~>
75
95
  - !ruby/object:Gem::Version
76
- version: 1.5.4
96
+ version: 1.6.2
77
97
  type: :development
78
98
  prerelease: false
79
- version_requirements: *10000560
99
+ version_requirements: *7700040
80
100
  - !ruby/object:Gem::Dependency
81
101
  name: guard-rspec
82
- requirement: &9999640 !ruby/object:Gem::Requirement
102
+ requirement: &7699300 !ruby/object:Gem::Requirement
83
103
  none: false
84
104
  requirements:
85
105
  - - ~>
86
106
  - !ruby/object:Gem::Version
87
- version: 2.3.0
107
+ version: 2.4.0
88
108
  type: :development
89
109
  prerelease: false
90
- version_requirements: *9999640
91
- - !ruby/object:Gem::Dependency
92
- name: rb-readline
93
- requirement: &9998740 !ruby/object:Gem::Requirement
94
- none: false
95
- requirements:
96
- - - ~>
97
- - !ruby/object:Gem::Version
98
- version: 0.4.2
99
- type: :development
100
- prerelease: false
101
- version_requirements: *9998740
110
+ version_requirements: *7699300
102
111
  - !ruby/object:Gem::Dependency
103
112
  name: rake
104
- requirement: &10014900 !ruby/object:Gem::Requirement
113
+ requirement: &7698640 !ruby/object:Gem::Requirement
105
114
  none: false
106
115
  requirements:
107
116
  - - ~>
108
117
  - !ruby/object:Gem::Version
109
- version: 10.0.2
118
+ version: 10.0.3
110
119
  type: :development
111
120
  prerelease: false
112
- version_requirements: *10014900
121
+ version_requirements: *7698640
113
122
  - !ruby/object:Gem::Dependency
114
123
  name: redcarpet
115
- requirement: &10014020 !ruby/object:Gem::Requirement
124
+ requirement: &7697940 !ruby/object:Gem::Requirement
116
125
  none: false
117
126
  requirements:
118
127
  - - ~>
@@ -120,10 +129,10 @@ dependencies:
120
129
  version: 2.2.2
121
130
  type: :development
122
131
  prerelease: false
123
- version_requirements: *10014020
132
+ version_requirements: *7697940
124
133
  - !ruby/object:Gem::Dependency
125
134
  name: rspec
126
- requirement: &10012340 !ruby/object:Gem::Requirement
135
+ requirement: &7687280 !ruby/object:Gem::Requirement
127
136
  none: false
128
137
  requirements:
129
138
  - - ~>
@@ -131,43 +140,43 @@ dependencies:
131
140
  version: 2.12.0
132
141
  type: :development
133
142
  prerelease: false
134
- version_requirements: *10012340
143
+ version_requirements: *7687280
135
144
  - !ruby/object:Gem::Dependency
136
145
  name: timecop
137
- requirement: &10011140 !ruby/object:Gem::Requirement
146
+ requirement: &7686480 !ruby/object:Gem::Requirement
138
147
  none: false
139
148
  requirements:
140
149
  - - ~>
141
150
  - !ruby/object:Gem::Version
142
- version: 0.5.3
151
+ version: 0.5.9.1
143
152
  type: :development
144
153
  prerelease: false
145
- version_requirements: *10011140
154
+ version_requirements: *7686480
146
155
  - !ruby/object:Gem::Dependency
147
156
  name: yard
148
- requirement: &10009380 !ruby/object:Gem::Requirement
157
+ requirement: &7685980 !ruby/object:Gem::Requirement
149
158
  none: false
150
159
  requirements:
151
160
  - - ~>
152
161
  - !ruby/object:Gem::Version
153
- version: 0.8.3
162
+ version: 0.8.4
154
163
  type: :development
155
164
  prerelease: false
156
- version_requirements: *10009380
165
+ version_requirements: *7685980
157
166
  - !ruby/object:Gem::Dependency
158
167
  name: rb-inotify
159
- requirement: &10026320 !ruby/object:Gem::Requirement
168
+ requirement: &7685520 !ruby/object:Gem::Requirement
160
169
  none: false
161
170
  requirements:
162
171
  - - ~>
163
172
  - !ruby/object:Gem::Version
164
- version: 0.8.8
173
+ version: 0.9.0
165
174
  type: :development
166
175
  prerelease: false
167
- version_requirements: *10026320
176
+ version_requirements: *7685520
168
177
  - !ruby/object:Gem::Dependency
169
178
  name: rb-fsevent
170
- requirement: &10024260 !ruby/object:Gem::Requirement
179
+ requirement: &7685040 !ruby/object:Gem::Requirement
171
180
  none: false
172
181
  requirements:
173
182
  - - ~>
@@ -175,7 +184,7 @@ dependencies:
175
184
  version: 0.9.2
176
185
  type: :development
177
186
  prerelease: false
178
- version_requirements: *10024260
187
+ version_requirements: *7685040
179
188
  description: Be lazy. Let Maid clean up after you, based on rules you define. Think
180
189
  of it as "Hazel for hackers".
181
190
  email:
@@ -247,9 +256,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
247
256
  required_rubygems_version: !ruby/object:Gem::Requirement
248
257
  none: false
249
258
  requirements:
250
- - - ! '>='
259
+ - - ! '>'
251
260
  - !ruby/object:Gem::Version
252
- version: '0'
261
+ version: 1.3.1
253
262
  requirements: []
254
263
  rubyforge_project: maid
255
264
  rubygems_version: 1.8.11