mirror of
https://github.com/sourcebot-dev/sourcebot.git
synced 2025-12-12 12:25:22 +00:00
Exclude repos by glob (#70)
This commit is contained in:
parent
276086d2d6
commit
a407792212
4 changed files with 78 additions and 17 deletions
|
|
@ -15,7 +15,9 @@
|
||||||
"forks": true,
|
"forks": true,
|
||||||
"repos": [
|
"repos": [
|
||||||
"my-org/repo1",
|
"my-org/repo1",
|
||||||
"my-org/repo2"
|
"my-org/repo2",
|
||||||
|
"my-org/sub-org-1/**",
|
||||||
|
"my-org/sub-org-*/**"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -34,7 +36,9 @@
|
||||||
"forks": true,
|
"forks": true,
|
||||||
"projects": [
|
"projects": [
|
||||||
"my-group/project1",
|
"my-group/project1",
|
||||||
"my-group/project2"
|
"my-group/project2",
|
||||||
|
"my-org/sub-org-1/**",
|
||||||
|
"my-org/sub-org-*/**"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -53,7 +57,9 @@
|
||||||
"forks": true,
|
"forks": true,
|
||||||
"repos": [
|
"repos": [
|
||||||
"my-org/repo1",
|
"my-org/repo1",
|
||||||
"my-org/repo2"
|
"my-org/repo2",
|
||||||
|
"my-org/sub-org-1/**",
|
||||||
|
"my-org/sub-org-*/**"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,62 @@
|
||||||
import { expect, test } from 'vitest';
|
import { expect, test } from 'vitest';
|
||||||
import { arraysEqualShallow, isRemotePath } from './utils';
|
import { arraysEqualShallow, isRemotePath, excludeReposByName } from './utils';
|
||||||
|
import { Repository } from './types';
|
||||||
|
|
||||||
|
const testNames: string[] = [
|
||||||
|
"abcdefg/zfmno/ioiwerj/fawdf",
|
||||||
|
"abcdefg/zfmno/ioiwerj/werw",
|
||||||
|
"abcdefg/zfmno/ioiwerj/terne",
|
||||||
|
"abcdefg/zfmno/ioiwerj/asdf45e4r",
|
||||||
|
"abcdefg/zfmno/ioiwerj/ddee",
|
||||||
|
"abcdefg/zfmno/ioiwerj/ccdfeee",
|
||||||
|
"abcdefg/zfmno/sadfaw",
|
||||||
|
"abcdefg/zfmno/ioiwerj/wwe",
|
||||||
|
"abcdefg/ieieiowowieu8383/ieckup-e",
|
||||||
|
"abcdefg/ieieiowowieu8383/fvas-eer-wwwer3"
|
||||||
|
];
|
||||||
|
|
||||||
|
const createRepository = (name: string) => (<Repository>{
|
||||||
|
vcs: 'git',
|
||||||
|
id: name,
|
||||||
|
name: name,
|
||||||
|
path: name,
|
||||||
|
isStale: false,
|
||||||
|
cloneUrl: name,
|
||||||
|
branches: [name],
|
||||||
|
tags: [name]
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should filter repos by micromatch pattern', () => {
|
||||||
|
// bad glob patterns
|
||||||
|
const unfilteredRepos = excludeReposByName(testNames.map(n => (createRepository(n))), ['/zfmno/']);
|
||||||
|
expect(unfilteredRepos.length).toBe(10);
|
||||||
|
expect(unfilteredRepos.map(r => r.name)).toEqual(testNames);
|
||||||
|
const unfilteredRepos1 = excludeReposByName(testNames.map(n => (createRepository(n))), ['**zfmno**']);
|
||||||
|
expect(unfilteredRepos1.length).toBe(10);
|
||||||
|
expect(unfilteredRepos1.map(r => r.name)).toEqual(testNames);
|
||||||
|
|
||||||
|
// good glob patterns
|
||||||
|
const filteredRepos = excludeReposByName(testNames.map(n => (createRepository(n))), ['**/zfmno/**']);
|
||||||
|
expect(filteredRepos.length).toBe(2);
|
||||||
|
expect(filteredRepos.map(r => r.name)).toEqual(["abcdefg/ieieiowowieu8383/ieckup-e", "abcdefg/ieieiowowieu8383/fvas-eer-wwwer3"]);
|
||||||
|
const filteredRepos1 = excludeReposByName(testNames.map(n => (createRepository(n))), ['**/*fmn*/**']);
|
||||||
|
expect(filteredRepos1.length).toBe(2);
|
||||||
|
expect(filteredRepos1.map(r => r.name)).toEqual(["abcdefg/ieieiowowieu8383/ieckup-e", "abcdefg/ieieiowowieu8383/fvas-eer-wwwer3"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should filter repos by name exact match', () => {
|
||||||
|
const filteredRepos = excludeReposByName(testNames.map(n => (createRepository(n))), testNames.slice(1, 9));
|
||||||
|
expect(filteredRepos.length).toBe(2);
|
||||||
|
expect(filteredRepos.map(r => r.name)).toEqual([testNames[0], testNames[9]]);
|
||||||
|
|
||||||
|
const filteredRepos1 = excludeReposByName(testNames.map(n => (createRepository(n))), testNames.slice(3, 5));
|
||||||
|
expect(filteredRepos1.length).toBe(8);
|
||||||
|
expect(filteredRepos1.map(r => r.name)).toEqual([testNames[0], testNames[1], testNames[2], testNames[5], testNames[6], testNames[7], testNames[8], testNames[9]]);
|
||||||
|
|
||||||
|
const filteredRepos2 = excludeReposByName(testNames.map(n => (createRepository(n))), [testNames[0], testNames[7], testNames[9]]);
|
||||||
|
expect(filteredRepos2.length).toBe(7);
|
||||||
|
expect(filteredRepos2.map(r => r.name)).toEqual([...testNames.slice(1, 7), testNames[8]]);
|
||||||
|
});
|
||||||
|
|
||||||
test('should return true for identical arrays', () => {
|
test('should return true for identical arrays', () => {
|
||||||
expect(arraysEqualShallow([1, 2, 3], [1, 2, 3])).toBe(true);
|
expect(arraysEqualShallow([1, 2, 3], [1, 2, 3])).toBe(true);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { Logger } from "winston";
|
import { Logger } from "winston";
|
||||||
import { AppContext, Repository } from "./types.js";
|
import { AppContext, Repository } from "./types.js";
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
import micromatch from "micromatch";
|
||||||
|
|
||||||
export const measure = async <T>(cb : () => Promise<T>) => {
|
export const measure = async <T>(cb : () => Promise<T>) => {
|
||||||
const start = Date.now();
|
const start = Date.now();
|
||||||
|
|
@ -36,10 +37,10 @@ export const excludeArchivedRepos = <T extends Repository>(repos: T[], logger?:
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export const excludeReposByName = <T extends Repository>(repos: T[], excludedRepoNames: string[], logger?: Logger) => {
|
export const excludeReposByName = <T extends Repository>(repos: T[], excludedRepoNames: string[], logger?: Logger) => {
|
||||||
const excludedRepos = new Set(excludedRepoNames);
|
|
||||||
return repos.filter((repo) => {
|
return repos.filter((repo) => {
|
||||||
if (excludedRepos.has(repo.name)) {
|
if (micromatch.isMatch(repo.name, excludedRepoNames)) {
|
||||||
logger?.debug(`Excluding repo ${repo.id}. Reason: exclude.repos contains ${repo.name}`);
|
logger?.debug(`Excluding repo ${repo.id}. Reason: exclude.repos contains ${repo.name}`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -146,11 +146,10 @@
|
||||||
"repos": {
|
"repos": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
"type": "string",
|
"type": "string"
|
||||||
"pattern": "^[\\w.-]+\\/[\\w.-]+$"
|
|
||||||
},
|
},
|
||||||
"default": [],
|
"default": [],
|
||||||
"description": "List of individual repositories to exclude from syncing. Expected to be formatted as '{orgName}/{repoName}' or '{userName}/{repoName}'."
|
"description": "List of individual repositories to exclude from syncing. Glob patterns are supported."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
|
|
@ -238,8 +237,7 @@
|
||||||
"projects": {
|
"projects": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
"type": "string",
|
"type": "string"
|
||||||
"pattern": "^[\\w.-]+\\/[\\w.-]+$"
|
|
||||||
},
|
},
|
||||||
"default": [],
|
"default": [],
|
||||||
"examples": [
|
"examples": [
|
||||||
|
|
@ -247,7 +245,7 @@
|
||||||
"my-group/my-project"
|
"my-group/my-project"
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
"description": "List of individual projects to exclude from syncing. The project's namespace must be specified. See: https://docs.gitlab.com/ee/user/namespace/"
|
"description": "List of projects to exclude from syncing. Glob patterns are supported. The project's namespace must be specified, see: https://docs.gitlab.com/ee/user/namespace/"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
|
|
@ -336,11 +334,10 @@
|
||||||
"repos": {
|
"repos": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
"type": "string",
|
"type": "string"
|
||||||
"pattern": "^[\\w.-]+\\/[\\w.-]+$"
|
|
||||||
},
|
},
|
||||||
"default": [],
|
"default": [],
|
||||||
"description": "List of individual repositories to exclude from syncing. Expected to be formatted as '{orgName}/{repoName}' or '{userName}/{repoName}'."
|
"description": "List of individual repositories to exclude from syncing. Glob patterns are supported."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue