amalgm 0.1.259 → 0.1.260
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
CHANGED
|
@@ -14,15 +14,31 @@ const { lookFailed } = require('../adapters/truth');
|
|
|
14
14
|
/**
|
|
15
15
|
* Does a .git hold this ground? Three answers, like every look — and
|
|
16
16
|
* only present or absent may conclude: territory is never born,
|
|
17
|
-
* buried, or converted on a look that failed.
|
|
17
|
+
* buried, or converted on a look that failed. A directory is Git's own
|
|
18
|
+
* repository marker. A file is a linked-worktree/submodule pointer, so it
|
|
19
|
+
* claims territory only when the referenced gitdir still exists: a stale
|
|
20
|
+
* pointer is ordinary folder ground, never a broken repo boundary.
|
|
18
21
|
*/
|
|
19
22
|
function gitDirTruth(absDir) {
|
|
23
|
+
let marker;
|
|
20
24
|
try {
|
|
21
|
-
fs.lstatSync(path.join(absDir, '.git'));
|
|
22
|
-
return 'present';
|
|
25
|
+
marker = fs.lstatSync(path.join(absDir, '.git'));
|
|
23
26
|
} catch (error) {
|
|
24
27
|
return lookFailed(error).truth;
|
|
25
28
|
}
|
|
29
|
+
if (marker.isDirectory()) return 'present';
|
|
30
|
+
if (!marker.isFile()) return 'absent';
|
|
31
|
+
try {
|
|
32
|
+
const source = fs.readFileSync(path.join(absDir, '.git'), 'utf8');
|
|
33
|
+
const match = /^gitdir:\s*(.+?)\s*$/im.exec(source);
|
|
34
|
+
if (!match) return 'absent';
|
|
35
|
+
const gitDir = path.resolve(absDir, match[1]);
|
|
36
|
+
if (!fs.lstatSync(gitDir).isDirectory()) return 'absent';
|
|
37
|
+
if (!fs.lstatSync(path.join(gitDir, 'HEAD')).isFile()) return 'absent';
|
|
38
|
+
return 'present';
|
|
39
|
+
} catch (error) {
|
|
40
|
+
return lookFailed(error).truth === 'unsettled' ? 'unsettled' : 'absent';
|
|
41
|
+
}
|
|
26
42
|
}
|
|
27
43
|
|
|
28
44
|
/**
|
|
@@ -72,9 +88,15 @@ function walkRoot(rootPath, shouldEnroll, { allowRootRepository = false } = {})
|
|
|
72
88
|
vanished(error, relDir);
|
|
73
89
|
continue;
|
|
74
90
|
}
|
|
75
|
-
// A .git claims its subtree: an embedded repository is repo
|
|
76
|
-
// never files territory. Its changes travel as one card, not
|
|
77
|
-
|
|
91
|
+
// A valid .git claims its subtree: an embedded repository is repo
|
|
92
|
+
// territory, never files territory. Its changes travel as one card, not
|
|
93
|
+
// as files. A stale linked-worktree pointer is plain folder ground.
|
|
94
|
+
const territory = gitDirTruth(absDir);
|
|
95
|
+
if (territory === 'unsettled') {
|
|
96
|
+
unsettled.push(relDir);
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
if (territory === 'present' && !(allowRootRepository && relDir === '')) {
|
|
78
100
|
repoDirs.push(relDir);
|
|
79
101
|
if (!relDir) return { files: [], dirs: [], links: [], repoDirs, unsettled }; // the whole root is repo territory
|
|
80
102
|
continue;
|
|
@@ -148,7 +170,12 @@ function listDir(rootPath, relDir, shouldEnroll) {
|
|
|
148
170
|
else out.unsettled = true;
|
|
149
171
|
return out;
|
|
150
172
|
}
|
|
151
|
-
|
|
173
|
+
const territory = gitDirTruth(absDir);
|
|
174
|
+
if (territory === 'unsettled') {
|
|
175
|
+
out.unsettled = true;
|
|
176
|
+
return out;
|
|
177
|
+
}
|
|
178
|
+
if (territory === 'present') {
|
|
152
179
|
out.hasGit = true;
|
|
153
180
|
return out;
|
|
154
181
|
}
|
|
@@ -218,7 +245,12 @@ function censusBoundaries(rootPath, shouldEnroll = defaultShouldEnroll) {
|
|
|
218
245
|
if (lookFailed(error).truth === 'unsettled') unsettled.push(relDir);
|
|
219
246
|
continue;
|
|
220
247
|
}
|
|
221
|
-
|
|
248
|
+
const territory = gitDirTruth(absDir);
|
|
249
|
+
if (territory === 'unsettled') {
|
|
250
|
+
unsettled.push(relDir);
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
253
|
+
if (relDir && territory === 'present') {
|
|
222
254
|
boundaries.push(relDir);
|
|
223
255
|
continue;
|
|
224
256
|
}
|
|
@@ -259,7 +291,12 @@ function censusLinks(rootPath, shouldEnroll = defaultShouldEnroll) {
|
|
|
259
291
|
if (lookFailed(error).truth === 'unsettled') unsettled.push(relDir);
|
|
260
292
|
continue;
|
|
261
293
|
}
|
|
262
|
-
|
|
294
|
+
const territory = gitDirTruth(absDir);
|
|
295
|
+
if (territory === 'unsettled') {
|
|
296
|
+
unsettled.push(relDir);
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
if (relDir && territory === 'present') continue;
|
|
263
300
|
for (const entry of entries) {
|
|
264
301
|
if (entry.name === '.git') continue;
|
|
265
302
|
const rel = relDir ? `${relDir}/${entry.name}` : entry.name;
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
const fs = require('fs');
|
|
30
30
|
const path = require('path');
|
|
31
31
|
const crypto = require('crypto');
|
|
32
|
+
const { gitDirTruth } = require('../observer/scan');
|
|
32
33
|
|
|
33
34
|
function rootType(rootPath, kind) {
|
|
34
35
|
if (kind === 'repo') return 'repo.git';
|
|
@@ -37,18 +38,10 @@ function rootType(rootPath, kind) {
|
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
function isRepository(dirPath) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
// A failed look cannot prove a repo boundary. Register the readable
|
|
45
|
-
// shape below it; observer territory detection retries the boundary
|
|
46
|
-
// look and performs the UUID-preserving folder → repo.git transition
|
|
47
|
-
// once Git becomes knowable.
|
|
48
|
-
if (error.code === 'ENOENT' || error.code === 'ENOTDIR'
|
|
49
|
-
|| error.code === 'EACCES' || error.code === 'EPERM') return false;
|
|
50
|
-
throw error;
|
|
51
|
-
}
|
|
41
|
+
// This is the observer's exact territory primitive. In particular, a
|
|
42
|
+
// stale linked-worktree pointer must be ordinary folder ground for both
|
|
43
|
+
// structural registration and later Watch/Detect reconciliation.
|
|
44
|
+
return gitDirTruth(dirPath) === 'present';
|
|
52
45
|
}
|
|
53
46
|
|
|
54
47
|
/**
|
|
@@ -63,6 +63,21 @@ test('a .git claims its subtree: embedded repos are never files territory', () =
|
|
|
63
63
|
));
|
|
64
64
|
});
|
|
65
65
|
|
|
66
|
+
test('a stale linked-worktree pointer is ordinary folder ground, not a broken repository', () => {
|
|
67
|
+
const dir = makeDir('stale-gitfile');
|
|
68
|
+
const child = path.join(dir, 'former-submodule');
|
|
69
|
+
fs.mkdirSync(child);
|
|
70
|
+
fs.writeFileSync(path.join(child, '.git'), 'gitdir: ../.git/modules/missing\n');
|
|
71
|
+
fs.writeFileSync(path.join(child, 'readme.md'), 'still ordinary files');
|
|
72
|
+
|
|
73
|
+
const { observer, events } = makeObserver();
|
|
74
|
+
observer.enrollRoot(dir);
|
|
75
|
+
|
|
76
|
+
assert.deepEqual(eventsOf(events, 'repo.discovered'), []);
|
|
77
|
+
assert.deepEqual(eventsOf(events, 'file.created').map((event) => event.path), ['former-submodule/readme.md']);
|
|
78
|
+
assert.equal(observer.listRoots().some((root) => root.path === child && root.kind === 'repo'), false);
|
|
79
|
+
});
|
|
80
|
+
|
|
66
81
|
test('a .git vanishing returns its territory to files: channels are reborn', () => {
|
|
67
82
|
const dir = makeDir('territory-back');
|
|
68
83
|
fs.mkdirSync(path.join(dir, 'vendor', '.git'), { recursive: true });
|