watskeburt 2.0.5 → 4.0.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 +30 -36
- package/dist/cli.js +6 -6
- package/dist/format/format.js +9 -0
- package/dist/{formatters → format}/json.js +1 -1
- package/dist/{formatters → format}/regex.js +2 -2
- package/dist/main.js +8 -5
- package/dist/parse-diff-lines.js +4 -4
- package/dist/parse-status-lines.js +4 -2
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/types/watskeburt.d.ts +29 -48
- package/dist/formatters/format.js +0 -12
package/README.md
CHANGED
@@ -2,21 +2,6 @@
|
|
2
2
|
|
3
3
|
Get changed files & their statuses since any git _revision_
|
4
4
|
|
5
|
-
## what's this do?
|
6
|
-
|
7
|
-
A micro-lib to retrieve an array of file names that were changed since a
|
8
|
-
revision. Also sports a cli for use outside of JavaScript c.s.
|
9
|
-
|
10
|
-
## why?
|
11
|
-
|
12
|
-
I needed something simple and robust to support some upcoming features in
|
13
|
-
[dependency-cruiser](https://github.com/sverweij/dependency-cruiser) and to
|
14
|
-
run standalone to use _in combination_ with dependency-cruiser.
|
15
|
-
|
16
|
-
There are a few specialized packages like this on npm, but it seems they've
|
17
|
-
fallen out of maintenance. More generic packages are still maintained,
|
18
|
-
but for just this simple usage they're a bit overkill.
|
19
|
-
|
20
5
|
## :construction_worker: usage
|
21
6
|
|
22
7
|
### :scroll: API
|
@@ -30,20 +15,23 @@ console.log(await getSHA());
|
|
30
15
|
// list all files that differ between 'main' and the current revision (including
|
31
16
|
// files not staged for commit and files not under revision control)
|
32
17
|
/** @type {import('watskeburt').IChange[]} */
|
33
|
-
const lChangedFiles = await list("main");
|
18
|
+
const lChangedFiles = await list({ oldRevision: "main" });
|
34
19
|
|
35
20
|
// list all files that differ between 'v0.6.1' and 'v0.7.1' (by definition
|
36
21
|
// won't include files staged for commit and/ or not under revision control)
|
37
22
|
/** @type {import('watskeburt').IChange[]} */
|
38
|
-
const lChangedFiles = await list(
|
23
|
+
const lChangedFiles = await list({
|
24
|
+
oldRevision: "v0.6.1",
|
25
|
+
newRevision: "v0.7.1",
|
26
|
+
});
|
39
27
|
|
40
|
-
//
|
41
|
-
// (
|
42
|
-
// a revision and the working tree):
|
28
|
+
// list all files that differ between 'main' and the current revision
|
29
|
+
// (excluding files not staged for commit)
|
43
30
|
/** @type {import('watskeburt').IChange[]|string} */
|
44
|
-
const lChangedFiles = await list(
|
31
|
+
const lChangedFiles = await list({
|
32
|
+
oldRevision: "main",
|
45
33
|
trackedOnly: false, // when set to true leaves out files not under revision control
|
46
|
-
outputType: "
|
34
|
+
outputType: "json", // options: "object", "json" and "regex"
|
47
35
|
});
|
48
36
|
```
|
49
37
|
|
@@ -53,24 +41,23 @@ The array of changes this returns looks like this:
|
|
53
41
|
[
|
54
42
|
{
|
55
43
|
name: "doc/cli.md",
|
56
|
-
|
44
|
+
type: "modified",
|
57
45
|
},
|
58
46
|
{
|
59
47
|
name: "test/thing.spec.mjs",
|
60
|
-
|
48
|
+
type: "renamed",
|
61
49
|
oldName: "test/old-thing.spec.mjs",
|
62
50
|
},
|
63
51
|
{
|
64
52
|
name: "src/not-tracked-yet.mjs",
|
65
|
-
|
53
|
+
type: "untracked",
|
66
54
|
},
|
67
55
|
];
|
68
56
|
```
|
69
57
|
|
70
58
|
### :shell: cli
|
71
59
|
|
72
|
-
|
73
|
-
node >=18.11).
|
60
|
+
Works with node >=18.11
|
74
61
|
|
75
62
|
```shell
|
76
63
|
# list all JavaScript-ish files changed since main in a regular expression
|
@@ -78,19 +65,18 @@ $ npx watskeburt main
|
|
78
65
|
^(src/cli[.]mjs|src/formatters/regex[.]mjs|src/version[.]mjs)$
|
79
66
|
```
|
80
67
|
|
81
|
-
|
82
|
-
source files in the JavaScript ecosystem (.js, .mjs, .ts, .tsx ...)
|
83
|
-
be used in e.g.
|
68
|
+
This emits a regex that contains all changed files that could be
|
69
|
+
source files in the JavaScript ecosystem (.js, .mjs, .ts, .tsx ...). It can
|
70
|
+
be used in e.g. dependency-cruiser's `--focus` and `--reaches` filters.
|
84
71
|
|
85
|
-
The JSON output (
|
86
|
-
also contains other extensions.
|
72
|
+
The JSON output (= the array above, serialized) also contains other extensions.
|
87
73
|
|
88
74
|
```
|
89
75
|
Usage: watskeburt [options] [old-revision] [new-revision]
|
90
76
|
|
91
77
|
lists files & their statuses since [old-revision] or between [old-revision] and [new-revision].
|
92
78
|
|
93
|
-
-> When you don't pass a revision
|
79
|
+
-> When you don't pass a revision old-revision defaults to the current one.
|
94
80
|
|
95
81
|
Options:
|
96
82
|
-T, --outputType <type> what format to emit (choices: "json", "regex", default: "regex")
|
@@ -99,11 +85,19 @@ Options:
|
|
99
85
|
-h, --help display help for command
|
100
86
|
```
|
101
87
|
|
88
|
+
## why?
|
89
|
+
|
90
|
+
I needed something robust to support caching in
|
91
|
+
[dependency-cruiser](https://github.com/sverweij/dependency-cruiser) and to
|
92
|
+
run standalone to use _in combination_ with dependency-cruiser.
|
93
|
+
|
94
|
+
A few specialized packages like this existed, but they had fallen out of
|
95
|
+
maintenance. More generic packages still were maintained, but for my use
|
96
|
+
case they were overkill.
|
97
|
+
|
102
98
|
## 🇳🇱 what does 'watskeburt' mean?
|
103
99
|
|
104
100
|
Wazzup.
|
105
101
|
|
106
102
|
_watskeburt_ is a fast pronunciation of the Dutch "wat is er gebeurd?"
|
107
|
-
(_what has happened?_) or "wat er is gebeurd" (_what has happened_).
|
108
|
-
also the title of a song by the Dutch band "De Jeugd van Tegenwoordig"
|
109
|
-
(_Youth these days_).
|
103
|
+
(_what has happened?_) or "wat er is gebeurd" (_what has happened_).
|
package/dist/cli.js
CHANGED
@@ -6,7 +6,7 @@ const HELP_MESSAGE = `Usage: watskeburt [options] [old-revision] [new-revision]
|
|
6
6
|
|
7
7
|
lists files & their statuses since [old-revision] or between [old-revision] and [new-revision].
|
8
8
|
|
9
|
-
-> When you don't pass a revision
|
9
|
+
-> When you don't pass a revision old-revision defaults to the current one.
|
10
10
|
|
11
11
|
Options:
|
12
12
|
-T, --outputType <type> what format to emit (choices: "json", "regex", default: "regex")
|
@@ -36,11 +36,11 @@ export async function cli(
|
|
36
36
|
process.exitCode = pErrorExitCode;
|
37
37
|
return;
|
38
38
|
}
|
39
|
-
const lResult = await list(
|
40
|
-
lArguments.
|
41
|
-
lArguments.positionals[
|
42
|
-
lArguments.
|
43
|
-
);
|
39
|
+
const lResult = await list({
|
40
|
+
...lArguments.values,
|
41
|
+
oldRevision: lArguments.positionals[0],
|
42
|
+
newRevision: lArguments.positionals[1],
|
43
|
+
});
|
44
44
|
pOutStream.write(`${lResult}${EOL}`);
|
45
45
|
} catch (pError) {
|
46
46
|
pErrorStream.write(`${EOL}ERROR: ${pError.message}${EOL}${EOL}`);
|
@@ -0,0 +1,9 @@
|
|
1
|
+
import formatAsRegex from "./regex.js";
|
2
|
+
import formatAsJSON from "./json.js";
|
3
|
+
const OUTPUT_TYPE_TO_FUNCTION = new Map([
|
4
|
+
["regex", formatAsRegex],
|
5
|
+
["json", formatAsJSON],
|
6
|
+
]);
|
7
|
+
export function format(pChanges, pOutputType) {
|
8
|
+
return OUTPUT_TYPE_TO_FUNCTION.get(pOutputType)(pChanges);
|
9
|
+
}
|
@@ -25,7 +25,7 @@ const DEFAULT_CHANGE_TYPES = new Set([
|
|
25
25
|
"copied",
|
26
26
|
"untracked",
|
27
27
|
]);
|
28
|
-
export default function
|
28
|
+
export default function formatAsRegex(
|
29
29
|
pChanges,
|
30
30
|
pExtensions = DEFAULT_EXTENSIONS,
|
31
31
|
pChangeTypes = DEFAULT_CHANGE_TYPES,
|
@@ -33,7 +33,7 @@ export default function formatToRegex(
|
|
33
33
|
const lChanges = pChanges
|
34
34
|
.filter(
|
35
35
|
(pChange) =>
|
36
|
-
pChangeTypes.has(pChange.
|
36
|
+
pChangeTypes.has(pChange.type) &&
|
37
37
|
pExtensions.has(extname(pChange.name)),
|
38
38
|
)
|
39
39
|
.map(({ name }) => name.replace(/\\/g, "\\\\").replace(/\./g, "[.]"))
|
package/dist/main.js
CHANGED
@@ -1,22 +1,25 @@
|
|
1
1
|
import { parseDiffLines } from "./parse-diff-lines.js";
|
2
2
|
import { parseStatusLines } from "./parse-status-lines.js";
|
3
3
|
import * as primitives from "./git-primitives.js";
|
4
|
-
|
5
|
-
|
6
|
-
const lOldRevision = pOldRevision || (await primitives.getSHA());
|
4
|
+
export async function list(pOptions) {
|
5
|
+
const lOldRevision = pOptions?.oldRevision || (await primitives.getSHA());
|
7
6
|
const lOptions = pOptions || {};
|
8
7
|
const [lDiffLines, lStatusLines] = await Promise.all([
|
9
|
-
primitives.getDiffLines(lOldRevision,
|
8
|
+
primitives.getDiffLines(lOldRevision, pOptions?.newRevision),
|
10
9
|
!lOptions.trackedOnly ? primitives.getStatusShort() : "",
|
11
10
|
]);
|
12
11
|
let lChanges = parseDiffLines(lDiffLines);
|
13
12
|
if (!lOptions.trackedOnly) {
|
14
13
|
lChanges = lChanges.concat(
|
15
14
|
parseStatusLines(lStatusLines).filter(
|
16
|
-
({ changeType }) => changeType === "untracked",
|
15
|
+
({ type: changeType }) => changeType === "untracked",
|
17
16
|
),
|
18
17
|
);
|
19
18
|
}
|
19
|
+
if (!lOptions.outputType) {
|
20
|
+
return lChanges;
|
21
|
+
}
|
22
|
+
const { format } = await import("./format/format.js");
|
20
23
|
return format(lChanges, lOptions.outputType);
|
21
24
|
}
|
22
25
|
export function getSHA() {
|
package/dist/parse-diff-lines.js
CHANGED
@@ -7,15 +7,15 @@ export function parseDiffLines(pString) {
|
|
7
7
|
.split(EOL)
|
8
8
|
.filter(Boolean)
|
9
9
|
.map(parseDiffLine)
|
10
|
-
.filter(
|
10
|
+
.filter(
|
11
|
+
({ name, type: changeType }) => Boolean(name) && Boolean(changeType),
|
12
|
+
);
|
11
13
|
}
|
12
14
|
export function parseDiffLine(pString) {
|
13
15
|
const lMatchResult = pString.match(DIFF_NAME_STATUS_LINE_PATTERN);
|
14
16
|
const lReturnValue = {};
|
15
17
|
if (lMatchResult?.groups) {
|
16
|
-
lReturnValue.
|
17
|
-
lMatchResult.groups.changeType,
|
18
|
-
);
|
18
|
+
lReturnValue.type = changeChar2ChangeType(lMatchResult.groups.changeType);
|
19
19
|
if (lMatchResult.groups.newName) {
|
20
20
|
lReturnValue.name = lMatchResult.groups.newName;
|
21
21
|
lReturnValue.oldName = lMatchResult.groups.name;
|
@@ -7,7 +7,9 @@ export function parseStatusLines(pString) {
|
|
7
7
|
.split(EOL)
|
8
8
|
.filter(Boolean)
|
9
9
|
.map(parseStatusLine)
|
10
|
-
.filter(
|
10
|
+
.filter(
|
11
|
+
({ name, type: changeType }) => Boolean(name) && Boolean(changeType),
|
12
|
+
);
|
11
13
|
}
|
12
14
|
export function parseStatusLine(pString) {
|
13
15
|
const lMatchResult = pString.match(DIFF_SHORT_STATUS_LINE_PATTERN);
|
@@ -19,7 +21,7 @@ export function parseStatusLine(pString) {
|
|
19
21
|
const lUnStagedChangeType = changeChar2ChangeType(
|
20
22
|
lMatchResult.groups.unStagedChangeType,
|
21
23
|
);
|
22
|
-
lReturnValue.
|
24
|
+
lReturnValue.type =
|
23
25
|
lStagedChangeType === "unmodified"
|
24
26
|
? lUnStagedChangeType
|
25
27
|
: lStagedChangeType;
|
package/dist/version.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
export const VERSION = "
|
1
|
+
export const VERSION = "4.0.0";
|
package/package.json
CHANGED
package/types/watskeburt.d.ts
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
export type
|
1
|
+
export type changeType =
|
2
2
|
| "added"
|
3
3
|
| "copied"
|
4
4
|
| "deleted"
|
@@ -20,86 +20,67 @@ export interface IChange {
|
|
20
20
|
/**
|
21
21
|
* how the file was changed
|
22
22
|
*/
|
23
|
-
|
23
|
+
type: changeType;
|
24
24
|
/**
|
25
25
|
* if the file was renamed: what the old file's name was
|
26
26
|
*/
|
27
27
|
oldName?: string;
|
28
28
|
}
|
29
29
|
|
30
|
-
export type outputTypeType = "regex" | "json"
|
30
|
+
export type outputTypeType = "regex" | "json";
|
31
31
|
|
32
|
-
export interface
|
32
|
+
export interface IBaseOptions {
|
33
33
|
/**
|
34
|
-
* The
|
35
|
-
*
|
34
|
+
* The revision against which to compare. When not passed defaults to the
|
35
|
+
* _current_ commit hash (if there's any)
|
36
36
|
*/
|
37
|
-
|
37
|
+
oldRevision?: string;
|
38
|
+
/**
|
39
|
+
* Newer revision against which to compare. Leave out when you want to
|
40
|
+
* compare against the working tree
|
41
|
+
*/
|
42
|
+
newRevision?: string;
|
38
43
|
/**
|
39
|
-
* When true
|
40
|
-
* When false also takes untracked files into account
|
41
|
-
*
|
42
|
-
* Defaults to false.
|
44
|
+
* When true only takes already tracked files into account.
|
45
|
+
* When false also takes untracked files into account (default)
|
43
46
|
*/
|
44
47
|
trackedOnly?: boolean;
|
45
48
|
}
|
46
49
|
|
47
|
-
export interface
|
50
|
+
export interface IFormatOptions extends IBaseOptions {
|
48
51
|
/**
|
49
|
-
* The type of output to deliver.
|
50
|
-
* the listSync function returns an IChange[] object
|
52
|
+
* The type of output to deliver.
|
51
53
|
*/
|
52
|
-
outputType
|
54
|
+
outputType: "regex" | "json";
|
55
|
+
}
|
56
|
+
|
57
|
+
export interface IInternalOptions extends IBaseOptions {
|
53
58
|
/**
|
54
|
-
*
|
55
|
-
*
|
56
|
-
*
|
57
|
-
* Defaults to false.
|
59
|
+
* The type of output to deliver. undefined/ left out
|
60
|
+
* the outputType defaults to a list of `IChange`s
|
58
61
|
*/
|
59
|
-
|
62
|
+
outputType?: undefined;
|
60
63
|
}
|
61
64
|
|
62
65
|
export type IOptions = IFormatOptions | IInternalOptions;
|
63
66
|
|
64
67
|
/**
|
65
|
-
*
|
68
|
+
* promises a list of files changed since pOldRevision.
|
66
69
|
*
|
67
|
-
* @param pOldRevision The revision against which to compare. E.g. a commit-hash,
|
68
|
-
* a branch or a tag. When not passed defaults to the _current_
|
69
|
-
* commit hash (if there's any)
|
70
|
-
* @param pNewRevision Newer revision against which to compare. Leave out or pass
|
71
|
-
* null when you want to compare against the working tree
|
72
|
-
* @param pOptions Options that influence how the changes are returned and that
|
73
|
-
* filter what is returned and
|
74
70
|
* @throws {Error}
|
75
71
|
*/
|
76
|
-
export function list(
|
77
|
-
pOldRevision?: string,
|
78
|
-
pNewRevision?: string,
|
79
|
-
pOptions?: IInternalOptions,
|
80
|
-
): Promise<IChange[]>;
|
72
|
+
export function list(pOptions?: IInternalOptions): Promise<IChange[]>;
|
81
73
|
|
82
74
|
/**
|
83
|
-
*
|
84
|
-
* string as a pOptions.outputType
|
75
|
+
* promises a list of files changed since pOldRevision, formatted
|
76
|
+
* into a string as a pOptions.outputType
|
85
77
|
*
|
86
|
-
* @param pOldRevision The revision against which to compare. E.g. a commit-hash,
|
87
|
-
* a branch or a tag. When not passed defaults to the _current_
|
88
|
-
* commit hash (if there's any)
|
89
|
-
* @param pNewRevision Newer revision against which to compare. Leave out or pass
|
90
|
-
* null when you want to compare against the working tree
|
91
|
-
* @param pOptions Options that influence how the changes are returned and that
|
92
|
-
* filter what is returned and
|
93
78
|
* @throws {Error}
|
94
79
|
*/
|
95
|
-
export function list(
|
96
|
-
pOldRevision?: string,
|
97
|
-
pNewRevision?: string,
|
98
|
-
pOptions?: IFormatOptions,
|
99
|
-
): Promise<string>;
|
80
|
+
export function list(pOptions?: IFormatOptions): Promise<string>;
|
100
81
|
|
101
82
|
/**
|
102
|
-
*
|
83
|
+
* Promises the SHA1 of the current HEAD
|
103
84
|
*
|
104
85
|
* @throws {Error}
|
105
86
|
*/
|
@@ -1,12 +0,0 @@
|
|
1
|
-
import formatToRegex from "./regex.js";
|
2
|
-
import formatToJSON from "./json.js";
|
3
|
-
const identity = (pX) => pX;
|
4
|
-
const OUTPUT_TYPE_TO_FUNCTION = new Map([
|
5
|
-
["regex", formatToRegex],
|
6
|
-
["json", formatToJSON],
|
7
|
-
]);
|
8
|
-
export default function format(pChanges, pOutputType) {
|
9
|
-
return (OUTPUT_TYPE_TO_FUNCTION.get(pOutputType ?? "unknown") || identity)(
|
10
|
-
pChanges,
|
11
|
-
);
|
12
|
-
}
|