From 4a9d38960e6a9b3f30b3599f1c1ac113944c74ce Mon Sep 17 00:00:00 2001 From: MontrealSergiy Date: Mon, 6 Jul 2026 17:35:26 -0400 Subject: [PATCH 1/3] detect possible overwriting output files by BoutiquesOutputFilenameRenamer module #1632 --- .../lib/boutiques_output_filename_renamer.rb | 53 ++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/BrainPortal/lib/boutiques_output_filename_renamer.rb b/BrainPortal/lib/boutiques_output_filename_renamer.rb index 7cb8b3c2f..d29b22ea0 100644 --- a/BrainPortal/lib/boutiques_output_filename_renamer.rb +++ b/BrainPortal/lib/boutiques_output_filename_renamer.rb @@ -95,7 +95,7 @@ # } module BoutiquesOutputFilenameRenamer - # Note: to access the revision info of the module, + # Note: to access the revision info of the module, # you need to access the constant directly, the # object method revision_info() won't work. Revision_info=CbrainFileRevision[__FILE__] #:nodoc: @@ -206,9 +206,60 @@ def after_form params_errors.add(outnameinputid, "is a pattern that seems to have unreplaced components") end end + + # check_for_overwriting_output_files(config_map) + # msg = "BoutiquesOutputFilenameRenamer module require actual pattern with {task_id}, {full} or {full_ex} is not compatible with batch tasks" + # raise exception msg unless self.has_pattern? message end + + + # checking that output patterns actually provided in the case of batch tasks + # because this module disables CBRAIN standards output suffixes that aim at aprevenitn + # from overwriting the output files + def final_task_list + tasklist = super + if tasklist.length > 1 && tasklist.last.is_a?(CbrainTask) + descriptor = descriptor_for_after_form + config_map = descriptor.custom_module_info('BoutiquesOutputFilenameRenamer') || {} + + # check that the output file names are unique at least for same output id + # (still there could be overwriting for different output ids) + + config_map.each do |_, pair| + fileinputid, outnameinputid = *pair + outname_pattern = invoke_params[outnameinputid].gsub('{time}', 'timestamp') # timestamp is unreliable + next if outname_pattern.include?('{task_id}') # enough for unique output names for input + outnames = {} + outname = input_userfile = nil + t, _ = tasklist.each_with_index.detect do |t, i| + + input_userfile_id = t.invoke_params[fileinputid] + input_userfile = Userfile.find(input_userfile_id) + outname = t.output_name_from_pattern(outname_pattern, input_userfile.name) # expected output file name + outnames[outname] ||= i # index of the first task in the tasklist, resulting in that output file name + outnames[outname] < i # same outname in two tasks + end + + if !t.nil? + t_1 = tasklist[outnames[outname]] + input_userfile_id_1 = t_1.invoke_params[fileinputid] # input file id resulting in duplicated output file name + input_userfile_1 = Userfile.find(input_userfile_id_1) + + msg = ":BoutiquesOutputFilenameRenamer module require unique output names for batch tasks," + + "yet input files '#{input_userfile.name}' and '#{input_userfile_1.name}' result in the same output file " + + " '#{outname}' for output file pattern #{outname_pattern} ." + + self.errors.add(outnameinputid, ": Add a pattern that may result in different files names, such a {full} or {task} to '#{outname_pattern}' ") + t.errors.add(outnameinputid, msg) + end + end + end + tasklist + end + + ################################################## # Cluster side overrides ################################################## From bf1bf4e1a2556c8aafc1466a4f3cd0fc9192fe87 Mon Sep 17 00:00:00 2001 From: MontrealSergiy Date: Tue, 7 Jul 2026 08:56:00 -0400 Subject: [PATCH 2/3] drop some comments #1632 --- BrainPortal/lib/boutiques_output_filename_renamer.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/BrainPortal/lib/boutiques_output_filename_renamer.rb b/BrainPortal/lib/boutiques_output_filename_renamer.rb index d29b22ea0..d46046263 100644 --- a/BrainPortal/lib/boutiques_output_filename_renamer.rb +++ b/BrainPortal/lib/boutiques_output_filename_renamer.rb @@ -95,7 +95,7 @@ # } module BoutiquesOutputFilenameRenamer - # Note: to access the revision info of the module, + # Note: to access the revision info of the module, # you need to access the constant directly, the # object method revision_info() won't work. Revision_info=CbrainFileRevision[__FILE__] #:nodoc: @@ -206,10 +206,6 @@ def after_form params_errors.add(outnameinputid, "is a pattern that seems to have unreplaced components") end end - - # check_for_overwriting_output_files(config_map) - # msg = "BoutiquesOutputFilenameRenamer module require actual pattern with {task_id}, {full} or {full_ex} is not compatible with batch tasks" - # raise exception msg unless self.has_pattern? message end From 35da8b5bbbd149ab639b9568d8c946ed6d4f23e1 Mon Sep 17 00:00:00 2001 From: MontrealSergiy Date: Wed, 8 Jul 2026 10:50:04 -0400 Subject: [PATCH 3/3] better error message and comments for detect possible overwriting output files by BoutiquesOutputFilenameRenamer module #1631 --- .../lib/boutiques_output_filename_renamer.rb | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/BrainPortal/lib/boutiques_output_filename_renamer.rb b/BrainPortal/lib/boutiques_output_filename_renamer.rb index d46046263..8694aece4 100644 --- a/BrainPortal/lib/boutiques_output_filename_renamer.rb +++ b/BrainPortal/lib/boutiques_output_filename_renamer.rb @@ -217,7 +217,7 @@ def after_form def final_task_list tasklist = super if tasklist.length > 1 && tasklist.last.is_a?(CbrainTask) - descriptor = descriptor_for_after_form + descriptor = descriptor_for_final_task_list config_map = descriptor.custom_module_info('BoutiquesOutputFilenameRenamer') || {} # check that the output file names are unique at least for same output id @@ -225,17 +225,17 @@ def final_task_list config_map.each do |_, pair| fileinputid, outnameinputid = *pair - outname_pattern = invoke_params[outnameinputid].gsub('{time}', 'timestamp') # timestamp is unreliable - next if outname_pattern.include?('{task_id}') # enough for unique output names for input + original_outname_pattern = invoke_params[outnameinputid] + next if original_outname_pattern.include?('{task_id}') # usually enough for unique output names for input + outname_pattern = original_outname_pattern.gsub('{time}', '12:23:45') # time is not very reliable outnames = {} outname = input_userfile = nil - t, _ = tasklist.each_with_index.detect do |t, i| - + t, _ = tasklist.each_with_index.detect do |t, i| input_userfile_id = t.invoke_params[fileinputid] input_userfile = Userfile.find(input_userfile_id) outname = t.output_name_from_pattern(outname_pattern, input_userfile.name) # expected output file name - outnames[outname] ||= i # index of the first task in the tasklist, resulting in that output file name - outnames[outname] < i # same outname in two tasks + outnames[outname] ||= i # index of the first task in the tasklist, resulting in output file name 'outname' + outnames[outname] < i # the file name could be generate both by i-th and one of previous tasks end if !t.nil? @@ -245,7 +245,7 @@ def final_task_list msg = ":BoutiquesOutputFilenameRenamer module require unique output names for batch tasks," + "yet input files '#{input_userfile.name}' and '#{input_userfile_1.name}' result in the same output file " + - " '#{outname}' for output file pattern #{outname_pattern} ." + " '#{outname}' for output file pattern '#{original_outname_pattern}'." self.errors.add(outnameinputid, ": Add a pattern that may result in different files names, such a {full} or {task} to '#{outname_pattern}' ") t.errors.add(outnameinputid, msg)