watskeburt 0.2.0 → 0.3.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/README.md +66 -23
- package/dist/cjs-bundle.js +1 -1
- package/package.json +60 -20
- package/src/.eslintrc.json +47 -0
- package/src/cli.mjs +8 -5
- package/src/convert-to-change-object.mjs +10 -6
- package/src/formatters/format.mjs +1 -1
- package/src/formatters/json.mjs +2 -1
- package/src/formatters/regex.mjs +13 -2
- package/src/git-primitives.mjs +88 -0
- package/src/main.mjs +9 -16
- package/src/version.mjs +1 -0
- package/types/watskeburt.d.ts +43 -0
- package/src/get-diff-lines.mjs +0 -51
package/README.md
CHANGED
@@ -1,45 +1,88 @@
|
|
1
1
|
# watskeburt
|
2
2
|
|
3
|
-
get git changed files & their statuses since _any
|
3
|
+
get git changed files & their statuses since _any revision_
|
4
4
|
|
5
5
|
## what's this do?
|
6
6
|
|
7
7
|
A micro-lib to retrieve an array of file names that were changed (added,
|
8
|
-
modified, renamed, deleted, ...) since the
|
8
|
+
modified, renamed, deleted, ...) since the revision it got passed. Also
|
9
|
+
sports a cli for use outside of JavaScript c.s.
|
9
10
|
|
10
11
|
- :warning: in the process of getting 'production ready'. It's automatically
|
11
12
|
tested + it's using itself - but a bunch of static analysis and a bit of
|
12
13
|
automation still needs be added.
|
13
|
-
- Interface is stable-ish, but can can change until 1.0.0 is published
|
14
|
+
- :warning: Interface is stable-ish, but can can change until 1.0.0 is published
|
15
|
+
- :warning: expect some rough edges for e.g. error scenarios
|
14
16
|
|
15
|
-
##
|
17
|
+
## why?
|
16
18
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
},
|
26
|
-
{ "name": "src/not-tracked-yet.mjs", "changeType": "untracked" }
|
27
|
-
// ...
|
28
|
-
]
|
29
|
-
```
|
19
|
+
Useful primitives to support e.g. auto-documenting pull requests, or to save
|
20
|
+
processing power by only doing static analysis only over stuff that is changed.
|
21
|
+
|
22
|
+
There are a few packages like these like this on npm, but it seems they've
|
23
|
+
fallen out of maintenance. More generic packages don't get plagued by this
|
24
|
+
but for just this simple usage they're a bit overkill.
|
25
|
+
|
26
|
+
## usage
|
30
27
|
|
31
|
-
|
28
|
+
### :shell: cli
|
32
29
|
|
33
30
|
For now there's also a simple command line interface
|
34
31
|
|
32
|
+
```shell
|
33
|
+
# list all JavaScript-ish files changed since main in a regular expression
|
34
|
+
$ npx watskeburt main
|
35
|
+
^(src/cli.mjs|src/formatters/regex.mjs|src/version.mjs)$
|
35
36
|
```
|
36
|
-
Usage: watskeburt [options] <reference>
|
37
37
|
|
38
|
-
|
38
|
+
By default this returns a regex that contains all changed files that could be
|
39
|
+
source files in the JavaScript ecosystem (.js, .mjs, .ts, .tsx ...) that can
|
40
|
+
be used in e.g. the `--focus` filter of dependency-cruiser:
|
41
|
+
|
42
|
+
```
|
43
|
+
Usage: cli [options] <revision>
|
44
|
+
|
45
|
+
lists files & their statuses since <revision>
|
39
46
|
|
40
47
|
Options:
|
41
|
-
|
42
|
-
|
43
|
-
|
48
|
+
-V, --version output the version number
|
49
|
+
-T, --output-type <type> json,regex (default: "regex")
|
50
|
+
--tracked-only only take tracked files into account (default: false)
|
51
|
+
-h, --help display help for command
|
52
|
+
|
53
|
+
```
|
44
54
|
|
55
|
+
### :scroll: API
|
56
|
+
|
57
|
+
```javascript
|
58
|
+
// const { list } = require('watskeburt'); // will work in commonjs contexts as well
|
59
|
+
import { list, getSHA } from "watskeburt";
|
60
|
+
|
61
|
+
// print the SHA1 of the current HEAD
|
62
|
+
console.log(getSHA());
|
63
|
+
|
64
|
+
// list all files that differ between 'main' and
|
65
|
+
/** @type {import('watskeburt').IChange[]} */
|
66
|
+
const lChangedFiles = list("main");
|
45
67
|
```
|
68
|
+
|
69
|
+
An array of changes looks something like this:
|
70
|
+
|
71
|
+
```javascript
|
72
|
+
[
|
73
|
+
{ name: "doc/cli.md", changeType: "modified" },
|
74
|
+
{
|
75
|
+
name: "test/thing.spec.mjs",
|
76
|
+
changeType: "renamed",
|
77
|
+
oldName: "test/old-thing.spec.mjs",
|
78
|
+
similarity: 66,
|
79
|
+
},
|
80
|
+
{ name: "src/not-tracked-yet.mjs", changeType: "untracked" },
|
81
|
+
];
|
82
|
+
```
|
83
|
+
|
84
|
+
## 🇳🇱 'watskeburt'??
|
85
|
+
|
86
|
+
_watskeburt_ is a fast pronunciation of the Dutch sentence "Wat is er gebeurd?"
|
87
|
+
(What has happened?), as well as the title of a song by the Dutch hip hop group
|
88
|
+
"De Jeugd van Tegenwoordig".
|
package/dist/cjs-bundle.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
var
|
1
|
+
var i=Object.defineProperty;var y=Object.getOwnPropertyDescriptor;var w=Object.getOwnPropertyNames;var x=Object.prototype.hasOwnProperty;var E=(e,t)=>{for(var n in t)i(e,n,{get:t[n],enumerable:!0})},C=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of w(t))!x.call(e,o)&&o!==n&&i(e,o,{get:()=>t[o],enumerable:!(r=y(t,o))||r.enumerable});return e};var A=e=>C(i({},"__esModule",{value:!0}),e);var M={};E(M,{getSHA:()=>B,list:()=>j});module.exports=A(M);var u=require("os"),_=/^(?<changeType>[ACDMRTUXB])(?<similarity>[0-9]{3})?[ \t]+(?<name>[^ \t]+)[ \t]*(?<newName>[^ \t]+)?$/,D=/^(?<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 s(e){return R[e]||"unknown"}function L(e){let t=e.match(D),n={};if(t){let r=s(t.groups.stagedChangeType),o=s(t.groups.unStagedChangeType);n.changeType=r==="unmodified"?o:r,t.groups.newName?(n.name=t.groups.newName,n.oldName=t.groups.name):n.name=t.groups.name}return n}function U(e){let t=e.match(_),n={};return t&&(n.changeType=s(t.groups.changeType),t.groups.similarity&&(n.similarity=Number.parseInt(t.groups.similarity,10)),t.groups.newName?(n.name=t.groups.newName,n.oldName=t.groups.name):n.name=t.groups.name),n}function l(e){return e.split(u.EOL).filter(Boolean).map(L).filter(({changeType:t})=>Boolean(t))}function g(e){return e.split(u.EOL).filter(Boolean).map(U).filter(({changeType:t})=>Boolean(t))}var a=require("child_process");function d(e){return e instanceof Buffer?e.toString("utf8"):e}function O(e){throw e.code==="ENOENT"?new Error("git executable not found"):new Error(`internal spawn error: ${e}`)}function c(e,t,n){let r=n("git",e,{cwd:process.cwd(),env:process.env});if(r.error&&O(r.error),r.status===0)return d(r.stdout);throw new Error(t[r.status]||`internal git error: ${r.status} (${d(r.stderr)})`)}function T(e=a.spawnSync){let t={129:`'${process.cwd()}' does not seem to be a git repository`};return c(["status","--porcelain"],t,e)}function h(e,t=a.spawnSync){let n={128:`revision '${e}' unknown `,129:`'${process.cwd()}' does not seem to be a git repository`};return c(["diff",e,"--name-status"],n,t)}function S(e=a.spawnSync){return c(["rev-parse","HEAD"],{},e).slice(0,40)}var N=require("path");function f(e,t=[".js",".jsx",".mjs",".cjs",".ts",".tsx",".vue",".vuex",".json"],n=["modified","added","renamed","copied","untracked"]){return`^(${e.filter(o=>n.includes(o.changeType)).map(({name:o})=>o).filter(o=>t.includes((0,N.extname)(o))).join("|")})$`}function p(e){return JSON.stringify(e,null,2)}var v={regex:f,json:p,object:e=>e},$="object";function m(e,t){return v[t||$](e)}function j(e,t){let n=g(h(e)),r=t||{};return r.trackedOnly||(n=n.concat(l(T()).filter(({changeType:o})=>o==="untracked"))),m(n,r.outputType)}function B(){return S()}0&&(module.exports={getSHA,list});
|
package/package.json
CHANGED
@@ -1,10 +1,28 @@
|
|
1
1
|
{
|
2
2
|
"name": "watskeburt",
|
3
|
-
"version": "0.
|
4
|
-
"description": "
|
3
|
+
"version": "0.3.0",
|
4
|
+
"description": "List files changed since a git revision",
|
5
|
+
"keywords": [
|
6
|
+
"git",
|
7
|
+
"diff"
|
8
|
+
],
|
9
|
+
"homepage": "https://github.com/sverweij/watskeburt",
|
10
|
+
"repository": {
|
11
|
+
"type": "git",
|
12
|
+
"url": "git+https://github.com/sverweij/watskeburt"
|
13
|
+
},
|
14
|
+
"bugs": {
|
15
|
+
"url": "https://github.com/sverweij/watskeburt/issues"
|
16
|
+
},
|
17
|
+
"author": {
|
18
|
+
"name": "Sander Verweij",
|
19
|
+
"url": "https://sverweij.github.io"
|
20
|
+
},
|
21
|
+
"license": "MIT",
|
5
22
|
"bin": "src/cli.mjs",
|
6
23
|
"main": "dist/cjs-bundle.js",
|
7
24
|
"module": "src/main.mjs",
|
25
|
+
"sideEffects": false,
|
8
26
|
"exports": {
|
9
27
|
".": [
|
10
28
|
{
|
@@ -25,8 +43,34 @@
|
|
25
43
|
"package.json",
|
26
44
|
"README.md"
|
27
45
|
],
|
46
|
+
"dependencies": {
|
47
|
+
"commander": "^9.3.0"
|
48
|
+
},
|
49
|
+
"devDependencies": {
|
50
|
+
"@typescript-eslint/eslint-plugin": "^5.30.5",
|
51
|
+
"c8": "^7.11.3",
|
52
|
+
"dependency-cruiser": "^11.11.0",
|
53
|
+
"esbuild": "^0.14.48",
|
54
|
+
"eslint": "^8.19.0",
|
55
|
+
"eslint-config-moving-meadow": "^3.0.0",
|
56
|
+
"eslint-config-prettier": "^8.5.0",
|
57
|
+
"eslint-plugin-budapestian": "^4.0.0",
|
58
|
+
"eslint-plugin-import": "^2.26.0",
|
59
|
+
"eslint-plugin-mocha": "^10.0.5",
|
60
|
+
"eslint-plugin-node": "^11.1.0",
|
61
|
+
"eslint-plugin-security": "^1.5.0",
|
62
|
+
"eslint-plugin-unicorn": "^43.0.1",
|
63
|
+
"mocha": "^10.0.0",
|
64
|
+
"npm-run-all": "^4.1.5",
|
65
|
+
"prettier": "^2.7.1"
|
66
|
+
},
|
67
|
+
"engines": {
|
68
|
+
"node": "^12.20||^14||>=16"
|
69
|
+
},
|
28
70
|
"scripts": {
|
29
|
-
"build": "
|
71
|
+
"build": "npm-run-all --sequential build:version build:dist",
|
72
|
+
"build:version": "node tools/get-version.mjs > src/version.mjs",
|
73
|
+
"build:dist": "esbuild src/main.mjs --format=cjs --target=node12 --platform=node --bundle --global-name=wkbtcjs --minify --outfile=dist/cjs-bundle.js",
|
30
74
|
"clean": "rm -rf dist",
|
31
75
|
"test": "mocha \"src/**/*.spec.mjs\"",
|
32
76
|
"test:cover": "c8 --check-coverage --statements 100 --branches 100 --functions 100 --lines 100 --exclude \"**/*.spec.mjs\" --reporter text-summary --reporter html --reporter json-summary npm test",
|
@@ -39,23 +83,19 @@
|
|
39
83
|
"depcruise:html": "depcruise src --progress --config --output-type err-html --output-to dependency-violation-report.html",
|
40
84
|
"depcruise:text": "depcruise src --progress --config --output-type text",
|
41
85
|
"depcruise:focus": "depcruise src --progress --config --output-type text --focus",
|
86
|
+
"lint": "npm-run-all --parallel --aggregate-output lint:format lint:eslint",
|
87
|
+
"lint:fix": "npm-run-all --parallel --aggregate-output lint:format:fix lint:eslint:fix",
|
88
|
+
"lint:eslint": "eslint src --cache --cache-location node_modules/.cache/eslint/",
|
89
|
+
"lint:eslint:fix": "eslint src tools --fix --cache --cache-location node_modules/.cache/eslint/",
|
90
|
+
"lint:format": "prettier --check \"{src,tools}/**/*.mjs\" \"types/**/*.ts\" \"*.{json,yml,md,js}\"",
|
91
|
+
"lint:format:fix": "prettier --loglevel warn --write \"{src,tools}/**/*.mjs\" \"types/**/*.ts\" \"*.{json,yml,md,js}\"",
|
42
92
|
"scm:stage": "git add .",
|
43
|
-
"version": "run-
|
44
|
-
},
|
45
|
-
"keywords": [
|
46
|
-
"git",
|
47
|
-
"diff"
|
48
|
-
],
|
49
|
-
"author": "Sander Verweij (https://sverweij.github.io/)",
|
50
|
-
"license": "MIT",
|
51
|
-
"devDependencies": {
|
52
|
-
"c8": "^7.11.3",
|
53
|
-
"dependency-cruiser": "^11.11.0",
|
54
|
-
"esbuild": "^0.14.48",
|
55
|
-
"mocha": "^10.0.0",
|
56
|
-
"npm-run-all": "^4.1.5"
|
93
|
+
"version": "npm-run-all --sequential clean build lint depcruise:graph scm:stage"
|
57
94
|
},
|
58
|
-
"
|
59
|
-
"
|
60
|
-
|
95
|
+
"eslintIgnore": [
|
96
|
+
"coverage",
|
97
|
+
"docs",
|
98
|
+
"dist",
|
99
|
+
"node_modules"
|
100
|
+
]
|
61
101
|
}
|
@@ -0,0 +1,47 @@
|
|
1
|
+
{
|
2
|
+
"root": true,
|
3
|
+
"extends": ["moving-meadow"],
|
4
|
+
"overrides": [
|
5
|
+
{
|
6
|
+
"files": ["**/*.mjs"],
|
7
|
+
"rules": {
|
8
|
+
"unicorn/no-null": "off",
|
9
|
+
"unicorn/prefer-spread": "off",
|
10
|
+
"node/no-unsupported-features/es-syntax": "off",
|
11
|
+
"import/no-relative-parent-imports": "off",
|
12
|
+
"sort-imports": "off",
|
13
|
+
"unicorn/prefer-node-protocol": "error",
|
14
|
+
"unicorn/prefer-module": "error"
|
15
|
+
},
|
16
|
+
"parserOptions": {
|
17
|
+
"ecmaVersion": "latest"
|
18
|
+
}
|
19
|
+
},
|
20
|
+
{
|
21
|
+
"files": ["**/*.spec.mjs"],
|
22
|
+
"env": {
|
23
|
+
"mocha": true
|
24
|
+
},
|
25
|
+
"rules": {
|
26
|
+
"no-magic-numbers": "off",
|
27
|
+
"security/detect-non-literal-require": "off",
|
28
|
+
"security/detect-non-literal-fs-filename": "off",
|
29
|
+
"max-lines-per-function": "off",
|
30
|
+
"max-lines": "off",
|
31
|
+
"no-null": "off"
|
32
|
+
}
|
33
|
+
},
|
34
|
+
{
|
35
|
+
"files": ["types/*.ts"],
|
36
|
+
"plugins": ["@typescript-eslint"],
|
37
|
+
"extends": ["plugin:@typescript-eslint/recommended"],
|
38
|
+
"parser": "@typescript-eslint/parser",
|
39
|
+
"parserOptions": {
|
40
|
+
"ecmaVersion": "latest"
|
41
|
+
},
|
42
|
+
"rules": {
|
43
|
+
"node/no-unsupported-features/es-syntax": "off"
|
44
|
+
}
|
45
|
+
}
|
46
|
+
]
|
47
|
+
}
|
package/src/cli.mjs
CHANGED
@@ -1,20 +1,23 @@
|
|
1
1
|
#!/usr/bin/env node
|
2
|
+
/* eslint-disable no-console */
|
2
3
|
|
3
4
|
import { program } from "commander";
|
4
|
-
import {
|
5
|
+
import { list } from "./main.mjs";
|
6
|
+
import { VERSION } from "./version.mjs";
|
5
7
|
|
6
8
|
program
|
7
|
-
.description("lists files since <
|
9
|
+
.description("lists files & their statuses since <revision>")
|
10
|
+
.version(VERSION)
|
8
11
|
.option("-T, --output-type <type>", "json,regex", "regex")
|
9
12
|
.option("--tracked-only", "only take tracked files into account", false)
|
10
|
-
.arguments("<
|
13
|
+
.arguments("<revision>")
|
11
14
|
.parse(process.argv);
|
12
15
|
|
13
16
|
if (program.args[0]) {
|
14
17
|
try {
|
15
|
-
console.log(
|
18
|
+
console.log(list(program.args[0], program.opts()));
|
16
19
|
} catch (pError) {
|
17
|
-
console.error(pError);
|
20
|
+
console.error(`ERROR: ${pError.message}`);
|
18
21
|
}
|
19
22
|
} else {
|
20
23
|
program.help();
|
@@ -1,10 +1,13 @@
|
|
1
|
+
// the security (and unicorn) plugins don't seem to detect named caption
|
2
|
+
// groups very well - false-flagging below regular expressions to be susceptible
|
3
|
+
// to redos attacks.
|
4
|
+
/* eslint-disable unicorn/no-unsafe-regex, security/detect-unsafe-regex */
|
1
5
|
import { EOL } from "node:os";
|
2
|
-
|
3
|
-
|
4
|
-
)
|
5
|
-
const DIFF_SHORT_STATUS_LINE_PATTERN =
|
6
|
-
|
7
|
-
);
|
6
|
+
|
7
|
+
const DIFF_NAME_STATUS_LINE_PATTERN =
|
8
|
+
/^(?<changeType>[ACDMRTUXB])(?<similarity>[0-9]{3})?[ \t]+(?<name>[^ \t]+)[ \t]*(?<newName>[^ \t]+)?$/;
|
9
|
+
const DIFF_SHORT_STATUS_LINE_PATTERN =
|
10
|
+
/^(?<stagedChangeType>[ ACDMRTUXB?!])(?<unStagedChangeType>[ ACDMRTUXB?!])[ \t]+(?<name>[^ \t]+)(( -> )(?<newName>[^ \t]+))?$/;
|
8
11
|
|
9
12
|
const CHANGE_CHAR_2_CHANGE_TYPE = {
|
10
13
|
A: "added",
|
@@ -22,6 +25,7 @@ const CHANGE_CHAR_2_CHANGE_TYPE = {
|
|
22
25
|
};
|
23
26
|
|
24
27
|
function changeChar2ChangeType(pChar) {
|
28
|
+
// eslint-disable-next-line security/detect-object-injection
|
25
29
|
return CHANGE_CHAR_2_CHANGE_TYPE[pChar] || "unknown";
|
26
30
|
}
|
27
31
|
|
package/src/formatters/json.mjs
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
+
const INDENT = 2;
|
1
2
|
/**
|
2
3
|
*
|
3
4
|
* @param {import('../types/watskeburt').IChange[]} pChanges
|
4
5
|
* @return {string}
|
5
6
|
*/
|
6
7
|
export default function formatToJSON(pChanges) {
|
7
|
-
return JSON.stringify(pChanges, null,
|
8
|
+
return JSON.stringify(pChanges, null, INDENT);
|
8
9
|
}
|
package/src/formatters/regex.mjs
CHANGED
@@ -9,13 +9,24 @@ import { extname } from "node:path";
|
|
9
9
|
*/
|
10
10
|
export default function formatToRegex(
|
11
11
|
pChanges,
|
12
|
-
pExtensions = [
|
12
|
+
pExtensions = [
|
13
|
+
".js",
|
14
|
+
".jsx",
|
15
|
+
".mjs",
|
16
|
+
".cjs",
|
17
|
+
".ts",
|
18
|
+
".tsx",
|
19
|
+
".vue",
|
20
|
+
".vuex",
|
21
|
+
".json",
|
22
|
+
],
|
13
23
|
pChangeTypes = ["modified", "added", "renamed", "copied", "untracked"]
|
14
24
|
) {
|
15
25
|
const lChanges = pChanges
|
16
26
|
.filter((pChange) => pChangeTypes.includes(pChange.changeType))
|
17
27
|
.map(
|
18
|
-
|
28
|
+
// .replace(/\./g, "\\\\.")
|
29
|
+
({ name }) => name
|
19
30
|
)
|
20
31
|
.filter((pName) => pExtensions.includes(extname(pName)))
|
21
32
|
.join("|");
|
@@ -0,0 +1,88 @@
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
2
|
+
|
3
|
+
function stringifyOutStream(pError) {
|
4
|
+
if (pError instanceof Buffer) {
|
5
|
+
return pError.toString("utf8");
|
6
|
+
} else {
|
7
|
+
return pError;
|
8
|
+
}
|
9
|
+
}
|
10
|
+
|
11
|
+
function throwSpawnError(pError) {
|
12
|
+
if (pError.code === "ENOENT") {
|
13
|
+
throw new Error("git executable not found");
|
14
|
+
} else {
|
15
|
+
throw new Error(`internal spawn error: ${pError}`);
|
16
|
+
}
|
17
|
+
}
|
18
|
+
|
19
|
+
/**
|
20
|
+
*
|
21
|
+
* @param {string[]} pArguments
|
22
|
+
* @return {string}
|
23
|
+
* @throws {Error}
|
24
|
+
*/
|
25
|
+
function getGitResult(pArguments, pErrorMap, pSpawnFunction) {
|
26
|
+
const lGitResult = pSpawnFunction("git", pArguments, {
|
27
|
+
cwd: process.cwd(),
|
28
|
+
// eslint-disable-next-line node/no-process-env
|
29
|
+
env: process.env,
|
30
|
+
});
|
31
|
+
|
32
|
+
if (lGitResult.error) {
|
33
|
+
throwSpawnError(lGitResult.error);
|
34
|
+
}
|
35
|
+
|
36
|
+
if (lGitResult.status === 0) {
|
37
|
+
return stringifyOutStream(lGitResult.stdout);
|
38
|
+
} else {
|
39
|
+
throw new Error(
|
40
|
+
pErrorMap[lGitResult.status] ||
|
41
|
+
`internal git error: ${lGitResult.status} (${stringifyOutStream(
|
42
|
+
lGitResult.stderr
|
43
|
+
)})`
|
44
|
+
);
|
45
|
+
}
|
46
|
+
}
|
47
|
+
|
48
|
+
/**
|
49
|
+
*
|
50
|
+
* @returns {string}
|
51
|
+
* @throws {Error}
|
52
|
+
*/
|
53
|
+
export function getStatusShort(pSpawnFunction = spawnSync) {
|
54
|
+
const lErrorMap = {
|
55
|
+
129: `'${process.cwd()}' does not seem to be a git repository`,
|
56
|
+
};
|
57
|
+
return getGitResult(["status", "--porcelain"], lErrorMap, pSpawnFunction);
|
58
|
+
}
|
59
|
+
|
60
|
+
/**
|
61
|
+
*
|
62
|
+
* @param {string} pOldRevision the target to compare against (e.g. branch name, commit, tag etc)
|
63
|
+
* @return {string}
|
64
|
+
* @throws {Error}
|
65
|
+
*/
|
66
|
+
export function getDiffLines(pOldRevision, pSpawnFunction = spawnSync) {
|
67
|
+
const lErrorMap = {
|
68
|
+
128: `revision '${pOldRevision}' unknown `,
|
69
|
+
129: `'${process.cwd()}' does not seem to be a git repository`,
|
70
|
+
};
|
71
|
+
return getGitResult(
|
72
|
+
["diff", pOldRevision, "--name-status"],
|
73
|
+
lErrorMap,
|
74
|
+
pSpawnFunction
|
75
|
+
);
|
76
|
+
}
|
77
|
+
/**
|
78
|
+
*
|
79
|
+
* @returns {string}
|
80
|
+
*/
|
81
|
+
export function getSHA1(pSpawnFunction = spawnSync) {
|
82
|
+
const lSha1Length = 40;
|
83
|
+
|
84
|
+
return getGitResult(["rev-parse", "HEAD"], {}, pSpawnFunction).slice(
|
85
|
+
0,
|
86
|
+
lSha1Length
|
87
|
+
);
|
88
|
+
}
|
package/src/main.mjs
CHANGED
@@ -2,24 +2,12 @@ import {
|
|
2
2
|
convertDiffLines,
|
3
3
|
convertStatusLines,
|
4
4
|
} from "./convert-to-change-object.mjs";
|
5
|
-
import { getDiffLines, getStatusShort } from "./
|
5
|
+
import { getDiffLines, getSHA1, getStatusShort } from "./git-primitives.mjs";
|
6
6
|
import format from "./formatters/format.mjs";
|
7
7
|
|
8
|
-
/**
|
9
|
-
|
10
|
-
|
11
|
-
* you can
|
12
|
-
* - influence whether you want to have the output as an array of
|
13
|
-
* IChange-s or one of the other output formats (outputType)
|
14
|
-
* - tell whether you want to take untracked files into account as
|
15
|
-
* well (by setting trackedOnly to false)
|
16
|
-
*
|
17
|
-
* @param {string} pOldThing reference to a commit, branch, tag, ...
|
18
|
-
* @param {import("../types/watskeburt.js").IOptions} pOptions
|
19
|
-
* @returns {string|import("../types/watskeburt.js").IChange[]}
|
20
|
-
*/
|
21
|
-
export function convert(pOldThing, pOptions) {
|
22
|
-
let lChanges = convertDiffLines(getDiffLines(pOldThing));
|
8
|
+
/** @type {import("../types/watskeburt.js").list} */
|
9
|
+
export function list(pOldRevision, pOptions) {
|
10
|
+
let lChanges = convertDiffLines(getDiffLines(pOldRevision));
|
23
11
|
const lOptions = pOptions || {};
|
24
12
|
|
25
13
|
if (!lOptions.trackedOnly) {
|
@@ -31,3 +19,8 @@ export function convert(pOldThing, pOptions) {
|
|
31
19
|
}
|
32
20
|
return format(lChanges, lOptions.outputType);
|
33
21
|
}
|
22
|
+
|
23
|
+
/** @type {import("../types/watskeburt.js").getSHA} */
|
24
|
+
export function getSHA() {
|
25
|
+
return getSHA1();
|
26
|
+
}
|
package/src/version.mjs
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
export const VERSION = "0.3.0";
|
package/types/watskeburt.d.ts
CHANGED
@@ -13,15 +13,58 @@ export type changeTypeType =
|
|
13
13
|
| "ignored";
|
14
14
|
|
15
15
|
export interface IChange {
|
16
|
+
/**
|
17
|
+
* name of the file
|
18
|
+
*/
|
16
19
|
name: string;
|
20
|
+
/**
|
21
|
+
* how the file was changed
|
22
|
+
*/
|
17
23
|
changeType: changeTypeType;
|
24
|
+
/**
|
25
|
+
* if the file was renamed: the % of similarity (range: 0 - 100)
|
26
|
+
*/
|
18
27
|
similarity?: Number;
|
28
|
+
/**
|
29
|
+
* if the file was renamed: what the old file's name was
|
30
|
+
*/
|
19
31
|
oldName?: string;
|
20
32
|
}
|
21
33
|
|
22
34
|
export type outputTypeType = "regex" | "json" | "object";
|
23
35
|
|
24
36
|
export interface IOptions {
|
37
|
+
/**
|
38
|
+
* The type of output to deliver. Defaults to "object" - in which case
|
39
|
+
* the list function returns an IChange[] object
|
40
|
+
*/
|
25
41
|
outputType: outputTypeType;
|
42
|
+
/**
|
43
|
+
* When true _only_ takes already tracked files into account.
|
44
|
+
* When true also takes untracked files into account.
|
45
|
+
*
|
46
|
+
* Defaults to true.
|
47
|
+
*/
|
26
48
|
trackedOnly: boolean;
|
27
49
|
}
|
50
|
+
|
51
|
+
/**
|
52
|
+
* returns a list of files changed since pOldRevision.
|
53
|
+
*
|
54
|
+
* @param pOldRevision the revision against which to compare. E.g. a commit-hash,
|
55
|
+
* a branch or a tag.
|
56
|
+
* @param pOptions Options that influence how the changes are returned and that
|
57
|
+
* filter what is returned and
|
58
|
+
* @throws {Error}
|
59
|
+
*/
|
60
|
+
export function list(
|
61
|
+
pOldRevision: string,
|
62
|
+
pOptions: IOptions
|
63
|
+
): IChange[] | string;
|
64
|
+
|
65
|
+
/**
|
66
|
+
* Returns the SHA1 of the current HEAD
|
67
|
+
*
|
68
|
+
* @throws {Error}
|
69
|
+
*/
|
70
|
+
export function getSHA(): string;
|
package/src/get-diff-lines.mjs
DELETED
@@ -1,51 +0,0 @@
|
|
1
|
-
import { spawnSync } from "node:child_process";
|
2
|
-
|
3
|
-
function stringifyOutStream(pError) {
|
4
|
-
if (pError instanceof Buffer) {
|
5
|
-
return pError.toString("utf8");
|
6
|
-
} else {
|
7
|
-
return pError;
|
8
|
-
}
|
9
|
-
}
|
10
|
-
|
11
|
-
/**
|
12
|
-
*
|
13
|
-
* @param {string[]} pArguments
|
14
|
-
* @return {string}
|
15
|
-
* @throws {Error}
|
16
|
-
*/
|
17
|
-
function getGitResult(pArguments, pSpawnFunction) {
|
18
|
-
const lGitResult = pSpawnFunction("git", pArguments, {
|
19
|
-
cwd: process.cwd(),
|
20
|
-
env: process.env,
|
21
|
-
});
|
22
|
-
|
23
|
-
if (lGitResult.error) {
|
24
|
-
throw new Error(stringifyOutStream(lGitResult.error));
|
25
|
-
}
|
26
|
-
|
27
|
-
if (lGitResult.status === 0) {
|
28
|
-
return stringifyOutStream(lGitResult.stdout);
|
29
|
-
} else {
|
30
|
-
throw new Error(lGitResult.output);
|
31
|
-
}
|
32
|
-
}
|
33
|
-
|
34
|
-
/**
|
35
|
-
*
|
36
|
-
* @returns {string}
|
37
|
-
* @throws {Error}
|
38
|
-
*/
|
39
|
-
export function getStatusShort(pSpawnFunction = spawnSync) {
|
40
|
-
return getGitResult(["status", "--porcelain"], pSpawnFunction);
|
41
|
-
}
|
42
|
-
|
43
|
-
/**
|
44
|
-
*
|
45
|
-
* @param {string} pOldThing the target to compare against (e.g. branch name, commit, tag etc)
|
46
|
-
* @return {string}
|
47
|
-
* @throws {Error}
|
48
|
-
*/
|
49
|
-
export function getDiffLines(pOldThing, pSpawnFunction = spawnSync) {
|
50
|
-
return getGitResult(["diff", pOldThing, "--name-status"], pSpawnFunction);
|
51
|
-
}
|