ic-mops 0.29.0 → 0.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli.ts +3 -2
- package/commands/add.ts +12 -3
- package/commands/import-identity.ts +22 -14
- package/commands/install.ts +2 -2
- package/commands/update.ts +30 -2
- package/dist/cli.js +3 -2
- package/dist/commands/add.js +11 -3
- package/dist/commands/bench/bench-canister.mo +4 -0
- package/dist/commands/bench.d.ts +5 -4
- package/dist/commands/bench.js +83 -42
- package/dist/commands/import-identity.d.ts +5 -1
- package/dist/commands/import-identity.js +17 -14
- package/dist/commands/install.js +2 -2
- package/dist/commands/update.js +27 -2
- package/dist/declarations/bench/bench.did +1 -0
- package/dist/declarations/bench/bench.did.d.ts +1 -0
- package/dist/declarations/bench/bench.did.js +1 -0
- package/dist/integrity.d.ts +4 -0
- package/dist/integrity.js +92 -0
- package/dist/mops.d.ts +4 -2
- package/dist/mops.js +19 -5
- package/dist/package.json +1 -1
- package/dist/vessel.js +10 -10
- package/mops.ts +20 -6
- package/package.json +1 -1
- package/vessel.ts +10 -10
package/cli.ts
CHANGED
|
@@ -135,8 +135,9 @@ program
|
|
|
135
135
|
program
|
|
136
136
|
.command('import-identity <data>')
|
|
137
137
|
.description('Import .pem file data to use as identity')
|
|
138
|
-
.
|
|
139
|
-
|
|
138
|
+
.addOption(new Option('--no-encrypt', 'Do not ask for a password to encrypt identity'))
|
|
139
|
+
.action(async (data, options) => {
|
|
140
|
+
await importPem(data, options);
|
|
140
141
|
await whoami();
|
|
141
142
|
});
|
|
142
143
|
|
package/commands/add.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
3
|
import logUpdate from 'log-update';
|
|
4
|
-
import {checkConfigFile, getHighestVersion, parseGithubURL, readConfig, writeConfig} from '../mops.js';
|
|
4
|
+
import {checkConfigFile, getGithubCommit, getHighestVersion, parseGithubURL, readConfig, writeConfig} from '../mops.js';
|
|
5
5
|
import {installFromGithub} from '../vessel.js';
|
|
6
6
|
import {install} from './install.js';
|
|
7
7
|
import {notifyInstalls} from '../notify-installs.js';
|
|
@@ -36,11 +36,20 @@ export async function add(name: string, {verbose = false, dev = false} = {}) {
|
|
|
36
36
|
}
|
|
37
37
|
// github package
|
|
38
38
|
else if (name.startsWith('https://github.com') || name.split('/').length > 1) {
|
|
39
|
-
|
|
39
|
+
let {org, gitName, branch, commitHash} = parseGithubURL(name);
|
|
40
|
+
|
|
41
|
+
// fetch latest commit hash of branch if not specified
|
|
42
|
+
if (!commitHash) {
|
|
43
|
+
let commit = await getGithubCommit(`${org}/${gitName}`, branch);
|
|
44
|
+
if (!commit.sha) {
|
|
45
|
+
throw Error(`Could not find commit hash for ${name}`);
|
|
46
|
+
}
|
|
47
|
+
commitHash = commit.sha;
|
|
48
|
+
}
|
|
40
49
|
|
|
41
50
|
pkgDetails = {
|
|
42
51
|
name: parseGithubURL(name).gitName,
|
|
43
|
-
repo: `https://github.com/${org}/${gitName}#${branch}`,
|
|
52
|
+
repo: `https://github.com/${org}/${gitName}#${branch}@${commitHash}`,
|
|
44
53
|
version: '',
|
|
45
54
|
};
|
|
46
55
|
}
|
|
@@ -6,28 +6,36 @@ import {deleteSync} from 'del';
|
|
|
6
6
|
import {globalConfigDir} from '../mops.js';
|
|
7
7
|
import {encrypt} from '../pem.js';
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
type ImportIdentityOptions = {
|
|
10
|
+
encrypt: boolean;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export async function importPem(data: string, options: ImportIdentityOptions = {encrypt: true}) {
|
|
10
14
|
try {
|
|
11
15
|
if (!fs.existsSync(globalConfigDir)) {
|
|
12
16
|
fs.mkdirSync(globalConfigDir);
|
|
13
17
|
}
|
|
14
18
|
|
|
15
|
-
let
|
|
16
|
-
type: 'password',
|
|
17
|
-
name: 'password',
|
|
18
|
-
message: 'Enter password to encrypt identity.pem',
|
|
19
|
-
});
|
|
20
|
-
let password = res.password;
|
|
19
|
+
let password = '';
|
|
21
20
|
|
|
22
|
-
if (
|
|
21
|
+
if (options.encrypt) {
|
|
23
22
|
let res = await prompts({
|
|
24
|
-
type: '
|
|
25
|
-
name: '
|
|
26
|
-
message: '
|
|
23
|
+
type: 'invisible',
|
|
24
|
+
name: 'password',
|
|
25
|
+
message: 'Enter password to encrypt identity.pem',
|
|
27
26
|
});
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
password = res.password;
|
|
28
|
+
|
|
29
|
+
if (!password) {
|
|
30
|
+
let res = await prompts({
|
|
31
|
+
type: 'confirm',
|
|
32
|
+
name: 'ok',
|
|
33
|
+
message: 'Are you sure you don\'t want to protect your identity.pem with a password?',
|
|
34
|
+
});
|
|
35
|
+
if (!res.ok) {
|
|
36
|
+
console.log('aborted');
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
31
39
|
}
|
|
32
40
|
}
|
|
33
41
|
|
package/commands/install.ts
CHANGED
|
@@ -36,13 +36,13 @@ export async function install(pkg: string, version = '', {verbose = false, silen
|
|
|
36
36
|
|
|
37
37
|
// already installed
|
|
38
38
|
if (fs.existsSync(dir)) {
|
|
39
|
-
silent || logUpdate(`${dep ? 'Dependency' : 'Installing'} ${pkg}@${version} (
|
|
39
|
+
silent || logUpdate(`${dep ? 'Dependency' : 'Installing'} ${pkg}@${version} (local cache)`);
|
|
40
40
|
alreadyInstalled = true;
|
|
41
41
|
}
|
|
42
42
|
// copy from cache
|
|
43
43
|
else if (isCached(`${pkg}@${version}`)) {
|
|
44
44
|
await copyCache(`${pkg}@${version}`, dir);
|
|
45
|
-
silent || logUpdate(`${dep ? 'Dependency' : 'Installing'} ${pkg}@${version} (cache)`);
|
|
45
|
+
silent || logUpdate(`${dep ? 'Dependency' : 'Installing'} ${pkg}@${version} (global cache)`);
|
|
46
46
|
}
|
|
47
47
|
// download
|
|
48
48
|
else {
|
package/commands/update.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
-
import {checkConfigFile, readConfig} from '../mops.js';
|
|
2
|
+
import {checkConfigFile, getGithubCommit, parseGithubURL, readConfig} from '../mops.js';
|
|
3
3
|
import {add} from './add.js';
|
|
4
4
|
import {getAvailableUpdates} from './available-updates.js';
|
|
5
5
|
|
|
@@ -9,10 +9,38 @@ export async function update(pkg?: string) {
|
|
|
9
9
|
}
|
|
10
10
|
let config = readConfig();
|
|
11
11
|
|
|
12
|
+
if (pkg && !config.dependencies?.[pkg] && !config['dev-dependencies']?.[pkg]) {
|
|
13
|
+
console.log(chalk.red(`Package "${pkg}" is not installed!`));
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// update github packages
|
|
18
|
+
let deps = Object.values(config.dependencies || {});
|
|
19
|
+
let devDeps = Object.values(config['dev-dependencies'] || {});
|
|
20
|
+
let githubDeps = [...deps, ...devDeps].filter((dep) => dep.repo);
|
|
21
|
+
if (pkg) {
|
|
22
|
+
githubDeps = githubDeps.filter((dep) => dep.name === pkg);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
for (let dep of githubDeps) {
|
|
26
|
+
let {org, gitName, branch, commitHash} = parseGithubURL(dep.repo || '');
|
|
27
|
+
let dev = !!config['dev-dependencies']?.[dep.name];
|
|
28
|
+
let commit = await getGithubCommit(`${org}/${gitName}`, branch);
|
|
29
|
+
if (commit.sha !== commitHash) {
|
|
30
|
+
await add(`https://github.com/${org}/${gitName}#${branch}@${commit.sha}`, {dev});
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// update mops packages
|
|
12
35
|
let available = await getAvailableUpdates(config, pkg);
|
|
13
36
|
|
|
14
37
|
if (available.length === 0) {
|
|
15
|
-
|
|
38
|
+
if (pkg) {
|
|
39
|
+
console.log(chalk.green(`Package "${pkg}" is up to date!`));
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
console.log(chalk.green('All dependencies are up to date!'));
|
|
43
|
+
}
|
|
16
44
|
}
|
|
17
45
|
else {
|
|
18
46
|
for (let dep of available) {
|
package/dist/cli.js
CHANGED
|
@@ -121,8 +121,9 @@ program
|
|
|
121
121
|
program
|
|
122
122
|
.command('import-identity <data>')
|
|
123
123
|
.description('Import .pem file data to use as identity')
|
|
124
|
-
.
|
|
125
|
-
|
|
124
|
+
.addOption(new Option('--no-encrypt', 'Do not ask for a password to encrypt identity'))
|
|
125
|
+
.action(async (data, options) => {
|
|
126
|
+
await importPem(data, options);
|
|
126
127
|
await whoami();
|
|
127
128
|
});
|
|
128
129
|
// sources
|
package/dist/commands/add.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
3
|
import logUpdate from 'log-update';
|
|
4
|
-
import { checkConfigFile, getHighestVersion, parseGithubURL, readConfig, writeConfig } from '../mops.js';
|
|
4
|
+
import { checkConfigFile, getGithubCommit, getHighestVersion, parseGithubURL, readConfig, writeConfig } from '../mops.js';
|
|
5
5
|
import { installFromGithub } from '../vessel.js';
|
|
6
6
|
import { install } from './install.js';
|
|
7
7
|
import { notifyInstalls } from '../notify-installs.js';
|
|
@@ -32,10 +32,18 @@ export async function add(name, { verbose = false, dev = false } = {}) {
|
|
|
32
32
|
}
|
|
33
33
|
// github package
|
|
34
34
|
else if (name.startsWith('https://github.com') || name.split('/').length > 1) {
|
|
35
|
-
|
|
35
|
+
let { org, gitName, branch, commitHash } = parseGithubURL(name);
|
|
36
|
+
// fetch latest commit hash of branch if not specified
|
|
37
|
+
if (!commitHash) {
|
|
38
|
+
let commit = await getGithubCommit(`${org}/${gitName}`, branch);
|
|
39
|
+
if (!commit.sha) {
|
|
40
|
+
throw Error(`Could not find commit hash for ${name}`);
|
|
41
|
+
}
|
|
42
|
+
commitHash = commit.sha;
|
|
43
|
+
}
|
|
36
44
|
pkgDetails = {
|
|
37
45
|
name: parseGithubURL(name).gitName,
|
|
38
|
-
repo: `https://github.com/${org}/${gitName}#${branch}`,
|
|
46
|
+
repo: `https://github.com/${org}/${gitName}#${branch}@${commitHash}`,
|
|
39
47
|
version: '',
|
|
40
48
|
};
|
|
41
49
|
}
|
|
@@ -82,4 +82,8 @@ actor class() {
|
|
|
82
82
|
public func runCellUpdate(rowIndex : Nat, colIndex : Nat) : async Bench.BenchResult {
|
|
83
83
|
await _runCellAwait(rowIndex, colIndex);
|
|
84
84
|
};
|
|
85
|
+
|
|
86
|
+
public func runCellUpdateAwait(rowIndex : Nat, colIndex : Nat) : async Bench.BenchResult {
|
|
87
|
+
_runCell(rowIndex, colIndex);
|
|
88
|
+
};
|
|
85
89
|
};
|
package/dist/commands/bench.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
type BenchOptions = {
|
|
2
|
-
verbose?: boolean;
|
|
3
|
-
save?: boolean;
|
|
4
|
-
compare?: boolean;
|
|
5
2
|
dfx?: string;
|
|
6
3
|
moc?: string;
|
|
7
|
-
gc?: 'copying' | 'compacting' | 'generational' | 'incremental'
|
|
4
|
+
gc?: 'copying' | 'compacting' | 'generational' | 'incremental';
|
|
5
|
+
forceGc?: boolean;
|
|
6
|
+
save?: boolean;
|
|
7
|
+
compare?: boolean;
|
|
8
|
+
verbose?: boolean;
|
|
8
9
|
};
|
|
9
10
|
export declare function bench(filter?: string, options?: BenchOptions): Promise<boolean>;
|
|
10
11
|
export {};
|
package/dist/commands/bench.js
CHANGED
|
@@ -12,6 +12,8 @@ import { createActor } from '../declarations/bench/index.js';
|
|
|
12
12
|
import { absToRel } from './test/utils.js';
|
|
13
13
|
import { getMocVersion } from '../helpers/get-moc-version.js';
|
|
14
14
|
import { getDfxVersion } from '../helpers/get-dfx-version.js';
|
|
15
|
+
import { getMocPath } from '../helpers/get-moc-path.js';
|
|
16
|
+
import { sources } from './sources.js';
|
|
15
17
|
let ignore = [
|
|
16
18
|
'**/node_modules/**',
|
|
17
19
|
'**/.mops/**',
|
|
@@ -23,6 +25,16 @@ let globConfig = {
|
|
|
23
25
|
ignore: ignore,
|
|
24
26
|
};
|
|
25
27
|
export async function bench(filter = '', options = {}) {
|
|
28
|
+
let defaultOptions = {
|
|
29
|
+
moc: getMocVersion(),
|
|
30
|
+
dfx: getDfxVersion(),
|
|
31
|
+
gc: 'incremental',
|
|
32
|
+
forceGc: true,
|
|
33
|
+
save: false,
|
|
34
|
+
compare: false,
|
|
35
|
+
verbose: false,
|
|
36
|
+
};
|
|
37
|
+
options = { ...defaultOptions, ...options };
|
|
26
38
|
let rootDir = getRootDir();
|
|
27
39
|
let globStr = '**/bench?(mark)/**/*.bench.mo';
|
|
28
40
|
if (filter) {
|
|
@@ -35,7 +47,7 @@ export async function bench(filter = '', options = {}) {
|
|
|
35
47
|
return false;
|
|
36
48
|
}
|
|
37
49
|
console.log('No *.bench.mo files found');
|
|
38
|
-
console.log('Put your benchmark
|
|
50
|
+
console.log('Put your benchmark code in \'bench\' directory in *.bench.mo files');
|
|
39
51
|
return false;
|
|
40
52
|
}
|
|
41
53
|
files.sort();
|
|
@@ -48,17 +60,16 @@ export async function bench(filter = '', options = {}) {
|
|
|
48
60
|
}
|
|
49
61
|
console.log('');
|
|
50
62
|
console.log('='.repeat(50));
|
|
63
|
+
console.log('');
|
|
51
64
|
console.log('Starting dfx replica...');
|
|
52
65
|
startDfx(options.verbose);
|
|
53
|
-
let resultsByName = new Map();
|
|
54
66
|
// await parallel(os.cpus().length, files, async (file: string) => {
|
|
55
67
|
await parallel(1, files, async (file) => {
|
|
56
68
|
console.log('\n' + '—'.repeat(50));
|
|
57
69
|
console.log(`\nRunning ${chalk.gray(absToRel(file))}...`);
|
|
58
70
|
console.log('');
|
|
59
71
|
try {
|
|
60
|
-
|
|
61
|
-
resultsByName.set(schema.name || absToRel(file), results);
|
|
72
|
+
await runBenchFile(file, options);
|
|
62
73
|
}
|
|
63
74
|
catch (err) {
|
|
64
75
|
console.error('Unexpected error. Stopping dfx replica...');
|
|
@@ -66,42 +77,36 @@ export async function bench(filter = '', options = {}) {
|
|
|
66
77
|
throw err;
|
|
67
78
|
}
|
|
68
79
|
});
|
|
69
|
-
if (options.save) {
|
|
70
|
-
console.log('Saving results to mops.bench.json...');
|
|
71
|
-
let json = {
|
|
72
|
-
version: 1,
|
|
73
|
-
moc: options.moc || getMocVersion(),
|
|
74
|
-
dfx: options.dfx || getDfxVersion(),
|
|
75
|
-
gc: options.gc || 'incremental',
|
|
76
|
-
results: {},
|
|
77
|
-
};
|
|
78
|
-
resultsByName.forEach((results, name) => {
|
|
79
|
-
json.results[name] = Array.from(results.entries());
|
|
80
|
-
});
|
|
81
|
-
fs.writeFileSync(path.join(rootDir, 'mops.bench.json'), JSON.stringify(json, (_, val) => {
|
|
82
|
-
if (typeof val === 'bigint') {
|
|
83
|
-
return Number(val);
|
|
84
|
-
}
|
|
85
|
-
else {
|
|
86
|
-
return val;
|
|
87
|
-
}
|
|
88
|
-
}, 2));
|
|
89
|
-
}
|
|
90
80
|
console.log('Stopping dfx replica...');
|
|
91
81
|
stopDfx(options.verbose);
|
|
92
82
|
fs.rmSync(benchDir, { recursive: true, force: true });
|
|
93
83
|
return true;
|
|
94
84
|
}
|
|
95
|
-
function
|
|
85
|
+
function getMocArgs(options) {
|
|
86
|
+
let args = '';
|
|
87
|
+
if (options.forceGc) {
|
|
88
|
+
args += ' --force-gc';
|
|
89
|
+
}
|
|
90
|
+
if (options.gc) {
|
|
91
|
+
args += ` --${options.gc}-gc`;
|
|
92
|
+
}
|
|
93
|
+
return args;
|
|
94
|
+
}
|
|
95
|
+
function dfxJson(canisterName, options = {}) {
|
|
96
|
+
options || console.log(options);
|
|
97
|
+
let canisters = {};
|
|
98
|
+
if (canisterName) {
|
|
99
|
+
canisters[canisterName] = {
|
|
100
|
+
// type: 'motoko',
|
|
101
|
+
type: 'custom',
|
|
102
|
+
wasm: 'canister.wasm',
|
|
103
|
+
candid: 'canister.did',
|
|
104
|
+
// args: getMocArgs(options),
|
|
105
|
+
};
|
|
106
|
+
}
|
|
96
107
|
return {
|
|
97
108
|
version: 1,
|
|
98
|
-
canisters
|
|
99
|
-
[canisterName]: {
|
|
100
|
-
type: 'motoko',
|
|
101
|
-
main: 'canister.mo',
|
|
102
|
-
args: '--force-gc --incremental-gc',
|
|
103
|
-
}
|
|
104
|
-
},
|
|
109
|
+
canisters,
|
|
105
110
|
defaults: {
|
|
106
111
|
build: {
|
|
107
112
|
packtool: 'mops sources',
|
|
@@ -119,21 +124,34 @@ function startDfx(verbose = false) {
|
|
|
119
124
|
stopDfx(verbose);
|
|
120
125
|
let dir = path.join(getRootDir(), '.mops/.bench');
|
|
121
126
|
fs.writeFileSync(path.join(dir, 'dfx.json'), JSON.stringify(dfxJson(''), null, 2));
|
|
122
|
-
execSync('dfx start --background --clean', { cwd: dir, stdio: ['inherit', verbose ? 'inherit' : 'ignore', 'inherit'] });
|
|
127
|
+
execSync('dfx start --background --clean' + (verbose ? '' : ' -qqqq'), { cwd: dir, stdio: ['inherit', verbose ? 'inherit' : 'ignore', 'inherit'] });
|
|
123
128
|
}
|
|
124
129
|
function stopDfx(verbose = false) {
|
|
125
130
|
let dir = path.join(getRootDir(), '.mops/.bench');
|
|
126
|
-
execSync('dfx stop', { cwd: dir, stdio: ['pipe', verbose ? 'inherit' : 'ignore', 'pipe'] });
|
|
131
|
+
execSync('dfx stop' + (verbose ? '' : ' -qqqq'), { cwd: dir, stdio: ['pipe', verbose ? 'inherit' : 'ignore', 'pipe'] });
|
|
127
132
|
}
|
|
128
|
-
async function
|
|
133
|
+
async function buildBenchFile(file, options = {}) {
|
|
129
134
|
let rootDir = getRootDir();
|
|
130
135
|
let tempDir = path.join(rootDir, '.mops/.bench/', path.parse(file).name);
|
|
131
136
|
fs.mkdirSync(tempDir, { recursive: true });
|
|
132
|
-
let canisterName = Date.now().toString(36);
|
|
137
|
+
// let canisterName = Date.now().toString(36);
|
|
138
|
+
let canisterName = path.parse(file).name;
|
|
133
139
|
// prepare temp files
|
|
134
|
-
fs.writeFileSync(path.join(tempDir, 'dfx.json'), JSON.stringify(dfxJson(canisterName), null, 2));
|
|
140
|
+
fs.writeFileSync(path.join(tempDir, 'dfx.json'), JSON.stringify(dfxJson(canisterName, options), null, 2));
|
|
135
141
|
fs.cpSync(new URL('./bench/bench-canister.mo', import.meta.url), path.join(tempDir, 'canister.mo'));
|
|
136
142
|
fs.cpSync(file, path.join(tempDir, 'user-bench.mo'));
|
|
143
|
+
// build canister
|
|
144
|
+
let mocPath = getMocPath();
|
|
145
|
+
let mocArgs = getMocArgs(options);
|
|
146
|
+
console.log(tempDir);
|
|
147
|
+
console.log(`${mocPath} -c --idl canister.mo ${mocArgs} ${(await sources({ cwd: tempDir })).join(' ')}`);
|
|
148
|
+
execSync(`${mocPath} -c --idl canister.mo ${mocArgs} ${(await sources({ cwd: tempDir })).join(' ')}`, { cwd: tempDir, stdio: options.verbose ? 'pipe' : ['pipe', 'ignore', 'pipe'] });
|
|
149
|
+
}
|
|
150
|
+
async function runBenchFile(file, options = {}) {
|
|
151
|
+
let rootDir = getRootDir();
|
|
152
|
+
await buildBenchFile(file, options);
|
|
153
|
+
let tempDir = path.join(rootDir, '.mops/.bench/', path.parse(file).name);
|
|
154
|
+
let canisterName = path.parse(file).name;
|
|
137
155
|
// deploy canister
|
|
138
156
|
execSync(`dfx deploy ${canisterName} --mode reinstall --yes --identity anonymous`, { cwd: tempDir, stdio: options.verbose ? 'pipe' : ['pipe', 'ignore', 'pipe'] });
|
|
139
157
|
let canisterId = execSync(`dfx canister id ${canisterName}`, { cwd: tempDir }).toString().trim();
|
|
@@ -145,13 +163,14 @@ async function runBenchFile(file, options = {}) {
|
|
|
145
163
|
let schema = await actor.init();
|
|
146
164
|
// load previous results
|
|
147
165
|
let prevResults;
|
|
166
|
+
let resultsJsonFile = path.join(rootDir, '.bench', `${path.parse(file).name}.json`);
|
|
148
167
|
if (options.compare) {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
prevResults = new Map(prevResultsJson.results
|
|
168
|
+
if (fs.existsSync(resultsJsonFile)) {
|
|
169
|
+
let prevResultsJson = JSON.parse(fs.readFileSync(resultsJsonFile).toString());
|
|
170
|
+
prevResults = new Map(prevResultsJson.results);
|
|
152
171
|
}
|
|
153
172
|
else {
|
|
154
|
-
console.log(chalk.yellow(`No previous results found
|
|
173
|
+
console.log(chalk.yellow(`No previous results found "${resultsJsonFile}"`));
|
|
155
174
|
}
|
|
156
175
|
}
|
|
157
176
|
let results = new Map();
|
|
@@ -205,10 +224,32 @@ async function runBenchFile(file, options = {}) {
|
|
|
205
224
|
for (let [colIndex, col] of schema.cols.entries()) {
|
|
206
225
|
// let res = await actor.runCellQuery(BigInt(rowIndex), BigInt(colIndex));
|
|
207
226
|
let res = await actor.runCellUpdate(BigInt(rowIndex), BigInt(colIndex));
|
|
227
|
+
// let res = await actor.runCellUpdateAwait(BigInt(rowIndex), BigInt(colIndex));
|
|
208
228
|
results.set(`${row}:${col}`, res);
|
|
209
229
|
printResults();
|
|
210
230
|
}
|
|
211
231
|
}
|
|
212
232
|
logUpdate.done();
|
|
233
|
+
// save results
|
|
234
|
+
if (options.save) {
|
|
235
|
+
console.log(`Saving results to ${chalk.gray(absToRel(resultsJsonFile))}`);
|
|
236
|
+
let json = {
|
|
237
|
+
version: 1,
|
|
238
|
+
moc: options.moc,
|
|
239
|
+
dfx: options.dfx,
|
|
240
|
+
gc: options.gc,
|
|
241
|
+
forceGc: options.forceGc,
|
|
242
|
+
results: Array.from(results.entries()),
|
|
243
|
+
};
|
|
244
|
+
fs.mkdirSync(path.dirname(resultsJsonFile), { recursive: true });
|
|
245
|
+
fs.writeFileSync(resultsJsonFile, JSON.stringify(json, (_, val) => {
|
|
246
|
+
if (typeof val === 'bigint') {
|
|
247
|
+
return Number(val);
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
return val;
|
|
251
|
+
}
|
|
252
|
+
}, 2));
|
|
253
|
+
}
|
|
213
254
|
return { schema, results };
|
|
214
255
|
}
|
|
@@ -5,26 +5,29 @@ import prompts from 'prompts';
|
|
|
5
5
|
import { deleteSync } from 'del';
|
|
6
6
|
import { globalConfigDir } from '../mops.js';
|
|
7
7
|
import { encrypt } from '../pem.js';
|
|
8
|
-
export async function importPem(data) {
|
|
8
|
+
export async function importPem(data, options = { encrypt: true }) {
|
|
9
9
|
try {
|
|
10
10
|
if (!fs.existsSync(globalConfigDir)) {
|
|
11
11
|
fs.mkdirSync(globalConfigDir);
|
|
12
12
|
}
|
|
13
|
-
let
|
|
14
|
-
|
|
15
|
-
name: 'password',
|
|
16
|
-
message: 'Enter password to encrypt identity.pem',
|
|
17
|
-
});
|
|
18
|
-
let password = res.password;
|
|
19
|
-
if (!password) {
|
|
13
|
+
let password = '';
|
|
14
|
+
if (options.encrypt) {
|
|
20
15
|
let res = await prompts({
|
|
21
|
-
type: '
|
|
22
|
-
name: '
|
|
23
|
-
message: '
|
|
16
|
+
type: 'invisible',
|
|
17
|
+
name: 'password',
|
|
18
|
+
message: 'Enter password to encrypt identity.pem',
|
|
24
19
|
});
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
20
|
+
password = res.password;
|
|
21
|
+
if (!password) {
|
|
22
|
+
let res = await prompts({
|
|
23
|
+
type: 'confirm',
|
|
24
|
+
name: 'ok',
|
|
25
|
+
message: 'Are you sure you don\'t want to protect your identity.pem with a password?',
|
|
26
|
+
});
|
|
27
|
+
if (!res.ok) {
|
|
28
|
+
console.log('aborted');
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
28
31
|
}
|
|
29
32
|
}
|
|
30
33
|
let identityPem = path.resolve(globalConfigDir, 'identity.pem');
|
package/dist/commands/install.js
CHANGED
|
@@ -31,13 +31,13 @@ export async function install(pkg, version = '', { verbose = false, silent = fal
|
|
|
31
31
|
let alreadyInstalled = false;
|
|
32
32
|
// already installed
|
|
33
33
|
if (fs.existsSync(dir)) {
|
|
34
|
-
silent || logUpdate(`${dep ? 'Dependency' : 'Installing'} ${pkg}@${version} (
|
|
34
|
+
silent || logUpdate(`${dep ? 'Dependency' : 'Installing'} ${pkg}@${version} (local cache)`);
|
|
35
35
|
alreadyInstalled = true;
|
|
36
36
|
}
|
|
37
37
|
// copy from cache
|
|
38
38
|
else if (isCached(`${pkg}@${version}`)) {
|
|
39
39
|
await copyCache(`${pkg}@${version}`, dir);
|
|
40
|
-
silent || logUpdate(`${dep ? 'Dependency' : 'Installing'} ${pkg}@${version} (cache)`);
|
|
40
|
+
silent || logUpdate(`${dep ? 'Dependency' : 'Installing'} ${pkg}@${version} (global cache)`);
|
|
41
41
|
}
|
|
42
42
|
// download
|
|
43
43
|
else {
|
package/dist/commands/update.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
-
import { checkConfigFile, readConfig } from '../mops.js';
|
|
2
|
+
import { checkConfigFile, getGithubCommit, parseGithubURL, readConfig } from '../mops.js';
|
|
3
3
|
import { add } from './add.js';
|
|
4
4
|
import { getAvailableUpdates } from './available-updates.js';
|
|
5
5
|
export async function update(pkg) {
|
|
@@ -7,9 +7,34 @@ export async function update(pkg) {
|
|
|
7
7
|
return;
|
|
8
8
|
}
|
|
9
9
|
let config = readConfig();
|
|
10
|
+
if (pkg && !config.dependencies?.[pkg] && !config['dev-dependencies']?.[pkg]) {
|
|
11
|
+
console.log(chalk.red(`Package "${pkg}" is not installed!`));
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
// update github packages
|
|
15
|
+
let deps = Object.values(config.dependencies || {});
|
|
16
|
+
let devDeps = Object.values(config['dev-dependencies'] || {});
|
|
17
|
+
let githubDeps = [...deps, ...devDeps].filter((dep) => dep.repo);
|
|
18
|
+
if (pkg) {
|
|
19
|
+
githubDeps = githubDeps.filter((dep) => dep.name === pkg);
|
|
20
|
+
}
|
|
21
|
+
for (let dep of githubDeps) {
|
|
22
|
+
let { org, gitName, branch, commitHash } = parseGithubURL(dep.repo || '');
|
|
23
|
+
let dev = !!config['dev-dependencies']?.[dep.name];
|
|
24
|
+
let commit = await getGithubCommit(`${org}/${gitName}`, branch);
|
|
25
|
+
if (commit.sha !== commitHash) {
|
|
26
|
+
await add(`https://github.com/${org}/${gitName}#${branch}@${commit.sha}`, { dev });
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
// update mops packages
|
|
10
30
|
let available = await getAvailableUpdates(config, pkg);
|
|
11
31
|
if (available.length === 0) {
|
|
12
|
-
|
|
32
|
+
if (pkg) {
|
|
33
|
+
console.log(chalk.green(`Package "${pkg}" is up to date!`));
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
console.log(chalk.green('All dependencies are up to date!'));
|
|
37
|
+
}
|
|
13
38
|
}
|
|
14
39
|
else {
|
|
15
40
|
for (let dep of available) {
|
|
@@ -20,5 +20,6 @@ export interface anon_class_10_1 {
|
|
|
20
20
|
'init' : ActorMethod<[], BenchSchema>,
|
|
21
21
|
'runCellQuery' : ActorMethod<[bigint, bigint], BenchResult>,
|
|
22
22
|
'runCellUpdate' : ActorMethod<[bigint, bigint], BenchResult>,
|
|
23
|
+
'runCellUpdateAwait' : ActorMethod<[bigint, bigint], BenchResult>,
|
|
23
24
|
}
|
|
24
25
|
export interface _SERVICE extends anon_class_10_1 {}
|
|
@@ -18,6 +18,7 @@ export const idlFactory = ({ IDL }) => {
|
|
|
18
18
|
'init' : IDL.Func([], [BenchSchema], []),
|
|
19
19
|
'runCellQuery' : IDL.Func([IDL.Nat, IDL.Nat], [BenchResult], ['query']),
|
|
20
20
|
'runCellUpdate' : IDL.Func([IDL.Nat, IDL.Nat], [BenchResult], []),
|
|
21
|
+
'runCellUpdateAwait' : IDL.Func([IDL.Nat, IDL.Nat], [BenchResult], []),
|
|
21
22
|
});
|
|
22
23
|
return anon_class_10_1;
|
|
23
24
|
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function getFileHashesFromRegistry(packageIds: string[]): Promise<[string, [string, Uint8Array | number[]][]][]>;
|
|
2
|
+
export declare function checkIntegrity(): Promise<void>;
|
|
3
|
+
export declare function saveLockFile(): Promise<void>;
|
|
4
|
+
export declare function checkLockFile(): Promise<void>;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { sha256 } from '@noble/hashes/sha256';
|
|
4
|
+
import { bytesToHex } from '@noble/hashes/utils';
|
|
5
|
+
import { getDependencyType, getRootDir, mainActor } from './mops.js';
|
|
6
|
+
import { resolvePackages } from './resolve-packages.js';
|
|
7
|
+
export async function getFileHashesFromRegistry(packageIds) {
|
|
8
|
+
let actor = await mainActor();
|
|
9
|
+
let fileHashesByPackageIds = await actor.getFileHashesByPackageIds(packageIds);
|
|
10
|
+
return fileHashesByPackageIds;
|
|
11
|
+
}
|
|
12
|
+
export async function checkIntegrity() {
|
|
13
|
+
let rootDir = getRootDir();
|
|
14
|
+
let resolvedPackages = await resolvePackages();
|
|
15
|
+
let packageIds = Object.entries(resolvedPackages)
|
|
16
|
+
.filter(([_, version]) => getDependencyType(version) === 'mops')
|
|
17
|
+
.map(([name, version]) => `${name}@${version}`);
|
|
18
|
+
let fileHashesFromRegistry = await getFileHashesFromRegistry(packageIds);
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
20
|
+
for (let [_packageId, fileHashes] of fileHashesFromRegistry) {
|
|
21
|
+
for (let [fileId, hash] of fileHashes) {
|
|
22
|
+
let remoteHash = new Uint8Array(hash);
|
|
23
|
+
let localData = fs.readFileSync(path.join(rootDir, '.mops', fileId));
|
|
24
|
+
let localHash = await sha256(localData);
|
|
25
|
+
if (bytesToHex(localHash) !== bytesToHex(remoteHash)) {
|
|
26
|
+
console.error('Integrity check failed.');
|
|
27
|
+
console.error(`Mismatched hash for ${fileId}: ${bytesToHex(localHash)} vs ${bytesToHex(remoteHash)}`);
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export async function saveLockFile() {
|
|
34
|
+
let rootDir = getRootDir();
|
|
35
|
+
let resolvedPackages = await resolvePackages();
|
|
36
|
+
let packageIds = Object.entries(resolvedPackages)
|
|
37
|
+
.filter(([_, version]) => getDependencyType(version) === 'mops')
|
|
38
|
+
.map(([name, version]) => `${name}@${version}`);
|
|
39
|
+
let fileHashes = await getFileHashesFromRegistry(packageIds);
|
|
40
|
+
let lockFileJson = {
|
|
41
|
+
version: 1,
|
|
42
|
+
hashes: fileHashes.reduce((acc, [packageId, fileHashes]) => {
|
|
43
|
+
acc[packageId] = fileHashes.reduce((acc, [fileId, hash]) => {
|
|
44
|
+
acc[fileId] = bytesToHex(new Uint8Array(hash));
|
|
45
|
+
return acc;
|
|
46
|
+
}, {});
|
|
47
|
+
return acc;
|
|
48
|
+
}, {}),
|
|
49
|
+
};
|
|
50
|
+
fs.writeFileSync(rootDir + '/mops-lock.json', JSON.stringify(lockFileJson, null, 2));
|
|
51
|
+
}
|
|
52
|
+
export async function checkLockFile() {
|
|
53
|
+
let rootDir = getRootDir();
|
|
54
|
+
let resolvedPackages = await resolvePackages();
|
|
55
|
+
let packageIds = Object.entries(resolvedPackages)
|
|
56
|
+
.filter(([_name, version]) => getDependencyType(version) === 'mops')
|
|
57
|
+
.map(([name, version]) => `${name}@${version}`);
|
|
58
|
+
let fileHashesFromRegistry = await getFileHashesFromRegistry(packageIds);
|
|
59
|
+
let lockFileJson = JSON.parse(fs.readFileSync(rootDir + '/mops-lock.json').toString());
|
|
60
|
+
if (lockFileJson.version !== 1) {
|
|
61
|
+
console.error(`Invalid lock file version: ${lockFileJson.version}`);
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
// if (lockFileJson.packageIds.length !== packageIds.length) {
|
|
65
|
+
// console.error(`Mismatched packageIds: ${JSON.stringify(lockFileJson.packageIds)} vs ${JSON.stringify(packageIds)}`);
|
|
66
|
+
// process.exit(1);
|
|
67
|
+
// }
|
|
68
|
+
// for (let i = 0; i < packageIds.length; i++) {
|
|
69
|
+
// if (lockFileJson.packageIds[i] !== packageIds[i]) {
|
|
70
|
+
// console.error(`Mismatched packageIds: ${JSON.stringify(lockFileJson.packageIds)} vs ${JSON.stringify(packageIds)}`);
|
|
71
|
+
// process.exit(1);
|
|
72
|
+
// }
|
|
73
|
+
// }
|
|
74
|
+
for (let [packageId, fileHashes] of fileHashesFromRegistry) {
|
|
75
|
+
let hashes = lockFileJson.hashes[packageId];
|
|
76
|
+
if (!hashes) {
|
|
77
|
+
console.error(`Missing packageId ${packageId} in lock file`);
|
|
78
|
+
process.exit(1);
|
|
79
|
+
}
|
|
80
|
+
for (let [fileId, hash] of fileHashes) {
|
|
81
|
+
let lockFileHash = hashes[fileId];
|
|
82
|
+
if (!lockFileHash) {
|
|
83
|
+
console.error(`Missing fileId ${fileId} in lock file`);
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
if (lockFileHash !== bytesToHex(new Uint8Array(hash))) {
|
|
87
|
+
console.error(`Mismatched hash for ${fileId}: ${lockFileHash} vs ${bytesToHex(new Uint8Array(hash))}`);
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
package/dist/mops.d.ts
CHANGED
|
@@ -21,10 +21,12 @@ export declare function checkConfigFile(): boolean;
|
|
|
21
21
|
export declare function progressBar(step: number, total: number): string;
|
|
22
22
|
export declare function getHighestVersion(pkgName: string): Promise<import("./declarations/main/main.did.js").Result_5>;
|
|
23
23
|
export declare function parseGithubURL(href: string): {
|
|
24
|
-
org: string
|
|
25
|
-
gitName: string
|
|
24
|
+
org: string;
|
|
25
|
+
gitName: string;
|
|
26
26
|
branch: string;
|
|
27
|
+
commitHash: string;
|
|
27
28
|
};
|
|
29
|
+
export declare function getGithubCommit(repo: string, ref: string): Promise<any>;
|
|
28
30
|
export declare function getDependencyType(version: string): "mops" | "github" | "local";
|
|
29
31
|
export declare function readConfig(configFile?: string): Config;
|
|
30
32
|
export declare function writeConfig(config: Config, configFile?: string): void;
|
package/dist/mops.js
CHANGED
|
@@ -104,7 +104,7 @@ export let getIdentity = async () => {
|
|
|
104
104
|
let identityPemEncrypted = path.resolve(globalConfigDir, 'identity.pem.encrypted');
|
|
105
105
|
if (fs.existsSync(identityPemEncrypted)) {
|
|
106
106
|
let res = await prompts({
|
|
107
|
-
type: '
|
|
107
|
+
type: 'invisible',
|
|
108
108
|
name: 'value',
|
|
109
109
|
message: 'Enter password:'
|
|
110
110
|
});
|
|
@@ -179,12 +179,26 @@ export async function getHighestVersion(pkgName) {
|
|
|
179
179
|
}
|
|
180
180
|
export function parseGithubURL(href) {
|
|
181
181
|
const url = new URL(href);
|
|
182
|
-
|
|
182
|
+
let branchAndSha = url.hash?.substring(1).split('@');
|
|
183
|
+
let branch = branchAndSha[0] || 'master';
|
|
184
|
+
let commitHash = branchAndSha[1] || '';
|
|
183
185
|
let [org, gitName] = url.pathname.split('/').filter(path => !!path);
|
|
186
|
+
org = org || '';
|
|
187
|
+
gitName = gitName || '';
|
|
184
188
|
if (gitName?.endsWith('.git')) {
|
|
185
189
|
gitName = gitName.substring(0, gitName.length - 4);
|
|
186
190
|
}
|
|
187
|
-
return { org, gitName, branch };
|
|
191
|
+
return { org, gitName, branch, commitHash };
|
|
192
|
+
}
|
|
193
|
+
export async function getGithubCommit(repo, ref) {
|
|
194
|
+
let res = await fetch(`https://api.github.com/repos/${repo}/commits/${ref}`);
|
|
195
|
+
let json = await res.json();
|
|
196
|
+
// try on main branch
|
|
197
|
+
if (json.message && ref === 'master') {
|
|
198
|
+
res = await fetch(`https://api.github.com/repos/${repo}/commits/main`);
|
|
199
|
+
json = await res.json();
|
|
200
|
+
}
|
|
201
|
+
return json;
|
|
188
202
|
}
|
|
189
203
|
export function getDependencyType(version) {
|
|
190
204
|
if (!version || typeof version !== 'string') {
|
|
@@ -244,8 +258,8 @@ export function formatDir(name, version) {
|
|
|
244
258
|
return path.join(getRootDir(), '.mops', `${name}@${version}`);
|
|
245
259
|
}
|
|
246
260
|
export function formatGithubDir(name, repo) {
|
|
247
|
-
const { branch } = parseGithubURL(repo);
|
|
248
|
-
return path.join(getRootDir(), '.mops/_github', `${name}
|
|
261
|
+
const { branch, commitHash } = parseGithubURL(repo);
|
|
262
|
+
return path.join(getRootDir(), '.mops/_github', `${name}#${branch}` + (commitHash ? `@${commitHash}` : ''));
|
|
249
263
|
}
|
|
250
264
|
export function readDfxJson() {
|
|
251
265
|
let dir = process.cwd();
|
package/dist/package.json
CHANGED
package/dist/vessel.js
CHANGED
|
@@ -59,8 +59,8 @@ export const readVesselConfig = async (dir, { cache = true } = {}) => {
|
|
|
59
59
|
return config;
|
|
60
60
|
};
|
|
61
61
|
export const downloadFromGithub = async (repo, dest, onProgress) => {
|
|
62
|
-
const { branch, org, gitName } = parseGithubURL(repo);
|
|
63
|
-
const zipFile = `https://github.com/${org}/${gitName}/archive/${branch}.zip`;
|
|
62
|
+
const { branch, org, gitName, commitHash } = parseGithubURL(repo);
|
|
63
|
+
const zipFile = `https://github.com/${org}/${gitName}/archive/${commitHash || branch}.zip`;
|
|
64
64
|
const readStream = got.stream(zipFile);
|
|
65
65
|
const promise = new Promise((resolve, reject) => {
|
|
66
66
|
readStream.on('error', (err) => {
|
|
@@ -71,7 +71,7 @@ export const downloadFromGithub = async (repo, dest, onProgress) => {
|
|
|
71
71
|
});
|
|
72
72
|
readStream.on('response', (response) => {
|
|
73
73
|
if (response.headers.age > 3600) {
|
|
74
|
-
console.
|
|
74
|
+
console.error(chalk.red('Error: ') + 'Failure - response too old');
|
|
75
75
|
readStream.destroy(); // Destroy the stream to prevent hanging resources.
|
|
76
76
|
reject();
|
|
77
77
|
return;
|
|
@@ -79,7 +79,7 @@ export const downloadFromGithub = async (repo, dest, onProgress) => {
|
|
|
79
79
|
// Prevent `onError` being called twice.
|
|
80
80
|
readStream.off('error', reject);
|
|
81
81
|
const tmpDir = path.resolve(process.cwd(), '.mops/_tmp/');
|
|
82
|
-
const tmpFile = path.resolve(tmpDir, `${gitName}@${branch}.zip`);
|
|
82
|
+
const tmpFile = path.resolve(tmpDir, `${gitName}@${commitHash || branch}.zip`);
|
|
83
83
|
try {
|
|
84
84
|
mkdirSync(tmpDir, { recursive: true });
|
|
85
85
|
pipeline(readStream, createWriteStream(tmpFile), (err) => {
|
|
@@ -114,20 +114,20 @@ export const downloadFromGithub = async (repo, dest, onProgress) => {
|
|
|
114
114
|
return promise;
|
|
115
115
|
};
|
|
116
116
|
export const installFromGithub = async (name, repo, { verbose = false, dep = false, silent = false } = {}) => {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
117
|
+
let { branch, commitHash } = parseGithubURL(repo);
|
|
118
|
+
let dir = formatGithubDir(name, repo);
|
|
119
|
+
let cacheName = `_github/${name}#${branch}` + (commitHash ? `@${commitHash}` : '');
|
|
120
120
|
if (existsSync(dir)) {
|
|
121
|
-
silent || logUpdate(`${dep ? 'Dependency' : 'Installing'} ${
|
|
121
|
+
silent || logUpdate(`${dep ? 'Dependency' : 'Installing'} ${repo} (local cache) from Github`);
|
|
122
122
|
}
|
|
123
123
|
else if (isCached(cacheName)) {
|
|
124
124
|
await copyCache(cacheName, dir);
|
|
125
|
-
silent || logUpdate(`${dep ? 'Dependency' : 'Installing'} ${
|
|
125
|
+
silent || logUpdate(`${dep ? 'Dependency' : 'Installing'} ${repo} (global cache) from Github`);
|
|
126
126
|
}
|
|
127
127
|
else {
|
|
128
128
|
mkdirSync(dir, { recursive: true });
|
|
129
129
|
let progress = (step, total) => {
|
|
130
|
-
silent || logUpdate(`${dep ? 'Dependency' : 'Installing'} ${
|
|
130
|
+
silent || logUpdate(`${dep ? 'Dependency' : 'Installing'} ${repo} ${progressBar(step, total)}`);
|
|
131
131
|
};
|
|
132
132
|
progress(0, 2 * (1024 ** 2));
|
|
133
133
|
try {
|
package/mops.ts
CHANGED
|
@@ -121,7 +121,7 @@ export let getIdentity = async (): Promise<Identity | undefined> => {
|
|
|
121
121
|
let identityPemEncrypted = path.resolve(globalConfigDir, 'identity.pem.encrypted');
|
|
122
122
|
if (fs.existsSync(identityPemEncrypted)) {
|
|
123
123
|
let res = await prompts({
|
|
124
|
-
type: '
|
|
124
|
+
type: 'invisible',
|
|
125
125
|
name: 'value',
|
|
126
126
|
message: 'Enter password:'
|
|
127
127
|
});
|
|
@@ -210,15 +210,29 @@ export async function getHighestVersion(pkgName: string) {
|
|
|
210
210
|
|
|
211
211
|
export function parseGithubURL(href: string) {
|
|
212
212
|
const url = new URL(href);
|
|
213
|
-
|
|
214
|
-
|
|
213
|
+
let branchAndSha = url.hash?.substring(1).split('@');
|
|
214
|
+
let branch = branchAndSha[0] || 'master';
|
|
215
|
+
let commitHash = branchAndSha[1] || '';
|
|
215
216
|
let [org, gitName] = url.pathname.split('/').filter(path => !!path);
|
|
217
|
+
org = org || '';
|
|
218
|
+
gitName = gitName || '';
|
|
216
219
|
|
|
217
220
|
if (gitName?.endsWith('.git')) {
|
|
218
221
|
gitName = gitName.substring(0, gitName.length - 4);
|
|
219
222
|
}
|
|
223
|
+
return {org, gitName, branch, commitHash};
|
|
224
|
+
}
|
|
220
225
|
|
|
221
|
-
|
|
226
|
+
export async function getGithubCommit(repo: string, ref: string): Promise<any> {
|
|
227
|
+
let res = await fetch(`https://api.github.com/repos/${repo}/commits/${ref}`);
|
|
228
|
+
let json: any = await res.json();
|
|
229
|
+
|
|
230
|
+
// try on main branch
|
|
231
|
+
if (json.message && ref === 'master') {
|
|
232
|
+
res = await fetch(`https://api.github.com/repos/${repo}/commits/main`);
|
|
233
|
+
json = await res.json();
|
|
234
|
+
}
|
|
235
|
+
return json;
|
|
222
236
|
}
|
|
223
237
|
|
|
224
238
|
export function getDependencyType(version: string) {
|
|
@@ -289,8 +303,8 @@ export function formatDir(name: string, version: string) {
|
|
|
289
303
|
}
|
|
290
304
|
|
|
291
305
|
export function formatGithubDir(name: string, repo: string) {
|
|
292
|
-
const {branch} = parseGithubURL(repo);
|
|
293
|
-
return path.join(getRootDir(), '.mops/_github', `${name}
|
|
306
|
+
const {branch, commitHash} = parseGithubURL(repo);
|
|
307
|
+
return path.join(getRootDir(), '.mops/_github', `${name}#${branch}` + (commitHash ? `@${commitHash}` : ''));
|
|
294
308
|
}
|
|
295
309
|
|
|
296
310
|
export function readDfxJson(): any {
|
package/package.json
CHANGED
package/vessel.ts
CHANGED
|
@@ -83,9 +83,9 @@ export const readVesselConfig = async (dir: string, {cache = true} = {}): Promis
|
|
|
83
83
|
};
|
|
84
84
|
|
|
85
85
|
export const downloadFromGithub = async (repo: string, dest: string, onProgress: any) => {
|
|
86
|
-
const {branch, org, gitName} = parseGithubURL(repo);
|
|
86
|
+
const {branch, org, gitName, commitHash} = parseGithubURL(repo);
|
|
87
87
|
|
|
88
|
-
const zipFile = `https://github.com/${org}/${gitName}/archive/${branch}.zip`;
|
|
88
|
+
const zipFile = `https://github.com/${org}/${gitName}/archive/${commitHash || branch}.zip`;
|
|
89
89
|
const readStream = got.stream(zipFile);
|
|
90
90
|
|
|
91
91
|
const promise = new Promise((resolve, reject) => {
|
|
@@ -99,7 +99,7 @@ export const downloadFromGithub = async (repo: string, dest: string, onProgress:
|
|
|
99
99
|
|
|
100
100
|
readStream.on('response', (response) => {
|
|
101
101
|
if (response.headers.age > 3600) {
|
|
102
|
-
console.
|
|
102
|
+
console.error(chalk.red('Error: ') + 'Failure - response too old');
|
|
103
103
|
readStream.destroy(); // Destroy the stream to prevent hanging resources.
|
|
104
104
|
reject();
|
|
105
105
|
return;
|
|
@@ -108,7 +108,7 @@ export const downloadFromGithub = async (repo: string, dest: string, onProgress:
|
|
|
108
108
|
// Prevent `onError` being called twice.
|
|
109
109
|
readStream.off('error', reject);
|
|
110
110
|
const tmpDir = path.resolve(process.cwd(), '.mops/_tmp/');
|
|
111
|
-
const tmpFile = path.resolve(tmpDir, `${gitName}@${branch}.zip`);
|
|
111
|
+
const tmpFile = path.resolve(tmpDir, `${gitName}@${commitHash || branch}.zip`);
|
|
112
112
|
|
|
113
113
|
try {
|
|
114
114
|
mkdirSync(tmpDir, {recursive: true});
|
|
@@ -147,22 +147,22 @@ export const downloadFromGithub = async (repo: string, dest: string, onProgress:
|
|
|
147
147
|
};
|
|
148
148
|
|
|
149
149
|
export const installFromGithub = async (name: string, repo: string, {verbose = false, dep = false, silent = false} = {}) => {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
150
|
+
let {branch, commitHash} = parseGithubURL(repo);
|
|
151
|
+
let dir = formatGithubDir(name, repo);
|
|
152
|
+
let cacheName = `_github/${name}#${branch}` + (commitHash ? `@${commitHash}` : '');
|
|
153
153
|
|
|
154
154
|
if (existsSync(dir)) {
|
|
155
|
-
silent || logUpdate(`${dep ? 'Dependency' : 'Installing'} ${
|
|
155
|
+
silent || logUpdate(`${dep ? 'Dependency' : 'Installing'} ${repo} (local cache) from Github`);
|
|
156
156
|
}
|
|
157
157
|
else if (isCached(cacheName)) {
|
|
158
158
|
await copyCache(cacheName, dir);
|
|
159
|
-
silent || logUpdate(`${dep ? 'Dependency' : 'Installing'} ${
|
|
159
|
+
silent || logUpdate(`${dep ? 'Dependency' : 'Installing'} ${repo} (global cache) from Github`);
|
|
160
160
|
}
|
|
161
161
|
else {
|
|
162
162
|
mkdirSync(dir, {recursive: true});
|
|
163
163
|
|
|
164
164
|
let progress = (step: number, total: number) => {
|
|
165
|
-
silent || logUpdate(`${dep ? 'Dependency' : 'Installing'} ${
|
|
165
|
+
silent || logUpdate(`${dep ? 'Dependency' : 'Installing'} ${repo} ${progressBar(step, total)}`);
|
|
166
166
|
};
|
|
167
167
|
|
|
168
168
|
progress(0, 2 * (1024 ** 2));
|