watskeburt 0.10.2 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +13 -4
- package/bin/cli.js +2 -2
- package/bin/version.js +1 -1
- package/dist/cjs-bundle.cjs +1 -1
- package/dist/esm/git-primitives-sync.js +64 -0
- package/dist/esm/git-primitives.js +44 -32
- package/dist/esm/main.js +17 -2
- package/package.json +8 -8
- package/types/watskeburt.d.ts +25 -0
package/README.md
CHANGED
@@ -25,29 +25,38 @@ but for just this simple usage they're a bit overkill.
|
|
25
25
|
|
26
26
|
```javascript
|
27
27
|
// const { listSync, getSHASync } = require("watskeburt"); // in commonjs contexts you can also require it
|
28
|
-
import { listSync, getSHASync } from "watskeburt";
|
28
|
+
import { list, getSHA, listSync, getSHASync } from "watskeburt";
|
29
29
|
|
30
30
|
// print the SHA1 of the current HEAD
|
31
|
+
console.log(await getSHA());
|
31
32
|
console.log(getSHASync());
|
32
33
|
|
33
34
|
// list all files that differ between 'main' and the current revision (including
|
34
35
|
// files not staged for commit and files not under revision control)
|
35
36
|
/** @type {import('watskeburt').IChange[]} */
|
36
|
-
const lChangedFiles =
|
37
|
+
const lChangedFiles = await list("main");
|
38
|
+
// or, with the sync interface:
|
39
|
+
// const lChangedFiles = listSync("main");
|
37
40
|
|
38
41
|
// list all files that differ between 'v0.6.1' and 'v0.7.1' (by definition
|
39
42
|
// won't include files staged for commit and/ or not under revision control)
|
40
43
|
/** @type {import('watskeburt').IChange[]} */
|
41
|
-
const lChangedFiles =
|
44
|
+
const lChangedFiles = await list("v0.6.1", "v0.7.1");
|
45
|
+
// const lChangedFiles = listSync("v0.6.1", "v0.7.1");
|
42
46
|
|
43
47
|
// As a third parameter you can pass some options
|
44
48
|
// (pass null as the second parameter if you only want to compare between
|
45
49
|
// a revision and the working tree):
|
46
50
|
/** @type {import('watskeburt').IChange[]|string} */
|
47
|
-
const lChangedFiles =
|
51
|
+
const lChangedFiles = await list("main", null, {
|
48
52
|
trackedOnly: false, // when set to true leaves out files not under revision control
|
49
53
|
outputType: "object", // other options: "json" and "regex" (as used in the CLI)
|
50
54
|
});
|
55
|
+
// or with synchronous code:
|
56
|
+
// const lChangedFiles = listSynd("main", null, {
|
57
|
+
// trackedOnly: false, // when set to true leaves out files not under revision control
|
58
|
+
// outputType: "object", // other options: "json" and "regex" (as used in the CLI)
|
59
|
+
// });
|
51
60
|
```
|
52
61
|
|
53
62
|
The array of changes this returns looks like this:
|
package/bin/cli.js
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
/* eslint-disable no-console */
|
3
3
|
import { EOL } from "node:os";
|
4
4
|
import { Option, program } from "commander";
|
5
|
-
import {
|
5
|
+
import { list } from "../dist/esm/main.js";
|
6
6
|
import { VERSION } from "./version.js";
|
7
7
|
|
8
8
|
program
|
@@ -23,7 +23,7 @@ program
|
|
23
23
|
.parse(process.argv);
|
24
24
|
|
25
25
|
try {
|
26
|
-
console.log(
|
26
|
+
console.log(await list(program.args[0], program.args[1], program.opts()));
|
27
27
|
} catch (pError) {
|
28
28
|
console.error(`ERROR: ${pError.message}`);
|
29
29
|
}
|
package/bin/version.js
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
// generated by tools/get-version.ts - edits will be overwritten
|
2
|
-
export const VERSION = "0.
|
2
|
+
export const VERSION = "0.11.0";
|
package/dist/cjs-bundle.cjs
CHANGED
@@ -1 +1 @@
|
|
1
|
-
"use strict";var
|
1
|
+
"use strict";var y=Object.defineProperty;var _=Object.getOwnPropertyDescriptor;var k=Object.getOwnPropertyNames;var M=Object.prototype.hasOwnProperty;var b=(t,e)=>{for(var n in e)y(t,n,{get:e[n],enumerable:!0})},B=(t,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of k(e))!M.call(t,o)&&o!==n&&y(t,o,{get:()=>e[o],enumerable:!(r=_(e,o))||r.enumerable});return t};var H=t=>B(y({},"__esModule",{value:!0}),t);var K={};b(K,{getSHA:()=>m,getSHASync:()=>p,list:()=>z,listSync:()=>q});module.exports=H(K);var T=require("os"),U=/^(?<changeType>[ACDMRTUXB])(?<similarity>[0-9]{3})?[ \t]+(?<name>[^ \t]+)[ \t]*(?<newName>[^ \t]+)?$/,j=/^(?<stagedChangeType>[ ACDMRTUXB?!])(?<unStagedChangeType>[ ACDMRTUXB?!])[ \t]+(?<name>[^ \t]+)(( -> )(?<newName>[^ \t]+))?$/,R={A:"added",C:"copied",D:"deleted",M:"modified",R:"renamed",T:"type changed",U:"unmerged",B:"pairing broken"," ":"unmodified","?":"untracked","!":"ignored"};function d(t){return R[t]??"unknown"}function v(t){let e=t.match(j),n={};if(e!=null&&e.groups){let r=d(e.groups.stagedChangeType),o=d(e.groups.unStagedChangeType);n.changeType=r==="unmodified"?o:r,e.groups.newName?(n.name=e.groups.newName,n.oldName=e.groups.name):n.name=e.groups.name}return n}function F(t){let e=t.match(U),n={};return e!=null&&e.groups&&(n.changeType=d(e.groups.changeType),e.groups.newName?(n.name=e.groups.newName,n.oldName=e.groups.name):n.name=e.groups.name),n}function h(t){return t.split(T.EOL).filter(Boolean).map(v).filter(({name:e,changeType:n})=>!!e&&!!n)}function S(t){return t.split(T.EOL).filter(Boolean).map(F).filter(({name:e,changeType:n})=>!!e&&!!n)}var u=require("child_process");function N(t){return t instanceof Buffer?t.toString("utf8"):t}function G(t){throw t.code==="ENOENT"?new Error("git executable not found"):new Error(`internal spawn error: ${t}`)}function w(t,e,n){let r=n("git",t,{cwd:process.cwd(),env:process.env});if(r.error&&G(r.error),r.status===0)return N(r.stdout);throw new Error(e[r.status??0]||`internal git error: ${r.status} (${N(r.stderr)})`)}function A(t=u.spawnSync){let e={129:`'${process.cwd()}' does not seem to be a git repository`};return w(["status","--porcelain"],e,t)}function D(t,e,n=u.spawnSync){let r={128:`revision '${t}' ${e?`(or '${e}') `:""}unknown`,129:`'${process.cwd()}' does not seem to be a git repository`};return w(e?["diff",t,e,"--name-status"]:["diff",t,"--name-status"],r,n)}function p(t=u.spawnSync){return w(["rev-parse","HEAD"],{},t).slice(0,40)}var L=require("path"),X=new Set([".cjs",".cjsx",".coffee",".csx",".cts",".js",".json",".jsx",".litcoffee",".ls",".mjs",".mts",".svelte",".ts",".tsx",".vue",".vuex"]),J=new Set(["modified","added","renamed","copied","untracked"]);function C(t,e=X,n=J){return`^(${t.filter(o=>n.has(o.changeType)).map(({name:o})=>o).filter(o=>e.has((0,L.extname)(o))).join("|")})$`}function I(t){return JSON.stringify(t,null,2)}var Y=t=>t,V=new Map([["regex",C],["json",I]]);function f(t,e){return(V.get(e??"unknown")||Y)(t)}var l=require("child_process");function O(t){return t instanceof Buffer?t.toString("utf8"):t}function E(t,e,n){let r=n("git",t,{cwd:process.cwd(),env:process.env}),o="",a="";return new Promise((c,i)=>{var g,x;(g=r.stdout)==null||g.on("data",s=>{o=o.concat(s)}),(x=r.stderr)==null||x.on("data",s=>{a=a.concat(s)}),r.on("close",s=>{s===0?c(O(o)):i(new Error(e[s??0]||`internal git error: ${s} (${O(a)})`))}),r.on("error",s=>{(s==null?void 0:s.code)==="ENOENT"?i(new Error("git executable not found")):i(new Error(`internal spawn error: ${s}`))})})}async function $(t=l.spawn){let e={129:`'${process.cwd()}' does not seem to be a git repository`};return await E(["status","--porcelain"],e,t)}async function P(t,e,n=l.spawn){let r={128:`revision '${t}' ${e?`(or '${e}') `:""}unknown`,129:`'${process.cwd()}' does not seem to be a git repository`};return await E(e?["diff",t,e,"--name-status"]:["diff",t,"--name-status"],r,n)}async function m(t=l.spawn){return(await E(["rev-parse","HEAD"],{},t)).slice(0,40)}function q(t,e,n){let r=t||p(),o=n||{},a=S(D(r,e));return o.trackedOnly||(a=a.concat(h(A()).filter(({changeType:c})=>c==="untracked"))),f(a,o.outputType)}async function z(t,e,n){let r=t||await m(),o=n||{},[a,c]=await Promise.all([P(r,e),o.trackedOnly?"":$()]),i=S(a);return o.trackedOnly||(i=i.concat(h(c).filter(({changeType:g})=>g==="untracked"))),f(i,o.outputType)}0&&(module.exports={getSHA,getSHASync,list,listSync});
|
@@ -0,0 +1,64 @@
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
2
|
+
function stringifyOutStream(pError) {
|
3
|
+
if (pError instanceof Buffer) {
|
4
|
+
return pError.toString("utf8");
|
5
|
+
}
|
6
|
+
else {
|
7
|
+
return pError;
|
8
|
+
}
|
9
|
+
}
|
10
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
11
|
+
function throwSpawnError(pError) {
|
12
|
+
if (pError.code === "ENOENT") {
|
13
|
+
throw new Error("git executable not found");
|
14
|
+
}
|
15
|
+
else {
|
16
|
+
throw new Error(`internal spawn error: ${pError}`);
|
17
|
+
}
|
18
|
+
}
|
19
|
+
/**
|
20
|
+
* @throws {Error}
|
21
|
+
*/
|
22
|
+
function getGitResultSync(pArguments, pErrorMap, pSpawnFunction) {
|
23
|
+
const lGitResult = pSpawnFunction("git", pArguments, {
|
24
|
+
cwd: process.cwd(),
|
25
|
+
// eslint-disable-next-line node/no-process-env
|
26
|
+
env: process.env,
|
27
|
+
});
|
28
|
+
if (lGitResult.error) {
|
29
|
+
throwSpawnError(lGitResult.error);
|
30
|
+
}
|
31
|
+
if (lGitResult.status === 0) {
|
32
|
+
return stringifyOutStream(lGitResult.stdout);
|
33
|
+
}
|
34
|
+
else {
|
35
|
+
throw new Error(pErrorMap[lGitResult.status ?? 0] ||
|
36
|
+
`internal git error: ${lGitResult.status} (${stringifyOutStream(lGitResult.stderr)})`);
|
37
|
+
}
|
38
|
+
}
|
39
|
+
/**
|
40
|
+
* @throws {Error}
|
41
|
+
*/
|
42
|
+
export function getStatusShortSync(pSpawnFunction = spawnSync) {
|
43
|
+
const lErrorMap = {
|
44
|
+
129: `'${process.cwd()}' does not seem to be a git repository`,
|
45
|
+
};
|
46
|
+
return getGitResultSync(["status", "--porcelain"], lErrorMap, pSpawnFunction);
|
47
|
+
}
|
48
|
+
/**
|
49
|
+
*
|
50
|
+
* @throws {Error}
|
51
|
+
*/
|
52
|
+
export function getDiffLinesSync(pOldRevision, pNewRevision, pSpawnFunction = spawnSync) {
|
53
|
+
const lErrorMap = {
|
54
|
+
128: `revision '${pOldRevision}' ${pNewRevision ? `(or '${pNewRevision}') ` : ""}unknown`,
|
55
|
+
129: `'${process.cwd()}' does not seem to be a git repository`,
|
56
|
+
};
|
57
|
+
return getGitResultSync(pNewRevision
|
58
|
+
? ["diff", pOldRevision, pNewRevision, "--name-status"]
|
59
|
+
: ["diff", pOldRevision, "--name-status"], lErrorMap, pSpawnFunction);
|
60
|
+
}
|
61
|
+
export function getSHASync(pSpawnFunction = spawnSync) {
|
62
|
+
const lSha1Length = 40;
|
63
|
+
return getGitResultSync(["rev-parse", "HEAD"], {}, pSpawnFunction).slice(0, lSha1Length);
|
64
|
+
}
|
@@ -1,64 +1,76 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
2
|
+
import { spawn } from "node:child_process";
|
3
|
+
function stringifyOutStream(pBufferOrString) {
|
4
|
+
if (pBufferOrString instanceof Buffer) {
|
5
|
+
return pBufferOrString.toString("utf8");
|
5
6
|
}
|
6
7
|
else {
|
7
|
-
return
|
8
|
-
}
|
9
|
-
}
|
10
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
11
|
-
function throwSpawnError(pError) {
|
12
|
-
if (pError.code === "ENOENT") {
|
13
|
-
throw new Error("git executable not found");
|
14
|
-
}
|
15
|
-
else {
|
16
|
-
throw new Error(`internal spawn error: ${pError}`);
|
8
|
+
return pBufferOrString;
|
17
9
|
}
|
18
10
|
}
|
19
11
|
/**
|
20
12
|
* @throws {Error}
|
21
13
|
*/
|
22
|
-
function
|
23
|
-
const
|
14
|
+
function getGitResult(pArguments, pErrorMap, pSpawnFunction) {
|
15
|
+
const lGit = pSpawnFunction("git", pArguments, {
|
24
16
|
cwd: process.cwd(),
|
25
17
|
// eslint-disable-next-line node/no-process-env
|
26
18
|
env: process.env,
|
27
19
|
});
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
20
|
+
let lStdOutData = "";
|
21
|
+
let lStdErrorData = "";
|
22
|
+
return new Promise((pResolve, pReject) => {
|
23
|
+
lGit.stdout?.on("data", (pData) => {
|
24
|
+
lStdOutData = lStdOutData.concat(pData);
|
25
|
+
});
|
26
|
+
lGit.stderr?.on("data", (pData) => {
|
27
|
+
lStdErrorData = lStdErrorData.concat(pData);
|
28
|
+
});
|
29
|
+
lGit.on("close", (pCode) => {
|
30
|
+
if (pCode === 0) {
|
31
|
+
pResolve(stringifyOutStream(lStdOutData));
|
32
|
+
}
|
33
|
+
else {
|
34
|
+
pReject(new Error(pErrorMap[pCode ?? 0] ||
|
35
|
+
`internal git error: ${pCode} (${stringifyOutStream(lStdErrorData)})`));
|
36
|
+
}
|
37
|
+
});
|
38
|
+
lGit.on("error", (pError) => {
|
39
|
+
if (pError?.code === "ENOENT") {
|
40
|
+
pReject(new Error("git executable not found"));
|
41
|
+
}
|
42
|
+
else {
|
43
|
+
pReject(new Error(`internal spawn error: ${pError}`));
|
44
|
+
}
|
45
|
+
});
|
46
|
+
});
|
38
47
|
}
|
39
48
|
/**
|
40
49
|
* @throws {Error}
|
41
50
|
*/
|
42
|
-
export function
|
51
|
+
export async function getStatusShort(pSpawnFunction = spawn) {
|
43
52
|
const lErrorMap = {
|
44
53
|
129: `'${process.cwd()}' does not seem to be a git repository`,
|
45
54
|
};
|
46
|
-
|
55
|
+
const lResult = await getGitResult(["status", "--porcelain"], lErrorMap, pSpawnFunction);
|
56
|
+
return lResult;
|
47
57
|
}
|
48
58
|
/**
|
49
59
|
*
|
50
60
|
* @throws {Error}
|
51
61
|
*/
|
52
|
-
export function
|
62
|
+
export async function getDiffLines(pOldRevision, pNewRevision, pSpawnFunction = spawn) {
|
53
63
|
const lErrorMap = {
|
54
64
|
128: `revision '${pOldRevision}' ${pNewRevision ? `(or '${pNewRevision}') ` : ""}unknown`,
|
55
65
|
129: `'${process.cwd()}' does not seem to be a git repository`,
|
56
66
|
};
|
57
|
-
|
67
|
+
const lResult = await getGitResult(pNewRevision
|
58
68
|
? ["diff", pOldRevision, pNewRevision, "--name-status"]
|
59
69
|
: ["diff", pOldRevision, "--name-status"], lErrorMap, pSpawnFunction);
|
70
|
+
return lResult;
|
60
71
|
}
|
61
|
-
export function
|
72
|
+
export async function getSHA(pSpawnFunction = spawn) {
|
62
73
|
const lSha1Length = 40;
|
63
|
-
|
74
|
+
const lResult = await getGitResult(["rev-parse", "HEAD"], {}, pSpawnFunction);
|
75
|
+
return lResult.slice(0, lSha1Length);
|
64
76
|
}
|
package/dist/esm/main.js
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
import { convertDiffLines, convertStatusLines, } from "./convert-to-change-object.js";
|
2
|
-
import { getDiffLinesSync, getSHASync, getStatusShortSync, } from "./git-primitives.js";
|
2
|
+
import { getDiffLinesSync, getSHASync, getStatusShortSync, } from "./git-primitives-sync.js";
|
3
3
|
import format from "./formatters/format.js";
|
4
|
+
import { getDiffLines, getStatusShort, getSHA } from "./git-primitives.js";
|
4
5
|
export function listSync(pOldRevision, pNewRevision, pOptions) {
|
5
6
|
const lOldRevision = pOldRevision || getSHASync();
|
6
7
|
const lOptions = pOptions || {};
|
@@ -10,4 +11,18 @@ export function listSync(pOldRevision, pNewRevision, pOptions) {
|
|
10
11
|
}
|
11
12
|
return format(lChanges, lOptions.outputType);
|
12
13
|
}
|
13
|
-
export
|
14
|
+
export async function list(pOldRevision, pNewRevision, pOptions) {
|
15
|
+
const lOldRevision = pOldRevision || (await getSHA());
|
16
|
+
const lOptions = pOptions || {};
|
17
|
+
const [lDiffLines, lStatusLines] = await Promise.all([
|
18
|
+
getDiffLines(lOldRevision, pNewRevision),
|
19
|
+
lOptions.trackedOnly ? "" : getStatusShort(),
|
20
|
+
]);
|
21
|
+
let lChanges = convertDiffLines(lDiffLines);
|
22
|
+
if (!lOptions.trackedOnly) {
|
23
|
+
lChanges = lChanges.concat(convertStatusLines(lStatusLines).filter(({ changeType }) => changeType === "untracked"));
|
24
|
+
}
|
25
|
+
return format(lChanges, lOptions.outputType);
|
26
|
+
}
|
27
|
+
export { getSHASync } from "./git-primitives-sync.js";
|
28
|
+
export { getSHA } from "./git-primitives.js";
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "watskeburt",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.11.0",
|
4
4
|
"description": "List files changed since a git revision",
|
5
5
|
"keywords": [
|
6
6
|
"git",
|
@@ -44,16 +44,16 @@
|
|
44
44
|
"README.md"
|
45
45
|
],
|
46
46
|
"dependencies": {
|
47
|
-
"commander": "10.0.
|
47
|
+
"commander": "10.0.1"
|
48
48
|
},
|
49
49
|
"devDependencies": {
|
50
50
|
"@types/mocha": "10.0.1",
|
51
|
-
"@types/node": "18.
|
52
|
-
"@typescript-eslint/eslint-plugin": "5.
|
51
|
+
"@types/node": "18.16.2",
|
52
|
+
"@typescript-eslint/eslint-plugin": "5.59.1",
|
53
53
|
"c8": "7.13.0",
|
54
|
-
"dependency-cruiser": "13.0.0-beta-
|
55
|
-
"esbuild": "0.17.
|
56
|
-
"eslint": "8.
|
54
|
+
"dependency-cruiser": "13.0.0-beta-5",
|
55
|
+
"esbuild": "0.17.18",
|
56
|
+
"eslint": "8.39.0",
|
57
57
|
"eslint-config-moving-meadow": "4.0.2",
|
58
58
|
"eslint-config-prettier": "8.8.0",
|
59
59
|
"eslint-plugin-budapestian": "5.0.1",
|
@@ -65,7 +65,7 @@
|
|
65
65
|
"eslint-plugin-unicorn": "46.0.0",
|
66
66
|
"mocha": "10.2.0",
|
67
67
|
"npm-run-all": "4.1.5",
|
68
|
-
"prettier": "2.8.
|
68
|
+
"prettier": "2.8.8",
|
69
69
|
"ts-node": "10.9.1",
|
70
70
|
"typescript": "5.0.4",
|
71
71
|
"upem": "7.3.2"
|
package/types/watskeburt.d.ts
CHANGED
@@ -62,9 +62,34 @@ export function listSync(
|
|
62
62
|
pOptions?: IOptions
|
63
63
|
): IChange[] | string;
|
64
64
|
|
65
|
+
/**
|
66
|
+
* returns a list of files changed since pOldRevision.
|
67
|
+
*
|
68
|
+
* @param pOldRevision The revision against which to compare. E.g. a commit-hash,
|
69
|
+
* a branch or a tag. When not passed defaults to the _current_
|
70
|
+
* commit hash (if there's any)
|
71
|
+
* @param pNewRevision Newer revision against which to compare. Leave out or pass
|
72
|
+
* null when you want to compare against the working tree
|
73
|
+
* @param pOptions Options that influence how the changes are returned and that
|
74
|
+
* filter what is returned and
|
75
|
+
* @throws {Error}
|
76
|
+
*/
|
77
|
+
export function list(
|
78
|
+
pOldRevision?: string,
|
79
|
+
pNewRevision?: string,
|
80
|
+
pOptions?: IOptions
|
81
|
+
): Promise<IChange[] | string>;
|
82
|
+
|
65
83
|
/**
|
66
84
|
* Returns the SHA1 of the current HEAD
|
67
85
|
*
|
68
86
|
* @throws {Error}
|
69
87
|
*/
|
70
88
|
export function getSHASync(): string;
|
89
|
+
|
90
|
+
/**
|
91
|
+
* Returns the SHA1 of the current HEAD
|
92
|
+
*
|
93
|
+
* @throws {Error}
|
94
|
+
*/
|
95
|
+
export function getSHA(): Promise<string>;
|