From f21bc89bf75dec152901e3468ae5e16f307bc0d1 Mon Sep 17 00:00:00 2001 From: kaur16 <126662478+kaur16@users.noreply.github.com> Date: Tue, 12 Dec 2023 15:03:32 +0530 Subject: [PATCH] YDA-5496: added touch microservice and support for overwriting data objects and collections Co-authored-by: Lazlo Westerhof --- research.py | 32 ++++++++++++++++++++------------ util/collection.py | 23 +++++++++++++++++------ util/msi.py | 2 ++ 3 files changed, 39 insertions(+), 18 deletions(-) diff --git a/research.py b/research.py index 5dea60590..bc5735a93 100644 --- a/research.py +++ b/research.py @@ -91,12 +91,13 @@ def api_research_folder_add(ctx, coll, new_folder_name): @api.make() -def api_research_folder_copy(ctx, folder_path, new_folder_path): +def api_research_folder_copy(ctx, folder_path, new_folder_path, overwrite=False): """Copy a folder in a research folder. :param ctx: Combined type of a callback and rei struct :param folder_path: Path to the folder to copy :param new_folder_path: Path to the new copy of the folder + :param overwrite: Overwrite folder if it already exists :returns: Dict with API status result """ @@ -139,12 +140,12 @@ def api_research_folder_copy(ctx, folder_path, new_folder_path): return api.Error('invalid_source', 'The original folder ' + folder_path + ' can not be found') # Collection exists in destination? - if collection.exists(ctx, new_folder_path): + if not overwrite and collection.exists(ctx, new_folder_path): return api.Error('invalid_destination', 'Folder with this name already exists in destination. Please choose another destination') # All requirements OK try: - collection.copy(ctx, folder_path, new_folder_path) + collection.copy(ctx, folder_path, new_folder_path, force=overwrite) except msi.Error: return api.Error('internal', 'Something went wrong. Please try again') @@ -152,12 +153,13 @@ def api_research_folder_copy(ctx, folder_path, new_folder_path): @api.make() -def api_research_folder_move(ctx, folder_path, new_folder_path): +def api_research_folder_move(ctx, folder_path, new_folder_path, overwrite=False): """Move a folder in a research folder. :param ctx: Combined type of a callback and rei struct :param folder_path: Path to the folder to move :param new_folder_path: Path to the new folder + :param overwrite: Overwrite folder if it already exists :returns: Dict with API status result """ @@ -200,12 +202,12 @@ def api_research_folder_move(ctx, folder_path, new_folder_path): return api.Error('invalid_source', 'The original folder ' + folder_path + ' can not be found') # Collection exists in destination? - if collection.exists(ctx, new_folder_path): + if not overwrite and collection.exists(ctx, new_folder_path): return api.Error('invalid_destination', 'Folder with this name already exists in destination. Please choose another destination') # All requirements OK try: - collection.move(ctx, folder_path, new_folder_path) + collection.move(ctx, folder_path, new_folder_path, force=overwrite) except msi.Error: return api.Error('internal', 'Something went wrong. Please try again') @@ -360,12 +362,13 @@ def api_research_list_temporary_files(ctx, coll): @api.make() -def api_research_file_copy(ctx, filepath, new_filepath): +def api_research_file_copy(ctx, filepath, new_filepath, overwrite=False): """Copy a file in a research folder. :param ctx: Combined type of a callback and rei struct :param filepath: Path to the file to copy :param new_filepath: Path to the new copy of the file + :param overwrite: Overwrite file if it already exists :returns: Dict with API status result """ @@ -410,12 +413,12 @@ def api_research_file_copy(ctx, filepath, new_filepath): return api.Error('invalid_source', 'The original file ' + data_name + ' can not be found') # new filename already exists? - if data_object.exists(ctx, new_filepath): + if not overwrite and data_object.exists(ctx, new_filepath): return api.Error('invalid_destination', 'The file ' + data_name + ' already exists') # All requirements OK try: - data_object.copy(ctx, filepath, new_filepath) + data_object.copy(ctx, filepath, new_filepath, force=overwrite) except msi.Error: return api.Error('internal', 'Something went wrong. Please try again') @@ -493,12 +496,13 @@ def api_research_file_rename(ctx, new_file_name, coll, org_file_name): @api.make() -def api_research_file_move(ctx, filepath, new_filepath): +def api_research_file_move(ctx, filepath, new_filepath, overwrite=False): """Move a file in a research folder. :param ctx: Combined type of a callback and rei struct :param filepath: Path to the file to move :param new_filepath: Path to the new location of the file + :param overwrite: Overwrite file if it already exists :returns: Dict with API status result """ @@ -543,12 +547,16 @@ def api_research_file_move(ctx, filepath, new_filepath): return api.Error('invalid_source', 'The original file ' + data_name + ' can not be found') # new filename already exists? - if data_object.exists(ctx, new_filepath): + if not overwrite and data_object.exists(ctx, new_filepath): return api.Error('invalid_destination', 'The file ' + data_name + ' already exists') # All requirements OK try: - data_object.rename(ctx, filepath, new_filepath) + if overwrite: + data_object.copy(ctx, filepath, new_filepath, force=overwrite) + data_object.remove(ctx, filepath) + else: + data_object.rename(ctx, filepath, new_filepath) except msi.Error: return api.Error('internal', 'Something went wrong. Please try again') diff --git a/util/collection.py b/util/collection.py index 2af943d85..753c85b48 100644 --- a/util/collection.py +++ b/util/collection.py @@ -5,6 +5,7 @@ __license__ = 'GPLv3, see LICENSE' import itertools +import json import sys if sys.version_info > (2, 7): from functools import reduce @@ -164,17 +165,20 @@ def create(ctx, path, entire_tree=''): irods_types.BytesBuf()) -def copy(ctx, path_org, path_copy): +def copy(ctx, path_org, path_copy, force=True): """Copy a collection. :param ctx: Combined type of a callback and rei struct :param path_org: Collection original path :param path_copy: Collection copy path + :param force: Applies "forceFlag" This may raise a error.UUError if the collection does not exist, or when the user does not have write permission. """ - create(ctx, path_copy) + if not force: + create(ctx, path_copy) + for row in genquery.row_iterator("DATA_NAME", "COLL_NAME = '{}'".format(path_org), genquery.AS_LIST, @@ -182,27 +186,34 @@ def copy(ctx, path_org, path_copy): data_obj = row[0] data_object.copy(ctx, path_org + "/" + data_obj, - path_copy + "/" + data_obj) + path_copy + "/" + data_obj, + force) for row in genquery.row_iterator("COLL_NAME", "COLL_PARENT_NAME = '{}'".format(path_org), genquery.AS_LIST, ctx): coll = row[0] - copy(ctx, coll, path_copy + coll[len(path_org):]) + copy(ctx, coll, path_copy + coll[len(path_org):], force) + + # Update modified date for collection if overwrite + if force: + json_inp = {"logical_path": path_copy} + msi.touch(ctx, json.dumps(json_inp)) -def move(ctx, path_org, path_move): +def move(ctx, path_org, path_move, force=True): """Move a collection. :param ctx: Combined type of a callback and rei struct :param path_org: Collection original path :param path_move: Collection move path + :param force: Applies "forceFlag" This may raise a error.UUError if the collection does not exist, or when the user does not have write permission. """ - copy(ctx, path_org, path_move) + copy(ctx, path_org, path_move, force) msi.rm_coll(ctx, path_org, '', diff --git a/util/msi.py b/util/msi.py index 691ff91e6..d2b472d99 100644 --- a/util/msi.py +++ b/util/msi.py @@ -137,6 +137,8 @@ def _make_exception(name, message): sudo_obj_acl_set, SudoObjAclSetError = make('SudoObjAclSet', 'Could not set ACLs as admin') +touch, TouchError = make('_touch', 'Could not update the data object or collection') + def kvpair(ctx, k, v): """Create a keyvalpair object, needed by certain msis."""