Merge branch '3136-stale-pipeline-instance-display' closes #3136
[arvados.git] / apps / workbench / app / controllers / actions_controller.rb
1 class ActionsController < ApplicationController
2
3   @@exposed_actions = {}
4   def self.expose_action method, &block
5     @@exposed_actions[method] = true
6     define_method method, block
7   end
8
9   def model_class
10     ArvadosBase::resource_class_for_uuid(params[:uuid])
11   end
12
13   def show
14     @object = model_class.andand.find(params[:uuid])
15     if @object.is_a? Link and
16         @object.link_class == 'name' and
17         ArvadosBase::resource_class_for_uuid(@object.head_uuid) == Collection
18       redirect_to collection_path(id: @object.uuid)
19     elsif @object
20       redirect_to @object
21     else
22       raise ActiveRecord::RecordNotFound
23     end
24   end
25
26   def post
27     params.keys.collect(&:to_sym).each do |param|
28       if @@exposed_actions[param]
29         return self.send(param)
30       end
31     end
32     redirect_to :back
33   end
34
35   expose_action :copy_selections_into_project do
36     move_or_copy :copy
37   end
38
39   expose_action :move_selections_into_project do
40     move_or_copy :move
41   end
42
43   def move_or_copy action
44     uuids_to_add = params["selection"]
45     uuids_to_add = [ uuids_to_add ] unless uuids_to_add.is_a? Array
46     uuids_to_add.
47       collect { |x| ArvadosBase::resource_class_for_uuid(x) }.
48       uniq.
49       each do |resource_class|
50       resource_class.filter([['uuid','in',uuids_to_add]]).each do |src|
51         if resource_class == Collection and not Collection.attribute_info.include?(:name)
52           dst = Link.new(owner_uuid: @object.uuid,
53                          tail_uuid: @object.uuid,
54                          head_uuid: src.uuid,
55                          link_class: 'name',
56                          name: src.uuid)
57         else
58           case action
59           when :copy
60             dst = src.dup
61             if dst.respond_to? :'name='
62               if dst.name
63                 dst.name = "Copy of #{dst.name}"
64               else
65                 dst.name = "Copy of unnamed #{dst.class_for_display.downcase}"
66               end
67             end
68             if resource_class == Collection
69               dst.manifest_text = Collection.select([:manifest_text]).where(uuid: src.uuid).first.manifest_text
70             end
71           when :move
72             dst = src
73           else
74             raise ArgumentError.new "Unsupported action #{action}"
75           end
76           dst.owner_uuid = @object.uuid
77           dst.tail_uuid = @object.uuid if dst.class == Link
78         end
79         begin
80           dst.save!
81         rescue
82           dst.name += " (#{Time.now.localtime})" if dst.respond_to? :name=
83           dst.save!
84         end
85       end
86     end
87     redirect_to @object
88   end
89
90   def arv_normalize mt, *opts
91     r = ""
92     env = Hash[ENV].
93       merge({'ARVADOS_API_HOST' =>
94               arvados_api_client.arvados_v1_base.
95               sub(/\/arvados\/v1/, '').
96               sub(/^https?:\/\//, ''),
97               'ARVADOS_API_TOKEN' => 'x',
98               'ARVADOS_API_HOST_INSECURE' =>
99               Rails.configuration.arvados_insecure_https ? 'true' : 'false'
100             })
101     IO.popen([env, 'arv-normalize'] + opts, 'w+b') do |io|
102       io.write mt
103       io.close_write
104       while buf = io.read(2**16)
105         r += buf
106       end
107     end
108     r
109   end
110
111   expose_action :combine_selected_files_into_collection do
112     lst = []
113     files = []
114     params["selection"].each do |s|
115       a = ArvadosBase::resource_class_for_uuid s
116       m = nil
117       if a == Link
118         begin
119           m = CollectionsHelper.match(Link.find(s).head_uuid)
120         rescue
121         end
122       else
123         m = CollectionsHelper.match(s)
124       end
125
126       if m and m[1] and m[2]
127         lst.append(m[1] + m[2])
128         files.append(m)
129       end
130     end
131
132     collections = Collection.where(uuid: lst)
133
134     chash = {}
135     collections.each do |c|
136       c.reload()
137       chash[c.uuid] = c
138     end
139
140     combined = ""
141     files.each do |m|
142       mt = chash[m[1]+m[2]].manifest_text
143       if m[4]
144         combined += arv_normalize mt, '--extract', m[4][1..-1]
145       else
146         combined += chash[m[1]+m[2]].manifest_text
147       end
148     end
149
150     normalized = arv_normalize combined
151     newc = Collection.new({:manifest_text => normalized})
152     newc.save!
153
154     chash.each do |k,v|
155       l = Link.new({
156                      tail_uuid: k,
157                      head_uuid: newc.uuid,
158                      link_class: "provenance",
159                      name: "provided"
160                    })
161       l.save!
162     end
163
164     redirect_to controller: 'collections', action: :show, id: newc.uuid
165   end
166
167 end