lib/bagit/manifest.rb in bagit-0.2.0 vs lib/bagit/manifest.rb in bagit-0.3.0.pre

- old
+ new

@@ -7,11 +7,14 @@ # Requires response to bag_dir, tag_files, bag_files module Manifest # All tag files that are bag manifest files (manifest-[algorithm].txt) def manifest_files - tag_files.select { |f| File.basename(f) =~ /^manifest-.*.txt/ } + files = Dir[File.join(@bag_dir, '*')].select { |f| + File.file? f and File.basename(f) =~ /^manifest-.*.txt/ + } + files end # A path to a manifest file of the specified algorithm def manifest_file(algo) File.join bag_dir, "manifest-#{algo}.txt" @@ -24,53 +27,107 @@ manifest_files.each { |f| FileUtils::rm f } # manifest each tag file for each algorithm bag_files.each do |f| rel_path = Pathname.new(f).relative_path_from(Pathname.new(bag_dir)).to_s - data = open(f) { |io| io.read } # sha1 - sha1 = Digest::SHA1.hexdigest data + sha1 = Digest::SHA1.file f open(manifest_file(:sha1), 'a') { |io| io.puts "#{sha1} #{rel_path}" } # md5 - md5 = Digest::MD5.hexdigest data + md5 = Digest::MD5.file f open(manifest_file(:md5), 'a') { |io| io.puts "#{md5} #{rel_path}" } end end # All tag files that are bag manifest files (tagmanifest-[algorithm].txt) def tagmanifest_files - tag_files.select { |f| File.basename(f) =~ /^tagmanifest-.*.txt/ } + files = Dir[File.join(@bag_dir, '*')].select { |f| + File.file? f and File.basename(f) =~ /^tagmanifest-.*.txt/ + } + files end # A path to a tagmanifest file of the specified algorithm def tagmanifest_file(algo) File.join bag_dir, "tagmanifest-#{algo}.txt" end # Generate manifest files for all the tag files (except the tag # manifest files) - def tagmanifest! + def tagmanifest!(tags=nil) + + tags = tag_files if tags == nil # nuke all the existing tagmanifest files tagmanifest_files.each { |f| FileUtils::rm f } + + # ensure presence of manfiest files + manifest_files.each do |manifest| + tags << manifest unless tags.include?(manifest) + end + # ensure presence of bag info files + tags << bag_info_txt_file unless tags.include?(bag_info_txt_file) + tags << bagit_txt_file unless tags.include?(bagit_txt_file) + # manifest each (non tagmanifest) tag file for each algorithm - (tag_files - tagmanifest_files).each do |f| - data = open(f) { |io| io.read } - rel_path = File.basename f + tags.each do |f| + add_tag_file(Pathname.new(f).relative_path_from(Pathname.new(bag_dir)).to_s) + end + tag_files + end - # sha1 - sha1 = Digest::SHA1.hexdigest data - open(tagmanifest_file(:sha1), 'a') { |io| io.puts "#{sha1} #{rel_path}" } + def add_tag_file(path, src_path=nil) - # md5 - md5 = Digest::MD5.hexdigest data - open(tagmanifest_file(:md5), 'a') { |io| io.puts "#{md5} #{rel_path}" } + f = File.join(@bag_dir, path) + raise "Tag file already in manifest: #{path}" if tag_files.include?(f) + + if not File.exist? f + FileUtils::mkdir_p File.dirname(f) + + # write file + if src_path.nil? + open(f, 'w') { |io| yield io } + else + FileUtils::cp src_path, f + end + # this adds the manifest and bag info files on initial creation + # it must only run when the manifest doesn't already exist or it will + # infinitely recall add_tag_file. Better way of doing this? + tagmanifest! + elsif not src_path.nil? + raise "Tag file already exists, will not overwrite: #{path}\n Use add_tag_file(path) to add an existing tag file." end + data = open(f) { |io| io.read } + rel_path = Pathname.new(f).relative_path_from(Pathname.new(bag_dir)).to_s + + # sha1 + sha1 = Digest::SHA1.hexdigest data + open(tagmanifest_file(:sha1), 'a') { |io| io.puts "#{sha1} #{rel_path}" } + + # md5 + md5 = Digest::MD5.hexdigest data + open(tagmanifest_file(:md5), 'a') { |io| io.puts "#{md5} #{rel_path}" } + tag_files + end + + def remove_tag_file(path) + tags = tag_files + raise "Tag file is not in manifest: #{path}" unless tags.include?(File.join(@bag_dir, path)) + tags.delete(File.join(@bag_dir, path)) + tagmanifest!(tags) + end + + def delete_tag_file(path) + filepath = File.join(@bag_dir, path) + raise "Tag file does not exist: #{path}" unless File.exist? filepath + #TODO: delete tags even when they are not in the manifest + remove_tag_file(path) + FileUtils::rm filepath end # Returns true if all present manifested files' message digests # match the actual message digest def fixed?