@lisang233/pi-sync 0.2.0 → 0.2.1
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/operations.ts +1 -1
- package/src/status.ts +27 -9
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lisang233/pi-sync",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Personal Pi extension that syncs Pi configuration through Git with background auto-sync and git-style fetch/merge conflict handling.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
package/src/operations.ts
CHANGED
|
@@ -76,7 +76,7 @@ async function computeState(config: SyncConfig, signal?: AbortSignal): Promise<S
|
|
|
76
76
|
readMergeBase(config, { signal }),
|
|
77
77
|
isMergeInProgress({ signal }),
|
|
78
78
|
]);
|
|
79
|
-
return classifyState(local, remote, base, mergePending);
|
|
79
|
+
return classifyState(local, remote, base, mergePending, config.include);
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
export async function status(
|
package/src/status.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { pathMatchesInclude } from "./tree.js";
|
|
2
|
+
|
|
1
3
|
export type SyncStateLabel =
|
|
2
4
|
| "unconfigured"
|
|
3
5
|
| "unknown"
|
|
@@ -37,17 +39,29 @@ export interface StateClassify {
|
|
|
37
39
|
* `base` is the content map at the merge-base (empty when there is none, e.g.
|
|
38
40
|
* a brand-new branch with no shared history). A path present in local & remote
|
|
39
41
|
* with different content and no base is conservatively a divergence.
|
|
42
|
+
*
|
|
43
|
+
* `include` is the include declaration. The remote and base maps are projected
|
|
44
|
+
* onto the include scope before comparison, so out-of-include paths (for
|
|
45
|
+
* example legacy `pi-sync/home/...` remnants from the old single-snapshot
|
|
46
|
+
* architecture) never pollute the state. A path the local side does not contain
|
|
47
|
+
* is never treated as a local change, which fixes the false "ahead" when the
|
|
48
|
+
* remote carries leftover paths the local never synced.
|
|
40
49
|
*/
|
|
41
50
|
export function classifyState(
|
|
42
51
|
local: Map<string, string>,
|
|
43
52
|
remote: Map<string, string>,
|
|
44
53
|
base: Map<string, string>,
|
|
45
54
|
mergePending: boolean,
|
|
55
|
+
include: string[],
|
|
46
56
|
): StateClassify {
|
|
57
|
+
const inInclude = (p: string) => include.some((entry) => pathMatchesInclude(p, entry));
|
|
58
|
+
const remoteP = new Map([...remote].filter(([p]) => inInclude(p)));
|
|
59
|
+
const baseP = new Map([...base].filter(([p]) => inInclude(p)));
|
|
60
|
+
|
|
47
61
|
if (mergePending) {
|
|
48
|
-
const diverged = [...new Set([...local.keys(), ...
|
|
49
|
-
(p) => local.get(p) !==
|
|
50
|
-
|
|
62
|
+
const diverged = [...new Set([...local.keys(), ...remoteP.keys()])]
|
|
63
|
+
.filter((p) => local.get(p) !== remoteP.get(p))
|
|
64
|
+
.filter(inInclude);
|
|
51
65
|
return {
|
|
52
66
|
label: "conflict",
|
|
53
67
|
ahead: 0,
|
|
@@ -58,24 +72,28 @@ export function classifyState(
|
|
|
58
72
|
diverged,
|
|
59
73
|
};
|
|
60
74
|
}
|
|
61
|
-
const paths = [...new Set([...local.keys(), ...
|
|
75
|
+
const paths = [...new Set([...local.keys(), ...remoteP.keys()])].filter(inInclude).sort();
|
|
62
76
|
const localChanged: string[] = [];
|
|
63
77
|
const remoteChanged: string[] = [];
|
|
64
78
|
const diverged: string[] = [];
|
|
65
79
|
for (const filePath of paths) {
|
|
66
80
|
const localContent = local.get(filePath);
|
|
67
|
-
const remoteContent =
|
|
81
|
+
const remoteContent = remoteP.get(filePath);
|
|
68
82
|
if (localContent === remoteContent) continue;
|
|
69
|
-
const baseContent =
|
|
70
|
-
const
|
|
71
|
-
|
|
83
|
+
const baseContent = baseP.get(filePath);
|
|
84
|
+
const baseHas = baseContent !== undefined;
|
|
85
|
+
// A side is "changed" only if it actually holds the path and its content
|
|
86
|
+
// differs from the base (an added or deleted file counts). Without a base
|
|
87
|
+
// (fresh branch) fall back to "the side holds the path".
|
|
88
|
+
const localChangedSide = baseHas ? localContent !== baseContent : localContent !== undefined;
|
|
89
|
+
const remoteChangedSide = baseHas ? remoteContent !== baseContent : remoteContent !== undefined;
|
|
72
90
|
if (localChangedSide && remoteChangedSide) diverged.push(filePath);
|
|
73
91
|
else if (localChangedSide) localChanged.push(filePath);
|
|
74
92
|
else if (remoteChangedSide) remoteChanged.push(filePath);
|
|
75
93
|
}
|
|
76
94
|
|
|
77
95
|
let label: SyncStateLabel;
|
|
78
|
-
if (
|
|
96
|
+
if (remoteP.size === 0) label = "unpublished";
|
|
79
97
|
else if (diverged.length > 0 || (localChanged.length > 0 && remoteChanged.length > 0)) {
|
|
80
98
|
label = "conflict";
|
|
81
99
|
} else if (remoteChanged.length > 0) {
|