mirror of https://github.com/laurent22/joplin.git
Tools: Moved some utility functions to @joplin/utils to reduce dependencies between packages
parent
1548ea18e1
commit
3e52411bc4
|
@ -14,7 +14,8 @@
|
|||
"@joplin/turndown-plugin-gfm",
|
||||
"@joplin/tools",
|
||||
"@joplin/react-native-saf-x",
|
||||
"@joplin/react-native-alarm-notification"
|
||||
"@joplin/react-native-alarm-notification",
|
||||
"@joplin/utils"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
|
@ -329,6 +329,7 @@
|
|||
"packages/renderer/MdToHtml/rules/sanitize_html.js": true,
|
||||
"packages/server/db-*.sqlite": true,
|
||||
"packages/server/dist/": true,
|
||||
"packages/utils/dist/": true,
|
||||
"packages/server/temp": true,
|
||||
"packages/server/test.pid": true,
|
||||
"phpunit.xml": true,
|
||||
|
|
|
@ -8,7 +8,7 @@ const Resource = require('@joplin/lib/models/Resource').default;
|
|||
const Setting = require('@joplin/lib/models/Setting').default;
|
||||
const reducer = require('@joplin/lib/reducer').default;
|
||||
const { defaultState } = require('@joplin/lib/reducer');
|
||||
const { splitCommandString } = require('@joplin/lib/string-utils.js');
|
||||
const { splitCommandString } = require('@joplin/utils');
|
||||
const { reg } = require('@joplin/lib/registry.js');
|
||||
const { _ } = require('@joplin/lib/locale');
|
||||
const shim = require('@joplin/lib/shim').default;
|
||||
|
|
|
@ -9,7 +9,8 @@ const Tag = require('@joplin/lib/models/Tag').default;
|
|||
const Setting = require('@joplin/lib/models/Setting').default;
|
||||
const { reg } = require('@joplin/lib/registry.js');
|
||||
const { fileExtension } = require('@joplin/lib/path-utils');
|
||||
const { splitCommandString, splitCommandBatch } = require('@joplin/lib/string-utils');
|
||||
const { splitCommandString } = require('@joplin/utils');
|
||||
const { splitCommandBatch } = require('@joplin/lib/string-utils');
|
||||
const { _ } = require('@joplin/lib/locale');
|
||||
const fs = require('fs-extra');
|
||||
const { cliUtils } = require('./cli-utils.js');
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
const fs = require('fs-extra');
|
||||
const BaseCommand = require('./base-command').default;
|
||||
const { splitCommandString } = require('@joplin/lib/string-utils.js');
|
||||
const { splitCommandString } = require('@joplin/utils');
|
||||
const uuid = require('@joplin/lib/uuid').default;
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('@joplin/lib/locale');
|
||||
|
|
|
@ -30,7 +30,8 @@
|
|||
2019,
|
||||
2020,
|
||||
2021,
|
||||
2022
|
||||
2022,
|
||||
2023
|
||||
],
|
||||
"owner": "Laurent Cozic"
|
||||
},
|
||||
|
@ -42,6 +43,7 @@
|
|||
"dependencies": {
|
||||
"@joplin/lib": "~2.10",
|
||||
"@joplin/renderer": "~2.10",
|
||||
"@joplin/utils": "~2.10",
|
||||
"aws-sdk": "2.1290.0",
|
||||
"chalk": "4.1.2",
|
||||
"compare-version": "0.1.2",
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
import * as fs from 'fs-extra';
|
||||
import { homedir } from 'os';
|
||||
import { execCommand2 } from '@joplin/tools/tool-utils';
|
||||
import { execCommand } from '@joplin/utils';
|
||||
import { chdir } from 'process';
|
||||
|
||||
const minUserNum = 1;
|
||||
|
@ -66,7 +66,7 @@ const processUser = async (userNum: number) => {
|
|||
|
||||
await chdir(cliDir);
|
||||
|
||||
await execCommand2(['yarn', 'run', 'start-no-build', '--', '--profile', profileDir, 'batch', commandFile]);
|
||||
await execCommand(['yarn', 'run', 'start-no-build', '--', '--profile', profileDir, 'batch', commandFile]);
|
||||
} catch (error) {
|
||||
console.error(`Could not process user ${userNum}:`, error);
|
||||
} finally {
|
||||
|
@ -90,7 +90,7 @@ const main = async () => {
|
|||
|
||||
// Build the app once before starting, because we'll use start-no-build to
|
||||
// run the scripts (faster)
|
||||
await execCommand2(['yarn', 'run', 'build']);
|
||||
await execCommand(['yarn', 'run', 'build']);
|
||||
|
||||
const focusUserNum = 0;
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ import Folder from './models/Folder';
|
|||
import BaseItem from './models/BaseItem';
|
||||
import Note from './models/Note';
|
||||
import Tag from './models/Tag';
|
||||
const { splitCommandString } = require('./string-utils.js');
|
||||
import { splitCommandString } from '@joplin/utils';
|
||||
import { reg } from './registry';
|
||||
import time from './time';
|
||||
import BaseSyncTarget from './BaseSyncTarget';
|
||||
|
@ -706,7 +706,7 @@ export default class BaseApplication {
|
|||
|
||||
flagContent = flagContent.trim();
|
||||
|
||||
let flags = splitCommandString(flagContent);
|
||||
let flags: any = splitCommandString(flagContent);
|
||||
flags.splice(0, 0, 'cmd');
|
||||
flags.splice(0, 0, 'node');
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
"@joplin/renderer": "^2.10.2",
|
||||
"@joplin/turndown": "^4.0.65",
|
||||
"@joplin/turndown-plugin-gfm": "^1.0.47",
|
||||
"@joplin/utils": "~2.10",
|
||||
"@types/nanoid": "3.0.0",
|
||||
"async-mutex": "0.4.0",
|
||||
"base-64": "1.0.0",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* eslint-disable import/prefer-default-export */
|
||||
|
||||
const { splitCommandString } = require('../../string-utils');
|
||||
import { splitCommandString } from '@joplin/utils';
|
||||
import { spawn } from 'child_process';
|
||||
import Logger from '../../Logger';
|
||||
import Setting from '../../models/Setting';
|
||||
|
|
|
@ -138,80 +138,6 @@ function commandArgumentsToString(args) {
|
|||
return output.join(' ');
|
||||
}
|
||||
|
||||
function splitCommandString(command, options = null) {
|
||||
options = options || {};
|
||||
if (!('handleEscape' in options)) {
|
||||
options.handleEscape = true;
|
||||
}
|
||||
|
||||
const args = [];
|
||||
let state = 'start';
|
||||
let current = '';
|
||||
let quote = '"';
|
||||
let escapeNext = false;
|
||||
for (let i = 0; i < command.length; i++) {
|
||||
const c = command[i];
|
||||
|
||||
if (state === 'quotes') {
|
||||
if (c !== quote) {
|
||||
current += c;
|
||||
} else {
|
||||
args.push(current);
|
||||
current = '';
|
||||
state = 'start';
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (escapeNext) {
|
||||
current += c;
|
||||
escapeNext = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c === '\\' && options.handleEscape) {
|
||||
escapeNext = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c === '"' || c === '\'') {
|
||||
state = 'quotes';
|
||||
quote = c;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (state === 'arg') {
|
||||
if (c === ' ' || c === '\t') {
|
||||
args.push(current);
|
||||
current = '';
|
||||
state = 'start';
|
||||
} else {
|
||||
current += c;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c !== ' ' && c !== '\t') {
|
||||
state = 'arg';
|
||||
current += c;
|
||||
}
|
||||
}
|
||||
|
||||
if (state === 'quotes') {
|
||||
throw new Error(`Unclosed quote in command line: ${command}`);
|
||||
}
|
||||
|
||||
if (current !== '') {
|
||||
args.push(current);
|
||||
}
|
||||
|
||||
if (args.length <= 0) {
|
||||
throw new Error('Empty command line');
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
function splitCommandBatch(commandBatch) {
|
||||
const commandLines = [];
|
||||
const eol = '\n';
|
||||
|
@ -368,4 +294,4 @@ function scriptType(s) {
|
|||
return 'en';
|
||||
}
|
||||
|
||||
module.exports = Object.assign({ formatCssSize, camelCaseToDash, removeDiacritics, substrWithEllipsis, nextWhitespaceIndex, escapeFilename, wrap, splitCommandString, splitCommandBatch, padLeft, toTitleCase, urlDecode, escapeHtml, surroundKeywords, scriptType, commandArgumentsToString }, stringUtilsCommon);
|
||||
module.exports = Object.assign({ formatCssSize, camelCaseToDash, removeDiacritics, substrWithEllipsis, nextWhitespaceIndex, escapeFilename, wrap, splitCommandBatch, padLeft, toTitleCase, urlDecode, escapeHtml, surroundKeywords, scriptType, commandArgumentsToString }, stringUtilsCommon);
|
||||
|
|
|
@ -9,7 +9,7 @@ import * as path from 'path';
|
|||
import * as process from 'process';
|
||||
import validatePluginId from '@joplin/lib/services/plugins/utils/validatePluginId';
|
||||
import validatePluginVersion from '@joplin/lib/services/plugins/utils/validatePluginVersion';
|
||||
import { execCommand2, resolveRelativePathWithinDir, gitPullTry, gitRepoCleanTry, gitRepoClean } from '@joplin/tools/tool-utils.js';
|
||||
import { resolveRelativePathWithinDir, gitPullTry, gitRepoCleanTry, gitRepoClean } from '@joplin/tools/tool-utils.js';
|
||||
import checkIfPluginCanBeAdded from './lib/checkIfPluginCanBeAdded';
|
||||
import updateReadme from './lib/updateReadme';
|
||||
import { NpmPackage } from './lib/types';
|
||||
|
@ -17,6 +17,7 @@ import gitCompareUrl from './lib/gitCompareUrl';
|
|||
import commandUpdateRelease from './commands/updateRelease';
|
||||
import { isJoplinPluginPackage, readJsonFile } from './lib/utils';
|
||||
import { applyManifestOverrides, getObsoleteManifests, readManifestOverrides } from './lib/overrideUtils';
|
||||
import { execCommand } from '@joplin/utils';
|
||||
|
||||
function pluginInfoFromSearchResults(results: any[]): NpmPackage[] {
|
||||
const output: NpmPackage[] = [];
|
||||
|
@ -49,7 +50,7 @@ async function checkPluginRepository(dirPath: string, dryRun: boolean) {
|
|||
async function extractPluginFilesFromPackage(existingManifests: any, workDir: string, packageName: string, destDir: string): Promise<any> {
|
||||
const previousDir = chdir(workDir);
|
||||
|
||||
await execCommand2(`npm install ${packageName} --save --ignore-scripts`, { showStderr: false, showStdout: false });
|
||||
await execCommand(`npm install ${packageName} --save --ignore-scripts`, { showStderr: false, showStdout: false });
|
||||
|
||||
const pluginDir = resolveRelativePathWithinDir(workDir, 'node_modules', packageName, 'publish');
|
||||
|
||||
|
@ -154,7 +155,7 @@ async function processNpmPackage(npmPackage: NpmPackage, repoDir: string, dryRun
|
|||
|
||||
await fs.mkdirp(packageTempDir);
|
||||
chdir(packageTempDir);
|
||||
await execCommand2('npm init --yes --loglevel silent', { quiet: true });
|
||||
await execCommand('npm init --yes --loglevel silent', { quiet: true });
|
||||
|
||||
let actionType: ProcessingActionType = ProcessingActionType.Update;
|
||||
let manifests: any = {};
|
||||
|
@ -200,8 +201,8 @@ async function processNpmPackage(npmPackage: NpmPackage, repoDir: string, dryRun
|
|||
|
||||
if (!dryRun) {
|
||||
if (!(await gitRepoClean())) {
|
||||
await execCommand2('git add -A', { showStdout: false });
|
||||
await execCommand2(['git', 'commit', '-m', commitMessage(actionType, manifest, previousManifest, npmPackage, error)], { showStdout: false });
|
||||
await execCommand('git add -A', { showStdout: false });
|
||||
await execCommand(['git', 'commit', '-m', commitMessage(actionType, manifest, previousManifest, npmPackage, error)], { showStdout: false });
|
||||
} else {
|
||||
console.info('Nothing to commit');
|
||||
}
|
||||
|
@ -227,14 +228,14 @@ async function commandBuild(args: CommandBuildArgs) {
|
|||
if (!dryRun) {
|
||||
if (!(await gitRepoClean())) {
|
||||
console.info('Updating README...');
|
||||
await execCommand2('git add -A');
|
||||
await execCommand2('git commit -m "Update README"');
|
||||
await execCommand('git add -A');
|
||||
await execCommand('git commit -m "Update README"');
|
||||
}
|
||||
}
|
||||
|
||||
chdir(previousDir);
|
||||
|
||||
const searchResults = (await execCommand2('npm search joplin-plugin --searchlimit 5000 --json', { showStdout: false, showStderr: false })).trim();
|
||||
const searchResults = (await execCommand('npm search joplin-plugin --searchlimit 5000 --json', { showStdout: false, showStderr: false })).trim();
|
||||
const npmPackages = pluginInfoFromSearchResults(JSON.parse(searchResults));
|
||||
|
||||
for (const npmPackage of npmPackages) {
|
||||
|
@ -245,11 +246,11 @@ async function commandBuild(args: CommandBuildArgs) {
|
|||
await commandUpdateRelease(args);
|
||||
|
||||
if (!(await gitRepoClean())) {
|
||||
await execCommand2('git add -A');
|
||||
await execCommand2('git commit -m "Update stats"');
|
||||
await execCommand('git add -A');
|
||||
await execCommand('git commit -m "Update stats"');
|
||||
}
|
||||
|
||||
await execCommand2('git push');
|
||||
await execCommand('git push');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
"dependencies": {
|
||||
"@joplin/lib": "^2.10.2",
|
||||
"@joplin/tools": "^2.10.2",
|
||||
"@joplin/utils": "~2.10",
|
||||
"fs-extra": "11.1.0",
|
||||
"gh-release-assets": "2.0.1",
|
||||
"node-fetch": "2.6.7",
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { execCommand2, rootDir } from './tool-utils';
|
||||
import { rootDir } from './tool-utils';
|
||||
import * as moment from 'moment';
|
||||
import { execCommand } from '@joplin/utils';
|
||||
|
||||
interface Argv {
|
||||
dryRun?: boolean;
|
||||
|
@ -35,7 +36,7 @@ async function main() {
|
|||
const buildDate = moment(new Date().getTime()).format('YYYY-MM-DDTHH:mm:ssZ');
|
||||
let revision = '';
|
||||
try {
|
||||
revision = await execCommand2('git rev-parse --short HEAD', { showStdout: false });
|
||||
revision = await execCommand('git rev-parse --short HEAD', { showStdout: false });
|
||||
} catch (error) {
|
||||
console.info('Could not get git commit: metadata revision field will be empty');
|
||||
}
|
||||
|
@ -62,11 +63,11 @@ async function main() {
|
|||
return;
|
||||
}
|
||||
|
||||
await execCommand2(dockerCommand);
|
||||
await execCommand(dockerCommand);
|
||||
|
||||
for (const tag of dockerTags) {
|
||||
await execCommand2(`docker tag "${repository}:${imageVersion}" "${repository}:${tag}"`);
|
||||
if (pushImages) await execCommand2(`docker push ${repository}:${tag}`);
|
||||
await execCommand(`docker tag "${repository}:${imageVersion}" "${repository}:${tag}"`);
|
||||
if (pushImages) await execCommand(`docker push ${repository}:${tag}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { join } from 'path';
|
||||
import { execCommand2 } from './tool-utils';
|
||||
import { pathExists, mkdir, readFile, move, remove, writeFile } from 'fs-extra';
|
||||
import { DefaultPluginsInfo } from '@joplin/lib/services/plugins/PluginService';
|
||||
import getDefaultPluginsInfo from '@joplin/lib/services/plugins/defaultPlugins/desktopDefaultPluginsInfo';
|
||||
import { execCommand } from '@joplin/utils';
|
||||
const fetch = require('node-fetch');
|
||||
|
||||
interface PluginAndVersion {
|
||||
|
@ -41,7 +41,7 @@ async function downloadFile(url: string, outputPath: string) {
|
|||
|
||||
export async function extractPlugins(currentDir: string, defaultPluginDir: string, downloadedPluginsNames: PluginIdAndName): Promise<void> {
|
||||
for (const pluginId of Object.keys(downloadedPluginsNames)) {
|
||||
await execCommand2(`tar xzf ${currentDir}/${downloadedPluginsNames[pluginId]}`, { quiet: true });
|
||||
await execCommand(`tar xzf ${currentDir}/${downloadedPluginsNames[pluginId]}`, { quiet: true });
|
||||
await move(`package/publish/${pluginId}.jpl`, `${defaultPluginDir}/${pluginId}/plugin.jpl`, { overwrite: true });
|
||||
await move(`package/publish/${pluginId}.json`, `${defaultPluginDir}/${pluginId}/manifest.json`, { overwrite: true });
|
||||
await remove(`${downloadedPluginsNames[pluginId]}`);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { execCommand2, rootDir } from './tool-utils';
|
||||
import { execCommand } from '@joplin/utils';
|
||||
import { rootDir } from './tool-utils';
|
||||
|
||||
const sqlts = require('@rmp135/sql-ts').default;
|
||||
const fs = require('fs-extra');
|
||||
|
@ -6,7 +7,7 @@ const fs = require('fs-extra');
|
|||
async function main() {
|
||||
// Run the CLI app once so as to generate the database file
|
||||
process.chdir(`${rootDir}/packages/app-cli`);
|
||||
await execCommand2('yarn start version');
|
||||
await execCommand('yarn start version');
|
||||
|
||||
const sqlTsConfig = {
|
||||
'client': 'sqlite3',
|
||||
|
|
|
@ -36,6 +36,7 @@ module.exports = {
|
|||
'packages/fork-sax/**',
|
||||
'packages/lib/plugin_types/**',
|
||||
'packages/server/**',
|
||||
'packages/utils/**',
|
||||
],
|
||||
}).filter(f => !f.endsWith('.d.ts'));
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { readdir, stat, writeFile } from 'fs-extra';
|
||||
import { chdir, cwd } from 'process';
|
||||
import { execCommand2, rootDir } from './tool-utils';
|
||||
import { rootDir } from './tool-utils';
|
||||
import { execCommand } from '@joplin/utils';
|
||||
import yargs = require('yargs');
|
||||
import { rtrimSlashes } from '@joplin/lib/path-utils';
|
||||
|
||||
|
@ -13,7 +14,7 @@ interface LicenseInfo {
|
|||
const getLicenses = async (directory: string): Promise<Record<string, LicenseInfo>> => {
|
||||
const previousDir = cwd();
|
||||
await chdir(directory);
|
||||
const result = await execCommand2(['license-checker-rseidelsohn', '--production', '--json'], { quiet: true });
|
||||
const result = await execCommand(['license-checker-rseidelsohn', '--production', '--json'], { quiet: true });
|
||||
const info: Record<string, LicenseInfo> = JSON.parse(result);
|
||||
if (!info) throw new Error(`Could not parse JSON: ${directory}`);
|
||||
await chdir(previousDir);
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
"dependencies": {
|
||||
"@joplin/lib": "^2.10.2",
|
||||
"@joplin/renderer": "^2.10.2",
|
||||
"@joplin/utils": "~2.10",
|
||||
"@types/node-fetch": "2.6.2",
|
||||
"@types/yargs": "17.0.20",
|
||||
"dayjs": "1.11.7",
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { execCommand } from '@joplin/utils';
|
||||
import * as fs from 'fs-extra';
|
||||
import { execCommandVerbose, execCommandWithPipes, githubRelease, githubOauthToken, fileExists, gitPullTry, completeReleaseWithChangelog, execCommand2 } from './tool-utils';
|
||||
import { execCommandVerbose, execCommandWithPipes, githubRelease, githubOauthToken, fileExists, gitPullTry, completeReleaseWithChangelog } from './tool-utils';
|
||||
const path = require('path');
|
||||
const fetch = require('node-fetch');
|
||||
const uriTemplate = require('uri-template');
|
||||
|
@ -150,7 +151,7 @@ async function main() {
|
|||
const isPreRelease = !('type' in argv) || argv.type === 'prerelease';
|
||||
|
||||
process.chdir(rnDir);
|
||||
await execCommand2('yarn run build', { showStdout: false });
|
||||
await execCommand('yarn run build', { showStdout: false });
|
||||
|
||||
if (isPreRelease) console.info('Creating pre-release');
|
||||
console.info('Updating version numbers in build.gradle...');
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { execCommand2, rootDir, completeReleaseWithChangelog } from './tool-utils';
|
||||
import { execCommand } from '@joplin/utils';
|
||||
import { rootDir, completeReleaseWithChangelog } from './tool-utils';
|
||||
|
||||
const appDir = `${rootDir}/packages/app-cli`;
|
||||
const changelogPath = `${rootDir}/readme/changelog_cli.md`;
|
||||
|
@ -8,19 +9,19 @@ const changelogPath = `${rootDir}/readme/changelog_cli.md`;
|
|||
async function main() {
|
||||
process.chdir(appDir);
|
||||
|
||||
await execCommand2('git pull');
|
||||
await execCommand('git pull');
|
||||
|
||||
const newVersion = (await execCommand2('npm version patch')).trim();
|
||||
const newVersion = (await execCommand('npm version patch')).trim();
|
||||
console.info(`Building ${newVersion}...`);
|
||||
const newTag = `cli-${newVersion}`;
|
||||
|
||||
await execCommand2('touch app/main.js');
|
||||
await execCommand2('yarn run build');
|
||||
await execCommand2('cp ../../README.md build/');
|
||||
await execCommand('touch app/main.js');
|
||||
await execCommand('yarn run build');
|
||||
await execCommand('cp ../../README.md build/');
|
||||
|
||||
process.chdir(`${appDir}/build`);
|
||||
|
||||
await execCommand2('npm publish');
|
||||
await execCommand('npm publish');
|
||||
|
||||
await completeReleaseWithChangelog(changelogPath, newVersion, newTag, 'CLI', false);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { execCommand2, gitCurrentBranch, githubRelease, gitPullTry, rootDir } from './tool-utils';
|
||||
import { execCommand } from '@joplin/utils';
|
||||
import { gitCurrentBranch, githubRelease, gitPullTry, rootDir } from './tool-utils';
|
||||
|
||||
const appDir = `${rootDir}/packages/app-desktop`;
|
||||
|
||||
|
@ -11,16 +12,16 @@ async function main() {
|
|||
|
||||
console.info(`Running from: ${process.cwd()}`);
|
||||
|
||||
const version = (await execCommand2('npm version patch')).trim();
|
||||
const version = (await execCommand('npm version patch')).trim();
|
||||
const tagName = version;
|
||||
|
||||
console.info(`New version number: ${version}`);
|
||||
|
||||
await execCommand2('git add -A');
|
||||
await execCommand2(`git commit -m "Desktop release ${version}"`);
|
||||
await execCommand2(`git tag ${tagName}`);
|
||||
await execCommand2('git push');
|
||||
await execCommand2('git push --tags');
|
||||
await execCommand('git add -A');
|
||||
await execCommand(`git commit -m "Desktop release ${version}"`);
|
||||
await execCommand(`git tag ${tagName}`);
|
||||
await execCommand('git push');
|
||||
await execCommand('git push --tags');
|
||||
|
||||
const releaseOptions = { isDraft: true, isPreRelease: !!argv.beta };
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { execCommand } from '@joplin/utils';
|
||||
import { chdir } from 'process';
|
||||
import { rootDir, gitPullTry, execCommand2, releaseFinalGitCommands } from './tool-utils';
|
||||
import { rootDir, gitPullTry, releaseFinalGitCommands } from './tool-utils';
|
||||
|
||||
const workDir = `${rootDir}/packages/plugin-repo-cli`;
|
||||
|
||||
|
@ -7,18 +8,18 @@ async function main() {
|
|||
await gitPullTry();
|
||||
|
||||
chdir(rootDir);
|
||||
await execCommand2('yarn run tsc');
|
||||
await execCommand('yarn run tsc');
|
||||
|
||||
chdir(workDir);
|
||||
await execCommand2('yarn run dist');
|
||||
await execCommand('yarn run dist');
|
||||
|
||||
const newVersion = (await execCommand2('npm version patch')).trim();
|
||||
const newVersion = (await execCommand('npm version patch')).trim();
|
||||
|
||||
console.info(`New version: ${newVersion}`);
|
||||
const tagName = `plugin-repo-cli-${newVersion}`;
|
||||
console.info(`Tag name: ${tagName}`);
|
||||
|
||||
await execCommand2('npm publish');
|
||||
await execCommand('npm publish');
|
||||
|
||||
console.info(releaseFinalGitCommands('Plugin Repo CLI', newVersion, tagName));
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { execCommand2, rootDir, gitPullTry, completeReleaseWithChangelog } from './tool-utils';
|
||||
import { execCommand } from '@joplin/utils';
|
||||
import { rootDir, gitPullTry, completeReleaseWithChangelog } from './tool-utils';
|
||||
|
||||
const serverDir = `${rootDir}/packages/server`;
|
||||
|
||||
|
@ -12,7 +13,7 @@ async function main() {
|
|||
await gitPullTry();
|
||||
|
||||
process.chdir(serverDir);
|
||||
const version = (await execCommand2('npm version patch')).trim();
|
||||
const version = (await execCommand('npm version patch')).trim();
|
||||
const versionSuffix = ''; // isPreRelease ? '-beta' : '';
|
||||
const tagName = `server-${version}${versionSuffix}`;
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import yargs = require('yargs');
|
||||
import { chdir } from 'process';
|
||||
import { execCommand2, rootDir } from './tool-utils';
|
||||
import { rootDir } from './tool-utils';
|
||||
import { execCommand } from '@joplin/utils';
|
||||
|
||||
const main = async () => {
|
||||
const argv = await yargs.argv;
|
||||
|
@ -10,7 +11,7 @@ const main = async () => {
|
|||
chdir(rootDir);
|
||||
|
||||
try {
|
||||
await execCommand2(['yarn', 'run', 'cspell'].concat(filePaths), { showStderr: false, showStdout: false });
|
||||
await execCommand(['yarn', 'run', 'cspell'].concat(filePaths), { showStderr: false, showStdout: false });
|
||||
} catch (error) {
|
||||
if (!error.stdout.trim()) return;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { execCommand2 } from './tool-utils';
|
||||
import { execCommand } from '@joplin/utils';
|
||||
|
||||
async function main() {
|
||||
const argv = require('yargs').argv;
|
||||
|
@ -6,9 +6,9 @@ async function main() {
|
|||
|
||||
const version = argv._[0];
|
||||
|
||||
await execCommand2(`docker pull "joplin/server:${version}"`);
|
||||
await execCommand2(`docker tag "joplin/server:${version}" "joplin/server:latest"`);
|
||||
await execCommand2('docker push joplin/server:latest');
|
||||
await execCommand(`docker pull "joplin/server:${version}"`);
|
||||
await execCommand(`docker tag "joplin/server:${version}" "joplin/server:latest"`);
|
||||
await execCommand('docker push joplin/server:latest');
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import * as fs from 'fs-extra';
|
||||
import { readCredentialFile } from '@joplin/lib/utils/credentialFiles';
|
||||
import { execCommand as execCommand2, commandToString } from '@joplin/utils';
|
||||
|
||||
const fetch = require('node-fetch');
|
||||
const execa = require('execa');
|
||||
const { splitCommandString } = require('@joplin/lib/string-utils');
|
||||
const moment = require('moment');
|
||||
|
||||
export interface GitHubReleaseAsset {
|
||||
|
@ -20,23 +20,6 @@ export interface GitHubRelease {
|
|||
draft: boolean;
|
||||
}
|
||||
|
||||
function quotePath(path: string) {
|
||||
if (!path) return '';
|
||||
if (path.indexOf('"') < 0 && path.indexOf(' ') < 0) return path;
|
||||
path = path.replace(/"/, '\\"');
|
||||
return `"${path}"`;
|
||||
}
|
||||
|
||||
function commandToString(commandName: string, args: string[] = []) {
|
||||
const output = [quotePath(commandName)];
|
||||
|
||||
for (const arg of args) {
|
||||
output.push(quotePath(arg));
|
||||
}
|
||||
|
||||
return output.join(' ');
|
||||
}
|
||||
|
||||
async function insertChangelog(tag: string, changelogPath: string, changelog: string, isPrerelease: boolean, repoTagUrl: string = '') {
|
||||
repoTagUrl = repoTagUrl || 'https://github.com/laurent22/joplin/releases/tag';
|
||||
|
||||
|
@ -163,52 +146,6 @@ export function execCommandVerbose(commandName: string, args: string[] = []) {
|
|||
return promise;
|
||||
}
|
||||
|
||||
interface ExecCommandOptions {
|
||||
showInput?: boolean;
|
||||
showStdout?: boolean;
|
||||
showStderr?: boolean;
|
||||
quiet?: boolean;
|
||||
}
|
||||
|
||||
// There's lot of execCommandXXX functions, but eventually all scripts should
|
||||
// use the one below, which supports:
|
||||
//
|
||||
// - Printing the command being executed
|
||||
// - Printing the output in real time (piping to stdout)
|
||||
// - Returning the command result as string
|
||||
export async function execCommand2(command: string | string[], options: ExecCommandOptions = null): Promise<string> {
|
||||
options = {
|
||||
showInput: true,
|
||||
showStdout: true,
|
||||
showStderr: true,
|
||||
quiet: false,
|
||||
...options,
|
||||
};
|
||||
|
||||
if (options.quiet) {
|
||||
options.showInput = false;
|
||||
options.showStdout = false;
|
||||
options.showStderr = false;
|
||||
}
|
||||
|
||||
if (options.showInput) {
|
||||
if (typeof command === 'string') {
|
||||
console.info(`> ${command}`);
|
||||
} else {
|
||||
console.info(`> ${commandToString(command[0], command.slice(1))}`);
|
||||
}
|
||||
}
|
||||
|
||||
const args: string[] = typeof command === 'string' ? splitCommandString(command) : command as string[];
|
||||
const executableName = args[0];
|
||||
args.splice(0, 1);
|
||||
const promise = execa(executableName, args);
|
||||
if (options.showStdout) promise.stdout.pipe(process.stdout);
|
||||
if (options.showStderr) promise.stdout.pipe(process.stderr);
|
||||
const result = await promise;
|
||||
return result.stdout.trim();
|
||||
}
|
||||
|
||||
export function execCommandWithPipes(executable: string, args: string[]) {
|
||||
const spawn = require('child_process').spawn;
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { execCommand } from '@joplin/utils';
|
||||
import { chdir } from 'process';
|
||||
import { execCommand2, rootDir, gitRepoCleanTry } from './tool-utils';
|
||||
import { rootDir, gitRepoCleanTry } from './tool-utils';
|
||||
import updateDownloadPage from './website/updateDownloadPage';
|
||||
|
||||
async function main() {
|
||||
|
@ -7,23 +8,23 @@ async function main() {
|
|||
|
||||
if (doGitOperations) {
|
||||
await gitRepoCleanTry();
|
||||
await execCommand2(['git', 'pull', '--rebase']);
|
||||
await execCommand(['git', 'pull', '--rebase']);
|
||||
}
|
||||
|
||||
await execCommand2(['node', `${rootDir}/packages/tools/update-readme-download.js`]);
|
||||
await execCommand2(['node', `${rootDir}/packages/tools/build-release-stats.js`, '--types=changelog']);
|
||||
await execCommand2(['node', `${rootDir}/packages/tools/build-release-stats.js`, '--types=stats', '--update-interval=30']);
|
||||
await execCommand2(['node', `${rootDir}/packages/tools/update-readme-sponsors.js`]);
|
||||
await execCommand2(['node', `${rootDir}/packages/tools/build-welcome.js`]);
|
||||
await execCommand(['node', `${rootDir}/packages/tools/update-readme-download.js`]);
|
||||
await execCommand(['node', `${rootDir}/packages/tools/build-release-stats.js`, '--types=changelog']);
|
||||
await execCommand(['node', `${rootDir}/packages/tools/build-release-stats.js`, '--types=stats', '--update-interval=30']);
|
||||
await execCommand(['node', `${rootDir}/packages/tools/update-readme-sponsors.js`]);
|
||||
await execCommand(['node', `${rootDir}/packages/tools/build-welcome.js`]);
|
||||
chdir(rootDir);
|
||||
await execCommand2(['yarn', 'run', 'buildApiDoc']);
|
||||
await execCommand(['yarn', 'run', 'buildApiDoc']);
|
||||
await updateDownloadPage();
|
||||
|
||||
if (doGitOperations) {
|
||||
await execCommand2(['git', 'add', '-A']);
|
||||
await execCommand2(['git', 'commit', '-m', 'Update Markdown doc']);
|
||||
await execCommand2(['git', 'pull', '--rebase']);
|
||||
await execCommand2(['git', 'push']);
|
||||
await execCommand(['git', 'add', '-A']);
|
||||
await execCommand(['git', 'commit', '-m', 'Update Markdown doc']);
|
||||
await execCommand(['git', 'pull', '--rebase']);
|
||||
await execCommand(['git', 'push']);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
dist/
|
||||
node_modules/
|
|
@ -0,0 +1,3 @@
|
|||
# Utility package
|
||||
|
||||
Those are generic utility functions that can be imported from any other packages. This package however shouldn't have any dependency to any other Joplin package, so that it can be imported without having to import "lib", "renderer" and so on. This is particulary important for Docker images, so that they can be trimmed down to only what's needed.
|
|
@ -0,0 +1,16 @@
|
|||
const quotePath = (path: string) => {
|
||||
if (!path) return '';
|
||||
if (path.indexOf('"') < 0 && path.indexOf(' ') < 0) return path;
|
||||
path = path.replace(/"/, '\\"');
|
||||
return `"${path}"`;
|
||||
};
|
||||
|
||||
export default (commandName: string, args: string[] = []) => {
|
||||
const output = [quotePath(commandName)];
|
||||
|
||||
for (const arg of args) {
|
||||
output.push(quotePath(arg));
|
||||
}
|
||||
|
||||
return output.join(' ');
|
||||
};
|
|
@ -0,0 +1,44 @@
|
|||
import * as execa from 'execa';
|
||||
import commandToString from './commandToString';
|
||||
import splitCommandString from './splitCommandString';
|
||||
import { stdout } from 'process';
|
||||
|
||||
interface ExecCommandOptions {
|
||||
showInput?: boolean;
|
||||
showStdout?: boolean;
|
||||
showStderr?: boolean;
|
||||
quiet?: boolean;
|
||||
}
|
||||
|
||||
export default async (command: string | string[], options: ExecCommandOptions | null = null): Promise<string> => {
|
||||
options = {
|
||||
showInput: true,
|
||||
showStdout: true,
|
||||
showStderr: true,
|
||||
quiet: false,
|
||||
...options,
|
||||
};
|
||||
|
||||
if (options.quiet) {
|
||||
options.showInput = false;
|
||||
options.showStdout = false;
|
||||
options.showStderr = false;
|
||||
}
|
||||
|
||||
if (options.showInput) {
|
||||
if (typeof command === 'string') {
|
||||
stdout.write(`> ${command}\n`);
|
||||
} else {
|
||||
stdout.write(`> ${commandToString(command[0], command.slice(1))}\n`);
|
||||
}
|
||||
}
|
||||
|
||||
const args: string[] = typeof command === 'string' ? splitCommandString(command) : command as string[];
|
||||
const executableName = args[0];
|
||||
args.splice(0, 1);
|
||||
const promise = execa(executableName, args);
|
||||
if (options.showStdout && promise.stdout) promise.stdout.pipe(process.stdout);
|
||||
if (options.showStderr && promise.stdout) promise.stdout.pipe(process.stderr);
|
||||
const result = await promise;
|
||||
return result.stdout.trim();
|
||||
};
|
|
@ -0,0 +1,9 @@
|
|||
import execCommand from './execCommand';
|
||||
import commandToString from './commandToString';
|
||||
import splitCommandString from './splitCommandString';
|
||||
|
||||
export {
|
||||
execCommand,
|
||||
commandToString,
|
||||
splitCommandString,
|
||||
};
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"name": "@joplin/utils",
|
||||
"version": "2.10.0",
|
||||
"description": "Utilities for Joplin",
|
||||
"repository": "https://github.com/laurent22/joplin/tree/dev/packages/utils",
|
||||
"main": "dist/index.js",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"scripts": {
|
||||
"tsc": "tsc --project tsconfig.json",
|
||||
"watch": "tsc --watch --preserveWatchOutput --project tsconfig.json",
|
||||
"test": "jest --verbose=false",
|
||||
"test-ci": "yarn test"
|
||||
},
|
||||
"author": "",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"execa": "5.1.1"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
export default (command: string, options: any = null) => {
|
||||
options = options || {};
|
||||
if (!('handleEscape' in options)) {
|
||||
options.handleEscape = true;
|
||||
}
|
||||
|
||||
const args = [];
|
||||
let state = 'start';
|
||||
let current = '';
|
||||
let quote = '"';
|
||||
let escapeNext = false;
|
||||
for (let i = 0; i < command.length; i++) {
|
||||
const c = command[i];
|
||||
|
||||
if (state === 'quotes') {
|
||||
if (c !== quote) {
|
||||
current += c;
|
||||
} else {
|
||||
args.push(current);
|
||||
current = '';
|
||||
state = 'start';
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (escapeNext) {
|
||||
current += c;
|
||||
escapeNext = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c === '\\' && options.handleEscape) {
|
||||
escapeNext = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c === '"' || c === '\'') {
|
||||
state = 'quotes';
|
||||
quote = c;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (state === 'arg') {
|
||||
if (c === ' ' || c === '\t') {
|
||||
args.push(current);
|
||||
current = '';
|
||||
state = 'start';
|
||||
} else {
|
||||
current += c;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c !== ' ' && c !== '\t') {
|
||||
state = 'arg';
|
||||
current += c;
|
||||
}
|
||||
}
|
||||
|
||||
if (state === 'quotes') {
|
||||
throw new Error(`Unclosed quote in command line: ${command}`);
|
||||
}
|
||||
|
||||
if (current !== '') {
|
||||
args.push(current);
|
||||
}
|
||||
|
||||
if (args.length <= 0) {
|
||||
throw new Error('Empty command line');
|
||||
}
|
||||
|
||||
return args;
|
||||
};
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"strict": true,
|
||||
"strictNullChecks": true
|
||||
},
|
||||
"rootDir": ".",
|
||||
"include": [
|
||||
"**/*.ts",
|
||||
"**/*.tsx",
|
||||
],
|
||||
"exclude": [
|
||||
"**/node_modules",
|
||||
],
|
||||
}
|
44
yarn.lock
44
yarn.lock
|
@ -4880,6 +4880,7 @@ __metadata:
|
|||
"@joplin/renderer": ^2.10.2
|
||||
"@joplin/turndown": ^4.0.65
|
||||
"@joplin/turndown-plugin-gfm": ^1.0.47
|
||||
"@joplin/utils": ~2.10
|
||||
"@types/fs-extra": 9.0.13
|
||||
"@types/jest": 29.2.6
|
||||
"@types/js-yaml": 4.0.5
|
||||
|
@ -4985,6 +4986,7 @@ __metadata:
|
|||
dependencies:
|
||||
"@joplin/lib": ^2.10.2
|
||||
"@joplin/tools": ^2.10.2
|
||||
"@joplin/utils": ~2.10
|
||||
"@types/fs-extra": 9.0.13
|
||||
"@types/jest": 29.2.6
|
||||
"@types/node": 18.11.18
|
||||
|
@ -5138,6 +5140,7 @@ __metadata:
|
|||
"@joplin/fork-htmlparser2": ^4.1.43
|
||||
"@joplin/lib": ^2.10.2
|
||||
"@joplin/renderer": ^2.10.2
|
||||
"@joplin/utils": ~2.10
|
||||
"@rmp135/sql-ts": 1.16.0
|
||||
"@types/fs-extra": 9.0.13
|
||||
"@types/jest": 29.2.6
|
||||
|
@ -5201,6 +5204,14 @@ __metadata:
|
|||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@joplin/utils@workspace:packages/utils, @joplin/utils@~2.10":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@joplin/utils@workspace:packages/utils"
|
||||
dependencies:
|
||||
execa: 5.1.1
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@jridgewell/gen-mapping@npm:^0.1.0":
|
||||
version: 0.1.1
|
||||
resolution: "@jridgewell/gen-mapping@npm:0.1.1"
|
||||
|
@ -15681,22 +15692,7 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"execa@npm:^1.0.0":
|
||||
version: 1.0.0
|
||||
resolution: "execa@npm:1.0.0"
|
||||
dependencies:
|
||||
cross-spawn: ^6.0.0
|
||||
get-stream: ^4.0.0
|
||||
is-stream: ^1.1.0
|
||||
npm-run-path: ^2.0.0
|
||||
p-finally: ^1.0.0
|
||||
signal-exit: ^3.0.0
|
||||
strip-eof: ^1.0.0
|
||||
checksum: ddf1342c1c7d02dd93b41364cd847640f6163350d9439071abf70bf4ceb1b9b2b2e37f54babb1d8dc1df8e0d8def32d0e81e74a2e62c3e1d70c303eb4c306bc4
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"execa@npm:^5.0.0, execa@npm:^5.1.1":
|
||||
"execa@npm:5.1.1, execa@npm:^5.0.0, execa@npm:^5.1.1":
|
||||
version: 5.1.1
|
||||
resolution: "execa@npm:5.1.1"
|
||||
dependencies:
|
||||
|
@ -15713,6 +15709,21 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"execa@npm:^1.0.0":
|
||||
version: 1.0.0
|
||||
resolution: "execa@npm:1.0.0"
|
||||
dependencies:
|
||||
cross-spawn: ^6.0.0
|
||||
get-stream: ^4.0.0
|
||||
is-stream: ^1.1.0
|
||||
npm-run-path: ^2.0.0
|
||||
p-finally: ^1.0.0
|
||||
signal-exit: ^3.0.0
|
||||
strip-eof: ^1.0.0
|
||||
checksum: ddf1342c1c7d02dd93b41364cd847640f6163350d9439071abf70bf4ceb1b9b2b2e37f54babb1d8dc1df8e0d8def32d0e81e74a2e62c3e1d70c303eb4c306bc4
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"execa@npm:^7.0.0":
|
||||
version: 7.1.1
|
||||
resolution: "execa@npm:7.1.1"
|
||||
|
@ -20444,6 +20455,7 @@ __metadata:
|
|||
"@joplin/lib": ~2.10
|
||||
"@joplin/renderer": ~2.10
|
||||
"@joplin/tools": ~2.10
|
||||
"@joplin/utils": ~2.10
|
||||
"@types/fs-extra": 9.0.13
|
||||
"@types/jest": 29.2.6
|
||||
"@types/node": 18.11.18
|
||||
|
|
Loading…
Reference in New Issue