Module: BagIt::Manifest

Included in:
Bag
Defined in:
lib/bagit/manifest.rb

Overview

Requires response to bag_dir, tag_files, bag_files

Instance Method Summary collapse

Instance Method Details

#add_tag_file(path, src_path = nil) ⇒ Object



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/bagit/manifest.rb', line 82

def add_tag_file(path, src_path=nil)

  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?
      File.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 = File.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
  File.open(tagmanifest_file(:sha1), 'a') { |io| io.puts "#{sha1} #{rel_path}" }

  # md5
  md5 = Digest::MD5.hexdigest data
  File.open(tagmanifest_file(:md5), 'a') { |io| io.puts "#{md5} #{rel_path}" }
  tag_files
end

#delete_tag_file(path) ⇒ Object



124
125
126
127
128
129
# File 'lib/bagit/manifest.rb', line 124

def delete_tag_file(path)
  filepath = File.join(@bag_dir, path)
  raise "Tag file does not exist: #{path}" unless File.exist? filepath
  remove_tag_file(path) if tag_files.include?(path)
  FileUtils::rm filepath
end

#fixed?Boolean

Returns true if all present manifested files’ message digests match the actual message digest

Returns:

  • (Boolean)


133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/bagit/manifest.rb', line 133

def fixed?
  (manifest_files + tagmanifest_files).all? do |mf|
    # extract the algorithm
    mf =~ /manifest-(.+).txt$/

    algo = case $1
           when /sha1/i
             Digest::SHA1
           when /md5/i
             Digest::MD5
           else
             :unknown
           end

    # check it, an unknown algorithm is always true
    unless algo == :unknown
      lines = File.open(mf) { |io| io.readlines }

      lines.all? do |line|
        manifested_digest, path = line.chomp.split /\s+/, 2
        actual_digest = File.open(File.join(@bag_dir, path)) { |io| algo.hexdigest io.read }
        actual_digest == manifested_digest
      end

    else
      true
    end

  end

end

#manifest!Object

Generate manifest files for all the bag files



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/bagit/manifest.rb', line 24

def manifest!

  # nuke all the existing manifest files
  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

    # sha1
    sha1 = Digest::SHA1.file f
    File.open(manifest_file(:sha1), 'a') { |io| io.puts "#{sha1} #{rel_path}" }

    # md5
    md5 = Digest::MD5.file f
    File.open(manifest_file(:md5), 'a') { |io| io.puts "#{md5} #{rel_path}" }
  end
  tagmanifest!
end

#manifest_file(algo) ⇒ Object

A path to a manifest file of the specified algorithm



19
20
21
# File 'lib/bagit/manifest.rb', line 19

def manifest_file(algo)
  File.join bag_dir, "manifest-#{algo}.txt"
end

#manifest_filesObject

All tag files that are bag manifest files (manifest-.txt)



11
12
13
14
15
16
# File 'lib/bagit/manifest.rb', line 11

def manifest_files
  files = Dir[File.join(@bag_dir, '*')].select { |f|
    File.file? f and File.basename(f) =~ /^manifest-.*.txt/
  }
  files
end

#remove_tag_file(path) ⇒ Object



117
118
119
120
121
122
# File 'lib/bagit/manifest.rb', line 117

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

#tagmanifest!(tags = nil) ⇒ Object

Generate manifest files for all the tag files (except the tag manifest files)



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/bagit/manifest.rb', line 59

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
  tags.each do |f|
    add_tag_file(Pathname.new(f).relative_path_from(Pathname.new(bag_dir)).to_s)
  end
  tag_files
end

#tagmanifest_file(algo) ⇒ Object

A path to a tagmanifest file of the specified algorithm



53
54
55
# File 'lib/bagit/manifest.rb', line 53

def tagmanifest_file(algo)
  File.join bag_dir, "tagmanifest-#{algo}.txt"
end

#tagmanifest_filesObject

All tag files that are bag manifest files (tagmanifest-.txt)



45
46
47
48
49
50
# File 'lib/bagit/manifest.rb', line 45

def tagmanifest_files
  files = Dir[File.join(@bag_dir, '*')].select { |f|
    File.file? f and File.basename(f) =~ /^tagmanifest-.*.txt/
  }
  files
end