feat: modified file check
This commit is contained in:
parent
05c59937e9
commit
9f24f812c9
@ -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();
|
||||
|
@ -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(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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> {
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user