fxn-unmac 0.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.
@@ -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