diff --git a/.eslintignore b/.eslintignore index 73a6f0f3b..74f1f559b 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1644,6 +1644,12 @@ packages/plugin-repo-cli/lib/gitCompareUrl.js.map packages/plugin-repo-cli/lib/gitCompareUrl.test.d.ts packages/plugin-repo-cli/lib/gitCompareUrl.test.js packages/plugin-repo-cli/lib/gitCompareUrl.test.js.map +packages/plugin-repo-cli/lib/overrideUtils.d.ts +packages/plugin-repo-cli/lib/overrideUtils.js +packages/plugin-repo-cli/lib/overrideUtils.js.map +packages/plugin-repo-cli/lib/overrideUtils.test.d.ts +packages/plugin-repo-cli/lib/overrideUtils.test.js +packages/plugin-repo-cli/lib/overrideUtils.test.js.map packages/plugin-repo-cli/lib/types.d.ts packages/plugin-repo-cli/lib/types.js packages/plugin-repo-cli/lib/types.js.map @@ -1653,6 +1659,9 @@ packages/plugin-repo-cli/lib/updateReadme.js.map packages/plugin-repo-cli/lib/updateReadme.test.d.ts packages/plugin-repo-cli/lib/updateReadme.test.js packages/plugin-repo-cli/lib/updateReadme.test.js.map +packages/plugin-repo-cli/lib/utils.d.ts +packages/plugin-repo-cli/lib/utils.js +packages/plugin-repo-cli/lib/utils.js.map packages/plugins/ToggleSidebars/api/index.d.ts packages/plugins/ToggleSidebars/api/index.js packages/plugins/ToggleSidebars/api/index.js.map diff --git a/.gitignore b/.gitignore index ff2c2ca7b..bf588a2b4 100644 --- a/.gitignore +++ b/.gitignore @@ -1629,6 +1629,12 @@ packages/plugin-repo-cli/lib/gitCompareUrl.js.map packages/plugin-repo-cli/lib/gitCompareUrl.test.d.ts packages/plugin-repo-cli/lib/gitCompareUrl.test.js packages/plugin-repo-cli/lib/gitCompareUrl.test.js.map +packages/plugin-repo-cli/lib/overrideUtils.d.ts +packages/plugin-repo-cli/lib/overrideUtils.js +packages/plugin-repo-cli/lib/overrideUtils.js.map +packages/plugin-repo-cli/lib/overrideUtils.test.d.ts +packages/plugin-repo-cli/lib/overrideUtils.test.js +packages/plugin-repo-cli/lib/overrideUtils.test.js.map packages/plugin-repo-cli/lib/types.d.ts packages/plugin-repo-cli/lib/types.js packages/plugin-repo-cli/lib/types.js.map @@ -1638,6 +1644,9 @@ packages/plugin-repo-cli/lib/updateReadme.js.map packages/plugin-repo-cli/lib/updateReadme.test.d.ts packages/plugin-repo-cli/lib/updateReadme.test.js packages/plugin-repo-cli/lib/updateReadme.test.js.map +packages/plugin-repo-cli/lib/utils.d.ts +packages/plugin-repo-cli/lib/utils.js +packages/plugin-repo-cli/lib/utils.js.map packages/plugins/ToggleSidebars/api/index.d.ts packages/plugins/ToggleSidebars/api/index.js packages/plugins/ToggleSidebars/api/index.js.map diff --git a/packages/plugin-repo-cli/index.ts b/packages/plugin-repo-cli/index.ts index dbcb04c27..e873523d4 100644 --- a/packages/plugin-repo-cli/index.ts +++ b/packages/plugin-repo-cli/index.ts @@ -10,18 +10,8 @@ import updateReadme from './lib/updateReadme'; import { NpmPackage } from './lib/types'; import gitCompareUrl from './lib/gitCompareUrl'; import commandUpdateRelease from './commands/updateRelease'; - -function stripOffPackageOrg(name: string): string { - const n = name.split('/'); - if (n[0][0] === '@') n.splice(0, 1); - return n.join('/'); -} - -function isJoplinPluginPackage(pack: any): boolean { - if (!pack.keywords || !pack.keywords.includes('joplin-plugin')) return false; - if (stripOffPackageOrg(pack.name).indexOf('joplin-plugin') !== 0) return false; - return true; -} +import { isJoplinPluginPackage, readJsonFile } from './lib/utils'; +import { applyManifestOverrides, getObsoleteManifests, readManifestOverrides } from './lib/overrideUtils'; function pluginInfoFromSearchResults(results: any[]): NpmPackage[] { const output: NpmPackage[] = []; @@ -44,19 +34,11 @@ async function checkPluginRepository(dirPath: string, dryRun: boolean) { if (!(await fs.pathExists(`${dirPath}/.git`))) throw new Error(`Directory is not a Git repository: ${dirPath}`); const previousDir = chdir(dirPath); - await gitRepoCleanTry(); - if (!dryRun) await gitPullTry(); - chdir(previousDir); -} - -async function readJsonFile(manifestPath: string, defaultValue: any = null): Promise { - if (!(await fs.pathExists(manifestPath))) { - if (defaultValue === null) throw new Error(`No such file: ${manifestPath}`); - return defaultValue; + if (!dryRun) { + await gitRepoCleanTry(); + await gitPullTry(); } - - const content = await fs.readFile(manifestPath, 'utf8'); - return JSON.parse(content); + chdir(previousDir); } async function extractPluginFilesFromPackage(existingManifests: any, workDir: string, packageName: string, destDir: string): Promise { @@ -147,14 +129,14 @@ function chdir(path: string): string { return previous; } -async function processNpmPackage(npmPackage: NpmPackage, repoDir: string) { +async function processNpmPackage(npmPackage: NpmPackage, repoDir: string, dryRun: boolean) { const tempDir = `${repoDir}/temp`; - const obsoleteManifestsPath = path.resolve(repoDir, 'obsoletes.json'); await fs.mkdirp(tempDir); const originalPluginManifests = await readManifests(repoDir); - const obsoleteManifests = await readJsonFile(obsoleteManifestsPath, {}); + const manifestOverrides = await readManifestOverrides(repoDir); + const obsoleteManifests = getObsoleteManifests(manifestOverrides); const existingManifests = { ...originalPluginManifests, ...obsoleteManifests, @@ -199,6 +181,8 @@ async function processNpmPackage(npmPackage: NpmPackage, repoDir: string) { ...manifests, }; + manifests = applyManifestOverrides(manifests, manifestOverrides); + await writeManifests(repoDir, manifests); await updateReadme(`${repoDir}/README.md`, manifests); } @@ -206,11 +190,13 @@ async function processNpmPackage(npmPackage: NpmPackage, repoDir: string) { chdir(repoDir); await fs.remove(tempDir); - if (!(await gitRepoClean())) { - await execCommand2('git add -A', { showOutput: false }); - await execCommand2(['git', 'commit', '-m', commitMessage(actionType, manifest, previousManifest, npmPackage, error)], { showOutput: false }); - } else { - console.info('Nothing to commit'); + if (!dryRun) { + if (!(await gitRepoClean())) { + await execCommand2('git add -A', { showOutput: false }); + await execCommand2(['git', 'commit', '-m', commitMessage(actionType, manifest, previousManifest, npmPackage, error)], { showOutput: false }); + } else { + console.info('Nothing to commit'); + } } } @@ -223,36 +209,40 @@ async function commandBuild(args: CommandBuildArgs) { await checkPluginRepository(repoDir, dryRun); // When starting, always update and commit README, in case something has - // been updated via a pull request (for example obsoletes.json being - // modified). We do that separately so that the README update doesn't get - // mixed up with plugin updates, as in this example: + // been updated via a pull request. We do that separately so that the README + // update doesn't get mixed up with plugin updates, as in this example: // https://github.com/joplin/plugins/commit/8a65bbbf64bf267674f854a172466ffd4f07c672 const manifests = await readManifests(repoDir); await updateReadme(`${repoDir}/README.md`, manifests); const previousDir = chdir(repoDir); - if (!(await gitRepoClean())) { - console.info('Updating README...'); - await execCommand2('git add -A', { showOutput: true }); - await execCommand2('git commit -m "Update README"', { showOutput: true }); + + if (!dryRun) { + if (!(await gitRepoClean())) { + console.info('Updating README...'); + await execCommand2('git add -A', { showOutput: true }); + await execCommand2('git commit -m "Update README"', { showOutput: true }); + } } + chdir(previousDir); const searchResults = (await execCommand2('npm search joplin-plugin --searchlimit 5000 --json', { showOutput: false })).trim(); const npmPackages = pluginInfoFromSearchResults(JSON.parse(searchResults)); for (const npmPackage of npmPackages) { - await processNpmPackage(npmPackage, repoDir); + await processNpmPackage(npmPackage, repoDir, dryRun); } if (!dryRun) { await commandUpdateRelease(args); + if (!(await gitRepoClean())) { await execCommand2('git add -A', { showOutput: true }); await execCommand2('git commit -m "Update stats"', { showOutput: true }); } - } - if (!dryRun) await execCommand2('git push'); + await execCommand2('git push'); + } } async function commandVersion() { diff --git a/packages/plugin-repo-cli/lib/overrideUtils.test.ts b/packages/plugin-repo-cli/lib/overrideUtils.test.ts new file mode 100644 index 000000000..fafab7221 --- /dev/null +++ b/packages/plugin-repo-cli/lib/overrideUtils.test.ts @@ -0,0 +1,95 @@ +import { applyManifestOverrides, getObsoleteManifests, ManifestOverrides } from './overrideUtils'; + +describe('overrideUtils', () => { + + test('should get the obsolete manifests', () => { + const manifestOverrides: any = { + 'ambrt.backlinksToNote': { + 'manifest_version': 1, + 'id': 'ambrt.backlinksToNote', + 'app_min_version': '1.5', + 'version': '1.0.2', + 'name': 'Backlinks to note', + 'description': 'Creates backlinks to opened note', + 'author': 'a', + 'homepage_url': 'https://discourse.joplinapp.org/t/insert-referencing-notes-backlinks-plugin/13632', + '_publish_hash': 'sha256:5676da6b9ad71fc5a9779d3bde13f17de5352344711e135f0db8c62c6dbb5696', + '_publish_commit': 'master:19e515bd67e51cc37bd270a32d2898ca009a0de2', + '_npm_package_name': 'joplin-plugin-backlinks', + '_obsolete': true, + }, + 'MyPlugin': { + 'manifest_version': 1, + 'id': 'MyPlugin', + 'app_min_version': '1.6', + 'version': '1.0.0', + 'name': 'Testing New Plugin', + 'description': 'bla', + 'author': 'bla', + 'homepage_url': 'bla', + 'repository_url': 'bla', + '_publish_hash': 'sha256:065285d06ea3c084e7f8f8c23583de8d70c4d586274a242c4c750f6faad8c7cb', + '_publish_commit': '', + '_npm_package_name': 'joplin-plugin-testing-new-plugin', + '_obsolete': true, + }, + 'io.github.jackgruber.copytags': { + '_recommended': true, + }, + }; + + const obsoletes = getObsoleteManifests(manifestOverrides); + expect(Object.keys(obsoletes).sort()).toEqual(['MyPlugin', 'ambrt.backlinksToNote']); + expect(obsoletes['ambrt.backlinksToNote'].description).toBe('Creates backlinks to opened note'); + }); + + test('should apply the overrides', () => { + const manifests: any = { + 'io.github.jackgruber.copytags': { + 'manifest_version': 1, + 'id': 'io.github.jackgruber.copytags', + 'app_min_version': '1.6.2', + 'version': '1.0.1', + 'name': 'Tagging', + 'description': 'Plugin to extend the Joplin tagging menu with a coppy all tags and a tagging dialog with more control. (Formerly Copy Tags).', + 'author': 'JackGruber', + 'homepage_url': 'https://github.com/JackGruber/joplin-plugin-tagging/blob/master/README.md', + 'repository_url': 'https://github.com/JackGruber/joplin-plugin-tagging', + 'keywords': [ + 'duplicate', + 'copy', + 'tags', + 'tagging', + 'tag', + ], + '_publish_hash': 'sha256:88daaf234a9b47e5644a8de6f830a801d12edbe41ea5364d994773e89eeafeef', + '_publish_commit': 'master:64c0510e3236df7788a8d10ec28dcfbb4c2bdbb7', + '_npm_package_name': 'joplin-plugin-copytags', + }, + 'joplin.plugin.ambrt.backlinksToNote': { + 'manifest_version': 1, + 'id': 'joplin.plugin.ambrt.backlinksToNote', + 'app_min_version': '1.7', + 'version': '2.0.11', + 'name': 'Automatic Backlinks to note', + 'description': 'Creates backlinks to opened note, also in automatic way', + 'author': 'ambrt,cyingfan', + 'homepage_url': 'https://discourse.joplinapp.org/t/insert-referencing-notes-backlinks-plugin/13632', + '_publish_hash': 'sha256:df57930d1ab62d4297dad0bb1764888935fcbf6ca8c04e3a843e86a260735c51', + '_publish_commit': 'master:98102718a9c0fa9416d654451b18602798c4d3bb', + '_npm_package_name': 'joplin-plugin-backlinks', + }, + }; + + const overrides: ManifestOverrides = { + 'io.github.jackgruber.copytags': { + _recommended: true, + }, + }; + + const updatedManifests = applyManifestOverrides(manifests, overrides); + expect(updatedManifests['io.github.jackgruber.copytags']._recommended).toBe(true); + expect(updatedManifests['joplin.plugin.ambrt.backlinksToNote']._recommended).toBe(undefined); + }); + +}); diff --git a/packages/plugin-repo-cli/lib/overrideUtils.ts b/packages/plugin-repo-cli/lib/overrideUtils.ts new file mode 100644 index 000000000..102a9d622 --- /dev/null +++ b/packages/plugin-repo-cli/lib/overrideUtils.ts @@ -0,0 +1,51 @@ +import * as path from 'path'; +import { readJsonFile } from './utils'; + +export interface ManifestOverride { + _obsolete?: boolean; + _recommended?: boolean; +} + +export type ManifestOverrides = Record; + +export function applyManifestOverrides(manifests: any, overrides: ManifestOverrides) { + for (const [pluginId, override] of Object.entries(overrides)) { + const manifest: any = manifests[pluginId]; + + if (!manifest) { + // If the manifest does not exist in the destination, it means the + // plugin has been taken out, so the obsolete property should be set + // to `true`. If not, it's an error. + if (!override._obsolete) { + console.error(`Could not find manifest for plugin ${pluginId} when applying override`); + } + continue; + } + + for (const [propName, propValue] of Object.entries(override)) { + manifest[propName] = propValue; + } + } + + return manifests; +} + +export function getObsoleteManifests(overrides: ManifestOverrides) { + const output: any = {}; + + for (const [pluginId, override] of Object.entries(overrides)) { + if (override._obsolete) { + output[pluginId] = override; + } + } + + return output; +} + +function pluginManifestOverridesPath(repoDir: string): string { + return path.resolve(repoDir, 'manifestOverrides.json'); +} + +export async function readManifestOverrides(repoDir: string): Promise { + return readJsonFile(pluginManifestOverridesPath(repoDir), {}); +} diff --git a/packages/plugin-repo-cli/lib/utils.ts b/packages/plugin-repo-cli/lib/utils.ts new file mode 100644 index 000000000..dbbf74021 --- /dev/null +++ b/packages/plugin-repo-cli/lib/utils.ts @@ -0,0 +1,23 @@ +import * as fs from 'fs-extra'; + +export async function readJsonFile(manifestPath: string, defaultValue: any = null): Promise { + if (!(await fs.pathExists(manifestPath))) { + if (defaultValue === null) throw new Error(`No such file: ${manifestPath}`); + return defaultValue; + } + + const content = await fs.readFile(manifestPath, 'utf8'); + return JSON.parse(content); +} + +function stripOffPackageOrg(name: string): string { + const n = name.split('/'); + if (n[0][0] === '@') n.splice(0, 1); + return n.join('/'); +} + +export function isJoplinPluginPackage(pack: any): boolean { + if (!pack.keywords || !pack.keywords.includes('joplin-plugin')) return false; + if (stripOffPackageOrg(pack.name).indexOf('joplin-plugin') !== 0) return false; + return true; +} diff --git a/packages/plugin-repo-cli/package.json b/packages/plugin-repo-cli/package.json index cf250df5c..23b522bec 100644 --- a/packages/plugin-repo-cli/package.json +++ b/packages/plugin-repo-cli/package.json @@ -13,7 +13,8 @@ "tsc": "tsc --project tsconfig.json", "watch": "tsc --watch --project tsconfig.json", "test": "jest", - "test-ci": "npm run test" + "test-ci": "npm run test", + "start": "node index.js" }, "author": "", "license": "MIT",