fxn-unmac 0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2007 ASPgems S.L.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
data/README ADDED
@@ -0,0 +1,67 @@
1
+ unmac -- Delete spurious Mac files under a directory or volume
2
+
3
+ Usage:
4
+ unmac [OPTIONS] directory ...
5
+
6
+ Options:
7
+ -h, --help Print this help
8
+ -v, --verbose Show processing
9
+ -s, --keep-spotlight Do not delete Spotlight data
10
+ -f, --keep-fsevents Do not delete Time Machine stuff
11
+ -t, --keep-trashes Do not delete volume trashes
12
+ -m, --keep-macosx Do not delete "__MACOSX" directories
13
+ -r, --keep-dsstore Do not delete ".DS_Store" directories
14
+ -d, --keep-apple-double Do not delete "._*" ghost files
15
+ -o, --keep-apple-double-orphans Delete "._foo.txt" only if "foo.txt" exists
16
+
17
+ Description:
18
+ When a Mac copies files to volumes that have a different file system it adds
19
+ some auxiliary files that represent different kinds of metadata. This typically
20
+ happens with memory sticks, network drives, SD cards, etc. Mac archivers like
21
+ zip(1) add special files as well, like "__MACOSX", you'll see them for example
22
+ if you extract a Zip file like that on Windows.
23
+
24
+ The purpose of these special files is to let another Mac rebuild the metadata
25
+ from them, Spotlight integration, etc. But if you are not interested in these
26
+ features your directory or volume just gets cluttered. This utility removes
27
+ all those extra files.
28
+
29
+ What's deleted:
30
+ This is just a summary, for more detailed explanations and pointers see the
31
+ comments in unmacer.rb:
32
+
33
+ * Spotlight leaves a folder called ".Spotlight-V100" in the root directory
34
+ of volumes.
35
+
36
+ * Time Machine relies on a folder called ".fseventsd" in the root directory
37
+ of volumes.
38
+
39
+ * A folder called ".Trashes" in the root directory of volumes stores their
40
+ trashes. Those ones are taken into account by the Trash in the Dock.
41
+
42
+ * Some archivers create auxiliary directories called "__MACOSX".
43
+
44
+ * Finder and Spotlight data related to each folder gets stored in an
45
+ extra file called ".DS_Store".
46
+
47
+ * For each file "foo.txt", its resource fork and some additional stuff
48
+ are stored in an accompaining ghost file called "._foo.txt". The pattern
49
+ is to prepend "._" to the original file name.
50
+
51
+ Some stuff is only found in the root folder of volumes, unmac looks for them
52
+ in any directory you pass as argument, but not on their subdirectories.
53
+
54
+ Installation:
55
+ unmac is distributed as a Ruby gem. Once you have Ruby and RubyGems installed
56
+ execute
57
+
58
+ gem sources -a http://gems.github.com # you need this only once
59
+ gem install fxn-unmac
60
+
61
+ This program is portable.
62
+
63
+ License:
64
+ See the MIT-LICENSE file included in the distribution.
65
+
66
+ Copyright:
67
+ Copyright (C) 2009 Xavier Noria.
@@ -0,0 +1,7 @@
1
+ task :default => [:test]
2
+
3
+ task :test do
4
+ Dir['test/test_*.rb'].each do |test|
5
+ ruby "-Ilib #{test}"
6
+ end
7
+ end
@@ -0,0 +1,99 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'getoptlong'
4
+ require 'rubygems'
5
+ require 'unmacer'
6
+
7
+ def usage
8
+ puts <<USAGE
9
+ unmac -- Delete spurious Mac files under a directory or volume
10
+
11
+ Usage:
12
+ unmac [OPTIONS] directory ...
13
+
14
+ Options:
15
+ -h, --help Print this help
16
+ -v, --verbose Show processing
17
+ -s, --keep-spotlight Do not delete Spotlight data
18
+ -f, --keep-fsevents Do not delete Time Machine stuff
19
+ -t, --keep-trashes Do not delete volume trashes
20
+ -m, --keep-macosx Do not delete "__MACOSX" directories
21
+ -r, --keep-dsstore Do not delete ".DS_Store" directories
22
+ -d, --keep-apple-double Do not delete "._*" ghost files
23
+ -o, --keep-apple-double-orphans Delete "._foo.txt" only if "foo.txt" exists
24
+
25
+ Description:
26
+ When a Mac copies files to volumes that have a different file system it adds
27
+ some auxiliary files that represent different kinds of metadata. This typically
28
+ happens with memory sticks, network drives, SD cards, etc. Mac archivers like
29
+ zip(1) add special files as well, like "#{Unmacer::MACOSX}", you'll see them
30
+ for example if you extract a Zip file like that on Windows.
31
+
32
+ The purpose of these special files is to let another Mac rebuild the metadata
33
+ from them, Spotlight integration, etc. But if you are not interested in these
34
+ features your directory or volume just gets cluttered. This utility removes
35
+ all those extra files.
36
+
37
+ What's deleted:
38
+ This is just a summary, for more detailed explanations and pointers see the
39
+ comments in unmacer.rb:
40
+
41
+ * Spotlight leaves a folder called "#{Unmacer::SPOTLIGHT}" in the root directory
42
+ of volumes.
43
+
44
+ * Time Machine relies on a folder called "#{Unmacer::FSEVENTS}" in the root directory
45
+ of volumes.
46
+
47
+ * A folder called "#{Unmacer::TRASHES}" in the root directory of volumes stores their
48
+ trashes. Those ones are taken into account by the Trash in the Dock.
49
+
50
+ * Some archivers create auxiliary directories called "#{Unmacer::MACOSX}".
51
+
52
+ * Finder and Spotlight data related to each folder gets stored in an
53
+ extra file called "#{Unmacer::DSSTORE}".
54
+
55
+ * For each file "foo.txt", its resource fork and some additional stuff
56
+ are stored in an accompaining ghost file called "._foo.txt". The pattern
57
+ is to prepend "._" to the original file name.
58
+
59
+ Some stuff is only found in the root folder of volumes, unmac looks for them
60
+ in any directory you pass as argument, but not on their subdirectories.
61
+ USAGE
62
+ end
63
+
64
+ opts = GetoptLong.new(
65
+ ['--help', '-h', GetoptLong::NO_ARGUMENT],
66
+ ['--verbose', '-v', GetoptLong::NO_ARGUMENT],
67
+ ['--keep-spotlight', '-s', GetoptLong::NO_ARGUMENT],
68
+ ['--keep-fsevents', '-f', GetoptLong::NO_ARGUMENT],
69
+ ['--keep-trashes', '-t', GetoptLong::NO_ARGUMENT],
70
+ ['--keep-macosx', '-m', GetoptLong::NO_ARGUMENT],
71
+ ['--keep-dsstore', '-r', GetoptLong::NO_ARGUMENT],
72
+ ['--keep-apple-double', '-d', GetoptLong::NO_ARGUMENT],
73
+ ['--keep-apple-double-orphans', '-o', GetoptLong::NO_ARGUMENT],
74
+ ['--test', GetoptLong::NO_ARGUMENT]
75
+ )
76
+
77
+ test = false
78
+ begin
79
+ unmacer = Unmacer.new
80
+ opts.each do |opt, val|
81
+ case opt
82
+ when '--help'
83
+ usage and exit
84
+ when '--verbose'
85
+ unmacer.verbose = true
86
+ when /\A--(keep-.*)/
87
+ flag = $1.gsub('-', '_')
88
+ unmacer.send("#{flag}=", true)
89
+ when '--test'
90
+ test = true
91
+ end
92
+ end
93
+ unmacer.unmac!(ARGV) unless test
94
+ rescue GetoptLong::InvalidOption
95
+ usage and exit 1
96
+ end
97
+
98
+ # The test suite for this file expects the unmacer to be the last expression.
99
+ unmacer
@@ -0,0 +1,156 @@
1
+ require 'fileutils'
2
+ require 'find'
3
+
4
+ class Unmacer
5
+ attr_accessor :verbose,
6
+ :keep_spotlight,
7
+ :keep_fsevents,
8
+ :keep_trashes,
9
+ :keep_macosx,
10
+ :keep_dsstore,
11
+ :keep_apple_double,
12
+ :keep_apple_double_orphans
13
+
14
+ SPOTLIGHT = '.Spotlight-V100'
15
+ FSEVENTS = '.fseventsd'
16
+ TRASHES = '.Trashes'
17
+ MACOSX = '__MACOSX'
18
+ DSSTORE = '.DS_Store'
19
+
20
+ def initialize
21
+ self.verbose = false
22
+ self.keep_spotlight = false
23
+ self.keep_fsevents = false
24
+ self.keep_trashes = false
25
+ self.keep_macosx = false
26
+ self.keep_dsstore = false
27
+ self.keep_apple_double = false
28
+ self.keep_apple_double_orphans = false
29
+ end
30
+
31
+ def unmac!(dirnames)
32
+ dirnames.each do |dirname|
33
+ unmac_root(dirname)
34
+ find_skipping_root(dirname) do |f|
35
+ unmac_folder(f) if File.directory?(f)
36
+ end
37
+ end
38
+ end
39
+
40
+ def find_skipping_root(path)
41
+ root_seen = false
42
+ Find.find(path) do |f|
43
+ if !root_seen
44
+ root_seen = true
45
+ else
46
+ yield f
47
+ end
48
+ end
49
+ end
50
+
51
+ private
52
+
53
+ def unmac_all(dirname)
54
+ unmac_root_folder(dirname)
55
+ end
56
+
57
+ def unmac_root(dirname)
58
+ # Order is important because ".Trashes" has "._.Trashes". Otherwise,
59
+ # "._.Trashes" could be left as an orphan.
60
+ unmac_folder(dirname)
61
+ delete_spotlight(dirname) unless keep_spotlight
62
+ delete_fsevents(dirname) unless keep_fsevents
63
+ delete_trashes(dirname) unless keep_trashes
64
+ end
65
+
66
+ def unmac_folder(dirname)
67
+ delete_macosx(dirname) unless keep_macosx
68
+ delete_dsstore(dirname) unless keep_dsstore
69
+ delete_apple_double(dirname) unless keep_apple_double
70
+ end
71
+
72
+ def delete(parent, file_or_directory)
73
+ name = File.join(parent, file_or_directory)
74
+ FileUtils.rm_r(name)
75
+ rescue Errno::ENOENT
76
+ # it does not exist, fine.
77
+ else
78
+ puts "deleted #{name}" if verbose
79
+ end
80
+
81
+ # Spotlight saves all its index-related files in the .Spotlight-V100 directory
82
+ # at the root level of a volume it has indexed.
83
+ #
84
+ # See http://www.thexlab.com/faqs/stopspotlightindex.html.
85
+ def delete_spotlight(dirname)
86
+ delete(dirname, SPOTLIGHT)
87
+ end
88
+
89
+ # The FSEvents framework has a daemon that dumps events from /dev/fsevents
90
+ # into log files stored in a .fseventsd directory at the root of the volume
91
+ # the events are for.
92
+ #
93
+ # See http://arstechnica.com/reviews/os/mac-os-x-10-5.ars/7.
94
+ def delete_fsevents(dirname)
95
+ delete(dirname, FSEVENTS)
96
+ end
97
+
98
+ # A volume may have a ".Trashes" folder in the root directory. The Trash in
99
+ # the Dock shows the contents of the ".Trash" folder in your home directory
100
+ # and the content of all the ".Trashes/uid" in the rest of volumes.
101
+ #
102
+ # See http://discussions.apple.com/thread.jspa?messageID=1145130.
103
+ def delete_trashes(dirname)
104
+ delete(dirname, TRASHES)
105
+ end
106
+
107
+ # Apple's builtin Zip archiver stores some metadata in a directory called
108
+ # "__MACOSX".
109
+ #
110
+ # See http://floatingsun.net/2007/02/07/whats-with-__macosx-in-zip-files.
111
+ def delete_macosx(dirname)
112
+ delete(dirname, MACOSX)
113
+ end
114
+
115
+ # In each directory the ".DS_Store" file stores info about Finder window
116
+ # settings and Spotlight comments of its files.
117
+ #
118
+ # See http://en.wikipedia.org/wiki/.DS_Store.
119
+ def delete_dsstore(dirname)
120
+ delete(dirname, DSSTORE)
121
+ end
122
+
123
+ # When a file is copied to a volume that does not natively support HFS file
124
+ # characteristics its data fork is stored under the file's regular name, and
125
+ # the additional HFS information (resource fork, type & creator codes, etc.)
126
+ # is stored in a second file in AppleDouble format, with a name that starts
127
+ # with "._". So if the original file is called "foo.txt" you get a spurious
128
+ # ghost file called "._foo.txt".
129
+ #
130
+ # If you drag & drop a file onto a Windows partition, or you unpack a tarball
131
+ # on Linux that was built with Apple's tar(1) archiver you'll get that extra
132
+ # stuff. Reason is if the tarball is extracted into another Mac the metadata
133
+ # is preserved with this hack.
134
+ #
135
+ # See http://www.westwind.com/reference/OS-X/invisibles.html.
136
+ # See http://en.wikipedia.org/wiki/Resource_fork.
137
+ # See http://en.wikipedia.org/wiki/AppleSingle.
138
+ #
139
+ # Given the listing of a directory in +basenames+ this method selects
140
+ # emulated resource forks in there.
141
+ #
142
+ # If +include_orphans+ is true any filename that start with "._" are
143
+ # selected. The idea is to clean up ghost entries corresponding to files
144
+ # that were deleted in the target volume mounted in a different OS.
145
+ # Otherwise we ensure the corresponding filename exists in +basenames+.
146
+ def delete_apple_double(dirname)
147
+ basenames = Dir.entries(dirname)
148
+ basenames.select do |basename|
149
+ basename =~ /\A\._(.*)/ &&
150
+ !keep_apple_double_orphans ||
151
+ basenames.include?($1)
152
+ end.each do |basename|
153
+ delete(dirname, basename)
154
+ end
155
+ end
156
+ end
@@ -0,0 +1,185 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
2
+
3
+ require 'stringio'
4
+ require 'unmacer'
5
+ require 'test/unit'
6
+
7
+ UNMAC_RB = File.join(File.dirname(__FILE__), '..', 'bin', 'unmac')
8
+ UNMAC_SRC = File.open(UNMAC_RB) { |f| f.read }
9
+
10
+ class TestUnmac < Test::Unit::TestCase
11
+ def call_unmac(*args)
12
+ ARGV.clear
13
+ ARGV.concat(['--test', *args])
14
+ eval UNMAC_SRC
15
+ end
16
+
17
+ def test_no_options
18
+ unmacer = call_unmac('dummy')
19
+ assert !unmacer.verbose
20
+ assert !unmacer.keep_spotlight
21
+ assert !unmacer.keep_fsevents
22
+ assert !unmacer.keep_trashes
23
+ assert !unmacer.keep_macosx
24
+ assert !unmacer.keep_dsstore
25
+ assert !unmacer.keep_apple_double
26
+ assert !unmacer.keep_apple_double_orphans
27
+ assert_equal %w(dummy), ARGV
28
+ end
29
+
30
+ def test_verbose
31
+ for opt in ['--verbose', '-v']
32
+ unmacer = call_unmac(opt, 'dummy')
33
+ assert unmacer.verbose
34
+ assert !unmacer.keep_spotlight
35
+ assert !unmacer.keep_fsevents
36
+ assert !unmacer.keep_trashes
37
+ assert !unmacer.keep_macosx
38
+ assert !unmacer.keep_dsstore
39
+ assert !unmacer.keep_apple_double
40
+ assert !unmacer.keep_apple_double_orphans
41
+ assert_equal %w(dummy), ARGV
42
+ end
43
+ end
44
+
45
+ def test_spotlight
46
+ for opt in ['--keep-spotlight', '-s']
47
+ unmacer = call_unmac(opt, 'dummy')
48
+ assert !unmacer.verbose
49
+ assert unmacer.keep_spotlight
50
+ assert !unmacer.keep_fsevents
51
+ assert !unmacer.keep_trashes
52
+ assert !unmacer.keep_macosx
53
+ assert !unmacer.keep_dsstore
54
+ assert !unmacer.keep_apple_double
55
+ assert !unmacer.keep_apple_double_orphans
56
+ assert_equal %w(dummy), ARGV
57
+ end
58
+ end
59
+
60
+ def test_fsevents
61
+ for opt in ['--keep-fsevents', '-f']
62
+ unmacer = call_unmac(opt, 'dummy')
63
+ assert !unmacer.verbose
64
+ assert !unmacer.keep_spotlight
65
+ assert unmacer.keep_fsevents
66
+ assert !unmacer.keep_trashes
67
+ assert !unmacer.keep_macosx
68
+ assert !unmacer.keep_dsstore
69
+ assert !unmacer.keep_apple_double
70
+ assert !unmacer.keep_apple_double_orphans
71
+ assert_equal %w(dummy), ARGV
72
+ end
73
+ end
74
+
75
+ def test_trashes
76
+ for opt in ['--keep-trashes', '-t']
77
+ unmacer = call_unmac(opt, 'dummy')
78
+ assert !unmacer.verbose
79
+ assert !unmacer.keep_spotlight
80
+ assert !unmacer.keep_fsevents
81
+ assert unmacer.keep_trashes
82
+ assert !unmacer.keep_macosx
83
+ assert !unmacer.keep_dsstore
84
+ assert !unmacer.keep_apple_double
85
+ assert !unmacer.keep_apple_double_orphans
86
+ assert_equal %w(dummy), ARGV
87
+ end
88
+ end
89
+
90
+ def test_macosx
91
+ for opt in ['--keep-macosx', '-m']
92
+ unmacer = call_unmac(opt, 'dummy')
93
+ assert !unmacer.verbose
94
+ assert !unmacer.keep_spotlight
95
+ assert !unmacer.keep_fsevents
96
+ assert !unmacer.keep_trashes
97
+ assert unmacer.keep_macosx
98
+ assert !unmacer.keep_dsstore
99
+ assert !unmacer.keep_apple_double
100
+ assert !unmacer.keep_apple_double_orphans
101
+ assert_equal %w(dummy), ARGV
102
+ end
103
+ end
104
+
105
+ def test_dsstore
106
+ for opt in ['--keep-dsstore', '-r']
107
+ unmacer = call_unmac(opt, 'dummy')
108
+ assert !unmacer.verbose
109
+ assert !unmacer.keep_spotlight
110
+ assert !unmacer.keep_fsevents
111
+ assert !unmacer.keep_trashes
112
+ assert !unmacer.keep_macosx
113
+ assert unmacer.keep_dsstore
114
+ assert !unmacer.keep_apple_double
115
+ assert !unmacer.keep_apple_double_orphans
116
+ assert_equal %w(dummy), ARGV
117
+ end
118
+ end
119
+
120
+ def test_apple_double
121
+ for opt in ['--keep-apple-double', '-d']
122
+ unmacer = call_unmac(opt, 'dummy')
123
+ assert !unmacer.verbose
124
+ assert !unmacer.keep_spotlight
125
+ assert !unmacer.keep_fsevents
126
+ assert !unmacer.keep_trashes
127
+ assert !unmacer.keep_macosx
128
+ assert !unmacer.keep_dsstore
129
+ assert unmacer.keep_apple_double
130
+ assert !unmacer.keep_apple_double_orphans
131
+ assert_equal %w(dummy), ARGV
132
+ end
133
+ end
134
+
135
+ def test_apple_double_orphans
136
+ for opt in ['--keep-apple-double-orphans', '-o']
137
+ unmacer = call_unmac(opt, 'dummy')
138
+ assert !unmacer.verbose
139
+ assert !unmacer.keep_spotlight
140
+ assert !unmacer.keep_fsevents
141
+ assert !unmacer.keep_trashes
142
+ assert !unmacer.keep_macosx
143
+ assert !unmacer.keep_dsstore
144
+ assert !unmacer.keep_apple_double
145
+ assert unmacer.keep_apple_double_orphans
146
+ assert_equal %w(dummy), ARGV
147
+ end
148
+ end
149
+
150
+ def test_mix_1
151
+ unmacer = call_unmac(*%w(-v -f -m -d dummy))
152
+ assert unmacer.verbose
153
+ assert !unmacer.keep_spotlight
154
+ assert unmacer.keep_fsevents
155
+ assert !unmacer.keep_trashes
156
+ assert unmacer.keep_macosx
157
+ assert !unmacer.keep_dsstore
158
+ assert unmacer.keep_apple_double
159
+ assert !unmacer.keep_apple_double_orphans
160
+ assert_equal %w(dummy), ARGV
161
+ end
162
+
163
+ def test_mix_2
164
+ unmacer = call_unmac(*%w(-s -t -r -o dummy))
165
+ assert !unmacer.verbose
166
+ assert unmacer.keep_spotlight
167
+ assert !unmacer.keep_fsevents
168
+ assert unmacer.keep_trashes
169
+ assert !unmacer.keep_macosx
170
+ assert unmacer.keep_dsstore
171
+ assert !unmacer.keep_apple_double
172
+ assert unmacer.keep_apple_double_orphans
173
+ assert_equal %w(dummy), ARGV
174
+ end
175
+
176
+ def test_help
177
+ buf = ""
178
+ $> = StringIO.open(buf, 'w')
179
+ call_unmac('-h')
180
+ $> = $stdout
181
+ assert_match /^unmac\b/, buf
182
+ assert_match /^Usage\b/, buf
183
+ assert ARGV.empty?
184
+ end
185
+ end
@@ -0,0 +1,202 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
2
+
3
+ require 'fileutils'
4
+ require 'set'
5
+ require 'unmacer'
6
+ require 'test/unit'
7
+
8
+ TEST_DIR = File.expand_path(File.dirname(__FILE__))
9
+ TMP_DIR = File.join(TEST_DIR, 'tmp')
10
+
11
+ class TestUnmacer < Test::Unit::TestCase
12
+ def in_test_dir
13
+ Dir.chdir(TEST_DIR) { yield }
14
+ end
15
+
16
+ def in_tmp_dir
17
+ Dir.chdir(TMP_DIR) { yield }
18
+ end
19
+
20
+ def setup
21
+ in_test_dir { Dir.mkdir('tmp') }
22
+ @unmacer = Unmacer.new
23
+ end
24
+
25
+ def teardown
26
+ in_test_dir { FileUtils.rm_r('tmp') }
27
+ end
28
+
29
+ def unmac!
30
+ @unmacer.unmac!(TMP_DIR)
31
+ end
32
+
33
+ def create_struct(dirnames=[], fnames=[])
34
+ in_tmp_dir do
35
+ FileUtils.mkdir_p([*dirnames])
36
+ FileUtils.touch([*fnames])
37
+ end
38
+ end
39
+
40
+ def read_struct
41
+ entries = []
42
+ in_tmp_dir do
43
+ @unmacer.find_skipping_root('.') do |f|
44
+ # File.find returns "./foo.txt", remove the leading stuff.
45
+ entries << f.sub(%r{\A\.[/\\]}, '')
46
+ end
47
+ end
48
+ entries
49
+ end
50
+
51
+ def test_an_empty_directory_should_remain_empty
52
+ create_struct
53
+ unmac!
54
+ assert read_struct.empty?
55
+ end
56
+
57
+ def test_spotlight
58
+ create_struct(Unmacer::SPOTLIGHT)
59
+ unmac!
60
+ assert read_struct.empty?
61
+ end
62
+
63
+ def test_spotlight_ignored_if_not_in_root
64
+ fake = File.join('dummy', Unmacer::SPOTLIGHT)
65
+ create_struct(fake)
66
+ unmac!
67
+ assert read_struct.include?(fake)
68
+ end
69
+
70
+ def test_keep_spotlight
71
+ create_struct(Unmacer::SPOTLIGHT)
72
+ @unmacer.keep_spotlight = true
73
+ unmac!
74
+ assert [Unmacer::SPOTLIGHT], read_struct
75
+ end
76
+
77
+ def test_fsevents
78
+ create_struct(Unmacer::FSEVENTS)
79
+ unmac!
80
+ assert read_struct.empty?
81
+ end
82
+
83
+ def test_fsevents_ignored_if_not_in_root
84
+ fake = File.join('dummy', Unmacer::FSEVENTS)
85
+ create_struct(fake)
86
+ unmac!
87
+ assert read_struct.include?(fake)
88
+ end
89
+
90
+ def test_keep_fsevents
91
+ create_struct(Unmacer::FSEVENTS)
92
+ @unmacer.keep_fsevents = true
93
+ unmac!
94
+ assert_equal [Unmacer::FSEVENTS], read_struct
95
+ end
96
+
97
+ def test_trashes
98
+ create_struct(Unmacer::TRASHES)
99
+ unmac!
100
+ assert read_struct.empty?
101
+ end
102
+
103
+ def test_trashes_ignored_if_not_in_root
104
+ fake = File.join('dummy', Unmacer::TRASHES)
105
+ create_struct(fake)
106
+ unmac!
107
+ assert read_struct.include?(fake)
108
+ end
109
+
110
+ def test_keep_trashes
111
+ create_struct(Unmacer::TRASHES)
112
+ @unmacer.keep_trashes = true
113
+ unmac!
114
+ assert_equal [Unmacer::TRASHES], read_struct
115
+ end
116
+
117
+ def test_macosx
118
+ create_struct(Unmacer::MACOSX)
119
+ unmac!
120
+ assert read_struct.empty?
121
+ end
122
+
123
+ def test_keep_macosx
124
+ create_struct(Unmacer::MACOSX)
125
+ @unmacer.keep_macosx = true
126
+ unmac!
127
+ assert_equal [Unmacer::MACOSX], read_struct
128
+ end
129
+
130
+ def test_dsstore
131
+ create_struct([], Unmacer::DSSTORE)
132
+ unmac!
133
+ assert read_struct.empty?
134
+ end
135
+
136
+ def test_keep_dsstore
137
+ create_struct([], Unmacer::DSSTORE)
138
+ @unmacer.keep_dsstore = true
139
+ unmac!
140
+ assert_equal [Unmacer::DSSTORE], read_struct
141
+ end
142
+
143
+ def test_apple_double_with_pair
144
+ create_struct([], %w(foo.txt ._foo.txt))
145
+ unmac!
146
+ assert_equal %w(foo.txt), read_struct
147
+ end
148
+
149
+ def test_keep_apple_double_with_pair
150
+ create_struct([], %w(foo.txt ._foo.txt))
151
+ @unmacer.keep_apple_double = true
152
+ unmac!
153
+ assert_equal Set.new(%w(foo.txt ._foo.txt)), Set.new(read_struct)
154
+ end
155
+
156
+ def test_apple_double_with_orphan
157
+ create_struct([], '._foo.txt')
158
+ unmac!
159
+ assert read_struct.empty?
160
+ end
161
+
162
+ def test_keep_apple_double_with_orphan
163
+ create_struct([], '._foo.txt')
164
+ @unmacer.keep_apple_double = true
165
+ unmac!
166
+ assert ['._foo.txt'], read_struct
167
+ end
168
+
169
+ def test_keep_apple_double_orphans
170
+ create_struct([], '._foo.txt')
171
+ @unmacer.keep_apple_double_orphans = true
172
+ unmac!
173
+ assert_equal %w(._foo.txt), read_struct
174
+ end
175
+
176
+ def test_a_handful_of_files
177
+ dummy = 'dummy'
178
+ dummy2 = File.join(dummy, 'dummy2')
179
+ ghost = File.join(dummy, '._ghost')
180
+ remain = File.join(dummy2, 'should_remain')
181
+ create_struct([
182
+ Unmacer::SPOTLIGHT,
183
+ Unmacer::FSEVENTS,
184
+ Unmacer::TRASHES,
185
+ Unmacer::MACOSX,
186
+ dummy,
187
+ dummy2
188
+ ], [
189
+ Unmacer::DSSTORE,
190
+ File.join(dummy, Unmacer::DSSTORE),
191
+ File.join(dummy2, Unmacer::DSSTORE),
192
+ File.join(dummy, Unmacer::MACOSX),
193
+ File.join(dummy2, Unmacer::MACOSX),
194
+ 'foo.txt',
195
+ '._foo.txt',
196
+ ghost,
197
+ remain
198
+ ])
199
+ unmac!
200
+ assert_equal Set.new(['foo.txt', dummy, dummy2, remain]), Set.new(read_struct)
201
+ end
202
+ end
@@ -0,0 +1,24 @@
1
+ Gem::Specification.new do |spec|
2
+ spec.name = 'unmac'
3
+ spec.version = '0.1'
4
+ spec.summary = 'Delete spurious Mac files under a directory or volume'
5
+ spec.homepage = 'http://github.com/fxn/unmac/tree/master'
6
+ spec.executables = %w(unmac)
7
+ spec.author = 'Xavier Noria'
8
+ spec.email = 'fxn@hashref.com'
9
+ spec.rubyforge_project = 'unmac'
10
+
11
+ spec.test_files = %w(
12
+ test/test_unmacer.rb
13
+ test/test_unmac.rb
14
+ )
15
+
16
+ spec.files = %w(
17
+ unmac.gemspec
18
+ Rakefile
19
+ README
20
+ MIT-LICENSE
21
+ bin/unmac
22
+ lib/unmacer.rb
23
+ ) + spec.test_files
24
+ end
metadata ADDED
@@ -0,0 +1,61 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fxn-unmac
3
+ version: !ruby/object:Gem::Version
4
+ version: "0.1"
5
+ platform: ruby
6
+ authors:
7
+ - Xavier Noria
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-12-22 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: fxn@hashref.com
18
+ executables:
19
+ - unmac
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - unmac.gemspec
26
+ - Rakefile
27
+ - README
28
+ - MIT-LICENSE
29
+ - bin/unmac
30
+ - lib/unmacer.rb
31
+ - test/test_unmacer.rb
32
+ - test/test_unmac.rb
33
+ has_rdoc: false
34
+ homepage: http://github.com/fxn/unmac/tree/master
35
+ post_install_message:
36
+ rdoc_options: []
37
+
38
+ require_paths:
39
+ - lib
40
+ required_ruby_version: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: "0"
45
+ version:
46
+ required_rubygems_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: "0"
51
+ version:
52
+ requirements: []
53
+
54
+ rubyforge_project: unmac
55
+ rubygems_version: 1.2.0
56
+ signing_key:
57
+ specification_version: 2
58
+ summary: Delete spurious Mac files under a directory or volume
59
+ test_files:
60
+ - test/test_unmacer.rb
61
+ - test/test_unmac.rb