feat: modified file check

This commit is contained in:
monoid 2024-11-16 04:14:41 +09:00
parent 05c59937e9
commit 9f24f812c9
7 changed files with 62 additions and 10 deletions

View File

@ -2,7 +2,7 @@ import { createHash } from "node:crypto";
import { promises, type Stats } from "node:fs";
import path, { extname } from "node:path";
import type { DocumentBody } from "dbtype";
import { oshash } from "src/util/oshash.ts";
import { oshash, OshashError } from "src/util/oshash.ts";
/**
* content file or directory referrer
*/
@ -30,7 +30,7 @@ export const createDefaultClass = (type: string): ContentFileConstructor => {
protected hash: string | undefined;
protected stat: Stats | undefined;
protected getStat(){
protected getStat() {
return this.stat;
}
@ -61,9 +61,17 @@ export const createDefaultClass = (type: string): ContentFileConstructor => {
}
async getHash(): Promise<string> {
if (this.hash !== undefined) return this.hash;
const hash = await oshash(this.path);
this.hash = hash.toString();
return this.hash;
try {
const hash = await oshash(this.path);
this.hash = hash.toString();
return this.hash;
} catch (error) {
if (error instanceof OshashError) {
// too short to hash
return "0";
}
throw error;
}
}
async getMtime(): Promise<number> {
const oldStat = this.getStat();

View File

@ -34,7 +34,8 @@ export class ContentDiffHandler {
diff
.on("create", (path) => this.OnCreated(path))
.on("delete", (path) => this.OnDeleted(path))
.on("change", (prev, cur) => this.OnChanged(prev, cur));
.on("change", (prev, cur) => this.OnChanged(prev, cur))
.on("modify", (path) => this.onModified(path));
}
private async OnDeleted(cpath: string) {
const basepath = dirname(cpath);
@ -126,4 +127,27 @@ export class ContentDiffHandler {
filename: cur_filename,
});
}
async onModified(path: string) {
const content = createContentFile(this.content_type, path);
// if it is in waiting list, update it.
if (this.waiting_list.hasByPath(path)) {
this.waiting_list.set(content);
return;
}
// if it is not in waiting list, check it in db.
const basepath = dirname(path);
const filename = basename(path);
const doc = await this.doc_cntr.findByPath(basepath, filename);
if (doc.length === 0) {
// if it is not in db, add it to waiting list. because it can happen that the file creation event occurs after the file modification event.
this.waiting_list.set(content);
return;
}
// if it is in db, update it.
await this.doc_cntr.update({
...doc[0],
content_hash: await content.getHash(),
modified_at: Date.now(),
});
}
}

View File

@ -10,6 +10,7 @@ export interface DiffWatcherEvent {
create: (path: string) => void;
delete: (path: string) => void;
change: (prev_path: string, cur_path: string) => void;
modify: (path: string) => void;
}
export interface IDiffWatcher extends event.EventEmitter {
@ -22,4 +23,5 @@ export function linkWatcher(fromWatcher: IDiffWatcher, toWatcher: IDiffWatcher)
fromWatcher.on("create", (p) => toWatcher.emit("create", p));
fromWatcher.on("delete", (p) => toWatcher.emit("delete", p));
fromWatcher.on("change", (p, c) => toWatcher.emit("change", p, c));
fromWatcher.on("modify", (p) => toWatcher.emit("modify", p));
}

View File

@ -33,6 +33,9 @@ export class CommonDiffWatcher extends event.EventEmitter implements IDiffWatche
this.emit("delete", join(this.path, filename));
}
}
if (eventType === "change") {
this.emit("modify", join(this.path, filename));
}
});
}
async setup(cntr: DocumentAccessor): Promise<void> {

View File

@ -47,6 +47,11 @@ export class RecursiveWatcher extends EventEmitter implements IDiffWatcher {
const cpath = path;
// console.log("unlink ", cpath);
this.emit("delete", cpath);
})
.on("change", (path) => {
const cpath = path;
// console.log("change ", cpath);
this.emit("modify", cpath);
});
}
if (option.watchDir) {

View File

@ -28,9 +28,11 @@ export class WatcherFilter extends EventEmitter implements IDiffWatcher {
return super.emit("create", cur);
}
return false;
}if (!this.filter(arg[0])) {
}
if (!this.filter(arg[0])) {
return false;
}return super.emit(event, ...arg);
}
return super.emit(event, ...arg);
}
constructor(refWatcher: IDiffWatcher, filter: (filename: string) => boolean) {
super();

View File

@ -1,4 +1,12 @@
import { open } from "fs/promises";
export class OshashError extends Error {
constructor(message: string) {
super(message);
this.name = "OshashError";
}
}
/**
* get hash of file or directory.
*
@ -22,7 +30,7 @@ export async function oshash(
if (st.size < minFileSize){
if (st.size < 8) {
fd.close();
throw new Error("Too short to hash");
throw new OshashError("Too short to hash");
}
// Although the original oshash algorithm should throw an exception,
// just applying the hash function.