Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions PeerStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,20 @@ export class PeerStorage extends Peer {
super(conf, dispatcher);
}

isExcludedPath(path: string): boolean {
if (!this.config.excludePrefixes || this.config.excludePrefixes.length === 0) {
return false;
}
// Exclude prefixes typically match the beginning of the file path.
// Let's normalize it to be sure we're matching string prefixes properly.
// The path being checked might be a posix path like "some_folder/file.txt".
return this.config.excludePrefixes.some(prefix => path.startsWith(prefix));
}

async delete(pathSrc: string): Promise<boolean> {
const lp = this.toLocalPath(pathSrc);
const relativePath = this.toPosixPath(pathSrc);
if (this.isExcludedPath(relativePath)) return false;
const path = this.toStoragePath(lp);
if (await this.isRepeating(lp, false)) {
return false;
Expand All @@ -39,6 +51,8 @@ export class PeerStorage extends Peer {
}
async put(pathSrc: string, data: FileData): Promise<boolean> {
const lp = this.toLocalPath(pathSrc);
const relativePath = this.toPosixPath(pathSrc);
if (this.isExcludedPath(relativePath)) return false;
const path = this.toStoragePath(lp);
if (await this.isRepeating(lp, data)) {
this.receiveLog(`${lp} save repeating`);
Expand Down Expand Up @@ -157,6 +171,8 @@ export class PeerStorage extends Peer {
const lP = this.toStoragePath(this.toLocalPath("."));
const path = this.toPosixPath(relative(lP, pathSrc));

if (this.isExcludedPath(path)) return;

const data = await this.get(path);

if (data === false) return;
Expand All @@ -177,6 +193,9 @@ export class PeerStorage extends Peer {
async dispatchDeleted(pathSrc: string) {
const lP = this.toStoragePath(this.toLocalPath("."));
const path = this.toPosixPath(relative(lP, pathSrc));

if (this.isExcludedPath(path)) return;

await scheduleOnceIfDuplicated(pathSrc, async () => {
await delay(250);
if (!await this.isRepeating(path, false)) {
Expand Down Expand Up @@ -260,6 +279,7 @@ export class PeerStorage extends Peer {
for await (const entry of walk(lP)) {
if (entry.isFile) {
const ePath = this.toPosixPath(relative(this.toLocalPath("."), entry.path));
if (this.isExcludedPath(ePath)) continue;
if (await this.isChanged(ePath)) {
this.debugLog(`Offline changes detected: ${ePath}`);
await this.dispatch(entry.path);
Expand Down
32 changes: 32 additions & 0 deletions tests/Patch5.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { assertEquals } from "jsr:@std/assert";
import { PeerStorage } from "../PeerStorage.ts";
import { PeerStorageConf } from "../types.ts";

Deno.test("PeerStorage - isExcludedPath", () => {
const config: PeerStorageConf = {
type: "storage",
name: "test-storage",
baseDir: "./test-dir",
excludePrefixes: [".git/", "node_modules/", "tmp_"]
};

// A dummy dispatcher function
const dummyDispatcher = async () => {};

const peer = new PeerStorage(config, dummyDispatcher);

assertEquals(peer.isExcludedPath(".git/config"), true);
assertEquals(peer.isExcludedPath("node_modules/package.json"), true);
assertEquals(peer.isExcludedPath("tmp_file.txt"), true);
assertEquals(peer.isExcludedPath("src/main.ts"), false);
assertEquals(peer.isExcludedPath("test-dir/.git/config"), false); // Exclude prefixes usually apply after baseDir resolution in dispatch, so the relative path is checked.

// Test with no excludePrefixes configured
const configNoExcludes: PeerStorageConf = {
type: "storage",
name: "test-storage-2",
baseDir: "./test-dir"
};
const peerNoExcludes = new PeerStorage(configNoExcludes, dummyDispatcher);
assertEquals(peerNoExcludes.isExcludedPath(".git/config"), false);
});
1 change: 1 addition & 0 deletions types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export interface PeerStorageConf {
args: string[]
}
useChokidar?: boolean;
excludePrefixes?: string[];
}
export interface PeerCouchDBConf extends DirectFileManipulatorOptions {
/** Glob patterns for i:-prefixed (internal) files to sync, e.g. [".claude/**"] */
Expand Down