Skip to content

Commit a664af7

Browse files
Merge pull request #81 from JarvusInnovations/develop
Release: v0.21.3
2 parents 492b450 + 6e84904 commit a664af7

File tree

9 files changed

+4075
-4564
lines changed

9 files changed

+4075
-4564
lines changed

.github/workflows/release-validate.yml

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,13 @@ env:
99
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
1010

1111
jobs:
12-
release-validate:
1312

13+
release-validate:
1414
runs-on: ubuntu-latest
1515
steps:
1616

17-
- name: Grab PR Title
17+
- name: Validate PR title
1818
run: |
19-
set -e
20-
2119
PR_TITLE=$(jq -r ".pull_request.title" $GITHUB_EVENT_PATH)
2220
2321
# check title format and extract tag
@@ -30,7 +28,7 @@ jobs:
3028
fi
3129
3230
# check that tag doesn't exist
33-
if git ls-remote --exit-code origin "refs/tags/${RELEASE_TAG}"; then
31+
if git ls-remote --exit-code "https://${GITHUB_ACTOR}:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}" "refs/tags/${RELEASE_TAG}"; then
3432
echo "The PR title's version exists already"
3533
exit 1
3634
fi

backend/bin/cli.js

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,22 @@
22

33

44
// setup logger
5-
const logger = require('winston')
6-
module.exports = { logger }
5+
const logger = require('winston');
6+
const loggerConsole = new logger.transports.Console({
7+
level: process.env.DEBUG ? 'debug' : 'info',
8+
format: logger.format.combine(
9+
logger.format.colorize(),
10+
logger.format.prettyPrint(),
11+
logger.format.splat(),
12+
logger.format.simple(),
13+
),
714

8-
if (process.env.DEBUG) {
9-
logger.level = 'debug'
10-
}
15+
// all logger output to STDERR
16+
stderrLevels: Object.keys(require('winston/lib/winston/config').cli.levels),
17+
});
18+
logger.add(loggerConsole);
1119

12-
13-
// all logger output to STDERR
14-
for (const level in logger.levels) {
15-
logger.default.transports.console.stderrLevels[level] = true;
16-
}
20+
module.exports = { logger };
1721

1822

1923
// route command line
@@ -25,15 +29,33 @@ require('yargs')
2529
default: false,
2630
global: true,
2731
})
32+
.option('q', {
33+
alias: 'quiet',
34+
type: 'boolean',
35+
default: false,
36+
global: true,
37+
})
2838
.check(function (argv) {
2939
if (argv.debug) {
30-
logger.level = 'debug'
40+
loggerConsole.level = 'debug';
3141
} else if (argv.quiet) {
32-
logger.level = 'error'
42+
loggerConsole.level = 'error';
3343
}
3444

3545
return true;
3646
})
37-
.commandDir('../commands')
47+
.commandDir('../commands', { exclude: /\.test\.js$/ })
3848
.demandCommand()
39-
.argv
49+
.showHelpOnFail(false, 'Specify --help for available options')
50+
.fail((msg, err) => {
51+
logger.error(msg || err.message);
52+
53+
if (err) {
54+
logger.debug(err.stack);
55+
}
56+
57+
process.exit(1);
58+
})
59+
.strict()
60+
.help()
61+
.argv;

