maid 0.3.0 → 0.4.0.alpha.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/AUTHORS.md +6 -0
- data/ChangeLog +46 -91
- data/README.md +6 -5
- data/Vagrantfile +7 -2
- data/lib/maid/app.rb +8 -3
- data/lib/maid/maid.rb +7 -2
- data/lib/maid/platform.rb +11 -0
- data/lib/maid/tools.rb +154 -9
- data/lib/maid/version.rb +1 -1
- data/maid.gemspec +14 -9
- data/spec/dependency_spec.rb +29 -0
- data/spec/fixtures/files/bar.zip +0 -0
- data/spec/fixtures/files/foo.zip +0 -0
- data/spec/fixtures/files/ruby.jpg +0 -0
- data/spec/fixtures/files//343/201/225.zip +0 -0
- data/spec/lib/maid/app_spec.rb +13 -5
- data/spec/lib/maid/maid_spec.rb +15 -5
- data/spec/lib/maid/platform_spec.rb +8 -0
- data/spec/lib/maid/tools_spec.rb +131 -3
- metadata +71 -41
- data/.rvmrc +0 -1
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
maid
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.8.7
|
data/AUTHORS.md
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
In alphabetical order:
|
2
2
|
|
3
3
|
* Benjamin Oakes (@benjaminoakes)
|
4
|
+
* Bradley Smith (@bradleyd)
|
5
|
+
* Graham Siener (@gsiener)
|
6
|
+
* John Colvin (@JohnColvin)
|
7
|
+
* Justin Hileman (@bobthecow)
|
4
8
|
* Larry Lv (@larrylv)
|
5
9
|
* Lewis O'Driscoll (@loddy1234)
|
6
10
|
* Lloyd Philbrook (@phoolish)
|
7
11
|
* Mark Jaquith (@markjaquith)
|
12
|
+
* Mikael Hultgren (@blomma)
|
13
|
+
* Mu Ye (@yemutex)
|
data/ChangeLog
CHANGED
@@ -1,3 +1,19 @@
|
|
1
|
+
maid (0.4.0) unstable; urgency=low
|
2
|
+
|
3
|
+
* (Work in progress)
|
4
|
+
* NOTE: A previous alpha of v0.3.0 was released as v0.2.3.alpha.1.
|
5
|
+
* Mu Ye: Require option to cause real cleaning to take place (Closes: #78)
|
6
|
+
* Graham Siener: Add UTF-8 support for zipfile_contents tool (Closes: #35)
|
7
|
+
* Justin Hileman: Add ability to list duplicate files (Closes: #15)
|
8
|
+
* Mikael Hultgren: Rotate log file
|
9
|
+
* John Colvin: Add filetype detection and filtering (Closes: #51)
|
10
|
+
* Mu Ye: Improve command line spec coverage (Closes: #97)
|
11
|
+
* Changed from ArgumentError to NotImplementedError when a command is
|
12
|
+
unsupported on the host OS.
|
13
|
+
* Bradley Smith: Add locate support on Ubuntu (Closes: #67)
|
14
|
+
|
15
|
+
-- Benjamin Oakes <hello@benjaminoakes.com> TODO
|
16
|
+
|
1
17
|
maid (0.3.0) stable; urgency=high
|
2
18
|
|
3
19
|
* Stats! { 'collaborators' => 11, 'downloads' => 5664, 'forks' => 36,
|
@@ -15,21 +31,12 @@ maid (0.2.2) stable; urgency=high
|
|
15
31
|
'open_issues' => 35, 'closed_issues' => 60, 'stars' => 654,
|
16
32
|
'users_sharing_rules' => 19 }
|
17
33
|
* "urgency=high" because of security related change in #70
|
18
|
-
* Includes all changes since the 0.2.1 release
|
19
|
-
|
20
|
-
-- Benjamin Oakes <hello@benjaminoakes.com> Wed, 27 Feb 2013 00:00:00 +0000
|
21
|
-
|
22
|
-
maid (0.2.2.beta.1) unstable; urgency=low
|
23
|
-
|
24
|
-
* Stats! { 'collaborators' => 11, 'downloads' => 4788, 'forks' => 36,
|
25
|
-
'open_issues' => 36, 'closed_issues' => 59, 'stars' => 649,
|
26
|
-
'users_sharing_rules' => 18 }
|
27
34
|
* Added better documentation (Closes: #91)
|
28
35
|
* Safely escape shell commands (Closes: #70)
|
29
36
|
* Made gem version dependencies less strict
|
30
37
|
* Started experimental Ruby 2.0 support
|
31
38
|
|
32
|
-
-- Benjamin Oakes <hello@benjaminoakes.com>
|
39
|
+
-- Benjamin Oakes <hello@benjaminoakes.com> Wed, 27 Feb 2013 00:00:00 +0000
|
33
40
|
|
34
41
|
maid (0.2.1) stable; urgency=low
|
35
42
|
|
@@ -40,108 +47,56 @@ maid (0.2.1) stable; urgency=low
|
|
40
47
|
|
41
48
|
maid (0.2.0) stable; urgency=low
|
42
49
|
|
43
|
-
*
|
44
|
-
|
45
|
-
|
46
|
-
-- Benjamin Oakes <hello@benjaminoakes.com> Tue, 25 Dec 2012 00:00:00 +0000
|
47
|
-
|
48
|
-
maid (0.2.0.rc.2) unstable; urgency=low
|
49
|
-
|
50
|
-
* Change "maid --version" to be the same as "maid version"
|
51
|
-
|
52
|
-
-- Benjamin Oakes <hello@benjaminoakes.com> Mon, 24 Dec 2012 00:00:00 +0000
|
53
|
-
|
54
|
-
maid (0.2.0.rc.1) unstable; urgency=low
|
55
|
-
|
56
|
-
* More documentation for "dir".
|
57
|
-
|
58
|
-
-- Benjamin Oakes <hello@benjaminoakes.com> Wed, 19 Dec 2012 00:00:00 +0000
|
59
|
-
|
60
|
-
maid (0.2.0.beta.3) unstable; urgency=low
|
61
|
-
|
62
|
-
* Use newly released "xdg" instead of custom "maid-xdg" dependency. (The new
|
63
|
-
release was found after Beta 2 was released.)
|
64
|
-
|
65
|
-
-- Benjamin Oakes <hello@benjaminoakes.com> Mon, 17 Dec 2012 00:00:00 +0000
|
66
|
-
|
67
|
-
maid (0.2.0.beta.2) unstable; urgency=low
|
68
|
-
|
50
|
+
* Started semver.org-like version numbering.
|
51
|
+
* Improved user documentation, now in Markdown. (Closes: #66)
|
69
52
|
* Add more documentation to "find" and "remove" (Closes: #74)
|
70
|
-
* Add
|
71
|
-
* Updated README to include Hacker News post
|
72
|
-
* Updated AUTHORS to include new contributors
|
73
|
-
* Various development improvements
|
74
|
-
|
75
|
-
-- Benjamin Oakes <hello@benjaminoakes.com> Sun, 16 Dec 2012 00:00:00 +0000
|
76
|
-
|
77
|
-
maid (0.2.0.beta.1) unstable; urgency=low
|
78
|
-
|
53
|
+
* Add more documentation for "dir".
|
79
54
|
* Change "dir" to allow multiple paths (Closes: #64)
|
80
|
-
* Change "mkdir" to return the path of the created directory (Closes: #69)
|
81
|
-
* Various development improvements
|
82
|
-
|
83
|
-
-- Benjamin Oakes <hello@benjaminoakes.com> Sun, 2 Dec 2012 00:00:00 +0000
|
84
|
-
|
85
|
-
maid (0.2.0.alpha.1) unstable; urgency=low
|
86
|
-
|
87
|
-
* Started semver.org-like version numbering. Total adoption is
|
88
|
-
forthcoming. This forced v0.2.0 vs. v0.1.4.
|
89
55
|
* Changed "dir" tool to always sort. (Closes: #62)
|
56
|
+
* Lewis O'Driscoll: Add logging to "mkdir" (Closes: #75, #77)
|
57
|
+
* Change "mkdir" to return the path of the created directory (Closes: #69)
|
58
|
+
* Use newly released "xdg" instead of custom "maid-xdg" dependency.
|
59
|
+
* Change "maid --version" to be the same as "maid version"
|
90
60
|
* Added "version --long" ("-l") command which gives information about the platform
|
91
61
|
version and Ruby version. (Closes: #65)
|
92
|
-
* Improved user documentation, now in Markdown. (Closes: #66)
|
93
62
|
* Updated development dependencies.
|
94
|
-
*
|
95
|
-
|
96
|
-
-- Benjamin Oakes <hello@benjaminoakes.com> Tue, 27 Nov 2012 00:00:00 +0000
|
97
|
-
|
98
|
-
maid (0.1.4.alpha.2) unstable; urgency=low
|
99
|
-
|
63
|
+
* Updated README to include Hacker News post
|
64
|
+
* Updated AUTHORS to include new contributors
|
100
65
|
* Noted license in gemspec. Was incorrect value in alpha.1. Made an early
|
101
66
|
alpha release to test effect on RubyGems.org listing. (Closes: #61)
|
102
|
-
*
|
67
|
+
* Various development improvements
|
103
68
|
|
104
|
-
-- Benjamin Oakes <hello@benjaminoakes.com>
|
69
|
+
-- Benjamin Oakes <hello@benjaminoakes.com> Tue, 25 Dec 2012 00:00:00 +0000
|
105
70
|
|
106
71
|
maid (0.1.3) stable; urgency=medium
|
107
72
|
|
108
73
|
* Stats! { 'stars' => 192 }
|
109
74
|
* First stable release with official support for Ubuntu.
|
110
|
-
* Added new features, fixed bugs as listed for betas 1 and 2.
|
111
|
-
* Minor development-only changes:
|
112
|
-
* Added ChangeLog (this file)
|
113
|
-
* Updated development dependencies to most recent versions
|
114
|
-
* Scripted testing of supported Ruby and Ubuntu releases
|
115
|
-
|
116
|
-
-- Benjamin Oakes <hello@benjaminoakes.com> Fri, 23 Nov 2012 00:00:00 +0000
|
117
|
-
|
118
|
-
maid (0.1.3.beta.2) unstable; urgency=low
|
119
|
-
|
120
|
-
* Fixed "Trash does not expand paths". (Closes: #56)
|
121
|
-
* Fixed "XDG gives a warning about RbConfig vs Config" on Ubuntu by using
|
122
|
-
custom-built maid-xdg gem. (Closes: #53)
|
123
|
-
|
124
|
-
-- Benjamin Oakes <hello@benjaminoakes.com> Wed, 21 Nov 2012 00:00:00 +0000
|
125
|
-
|
126
|
-
maid (0.1.3.beta.1) unstable; urgency=low
|
127
|
-
|
128
|
-
* Started official support for Ubuntu.
|
129
75
|
* Fixed default trash path on Ubuntu (and possibly other Linux
|
130
76
|
distributions). (Closes: #6)
|
131
|
-
* Added ability to handle an array of filenames passed to
|
132
|
-
#16)
|
133
|
-
* Added "remove" tool for deleting files, and secure deletion.
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
* Added "
|
77
|
+
* Lloyd Philbrook: Added ability to handle an array of filenames passed to
|
78
|
+
"move", "trash". (Closes: #16)
|
79
|
+
* Lloyd Philbrook: Added "remove" tool for deleting files, and secure deletion.
|
80
|
+
(Closes: #30)
|
81
|
+
* Lloyd Philbrook: Added "remove_over" option for "trash" which can delete
|
82
|
+
files if they're over a size threshold. (Closes: #32)
|
83
|
+
* Lloyd Philbrook: Added "sync" tool for using rsync. (Closes: #17)
|
84
|
+
* Larry Lv: Added "mkdir" tool for making directories ("folders"). (Closes: #20)
|
85
|
+
* Larry Lv: The "find" tool acts like "dir" when no block is given. (Closes: #27)
|
138
86
|
* Added "created_at" tool for looking up creation time. (Closes: #21)
|
139
87
|
* Added "modified_at" tool for looking up modification time. (Closes: #13)
|
140
|
-
* Renamed "last_accessed" to "accessed_at", deprecated
|
141
|
-
(Closes: #22)
|
88
|
+
* Lloyd Philbrook: Renamed "last_accessed" to "accessed_at", deprecated
|
89
|
+
"last_accessed". (Closes: #22)
|
142
90
|
* Deprecated "git_piston" in favor of SparkleShare. (Closes: #18)
|
143
91
|
* Updated README and samples. (Closes: #38)
|
144
92
|
* Updated dependencies. (Closes: #5)
|
93
|
+
* Fixed "Trash does not expand paths". (Closes: #56)
|
94
|
+
* Fixed "XDG gives a warning about RbConfig vs Config" on Ubuntu by using
|
95
|
+
custom-built maid-xdg gem. (Closes: #53)
|
96
|
+
* Minor development-only changes:
|
97
|
+
* Added ChangeLog (this file)
|
98
|
+
* Updated development dependencies to most recent versions
|
99
|
+
* Scripted testing of supported Ruby and Ubuntu releases
|
145
100
|
|
146
101
|
-- Benjamin Oakes <hello@benjaminoakes.com> Mon, 15 Oct 2012 00:00:00 +0000
|
147
102
|
|
data/README.md
CHANGED
@@ -1,6 +1,11 @@
|
|
1
1
|
# Maid
|
2
2
|
|
3
|
-
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/maid.png)](http://badge.fury.io/rb/maid)
|
4
|
+
[![Build Status](https://secure.travis-ci.org/benjaminoakes/maid.png)](http://travis-ci.org/benjaminoakes/maid)
|
5
|
+
[![Dependency Status](https://gemnasium.com/benjaminoakes/maid.png)](https://gemnasium.com/benjaminoakes/maid)
|
6
|
+
[![Code Climate](https://codeclimate.com/github/benjaminoakes/maid.png)](https://codeclimate.com/github/benjaminoakes/maid)
|
7
|
+
|
8
|
+
**Be lazy!** Let Maid clean up after you, based on rules you define.
|
4
9
|
|
5
10
|
[Installation](#installation)
|
6
11
|
| [Tutorial](#tutorial)
|
@@ -43,10 +48,6 @@ This project wouldn't be where it is today without its users and contributors.
|
|
43
48
|
|
44
49
|
### For Developers
|
45
50
|
|
46
|
-
[![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/benjaminoakes/maid)
|
47
|
-
[![Build Status](https://secure.travis-ci.org/benjaminoakes/maid.png)](http://travis-ci.org/benjaminoakes/maid)
|
48
|
-
[![Dependency Status](https://gemnasium.com/benjaminoakes/maid.png)](https://gemnasium.com/benjaminoakes/maid)
|
49
|
-
|
50
51
|
* Address a `TODO` or `FIXME` in the code.
|
51
52
|
* Complete an issue (easy ones [are labelled](https://github.com/benjaminoakes/maid/issues?labels=difficulty-1&page=1&state=open), and issues for future releases are [grouped by milestone](https://github.com/benjaminoakes/maid/issues/milestones)).
|
52
53
|
* **Working on an issue?** Please leave a comment so others know.
|
data/Vagrantfile
CHANGED
@@ -1,10 +1,15 @@
|
|
1
1
|
# -*- mode: ruby -*-
|
2
2
|
# vi: set ft=ruby :
|
3
3
|
|
4
|
-
Vagrant
|
4
|
+
Vagrant.configure('2') do |config|
|
5
5
|
# See also: `script/vagrant-test`, `script/vagrant-test-all`
|
6
|
-
config.vm.box
|
6
|
+
config.vm.box = ENV['MAID_TARGET_BOX'] || 'precise64'
|
7
7
|
config.vm.box_url = 'http://files.vagrantup.com/precise64.box' if 'precise64' == config.vm.box
|
8
8
|
|
9
|
+
config.vm.provider :virtualbox do |vb|
|
10
|
+
# Maid has very low system requirements
|
11
|
+
vb.customize ['modifyvm', :id, '--cpus', 1, '--memory', 192]
|
12
|
+
end
|
13
|
+
|
9
14
|
config.vm.provision(:shell, :path => 'script/vagrant-provision', :args => ENV['MAID_TARGET_RUBY'] || '1.9.3')
|
10
15
|
end
|
data/lib/maid/app.rb
CHANGED
@@ -11,12 +11,17 @@ class Maid::App < Thor
|
|
11
11
|
end
|
12
12
|
|
13
13
|
desc 'clean', 'Clean based on rules'
|
14
|
-
method_option :rules,
|
15
|
-
method_option :noop,
|
16
|
-
method_option :
|
14
|
+
method_option :rules, :type => :string, :aliases => %w(-r)
|
15
|
+
method_option :noop, :type => :boolean, :aliases => %w(-n --dry-run)
|
16
|
+
method_option :force, :type => :boolean, :aliases => %w(-f)
|
17
|
+
method_option :silent, :type => :boolean, :aliases => %w(-s)
|
17
18
|
def clean
|
18
19
|
maid = Maid::Maid.new(maid_options(options))
|
19
20
|
|
21
|
+
unless options.noop? || options.force?
|
22
|
+
warn 'Running "maid clean" without a flag is deprecated. Please use "maid clean --noop" or "maid clean --force".'
|
23
|
+
end
|
24
|
+
|
20
25
|
if Maid::TrashMigration.needed?
|
21
26
|
migrate_trash
|
22
27
|
return
|
data/lib/maid/maid.rb
CHANGED
@@ -10,7 +10,12 @@ require 'xdg'
|
|
10
10
|
class Maid::Maid
|
11
11
|
DEFAULTS = {
|
12
12
|
:progname => 'Maid',
|
13
|
+
|
13
14
|
:log_device => File.expand_path('~/.maid/maid.log'),
|
15
|
+
# We don't want the log files to grow without check, but 50 MB doesn't seem too bad. (We're going with a larger size just for safety right now.)
|
16
|
+
:log_shift_age => 5,
|
17
|
+
:log_shift_size => 10 * 1_048_576, # 10 * 1 MB
|
18
|
+
|
14
19
|
:rules_path => File.expand_path('~/.maid/rules.rb'),
|
15
20
|
:file_options => { :noop => false }, # for `FileUtils`
|
16
21
|
}.freeze
|
@@ -31,7 +36,7 @@ class Maid::Maid
|
|
31
36
|
@logger = unless options[:logger]
|
32
37
|
@log_device = options[:log_device]
|
33
38
|
FileUtils.mkdir_p(File.dirname(@log_device)) unless @log_device.kind_of?(IO)
|
34
|
-
Logger.new(@log_device)
|
39
|
+
@logger = Logger.new(@log_device, options[:log_shift_age], options[:log_shift_size])
|
35
40
|
else
|
36
41
|
options[:logger]
|
37
42
|
end
|
@@ -98,7 +103,7 @@ class Maid::Maid
|
|
98
103
|
if supported_command?(command)
|
99
104
|
%x(#{ command })
|
100
105
|
else
|
101
|
-
raise
|
106
|
+
raise NotImplementedError, "Unsupported system command: #{ command.inspect }"
|
102
107
|
end
|
103
108
|
end
|
104
109
|
|
data/lib/maid/platform.rb
CHANGED
@@ -13,5 +13,16 @@ module Maid::Platform
|
|
13
13
|
def osx?
|
14
14
|
!!(host_os =~ /darwin/i)
|
15
15
|
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
# Commands based on OS type
|
20
|
+
class Commands
|
21
|
+
class << self
|
22
|
+
# logicaly decides which locate command to use
|
23
|
+
def locate
|
24
|
+
Maid::Platform.linux? ? 'locate' : 'mdfind -name'
|
25
|
+
end
|
26
|
+
end
|
16
27
|
end
|
17
28
|
end
|
data/lib/maid/tools.rb
CHANGED
@@ -1,7 +1,11 @@
|
|
1
|
-
require '
|
1
|
+
require 'digest/md5'
|
2
2
|
require 'find'
|
3
|
+
require 'fileutils'
|
3
4
|
require 'time'
|
4
5
|
|
6
|
+
require 'mime/types'
|
7
|
+
require 'zip/zip'
|
8
|
+
|
5
9
|
# These "tools" are methods available in the Maid DSL.
|
6
10
|
#
|
7
11
|
# In general, methods are expected to:
|
@@ -208,6 +212,15 @@ module Maid::Tools
|
|
208
212
|
sort
|
209
213
|
end
|
210
214
|
|
215
|
+
# Give only files matching the given glob.
|
216
|
+
#
|
217
|
+
# This is the same as #dir but only includes actual files (no directories or symlinks).
|
218
|
+
#
|
219
|
+
def files(globs)
|
220
|
+
dir(globs).
|
221
|
+
select { |f| File.file?(f) }
|
222
|
+
end
|
223
|
+
|
211
224
|
# Create a directory and all of its parent directories.
|
212
225
|
#
|
213
226
|
# The path of the created directory is returned, which allows for chaining (see examples).
|
@@ -270,13 +283,13 @@ module Maid::Tools
|
|
270
283
|
|
271
284
|
# [Mac OS X] Use Spotlight to locate all files matching the given filename.
|
272
285
|
#
|
273
|
-
# [Ubuntu]
|
286
|
+
# [Ubuntu] Use `locate` to locate all files matching the given filename.
|
274
287
|
#
|
275
288
|
# ## Examples
|
276
289
|
#
|
277
290
|
# locate('foo.zip') # => ['/a/foo.zip', '/b/foo.zip']
|
278
291
|
def locate(name)
|
279
|
-
cmd("
|
292
|
+
cmd("#{Maid::Platform::Commands.locate} #{ sh_escape(name) }").split("\n")
|
280
293
|
end
|
281
294
|
|
282
295
|
# [Mac OS X] Use Spotlight metadata to determine the site from which a file was downloaded.
|
@@ -285,9 +298,46 @@ module Maid::Tools
|
|
285
298
|
#
|
286
299
|
# downloaded_from('foo.zip') # => ['http://www.site.com/foo.zip', 'http://www.site.com/']
|
287
300
|
def downloaded_from(path)
|
288
|
-
|
289
|
-
|
290
|
-
|
301
|
+
mdls_to_array(path, 'kMDItemWhereFroms')
|
302
|
+
end
|
303
|
+
|
304
|
+
# Find all duplicate files in the given globs.
|
305
|
+
#
|
306
|
+
# Globs are expanded as in #dir, then all non-files are filtered out. The remaining
|
307
|
+
# files are compared by size, and non-dupes are filtered out. The remaining candidates
|
308
|
+
# are then compared by checksum. Dupes are returned as an array of arrays.
|
309
|
+
#
|
310
|
+
# ## Examples
|
311
|
+
#
|
312
|
+
# dupes_in('~/{Downloads,Desktop}/*') # => [
|
313
|
+
# ['~/Downloads/foo.zip', '~/Downloads/foo (1).zip'],
|
314
|
+
# ['~/Desktop/bar.txt', '~/Desktop/bar copy.txt']
|
315
|
+
# ]
|
316
|
+
#
|
317
|
+
# Keep the dupe with the shortest name (ideal for `foo (1).zip` and `foo copy.zip` style dupes):
|
318
|
+
#
|
319
|
+
# dupes_in('~/Downloads/*').each do |dupes|
|
320
|
+
# trash dupes.sort_by { |p| File.basename(p).length }[1..-1]
|
321
|
+
# end
|
322
|
+
#
|
323
|
+
# Keep the oldest dupe:
|
324
|
+
#
|
325
|
+
# dupes_in('~/Desktop/*', '~/Downloads/*').each do |dupes|
|
326
|
+
# trash dupes.sort_by { |p| File.mtime(p) }[1..-1]
|
327
|
+
# end
|
328
|
+
#
|
329
|
+
def dupes_in(globs)
|
330
|
+
dupes = []
|
331
|
+
files(globs). # Start by filtering out non-files
|
332
|
+
group_by { |f| size_of(f) }. # ... then grouping by size, since that's fast
|
333
|
+
reject { |s, p| p.length < 2 }. # ... and filter out any non-dupes
|
334
|
+
map do |size, candidates|
|
335
|
+
dupes += candidates.
|
336
|
+
group_by { |p| checksum_of(p) }. # Now group our candidates by a slower checksum calculation
|
337
|
+
reject { |c, p| p.length < 2 }. # ... and filter out any non-dupes
|
338
|
+
values
|
339
|
+
end
|
340
|
+
dupes
|
291
341
|
end
|
292
342
|
|
293
343
|
# [Mac OS X] Use Spotlight metadata to determine audio length.
|
@@ -303,10 +353,10 @@ module Maid::Tools
|
|
303
353
|
#
|
304
354
|
# ## Examples
|
305
355
|
#
|
306
|
-
# zipfile_contents('foo.zip') # => ['foo
|
356
|
+
# zipfile_contents('foo.zip') # => ['foo.exe', 'README.txt', 'subdir/anything.txt']
|
307
357
|
def zipfile_contents(path)
|
308
|
-
|
309
|
-
|
358
|
+
# It might be nice to use `glob` from `Zip::ZipFileSystem`, but it seems buggy. (Subdirectories aren't included.)
|
359
|
+
Zip::ZipFile.foreach(path).map { |entry| entry.name }.sort
|
310
360
|
end
|
311
361
|
|
312
362
|
# Calculate disk usage of a given path in kilobytes.
|
@@ -370,6 +420,24 @@ module Maid::Tools
|
|
370
420
|
File.mtime(expand(path))
|
371
421
|
end
|
372
422
|
|
423
|
+
# Get the size of a file.
|
424
|
+
#
|
425
|
+
# ## Examples
|
426
|
+
#
|
427
|
+
# size_of('foo.zip') # => 2193
|
428
|
+
def size_of(path)
|
429
|
+
File.size(path)
|
430
|
+
end
|
431
|
+
|
432
|
+
# Get a checksum for a file.
|
433
|
+
#
|
434
|
+
# ## Examples
|
435
|
+
#
|
436
|
+
# checksum_of('foo.zip') # => "ae8dbb203dfd560158083e5de90969c2"
|
437
|
+
def checksum_of(path)
|
438
|
+
Digest::MD5.hexdigest(File.read(path))
|
439
|
+
end
|
440
|
+
|
373
441
|
# @deprecated
|
374
442
|
#
|
375
443
|
# Pull and push the `git` repository at the given path.
|
@@ -439,6 +507,75 @@ module Maid::Tools
|
|
439
507
|
log("Fired sync from #{ sh_escape(from) } to #{ sh_escape(to) }. STDOUT:\n\n#{ stdout }")
|
440
508
|
end
|
441
509
|
|
510
|
+
# [Mac OS X] Use Spotlight metadata to determine which content types a file has.
|
511
|
+
#
|
512
|
+
# ## Examples
|
513
|
+
#
|
514
|
+
# spotlight_content_types('foo.zip') # => ['public.zip-archive', 'public.archive']
|
515
|
+
def spotlight_content_types(path)
|
516
|
+
mdls_to_array(path, 'kMDItemContentTypeTree')
|
517
|
+
end
|
518
|
+
|
519
|
+
# Get the content types of a path.
|
520
|
+
#
|
521
|
+
# Content types can be MIME types, Internet media types or Spotlight content types (OS X only).
|
522
|
+
#
|
523
|
+
# ## Examples
|
524
|
+
#
|
525
|
+
# content_types('foo.zip') # => ["public.zip-archive", "com.pkware.zip-archive", "public.archive", "application/zip", "application"]
|
526
|
+
# content_types('bar.jpg') # => ["public.jpeg", "public.image", "image/jpeg", "image"]
|
527
|
+
def content_types(path)
|
528
|
+
[spotlight_content_types(path), mime_type(path), media_type(path)].flatten
|
529
|
+
end
|
530
|
+
|
531
|
+
# Get the MIME type of the file.
|
532
|
+
#
|
533
|
+
# ## Examples
|
534
|
+
#
|
535
|
+
# mime_type('bar.jpg') # => "image/jpeg"
|
536
|
+
def mime_type(path)
|
537
|
+
type = MIME::Types.type_for(path)[0]
|
538
|
+
[type.media_type, type.sub_type].join('/')
|
539
|
+
end
|
540
|
+
|
541
|
+
# Get the Internet media type of the file.
|
542
|
+
#
|
543
|
+
# In other words, the first part of `mime_type`.
|
544
|
+
#
|
545
|
+
# ## Examples
|
546
|
+
#
|
547
|
+
# media_type('bar.jpg') # => "image"
|
548
|
+
def media_type(path)
|
549
|
+
MIME::Types.type_for(path)[0].media_type
|
550
|
+
end
|
551
|
+
|
552
|
+
# Filter an array by content types.
|
553
|
+
#
|
554
|
+
# Content types can be MIME types, internet media types or Spotlight content types (OS X only).
|
555
|
+
#
|
556
|
+
# If you need your rules to work on multiple platforms, it's recommended to avoid using Spotlight content types.
|
557
|
+
#
|
558
|
+
# ## Examples
|
559
|
+
#
|
560
|
+
# ### Using media types
|
561
|
+
#
|
562
|
+
# where_content_type(dir('~/Downloads/*'), 'video')
|
563
|
+
# where_content_type(dir('~/Downloads/*'), ['image', 'audio'])
|
564
|
+
#
|
565
|
+
# ### Using MIME types
|
566
|
+
#
|
567
|
+
# where_content_type(dir('~/Downloads/*'), 'image/jpeg')
|
568
|
+
#
|
569
|
+
# ### Using Spotlight content types
|
570
|
+
#
|
571
|
+
# Less portable, but richer data in some cases.
|
572
|
+
#
|
573
|
+
# where_content_type(dir('~/Downloads/*'), 'public.image')
|
574
|
+
def where_content_type(paths, filter_types)
|
575
|
+
filter_types = Array(filter_types)
|
576
|
+
Array(paths).select { |p| !(filter_types & content_types(p)).empty? }
|
577
|
+
end
|
578
|
+
|
442
579
|
private
|
443
580
|
|
444
581
|
def sh_escape(array)
|
@@ -460,4 +597,12 @@ module Maid::Tools
|
|
460
597
|
def expand_all(paths)
|
461
598
|
Array(paths).map { |path| expand(path) }
|
462
599
|
end
|
600
|
+
|
601
|
+
def mdls_to_array(path, attribute)
|
602
|
+
return [] unless Maid::Platform.osx?
|
603
|
+
raw = cmd("mdls -raw -name #{attribute} #{ sh_escape(path) }")
|
604
|
+
return [] if raw.empty?
|
605
|
+
clean = raw[1, raw.length - 2]
|
606
|
+
clean.split(/,\s+/).map { |s| t = s.strip; t[1, t.length - 2] }
|
607
|
+
end
|
463
608
|
end
|
data/lib/maid/version.rb
CHANGED
data/maid.gemspec
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
$:.push File.expand_path('../lib', __FILE__)
|
3
3
|
require 'maid/version'
|
4
|
-
require 'maid/platform'
|
5
4
|
|
6
5
|
Gem::Specification.new do |s|
|
7
6
|
s.name = 'maid'
|
@@ -18,19 +17,25 @@ Gem::Specification.new do |s|
|
|
18
17
|
|
19
18
|
# Strategy: if possible, use ranges (so there are fewer chances of version conflicts)
|
20
19
|
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.
|
20
|
+
s.add_dependency('thor', '>= 0.14.0', '< 0.19.0')
|
22
21
|
s.add_dependency('deprecated', '~> 3.0.0')
|
23
|
-
s.add_dependency('
|
22
|
+
s.add_dependency('mime-types', '~> 1.21') # TODO: loosen version restrictions based on testing
|
23
|
+
s.add_dependency('ohai', '>= 6.14.0', '< 6.18.0')
|
24
|
+
s.add_dependency('rubyzip', '>= 0.5.7', '< 0.10.0')
|
24
25
|
s.add_dependency('xdg', '~> 2.2.3') # previous versions had bugs
|
26
|
+
# TODO: use one of these two gems instead of `mdfind`. **But** They have to work on Linux as well.
|
27
|
+
#
|
28
|
+
# s.add_dependency('mac-spotlight', '~> 0.0.4')
|
29
|
+
# s.add_dependency('spotlight', '~> 0.0.6')
|
25
30
|
|
26
31
|
# Strategy: specific versions (since they're just for development)
|
27
32
|
s.add_development_dependency('fakefs', '~> 0.4.2')
|
28
33
|
s.add_development_dependency('guard', '~> 1.6.2')
|
29
|
-
s.add_development_dependency('guard-rspec', '~> 2.
|
34
|
+
s.add_development_dependency('guard-rspec', '~> 2.5.0')
|
30
35
|
s.add_development_dependency('rake', '~> 10.0.3')
|
31
36
|
s.add_development_dependency('redcarpet', '~> 2.2.2') # Soft dependency of `yard`
|
32
|
-
s.add_development_dependency('rspec', '~> 2.
|
33
|
-
s.add_development_dependency('timecop', '~> 0.
|
37
|
+
s.add_development_dependency('rspec', '~> 2.13.0')
|
38
|
+
s.add_development_dependency('timecop', '~> 0.6.1')
|
34
39
|
s.add_development_dependency('yard', '~> 0.8.4')
|
35
40
|
|
36
41
|
# In Vagrant, polling won't cross over the OS boundary if you develop in the host OS but run your tests in the
|
@@ -41,8 +46,8 @@ Gem::Specification.new do |s|
|
|
41
46
|
s.add_development_dependency('rb-inotify', '~> 0.9.0')
|
42
47
|
s.add_development_dependency('rb-fsevent', '~> 0.9.2')
|
43
48
|
|
44
|
-
s.files = `git ls-files`.split("\
|
45
|
-
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\
|
46
|
-
s.executables = `git ls-files -- bin/*`.split("\
|
49
|
+
s.files = `git ls-files -z`.split("\0")
|
50
|
+
s.test_files = `git ls-files -z -- {test,spec,features}/*`.split("\0")
|
51
|
+
s.executables = `git ls-files -z -- bin/*`.split("\0").map{ |f| File.basename(f) }
|
47
52
|
s.require_paths = %w(lib)
|
48
53
|
end
|
data/spec/dependency_spec.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
require 'logger'
|
2
|
+
require 'mime/types'
|
2
3
|
require 'ohai'
|
3
4
|
require 'rbconfig'
|
4
5
|
require 'stringio'
|
5
6
|
require 'xdg'
|
7
|
+
require 'zip/zip'
|
6
8
|
|
7
9
|
# > What is Dependency Testing?
|
8
10
|
# >
|
@@ -11,6 +13,10 @@ require 'xdg'
|
|
11
13
|
# >
|
12
14
|
# > -- http://sqa.fyicenter.com/FAQ/Software-QA-Testing/What_is_Dependency_Testing_.html
|
13
15
|
describe 'Dependency expectations' do
|
16
|
+
before do
|
17
|
+
@file_fixtures_path = File.expand_path(File.dirname(__FILE__) + '/fixtures/files/')
|
18
|
+
end
|
19
|
+
|
14
20
|
describe Logger do
|
15
21
|
# Depending on the situation, `Logger` might have been overwritten to have a different interface. (I'm looking at you, Rails.)
|
16
22
|
it 'logs with the expected interface' do
|
@@ -22,6 +28,16 @@ describe 'Dependency expectations' do
|
|
22
28
|
end
|
23
29
|
end
|
24
30
|
|
31
|
+
describe MIME::Types do
|
32
|
+
it 'reports media types and sub types when given a path' do
|
33
|
+
types = MIME::Types.type_for('anything.jpg')
|
34
|
+
types.length.should == 1
|
35
|
+
type = types[0]
|
36
|
+
type.media_type.should == 'image'
|
37
|
+
type.sub_type.should == 'jpeg'
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
25
41
|
describe Ohai do
|
26
42
|
before do
|
27
43
|
@ohai = Ohai::System.new
|
@@ -59,4 +75,17 @@ describe 'Dependency expectations' do
|
|
59
75
|
XDG['DATA_HOME'].to_s.should match(%r{^/.*?/\.local/share$})
|
60
76
|
end
|
61
77
|
end
|
78
|
+
|
79
|
+
describe Zip::ZipFile do
|
80
|
+
it 'makes entries available with foreach' do
|
81
|
+
Zip::ZipFile.foreach("#@file_fixtures_path/foo.zip").map { |entry| entry.name }.sort.
|
82
|
+
should == %w(README.txt foo.exe subdir/anything.txt)
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'supports UTF-8 filenames' do
|
86
|
+
# Filename is a Japanese character
|
87
|
+
Zip::ZipFile.foreach("#@file_fixtures_path/\343\201\225.zip").map { |entry| entry.name }.
|
88
|
+
should == %w(anything.txt)
|
89
|
+
end
|
90
|
+
end
|
62
91
|
end
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/spec/lib/maid/app_spec.rb
CHANGED
@@ -43,22 +43,30 @@ module Maid
|
|
43
43
|
@app.clean
|
44
44
|
end
|
45
45
|
|
46
|
-
it 'should
|
46
|
+
it 'should clean when --force is specified' do
|
47
47
|
@maid.should_receive(:clean)
|
48
|
-
|
48
|
+
App.start(['clean', '--force'])
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'should issue deprecation notice when called without option, but still clean' do
|
52
|
+
@maid.should_receive(:clean).twice
|
53
|
+
capture_stderr { App.start(['clean']) }.string.should match(/deprecated/)
|
54
|
+
capture_stderr { App.start(['clean', '--silent']) }.string.should match(/deprecated/)
|
49
55
|
end
|
50
56
|
|
51
57
|
it 'should not be silent if not given the --silent option' do
|
52
|
-
capture_stdout { App.start(['clean']) }.string.should_not == ''
|
58
|
+
capture_stdout { App.start(['clean', '--force']) }.string.should_not == ''
|
53
59
|
end
|
54
60
|
|
55
61
|
it 'should be silent if given the --silent option' do
|
56
62
|
# TODO: It might even make sense to wrap `maid.clean` in `capture_stdout { ... }`
|
57
|
-
capture_stdout { App.start(['clean', '--silent']) }.string.should == ''
|
63
|
+
capture_stdout { App.start(['clean', '--noop', '--silent']) }.string.should == ''
|
64
|
+
capture_stdout { App.start(['clean', '--force', '--silent']) }.string.should == ''
|
58
65
|
end
|
59
66
|
|
60
67
|
it 'should complain about a MISSPELLED option' do
|
61
68
|
capture_stderr { App.start(['clean', '--slient']) }.string.should match(/Unknown/)
|
69
|
+
capture_stderr { App.start(['clean', '--noop', '--slient']) }.string.should match(/Unknown/)
|
62
70
|
end
|
63
71
|
|
64
72
|
it 'should complain about an undefined task' do
|
@@ -77,7 +85,7 @@ module Maid
|
|
77
85
|
end
|
78
86
|
|
79
87
|
it 'is mapped as --version' do
|
80
|
-
|
88
|
+
App.start(['--version']).should == @app.version
|
81
89
|
end
|
82
90
|
|
83
91
|
context 'with the "long" option' do
|
data/spec/lib/maid/maid_spec.rb
CHANGED
@@ -10,16 +10,26 @@ module Maid
|
|
10
10
|
|
11
11
|
describe '.new' do
|
12
12
|
it 'should set up a logger with the default path' do
|
13
|
-
Logger.should_receive(:new).with(Maid::DEFAULTS[:log_device])
|
13
|
+
Logger.should_receive(:new).with(Maid::DEFAULTS[:log_device], anything, anything)
|
14
14
|
Maid.new
|
15
15
|
end
|
16
16
|
|
17
|
-
it 'should set up a logger with the given path,
|
17
|
+
it 'should set up a logger with the given path, when provided' do
|
18
18
|
log_device = '/var/log/maid.log'
|
19
|
-
Logger.should_receive(:new).with(log_device)
|
19
|
+
Logger.should_receive(:new).with(log_device, anything, anything)
|
20
20
|
Maid.new(:log_device => log_device)
|
21
21
|
end
|
22
22
|
|
23
|
+
it 'should rotate the log with the default settings' do
|
24
|
+
Logger.should_receive(:new).with(anything, Maid::DEFAULTS[:log_shift_age], Maid::DEFAULTS[:log_shift_size])
|
25
|
+
Maid.new
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should rotate the log with the given settings, when provided' do
|
29
|
+
Logger.should_receive(:new).with(anything, 42, 1_000_000)
|
30
|
+
Maid.new(:log_shift_age => 42, :log_shift_size => 1_000_000)
|
31
|
+
end
|
32
|
+
|
23
33
|
it 'should make the log directory in case it does not exist' do
|
24
34
|
FileUtils.should_receive(:mkdir_p).with('/home/username/log')
|
25
35
|
Maid.new(:log_device => '/home/username/log/maid.log')
|
@@ -189,11 +199,11 @@ module Maid
|
|
189
199
|
end
|
190
200
|
|
191
201
|
it 'should report `not-a-real-command` as not being a supported command' do
|
192
|
-
lambda { @maid.cmd('not-a-real-command arg1 arg2') }.should raise_error(
|
202
|
+
lambda { @maid.cmd('not-a-real-command arg1 arg2') }.should raise_error(NotImplementedError)
|
193
203
|
end
|
194
204
|
|
195
205
|
it 'should report `echo` as a real command' do
|
196
|
-
lambda { @maid.cmd('echo .') }.should_not raise_error(
|
206
|
+
lambda { @maid.cmd('echo .') }.should_not raise_error(NotImplementedError)
|
197
207
|
end
|
198
208
|
end
|
199
209
|
end
|
@@ -25,6 +25,10 @@ module Maid
|
|
25
25
|
it 'is not identified as OS X' do
|
26
26
|
subject.osx?.should be_false
|
27
27
|
end
|
28
|
+
|
29
|
+
it 'locate is "locate"' do
|
30
|
+
Platform::Commands.locate.should match(/locate/)
|
31
|
+
end
|
28
32
|
end
|
29
33
|
|
30
34
|
context 'when running on Mac OS X' do
|
@@ -39,6 +43,10 @@ module Maid
|
|
39
43
|
it 'is identified as OS X' do
|
40
44
|
subject.osx?.should be_true
|
41
45
|
end
|
46
|
+
|
47
|
+
it 'locate is "mdfind"' do
|
48
|
+
Platform::Commands.locate.should match(/mdfind/)
|
49
|
+
end
|
42
50
|
end
|
43
51
|
end
|
44
52
|
end
|
data/spec/lib/maid/tools_spec.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# encoding: utf-8
|
1
2
|
require 'spec_helper'
|
2
3
|
|
3
4
|
module Maid
|
@@ -188,7 +189,7 @@ module Maid
|
|
188
189
|
end
|
189
190
|
|
190
191
|
it 'should handle multiple paths' do
|
191
|
-
second_src_file =
|
192
|
+
second_src_file = "#@src_dir/bar.zip"
|
192
193
|
FileUtils.touch(second_src_file)
|
193
194
|
@src_files = [@src_file, second_src_file]
|
194
195
|
|
@@ -250,6 +251,56 @@ module Maid
|
|
250
251
|
end
|
251
252
|
end
|
252
253
|
|
254
|
+
describe '#files' do
|
255
|
+
before do
|
256
|
+
@file = (@dir = "#@home/Downloads") + '/foo.zip'
|
257
|
+
FileUtils.mkdir_p(@dir)
|
258
|
+
FileUtils.mkdir(@dir + '/notfile')
|
259
|
+
end
|
260
|
+
|
261
|
+
it 'lists only files in a directory' do
|
262
|
+
FileUtils.touch(@file)
|
263
|
+
@maid.files('~/Downloads/*.zip').should == [@file]
|
264
|
+
end
|
265
|
+
|
266
|
+
it 'lists multiple files in alphabetical order' do
|
267
|
+
# It doesn't occur with `FakeFS` as far as I can tell, but Ubuntu (and possibly OS X) can give the results out
|
268
|
+
# of lexical order. That makes using the `dry-run` output difficult to use.
|
269
|
+
Dir.stub(:glob) { %w(/home/foo/b.zip /home/foo/a.zip /home/foo/c.zip) }
|
270
|
+
@maid.dir('~/Downloads/*.zip').should == %w(/home/foo/a.zip /home/foo/b.zip /home/foo/c.zip)
|
271
|
+
end
|
272
|
+
|
273
|
+
context 'with multiple files' do
|
274
|
+
before do
|
275
|
+
@other_file = "#@dir/qux.tgz"
|
276
|
+
FileUtils.touch(@file)
|
277
|
+
FileUtils.touch(@other_file)
|
278
|
+
end
|
279
|
+
|
280
|
+
it 'list files in all provided globs' do
|
281
|
+
@maid.dir(%w(~/Downloads/*.tgz ~/Downloads/*.zip)).should == [@file, @other_file]
|
282
|
+
end
|
283
|
+
|
284
|
+
it 'lists files when using regexp-like glob patterns' do
|
285
|
+
@maid.dir('~/Downloads/*.{tgz,zip}').should == [@file, @other_file]
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
context 'with multiple directories' do
|
290
|
+
before do
|
291
|
+
@other_file = "#@home/Desktop/bar.zip"
|
292
|
+
FileUtils.touch(@file)
|
293
|
+
FileUtils.mkdir_p(File.dirname(@other_file))
|
294
|
+
FileUtils.mkdir(@home + '/Desktop/notfile')
|
295
|
+
FileUtils.touch(@other_file)
|
296
|
+
end
|
297
|
+
|
298
|
+
it 'lists files in directories when using regexp-like glob patterns' do
|
299
|
+
@maid.dir('~/{Desktop,Downloads}/*.zip').should == [@other_file, @file]
|
300
|
+
end
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
253
304
|
describe '#mkdir' do
|
254
305
|
it 'should create a directory successfully' do
|
255
306
|
@maid.mkdir('~/Downloads/Music/Pink.Floyd')
|
@@ -301,6 +352,10 @@ module Maid
|
|
301
352
|
end
|
302
353
|
|
303
354
|
describe '#downloaded_from' do
|
355
|
+
before do
|
356
|
+
Platform.stub(:osx?) { true }
|
357
|
+
end
|
358
|
+
|
304
359
|
it 'should determine the download site' do
|
305
360
|
@maid.should_receive(:cmd).and_return(%((\n "http://www.site.com/foo.zip",\n"http://www.site.com/"\n)))
|
306
361
|
@maid.downloaded_from('foo.zip').should == ['http://www.site.com/foo.zip', 'http://www.site.com/']
|
@@ -316,8 +371,11 @@ module Maid
|
|
316
371
|
|
317
372
|
describe '#zipfile_contents' do
|
318
373
|
it 'should inspect the contents of a .zip file' do
|
319
|
-
|
320
|
-
|
374
|
+
Zip::ZipFile.stub(:foreach) do
|
375
|
+
[mock(:name => 'foo.exe'), mock(:name => 'README.txt'), mock(:name => 'subdir/anything.txt')]
|
376
|
+
end
|
377
|
+
|
378
|
+
@maid.zipfile_contents('foo.zip').should == ['README.txt', 'foo.exe', 'subdir/anything.txt']
|
321
379
|
end
|
322
380
|
end
|
323
381
|
|
@@ -378,6 +436,28 @@ module Maid
|
|
378
436
|
end
|
379
437
|
end
|
380
438
|
|
439
|
+
describe '#size_of' do
|
440
|
+
before do
|
441
|
+
@file = '~/foo.zip'
|
442
|
+
end
|
443
|
+
|
444
|
+
it 'should give the size of the file' do
|
445
|
+
File.should_receive(:size).with(@file).and_return(42)
|
446
|
+
@maid.size_of(@file).should == 42
|
447
|
+
end
|
448
|
+
end
|
449
|
+
|
450
|
+
describe '#checksum_of' do
|
451
|
+
before do
|
452
|
+
@file = '~/test.txt'
|
453
|
+
end
|
454
|
+
|
455
|
+
it 'should return the checksum of the file' do
|
456
|
+
File.should_receive(:read).with(@file).and_return('contents')
|
457
|
+
@maid.checksum_of(@file).should == Digest::MD5.hexdigest('contents')
|
458
|
+
end
|
459
|
+
end
|
460
|
+
|
381
461
|
describe '#git_piston' do
|
382
462
|
it 'is deprecated' do
|
383
463
|
@maid.should have_deprecated_method(:git_piston)
|
@@ -431,4 +511,52 @@ module Maid
|
|
431
511
|
end
|
432
512
|
end
|
433
513
|
end
|
514
|
+
|
515
|
+
describe Tools, :fakefs => false do
|
516
|
+
let(:file_fixtures_path) { File.expand_path(File.dirname(__FILE__) + '../../../fixtures/files/') }
|
517
|
+
let(:file_fixtures_glob) { "#{ file_fixtures_path }/*" }
|
518
|
+
let(:image_path) { File.join(file_fixtures_path, 'ruby.jpg') }
|
519
|
+
|
520
|
+
before do
|
521
|
+
@logger = double('Logger').as_null_object
|
522
|
+
@maid = Maid.new(:logger => @logger)
|
523
|
+
end
|
524
|
+
|
525
|
+
describe '#dupes_in' do
|
526
|
+
it 'should list duplicate files in arrays' do
|
527
|
+
dupes = @maid.dupes_in(file_fixtures_glob)
|
528
|
+
dupes.first.should be_kind_of(Array)
|
529
|
+
|
530
|
+
basenames = dupes.flatten.map { |p| File.basename(p) }
|
531
|
+
basenames.should == %w(bar.zip foo.zip)
|
532
|
+
end
|
533
|
+
end
|
534
|
+
|
535
|
+
describe '#mime_type' do
|
536
|
+
context 'given a JPEG image' do
|
537
|
+
it 'reports "image/jpeg"' do
|
538
|
+
@maid.mime_type(image_path).should == 'image/jpeg'
|
539
|
+
end
|
540
|
+
end
|
541
|
+
end
|
542
|
+
|
543
|
+
describe '#media_type' do
|
544
|
+
context 'given a JPEG image' do
|
545
|
+
it 'reports "image"' do
|
546
|
+
@maid.media_type(image_path).should == 'image'
|
547
|
+
end
|
548
|
+
end
|
549
|
+
end
|
550
|
+
|
551
|
+
describe '#where_content_type' do
|
552
|
+
context 'given "image"' do
|
553
|
+
it 'only lists the fixture JPEG' do
|
554
|
+
matches = @maid.where_content_type(@maid.dir(file_fixtures_glob), 'image')
|
555
|
+
|
556
|
+
matches.length.should == 1
|
557
|
+
matches.first.should end_with('spec/fixtures/files/ruby.jpg')
|
558
|
+
end
|
559
|
+
end
|
560
|
+
end
|
561
|
+
end
|
434
562
|
end
|
metadata
CHANGED
@@ -1,19 +1,19 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: maid
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.4.0.alpha.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: 2013-
|
12
|
+
date: 2013-07-21 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: escape
|
16
|
-
requirement: &
|
16
|
+
requirement: &10781460 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -24,10 +24,10 @@ dependencies:
|
|
24
24
|
version: 0.1.0
|
25
25
|
type: :runtime
|
26
26
|
prerelease: false
|
27
|
-
version_requirements: *
|
27
|
+
version_requirements: *10781460
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: thor
|
30
|
-
requirement: &
|
30
|
+
requirement: &10780320 !ruby/object:Gem::Requirement
|
31
31
|
none: false
|
32
32
|
requirements:
|
33
33
|
- - ! '>='
|
@@ -35,13 +35,13 @@ dependencies:
|
|
35
35
|
version: 0.14.0
|
36
36
|
- - <
|
37
37
|
- !ruby/object:Gem::Version
|
38
|
-
version: 0.
|
38
|
+
version: 0.19.0
|
39
39
|
type: :runtime
|
40
40
|
prerelease: false
|
41
|
-
version_requirements: *
|
41
|
+
version_requirements: *10780320
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
43
|
name: deprecated
|
44
|
-
requirement: &
|
44
|
+
requirement: &10779220 !ruby/object:Gem::Requirement
|
45
45
|
none: false
|
46
46
|
requirements:
|
47
47
|
- - ~>
|
@@ -49,10 +49,21 @@ dependencies:
|
|
49
49
|
version: 3.0.0
|
50
50
|
type: :runtime
|
51
51
|
prerelease: false
|
52
|
-
version_requirements: *
|
52
|
+
version_requirements: *10779220
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: mime-types
|
55
|
+
requirement: &10794980 !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
57
|
+
requirements:
|
58
|
+
- - ~>
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '1.21'
|
61
|
+
type: :runtime
|
62
|
+
prerelease: false
|
63
|
+
version_requirements: *10794980
|
53
64
|
- !ruby/object:Gem::Dependency
|
54
65
|
name: ohai
|
55
|
-
requirement: &
|
66
|
+
requirement: &10794500 !ruby/object:Gem::Requirement
|
56
67
|
none: false
|
57
68
|
requirements:
|
58
69
|
- - ! '>='
|
@@ -60,13 +71,27 @@ dependencies:
|
|
60
71
|
version: 6.14.0
|
61
72
|
- - <
|
62
73
|
- !ruby/object:Gem::Version
|
63
|
-
version: 6.
|
74
|
+
version: 6.18.0
|
75
|
+
type: :runtime
|
76
|
+
prerelease: false
|
77
|
+
version_requirements: *10794500
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: rubyzip
|
80
|
+
requirement: &10793740 !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: 0.5.7
|
86
|
+
- - <
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: 0.10.0
|
64
89
|
type: :runtime
|
65
90
|
prerelease: false
|
66
|
-
version_requirements: *
|
91
|
+
version_requirements: *10793740
|
67
92
|
- !ruby/object:Gem::Dependency
|
68
93
|
name: xdg
|
69
|
-
requirement: &
|
94
|
+
requirement: &10792860 !ruby/object:Gem::Requirement
|
70
95
|
none: false
|
71
96
|
requirements:
|
72
97
|
- - ~>
|
@@ -74,10 +99,10 @@ dependencies:
|
|
74
99
|
version: 2.2.3
|
75
100
|
type: :runtime
|
76
101
|
prerelease: false
|
77
|
-
version_requirements: *
|
102
|
+
version_requirements: *10792860
|
78
103
|
- !ruby/object:Gem::Dependency
|
79
104
|
name: fakefs
|
80
|
-
requirement: &
|
105
|
+
requirement: &10792180 !ruby/object:Gem::Requirement
|
81
106
|
none: false
|
82
107
|
requirements:
|
83
108
|
- - ~>
|
@@ -85,10 +110,10 @@ dependencies:
|
|
85
110
|
version: 0.4.2
|
86
111
|
type: :development
|
87
112
|
prerelease: false
|
88
|
-
version_requirements: *
|
113
|
+
version_requirements: *10792180
|
89
114
|
- !ruby/object:Gem::Dependency
|
90
115
|
name: guard
|
91
|
-
requirement: &
|
116
|
+
requirement: &10791120 !ruby/object:Gem::Requirement
|
92
117
|
none: false
|
93
118
|
requirements:
|
94
119
|
- - ~>
|
@@ -96,21 +121,21 @@ dependencies:
|
|
96
121
|
version: 1.6.2
|
97
122
|
type: :development
|
98
123
|
prerelease: false
|
99
|
-
version_requirements: *
|
124
|
+
version_requirements: *10791120
|
100
125
|
- !ruby/object:Gem::Dependency
|
101
126
|
name: guard-rspec
|
102
|
-
requirement: &
|
127
|
+
requirement: &10790520 !ruby/object:Gem::Requirement
|
103
128
|
none: false
|
104
129
|
requirements:
|
105
130
|
- - ~>
|
106
131
|
- !ruby/object:Gem::Version
|
107
|
-
version: 2.
|
132
|
+
version: 2.5.0
|
108
133
|
type: :development
|
109
134
|
prerelease: false
|
110
|
-
version_requirements: *
|
135
|
+
version_requirements: *10790520
|
111
136
|
- !ruby/object:Gem::Dependency
|
112
137
|
name: rake
|
113
|
-
requirement: &
|
138
|
+
requirement: &10789880 !ruby/object:Gem::Requirement
|
114
139
|
none: false
|
115
140
|
requirements:
|
116
141
|
- - ~>
|
@@ -118,10 +143,10 @@ dependencies:
|
|
118
143
|
version: 10.0.3
|
119
144
|
type: :development
|
120
145
|
prerelease: false
|
121
|
-
version_requirements: *
|
146
|
+
version_requirements: *10789880
|
122
147
|
- !ruby/object:Gem::Dependency
|
123
148
|
name: redcarpet
|
124
|
-
requirement: &
|
149
|
+
requirement: &10788600 !ruby/object:Gem::Requirement
|
125
150
|
none: false
|
126
151
|
requirements:
|
127
152
|
- - ~>
|
@@ -129,32 +154,32 @@ dependencies:
|
|
129
154
|
version: 2.2.2
|
130
155
|
type: :development
|
131
156
|
prerelease: false
|
132
|
-
version_requirements: *
|
157
|
+
version_requirements: *10788600
|
133
158
|
- !ruby/object:Gem::Dependency
|
134
159
|
name: rspec
|
135
|
-
requirement: &
|
160
|
+
requirement: &10787920 !ruby/object:Gem::Requirement
|
136
161
|
none: false
|
137
162
|
requirements:
|
138
163
|
- - ~>
|
139
164
|
- !ruby/object:Gem::Version
|
140
|
-
version: 2.
|
165
|
+
version: 2.13.0
|
141
166
|
type: :development
|
142
167
|
prerelease: false
|
143
|
-
version_requirements: *
|
168
|
+
version_requirements: *10787920
|
144
169
|
- !ruby/object:Gem::Dependency
|
145
170
|
name: timecop
|
146
|
-
requirement: &
|
171
|
+
requirement: &10787160 !ruby/object:Gem::Requirement
|
147
172
|
none: false
|
148
173
|
requirements:
|
149
174
|
- - ~>
|
150
175
|
- !ruby/object:Gem::Version
|
151
|
-
version: 0.
|
176
|
+
version: 0.6.1
|
152
177
|
type: :development
|
153
178
|
prerelease: false
|
154
|
-
version_requirements: *
|
179
|
+
version_requirements: *10787160
|
155
180
|
- !ruby/object:Gem::Dependency
|
156
181
|
name: yard
|
157
|
-
requirement: &
|
182
|
+
requirement: &10803020 !ruby/object:Gem::Requirement
|
158
183
|
none: false
|
159
184
|
requirements:
|
160
185
|
- - ~>
|
@@ -162,10 +187,10 @@ dependencies:
|
|
162
187
|
version: 0.8.4
|
163
188
|
type: :development
|
164
189
|
prerelease: false
|
165
|
-
version_requirements: *
|
190
|
+
version_requirements: *10803020
|
166
191
|
- !ruby/object:Gem::Dependency
|
167
192
|
name: rb-inotify
|
168
|
-
requirement: &
|
193
|
+
requirement: &10802560 !ruby/object:Gem::Requirement
|
169
194
|
none: false
|
170
195
|
requirements:
|
171
196
|
- - ~>
|
@@ -173,10 +198,10 @@ dependencies:
|
|
173
198
|
version: 0.9.0
|
174
199
|
type: :development
|
175
200
|
prerelease: false
|
176
|
-
version_requirements: *
|
201
|
+
version_requirements: *10802560
|
177
202
|
- !ruby/object:Gem::Dependency
|
178
203
|
name: rb-fsevent
|
179
|
-
requirement: &
|
204
|
+
requirement: &10802060 !ruby/object:Gem::Requirement
|
180
205
|
none: false
|
181
206
|
requirements:
|
182
207
|
- - ~>
|
@@ -184,7 +209,7 @@ dependencies:
|
|
184
209
|
version: 0.9.2
|
185
210
|
type: :development
|
186
211
|
prerelease: false
|
187
|
-
version_requirements: *
|
212
|
+
version_requirements: *10802060
|
188
213
|
description: Be lazy. Let Maid clean up after you, based on rules you define. Think
|
189
214
|
of it as "Hazel for hackers".
|
190
215
|
email:
|
@@ -196,7 +221,8 @@ extra_rdoc_files: []
|
|
196
221
|
files:
|
197
222
|
- .gitignore
|
198
223
|
- .rspec
|
199
|
-
- .
|
224
|
+
- .ruby-gemset
|
225
|
+
- .ruby-version
|
200
226
|
- .travis.yml
|
201
227
|
- .yardopts
|
202
228
|
- AUTHORS.md
|
@@ -230,6 +256,10 @@ files:
|
|
230
256
|
- script/vagrant-test
|
231
257
|
- script/vagrant-test-all
|
232
258
|
- spec/dependency_spec.rb
|
259
|
+
- spec/fixtures/files/bar.zip
|
260
|
+
- spec/fixtures/files/foo.zip
|
261
|
+
- spec/fixtures/files/ruby.jpg
|
262
|
+
- spec/fixtures/files/さ.zip
|
233
263
|
- spec/lib/maid/app_spec.rb
|
234
264
|
- spec/lib/maid/maid_spec.rb
|
235
265
|
- spec/lib/maid/numeric_extensions_spec.rb
|
@@ -256,9 +286,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
256
286
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
257
287
|
none: false
|
258
288
|
requirements:
|
259
|
-
- - ! '
|
289
|
+
- - ! '>'
|
260
290
|
- !ruby/object:Gem::Version
|
261
|
-
version:
|
291
|
+
version: 1.3.1
|
262
292
|
requirements: []
|
263
293
|
rubyforge_project: maid
|
264
294
|
rubygems_version: 1.8.11
|
data/.rvmrc
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
rvm use 1.8.7@maid --create
|