X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/7024cc159936593350aaf7939d700102f6510787..549f4a1deddb41f6abbc493a660d9fb0976da91a:/services/api/app/models/collection.rb diff --git a/services/api/app/models/collection.rb b/services/api/app/models/collection.rb index f6c8b26598..64a6bb0530 100644 --- a/services/api/app/models/collection.rb +++ b/services/api/app/models/collection.rb @@ -1,5 +1,5 @@ class Collection < ArvadosModel - include AssignUuid + include HasUuid include KindAndEtag include CommonApiTemplate @@ -65,8 +65,19 @@ 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(" ") @@ -98,11 +109,27 @@ class Collection < ArvadosModel else $1.to_i(8).chr end end - @files << [stream, filename, re[2].to_i] + 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 @@ -120,4 +147,49 @@ class Collection < ArvadosModel raise "uuid #{uuid} has no hash part" if !hash_part [hash_part, size_part].compact.join '+' end + + def self.for_latest_docker_image(search_term, search_tag=nil, readers=nil) + readers ||= [Thread.current[:user]] + base_search = Link. + readable_by(*readers). + readable_by(*readers, table_name: "collections"). + joins("JOIN collections ON links.head_uuid = collections.uuid"). + order("links.created_at DESC") + + # If the search term is a Collection locator with an associated + # Docker image hash link, return that Collection. + coll_matches = base_search. + where(link_class: "docker_image_hash", collections: {uuid: search_term}) + if match = coll_matches.first + return find_by_uuid(match.head_uuid) + end + + # Find Collections with matching Docker image repository+tag pairs. + matches = base_search. + where(link_class: "docker_image_repo+tag", + name: "#{search_term}:#{search_tag || 'latest'}") + + # If that didn't work, find Collections with matching Docker image hashes. + if matches.empty? + matches = base_search. + where("link_class = ? and name LIKE ?", + "docker_image_hash", "#{search_term}%") + end + + # Select the image that was created most recently. Note that the + # SQL search order and fallback timestamp values are chosen so + # that if image timestamps are missing, we use the image with the + # newest link. + latest_image_link = nil + latest_image_timestamp = "1900-01-01T00:00:00Z" + matches.find_each do |link| + link_timestamp = link.properties.fetch("image_timestamp", + "1900-01-01T00:00:01Z") + if link_timestamp > latest_image_timestamp + latest_image_link = link + latest_image_timestamp = link_timestamp + end + end + latest_image_link.nil? ? nil : find_by_uuid(latest_image_link.head_uuid) + end end