1
0
mirror of https://github.com/laurent22/joplin.git synced 2024-12-21 09:38:01 +02:00

Plugin Repo: Allow overridding manifest properties and added recommended plugins

This commit is contained in:
Laurent Cozic 2021-08-31 22:37:56 +01:00
parent dc008ecf64
commit 9c44133bd0
7 changed files with 221 additions and 43 deletions

View File

@ -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.d.ts
packages/plugin-repo-cli/lib/gitCompareUrl.test.js packages/plugin-repo-cli/lib/gitCompareUrl.test.js
packages/plugin-repo-cli/lib/gitCompareUrl.test.js.map 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.d.ts
packages/plugin-repo-cli/lib/types.js packages/plugin-repo-cli/lib/types.js
packages/plugin-repo-cli/lib/types.js.map 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.d.ts
packages/plugin-repo-cli/lib/updateReadme.test.js packages/plugin-repo-cli/lib/updateReadme.test.js
packages/plugin-repo-cli/lib/updateReadme.test.js.map 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.d.ts
packages/plugins/ToggleSidebars/api/index.js packages/plugins/ToggleSidebars/api/index.js
packages/plugins/ToggleSidebars/api/index.js.map packages/plugins/ToggleSidebars/api/index.js.map

9
.gitignore vendored
View File

@ -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.d.ts
packages/plugin-repo-cli/lib/gitCompareUrl.test.js packages/plugin-repo-cli/lib/gitCompareUrl.test.js
packages/plugin-repo-cli/lib/gitCompareUrl.test.js.map 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.d.ts
packages/plugin-repo-cli/lib/types.js packages/plugin-repo-cli/lib/types.js
packages/plugin-repo-cli/lib/types.js.map 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.d.ts
packages/plugin-repo-cli/lib/updateReadme.test.js packages/plugin-repo-cli/lib/updateReadme.test.js
packages/plugin-repo-cli/lib/updateReadme.test.js.map 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.d.ts
packages/plugins/ToggleSidebars/api/index.js packages/plugins/ToggleSidebars/api/index.js
packages/plugins/ToggleSidebars/api/index.js.map packages/plugins/ToggleSidebars/api/index.js.map

View File

