mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2026-11-01 22:08:18 +00:00
Fix CLI internal path filtering on Windows
Split logical Vault paths on '/' on every platform so that internal database files and hidden path segments remain excluded when the database and Vault share a directory. Cover POSIX and Windows host separators through the real CLI bootstrap filter, preserving the omitted-Vault-path E2E scenario.
This commit is contained in:
1 parent
2433d117c2
commit
5e3e7e1330
3 files changed
+39
-1
No files matched your search
@@ -3,6 +3,7 @@ import { appendFile, mkdtemp, mkdir, readFile, rm, stat, writeFile } from "node:
|
|||||||
import { tmpdir } from "node:os";
|
import { tmpdir } from "node:os";
|
||||||
import { join } from "node:path";
|
import { join } from "node:path";
|
||||||
import * as chokidar from "chokidar";
|
import * as chokidar from "chokidar";
|
||||||
|
import { path } from "@vrtmrz/livesync-commonlib/node";
|
||||||
import * as offlineScanner from "@vrtmrz/livesync-commonlib/compat/serviceFeatures/offlineScanner";
|
import * as offlineScanner from "@vrtmrz/livesync-commonlib/compat/serviceFeatures/offlineScanner";
|
||||||
import { ControlService } from "@vrtmrz/livesync-commonlib/compat/services/base/ControlService";
|
import { ControlService } from "@vrtmrz/livesync-commonlib/compat/services/base/ControlService";
|
||||||
import {
|
import {
|
||||||
@@ -20,6 +21,11 @@ import { main, type CliCommandRunner } from "./main";
|
|||||||
import { cloneSettings } from "./settingsPersistence";
|
import { cloneSettings } from "./settingsPersistence";
|
||||||
import type { CLICommand } from "./commands/types";
|
import type { CLICommand } from "./commands/types";
|
||||||
|
|
||||||
|
vi.mock("@vrtmrz/livesync-commonlib/node", async (importOriginal) => {
|
||||||
|
const actual = await importOriginal<typeof import("@vrtmrz/livesync-commonlib/node")>();
|
||||||
|
return { ...actual, path: { ...actual.path } };
|
||||||
|
});
|
||||||
|
|
||||||
vi.mock("chokidar", { spy: true });
|
vi.mock("chokidar", { spy: true });
|
||||||
vi.mock("@vrtmrz/livesync-commonlib/compat/serviceFeatures/offlineScanner", { spy: true });
|
vi.mock("@vrtmrz/livesync-commonlib/compat/serviceFeatures/offlineScanner", { spy: true });
|
||||||
|
|
||||||
@@ -88,6 +94,36 @@ describe("CLI database preparation", () => {
|
|||||||
await expect(main(standardIo, runner)).rejects.toThrow(`__EXIT__:${exitCode}`);
|
await expect(main(standardIo, runner)).rejects.toThrow(`__EXIT__:${exitCode}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
it.each([
|
||||||
|
{ separator: "/", platform: "POSIX" },
|
||||||
|
{ separator: "\\", platform: "Windows" },
|
||||||
|
])("excludes internal Vault paths with the $platform host separator", async ({ separator }) => {
|
||||||
|
const targets = [
|
||||||
|
"headless-vault-livesync-v2/LOCK",
|
||||||
|
".livesync/settings.json",
|
||||||
|
"notes/.private/secret.md",
|
||||||
|
"notes/local.md",
|
||||||
|
];
|
||||||
|
const observed: boolean[] = [];
|
||||||
|
const runner = vi.fn<CliCommandRunner>(async (_options, { core }) => {
|
||||||
|
const originalSeparator = path.sep;
|
||||||
|
try {
|
||||||
|
Object.defineProperty(path, "sep", { value: separator });
|
||||||
|
for (const target of targets) {
|
||||||
|
observed.push(await core.services.vault.isTargetFile(target as FilePathWithPrefix));
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
Object.defineProperty(path, "sep", { value: originalSeparator });
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
await start("ls", runner);
|
||||||
|
|
||||||
|
expect(runner).toHaveBeenCalledOnce();
|
||||||
|
expect(observed).toEqual([false, false, false, true]);
|
||||||
|
});
|
||||||
|
|
||||||
it("loads legacy device values and persists configuration through the service-owned store", async () => {
|
it("loads legacy device values and persists configuration through the service-owned store", async () => {
|
||||||
const localStoragePath = join(directory, ".livesync", "runtime", "local-storage.json");
|
const localStoragePath = join(directory, ".livesync", "runtime", "local-storage.json");
|
||||||
await mkdir(join(directory, ".livesync", "runtime"), { recursive: true });
|
await mkdir(join(directory, ".livesync", "runtime"), { recursive: true });
|
||||||
|
|||||||
@@ -550,7 +550,7 @@ export async function main(
|
|||||||
// Add target filter to prevent internal files are handled
|
// Add target filter to prevent internal files are handled
|
||||||
core.services.vault.isTargetFile.addHandler(async (target) => {
|
core.services.vault.isTargetFile.addHandler(async (target) => {
|
||||||
const targetPath = stripAllPrefixes(getPathFromUXFileInfo(target));
|
const targetPath = stripAllPrefixes(getPathFromUXFileInfo(target));
|
||||||
const parts = targetPath.split(path.sep);
|
const parts = targetPath.split("/");
|
||||||
// if some part of the path starts with dot, treat it as internal file and ignore.
|
// if some part of the path starts with dot, treat it as internal file and ignore.
|
||||||
if (parts.some((part) => part.startsWith("."))) {
|
if (parts.some((part) => part.startsWith("."))) {
|
||||||
return await Promise.resolve(false);
|
return await Promise.resolve(false);
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ Earlier releases remain available in the 1.0 release history, the 1.0 preview hi
|
|||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
- The CLI mirror now starts correctly on Windows when the Vault path is omitted and the database directory is also used as the Vault. It checks logical Vault paths using `/` separators, correctly excluding internal database files and nested hidden directories even when the host uses Windows path separators.
|
||||||
|
|
||||||
## 1.0.43
|
## 1.0.43
|
||||||
|
|
||||||
30th October, 2026
|
30th October, 2026
|
||||||
|
|||||||
Reference in new issue
Block a user