This commit is contained in:
Manav Rathi 2024-04-18 21:07:00 +05:30
parent ca36b3c750
commit 76053c4029
No known key found for this signature in database
5 changed files with 53 additions and 65 deletions

View file

@ -224,7 +224,7 @@ export const attachIPCHandlers = () => {
export const attachFSWatchIPCHandlers = (watcher: FSWatcher) => {
// - Watch
ipcMain.handle("watchGet", () => watchGet());
ipcMain.handle("watchGet", () => watchGet(watcher));
ipcMain.handle(
"watchAdd",

View file

@ -3,6 +3,7 @@ import { BrowserWindow } from "electron/main";
import fs from "node:fs/promises";
import path from "node:path";
import { FolderWatch, type CollectionMapping } from "../../types/ipc";
import { fsIsDir } from "../fs";
import log from "../log";
import { watchStore } from "../stores/watch";
@ -52,77 +53,65 @@ const eventData = (path: string): [string, FolderWatch] => {
const posixPath = (filePath: string) =>
filePath.split(path.sep).join(path.posix.sep);
export const watchGet = () => {
return folderWatches();
export const watchGet = (watcher: FSWatcher) => {
const [valid, deleted] = folderWatches().reduce(
([valid, deleted], watch) => {
(fsIsDir(watch.folderPath) ? valid : deleted).push(watch);
return [valid, deleted];
},
[[], []],
);
if (deleted.length) {
for (const watch of deleted) watchRemove(watcher, watch.folderPath);
setFolderWatches(valid);
}
return valid;
};
const folderWatches = () => {
let watches = watchStore.get("mappings") ?? [];
// Previous versions of the store used to store an integer to indicate the
// collection mapping, migrate these to the new schema if we see them still.
let needsUpdate = false;
watches = watches.map((watch) => {
const cm = watch.collectionMapping;
if (cm != "root" && cm != "parent") {
const uploadStrategy = watch.uploadStrategy;
const collectionMapping = uploadStrategy == 1 ? "parent" : "root";
needsUpdate = true;
return { ...watch, collectionMapping }
}
})
if (watches.length && watches)
return mappings;
};
const folderWatches = (): FolderWatch[] => watchStore.get("mappings") ?? [];
const setFolderWatches = (watches: FolderWatch[]) =>
watchStore.set("mappings", watches);
export const watchAdd = async (
watcher: FSWatcher,
folderPath: string,
collectionMapping: CollectionMapping,
) => {
const watchMappings = getWatchMappings();
if (isMappingPresent(watchMappings, folderPath)) {
throw new Error(`Watch mapping already exists`);
}
const watches = folderWatches();
watcher.add(folderPath);
if (!fsIsDir(folderPath))
throw new Error(
`Attempting to add a folder watch for a folder path ${folderPath} that is not an existing directory`,
);
watchMappings.push({
rootFolderName,
uploadStrategy,
if (watches.find((watch) => watch.folderPath == folderPath))
throw new Error(
`A folder watch with the given folder path ${folderPath} already exists`,
);
watches.push({
folderPath,
collectionMapping,
syncedFiles: [],
ignoredFiles: [],
});
setWatchMappings(watchMappings);
setFolderWatches(watches);
watcher.add(folderPath);
};
function isMappingPresent(watchMappings: FolderWatch[], folderPath: string) {
const watchMapping = watchMappings?.find(
(mapping) => mapping.folderPath === folderPath,
);
return !!watchMapping;
}
export const watchRemove = async (watcher: FSWatcher, folderPath: string) => {
let watchMappings = getWatchMappings();
const watchMapping = watchMappings.find(
(mapping) => mapping.folderPath === folderPath,
);
if (!watchMapping) {
throw new Error(`Watch mapping does not exist`);
}
watcher.unwatch(watchMapping.folderPath);
watchMappings = watchMappings.filter(
(mapping) => mapping.folderPath !== watchMapping.folderPath,
);
setWatchMappings(watchMappings);
const watches = folderWatches();
const filtered = watches.filter((watch) => watch.folderPath != folderPath);
if (watches.length == filtered.length)
throw new Error(
`Attempting to remove a non-existing folder watch for folder path ${folderPath}`,
);
setFolderWatches(filtered);
watcher.unwatch(folderPath);
return filtered;
};
export function updateWatchMappingSyncedFiles(
@ -159,11 +148,6 @@ export function updateWatchMappingIgnoredFiles(
setWatchMappings(watchMappings);
}
function setWatchMappings(watchMappings: WatchStoreType["mappings"]) {
watchStore.set("mappings", watchMappings);
}
export const watchFindFiles = async (dirPath: string) => {
const items = await fs.readdir(dirPath, { withFileTypes: true });
let paths: string[] = [];

View file

@ -8,7 +8,9 @@ interface WatchStore {
type FolderWatchWithLegacyFields = FolderWatch & {
/** @deprecated Only retained for migration, do not use in other code */
uploadStrategy: number;
rootFolderName?: string;
/** @deprecated Only retained for migration, do not use in other code */
uploadStrategy?: number;
};
const watchStoreSchema: Schema<WatchStore> = {
@ -58,6 +60,10 @@ export const migrateLegacyWatchStoreIfNeeded = () => {
collectionMapping = watch.uploadStrategy == 1 ? "parent" : "root";
needsUpdate = true;
}
if (watch.rootFolderName) {
delete watch.rootFolderName;
needsUpdate = true;
}
return { ...watch, collectionMapping };
});
if (needsUpdate) {

View file

@ -11,8 +11,6 @@ export interface AppUpdate {
}
export interface FolderWatch {
// TODO(MR): Is this needed?
rootFolderName: string;
collectionMapping: CollectionMapping;
folderPath: string;
syncedFiles: FolderWatchSyncedFile[];

View file

@ -290,12 +290,12 @@ export interface Electron {
*/
watch: {
/**
* Return the list of folder watches.
* Return the list of folder watches, pruning non-existing directories.
*
* The list of folder paths (and auxillary details) is persisted in the
* Node.js layer. When we invoke this method, the Node.js goes through
* the list, permanently removes any watches whose on-disk directory has
* is no longer present, and returns this pruned list of watches.
* Node.js layer. The implementation of this function goes through the
* list, permanently removes any watches whose on-disk directory is no
* longer present, and returns this pruned list of watches.
*/
get: () => Promise<FolderWatch[]>;