Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix issue with file inclusion patterns #1075

Merged
merged 3 commits into from
Nov 4, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 21 additions & 9 deletions src/package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,14 @@ const MinimatchOptions: minimatch.IOptions = { dot: true };
export interface IInMemoryFile {
path: string;
mode?: number;
originalPath?: string; // used to track the original path of a file that was renamed
readonly contents: Buffer | string;
}

export interface ILocalFile {
path: string;
mode?: number;
originalPath?: string; // used to track the original path of a file that was renamed
readonly localPath: string;
}

Expand Down Expand Up @@ -919,6 +921,7 @@ export abstract class MarkdownProcessor extends BaseProcessor {
return {
path: file.path,
contents: Buffer.from(contents, 'utf8'),
originalPath: file.originalPath
};
}

Expand Down Expand Up @@ -981,7 +984,11 @@ export class ReadmeProcessor extends MarkdownProcessor {
}

override async processFile(file: IFile): Promise<IFile> {
file.path = 'extension/readme.md';
if (isInMemoryFile(file)) {
util.log.warn(`The provided readme file is in memory and will not be included in the VSIX.`);
return file;
}
file = { ...file, originalPath: file.localPath, path: 'extension/readme.md' };
return await super.processFile(file, file.path);
}

Expand All @@ -1005,7 +1012,11 @@ export class ChangelogProcessor extends MarkdownProcessor {
}

override async processFile(file: IFile): Promise<IFile> {
file.path = 'extension/changelog.md';
if (isInMemoryFile(file)) {
util.log.warn(`The provided changelog file is in memory and will not be included in the VSIX.`);
return file;
}
file = { ...file, originalPath: file.localPath, path: 'extension/changelog.md' };
return await super.processFile(file, file.path);
}

Expand Down Expand Up @@ -2037,18 +2048,19 @@ export async function printAndValidatePackagedFiles(files: IFile[], cwd: string,
// Throw an error if the extension uses the files property in package.json and
// the package does not include at least one file for each include pattern
else if (manifest.files !== undefined && manifest.files.length > 0 && !options.allowUnusedFilesPattern) {
const localPaths = (files.filter(f => !isInMemoryFile(f)) as ILocalFile[]).map(f => util.normalize(f.localPath));
const filesIncludePatterns = manifest.files.map(includePattern => util.normalize(path.join(cwd, includePattern)));
const localPaths = files.map(f => util.normalize(f.originalPath ?? (!isInMemoryFile(f) ? f.localPath : path.join(cwd, f.path))));
const filesIncludePatterns = manifest.files.map(includePattern => ({ absolute: util.normalize(path.join(cwd, includePattern)), relative: includePattern }));

const unusedIncludePatterns = filesIncludePatterns.filter(includePattern => {
let absoluteIncludePattern = includePattern.absolute;
// Check if the pattern provided by the user matches any file in the package
if (localPaths.some(localFilePath => minimatch(localFilePath, includePattern, MinimatchOptions))) {
if (localPaths.some(localFilePath => minimatch(localFilePath, absoluteIncludePattern, MinimatchOptions))) {
return false;
}
// Check if the pattern provided by the user matches any folder in the package
if (!/(^|\/)[^/]*\*[^/]*$/.test(includePattern)) {
includePattern = (/\/$/.test(includePattern) ? `${includePattern}**` : `${includePattern}/**`);
return !localPaths.some(localFilePath => minimatch(localFilePath, includePattern, MinimatchOptions));
if (!/(^|\/)[^/]*\*[^/]*$/.test(absoluteIncludePattern)) {
absoluteIncludePattern = (/\/$/.test(absoluteIncludePattern) ? `${absoluteIncludePattern}**` : `${absoluteIncludePattern}/**`);
return !localPaths.some(localFilePath => minimatch(localFilePath, absoluteIncludePattern, MinimatchOptions));
}
// Pattern does not match any file or folder
return true;
Expand All @@ -2057,7 +2069,7 @@ export async function printAndValidatePackagedFiles(files: IFile[], cwd: string,
if (unusedIncludePatterns.length > 0) {
let message = '';
message += `The following include patterns in the ${chalk.bold('"files"')} property in package.json do not match any files packaged in the extension:\n`;
message += unusedIncludePatterns.map(p => ` - ${p}`).join('\n');
message += unusedIncludePatterns.map(p => ` - ${p.relative}`).join('\n');
message += '\nRemove any include pattern which is not needed.\n';
message += `\n=> Run ${chalk.bold('vsce ls --tree')} to see all included files.\n`;
message += `=> Use ${chalk.bold('--allow-unused-files-pattern')} to skip this check`;
Expand Down
1 change: 1 addition & 0 deletions src/test/fixtures/manifestFiles/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Test
13 changes: 11 additions & 2 deletions src/test/fixtures/manifestFiles/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@
"name": "uuid",
"publisher": "joaomoreno",
"version": "1.0.0",
"engines": { "vscode": "*" },
"files": ["foo", "foo2/bar2/include.me", "*/bar3/**", "package.json", "LICENSE"]
"engines": {
"vscode": "*"
},
"files": [
"foo",
"foo2/bar2/include.me",
"*/bar3/**",
"package.json",
"LICENSE",
"README.md"
]
}
1 change: 1 addition & 0 deletions src/test/package.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ describe('collect', function () {
'extension/foo2/bar2/include.me',
'extension/foo3/bar3/hello.txt',
'extension/package.json',
'extension/readme.md',
]);
});

Expand Down
Loading