diff --git a/src/sdk/namespace_fs.js b/src/sdk/namespace_fs.js index f9331a7f8d..6c743606c9 100644 --- a/src/sdk/namespace_fs.js +++ b/src/sdk/namespace_fs.js @@ -2768,6 +2768,7 @@ class NamespaceFS { * @returns {Promise} */ async _find_version_path(fs_context, { key, version_id }, return_md_path) { + key = await this._get_correct_key_path(fs_context, key); const cur_ver_path = return_md_path ? this._get_file_md_path({ key }) : this._get_file_path({ key }); if (!version_id) return cur_ver_path; @@ -2778,6 +2779,27 @@ class NamespaceFS { const versioned_path = this._get_version_path(key, version_id); return versioned_path; } + /** + * method append slash at the end of dir key when key misses last slash. + * @param {import('./nb').NativeFSContext} fs_context + * @param {string} key + */ + async _get_correct_key_path(fs_context, key) { + try { + let is_dir = false; + const key_path = path.normalize(path.join(this.bucket_path, key)); + const key_state = await nb_native().fs.stat(fs_context, key_path, { skip_user_xattr: true }); + if (key_state) { + is_dir = await native_fs_utils.isDirectory(key_state); + } + if (is_dir) { + key = key.endsWith('/') ? key : path.join(key, '/'); + } + } catch (err) { + dbg.warn('NamespaceFS._correct_key_path : error while getting state for key ', key, err); + } + return key; + } _throw_if_delete_marker(stat, params) { if (this.versioning === versioning_status_enum.VER_ENABLED || this.versioning === versioning_status_enum.VER_SUSPENDED) { diff --git a/src/test/unit_tests/test_namespace_fs.js b/src/test/unit_tests/test_namespace_fs.js index 641e30a00c..4cefe77bcc 100644 --- a/src/test/unit_tests/test_namespace_fs.js +++ b/src/test/unit_tests/test_namespace_fs.js @@ -1,6 +1,6 @@ /* Copyright (C) 2020 NooBaa */ /*eslint max-lines-per-function: ["error", 900]*/ -/*eslint max-lines: ["error", 2100]*/ +/*eslint max-lines: ["error", 2200]*/ 'use strict'; const _ = require('lodash'); @@ -472,6 +472,22 @@ mocha.describe('namespace_fs', function() { }); + mocha.it('delete dir object without last slash - a/b/c', async function() { + const source = buffer_utils.buffer_to_read_stream(data); + await upload_object(ns_tmp, upload_bkt, dir_1, dummy_object_sdk, source); + await delete_object(ns_tmp, upload_bkt, '/a/b/c', dummy_object_sdk); + + let entries; + try { + entries = await nb_native().fs.readdir(DEFAULT_FS_CONFIG, ns_tmp_bucket_path + dir_2); + } catch (e) { + assert.ifError(e); + } + console.log('stop when not empty - entries', entries); + assert.strictEqual(entries.length, 1); + + }); + mocha.after(async function() { let entries_before; let entries_after;