properly delete file in case of errors in StoredFile.create
authorLunar <lunar@anargeek.net>
Tue, 6 Mar 2012 16:14:29 +0000 (17:14 +0100)
committerLunar <lunar@anargeek.net>
Fri, 23 Mar 2012 17:11:28 +0000 (18:11 +0100)
This means that Depot.add_file does not have to care about removing leftover
files.

lib/coquelicot/depot.rb
lib/coquelicot/stored_file.rb
spec/coquelicot/stored_file_spec.rb

index 334b88d..eda3b6a 100644 (file)
@@ -28,21 +28,16 @@ module Coquelicot
     def add_file(pass, options, &block)
       dst = nil
 
-      begin
-        # Ensure that the generated name is not already used
-        loop do
-          dst = gen_random_file_name
-          begin
-            StoredFile.create(full_path(dst), pass, options, &block)
-            break
-          rescue Errno::EEXIST => e
-            raise unless e.message =~ /(?:^|\s)#{Regexp.escape(full_path(dst))}(?:\s|$)/
-            next # let's try again
-          end
+      # Ensure that the generated name is not already used
+      loop do
+        dst = gen_random_file_name
+        begin
+          StoredFile.create(full_path(dst), pass, options, &block)
+          break
+        rescue Errno::EEXIST => e
+          raise unless e.message =~ /(?:^|\s)#{Regexp.escape(full_path(dst))}(?:\s|$)/
+          next # let's try again
         end
-      rescue
-        File.unlink full_path(dst)
-        raise
       end
       link = gen_random_file_name
       add_link(link, dst)
index e5e8335..82cfaef 100644 (file)
@@ -43,13 +43,13 @@ module Coquelicot
       @meta['One-time-only']
     end
 
-    def self.create(dest, pass, meta)
+    def self.create(path, pass, meta)
       salt = gen_salt
       clear_meta = { "Coquelicot" => COQUELICOT_VERSION,
                      "Salt" => Base64.encode64(salt).strip,
                      "Expire-at" => meta.delete('Expire-at'),
                    }
-      File.open(dest, File::WRONLY|File::EXCL|File::CREAT) do |dest|
+      File.open(path, File::WRONLY|File::EXCL|File::CREAT) do |dest|
         dest.write(YAML.dump(clear_meta) + YAML_START)
 
         cipher = get_cipher(pass, salt, :encrypt)
@@ -61,6 +61,12 @@ module Coquelicot
         end
         dest.write(cipher.final)
       end
+    rescue Errno::EEXIST
+      # do not remove the file if it already existed before!
+      raise
+    rescue
+      FileUtils.rm path, :force => true
+      raise
     end
 
     def empty!
index 1b701ba..eff5981 100644 (file)
@@ -209,7 +209,17 @@ module Coquelicot
         end
       end
       context 'when the given block raise an error' do
-        it 'should not create a file'
+        it 'should not create a file' do
+          path = File.expand_path('stored_file', @tmpdir)
+          begin
+            StoredFile.create(path, 'secret', {}) do
+              raise StandardError.new
+            end
+          rescue StandardError
+            # that was expected!
+          end
+          File.should_not exist(path)
+        end
       end
     end