Skip to content

Commit

Permalink
Merge 7271cf2 into 8bab11a
Browse files Browse the repository at this point in the history
  • Loading branch information
jcoyne committed Aug 15, 2019
2 parents 8bab11a + 7271cf2 commit 6a6a06b
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 13 deletions.
2 changes: 1 addition & 1 deletion app/controllers/workspaces_controller.rb
Expand Up @@ -2,7 +2,7 @@

# Handles API routes for managing the DOR workspace
class WorkspacesController < ApplicationController
rescue_from(DruidTools::SameContentExistsError, DruidTools::DifferentContentExistsError) do |e|
rescue_from(DruidPath::SameContentExistsError, DruidPath::DifferentContentExistsError) do |e|
render status: 409, plain: e.message
end

Expand Down
48 changes: 48 additions & 0 deletions app/services/druid_path.rb
@@ -0,0 +1,48 @@
# frozen_string_literal: true

# Creates and removes the druid path from the filesystem
class DruidPath
class SameContentExistsError < RuntimeError; end
class DifferentContentExistsError < RuntimeError; end

# @param [DruidTools::Druid] druid
def initialize(druid:)
@druid = druid
end

def mkdir(extra = nil)
new_path = druid.path(extra)
raise DifferentContentExistsError, "Unable to create directory, link already exists: #{new_path}" if File.symlink? new_path
raise SameContentExistsError, "The directory already exists: #{new_path}" if File.directory? new_path

FileUtils.mkdir_p(new_path)
end

def mkdir_with_final_link(source, extra = nil)
new_path = druid.path(extra)
raise DifferentContentExistsError, "Unable to create link, directory already exists: #{new_path}" if File.directory?(new_path) && !File.symlink?(new_path)

real_path = File.expand_path('..', new_path)
FileUtils.mkdir_p(real_path)
FileUtils.ln_s(source, new_path, force: true)
end

def rmdir(extra = nil)
parts = druid.tree
parts << extra unless extra.nil?
until parts.empty?
dir = File.join(druid.base, *parts)
begin
FileUtils.rm(File.join(dir, '.DS_Store'), force: true)
FileUtils.rmdir(dir)
rescue Errno::ENOTEMPTY
break
end
parts.pop
end
end

private

attr_reader :druid
end
7 changes: 3 additions & 4 deletions app/services/workspace_service.rb
Expand Up @@ -3,11 +3,10 @@
# Creates workspaces. This replaces https://github.com/sul-dlss/dor-services/blob/master/lib/dor/models/concerns/assembleable.rb
class WorkspaceService
# @param [Dor::Item] work the work to create the workspace for
# @param [String] source the path to create
# @param [String, nil] source the path to create
def self.create(work, source)
druid = DruidTools::Druid.new(work.pid, Settings.stacks.local_workspace_root)
return druid.mkdir if source.nil?

druid.mkdir_with_final_link(source)
druid_path = DruidPath.new(druid: druid)
source ? druid_path.mkdir_with_final_link(source) : druid_path.mkdir
end
end
4 changes: 2 additions & 2 deletions spec/controllers/workspaces_controller_spec.rb
Expand Up @@ -38,7 +38,7 @@
context 'when the link/directory already exists' do
before do
druid = DruidTools::Druid.new(item.pid, TEST_WORKSPACE)
druid.mkdir
DruidPath.new(druid: druid).mkdir
end

it 'returns a 409 Conflict http status code' do
Expand All @@ -51,7 +51,7 @@
context 'when the workspace already exists with different content' do
before do
druid = DruidTools::Druid.new(item.pid, TEST_WORKSPACE)
druid.mkdir
DruidPath.new(druid: druid).mkdir
end

it 'returns a 409 Conflict http status code' do
Expand Down
10 changes: 5 additions & 5 deletions spec/services/cleanup_service_spec.rb
Expand Up @@ -148,10 +148,10 @@ def create_tempfile(path)
dr1_assembly = DruidTools::Druid.new(druid_1, assembly_dir)
dr2_assembly = DruidTools::Druid.new(druid_2, assembly_dir)

dr1_wspace.mkdir
dr2_wspace.mkdir
dr1_assembly.mkdir
dr2_assembly.mkdir
DruidPath.new(druid: dr1_wspace).mkdir
DruidPath.new(druid: dr2_wspace).mkdir
DruidPath.new(druid: dr1_assembly).mkdir
DruidPath.new(druid: dr2_assembly).mkdir

