Skip to content

Add CLI #82

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions lib/cli-run.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env node

const { main } = require('./cli');

process.exit(main());
102 changes: 102 additions & 0 deletions lib/cli.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
const fs = require('fs');
const parseConflictJSON = require('.');
const { isDiff } = parseConflictJSON;
const { version, description } = require('../package.json');


const help = `\
usage: npx parse-conflict-json [OPTIONS...] [--] [FILE]...

Parse JSON file(s) and resolve merge conflicts if possible.

options:
-h, --help print this help and exit
-v, --version print version number and exit
-i, --in-place write resolved conflicts back to FILE (default to stdout)
-p, --prefer {ours|theirs}
prefer *our* or *their* version of the file, respectively
(default: 'ours')

Exits 0 on success, 1 on error.\
`;


function parseArgs(argv = process.argv.slice(2)) {
const argSepIdx = argv.findIndex(x => x == '--');
const opts = argSepIdx >= 0 ? argv.slice(0, argSepIdx) : argv;
const args = argSepIdx >= 0 ? argv.slice(argSepIdx + 1) : [];

if (opts.find(arg => arg === "-h" || arg === "--help")) {
console.log(help);
return;
}

const options = {
inPlace: false,
prefer: '',
files: (args.slice() || []),
};

for (let i = 0, len = opts.length; i < len; i++) {
const [opt, ...maybeArg] = opts[i].split('=', 1);
switch (opt) {
case '-v':
case '--version':
console.log(version);
return;
case '-i':
case '--in-place':
if (maybeArg.length) {
throw new Error(`option ${opt} does not take an argument`);
}
options.inPlace = true;
case '-p':
case '--prefer':
const arg = maybeArg.length ? maybeArg[0] : opts[++i];
options.prefer = arg; // error will be thrown by index.js
default:
if (args.length || opt.startsWith('-')) {
throw new Error(`unrecognized option ${opt}`)
} else {
options.files.push(opt);
}
}
}

return options;
}

function main(argv = process.argv.slice(2)) {
try {
const options = parseArgs(argv);
if (!options) { return 0; }

if (!options.files.length) {
throw Error("No files specified!");
}

for (const file of options.files) {
const contents = fs.readFileSync(file).toString();

if (!isDiff(contents)) {
console.error(`warning: file {file} does not have conflict markers`);
}

const resolved = parseConflictJSON(contents, null, options.prefer);

if (options.inPlace) {
fs.writeFileSync(file, resolved);
console.error(`${file}: wrote ${Buffer.byteLength(resolved, 'utf8')} bytes`)
} else {
console.log(resolved);
}
}
return 0;

} catch (err) {
console.error(`${err}`);
return 1;
}
}

module.exports = { main, parseArgs };
10 changes: 2 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"author": "GitHub Inc.",
"license": "ISC",
"main": "lib",
"bin": "lib/cli-run.js",
"scripts": {
"test": "tap",
"snap": "tap",
Expand All @@ -14,17 +15,10 @@
"posttest": "npm run lint",
"template-oss-apply": "template-oss-apply --force"
},
"tap": {
"check-coverage": true,
"nyc-arg": [
"--exclude",
"tap-snapshots/**"
]
},
"devDependencies": {
"@npmcli/eslint-config": "^4.0.0",
"@npmcli/template-oss": "4.21.4",
"tap": "^16.0.1"
"tap": "^18.7.2"
},
"dependencies": {
"json-parse-even-better-errors": "^3.0.0",
Expand Down
20 changes: 15 additions & 5 deletions tap-snapshots/test/basic.js.test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
* Make sure to inspect the output below. Do not ignore changes!
*/
'use strict'
exports[`test/basic.js TAP basic usage > parse unconflicted 1`] = `
exports[`test/basic.js > TAP > basic usage > parse unconflicted 1`] = `
Object {
"a": "apple",
[Symbol.for(indent)]: "",
[Symbol.for(newline)]: "",
}
`

exports[`test/basic.js TAP conflicted > parse conflicted, preferring theirs 1`] = `
exports[`test/basic.js > TAP > conflicted > parse conflicted, preferring theirs 1`] = `
Object {
"a": Object {
"b": Object {
Expand All @@ -32,10 +34,12 @@ Object {
},
1,
],
[Symbol.for(indent)]: "",
[Symbol.for(newline)]: "",
}
`

exports[`test/basic.js TAP conflicted > prefer theirs 1`] = `
exports[`test/basic.js > TAP > conflicted > prefer theirs 1`] = `
Object {
"a": Object {
"b": Object {
Expand All @@ -54,10 +58,12 @@ Object {
},
1,
],
[Symbol.for(indent)]: "",
[Symbol.for(newline)]: "",
}
`

exports[`test/basic.js TAP error states > BOM is no problem 1`] = `
exports[`test/basic.js > TAP > error states > BOM is no problem 1`] = `
Object {
"a": Object {
"b": Object {
Expand All @@ -78,13 +84,17 @@ Object {
},
1,
],
[Symbol.for(indent)]: "",
[Symbol.for(newline)]: "",
}
`

exports[`test/basic.js TAP global object attributes > filters out global object attributes 1`] = `
exports[`test/basic.js > TAP > global object attributes > filters out global object attributes 1`] = `
Object {
"__proto__": "__proto__",
"constructor": "constructor",
[Symbol.for(indent)]: "",
[Symbol.for(newline)]: "",
"toString": "toString",
"x": Object {},
}
Expand Down
Loading