maid 0.3.0 → 0.4.0.alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
[](http://badge.fury.io/rb/maid)
|
|
4
|
+
[](http://travis-ci.org/benjaminoakes/maid)
|
|
5
|
+
[](https://gemnasium.com/benjaminoakes/maid)
|
|
6
|
+
[](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
|
-
[](https://codeclimate.com/github/benjaminoakes/maid)
|
|
47
|
-
[](http://travis-ci.org/benjaminoakes/maid)
|
|
48
|
-
[](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
|