diff --git a/lib/fog/aws/models/storage/directory.rb b/lib/fog/aws/models/storage/directory.rb index 9f31a49cf..fcd5707f1 100644 --- a/lib/fog/aws/models/storage/directory.rb +++ b/lib/fog/aws/models/storage/directory.rb @@ -1,5 +1,6 @@ require 'fog/core/model' require 'fog/aws/models/storage/files' +require 'fog/aws/models/storage/versions' module Fog module Storage @@ -69,6 +70,15 @@ module Fog connection.put_bucket_versioning(key, new_versioning ? 'Enabled' : 'Suspended') end + def versions + @versions ||= begin + Fog::Storage::AWS::Versions.new( + :directory => self, + :connection => connection + ) + end + end + def public=(new_public) if new_public @acl = 'public-read' diff --git a/lib/fog/aws/models/storage/version.rb b/lib/fog/aws/models/storage/version.rb index 5e83cd6a4..eaffa083f 100644 --- a/lib/fog/aws/models/storage/version.rb +++ b/lib/fog/aws/models/storage/version.rb @@ -15,7 +15,19 @@ module Fog attribute :delete_marker, :type => :boolean def file - @file ||= collection.file.directory.files.get(key, 'versionId' => version) + @file ||= if collection.file + collection.file.directory.files.get(key, 'versionId' => version) + else + collection.directory.files.get(key, 'versionId' => version) + end + end + + def destroy + if collection.file + collection.connection.delete_object(collection.file.directory.key, key, 'versionId' => version) + else + collection.connection.delete_object(collection.directory.key, key, 'versionId' => version) + end end end diff --git a/lib/fog/aws/models/storage/versions.rb b/lib/fog/aws/models/storage/versions.rb index 42f1ccd5d..8ed61d4f0 100644 --- a/lib/fog/aws/models/storage/versions.rb +++ b/lib/fog/aws/models/storage/versions.rb @@ -8,20 +8,24 @@ module Fog class Versions < Fog::Collection attribute :file + attribute :directory model Fog::Storage::AWS::Version def all - data = connection.get_bucket_object_versions(file.directory.key, :prefix => file.key).body['Versions'] + data = if file + connection.get_bucket_object_versions(file.directory.key, :prefix => file.key).body['Versions'] + else + connection.get_bucket_object_versions(directory.key).body['Versions'] + end + load(data) end def new(attributes = {}) - requires :file - version_type = attributes.keys.first - model = super({ :file => file }.merge!(attributes[version_type])) + model = super(attributes[version_type]) model.delete_marker = version_type == 'DeleteMarker' model diff --git a/lib/fog/aws/requests/storage/delete_object.rb b/lib/fog/aws/requests/storage/delete_object.rb index d8603df7c..e28bf91f8 100644 --- a/lib/fog/aws/requests/storage/delete_object.rb +++ b/lib/fog/aws/requests/storage/delete_object.rb @@ -52,8 +52,9 @@ module Fog version = bucket[:objects][object_name].find { |object| object['VersionId'] == version_id} # S3 special cases the 'null' value to not error out if no such version exists. - if version || version_id == 'null' + if version || (version_id == 'null') bucket[:objects][object_name].delete(version) + bucket[:objects].delete(object_name) if bucket[:objects][object_name].empty? response.headers['x-amz-delete-marker'] = 'true' if version[:delete_marker] response.headers['x-amz-version-id'] = version_id diff --git a/tests/aws/models/storage/directory_tests.rb b/tests/aws/models/storage/directory_tests.rb index e6b0b8774..d1fb399e2 100644 --- a/tests/aws/models/storage/directory_tests.rb +++ b/tests/aws/models/storage/directory_tests.rb @@ -28,6 +28,10 @@ Shindo.tests("Storage[:aws] | directory", [:aws]) do end end + end + + model_tests(Fog::Storage[:aws].directories, directory_attributes, Fog.mocking?) do + tests("#versioning?") do tests("#versioning? false if not enabled").returns(false) do @instance.versioning? @@ -43,6 +47,29 @@ Shindo.tests("Storage[:aws] | directory", [:aws]) do @instance.versioning? end end + + end + + model_tests(Fog::Storage[:aws].directories, directory_attributes, Fog.mocking?) do + @instance.versioning = true + + versions = [] + versions << @instance.connection.put_object(@instance.key, 'one', 'abcde').headers['x-amz-version-id'] + versions << @instance.connection.put_object(@instance.key, 'one', '32423').headers['x-amz-version-id'] + versions << @instance.connection.delete_object(@instance.key, 'one').headers['x-amz-version-id'] + versions << @instance.connection.put_object(@instance.key, 'two', 'aoeu').headers['x-amz-version-id'] + + tests('#versions') do + tests('#versions.size includes versions (including DeleteMarkers) for all keys').returns(4) do + @instance.versions.size + end + + tests('#versions returns the correct versions').returns(versions) do + @instance.versions.collect(&:version) + end + end + + @instance.versions.each(&:destroy) end end \ No newline at end of file diff --git a/tests/aws/models/storage/file_tests.rb b/tests/aws/models/storage/file_tests.rb index dace1cb43..04cac2c12 100644 --- a/tests/aws/models/storage/file_tests.rb +++ b/tests/aws/models/storage/file_tests.rb @@ -34,8 +34,30 @@ Shindo.tests("Storage[:aws] | file", [:aws]) do end end + + @directory.files.create(:key => @instance.key) + @instance.destroy + + tests("#versions") do + tests('#versions.size includes versions (including DeleteMarkers) for all keys').returns(3) do + @instance.versions.size + end + + tests('#versions are all for the correct key').returns(true) do + @instance.versions.all? { |v| v.key == @instance.key } + end + end + + tests("#destroy") do + tests("#destroy a specific version should delete the version, not create a DeleteMarker").returns(2) do + @instance.destroy('versionId' => @instance.version) + @instance.versions.all.size + end + end + end + @directory.versions.each(&:destroy) @directory.destroy end