2872: Fix bugs, tweak formatting
[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 post
14     params.keys.collect(&:to_sym).each do |param|
15       if @@exposed_actions[param]
16         return self.send(param)
17       end
18     end
19     redirect_to :back
20   end
21
22   expose_action :copy_selections_into_project do
23     move_or_copy :copy
24   end
25
26   expose_action :move_selections_into_project do
27     move_or_copy :move
28   end
29
30   def move_or_copy action
31     uuids_to_add = params["selection"]
32     uuids_to_add.
33       collect { |x| ArvadosBase::resource_class_for_uuid(x) }.
34       uniq.
35       each do |resource_class|
36       resource_class.filter([['uuid','in',uuids_to_add]]).each do |src|
37         if resource_class == Collection
38           dst = Link.new(owner_uuid: @object.uuid,
39                          tail_uuid: @object.uuid,
40                          head_uuid: src.uuid,
41                          link_class: 'name',
42                          name: src.uuid)
43         else
44           case action
45           when :copy
46             dst = src.dup
47             if dst.respond_to? :'name='
48               if dst.name
49                 dst.name = "Copy of #{dst.name}"
50               else
51                 dst.name = "Copy of unnamed #{dst.class_for_display.downcase}"
52               end
53             end
54           when :move
55             dst = src
56           else
57             raise ArgumentError.new "Unsupported action #{action}"
58           end
59           dst.owner_uuid = @object.uuid
60           dst.tail_uuid = @object.uuid if dst.class == Link
61         end
62         begin
63           dst.save!
64         rescue
65           dst.name += " (#{Time.now.localtime})" if dst.respond_to? :name=
66           dst.save!
67         end
68       end
69     end
70     redirect_to @object
71   end
72
73   expose_action :combine_selected_files_into_collection do
74     lst = []
75     files = []
76     params["selection"].each do |s|
77       m = CollectionsHelper.match(s)
78       if m and m[1] and m[2]
79         lst.append(m[1] + m[2])
80         files.append(m)
81       end
82     end
83
84     collections = Collection.where(uuid: lst)
85
86     chash = {}
87     collections.each do |c|
88       c.reload()
89       chash[c.uuid] = c
90     end
91
92     combined = ""
93     files.each do |m|
94       mt = chash[m[1]+m[2]].manifest_text
95       if m[4]
96         IO.popen(['arv-normalize', '--extract', m[4][1..-1]], 'w+b') do |io|
97           io.write mt
98           io.close_write
99           while buf = io.read(2**20)
100             combined += buf
101           end
102         end
103       else
104         combined += chash[m[1]+m[2]].manifest_text
105       end
106     end
107
108     normalized = ''
109     IO.popen(['arv-normalize'], 'w+b') do |io|
110       io.write combined
111       io.close_write
112       while buf = io.read(2**20)
113         normalized += buf
114       end
115     end
116
117     require 'digest/md5'
118
119     d = Digest::MD5.new()
120     d << normalized
121     newuuid = "#{d.hexdigest}+#{normalized.length}"
122
123     env = Hash[ENV].
124       merge({
125               'ARVADOS_API_HOST' =>
126               arvados_api_client.arvados_v1_base.
127               sub(/\/arvados\/v1/, '').
128               sub(/^https?:\/\//, ''),
129               'ARVADOS_API_TOKEN' => Thread.current[:arvados_api_token],
130               'ARVADOS_API_HOST_INSECURE' =>
131               Rails.configuration.arvados_insecure_https ? 'true' : 'false'
132             })
133
134     IO.popen([env, 'arv-put', '--raw'], 'w+b') do |io|
135       io.write normalized
136       io.close_write
137       while buf = io.read(2**20)
138
139       end
140     end
141
142     newc = Collection.new({:uuid => newuuid, :manifest_text => normalized})
143     newc.save!
144
145     chash.each do |k,v|
146       l = Link.new({
147                      tail_uuid: k,
148                      head_uuid: newuuid,
149                      link_class: "provenance",
150                      name: "provided"
151                    })
152       l.save!
153     end
154
155     redirect_to controller: 'collections', action: :show, id: newc.uuid
156   end
157
158 end