tmptation 1.4 → 1.5

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.
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