tmptation 1.4 → 1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/lib/tmptation.rb +30 -10
  2. data/test/tmptation_test.rb +34 -0
  3. metadata +3 -3
data/lib/tmptation.rb CHANGED
@@ -5,7 +5,7 @@ require 'fileutils'
5
5
  require 'forwardable'
6
6
 
7
7
  module Tmptation
8
- VERSION = 1.4
8
+ VERSION = 1.5
9
9
 
10
10
  # Adds a #safe_delete method that will delete the object's associated path
11
11
  # (either #path or #to_s, if it exists) only if it lives within the system's
@@ -33,22 +33,42 @@ module Tmptation
33
33
  module SafeDeletable
34
34
  UnsafeDelete = Class.new(RuntimeError)
35
35
 
36
- # Delete `#path` or `#to_s` if it exists, and only if it lives within
37
- # `Dir.tmpdir`. If the path is a directory, it is deleted recursively.
38
- #
39
- # @raises SafeDeletable::UnsafeDelete if directory isn't within `Dir.tmpdir`
40
- #
41
- def safe_delete
42
- path = self.respond_to?(:path) ? self.path : self.to_s
36
+ def self.path_for(obj)
37
+ path = obj.respond_to?(:path) ? obj.path : obj.to_s
43
38
  path = Pathname(path).expand_path
44
39
 
45
- unless path.to_s.match(/^#{Regexp.escape(Dir.tmpdir)}/)
40
+ unless safe?(path)
46
41
  raise UnsafeDelete.new("refusing to remove non-tmp directory '#{path}'")
47
42
  end
48
- FileUtils.remove_entry_secure(path.to_s)
43
+
44
+ path
45
+ end
46
+
47
+ # Whether `path` lives under `Dir.tmpdir`
48
+ def self.safe?(path)
49
+ !!path.to_s.match(/^#{Regexp.escape(Dir.tmpdir)}/)
50
+ end
51
+
52
+ # Delete `#path` or `#to_s` if it exists, and only if it lives under
53
+ # `Dir.tmpdir`. If the path is a directory, it is deleted recursively.
54
+ #
55
+ # @raises SafeDeletable::UnsafeDelete if directory isn't under `Dir.tmpdir`
56
+ #
57
+ def safe_delete
58
+ FileUtils.remove_entry_secure(SafeDeletable.path_for(self).to_s)
49
59
  rescue Errno::ENOENT
50
60
  # noop
51
61
  end
62
+
63
+ # Same as `#safe_delete`, but only deletes the contents of the directory,
64
+ # i.e. files and subdirectories
65
+ #
66
+ # @raises SafeDeletable::UnsafeDelete if directory isn't under `Dir.tmpdir`
67
+ # @raises Errno::ENOTDIR if `#path` is not a directory
68
+ #
69
+ def safe_delete_contents
70
+ SafeDeletable.path_for(self).children.each {|entry| FileUtils.remove_entry_secure(entry) }
71
+ end
52
72
  end
53
73
 
54
74
  # Keep track of a class's instances
@@ -89,6 +89,40 @@ describe Tmptation do
89
89
  file.delete if File.exist?(file)
90
90
  end
91
91
  end
92
+
93
+ it "should delete a directory's contents" do
94
+ begin
95
+ dir = Pathname(Dir.mktmpdir('SafeDeletable-')).expand_path
96
+ dir.extend(SafeDeletable)
97
+
98
+ sub = dir.join('foo')
99
+ sub.mkdir
100
+
101
+ assert dir.exist?
102
+ assert sub.exist?
103
+
104
+ dir.safe_delete_contents
105
+
106
+ assert dir.exist?
107
+ refute sub.exist?
108
+ ensure
109
+ sub.rmdir if sub.exist?
110
+ dir.rmdir if dir.exist?
111
+ end
112
+ end
113
+
114
+ it "should refuse to #safe_delete_contents for files" do
115
+ begin
116
+ file = Tempfile.new('safe_deletable')
117
+ file.extend(SafeDeletable)
118
+
119
+ assert File.exist?(file.path)
120
+
121
+ assert_raises(Errno::ENOTDIR) { file.safe_delete_contents }
122
+ ensure
123
+ file.delete if File.exist?(file)
124
+ end
125
+ end
92
126
  end
93
127
 
94
128
  describe InstanceTracking do
metadata CHANGED
@@ -4,8 +4,8 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 1
7
- - 4
8
- version: "1.4"
7
+ - 5
8
+ version: "1.5"
9
9
  platform: ruby
10
10
  authors:
11
11
  - Martin Aumont
@@ -13,7 +13,7 @@ autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
15
 
16
- date: 2010-11-07 01:00:00 -07:00
16
+ date: 2010-11-08 00:00:00 -08:00
17
17
  default_executable:
18
18
  dependencies:
19
19
  - !ruby/object:Gem::Dependency