@ -10,18 +10,8 @@ import updateReadme from './lib/updateReadme';
import { NpmPackage } from './lib/types'; import { NpmPackage } from './lib/types';
import gitCompareUrl from './lib/gitCompareUrl'; import gitCompareUrl from './lib/gitCompareUrl';
import commandUpdateRelease from './commands/updateRelease'; import commandUpdateRelease from './commands/updateRelease';
import { isJoplinPluginPackage, readJsonFile } from './lib/utils';
function stripOffPackageOrg(name: string): string { import { applyManifestOverrides, getObsoleteManifests, readManifestOverrides } from './lib/overrideUtils';
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;
}
function pluginInfoFromSearchResults(results: any[]): NpmPackage[] { function pluginInfoFromSearchResults(results: any[]): NpmPackage[] {
const output: 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}`); if (!(await fs.pathExists(`${dirPath}/.git`))) throw new Error(`Directory is not a Git repository: ${dirPath}`);
const previousDir = chdir(dirPath); const previousDir = chdir(dirPath);
if (!dryRun) {
await gitRepoCleanTry(); await gitRepoCleanTry();
if (!dryRun) await gitPullTry(); await gitPullTry();
chdir(previousDir);
}
async function readJsonFile(manifestPath: string, defaultValue: any = null): Promise<any> {
if (!(await fs.pathExists(manifestPath))) {
if (defaultValue === null) throw new Error(`No such file: ${manifestPath}`);
return defaultValue;
} }
chdir(previousDir);
const content = await fs.readFile(manifestPath, 'utf8');
return JSON.parse(content);
} }
async function extractPluginFilesFromPackage(existingManifests: any, workDir: string, packageName: string, destDir: string): Promise<any> { async function extractPluginFilesFromPackage(existingManifests: any, workDir: string, packageName: string, destDir: string): Promise<any> {
@ -147,14 +129,14 @@ function chdir(path: string): string {
return previous; return previous;
} }
async function processNpmPackage(npmPackage: NpmPackage, repoDir: string) { async function processNpmPackage(npmPackage: NpmPackage, repoDir: string, dryRun: boolean) {
const tempDir = `${repoDir}/temp`; const tempDir = `${repoDir}/temp`;
const obsoleteManifestsPath = path.resolve(repoDir, 'obsoletes.json');
await fs.mkdirp(tempDir); await fs.mkdirp(tempDir);
const originalPluginManifests = await readManifests(repoDir); const originalPluginManifests = await readManifests(repoDir);
const obsoleteManifests = await readJsonFile(obsoleteManifestsPath, {}); const manifestOverrides = await readManifestOverrides(repoDir);
const obsoleteManifests = getObsoleteManifests(manifestOverrides);
const existingManifests = { const existingManifests = {
...originalPluginManifests, ...originalPluginManifests,
...obsoleteManifests, ...obsoleteManifests,
@ -199,6 +181,8 @@ async function processNpmPackage(npmPackage: NpmPackage, repoDir: string) {
...manifests, ...manifests,
}; };
manifests = applyManifestOverrides(manifests, manifestOverrides);
await writeManifests(repoDir, manifests); await writeManifests(repoDir, manifests);
await updateReadme(`${repoDir}/README.md`, manifests); await updateReadme(`${repoDir}/README.md`, manifests);
} }
@ -206,12 +190,14 @@ async function processNpmPackage(npmPackage: NpmPackage, repoDir: string) {
chdir(repoDir); chdir(repoDir);
await fs.remove(tempDir); await fs.remove(tempDir);
if (!dryRun) {
if (!(await gitRepoClean())) { if (!(await gitRepoClean())) {
await execCommand2('git add -A', { showOutput: false }); await execCommand2('git add -A', { showOutput: false });
await execCommand2(['git', 'commit', '-m', commitMessage(actionType, manifest, previousManifest, npmPackage, error)], { showOutput: false }); await execCommand2(['git', 'commit', '-m', commitMessage(actionType, manifest, previousManifest, npmPackage, error)], { showOutput: false });
} else { } else {
console.info('Nothing to commit'); console.info('Nothing to commit');
} }
}
} }
async function commandBuild(args: CommandBuildArgs) { async function commandBuild(args: CommandBuildArgs) {
@ -223,36 +209,40 @@ async function commandBuild(args: CommandBuildArgs) {
await checkPluginRepository(repoDir, dryRun); await checkPluginRepository(repoDir, dryRun);
// When starting, always update and commit README, in case something has // When starting, always update and commit README, in case something has
// been updated via a pull request (for example obsoletes.json being // been updated via a pull request. We do that separately so that the README
// modified). We do that separately so that the README update doesn't get // update doesn't get mixed up with plugin updates, as in this example:
// mixed up with plugin updates, as in this example:
// https://github.com/joplin/plugins/commit/8a65bbbf64bf267674f854a172466ffd4f07c672 // https://github.com/joplin/plugins/commit/8a65bbbf64bf267674f854a172466ffd4f07c672
const manifests = await readManifests(repoDir); const manifests = await readManifests(repoDir);
await updateReadme(`${repoDir}/README.md`, manifests); await updateReadme(`${repoDir}/README.md`, manifests);
const previousDir = chdir(repoDir); const previousDir = chdir(repoDir);
if (!dryRun) {
if (!(await gitRepoClean())) { if (!(await gitRepoClean())) {
console.info('Updating README...'); console.info('Updating README...');
await execCommand2('git add -A', { showOutput: true }); await execCommand2('git add -A', { showOutput: true });
await execCommand2('git commit -m "Update README"', { showOutput: true }); await execCommand2('git commit -m "Update README"', { showOutput: true });
} }
}
chdir(previousDir); chdir(previousDir);
const searchResults = (await execCommand2('npm search joplin-plugin --searchlimit 5000 --json', { showOutput: false })).trim(); const searchResults = (await execCommand2('npm search joplin-plugin --searchlimit 5000 --json', { showOutput: false })).trim();
const npmPackages = pluginInfoFromSearchResults(JSON.parse(searchResults)); const npmPackages = pluginInfoFromSearchResults(JSON.parse(searchResults));
for (const npmPackage of npmPackages) { for (const npmPackage of npmPackages) {
await processNpmPackage(npmPackage, repoDir); await processNpmPackage(npmPackage, repoDir, dryRun);
} }
if (!dryRun) { if (!dryRun) {
await commandUpdateRelease(args); await commandUpdateRelease(args);
if (!(await gitRepoClean())) { if (!(await gitRepoClean())) {
await execCommand2('git add -A', { showOutput: true }); await execCommand2('git add -A', { showOutput: true });
await execCommand2('git commit -m "Update stats"', { showOutput: true }); await execCommand2('git commit -m "Update stats"', { showOutput: true });
} }
}
if (!dryRun) await execCommand2('git push'); await execCommand2('git push');
}
} }
async function commandVersion() { async function commandVersion() {

View File

@ -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);
});
});

View File

@ -0,0 +1,51 @@
import * as path from 'path';
import { readJsonFile } from './utils';
export interface ManifestOverride {
_obsolete?: boolean;
_recommended?: boolean;
}
export type ManifestOverrides = Record<string, ManifestOverride>;
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<ManifestOverrides> {
return readJsonFile(pluginManifestOverridesPath(repoDir), {});
}

View File

@ -0,0 +1,23 @@
import * as fs from 'fs-extra';
export async function readJsonFile(manifestPath: string, defaultValue: any = null): Promise<any> {
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;
}

View File

@ -13,7 +13,8 @@
"tsc": "tsc --project tsconfig.json", "tsc": "tsc --project tsconfig.json",
"watch": "tsc --watch --project tsconfig.json", "watch": "tsc --watch --project tsconfig.json",
"test": "jest", "test": "jest",
"test-ci": "npm run test" "test-ci": "npm run test",
"start": "node index.js"
}, },
"author": "", "author": "",
"license": "MIT", "license": "MIT",