# Add some 'content'
create_tempfile dr1_wspace.path
Expand Down Expand Up @@ -192,7 +192,7 @@ def create_tempfile(path)

it 'cleans up without assembly content' do
dr1_wspace = DruidTools::Druid.new(druid_1, workspace_dir)
dr1_wspace.mkdir
DruidPath.new(druid: dr1_wspace).mkdir

described_class.cleanup_by_druid druid_1
expect(File).not_to exist(dr1_wspace.path)
Expand Down
83 changes: 83 additions & 0 deletions spec/services/druid_path_spec.rb
@@ -0,0 +1,83 @@
# frozen_string_literal: true

require 'rails_helper'

RSpec.describe DruidPath do
let(:strictly_valid_druid_str) { 'druid:cd456gh1234' }
let(:tree2) { File.join(fixture_dir, 'cd/456/gh/1234/cd456gh1234') }

after do
FileUtils.rm_rf(File.join(fixture_dir, 'cd'))
end

describe '#mkdir error handling' do
it 'raises SameContentExistsError if the directory already exists' do
druid_obj = DruidTools::Druid.new(strictly_valid_druid_str, fixture_dir)
service = described_class.new(druid: druid_obj)
service.mkdir
expect { service.mkdir }.to raise_error(described_class::SameContentExistsError)
end

it 'raises DifferentContentExistsError if a link already exists in the workspace for this druid' do
source_dir = '/tmp/content_dir'
FileUtils.mkdir_p(source_dir)
dr = DruidTools::Druid.new(strictly_valid_druid_str, fixture_dir)
service = described_class.new(druid: dr)
service.mkdir_with_final_link(source_dir)

expect { service.mkdir }.to raise_error(described_class::DifferentContentExistsError)
end
end

describe '#mkdir_with_final_link' do
let(:source_dir) { '/tmp/content_dir' }
let(:druid_obj) { DruidTools::Druid.new(strictly_valid_druid_str, fixture_dir) }
let(:service) { described_class.new(druid: druid_obj) }

before do
FileUtils.mkdir_p(source_dir)
end

it 'creates a druid tree in the workspace with the final directory being a link to the passed in source' do
service.mkdir_with_final_link(source_dir)
expect(File).to be_symlink(druid_obj.path)
expect(File.readlink(tree2)).to eq(source_dir)
end

it 'raises DifferentContentExistsError if a directory already exists in the workspace for this druid' do
service.mkdir(fixture_dir)
expect { service.mkdir_with_final_link(source_dir) }.to raise_error(described_class::DifferentContentExistsError)
end
end

describe '#rmdir' do
let(:druid_str) { 'druid:cd456ef7890' }
let(:tree1) { File.join(fixture_dir, 'cd/456/ef/7890/cd456ef7890') }
let(:druid1) { DruidTools::Druid.new(druid_str, fixture_dir) }
let(:druid2) { DruidTools::Druid.new(strictly_valid_druid_str, fixture_dir) }
let(:service1) { described_class.new(druid: druid1) }
let(:service2) { described_class.new(druid: druid2) }

it 'destroys druid directories' do
expect(File.exist?(tree1)).to eq false
expect(File.exist?(tree2)).to eq false

service1.mkdir
expect(File.exist?(tree1)).to eq true
expect(File.exist?(tree2)).to eq false

service2.mkdir
expect(File.exist?(tree1)).to eq true
expect(File.exist?(tree2)).to eq true

service2.rmdir
expect(File.exist?(tree1)).to eq true
expect(File.exist?(tree2)).to eq false

service1.rmdir
expect(File.exist?(tree1)).to eq false
expect(File.exist?(tree2)).to eq false
expect(File.exist?(File.join(fixture_dir, 'cd'))).to eq false
end
end
end
2 changes: 1 addition & 1 deletion spec/services/prune_service_spec.rb
Expand Up @@ -53,7 +53,7 @@
# Nil the create records for this test
source_dir = File.join workspace, 'src_dir'
FileUtils.mkdir_p(source_dir)
dr2.mkdir_with_final_link(source_dir)
DruidPath.new(druid: dr2).mkdir_with_final_link(source_dir)
described_class.new(druid: dr2).prune!

expect(File).not_to exist(dr2.path)
Expand Down

0 comments on commit 6a6a06b

Please sign in to comment.