druid-tools 0.2.6

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 (46) hide show
  1. data/.gitignore +16 -0
  2. data/.rvmrc +1 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE +20 -0
  5. data/README.md +80 -0
  6. data/Rakefile +7 -0
  7. data/VERSION +1 -0
  8. data/doc/classes/DruidTools.html +132 -0
  9. data/doc/classes/DruidTools/DifferentContentExistsError.html +111 -0
  10. data/doc/classes/DruidTools/Druid.html +352 -0
  11. data/doc/classes/DruidTools/Druid.src/M000001.html +18 -0
  12. data/doc/classes/DruidTools/Druid.src/M000002.html +18 -0
  13. data/doc/classes/DruidTools/Druid.src/M000003.html +18 -0
  14. data/doc/classes/DruidTools/Druid.src/M000004.html +24 -0
  15. data/doc/classes/DruidTools/Druid.src/M000005.html +18 -0
  16. data/doc/classes/DruidTools/Druid.src/M000006.html +18 -0
  17. data/doc/classes/DruidTools/Druid.src/M000007.html +20 -0
  18. data/doc/classes/DruidTools/Druid.src/M000008.html +25 -0
  19. data/doc/classes/DruidTools/Druid.src/M000009.html +20 -0
  20. data/doc/classes/DruidTools/Druid.src/M000010.html +27 -0
  21. data/doc/classes/DruidTools/Druid.src/M000011.html +24 -0
  22. data/doc/classes/DruidTools/Druid.src/M000012.html +29 -0
  23. data/doc/classes/DruidTools/InvalidDruidError.html +111 -0
  24. data/doc/classes/DruidTools/SameContentExistsError.html +111 -0
  25. data/doc/created.rid +1 -0
  26. data/doc/files/lib/druid-tools_rb.html +108 -0
  27. data/doc/files/lib/druid_tools/druid_rb.html +108 -0
  28. data/doc/files/lib/druid_tools/exceptions_rb.html +101 -0
  29. data/doc/files/lib/druid_tools/version_rb.html +101 -0
  30. data/doc/files/lib/druid_tools_rb.html +110 -0
  31. data/doc/files/spec/druid_tools_spec_rb.html +115 -0
  32. data/doc/files/spec/spec_helper_rb.html +114 -0
  33. data/doc/fr_class_index.html +28 -0
  34. data/doc/fr_file_index.html +30 -0
  35. data/doc/fr_method_index.html +38 -0
  36. data/doc/index.html +24 -0
  37. data/doc/rdoc-style.css +208 -0
  38. data/druid-tools.gemspec +21 -0
  39. data/lib/druid-tools.rb +1 -0
  40. data/lib/druid_tools.rb +5 -0
  41. data/lib/druid_tools/druid.rb +127 -0
  42. data/lib/druid_tools/exceptions.rb +5 -0
  43. data/lib/druid_tools/version.rb +3 -0
  44. data/spec/druid_tools_spec.rb +255 -0
  45. data/spec/spec_helper.rb +3 -0
  46. metadata +133 -0
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |gem|
4
+ gem.authors = ['Michael Klein', 'Darren Hardy']
5
+ gem.email = ['mbklein@stanford.edu']
6
+ gem.description = 'Tools to manipulate DRUID trees and content directories'
7
+ gem.summary = 'Tools to manipulate DRUID trees and content directories'
8
+ gem.homepage = 'http://github.com/sul-dlss/druid-tools'
9
+ gem.licenses = ['ALv2', 'Stanford University Libraries']
10
+ gem.has_rdoc = true
11
+
12
+ gem.files = `git ls-files`.split($\)
13
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
14
+ gem.test_files = gem.files.grep(%r{^spec/})
15
+ gem.name = 'druid-tools'
16
+ gem.require_paths = ['lib']
17
+ gem.version = File.read('VERSION').strip
18
+
19
+ gem.add_development_dependency 'rake', '>= 10.1.0'
20
+ gem.add_development_dependency 'rspec', '>= 2.14.0'
21
+ end
@@ -0,0 +1 @@
1
+ require 'druid_tools'
@@ -0,0 +1,5 @@
1
+ module DruidTools
2
+ require 'druid_tools/version'
3
+ require 'druid_tools/druid'
4
+ require 'druid_tools/exceptions'
5
+ end
@@ -0,0 +1,127 @@
1
+ require 'pathname'
2
+
3
+ module DruidTools
4
+ class Druid
5
+ attr_accessor :druid, :base
6
+
7
+ class << self
8
+ attr_accessor :prefix
9
+
10
+ # @return [Regexp] matches druid:aa111aa1111 or aa111aa1111
11
+ def pattern
12
+ /\A(?:#{self.prefix}:)?([a-z]{2})(\d{3})([a-z]{2})(\d{4})\z/
13
+ end
14
+
15
+ # @return [String] suitable for use in [Dir#glob]
16
+ def glob
17
+ "{#{self.prefix}:,}[a-z][a-z][0-9][0-9][0-9][a-z][a-z][0-9][0-9][0-9][0-9]"
18
+ end
19
+
20
+ # @param [String] druid id
21
+ # @return [Boolean] true if druid matches pattern; otherwise false
22
+ def valid?(druid)
23
+ return druid =~ pattern ? true : false
24
+ end
25
+
26
+ end
27
+ self.prefix = 'druid'
28
+
29
+ [:content, :metadata, :temp].each do |dir_type|
30
+ self.class_eval <<-EOC
31
+ def #{dir_type}_dir(create=true)
32
+ path("#{dir_type}",create)
33
+ end
34
+
35
+ def find_#{dir_type}(path)
36
+ find(:#{dir_type},path)
37
+ end
38
+ EOC
39
+ end
40
+
41
+ # @param druid [String] A valid druid
42
+ # @param base [String] The directory used by #path
43
+ def initialize(druid, base='.')
44
+ druid = druid.to_s unless druid.is_a? String
45
+ unless self.class.valid?(druid)
46
+ raise ArgumentError, "Invalid DRUID: '#{druid}'"
47
+ end
48
+ druid = [self.class.prefix,druid].join(':') unless druid =~ /^#{self.class.prefix}:/
49
+ @base = base
50
+ @druid = druid
51
+ end
52
+
53
+ def id
54
+ @druid.scan(self.class.pattern).flatten.join('')
55
+ end
56
+
57
+ def tree
58
+ @druid.scan(self.class.pattern).flatten + [id]
59
+ end
60
+
61
+ def path(extra=nil, create=false)
62
+ result = File.join(*([base,tree,extra].compact))
63
+ mkdir(extra) if create and not File.exists?(result)
64
+ result
65
+ end
66
+
67
+ def mkdir(extra=nil)
68
+ new_path = path(extra)
69
+ if(File.symlink? new_path)
70
+ raise DruidTools::DifferentContentExistsError, "Unable to create directory, link already exists: #{new_path}"
71
+ end
72
+ if(File.directory? new_path)
73
+ raise DruidTools::SameContentExistsError, "The directory already exists: #{new_path}"
74
+ end
75
+ FileUtils.mkdir_p(new_path)
76
+ end
77
+
78
+ def find(type, path)
79
+ possibles = [self.path(type.to_s),self.path,File.expand_path('..',self.path)]
80
+ loc = possibles.find { |p| File.exists?(File.join(p,path)) }
81
+ loc.nil? ? nil : File.join(loc,path)
82
+ end
83
+
84
+ # @param [String] type The type of directory being sought ('content', 'metadata', or 'temp')
85
+ # @param [Array<String>,String] filelist The files that are expected to be present in the directory
86
+ # @return [Pathname] Search for and return the pathname of the directory that contains the list of files.
87
+ # Raises an exception unless a directory is found that contains all the files in the list.
88
+ def find_filelist_parent(type, filelist)
89
+ raise "File list not specified" if filelist.nil? or filelist.empty?
90
+ filelist = [filelist] unless filelist.is_a?(Array)
91
+ search_dir = Pathname(self.path(type))
92
+ directories = [search_dir, search_dir.parent, search_dir.parent.parent]
93
+ found_dir = directories.find { |pathname| pathname.join(filelist[0]).exist? }
94
+ raise "#{type} dir not found for '#{filelist[0]}' when searching '#{search_dir}'" if found_dir.nil?
95
+ filelist.each do |filename|
96
+ raise "File '#{filename}' not found in #{type} dir s'#{found_dir}'" unless found_dir.join(filename).exist?
97
+ end
98
+ found_dir
99
+ end
100
+
101
+ def mkdir_with_final_link(source, extra=nil)
102
+ new_path = path(extra)
103
+ if(File.directory?(new_path) && !File.symlink?(new_path))
104
+ raise DruidTools::DifferentContentExistsError, "Unable to create link, directory already exists: #{new_path}"
105
+ end
106
+ real_path = File.expand_path('..',new_path)
107
+ FileUtils.mkdir_p(real_path)
108
+ FileUtils.ln_s(source, new_path, :force=>true)
109
+ end
110
+
111
+ def rmdir(extra=nil)
112
+ parts = tree
113
+ parts << extra unless extra.nil?
114
+ while parts.length > 0
115
+ dir = File.join(base, *parts)
116
+ begin
117
+ FileUtils.rm(File.join(dir,'.DS_Store'), :force => true)
118
+ FileUtils.rmdir(dir)
119
+ rescue Errno::ENOTEMPTY
120
+ break
121
+ end
122
+ parts.pop
123
+ end
124
+ end
125
+
126
+ end
127
+ end
@@ -0,0 +1,5 @@
1
+ module DruidTools
2
+ class SameContentExistsError < Exception; end
3
+ class DifferentContentExistsError < Exception; end
4
+ class InvalidDruidError < Exception; end
5
+ end
@@ -0,0 +1,3 @@
1
+ module DruidTools
2
+ VERSION = File.read(File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'VERSION'))).to_s.strip
3
+ end
@@ -0,0 +1,255 @@
1
+ #require File.expand_path('../spec_helper',__FILE__)
2
+ #puts $LOAD_PATH.join("\n")
3
+ require 'druid-tools'
4
+
5
+ describe DruidTools::Druid do
6
+ before (:all) do
7
+ @fixture_dir = File.expand_path("../fixtures",__FILE__)
8
+ FileUtils.rm_rf(File.join(@fixture_dir,'cd'))
9
+ @druid_1 = 'druid:cd456ef7890'
10
+ @tree_1 = File.join(@fixture_dir,'cd/456/ef/7890/cd456ef7890')
11
+ @druid_2 = 'druid:cd456gh1234'
12
+ @tree_2 = File.join(@fixture_dir,'cd/456/gh/1234/cd456gh1234')
13
+ end
14
+
15
+ after(:each) do
16
+ FileUtils.rm_rf(File.join(@fixture_dir,'cd'))
17
+ end
18
+
19
+ it "should be able to validate druid strings using the valid? class method" do
20
+ tests = [
21
+ # Expected Input druid
22
+ [true, 'druid:aa000bb0001'],
23
+ [true, 'aa000bb0001'],
24
+ [false, 'Aa000bb0001'],
25
+ [false, "xxx\naa000bb0001"],
26
+ [false, 'aaa000bb0001'],
27
+ [false, 'druidX:aa000bb0001'],
28
+ [false, ':aa000bb0001'],
29
+ [true, 'aa123bb1234'],
30
+ [false, 'aa12bb1234'],
31
+ [false, 'aa1234bb1234'],
32
+ [false, 'aa123bb123'],
33
+ [false, 'aa123bb12345'],
34
+ [false, 'a123bb1234'],
35
+ [false, 'aaa123bb1234'],
36
+ [false, 'aa123b1234'],
37
+ [false, 'aa123bbb1234'],
38
+ [false, 'druid:az918AZ9381'.upcase],
39
+ [true, 'druid:az918AZ9381'.downcase],
40
+ [true, 'druid:zz943vx1492']
41
+ ]
42
+ tests.each do |exp, dru|
43
+ DruidTools::Druid.valid?(dru).should == exp
44
+ end
45
+ end
46
+
47
+ it "should provide the full druid including the prefix" do
48
+ DruidTools::Druid.new('druid:cd456ef7890',@fixture_dir).druid.should == 'druid:cd456ef7890'
49
+ DruidTools::Druid.new('cd456ef7890',@fixture_dir).druid.should == 'druid:cd456ef7890'
50
+ end
51
+
52
+ it "should extract the ID from the stem" do
53
+ DruidTools::Druid.new('druid:cd456ef7890',@fixture_dir).id.should == 'cd456ef7890'
54
+ DruidTools::Druid.new('cd456ef7890',@fixture_dir).id.should == 'cd456ef7890'
55
+ end
56
+
57
+ it "should raise an exception if the druid is invalid" do
58
+ lambda { DruidTools::Druid.new('nondruid:cd456ef7890',@fixture_dir) }.should raise_error(ArgumentError)
59
+ lambda { DruidTools::Druid.new('druid:cd4567ef890',@fixture_dir) }.should raise_error(ArgumentError)
60
+ end
61
+
62
+ it "should build a druid tree from a druid" do
63
+ druid = DruidTools::Druid.new(@druid_1,@fixture_dir)
64
+ druid.tree.should == ['cd','456','ef','7890','cd456ef7890']
65
+ druid.path.should == @tree_1
66
+ end
67
+
68
+ it "should create and destroy druid directories" do
69
+ File.exists?(@tree_1).should be_false
70
+ File.exists?(@tree_2).should be_false
71
+
72
+ druid_1 = DruidTools::Druid.new(@druid_1,@fixture_dir)
73
+ druid_2 = DruidTools::Druid.new(@druid_2,@fixture_dir)
74
+
75
+ druid_1.mkdir
76
+ File.exists?(@tree_1).should be_true
77
+ File.exists?(@tree_2).should be_false
78
+
79
+ druid_2.mkdir
80
+ File.exists?(@tree_1).should be_true
81
+ File.exists?(@tree_2).should be_true
82
+
83
+ druid_2.rmdir
84
+ File.exists?(@tree_1).should be_true
85
+ File.exists?(@tree_2).should be_false
86
+
87
+ druid_1.rmdir
88
+ File.exists?(@tree_1).should be_false
89
+ File.exists?(@tree_2).should be_false
90
+ File.exists?(File.join(@fixture_dir,'cd')).should be_false
91
+ end
92
+
93
+ describe "alternate prefixes" do
94
+ before :all do
95
+ DruidTools::Druid.prefix = 'sulair'
96
+ end
97
+
98
+ after :all do
99
+ DruidTools::Druid.prefix = 'druid'
100
+ end
101
+
102
+ it "should handle alternate prefixes" do
103
+ lambda { DruidTools::Druid.new('druid:cd456ef7890',@fixture_dir) }.should raise_error(ArgumentError)
104
+ DruidTools::Druid.new('sulair:cd456ef7890',@fixture_dir).id.should == 'cd456ef7890'
105
+ DruidTools::Druid.new('cd456ef7890',@fixture_dir).druid.should == 'sulair:cd456ef7890'
106
+ end
107
+ end
108
+
109
+ describe "content directories" do
110
+ it "should know where its content goes" do
111
+ druid = DruidTools::Druid.new(@druid_1,@fixture_dir)
112
+ druid.content_dir(false).should == File.join(@tree_1,'content')
113
+ druid.metadata_dir(false).should == File.join(@tree_1,'metadata')
114
+ druid.temp_dir(false).should == File.join(@tree_1,'temp')
115
+
116
+ File.exists?(File.join(@tree_1,'content')).should be_false
117
+ File.exists?(File.join(@tree_1,'metadata')).should be_false
118
+ File.exists?(File.join(@tree_1,'temp')).should be_false
119
+ end
120
+
121
+ it "should create its content directories on the fly" do
122
+ druid = DruidTools::Druid.new(@druid_1,@fixture_dir)
123
+ druid.content_dir.should == File.join(@tree_1,'content')
124
+ druid.metadata_dir.should == File.join(@tree_1,'metadata')
125
+ druid.temp_dir.should == File.join(@tree_1,'temp')
126
+
127
+ File.exists?(File.join(@tree_1,'content')).should be_true
128
+ File.exists?(File.join(@tree_1,'metadata')).should be_true
129
+ File.exists?(File.join(@tree_1,'temp')).should be_true
130
+ end
131
+
132
+ it "should match glob" do
133
+ druid = DruidTools::Druid.new(@druid_1,@fixture_dir)
134
+ druid.mkdir
135
+ Dir.glob(File.join(File.dirname(druid.path), DruidTools::Druid::glob)).size.should == 1
136
+ end
137
+ end
138
+
139
+ describe "content discovery" do
140
+ before :all do
141
+ @druid = DruidTools::Druid.new(@druid_1,@fixture_dir)
142
+ @filelist = %w(1 2 3 4).collect { |num| "someFile#{num}" }
143
+ end
144
+
145
+ it "should find content in content directories" do
146
+ location = @druid.content_dir
147
+ File.open(File.join(location,'someContent'),'w') { |f| f.write 'This is the content' }
148
+ @druid.find_content('someContent').should == File.join(location,'someContent')
149
+ end
150
+
151
+ it "should find content in the root directory" do
152
+ location = @druid.path(nil,true)
153
+ File.open(File.join(location,'someContent'),'w') { |f| f.write 'This is the content' }
154
+ @druid.find_content('someContent').should == File.join(location,'someContent')
155
+ end
156
+
157
+ it "should find content in the leaf directory" do
158
+ location = File.expand_path('..',@druid.path(nil,true))
159
+ File.open(File.join(location,'someContent'),'w') { |f| f.write 'This is the content' }
160
+ @druid.find_content('someContent').should == File.join(location,'someContent')
161
+ end
162
+
163
+ it "should not find content in the wrong content directory" do
164
+ location = @druid.metadata_dir
165
+ File.open(File.join(location,'someContent'),'w') { |f| f.write 'This is the content' }
166
+ @druid.find_content('someContent').should be_nil
167
+ end
168
+
169
+ it "should not find content in a higher-up directory" do
170
+ location = File.expand_path('../..',@druid.path(nil,true))
171
+ File.open(File.join(location,'someContent'),'w') { |f| f.write 'This is the content' }
172
+ @druid.find_content('someContent').should be_nil
173
+ end
174
+
175
+ it "should find a filelist in the content directory" do
176
+ location = Pathname(@druid.content_dir)
177
+ @filelist.each do |filename|
178
+ location.join(filename).open('w') { |f| f.write "This is #{filename}" }
179
+ end
180
+ @druid.find_filelist_parent('content',@filelist).should == location
181
+ end
182
+
183
+ it "should find a filelist in the root directory" do
184
+ location = Pathname(@druid.path(nil,true))
185
+ @filelist.each do |filename|
186
+ location.join(filename).open('w') { |f| f.write "This is #{filename}" }
187
+ end
188
+ @druid.find_filelist_parent('content',@filelist).should == location
189
+ end
190
+
191
+ it "should find a filelist in the leaf directory" do
192
+ location = Pathname(File.expand_path('..',@druid.path(nil,true)))
193
+ @filelist.each do |filename|
194
+ location.join(filename).open('w') { |f| f.write "This is #{filename}" }
195
+ end
196
+ @druid.find_filelist_parent('content',@filelist).should == location
197
+ end
198
+
199
+ it "should raise an exception if the first file in the filelist is not found" do
200
+ location = Pathname(@druid.content_dir)
201
+ lambda{@druid.find_filelist_parent('content',@filelist)}.should raise_exception(/content dir not found for 'someFile1' when searching/)
202
+ end
203
+
204
+ it "should raise an exception if any other file in the filelist is not found" do
205
+ location = Pathname(@druid.content_dir)
206
+ location.join(@filelist.first).open('w') { |f| f.write "This is #{@filelist.first}" }
207
+ lambda{@druid.find_filelist_parent('content',@filelist)}.should raise_exception(/File 'someFile2' not found/)
208
+ end
209
+
210
+ end
211
+
212
+ describe "#mkdir error handling" do
213
+ it "raises SameContentExistsError if the directory already exists" do
214
+ druid_2 = DruidTools::Druid.new(@druid_2,@fixture_dir)
215
+ druid_2.mkdir
216
+ lambda { druid_2.mkdir }.should raise_error(DruidTools::SameContentExistsError)
217
+ end
218
+
219
+ it "raises DifferentContentExistsError if a link already exists in the workspace for this druid" do
220
+ source_dir = '/tmp/content_dir'
221
+ FileUtils.mkdir_p(source_dir)
222
+ dr = DruidTools::Druid.new(@druid_2,@fixture_dir)
223
+ dr.mkdir_with_final_link(source_dir)
224
+ lambda { dr.mkdir }.should raise_error(DruidTools::DifferentContentExistsError)
225
+ end
226
+ end
227
+
228
+ describe "#mkdir_with_final_link" do
229
+
230
+ before(:each) do
231
+ @source_dir = '/tmp/content_dir'
232
+ FileUtils.mkdir_p(@source_dir)
233
+ @dr = DruidTools::Druid.new(@druid_2,@fixture_dir)
234
+ end
235
+
236
+ it "creates a druid tree in the workspace with the final directory being a link to the passed in source" do
237
+ @dr.mkdir_with_final_link(@source_dir)
238
+
239
+ File.should be_symlink(@dr.path)
240
+ File.readlink(@tree_2).should == @source_dir
241
+ end
242
+
243
+ it "should not error out if the link to source already exists" do
244
+ @dr.mkdir_with_final_link(@source_dir)
245
+ File.should be_symlink(@dr.path)
246
+ File.readlink(@tree_2).should == @source_dir
247
+ end
248
+
249
+ it "raises DifferentContentExistsError if a directory already exists in the workspace for this druid" do
250
+ @dr.mkdir(@fixture_dir)
251
+ lambda { @dr.mkdir_with_final_link(@source_di) }.should raise_error(DruidTools::DifferentContentExistsError)
252
+ end
253
+ end
254
+
255
+ end
@@ -0,0 +1,3 @@
1
+ #$LOAD_PATH.unshift(File.expand_path('../../lib',__FILE__))
2
+
3
+ require 'bundler/setup'
metadata ADDED
@@ -0,0 +1,133 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: druid-tools
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.6
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Michael Klein
9
+ - Darren Hardy
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2013-10-15 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rake
17
+ requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: 10.1.0
23
+ type: :development
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ! '>='
29
+ - !ruby/object:Gem::Version
30
+ version: 10.1.0
31
+ - !ruby/object:Gem::Dependency
32
+ name: rspec
33
+ requirement: !ruby/object:Gem::Requirement
34
+ none: false
35
+ requirements:
36
+ - - ! '>='
37
+ - !ruby/object:Gem::Version
38
+ version: 2.14.0
39
+ type: :development
40
+ prerelease: false
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: 2.14.0
47
+ description: Tools to manipulate DRUID trees and content directories
48
+ email:
49
+ - mbklein@stanford.edu
50
+ executables: []
51
+ extensions: []
52
+ extra_rdoc_files: []
53
+ files:
54
+ - .gitignore
55
+ - .rvmrc
56
+ - Gemfile
57
+ - LICENSE
58
+ - README.md
59
+ - Rakefile
60
+ - VERSION
61
+ - doc/classes/DruidTools.html
62
+ - doc/classes/DruidTools/DifferentContentExistsError.html
63
+ - doc/classes/DruidTools/Druid.html
64
+ - doc/classes/DruidTools/Druid.src/M000001.html
65
+ - doc/classes/DruidTools/Druid.src/M000002.html
66
+ - doc/classes/DruidTools/Druid.src/M000003.html
67
+ - doc/classes/DruidTools/Druid.src/M000004.html
68
+ - doc/classes/DruidTools/Druid.src/M000005.html
69
+ - doc/classes/DruidTools/Druid.src/M000006.html
70
+ - doc/classes/DruidTools/Druid.src/M000007.html
71
+ - doc/classes/DruidTools/Druid.src/M000008.html
72
+ - doc/classes/DruidTools/Druid.src/M000009.html
73
+ - doc/classes/DruidTools/Druid.src/M000010.html
74
+ - doc/classes/DruidTools/Druid.src/M000011.html
75
+ - doc/classes/DruidTools/Druid.src/M000012.html
76
+ - doc/classes/DruidTools/InvalidDruidError.html
77
+ - doc/classes/DruidTools/SameContentExistsError.html
78
+ - doc/created.rid
79
+ - doc/files/lib/druid-tools_rb.html
80
+ - doc/files/lib/druid_tools/druid_rb.html
81
+ - doc/files/lib/druid_tools/exceptions_rb.html
82
+ - doc/files/lib/druid_tools/version_rb.html
83
+ - doc/files/lib/druid_tools_rb.html
84
+ - doc/files/spec/druid_tools_spec_rb.html
85
+ - doc/files/spec/spec_helper_rb.html
86
+ - doc/fr_class_index.html
87
+ - doc/fr_file_index.html
88
+ - doc/fr_method_index.html
89
+ - doc/index.html
90
+ - doc/rdoc-style.css
91
+ - druid-tools.gemspec
92
+ - lib/druid-tools.rb
93
+ - lib/druid_tools.rb
94
+ - lib/druid_tools/druid.rb
95
+ - lib/druid_tools/exceptions.rb
96
+ - lib/druid_tools/version.rb
97
+ - spec/druid_tools_spec.rb
98
+ - spec/spec_helper.rb
99
+ homepage: http://github.com/sul-dlss/druid-tools
100
+ licenses:
101
+ - ALv2
102
+ - Stanford University Libraries
103
+ post_install_message:
104
+ rdoc_options: []
105
+ require_paths:
106
+ - lib
107
+ required_ruby_version: !ruby/object:Gem::Requirement
108
+ none: false
109
+ requirements:
110
+ - - ! '>='
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ segments:
114
+ - 0
115
+ hash: -3564401623141727809
116
+ required_rubygems_version: !ruby/object:Gem::Requirement
117
+ none: false
118
+ requirements:
119
+ - - ! '>='
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ segments:
123
+ - 0
124
+ hash: -3564401623141727809
125
+ requirements: []
126
+ rubyforge_project:
127
+ rubygems_version: 1.8.23
128
+ signing_key:
129
+ specification_version: 3
130
+ summary: Tools to manipulate DRUID trees and content directories
131
+ test_files:
132
+ - spec/druid_tools_spec.rb
133
+ - spec/spec_helper.rb