tune-basic-toolset 0.1.12 → 0.1.13
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/package.json +1 -1
- package/src/patch.tool.js +45 -21
package/package.json
CHANGED
package/src/patch.tool.js
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
const fs = require('fs').promises;
|
|
2
2
|
|
|
3
3
|
// Patch tool to apply custom diffs marked with <<<<<<< ORIGINAL and >>>>>>> UPDATED
|
|
4
|
-
//
|
|
5
|
-
|
|
4
|
+
// More tolerant to whitespace differences on each line and reports per-block success.
|
|
6
5
|
module.exports = async function patch({ text, filename }, ctx) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const patchRegex = /<{6,}\s*ORIGINAL[^\n]*\n([\s\S]*?)=+\n([\s\S]*?)>{6,}\s*UPDATED[^\n]*(?:\n|$)/g;
|
|
11
|
-
const patches = [];
|
|
12
|
-
let match;
|
|
6
|
+
if (!text || !filename) {
|
|
7
|
+
return "No patch text or filename provided";
|
|
8
|
+
}
|
|
13
9
|
|
|
14
|
-
//
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
10
|
+
// Match: <<<<<<< ORIGINAL ... ======= ... >>>>>>> UPDATED
|
|
11
|
+
// Be tolerant to CRLF/LF and optional trailing text/spaces on the markers.
|
|
12
|
+
const patchRegex = /<{6,}\s*ORIGINAL[^\n]*\r?\n([\s\S]*?)=+[^\n]*\r?\n([\s\S]*?)>{6,}\s*UPDATED[^\n]*(?:\r?\n|$)/g;
|
|
13
|
+
|
|
14
|
+
const patches = [];
|
|
15
|
+
let m;
|
|
16
|
+
while ((m = patchRegex.exec(text)) !== null) {
|
|
17
|
+
const oldPart = String(m[1]).replace(/^\s*\r?\n+|\r?\n+\s*$/g, "");
|
|
18
|
+
const newPart = String(m[2]).replace(/^\s*\r?\n+|\r?\n+\s*$/g, "");
|
|
18
19
|
patches.push({ oldPart, newPart });
|
|
19
20
|
}
|
|
20
21
|
|
|
@@ -24,18 +25,41 @@ module.exports = async function patch({ text, filename }, ctx) {
|
|
|
24
25
|
|
|
25
26
|
let fileContent = await ctx.read(filename);
|
|
26
27
|
|
|
27
|
-
|
|
28
|
-
// Escape regex
|
|
29
|
-
|
|
30
|
-
//
|
|
31
|
-
let escaped = oldPart.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
28
|
+
function buildPattern(oldStr) {
|
|
29
|
+
// Escape special regex chars
|
|
30
|
+
let escaped = oldStr.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
31
|
+
// Normalize line endings to \r?\n so CRLF/LF both match
|
|
32
32
|
escaped = escaped.replace(/\r?\n/g, "\\r?\\n");
|
|
33
|
-
|
|
33
|
+
// Tolerate indentation/space differences (spaces or tabs), zero-or-more
|
|
34
|
+
// Keep newlines strict so structure must still match.
|
|
35
|
+
escaped = escaped.replace(/[ \t]+/g, "[ \\t]*");
|
|
36
|
+
return new RegExp(escaped, "g");
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const totalSegments = patches.length;
|
|
40
|
+
let appliedSegments = 0;
|
|
41
|
+
let totalReplacements = 0;
|
|
34
42
|
|
|
35
|
-
|
|
36
|
-
|
|
43
|
+
for (const { oldPart, newPart } of patches) {
|
|
44
|
+
const re = buildPattern(oldPart);
|
|
45
|
+
let matches = 0;
|
|
46
|
+
fileContent = fileContent.replace(re, () => {
|
|
47
|
+
matches += 1;
|
|
48
|
+
return newPart;
|
|
49
|
+
});
|
|
50
|
+
if (matches > 0) {
|
|
51
|
+
appliedSegments += 1;
|
|
52
|
+
totalReplacements += matches;
|
|
53
|
+
}
|
|
37
54
|
}
|
|
38
55
|
|
|
39
56
|
await ctx.write(filename, fileContent);
|
|
40
|
-
|
|
57
|
+
|
|
58
|
+
if (appliedSegments === 0) {
|
|
59
|
+
return `no matches applied (0/${totalSegments})`;
|
|
60
|
+
}
|
|
61
|
+
if (appliedSegments < totalSegments) {
|
|
62
|
+
return `patched partially (${appliedSegments}/${totalSegments}), replacements: ${totalReplacements}`;
|
|
63
|
+
}
|
|
64
|
+
return `patched (${appliedSegments}/${totalSegments}), replacements: ${totalReplacements}`;
|
|
41
65
|
};
|