mirror of
https://github.com/immich-app/immich.git
synced 2025-01-27 22:22:45 +01:00
fix(server): Allow commas and braces in import paths (#13259)
fix commas and braces in paths
This commit is contained in:
parent
94d213bbb9
commit
5b00bc499f
2 changed files with 65 additions and 6 deletions
|
@ -347,6 +347,62 @@ describe('/libraries', () => {
|
||||||
expect(assets.items.find((asset) => asset.originalPath.includes('directoryB'))).toBeDefined();
|
expect(assets.items.find((asset) => asset.originalPath.includes('directoryB'))).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should scan multiple import paths with commas', async () => {
|
||||||
|
// https://github.com/immich-app/immich/issues/10699
|
||||||
|
const library = await utils.createLibrary(admin.accessToken, {
|
||||||
|
ownerId: admin.userId,
|
||||||
|
importPaths: [`${testAssetDirInternal}/temp/folder, a`, `${testAssetDirInternal}/temp/folder, b`],
|
||||||
|
});
|
||||||
|
|
||||||
|
utils.createImageFile(`${testAssetDir}/temp/folder, a/assetA.png`);
|
||||||
|
utils.createImageFile(`${testAssetDir}/temp/folder, b/assetB.png`);
|
||||||
|
|
||||||
|
const { status } = await request(app)
|
||||||
|
.post(`/libraries/${library.id}/scan`)
|
||||||
|
.set('Authorization', `Bearer ${admin.accessToken}`)
|
||||||
|
.send();
|
||||||
|
expect(status).toBe(204);
|
||||||
|
|
||||||
|
await utils.waitForQueueFinish(admin.accessToken, 'library');
|
||||||
|
|
||||||
|
const { assets } = await utils.metadataSearch(admin.accessToken, { libraryId: library.id });
|
||||||
|
|
||||||
|
expect(assets.count).toBe(2);
|
||||||
|
expect(assets.items.find((asset) => asset.originalPath.includes('folder, a'))).toBeDefined();
|
||||||
|
expect(assets.items.find((asset) => asset.originalPath.includes('folder, b'))).toBeDefined();
|
||||||
|
|
||||||
|
utils.removeImageFile(`${testAssetDir}/temp/folder, a/assetA.png`);
|
||||||
|
utils.removeImageFile(`${testAssetDir}/temp/folder, b/assetB.png`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should scan multiple import paths with braces', async () => {
|
||||||
|
// https://github.com/immich-app/immich/issues/10699
|
||||||
|
const library = await utils.createLibrary(admin.accessToken, {
|
||||||
|
ownerId: admin.userId,
|
||||||
|
importPaths: [`${testAssetDirInternal}/temp/folder{ a`, `${testAssetDirInternal}/temp/folder} b`],
|
||||||
|
});
|
||||||
|
|
||||||
|
utils.createImageFile(`${testAssetDir}/temp/folder{ a/assetA.png`);
|
||||||
|
utils.createImageFile(`${testAssetDir}/temp/folder} b/assetB.png`);
|
||||||
|
|
||||||
|
const { status } = await request(app)
|
||||||
|
.post(`/libraries/${library.id}/scan`)
|
||||||
|
.set('Authorization', `Bearer ${admin.accessToken}`)
|
||||||
|
.send();
|
||||||
|
expect(status).toBe(204);
|
||||||
|
|
||||||
|
await utils.waitForQueueFinish(admin.accessToken, 'library');
|
||||||
|
|
||||||
|
const { assets } = await utils.metadataSearch(admin.accessToken, { libraryId: library.id });
|
||||||
|
|
||||||
|
expect(assets.count).toBe(2);
|
||||||
|
expect(assets.items.find((asset) => asset.originalPath.includes('folder{ a'))).toBeDefined();
|
||||||
|
expect(assets.items.find((asset) => asset.originalPath.includes('folder} b'))).toBeDefined();
|
||||||
|
|
||||||
|
utils.removeImageFile(`${testAssetDir}/temp/folder{ a/assetA.png`);
|
||||||
|
utils.removeImageFile(`${testAssetDir}/temp/folder} b/assetB.png`);
|
||||||
|
});
|
||||||
|
|
||||||
it('should reimport a modified file', async () => {
|
it('should reimport a modified file', async () => {
|
||||||
const library = await utils.createLibrary(admin.accessToken, {
|
const library = await utils.createLibrary(admin.accessToken, {
|
||||||
ownerId: admin.userId,
|
ownerId: admin.userId,
|
||||||
|
|
|
@ -156,7 +156,9 @@ export class StorageRepository implements IStorageRepository {
|
||||||
return Promise.resolve([]);
|
return Promise.resolve([]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return glob(this.asGlob(pathsToCrawl), {
|
const globbedPaths = pathsToCrawl.map((path) => this.asGlob(path));
|
||||||
|
|
||||||
|
return glob(globbedPaths, {
|
||||||
absolute: true,
|
absolute: true,
|
||||||
caseSensitiveMatch: false,
|
caseSensitiveMatch: false,
|
||||||
onlyFiles: true,
|
onlyFiles: true,
|
||||||
|
@ -172,7 +174,9 @@ export class StorageRepository implements IStorageRepository {
|
||||||
return emptyGenerator();
|
return emptyGenerator();
|
||||||
}
|
}
|
||||||
|
|
||||||
const stream = globStream(this.asGlob(pathsToCrawl), {
|
const globbedPaths = pathsToCrawl.map((path) => this.asGlob(path));
|
||||||
|
|
||||||
|
const stream = globStream(globbedPaths, {
|
||||||
absolute: true,
|
absolute: true,
|
||||||
caseSensitiveMatch: false,
|
caseSensitiveMatch: false,
|
||||||
onlyFiles: true,
|
onlyFiles: true,
|
||||||
|
@ -206,10 +210,9 @@ export class StorageRepository implements IStorageRepository {
|
||||||
return () => watcher.close();
|
return () => watcher.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private asGlob(pathsToCrawl: string[]): string {
|
private asGlob(pathToCrawl: string): string {
|
||||||
const escapedPaths = pathsToCrawl.map((path) => escapePath(path));
|
const escapedPath = escapePath(pathToCrawl);
|
||||||
const base = escapedPaths.length === 1 ? escapedPaths[0] : `{${escapedPaths.join(',')}}`;
|
|
||||||
const extensions = `*{${mimeTypes.getSupportedFileExtensions().join(',')}}`;
|
const extensions = `*{${mimeTypes.getSupportedFileExtensions().join(',')}}`;
|
||||||
return `${base}/**/${extensions}`;
|
return `${escapedPath}/**/${extensions}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue