From 534c311dacae712f187bc8ddbd7dfde65f681ae1 Mon Sep 17 00:00:00 2001 From: "Scott E. Graves" Date: Tue, 1 Jun 2021 23:26:43 -0500 Subject: [PATCH] Added directory/file exists --- CHANGELOG.md | 8 ++++++++ src/__tests__/constants.test.js | 4 ++-- src/__tests__/repertory.test.js | 28 ++++++++++++++++++++++++++ src/index.js | 22 +++++++++++++++++++++ src/networking/connection.js | 35 +++++++++++++++++++++++++-------- src/ops/index.js | 31 +++++++++++++++++++++++++++++ 6 files changed, 118 insertions(+), 10 deletions(-) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..bb00c4b --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,8 @@ +# Changelog + +## 1.3.1-r3 +- Added directory/file exists +- Fix unit tests + +## 1.3.1-r2 +- Initial release diff --git a/src/__tests__/constants.test.js b/src/__tests__/constants.test.js index 18f6439..59e95d2 100644 --- a/src/__tests__/constants.test.js +++ b/src/__tests__/constants.test.js @@ -1,4 +1,4 @@ -import {get_version, instance_id, package_json} from '../utils/constants'; +import { get_version, instance_id, package_json } from '../utils/constants'; import * as uuid from 'uuid'; test(`can read 'package.json'`, () => { @@ -14,7 +14,7 @@ test(`'instance_id' is valid`, () => { test(`'version' can be read from 'package.json'`, () => { console.log(get_version()); - expect(get_version()).toBe('1.3.1-r1'); + expect(get_version()).toBe('1.3.1-r3'); }); test(`'version' can be overridden by environment variable`, () => { diff --git a/src/__tests__/repertory.test.js b/src/__tests__/repertory.test.js index 2bd5602..b3c1814 100644 --- a/src/__tests__/repertory.test.js +++ b/src/__tests__/repertory.test.js @@ -102,6 +102,8 @@ test('can create and remove a directory using api', async () => { ); const api = repertory.create_api(conn); expect(await api.directory.create('/repertory_js')).toEqual(0); + expect(await api.directory.exists('/repertory_js')).toEqual(true); + expect(await api.file.exists('/repertory_js')).toEqual(false); expect(await api.directory.remove('/repertory_js')).toEqual(0); await conn.disconnect(); @@ -278,6 +280,8 @@ test('can upload and download a file using api', async () => { await calculate_sha256('repertory_test.dat') ); + expect(await api.directory.exists('/repertory_test.dat')).toEqual(false); + expect(await api.file.exists('/repertory_test.dat')).toEqual(true); expect(await api.file.delete('/repertory_test.dat')).toEqual(0); fs.unlinkSync('repertory_test.dat'); @@ -518,3 +522,27 @@ test('can resume upload using api', async () => { await conn.disconnect(); }, 60000); + +test('exists returns false if directory is not found', async () => { + const conn = await repertory.create_pool( + 2, + TEST_HOST, + TEST_PORT, + TEST_PASSWORD + ); + const api = repertory.create_api(conn); + expect(await api.directory.exists('/cow')).toEqual(false); + await conn.disconnect(); +}); + +test('exists returns false if file is not found', async () => { + const conn = await repertory.create_pool( + 2, + TEST_HOST, + TEST_PORT, + TEST_PASSWORD + ); + const api = repertory.create_api(conn); + expect(await api.file.exists('/cow')).toEqual(false); + await conn.disconnect(); +}); diff --git a/src/index.js b/src/index.js index 3a7f537..d9fb49e 100644 --- a/src/index.js +++ b/src/index.js @@ -13,6 +13,17 @@ export const create_api = (conn) => { return { directory: { create: async (remote_path) => ops.create_directory(conn, remote_path), + exists: async (remote_path) => { + try { + const info = await ops.get_file_attributes2(conn, remote_path); + return info.directory; + } catch (e) { + if (e.message.split(':')[1].trim() == '-2') { + return false; + } + throw new Error(e.message); + } + }, list: async (remote_path, page_reader_cb) => ops.list_directory(conn, remote_path, page_reader_cb), remove: async (remote_path) => ops.remove_directory(conn, remote_path), @@ -43,6 +54,17 @@ export const create_api = (conn) => { overwrite, resume ), + exists: async (remote_path) => { + try { + const info = await ops.get_file_attributes2(conn, remote_path); + return !info.directory; + } catch (e) { + if (e.message.split(':')[1].trim() == '-2') { + return false; + } + throw new Error(e.message); + } + }, open: async (remote_path) => new file(conn, await ops.open_file(conn, remote_path), remote_path), upload: async (local_path, remote_path, progress_cb, overwrite, resume) => diff --git a/src/networking/connection.js b/src/networking/connection.js index 9af889a..43b9804 100644 --- a/src/networking/connection.js +++ b/src/networking/connection.js @@ -38,6 +38,7 @@ export default class connection { this.host_or_ip, (err) => { if (err) { + console.log(err); return reject(err); } return resolve(); @@ -67,20 +68,32 @@ export default class connection { if (buffer.length >= size + 4) { const packet_data = buffer.slice(4, 4 + size); if (this.resolve) { - const reject = this.reject; - const resolve = this.resolve; - - cleanup(); + const complete = () => { + const reject = this.reject; + const resolve = this.resolve; + cleanup(); + return { + reject, + resolve, + }; + }; const response = new packet(this.password); response.buffer = new Uint8Array(packet_data); response .decrypt() .then(() => { - resolve(response); + const { resolve } = complete(); + if (resolve) { + resolve(response); + } }) .catch((e) => { - reject(e); + console.log(e); + const { reject } = complete(); + if (reject) { + reject(e); + } }); } } @@ -94,7 +107,10 @@ export default class connection { cleanup(); this.connected = false; - reject(e); + console.log(e); + if (reject) { + reject(e); + } } }); @@ -105,7 +121,10 @@ export default class connection { cleanup(); this.connected = false; - reject(new Error('socket closed')); + console.log('socket closed'); + if (reject) { + reject(new Error('socket closed')); + } } }); } diff --git a/src/ops/index.js b/src/ops/index.js index ca6b321..b2ef48d 100644 --- a/src/ops/index.js +++ b/src/ops/index.js @@ -312,6 +312,37 @@ export const get_file_attributes = async ( } }; +export const get_file_attributes2 = async ( + conn, + remote_path, + optional_thread_id +) => { + try { + const request = new packet(); + request.encode_utf8(remote_path); + request.encode_ui32(0); + request.encode_ui32(0); + + const response = await conn.send( + '::RemoteFUSEGetattr', + request, + optional_thread_id + ); + response.decode_ui32(); // Service flags + + const result = response.decode_i32(); + if (result === 0) { + return response.decode_stat(); + } + + return Promise.reject( + new Error(`'get_file_attributes2' failed: ${result}`) + ); + } catch (err) { + return Promise.reject(new Error(`'get_file_attributes2' failed: ${err}`)); + } +}; + export const list_directory = async (conn, remote_path, page_reader_cb) => { const dir_snapshot = await _snapshot_directory(conn, remote_path); try {