Skip to content

Commit

Permalink
feat(cli): handle patterns correctly on Windows
Browse files Browse the repository at this point in the history
Modify the handling of patterns in the `crawl` function to correctly
convert the current path to a pattern when it contains backslash on
Windows, in according to fast-glob's docs.
  • Loading branch information
fky2015 committed Jun 18, 2024
1 parent b21572c commit ae4cb06
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 6 deletions.
32 changes: 32 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,38 @@ jobs:
run: npm run test:cov
if: ${{ !cancelled() }}

cli-unit-tests-win:
name: CLI (Windows)
runs-on: windows-latest
defaults:
run:
working-directory: ./cli

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20

- name: Setup typescript-sdk
run: npm ci && npm run build
working-directory: ./open-api/typescript-sdk

- name: Install deps
run: npm ci

# Skip linter & formatter in Windows test.
- name: Run tsc
run: npm run check
if: ${{ !cancelled() }}

- name: Run unit tests & coverage
run: npm run test:cov
if: ${{ !cancelled() }}

web-unit-tests:
name: Web
runs-on: ubuntu-latest
Expand Down
14 changes: 11 additions & 3 deletions cli/src/utils.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import mockfs from 'mock-fs';
import { readFileSync } from 'node:fs';
import { CrawlOptions, crawl } from 'src/utils';

interface Test {
Expand All @@ -9,6 +10,10 @@ interface Test {

const cwd = process.cwd();

const readContent = (path: string) => {
return readFileSync(path).toString();
};

const extensions = [
'.jpg',
'.jpeg',
Expand Down Expand Up @@ -256,7 +261,8 @@ const tests: Test[] = [
{
test: 'should support ignoring absolute paths',
options: {
pathsToCrawl: ['/'],
// Currently, fast-glob has some caveat when dealing with `/`.
pathsToCrawl: ['/*s'],
recursive: true,
exclusionPattern: '/images/**',
},
Expand All @@ -276,14 +282,16 @@ describe('crawl', () => {
describe('crawl', () => {
for (const { test, options, files } of tests) {
it(test, async () => {
mockfs(Object.fromEntries(Object.keys(files).map((file) => [file, ''])));
// The file contents is the same as the path.
mockfs(Object.fromEntries(Object.keys(files).map((file) => [file, file])));

const actual = await crawl({ ...options, extensions });
const expected = Object.entries(files)
.filter((entry) => entry[1])
.map(([file]) => file);

expect(actual.sort()).toEqual(expected.sort());
// Compare file's content instead of path since a file can be represent in multiple ways.
expect(actual.map((path) => readContent(path)).sort()).toEqual(expected.sort());
});
}
});
Expand Down
12 changes: 9 additions & 3 deletions cli/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { getMyUser, init, isHttpError } from '@immich/sdk';
import { glob } from 'fast-glob';
import { convertPathToPattern, glob } from 'fast-glob';
import { createHash } from 'node:crypto';
import { createReadStream } from 'node:fs';
import { readFile, stat, writeFile } from 'node:fs/promises';
import { platform } from 'node:os';
import { join, resolve } from 'node:path';
import yaml from 'yaml';

Expand Down Expand Up @@ -106,6 +107,11 @@ export interface CrawlOptions {
exclusionPattern?: string;
extensions: string[];
}

const convertPathToPatternOnWin = (path: string) => {
return platform() === 'win32' ? convertPathToPattern(path) : path;
};

export const crawl = async (options: CrawlOptions): Promise<string[]> => {
const { extensions: extensionsWithPeriod, recursive, pathsToCrawl, exclusionPattern, includeHidden } = options;
const extensions = extensionsWithPeriod.map((extension) => extension.replace('.', ''));
Expand All @@ -124,11 +130,11 @@ export const crawl = async (options: CrawlOptions): Promise<string[]> => {
if (stats.isFile() || stats.isSymbolicLink()) {
crawledFiles.push(absolutePath);
} else {
patterns.push(absolutePath);
patterns.push(convertPathToPatternOnWin(absolutePath));
}
} catch (error: any) {
if (error.code === 'ENOENT') {
patterns.push(currentPath);
patterns.push(convertPathToPatternOnWin(currentPath));
} else {
throw error;
}
Expand Down
1 change: 1 addition & 0 deletions cli/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { defineConfig } from 'vite';
import tsconfigPaths from 'vite-tsconfig-paths';

export default defineConfig({
resolve: { alias: { src: '/src' } },
build: {
rollupOptions: {
input: 'src/index.ts',
Expand Down

0 comments on commit ae4cb06

Please sign in to comment.