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 { promises, type Stats } from "node:fs";
|
||||||
import path, { extname } from "node:path";
|
import path, { extname } from "node:path";
|
||||||
import type { DocumentBody } from "dbtype";
|
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
|
* content file or directory referrer
|
||||||
*/
|
*/
|
||||||
@ -30,7 +30,7 @@ export const createDefaultClass = (type: string): ContentFileConstructor => {
|
|||||||
protected hash: string | undefined;
|
protected hash: string | undefined;
|
||||||
protected stat: Stats | undefined;
|
protected stat: Stats | undefined;
|
||||||
|
|
||||||
protected getStat(){
|
protected getStat() {
|
||||||
return this.stat;
|
return this.stat;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ export const createDefaultClass = (type: string): ContentFileConstructor => {
|
|||||||
async createDocumentBody(): Promise<DocumentBody> {
|
async createDocumentBody(): Promise<DocumentBody> {
|
||||||
console.log(`createDocumentBody: ${this.path}`);
|
console.log(`createDocumentBody: ${this.path}`);
|
||||||
const { base, dir, name } = path.parse(this.path);
|
const { base, dir, name } = path.parse(this.path);
|
||||||
|
|
||||||
const ret = {
|
const ret = {
|
||||||
title: name,
|
title: name,
|
||||||
basepath: dir,
|
basepath: dir,
|
||||||
@ -61,9 +61,17 @@ export const createDefaultClass = (type: string): ContentFileConstructor => {
|
|||||||
}
|
}
|
||||||
async getHash(): Promise<string> {
|
async getHash(): Promise<string> {
|
||||||
if (this.hash !== undefined) return this.hash;
|
if (this.hash !== undefined) return this.hash;
|
||||||
const hash = await oshash(this.path);
|
try {
|
||||||
this.hash = hash.toString();
|
const hash = await oshash(this.path);
|
||||||
return this.hash;
|
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> {
|
async getMtime(): Promise<number> {
|
||||||
const oldStat = this.getStat();
|
const oldStat = this.getStat();
|
||||||
|
@ -34,7 +34,8 @@ export class ContentDiffHandler {
|
|||||||
diff
|
diff
|
||||||
.on("create", (path) => this.OnCreated(path))
|
.on("create", (path) => this.OnCreated(path))
|
||||||
.on("delete", (path) => this.OnDeleted(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) {
|
private async OnDeleted(cpath: string) {
|
||||||
const basepath = dirname(cpath);
|
const basepath = dirname(cpath);
|
||||||
@ -126,4 +127,27 @@ export class ContentDiffHandler {
|
|||||||
filename: cur_filename,
|
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;
|
create: (path: string) => void;
|
||||||
delete: (path: string) => void;
|
delete: (path: string) => void;
|
||||||
change: (prev_path: string, cur_path: string) => void;
|
change: (prev_path: string, cur_path: string) => void;
|
||||||
|
modify: (path: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IDiffWatcher extends event.EventEmitter {
|
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("create", (p) => toWatcher.emit("create", p));
|
||||||
fromWatcher.on("delete", (p) => toWatcher.emit("delete", p));
|
fromWatcher.on("delete", (p) => toWatcher.emit("delete", p));
|
||||||
fromWatcher.on("change", (p, c) => toWatcher.emit("change", p, c));
|
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));
|
this.emit("delete", join(this.path, filename));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (eventType === "change") {
|
||||||
|
this.emit("modify", join(this.path, filename));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async setup(cntr: DocumentAccessor): Promise<void> {
|
async setup(cntr: DocumentAccessor): Promise<void> {
|
||||||
|
@ -47,6 +47,11 @@ export class RecursiveWatcher extends EventEmitter implements IDiffWatcher {
|
|||||||
const cpath = path;
|
const cpath = path;
|
||||||
// console.log("unlink ", cpath);
|
// console.log("unlink ", cpath);
|
||||||
this.emit("delete", cpath);
|
this.emit("delete", cpath);
|
||||||
|
})
|
||||||
|
.on("change", (path) => {
|
||||||
|
const cpath = path;
|
||||||
|
// console.log("change ", cpath);
|
||||||
|
this.emit("modify", cpath);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (option.watchDir) {
|
if (option.watchDir) {
|
||||||
|
@ -28,9 +28,11 @@ export class WatcherFilter extends EventEmitter implements IDiffWatcher {
|
|||||||
return super.emit("create", cur);
|
return super.emit("create", cur);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}if (!this.filter(arg[0])) {
|
}
|
||||||
|
if (!this.filter(arg[0])) {
|
||||||
return false;
|
return false;
|
||||||
}return super.emit(event, ...arg);
|
}
|
||||||
|
return super.emit(event, ...arg);
|
||||||
}
|
}
|
||||||
constructor(refWatcher: IDiffWatcher, filter: (filename: string) => boolean) {
|
constructor(refWatcher: IDiffWatcher, filter: (filename: string) => boolean) {
|
||||||
super();
|
super();
|
||||||
|
@ -1,4 +1,12 @@
|
|||||||
import { open } from "fs/promises";
|
import { open } from "fs/promises";
|
||||||
|
|
||||||
|
export class OshashError extends Error {
|
||||||
|
constructor(message: string) {
|
||||||
|
super(message);
|
||||||
|
this.name = "OshashError";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get hash of file or directory.
|
* get hash of file or directory.
|
||||||
*
|
*
|
||||||
@ -22,7 +30,7 @@ export async function oshash(
|
|||||||
if (st.size < minFileSize){
|
if (st.size < minFileSize){
|
||||||
if (st.size < 8) {
|
if (st.size < 8) {
|
||||||
fd.close();
|
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,
|
// Although the original oshash algorithm should throw an exception,
|
||||||
// just applying the hash function.
|
// just applying the hash function.
|
||||||
|
Loading…
Reference in New Issue
Block a user