binary-collections 2.0.7 → 2.0.9
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/bin/dir-tree.cmd +7 -0
- package/bin/git-diff +4 -0
- package/bin/git-diff.cmd +5 -2
- package/bin/{git-fix-encoding → git-fix} +1 -4
- package/bin/git-fix.cmd +7 -0
- package/bin/nodekill +0 -0
- package/bin/nodekill.ps1 +0 -0
- package/bin/{submodule → submodule.txt} +0 -0
- package/lib/binary-collections-config.cjs +14 -0
- package/lib/binary-collections-config.d.mts +18 -0
- package/lib/binary-collections-config.d.ts +16 -0
- package/lib/binary-collections-config.js +39 -0
- package/lib/binary-collections-config.mjs +6 -0
- package/lib/binary-collections.cjs +123 -0
- package/lib/binary-collections.d.cts +2 -0
- package/lib/binary-collections.d.mts +137 -0
- package/lib/binary-collections.d.ts +137 -0
- package/lib/binary-collections.mjs +300 -0
- package/lib/changelog.cjs +328 -0
- package/lib/changelog.d.mts +2 -0
- package/lib/changelog.d.ts +1 -0
- package/lib/changelog.js +226 -0
- package/lib/changelog.mjs +199 -0
- package/lib/chunk-4BYBVEYC.mjs +30 -0
- package/lib/{chunk-FB6YIQYR.mjs → chunk-AASHBCRW.mjs} +17 -2
- package/lib/chunk-APBWENF6.mjs +135 -0
- package/lib/{chunk-4LEXWIIF.mjs → chunk-DPKAJKFO.mjs} +2 -4
- package/lib/chunk-EGSSKVDH.mjs +66 -0
- package/lib/{chunk-3LOB2P54.mjs → chunk-G3THLIDT.mjs} +3 -5
- package/lib/chunk-JGR2NW6D.mjs +187 -0
- package/lib/chunk-ONIBBBQ3.mjs +108 -0
- package/lib/chunk-SH3L6HHV.mjs +27 -0
- package/lib/chunk-VVEZVNIV.mjs +81 -0
- package/lib/{chunk-JL32QDSH.mjs → chunk-W3ENOM53.mjs} +2 -4
- package/lib/chunk-YV7DO3YV.mjs +48 -0
- package/lib/{chunk-BSD5CIRU.mjs → chunk-YX5U7XDR.mjs} +11 -5
- package/lib/chunk-ZYAQRPUL.mjs +28 -0
- package/lib/clean-github-actions-caches.cjs +162 -0
- package/lib/clean-github-actions-caches.d.cts +1 -0
- package/lib/clean-github-actions-caches.d.mts +169 -0
- package/lib/clean-github-actions-caches.d.ts +169 -0
- package/lib/clean-github-actions-caches.mjs +132 -0
- package/lib/del-gradle.cjs +87 -3
- package/lib/del-gradle.js +1 -1
- package/lib/del-gradle.mjs +4 -6
- package/lib/del-node-modules.cjs +86 -2
- package/lib/del-node-modules.mjs +3 -5
- package/lib/del-ps.cjs +89 -5
- package/lib/del-ps.js +2 -2
- package/lib/del-ps.mjs +6 -8
- package/lib/del-yarn-caches.cjs +86 -2
- package/lib/del-yarn-caches.mjs +3 -5
- package/lib/find-node-modules-cli.cjs +8 -0
- package/lib/find-node-modules-cli.mjs +2 -3
- package/lib/find-node-modules.cjs +8 -0
- package/lib/find-node-modules.d.mts +3 -0
- package/lib/find-node-modules.d.ts +3 -0
- package/lib/find-node-modules.js +12 -0
- package/lib/find-node-modules.mjs +2 -3
- package/lib/git/gitattributes.cjs +171 -0
- package/lib/git/gitattributes.d.mts +35 -0
- package/lib/git/gitattributes.d.ts +33 -0
- package/lib/git/gitattributes.js +223 -0
- package/lib/git/gitattributes.mjs +6 -0
- package/lib/git/line-endings.cjs +74 -0
- package/lib/git/line-endings.d.cts +7 -0
- package/lib/git/line-endings.d.mts +83 -0
- package/lib/git/line-endings.d.ts +83 -0
- package/lib/git/line-endings.mjs +8 -0
- package/lib/git/normalize.cjs +42 -0
- package/lib/git/normalize.d.cts +6 -0
- package/lib/git/normalize.d.mts +43 -0
- package/lib/git/normalize.d.ts +43 -0
- package/lib/git/normalize.mjs +6 -0
- package/lib/git/permissions.cjs +15 -0
- package/lib/git/permissions.d.cts +6 -0
- package/lib/git/permissions.d.mts +17 -0
- package/lib/git/permissions.d.ts +17 -0
- package/lib/git/permissions.mjs +7 -0
- package/lib/git/pull-strategy.cjs +13 -0
- package/lib/git/pull-strategy.d.cts +5 -0
- package/lib/git/pull-strategy.d.mts +15 -0
- package/lib/git/pull-strategy.d.ts +15 -0
- package/lib/git/pull-strategy.mjs +7 -0
- package/lib/git/user-config.cjs +100 -0
- package/lib/git/user-config.d.cts +10 -0
- package/lib/git/user-config.d.mts +105 -0
- package/lib/git/user-config.d.ts +105 -0
- package/lib/git/user-config.mjs +8 -0
- package/lib/git/utils.cjs +70 -0
- package/lib/git/utils.d.cts +20 -0
- package/lib/git/utils.d.mts +69 -0
- package/lib/git/utils.d.ts +69 -0
- package/lib/git/utils.mjs +6 -0
- package/lib/git-diff.cjs +23 -24
- package/lib/git-diff.d.mts +25 -28
- package/lib/git-diff.d.ts +25 -28
- package/lib/git-diff.mjs +32 -27
- package/lib/git-fix.cjs +129 -0
- package/lib/git-fix.d.cts +2 -0
- package/lib/git-fix.d.mts +141 -0
- package/lib/git-fix.d.ts +141 -0
- package/lib/git-fix.mjs +151 -0
- package/lib/git-purge.cjs +86 -2
- package/lib/git-purge.mjs +3 -5
- package/lib/index.cjs +8 -0
- package/lib/index.mjs +3 -5
- package/lib/npm-run-series.cjs +140 -1
- package/lib/npm-run-series.js +2 -1
- package/lib/npm-run-series.mjs +7 -5
- package/lib/package-resolutions-updater.cjs +447 -0
- package/lib/package-resolutions-updater.d.mts +1 -0
- package/lib/package-resolutions-updater.d.ts +352 -0
- package/lib/package-resolutions-updater.mjs +339 -0
- package/lib/print-directory-tree.cjs +241 -0
- package/lib/print-directory-tree.d.cts +1 -0
- package/lib/print-directory-tree.d.mts +234 -0
- package/lib/print-directory-tree.d.ts +234 -0
- package/lib/print-directory-tree.mjs +182 -0
- package/lib/ps/connected-domain.mjs +2 -3
- package/lib/ps/index.cjs +3 -3
- package/lib/ps/index.d.mjs +1 -2
- package/lib/ps/index.js +6 -3
- package/lib/ps/index.mjs +9 -11
- package/lib/ps/isWin.mjs +2 -3
- package/lib/ps/table-parser.mjs +3 -4
- package/lib/submodule-install.cjs +18 -35
- package/lib/submodule-install.d.mts +17 -37
- package/lib/submodule-install.d.ts +17 -37
- package/lib/submodule-install.mjs +21 -29
- package/lib/utils.cjs +86 -2
- package/lib/utils.d.mts +29 -9
- package/lib/utils.d.ts +28 -8
- package/lib/utils.js +139 -8
- package/lib/utils.mjs +2 -3
- package/lib/yarn-reinstall.cjs +9 -7
- package/lib/yarn-reinstall.d.mts +12 -8
- package/lib/yarn-reinstall.d.ts +12 -8
- package/lib/yarn-reinstall.mjs +14 -10
- package/package.json +109 -80
- package/readme.md +74 -11
- package/src/package-resolutions-updater.mjs +350 -0
- package/src/print-directory-tree.cjs +234 -0
- package/src/ps/index.js +4 -3
- package/src/yarn-reinstall.cjs +49 -0
- package/test-project/package.json +16 -0
- package/tmp/test-repo/package.json +7 -0
- package/bin/git-fix-encoding.cmd +0 -6
- package/lib/chunk-OKYLF2MU.mjs +0 -53
- package/lib/chunk-VXZQNLPU.mjs +0 -23
- package/lib/package-resolutions.cjs +0 -28
- package/lib/package-resolutions.d.mts +0 -25
- package/lib/package-resolutions.d.ts +0 -25
- package/lib/package-resolutions.mjs +0 -31
- /package/bin/{submodule-install → submodule-install.txt} +0 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
// src/git/gitattributes.js
|
|
2
|
+
var fs = require("fs");
|
|
3
|
+
function parseGitAttributes(gitattributesPath) {
|
|
4
|
+
const rules = [];
|
|
5
|
+
if (!fs.existsSync(gitattributesPath)) {
|
|
6
|
+
return rules;
|
|
7
|
+
}
|
|
8
|
+
const content = fs.readFileSync(gitattributesPath, "utf8");
|
|
9
|
+
const lines = content.split("\n");
|
|
10
|
+
lines.forEach((line, index) => {
|
|
11
|
+
const trimmedLine = line.trim();
|
|
12
|
+
if (!trimmedLine || trimmedLine.startsWith("#")) {
|
|
13
|
+
rules.push({
|
|
14
|
+
type: trimmedLine.startsWith("#") ? "comment" : "empty",
|
|
15
|
+
content: line,
|
|
16
|
+
lineNumber: index + 1
|
|
17
|
+
});
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
const parts = trimmedLine.split(/\s+/);
|
|
21
|
+
if (parts.length >= 2) {
|
|
22
|
+
const pattern = parts[0];
|
|
23
|
+
const attributes = parts.slice(1).join(" ");
|
|
24
|
+
rules.push({
|
|
25
|
+
type: "rule",
|
|
26
|
+
pattern,
|
|
27
|
+
attributes,
|
|
28
|
+
content: line,
|
|
29
|
+
lineNumber: index + 1
|
|
30
|
+
});
|
|
31
|
+
} else {
|
|
32
|
+
rules.push({
|
|
33
|
+
type: "invalid",
|
|
34
|
+
content: line,
|
|
35
|
+
lineNumber: index + 1
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
return rules;
|
|
40
|
+
}
|
|
41
|
+
function patternsConflict(pattern1, pattern2) {
|
|
42
|
+
if (pattern1 === pattern2) {
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
if (pattern1 === "*" || pattern2 === "*") {
|
|
46
|
+
return pattern1 !== pattern2;
|
|
47
|
+
}
|
|
48
|
+
const normalize = (p) => p.replace(/\{[^}]+\}/g, "*").replace(/\*+/g, "*");
|
|
49
|
+
const norm1 = normalize(pattern1);
|
|
50
|
+
const norm2 = normalize(pattern2);
|
|
51
|
+
return norm1 === norm2;
|
|
52
|
+
}
|
|
53
|
+
function mergeGitAttributeRules(existingRules, desiredRules) {
|
|
54
|
+
let mergedRules;
|
|
55
|
+
if (existingRules.length === 0) {
|
|
56
|
+
mergedRules = desiredRules.map((desired, idx) => ({
|
|
57
|
+
type: "rule",
|
|
58
|
+
pattern: desired.pattern,
|
|
59
|
+
attributes: desired.attributes,
|
|
60
|
+
content: `${desired.pattern} ${desired.attributes}`,
|
|
61
|
+
lineNumber: idx + 1,
|
|
62
|
+
added: true
|
|
63
|
+
}));
|
|
64
|
+
return {
|
|
65
|
+
mergedRules,
|
|
66
|
+
conflicts: [],
|
|
67
|
+
changes: desiredRules.map((rule) => ({ action: "added", pattern: rule.pattern, attributes: rule.attributes }))
|
|
68
|
+
};
|
|
69
|
+
} else {
|
|
70
|
+
mergedRules = [...existingRules];
|
|
71
|
+
}
|
|
72
|
+
const conflicts = [];
|
|
73
|
+
const changes = [];
|
|
74
|
+
desiredRules.forEach((desired) => {
|
|
75
|
+
const existingIdx = mergedRules.findIndex((r) => r.type === "rule" && r.pattern === desired.pattern);
|
|
76
|
+
if (existingIdx !== -1) {
|
|
77
|
+
const existing = mergedRules[existingIdx];
|
|
78
|
+
if (existing.attributes === desired.attributes) {
|
|
79
|
+
conflicts.push({
|
|
80
|
+
pattern: desired.pattern,
|
|
81
|
+
existing: existing.attributes,
|
|
82
|
+
proposed: desired.attributes,
|
|
83
|
+
action: "kept existing (identical)"
|
|
84
|
+
});
|
|
85
|
+
} else if (desired.priority > (existing.priority || 0)) {
|
|
86
|
+
mergedRules[existingIdx] = {
|
|
87
|
+
type: "rule",
|
|
88
|
+
pattern: desired.pattern,
|
|
89
|
+
attributes: desired.attributes,
|
|
90
|
+
content: `${desired.pattern} ${desired.attributes}`,
|
|
91
|
+
lineNumber: existing.lineNumber,
|
|
92
|
+
replaced: true
|
|
93
|
+
};
|
|
94
|
+
conflicts.push({
|
|
95
|
+
pattern: desired.pattern,
|
|
96
|
+
existing: existing.attributes,
|
|
97
|
+
proposed: desired.attributes,
|
|
98
|
+
action: "replaced (higher priority)"
|
|
99
|
+
});
|
|
100
|
+
changes.push({
|
|
101
|
+
action: "replaced",
|
|
102
|
+
pattern: desired.pattern,
|
|
103
|
+
attributes: desired.attributes,
|
|
104
|
+
oldAttributes: existing.attributes
|
|
105
|
+
});
|
|
106
|
+
} else {
|
|
107
|
+
conflicts.push({
|
|
108
|
+
pattern: desired.pattern,
|
|
109
|
+
existing: existing.attributes,
|
|
110
|
+
proposed: desired.attributes,
|
|
111
|
+
action: "kept existing (lower priority)"
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
} else {
|
|
115
|
+
mergedRules.push({
|
|
116
|
+
type: "rule",
|
|
117
|
+
pattern: desired.pattern,
|
|
118
|
+
attributes: desired.attributes,
|
|
119
|
+
content: `${desired.pattern} ${desired.attributes}`,
|
|
120
|
+
lineNumber: mergedRules.length + 1,
|
|
121
|
+
added: true
|
|
122
|
+
});
|
|
123
|
+
changes.push({
|
|
124
|
+
action: "added",
|
|
125
|
+
pattern: desired.pattern,
|
|
126
|
+
attributes: desired.attributes
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
return { mergedRules, conflicts, changes };
|
|
131
|
+
}
|
|
132
|
+
function formatGitAttributes(rules) {
|
|
133
|
+
return rules.map((rule) => {
|
|
134
|
+
if (rule.type === "rule") {
|
|
135
|
+
return `${rule.pattern} ${rule.attributes}`;
|
|
136
|
+
}
|
|
137
|
+
return rule.content;
|
|
138
|
+
}).join("\n") + "\n";
|
|
139
|
+
}
|
|
140
|
+
function updateGitAttributes(gitattributesPath, desiredRules) {
|
|
141
|
+
try {
|
|
142
|
+
const existingRules = parseGitAttributes(gitattributesPath);
|
|
143
|
+
const { mergedRules, conflicts, changes } = mergeGitAttributeRules(existingRules, desiredRules);
|
|
144
|
+
let success = false;
|
|
145
|
+
if (changes.length > 0) {
|
|
146
|
+
const newContent = formatGitAttributes(mergedRules);
|
|
147
|
+
fs.writeFileSync(gitattributesPath, newContent);
|
|
148
|
+
success = true;
|
|
149
|
+
}
|
|
150
|
+
return {
|
|
151
|
+
success,
|
|
152
|
+
conflicts,
|
|
153
|
+
changes,
|
|
154
|
+
message: success ? `Updated .gitattributes with ${changes.length} changes` : "No changes needed - all rules already present"
|
|
155
|
+
};
|
|
156
|
+
} catch (error) {
|
|
157
|
+
return {
|
|
158
|
+
success: false,
|
|
159
|
+
error: error.message,
|
|
160
|
+
conflicts: [],
|
|
161
|
+
changes: []
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
module.exports = {
|
|
166
|
+
parseGitAttributes,
|
|
167
|
+
patternsConflict,
|
|
168
|
+
mergeGitAttributeRules,
|
|
169
|
+
formatGitAttributes,
|
|
170
|
+
updateGitAttributes
|
|
171
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse existing .gitattributes file into structured rules
|
|
3
|
+
* @param {string} gitattributesPath - Path to .gitattributes file
|
|
4
|
+
* @returns {Array} Array of parsed rules
|
|
5
|
+
*/
|
|
6
|
+
declare function parseGitAttributes(gitattributesPath: string): any[];
|
|
7
|
+
/**
|
|
8
|
+
* Check if two patterns conflict (same or overlapping file patterns)
|
|
9
|
+
* @param {string} pattern1 - First pattern
|
|
10
|
+
* @param {string} pattern2 - Second pattern
|
|
11
|
+
* @returns {boolean} True if patterns conflict
|
|
12
|
+
*/
|
|
13
|
+
declare function patternsConflict(pattern1: string, pattern2: string): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Merge existing rules with desired rules, detecting conflicts
|
|
16
|
+
* @param {Array} existingRules - Parsed existing rules
|
|
17
|
+
* @param {Array} desiredRules - Desired rules to add
|
|
18
|
+
* @returns {Object} Result with mergedRules, conflicts, and changes
|
|
19
|
+
*/
|
|
20
|
+
declare function mergeGitAttributeRules(existingRules: any[], desiredRules: any[]): any;
|
|
21
|
+
/**
|
|
22
|
+
* Format merged rules back into .gitattributes content
|
|
23
|
+
* @param {Array} rules - Merged rules array
|
|
24
|
+
* @returns {string} Formatted .gitattributes content
|
|
25
|
+
*/
|
|
26
|
+
declare function formatGitAttributes(rules: any[]): string;
|
|
27
|
+
/**
|
|
28
|
+
* Update .gitattributes file with new rules, handling conflicts intelligently
|
|
29
|
+
* @param {string} gitattributesPath - Path to .gitattributes file
|
|
30
|
+
* @param {Array} desiredRules - Array of desired rules to add/merge
|
|
31
|
+
* @returns {Object} Result with success status, conflicts, and changes
|
|
32
|
+
*/
|
|
33
|
+
declare function updateGitAttributes(gitattributesPath: string, desiredRules: any[]): any;
|
|
34
|
+
|
|
35
|
+
export { formatGitAttributes, mergeGitAttributeRules, parseGitAttributes, patternsConflict, updateGitAttributes };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse existing .gitattributes file into structured rules
|
|
3
|
+
* @param {string} gitattributesPath - Path to .gitattributes file
|
|
4
|
+
* @returns {Array} Array of parsed rules
|
|
5
|
+
*/
|
|
6
|
+
export function parseGitAttributes(gitattributesPath: string): any[];
|
|
7
|
+
/**
|
|
8
|
+
* Check if two patterns conflict (same or overlapping file patterns)
|
|
9
|
+
* @param {string} pattern1 - First pattern
|
|
10
|
+
* @param {string} pattern2 - Second pattern
|
|
11
|
+
* @returns {boolean} True if patterns conflict
|
|
12
|
+
*/
|
|
13
|
+
export function patternsConflict(pattern1: string, pattern2: string): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Merge existing rules with desired rules, detecting conflicts
|
|
16
|
+
* @param {Array} existingRules - Parsed existing rules
|
|
17
|
+
* @param {Array} desiredRules - Desired rules to add
|
|
18
|
+
* @returns {Object} Result with mergedRules, conflicts, and changes
|
|
19
|
+
*/
|
|
20
|
+
export function mergeGitAttributeRules(existingRules: any[], desiredRules: any[]): any;
|
|
21
|
+
/**
|
|
22
|
+
* Format merged rules back into .gitattributes content
|
|
23
|
+
* @param {Array} rules - Merged rules array
|
|
24
|
+
* @returns {string} Formatted .gitattributes content
|
|
25
|
+
*/
|
|
26
|
+
export function formatGitAttributes(rules: any[]): string;
|
|
27
|
+
/**
|
|
28
|
+
* Update .gitattributes file with new rules, handling conflicts intelligently
|
|
29
|
+
* @param {string} gitattributesPath - Path to .gitattributes file
|
|
30
|
+
* @param {Array} desiredRules - Array of desired rules to add/merge
|
|
31
|
+
* @returns {Object} Result with success status, conflicts, and changes
|
|
32
|
+
*/
|
|
33
|
+
export function updateGitAttributes(gitattributesPath: string, desiredRules: any[]): any;
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
/**
|
|
3
|
+
* Parse existing .gitattributes file into structured rules
|
|
4
|
+
* @param {string} gitattributesPath - Path to .gitattributes file
|
|
5
|
+
* @returns {Array} Array of parsed rules
|
|
6
|
+
*/
|
|
7
|
+
function parseGitAttributes(gitattributesPath) {
|
|
8
|
+
const rules = [];
|
|
9
|
+
if (!fs.existsSync(gitattributesPath)) {
|
|
10
|
+
return rules;
|
|
11
|
+
}
|
|
12
|
+
const content = fs.readFileSync(gitattributesPath, "utf8");
|
|
13
|
+
const lines = content.split("\n");
|
|
14
|
+
lines.forEach((line, index) => {
|
|
15
|
+
const trimmedLine = line.trim();
|
|
16
|
+
// Skip empty lines and comments
|
|
17
|
+
if (!trimmedLine || trimmedLine.startsWith("#")) {
|
|
18
|
+
rules.push({
|
|
19
|
+
type: trimmedLine.startsWith("#") ? "comment" : "empty",
|
|
20
|
+
content: line,
|
|
21
|
+
lineNumber: index + 1
|
|
22
|
+
});
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
// Parse rule line
|
|
26
|
+
const parts = trimmedLine.split(/\s+/);
|
|
27
|
+
if (parts.length >= 2) {
|
|
28
|
+
const pattern = parts[0];
|
|
29
|
+
const attributes = parts.slice(1).join(" ");
|
|
30
|
+
rules.push({
|
|
31
|
+
type: "rule",
|
|
32
|
+
pattern,
|
|
33
|
+
attributes,
|
|
34
|
+
content: line,
|
|
35
|
+
lineNumber: index + 1
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
// Invalid line, keep as-is
|
|
40
|
+
rules.push({
|
|
41
|
+
type: "invalid",
|
|
42
|
+
content: line,
|
|
43
|
+
lineNumber: index + 1
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
return rules;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Check if two patterns conflict (same or overlapping file patterns)
|
|
51
|
+
* @param {string} pattern1 - First pattern
|
|
52
|
+
* @param {string} pattern2 - Second pattern
|
|
53
|
+
* @returns {boolean} True if patterns conflict
|
|
54
|
+
*/
|
|
55
|
+
function patternsConflict(pattern1, pattern2) {
|
|
56
|
+
// Exact match
|
|
57
|
+
if (pattern1 === pattern2) {
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
// Universal pattern conflicts with everything
|
|
61
|
+
if (pattern1 === "*" || pattern2 === "*") {
|
|
62
|
+
return pattern1 !== pattern2;
|
|
63
|
+
}
|
|
64
|
+
// Simple glob overlap detection
|
|
65
|
+
const normalize = (p) => p.replace(/\{[^}]+\}/g, "*").replace(/\*+/g, "*");
|
|
66
|
+
const norm1 = normalize(pattern1);
|
|
67
|
+
const norm2 = normalize(pattern2);
|
|
68
|
+
return norm1 === norm2;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Merge existing rules with desired rules, detecting conflicts
|
|
72
|
+
* @param {Array} existingRules - Parsed existing rules
|
|
73
|
+
* @param {Array} desiredRules - Desired rules to add
|
|
74
|
+
* @returns {Object} Result with mergedRules, conflicts, and changes
|
|
75
|
+
*/
|
|
76
|
+
function mergeGitAttributeRules(existingRules, desiredRules) {
|
|
77
|
+
let mergedRules;
|
|
78
|
+
if (existingRules.length === 0) {
|
|
79
|
+
// If no existing rules, just add all desired rules in order
|
|
80
|
+
mergedRules = desiredRules.map((desired, idx) => ({
|
|
81
|
+
type: "rule",
|
|
82
|
+
pattern: desired.pattern,
|
|
83
|
+
attributes: desired.attributes,
|
|
84
|
+
content: `${desired.pattern} ${desired.attributes}`,
|
|
85
|
+
lineNumber: idx + 1,
|
|
86
|
+
added: true
|
|
87
|
+
}));
|
|
88
|
+
return {
|
|
89
|
+
mergedRules,
|
|
90
|
+
conflicts: [],
|
|
91
|
+
changes: desiredRules.map((rule) => ({ action: "added", pattern: rule.pattern, attributes: rule.attributes }))
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
mergedRules = [...existingRules];
|
|
96
|
+
}
|
|
97
|
+
const conflicts = [];
|
|
98
|
+
const changes = [];
|
|
99
|
+
desiredRules.forEach((desired) => {
|
|
100
|
+
// Look for an exact pattern match in existing rules
|
|
101
|
+
const existingIdx = mergedRules.findIndex((r) => r.type === "rule" && r.pattern === desired.pattern);
|
|
102
|
+
if (existingIdx !== -1) {
|
|
103
|
+
const existing = mergedRules[existingIdx];
|
|
104
|
+
if (existing.attributes === desired.attributes) {
|
|
105
|
+
// Already present, do nothing
|
|
106
|
+
conflicts.push({
|
|
107
|
+
pattern: desired.pattern,
|
|
108
|
+
existing: existing.attributes,
|
|
109
|
+
proposed: desired.attributes,
|
|
110
|
+
action: "kept existing (identical)"
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
else if (desired.priority > (existing.priority || 0)) {
|
|
114
|
+
// Replace with higher priority rule
|
|
115
|
+
mergedRules[existingIdx] = {
|
|
116
|
+
type: "rule",
|
|
117
|
+
pattern: desired.pattern,
|
|
118
|
+
attributes: desired.attributes,
|
|
119
|
+
content: `${desired.pattern} ${desired.attributes}`,
|
|
120
|
+
lineNumber: existing.lineNumber,
|
|
121
|
+
replaced: true
|
|
122
|
+
};
|
|
123
|
+
conflicts.push({
|
|
124
|
+
pattern: desired.pattern,
|
|
125
|
+
existing: existing.attributes,
|
|
126
|
+
proposed: desired.attributes,
|
|
127
|
+
action: "replaced (higher priority)"
|
|
128
|
+
});
|
|
129
|
+
changes.push({
|
|
130
|
+
action: "replaced",
|
|
131
|
+
pattern: desired.pattern,
|
|
132
|
+
attributes: desired.attributes,
|
|
133
|
+
oldAttributes: existing.attributes
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
// Keep existing rule
|
|
138
|
+
conflicts.push({
|
|
139
|
+
pattern: desired.pattern,
|
|
140
|
+
existing: existing.attributes,
|
|
141
|
+
proposed: desired.attributes,
|
|
142
|
+
action: "kept existing (lower priority)"
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
// No exact pattern match, add new rule
|
|
148
|
+
mergedRules.push({
|
|
149
|
+
type: "rule",
|
|
150
|
+
pattern: desired.pattern,
|
|
151
|
+
attributes: desired.attributes,
|
|
152
|
+
content: `${desired.pattern} ${desired.attributes}`,
|
|
153
|
+
lineNumber: mergedRules.length + 1,
|
|
154
|
+
added: true
|
|
155
|
+
});
|
|
156
|
+
changes.push({
|
|
157
|
+
action: "added",
|
|
158
|
+
pattern: desired.pattern,
|
|
159
|
+
attributes: desired.attributes
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
return { mergedRules, conflicts, changes };
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Format merged rules back into .gitattributes content
|
|
167
|
+
* @param {Array} rules - Merged rules array
|
|
168
|
+
* @returns {string} Formatted .gitattributes content
|
|
169
|
+
*/
|
|
170
|
+
function formatGitAttributes(rules) {
|
|
171
|
+
return (rules
|
|
172
|
+
.map((rule) => {
|
|
173
|
+
if (rule.type === "rule") {
|
|
174
|
+
return `${rule.pattern} ${rule.attributes}`;
|
|
175
|
+
}
|
|
176
|
+
return rule.content;
|
|
177
|
+
})
|
|
178
|
+
.join("\n") + "\n");
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Update .gitattributes file with new rules, handling conflicts intelligently
|
|
182
|
+
* @param {string} gitattributesPath - Path to .gitattributes file
|
|
183
|
+
* @param {Array} desiredRules - Array of desired rules to add/merge
|
|
184
|
+
* @returns {Object} Result with success status, conflicts, and changes
|
|
185
|
+
*/
|
|
186
|
+
function updateGitAttributes(gitattributesPath, desiredRules) {
|
|
187
|
+
try {
|
|
188
|
+
// Parse existing .gitattributes
|
|
189
|
+
const existingRules = parseGitAttributes(gitattributesPath);
|
|
190
|
+
// Merge rules and detect conflicts
|
|
191
|
+
const { mergedRules, conflicts, changes } = mergeGitAttributeRules(existingRules, desiredRules);
|
|
192
|
+
// Write updated .gitattributes if changes were made
|
|
193
|
+
let success = false;
|
|
194
|
+
if (changes.length > 0) {
|
|
195
|
+
const newContent = formatGitAttributes(mergedRules);
|
|
196
|
+
fs.writeFileSync(gitattributesPath, newContent);
|
|
197
|
+
success = true;
|
|
198
|
+
}
|
|
199
|
+
return {
|
|
200
|
+
success,
|
|
201
|
+
conflicts,
|
|
202
|
+
changes,
|
|
203
|
+
message: success
|
|
204
|
+
? `Updated .gitattributes with ${changes.length} changes`
|
|
205
|
+
: "No changes needed - all rules already present"
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
catch (error) {
|
|
209
|
+
return {
|
|
210
|
+
success: false,
|
|
211
|
+
error: error.message,
|
|
212
|
+
conflicts: [],
|
|
213
|
+
changes: []
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
module.exports = {
|
|
218
|
+
parseGitAttributes,
|
|
219
|
+
patternsConflict,
|
|
220
|
+
mergeGitAttributeRules,
|
|
221
|
+
formatGitAttributes,
|
|
222
|
+
updateGitAttributes
|
|
223
|
+
};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const path = require("upath");
|
|
3
|
+
const fs = require("fs");
|
|
4
|
+
const { runGitCommand } = require("./utils.cjs");
|
|
5
|
+
const { updateGitAttributes } = require("./gitattributes.js");
|
|
6
|
+
/**
|
|
7
|
+
* Force LF line endings configuration
|
|
8
|
+
* - Sets core.autocrlf = false
|
|
9
|
+
* - Sets core.eol = lf
|
|
10
|
+
* - Creates/updates .gitattributes with proper line ending rules
|
|
11
|
+
*/
|
|
12
|
+
function forceLfLineEndings() {
|
|
13
|
+
console.log("\n=== Configuring LF Line Endings ===");
|
|
14
|
+
// Force LF line endings
|
|
15
|
+
runGitCommand(["config", "core.autocrlf", "false"], "Disable automatic CRLF conversion");
|
|
16
|
+
runGitCommand(["config", "core.eol", "lf"], "Set end-of-line to LF");
|
|
17
|
+
// Create or update .gitattributes
|
|
18
|
+
const gitattributesPath = path.join(process.cwd(), ".gitattributes");
|
|
19
|
+
// Always ensure the universal LF rule is present, even if file exists
|
|
20
|
+
if (fs.existsSync(gitattributesPath)) {
|
|
21
|
+
let content = fs.readFileSync(gitattributesPath, "utf8");
|
|
22
|
+
// Match * text=auto eol=lf with any whitespace (space or tab) between tokens
|
|
23
|
+
if (!/^\*\s+text=auto\s+eol=lf/m.test(content)) {
|
|
24
|
+
content = `* text=auto eol=lf\n` + content;
|
|
25
|
+
fs.writeFileSync(gitattributesPath, content);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
// Define desired rules with priorities
|
|
29
|
+
const desiredRules = [
|
|
30
|
+
{ pattern: "*", attributes: "text=auto eol=lf", priority: 1 },
|
|
31
|
+
{
|
|
32
|
+
pattern: "*.{cmd,bat,ps1,sh,cmd1,cmd2,bat1,bat2,vbs}",
|
|
33
|
+
attributes: "text eol=crlf",
|
|
34
|
+
priority: 2
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
pattern: "*.{png,jpg,jpeg,gif,ico,svg,bmp,webp,avif,tiff,tif,psd,ai,eps,raw}",
|
|
38
|
+
attributes: "binary",
|
|
39
|
+
priority: 3
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
pattern: "*.{zip,tar,gz,7z,rar,exe,dll,so,bin,jar,war,ear,apk,msi,deb,rpm,iso,img,dmg,pdf,mp3,mp4,mov,avi,mkv,flv,wmv,ogg,webm,wav,aac,m4a,otf,ttf,woff,woff2,eot}",
|
|
43
|
+
attributes: "binary",
|
|
44
|
+
priority: 3
|
|
45
|
+
}
|
|
46
|
+
];
|
|
47
|
+
// Update .gitattributes using the dedicated module
|
|
48
|
+
const result = updateGitAttributes(gitattributesPath, desiredRules);
|
|
49
|
+
// Report results
|
|
50
|
+
if (result.error) {
|
|
51
|
+
console.log(`[✗] Error updating .gitattributes: ${result.error}`);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
// Report conflicts if any
|
|
55
|
+
if (result.conflicts.length > 0) {
|
|
56
|
+
console.log("\n[!] Detected conflicts in .gitattributes:");
|
|
57
|
+
result.conflicts.forEach((conflict) => {
|
|
58
|
+
console.log(` ${conflict.pattern}: ${conflict.existing} -> ${conflict.proposed} (${conflict.action})`);
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
// Report changes
|
|
62
|
+
if (result.success) {
|
|
63
|
+
console.log(`[✓] ${result.message}:`);
|
|
64
|
+
result.changes.forEach((change) => {
|
|
65
|
+
console.log(` ${change.action}: ${change.pattern} ${change.attributes}`);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
console.log(`[i] ${result.message}`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
module.exports = {
|
|
73
|
+
forceLfLineEndings
|
|
74
|
+
};
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
const path = require("upath");
|
|
2
|
+
const fs = require("fs");
|
|
3
|
+
const { runGitCommand } = require("./utils.cjs");
|
|
4
|
+
const { updateGitAttributes } = require("./gitattributes.js");
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Force LF line endings configuration
|
|
8
|
+
* - Sets core.autocrlf = false
|
|
9
|
+
* - Sets core.eol = lf
|
|
10
|
+
* - Creates/updates .gitattributes with proper line ending rules
|
|
11
|
+
*/
|
|
12
|
+
function forceLfLineEndings() {
|
|
13
|
+
console.log("\n=== Configuring LF Line Endings ===");
|
|
14
|
+
|
|
15
|
+
// Force LF line endings
|
|
16
|
+
runGitCommand(["config", "core.autocrlf", "false"], "Disable automatic CRLF conversion");
|
|
17
|
+
runGitCommand(["config", "core.eol", "lf"], "Set end-of-line to LF");
|
|
18
|
+
|
|
19
|
+
// Create or update .gitattributes
|
|
20
|
+
const gitattributesPath = path.join(process.cwd(), ".gitattributes");
|
|
21
|
+
|
|
22
|
+
// Always ensure the universal LF rule is present, even if file exists
|
|
23
|
+
if (fs.existsSync(gitattributesPath)) {
|
|
24
|
+
let content = fs.readFileSync(gitattributesPath, "utf8");
|
|
25
|
+
// Match * text=auto eol=lf with any whitespace (space or tab) between tokens
|
|
26
|
+
if (!/^\*\s+text=auto\s+eol=lf/m.test(content)) {
|
|
27
|
+
content = `* text=auto eol=lf\n` + content;
|
|
28
|
+
fs.writeFileSync(gitattributesPath, content);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Define desired rules with priorities
|
|
33
|
+
const desiredRules = [
|
|
34
|
+
{ pattern: "*", attributes: "text=auto eol=lf", priority: 1 },
|
|
35
|
+
{
|
|
36
|
+
pattern: "*.{cmd,bat,ps1,sh,cmd1,cmd2,bat1,bat2,vbs}",
|
|
37
|
+
attributes: "text eol=crlf",
|
|
38
|
+
priority: 2
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
pattern: "*.{png,jpg,jpeg,gif,ico,svg,bmp,webp,avif,tiff,tif,psd,ai,eps,raw}",
|
|
42
|
+
attributes: "binary",
|
|
43
|
+
priority: 3
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
pattern:
|
|
47
|
+
"*.{zip,tar,gz,7z,rar,exe,dll,so,bin,jar,war,ear,apk,msi,deb,rpm,iso,img,dmg,pdf,mp3,mp4,mov,avi,mkv,flv,wmv,ogg,webm,wav,aac,m4a,otf,ttf,woff,woff2,eot}",
|
|
48
|
+
attributes: "binary",
|
|
49
|
+
priority: 3
|
|
50
|
+
}
|
|
51
|
+
];
|
|
52
|
+
|
|
53
|
+
// Update .gitattributes using the dedicated module
|
|
54
|
+
const result = updateGitAttributes(gitattributesPath, desiredRules);
|
|
55
|
+
|
|
56
|
+
// Report results
|
|
57
|
+
if (result.error) {
|
|
58
|
+
console.log(`[✗] Error updating .gitattributes: ${result.error}`);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Report conflicts if any
|
|
63
|
+
if (result.conflicts.length > 0) {
|
|
64
|
+
console.log("\n[!] Detected conflicts in .gitattributes:");
|
|
65
|
+
result.conflicts.forEach((conflict) => {
|
|
66
|
+
console.log(` ${conflict.pattern}: ${conflict.existing} -> ${conflict.proposed} (${conflict.action})`);
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Report changes
|
|
71
|
+
if (result.success) {
|
|
72
|
+
console.log(`[✓] ${result.message}:`);
|
|
73
|
+
result.changes.forEach((change) => {
|
|
74
|
+
console.log(` ${change.action}: ${change.pattern} ${change.attributes}`);
|
|
75
|
+
});
|
|
76
|
+
} else {
|
|
77
|
+
console.log(`[i] ${result.message}`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
module.exports = {
|
|
82
|
+
forceLfLineEndings
|
|
83
|
+
};
|