X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/d6cc9d6e055974384be446f6da8218ff7da048ae..eb7227693e8847a65798afa7f7e8a4ffe8a199a4:/services/api/app/models/collection.rb diff --git a/services/api/app/models/collection.rb b/services/api/app/models/collection.rb index df84b09dfb..600c07511b 100644 --- a/services/api/app/models/collection.rb +++ b/services/api/app/models/collection.rb @@ -8,6 +8,10 @@ class Collection < ArvadosModel t.add :files end + api_accessible :with_data, extend: :user do |t| + t.add :manifest_text + end + def redundancy_status if redundancy_confirmed_as.nil? 'unconfirmed' @@ -28,17 +32,19 @@ class Collection < ArvadosModel if self.manifest_text.nil? and self.uuid.nil? super elsif self.manifest_text and self.uuid - if self.uuid.gsub(/\+[^,]+/,'') == Digest::MD5.hexdigest(self.manifest_text) + self.uuid.gsub! /\+.*/, '' + if self.uuid == Digest::MD5.hexdigest(self.manifest_text) + self.uuid.gsub! /$/, '+' + self.manifest_text.length.to_s true else - errors.add :uuid, 'uuid does not match checksum of manifest_text' + errors.add :uuid, 'does not match checksum of manifest_text' false end elsif self.manifest_text - errors.add :uuid, 'checksum for manifest_text not supplied in uuid' + errors.add :uuid, 'not supplied (must match checksum of manifest_text)' false else - errors.add :manifest_text, 'manifest_text not supplied' + errors.add :manifest_text, 'not supplied' false end end @@ -59,10 +65,29 @@ class Collection < ArvadosModel @files = [] return end + + #normalized_manifest = "" + #IO.popen(['arv-normalize'], 'w+b') do |io| + # io.write manifest_text + # io.close_write + # while buf = io.read(2**20) + # normalized_manifest += buf + # end + #end + @data_size = 0 - @files = [] + tmp = {} + manifest_text.split("\n").each do |stream| toks = stream.split(" ") + + stream = toks[0].gsub /\\(\\|[0-7]{3})/ do |escape_sequence| + case $1 + when '\\' '\\' + else $1.to_i(8).chr + end + end + toks[1..-1].each do |tok| if (re = tok.match /^[0-9a-f]{32}/) blocksize = nil @@ -78,10 +103,48 @@ class Collection < ArvadosModel @data_size += blocksize if @data_size else if (re = tok.match /^(\d+):(\d+):(\S+)$/) - @files << [toks[0], re[3], re[2].to_i] + filename = re[3].gsub /\\(\\|[0-7]{3})/ do |escape_sequence| + case $1 + when '\\' '\\' + else $1.to_i(8).chr + end + end + fn = stream + '/' + filename + i = re[2].to_i + if tmp[fn] + tmp[fn] += i + else + tmp[fn] = i + end end end end end + + @files = [] + tmp.each do |k, v| + re = k.match(/^(.+)\/(.+)/) + @files << [re[1], re[2], v] + end + end + + def self.uuid_like_pattern + "________________________________+%" + end + + def self.normalize_uuid uuid + hash_part = nil + size_part = nil + uuid.split('+').each do |token| + if token.match /^[0-9a-f]{32,}$/ + raise "uuid #{uuid} has multiple hash parts" if hash_part + hash_part = token + elsif token.match /^\d+$/ + raise "uuid #{uuid} has multiple size parts" if size_part + size_part = token + end + end + raise "uuid #{uuid} has no hash part" if !hash_part + [hash_part, size_part].compact.join '+' end end