backend/commands/edit.js

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,24 +19,30 @@ exports.builder = {
1919
exports.handler = async function edit({ recordPath, resumePath, encoding }) {
2020
const fs = require('fs');
2121
const { spawn } = require('child_process');
22+
const path = require('path');
23+
const tmp = require('tmp');
2224
const TOML = require('@iarna/toml');
2325
const Repository = require('../lib/Repository.js');
2426
const Sheet = require('../lib/Sheet.js')
2527
const repo = await Repository.getFromEnvironment({ working: true });
2628
const git = await repo.getGit();
2729

2830
// open record
29-
const recordToml = fs.readFileSync(resumePath || recordPath, encoding);
31+
let recordToml = fs.readFileSync(resumePath || recordPath, encoding);
3032

31-
// get temp path
32-
const tempFilePath = await new Promise((resolve, reject) => {
33-
const mktemp = spawn('mktemp', ['-t', 'gitsheet.XXXXXX.toml']);
34-
35-
let stdout = '', stderr = '';
36-
mktemp.stdout.on('data', chunk => stdout += chunk);
37-
mktemp.stderr.on('data', chunk => stderr += chunk);
33+
// try to parse and format
34+
try {
35+
const record = TOML.parse(recordToml);
36+
recordToml = Sheet.stringifyRecord(record);
37+
} catch (err) {
38+
console.warn(`Failed to parse opened record:\n${err}`);
39+
}
3840

39-
mktemp.on('close', code => code === 0 ? resolve(stdout.trim()) : reject(stderr.trim()));
41+
// get temp path
42+
const { name: tempFilePath } = tmp.fileSync({
43+
prefix: path.basename(recordPath, '.toml'),
44+
postfix: '.toml',
45+
discardDescriptor: true,
4046
});
4147

4248
// populate temp path
@@ -67,7 +73,7 @@ exports.handler = async function edit({ recordPath, resumePath, encoding }) {
6773
try {
6874
editedRecord = TOML.parse(editedToml);
6975
} catch (err) {
70-
console.error(`Failed to parse record:\n${err}`);
76+
console.error(`Failed to parse edited record:\n${err}`);
7177
console.error(`To resume editing, run: git sheet edit ${recordPath} ${tempFilePath}`);
7278
process.exit(1);
7379
}

backend/commands/normalize.js

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,23 @@ exports.handler = async function query({
5454
}
5555

5656
// loop through all records and re-upsert
57-
for await (const record of sheet.query()) {
58-
logger.info(`rewriting ${sheetName}/${record[Symbol.for('gitsheets-path')]}`);
59-
await sheet.upsert(record);
57+
try {
58+
for await (const record of sheet.query()) {
59+
const originalPath = record[Symbol.for('gitsheets-path')];
60+
logger.info(`rewriting ${path.join(root, prefix, sheetName, originalPath)}.toml`);
61+
const { path: normalizedPath } = await sheet.upsert(record);
62+
63+
if (normalizedPath !== originalPath) {
64+
logger.warn(`^- moved to ${path.join(root, prefix, sheetName, normalizedPath)}.toml`);
65+
}
66+
}
67+
} catch (err) {
68+
if (err.constructor.name == 'TomlError') {
69+
logger.error(`failed to parse ${path.join(root, prefix, err.file)}\n${err.message}`);
70+
process.exit(1);
71+
}
72+
73+
throw err;
6074
}
6175
}
6276

backend/commands/read.js

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ exports.desc = 'Read a record, converting to desired format';
33
exports.builder = {
44
'record-path': {
55
type: 'string',
6-
describe: 'The path to a record file to edit',
6+
describe: 'The path to a record file to read',
77
demandOption: true,
88
},
99
encoding: {
@@ -24,12 +24,7 @@ exports.builder = {
2424

2525
exports.handler = async function edit({ recordPath, encoding, format, headers }) {
2626
const fs = require('fs');
27-
const { spawn } = require('child_process');
2827
const TOML = require('@iarna/toml');
29-
const Repository = require('../lib/Repository.js');
30-
const Sheet = require('../lib/Sheet.js')
31-
const repo = await Repository.getFromEnvironment({ working: true });
32-
const git = await repo.getGit();
3328

3429
// open record
3530
const recordToml = fs.readFileSync(recordPath, encoding);
@@ -64,6 +59,6 @@ async function outputCsv(record, { headers = true, delimiter = ',' } = {}) {
6459
}
6560

6661
async function outputToml(record) {
67-
const TOML = require('@iarna/toml');
68-
console.log(`${TOML.stringify(record)}`);
62+
const Sheet = require('../lib/Sheet.js')
63+
console.log(`${Sheet.stringifyRecord(record)}`);
6964
}

backend/lib/Sheet.js

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,20 @@ class Sheet extends Configurable
118118
async readRecord (blob, path = null) {
119119
const cache = this.#recordCache.get(blob.hash);
120120

121-
const record = cache
122-
? v8.deserialize(cache)
123-
: await blob.read().then(TOML.parse);
121+
let record;
122+
123+
if (cache) {
124+
record = v8.deserialize(cache);
125+
} else {
126+
const toml = await blob.read();
127+
128+
try {
129+
record = TOML.parse(toml);
130+
} catch (err) {
131+
err.file = path;
132+
throw err;
133+
}
134+
}
124135

125136
// annotate with gitsheets keys
126137
record[RECORD_SHEET_KEY] = this.name;
@@ -153,14 +164,14 @@ class Sheet extends Configurable
153164
const pathTemplate = PathTemplate.fromString(pathTemplateString);
154165
const sheetDataTree = await this.dataTree.getSubtree(sheetRoot);
155166

156-
BLOBS: for await (const blob of pathTemplate.queryTree(sheetDataTree, query)) {
157-
const record = await this.readRecord(blob);
167+
BLOBS: for await (const { blob, path: blobPath } of pathTemplate.queryTree(sheetDataTree, query)) {
168+
const record = await this.readRecord(blob, blobPath);
158169

159170
if (!queryMatches(query, record)) {
160171
continue BLOBS;
161172
}
162173

163-
record[RECORD_PATH_KEY] = pathTemplate.render(record);
174+
record[RECORD_PATH_KEY] = blobPath || pathTemplate.render(record);
164175

165176
yield record;
166177
}

backend/lib/path/Template.js

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class Template
5050
return recordPath.join('/');
5151
}
5252

53-
async* queryTree (tree, query, depth = 0) {
53+
async* queryTree (tree, query, pathPrefix = '', depth = 0) {
5454
const numComponents = this.#components.length;
5555

5656
if (!tree) {
@@ -68,7 +68,7 @@ class Template
6868
const child = await currentTree.getChild(`${nextName}.toml`);
6969

7070
if (child) {
71-
yield child;
71+
yield { path: path.join(pathPrefix, nextName), blob: child };
7272
}
7373

7474
// absolute match on a leaf, we're done with this query
@@ -97,8 +97,9 @@ class Template
9797
continue;
9898
}
9999

100-
attachmentsPrefix = `${childPath.substr(0, childPath.length - 5)}/`;
101-
yield child;
100+
const childName = childPath.substr(0, childPath.length - 5);
101+
attachmentsPrefix = `${childName}/`;
102+
yield { path: path.join(pathPrefix, childName), blob: child };
102103
}
103104

104105
return;
@@ -117,14 +118,14 @@ class Template
117118
} else {
118119
// each tree in current tree could contain matching records
119120
const children = await currentTree.getChildren();
120-
for (const childName in children) {
121-
const child = children[childName];
121+
for (const childPath in children) {
122+
const child = children[childPath];
122123

123124
if (!child.isTree) {
124125
continue;
125126
}
126127

127-
yield* this.queryTree(child, query, i+1);
128+
yield* this.queryTree(child, query, path.join(pathPrefix, childPath), i+1);
128129
}
129130

130131
return;

0 commit comments

Comments
 (0)