diff --git a/app/src/app/event/error-handler.ts b/app/src/app/event/error-handler.ts index d2ef5202..bc62ff88 100644 --- a/app/src/app/event/error-handler.ts +++ b/app/src/app/event/error-handler.ts @@ -420,8 +420,7 @@ export class ErrorHandler { * @returns A promise that resolves to a Buffer holding the prepared HAR file, or undefined if no file is available - compressed using the brotli algorithm */ async prepareHarFile(): Promise { - const filePath = Resources.manager().harFilePath; - if (!filePath) { + if (!Resources.manager().enableNetworkCapture) { return undefined; } diff --git a/app/src/app/icloud-app.ts b/app/src/app/icloud-app.ts index 49ce90c9..a52c6c5e 100644 --- a/app/src/app/icloud-app.ts +++ b/app/src/app/icloud-app.ts @@ -12,10 +12,7 @@ import {APP_ERR, AUTH_ERR, LIBRARY_ERR} from "./error/error-codes.js"; import {Resources} from "../lib/resources/main.js"; import {iCPSEventApp, iCPSEventCloud, iCPSEventPhotos, iCPSEventRuntimeError} from "../lib/resources/events-types.js"; -/** - * Filename for library lock file located in DATA_DIR - */ -export const LIBRARY_LOCK_FILE = `.library.lock`; + /** * Abstract class returned by the factory function @@ -126,7 +123,7 @@ abstract class iCloudApp extends iCPSApp { * @throws An iCPSError, if the lock could not be acquired */ async acquireLibraryLock() { - const lockFilePath = path.join(Resources.manager().dataDir, LIBRARY_LOCK_FILE); + const lockFilePath = Resources.manager().lockFilePath; const lockFileExists = await fs.promises.stat(lockFilePath) .then(stat => stat.isFile()) .catch(() => false); @@ -149,7 +146,7 @@ abstract class iCloudApp extends iCPSApp { * @throws An iCPSError, if the lock could not be released */ async releaseLibraryLock() { - const lockFilePath = path.join(Resources.manager().dataDir, LIBRARY_LOCK_FILE); + const lockFilePath = Resources.manager().lockFilePath; const lockFileExists = await fs.promises.stat(lockFilePath) .then(stat => stat.isFile()) .catch(() => false); diff --git a/app/src/lib/resources/network-manager.ts b/app/src/lib/resources/network-manager.ts index ffe7d7c3..1b62c846 100644 --- a/app/src/lib/resources/network-manager.ts +++ b/app/src/lib/resources/network-manager.ts @@ -314,7 +314,7 @@ export class NetworkManager { * @returns - Returns a promise that resolves to false, if network capture was disabled or no entries were captured, true if a file was written */ async writeHarFile(): Promise { - if (!Resources.manager().harFilePath) { + if (!Resources.manager().enableNetworkCapture) { Resources.logger(this).debug(`Not writing HAR file because network capture is disabled`); return false; } diff --git a/app/src/lib/resources/resource-manager.ts b/app/src/lib/resources/resource-manager.ts index 43c3d575..37d2c3a9 100644 --- a/app/src/lib/resources/resource-manager.ts +++ b/app/src/lib/resources/resource-manager.ts @@ -4,7 +4,7 @@ import {iCPSAppOptions} from "../../app/factory.js"; import * as PHOTOS_LIBRARY from '../photos-library/constants.js'; import * as path from 'path'; import {readFileSync, writeFileSync} from "fs"; -import {FILE_ENCODING, HAR_FILE_NAME, LOG_FILE_NAME, METRICS_FILE_NAME, PhotosAccountZone, RESOURCE_FILE_NAME, ResourceFile, iCPSResources} from "./resource-types.js"; +import {FILE_ENCODING, HAR_FILE_NAME, LIBRARY_LOCK_FILE_NAME, LOG_FILE_NAME, METRICS_FILE_NAME, PhotosAccountZone, RESOURCE_FILE_NAME, ResourceFile, iCPSResources} from "./resource-types.js"; import {LogLevel} from "../../app/event/log.js"; import {Resources} from "./main.js"; import {iCPSEventRuntimeWarning} from "./events-types.js"; @@ -102,31 +102,33 @@ export class ResourceManager { } /** - * @returns The path to the metrics file, or undefined if metrics are disabled + * @returns The path to the library lock file */ - get metricsFilePath(): string | undefined { - if (this._resources.exportMetrics) { - return path.format({ - dir: this.dataDir, - base: METRICS_FILE_NAME, - }); - } - - return undefined; + get lockFilePath(): string { + return path.format({ + dir: this.dataDir, + base: LIBRARY_LOCK_FILE_NAME, + }); } /** - * @returns The path to the metrics file, or undefined if network capture is disabled + * @returns The path to the metrics file */ - get harFilePath(): string | undefined { - if (this._resources.enableNetworkCapture) { - return path.format({ - dir: this.dataDir, - base: HAR_FILE_NAME, - }); - } + get metricsFilePath(): string { + return path.format({ + dir: this.dataDir, + base: METRICS_FILE_NAME, + }); + } - return undefined; + /** + * @returns The path to the har file + */ + get harFilePath(): string { + return path.format({ + dir: this.dataDir, + base: HAR_FILE_NAME, + }); } /** diff --git a/app/src/lib/resources/resource-types.ts b/app/src/lib/resources/resource-types.ts index f594446d..7f9261ad 100644 --- a/app/src/lib/resources/resource-types.ts +++ b/app/src/lib/resources/resource-types.ts @@ -9,6 +9,11 @@ import {iCPSAppOptions} from "../../app/factory.js"; */ export const FILE_ENCODING = `utf8`; +/** + * Filename for library lock file located in DATA_DIR + */ +export const LIBRARY_LOCK_FILE_NAME = `.library.lock`; + /** * Filename of the resource file */ diff --git a/app/test/unit/app.test.ts b/app/test/unit/app.test.ts index 17b21bbd..e08e7dd6 100644 --- a/app/test/unit/app.test.ts +++ b/app/test/unit/app.test.ts @@ -3,7 +3,7 @@ import fs from 'fs'; import {describe, test, expect, jest, beforeEach, afterEach} from '@jest/globals'; import * as Config from '../_helpers/_config'; import {nonRejectOptions, rejectOptions, validOptions} from '../_helpers/app-factory.helper'; -import {ArchiveApp, DaemonApp, LIBRARY_LOCK_FILE, SyncApp, TokenApp} from '../../src/app/icloud-app'; +import {ArchiveApp, DaemonApp, SyncApp, TokenApp} from '../../src/app/icloud-app'; import {appFactory} from '../../src/app/factory'; import {Asset} from '../../src/lib/photos-library/model/asset'; import {prepareResources, spyOnEvent} from '../_helpers/_general'; @@ -11,6 +11,7 @@ import path from 'path'; import {iCPSEventApp, iCPSEventCloud, iCPSEventRuntimeError} from '../../src/lib/resources/events-types'; import {Resources} from '../../src/lib/resources/main'; import {stdin} from 'mock-stdin'; +import { LIBRARY_LOCK_FILE_NAME} from '../../src/lib/resources/resource-types'; beforeEach(() => { mockfs(); @@ -492,7 +493,7 @@ describe(`Library Lock`, () => { await tokenApp.acquireLibraryLock(); - const lockFile = (await fs.promises.readFile(path.join(Config.defaultConfig.dataDir, LIBRARY_LOCK_FILE), {encoding: `utf-8`})).toString(); + const lockFile = (await fs.promises.readFile(path.join(Config.defaultConfig.dataDir, LIBRARY_LOCK_FILE_NAME), {encoding: `utf-8`})).toString(); expect(lockFile).toEqual(thisPID); }); @@ -502,12 +503,12 @@ describe(`Library Lock`, () => { mockfs({ [Config.defaultConfig.dataDir]: { - [LIBRARY_LOCK_FILE]: notThisPID, + [LIBRARY_LOCK_FILE_NAME]: notThisPID, }, }); await expect(tokenApp.acquireLibraryLock()).rejects.toThrow(/^Library locked. Use --force \(or FORCE env variable\) to forcefully remove the lock$/); - expect(fs.existsSync(path.join(Resources.manager().dataDir, LIBRARY_LOCK_FILE))).toBeTruthy(); + expect(fs.existsSync(path.join(Resources.manager().dataDir, LIBRARY_LOCK_FILE_NAME))).toBeTruthy(); }); test(`Acquire lock warning - already locked with --force`, async () => { @@ -517,13 +518,13 @@ describe(`Library Lock`, () => { mockfs({ [Resources.manager().dataDir]: { - [LIBRARY_LOCK_FILE]: notThisPID, + [LIBRARY_LOCK_FILE_NAME]: notThisPID, }, }); await tokenApp.acquireLibraryLock(); - const lockFile = (await fs.promises.readFile(path.join(Resources.manager().dataDir, LIBRARY_LOCK_FILE), {encoding: `utf-8`})).toString(); + const lockFile = (await fs.promises.readFile(path.join(Resources.manager().dataDir, LIBRARY_LOCK_FILE_NAME), {encoding: `utf-8`})).toString(); expect(lockFile).toEqual(thisPID); }); @@ -533,13 +534,13 @@ describe(`Library Lock`, () => { mockfs({ [Config.defaultConfig.dataDir]: { - [LIBRARY_LOCK_FILE]: thisPID, + [LIBRARY_LOCK_FILE_NAME]: thisPID, }, }); await tokenApp.releaseLibraryLock(); - expect(fs.existsSync(path.join(Resources.manager().dataDir, LIBRARY_LOCK_FILE))).toBeFalsy(); + expect(fs.existsSync(path.join(Resources.manager().dataDir, LIBRARY_LOCK_FILE_NAME))).toBeFalsy(); }); test(`Release lock error - not this process' lock`, async () => { @@ -548,13 +549,13 @@ describe(`Library Lock`, () => { mockfs({ [Resources.manager().dataDir]: { - [LIBRARY_LOCK_FILE]: notThisPID, + [LIBRARY_LOCK_FILE_NAME]: notThisPID, }, }); await expect(tokenApp.releaseLibraryLock()).rejects.toThrow(/^Library locked. Use --force \(or FORCE env variable\) to forcefully remove the lock$/); - expect(fs.existsSync(path.join(Resources.manager().dataDir, LIBRARY_LOCK_FILE))).toBeTruthy(); + expect(fs.existsSync(path.join(Resources.manager().dataDir, LIBRARY_LOCK_FILE_NAME))).toBeTruthy(); }); test(`Release lock error - not this process' lock --force`, async () => { @@ -563,13 +564,13 @@ describe(`Library Lock`, () => { mockfs({ [Resources.manager().dataDir]: { - [LIBRARY_LOCK_FILE]: notThisPID, + [LIBRARY_LOCK_FILE_NAME]: notThisPID, }, }); await tokenApp.releaseLibraryLock(); - expect(fs.existsSync(path.join(Resources.manager().dataDir, LIBRARY_LOCK_FILE))).toBeFalsy(); + expect(fs.existsSync(path.join(Resources.manager().dataDir, LIBRARY_LOCK_FILE_NAME))).toBeFalsy(); }); test(`Release lock error - no lock`, async () => { @@ -577,6 +578,6 @@ describe(`Library Lock`, () => { await expect(tokenApp.releaseLibraryLock()).resolves.toBeUndefined(); - expect(!fs.existsSync(path.join(Resources.manager().dataDir, LIBRARY_LOCK_FILE))).toBeTruthy(); + expect(!fs.existsSync(path.join(Resources.manager().dataDir, LIBRARY_LOCK_FILE_NAME))).toBeTruthy(); }); }); \ No newline at end of file diff --git a/app/test/unit/resources.resource-manager.test.ts b/app/test/unit/resources.resource-manager.test.ts index e4fa0573..3c5e37db 100644 --- a/app/test/unit/resources.resource-manager.test.ts +++ b/app/test/unit/resources.resource-manager.test.ts @@ -306,6 +306,13 @@ describe(`ResourceManager`, () => { }); }); + describe(`libraryLockFile`, () => { + test(`should return the path to the library lock file`, () => { + const expectedPath = path.join(resources.dataDir, `.library.lock`); + expect(resourceManager.lockFilePath).toEqual(expectedPath); + }); + }); + describe(`metricsFilePath`, () => { test(`should return the path to the metrics file if exportMetrics is enabled`, () => { resourceManager._resources.exportMetrics = true; @@ -313,9 +320,10 @@ describe(`ResourceManager`, () => { expect(resourceManager.metricsFilePath).toEqual(expectedPath); }); - test(`should return undefined if exportMetrics is disabled`, () => { - resourceManager._resources.exportMetrics = false; - expect(resourceManager.metricsFilePath).toBeUndefined(); + test(`should return the path to the metrics file if exportMetrics is disabled`, () => { + resourceManager._resources.exportMetrics = true; + const expectedPath = path.join(resources.dataDir, `.icloud-photos-sync.metrics`); + expect(resourceManager.metricsFilePath).toEqual(expectedPath); }); }); @@ -326,10 +334,10 @@ describe(`ResourceManager`, () => { expect(resourceManager.harFilePath).toEqual(expectedPath); }); - test(`should return undefined if enableNetworkCapture is disabled`, () => { + test(`should return the path to the HAR file if enableNetworkCapture is disabled`, () => { resourceManager._resources.enableNetworkCapture = false; - - expect(resourceManager.harFilePath).toBeUndefined(); + const expectedPath = path.join(resources.dataDir, `.icloud-photos-sync.har`); + expect(resourceManager.harFilePath).toEqual(expectedPath); }); });