diff --git a/CHANGELOG.md b/CHANGELOG.md index 37fab42..305fdd6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Change Log +## [Unreleased] + +- manifest: Allow to configure directories to ignore while searching for manifests + ## [0.0.37] - manifest: Automatically set `development` flatpak manifests, suffixed with `Devel` / `.devel` by default diff --git a/package.json b/package.json index 54b0928..460e898 100644 --- a/package.json +++ b/package.json @@ -214,7 +214,20 @@ ], "url": "https://raw.githubusercontent.com/flatpak/flatpak-builder/master/data/flatpak-manifest.schema.json" } - ] + ], + "configuration": { + "title": "Flatpak", + "properties": { + "flatpak-vscode.excludeManifestDirs": { + "markdownDescription": "These directories, with `.flatpak` and `_build`, will be ignored when searching for Flatpak manifests. You may also need to add these folders to Code's `files.watcherExclude` for performance.", + "default": ["target", ".vscode", ".flatpak-builder", "flatpak_app", ".github"], + "type": "array", + "items": { + "type": "string" + } + } + } + } }, "scripts": { "vscode:prepublish": "yarn run compile", diff --git a/src/manifestManager.ts b/src/manifestManager.ts index a744d0d..ce9da30 100644 --- a/src/manifestManager.ts +++ b/src/manifestManager.ts @@ -43,12 +43,6 @@ export class ManifestManager implements vscode.Disposable { const manifests = await this.getManifests() manifests.add(newManifest) - - // If that manifest is the first valid manifest, select it automatically. - if (manifests.size() === 1) { - console.log(`Found the first valid manifest at ${newManifest.uri.fsPath}. Setting it as active.`) - await this.setActiveManifest(newManifest, true) - } } catch (err) { console.warn(`Failed to parse manifest at ${newUri.fsPath}`) } @@ -62,17 +56,11 @@ export class ManifestManager implements vscode.Disposable { const manifests = await this.getManifests() manifests.delete(deletedUri) + }) - if (deletedUri.fsPath === this.activeManifest?.uri.fsPath) { - // If current active manifest is deleted and there is only one manifest - // left, select that manifest automatically. - const firstManifest = manifests.getFirstItem() - if (manifests.size() === 1 && firstManifest) { - console.log(`Found only one valid manifest. Setting active manifest to ${firstManifest.uri.fsPath}`) - await this.setActiveManifest(firstManifest, false) - } else { - await this.setActiveManifest(null, false) - } + vscode.workspace.onDidChangeConfiguration(async (event) => { + if (event.affectsConfiguration('flatpak-vscode')) { + await this.refreshManifests() } }) @@ -136,11 +124,39 @@ export class ManifestManager implements vscode.Disposable { this.manifests.onDidItemsChanged(() => { this.tryShowStatusItem() }) + this.manifests.onDidItemAdded(async (manifest) => { + // If that manifest is the first valid manifest, select it automatically. + if (this.manifests!.size() === 1) { + console.log(`Found the first valid manifest at ${manifest.uri.fsPath}. Setting it as active.`) + await this.setActiveManifest(manifest, true) + } + }) + this.manifests.onDidItemDeleted(async (deletedUri) => { + if (deletedUri.fsPath === this.activeManifest?.uri.fsPath) { + // If current active manifest is deleted and there is only one manifest + // left, select that manifest automatically. + const firstManifest = this.manifests!.getFirstItem() + if (this.manifests!.size() === 1 && firstManifest) { + console.log(`Found only one valid manifest. Setting active manifest to ${firstManifest.uri.fsPath}`) + await this.setActiveManifest(firstManifest, false) + } else { + await this.setActiveManifest(null, false) + } + } + }) } return this.manifests } + async refreshManifests(): Promise { + if (this.manifests !== undefined) { + console.log('Refreshing Flatpak manifests') + const newManifests = await findManifests() + this.manifests.update(newManifests) + } + } + /** * Like `getActiveManifestUnchecked` but throws an error when the active manifest contains error. * @@ -227,7 +243,8 @@ export class ManifestManager implements vscode.Disposable { return } - manifests.delete(oldManifest.uri) + // The path has not changed so this will only update the content of + // the manifest. manifests.add(updatedManifest) if (uri.fsPath === this.activeManifest?.uri.fsPath) { diff --git a/src/manifestMap.ts b/src/manifestMap.ts index e696602..b5c25f3 100644 --- a/src/manifestMap.ts +++ b/src/manifestMap.ts @@ -6,6 +6,10 @@ export class ManifestMap implements Iterable { private readonly _onDidItemsChanged = new vscode.EventEmitter() readonly onDidItemsChanged = this._onDidItemsChanged.event + private readonly _onDidItemAdded = new vscode.EventEmitter() + readonly onDidItemAdded = this._onDidItemAdded.event + private readonly _onDidItemDeleted = new vscode.EventEmitter() + readonly onDidItemDeleted = this._onDidItemDeleted.event constructor() { this.inner = new Map() @@ -16,8 +20,14 @@ export class ManifestMap implements Iterable { } add(manifest: Manifest): void { + const isAdded = !this.inner.has(manifest.uri.fsPath) + this.inner.set(manifest.uri.fsPath, manifest) this._onDidItemsChanged.fire() + + if (isAdded) { + this._onDidItemAdded.fire(manifest) + } } delete(uri: vscode.Uri): boolean { @@ -25,11 +35,24 @@ export class ManifestMap implements Iterable { if (isDeleted) { this._onDidItemsChanged.fire() + this._onDidItemDeleted.fire(uri) } return isDeleted } + update(other: ManifestMap): void { + for (const manifest of this) { + if (!other.inner.has(manifest.uri.fsPath)) { + this.delete(manifest.uri) + } + } + + for (const manifest of other) { + this.add(manifest) + } + } + get(uri: vscode.Uri): Manifest | undefined { return this.inner.get(uri.fsPath) } diff --git a/src/manifestUtils.ts b/src/manifestUtils.ts index 5f942be..72ec016 100644 --- a/src/manifestUtils.ts +++ b/src/manifestUtils.ts @@ -18,9 +18,14 @@ export const MANIFEST_PATH_GLOB_PATTERN = '**/*.{json,yaml,yml}' * @returns List of Flatpak Manifest */ export async function findManifests(): Promise { + // Always exclude the directories we generate. + const excludeBaseDirs = ['.flatpak', '_build'] + const excludeConfigDirs = workspace.getConfiguration('flatpak-vscode').get('excludeManifestDirs') + const excludeDirs = excludeBaseDirs.concat(excludeConfigDirs ?? []).join(',') + const uris: Uri[] = await workspace.findFiles( MANIFEST_PATH_GLOB_PATTERN, - '**/{target,.vscode,.flatpak-builder,flatpak_app,.flatpak,_build,.github}/*', + `**/{${excludeDirs}}/*`, 1000 ) const manifests = new ManifestMap() diff --git a/src/test/suite/extension.test.ts b/src/test/suite/extension.test.ts index 550e3c6..8033e90 100644 --- a/src/test/suite/extension.test.ts +++ b/src/test/suite/extension.test.ts @@ -104,6 +104,45 @@ suite('manifestMap', () => { }) assert.equal(nIter, 2) }) + + test('update', () => { + const first_map = new ManifestMap() + assert(first_map.isEmpty()) + + const second_map = new ManifestMap() + assert(second_map.isEmpty()) + + const manifestAUri = Uri.file('/home/test/a.a.a.json') + const manifestA = createTestManifest(manifestAUri) + + const manifestBUri = Uri.file('/home/test/b.b.b.json') + const manifestB = createTestManifest(manifestBUri) + + first_map.add(manifestA) + assert.equal(first_map.size(), 1) + assert.deepStrictEqual(first_map.get(manifestAUri), manifestA) + + second_map.add(manifestB) + assert.equal(second_map.size(), 1) + assert.deepStrictEqual(second_map.get(manifestBUri), manifestB) + + first_map.update(second_map) + assert.equal(first_map.size(), 1) + assert.deepStrictEqual(first_map.get(manifestBUri), manifestB) + + second_map.delete(manifestBUri) + assert(second_map.isEmpty()) + + first_map.update(second_map) + assert(first_map.isEmpty()) + + second_map.add(manifestA) + second_map.add(manifestB) + assert.equal(second_map.size(), 2) + + first_map.update(second_map) + assert.equal(first_map.size(), 2) + }) }) suite('manifestUtils', () => {