import {basename, dirname, join as pathjoin} from 'path'; import {Document, DocumentAccessor} from '../model/mod'; import { ContentFile, createContentFile } from '../content/mod'; import {IDiffWatcher} from './watcher'; import {ContentList} from './content_list'; //refactoring needed. export class ContentDiffHandler{ /** content file list waiting to add */ waiting_list:ContentList; /** deleted contents */ tombstone: Map;//hash, contentfile doc_cntr: DocumentAccessor; /** content type of handle */ content_type: string; constructor(cntr: DocumentAccessor,content_type:string){ this.waiting_list = new ContentList(); this.tombstone = new Map(); this.doc_cntr = cntr; this.content_type = content_type; } async setup(){ const deleted = await this.doc_cntr.findDeleted(this.content_type); for (const it of deleted) { this.tombstone.set(it.content_hash,it); } } register(diff:IDiffWatcher){ diff.on('create',(path)=>this.OnCreated(path)) .on('delete',(path)=>this.OnDeleted(path)) .on('change',(prev,cur)=>this.OnChanged(prev,cur)); } private async OnDeleted(cpath: string){ const basepath = dirname(cpath); const filename = basename(cpath); console.log("deleted ",cpath); //if it wait to add, delete it from waiting list. if(this.waiting_list.hasByPath(cpath)){ this.waiting_list.deleteByPath(cpath); return; } const dbc = await this.doc_cntr.findByPath(basepath,filename); //when there is no related content in db, ignore. if(dbc.length === 0) return; const content_hash = dbc[0].content_hash; // When a path is changed, it takes into account when the // creation event occurs first and the deletion occurs, not // the change event. const cf = this.waiting_list.getByHash(content_hash); if(cf){ //if a path is changed, update the changed path. console.log("update path from", cpath,"to",cf.path); const newFilename = basename(cf.path); const newBasepath = dirname(cf.path); await this.waiting_list.deleteByHash(content_hash); await this.doc_cntr.update({ id:dbc[0].id, deleted_at: null, filename:newFilename, basepath:newBasepath, }); return; } //invalidate db and add it to tombstone. await this.doc_cntr.update({ id:dbc[0].id, deleted_at: Date.now(), }); this.tombstone.set(dbc[0].content_hash, dbc[0]); } private async OnCreated(cpath:string){ const basepath = dirname(cpath); const filename = basename(cpath); console.log("createContentFile", cpath); const content = createContentFile(this.content_type,pathjoin(basepath,filename)); const hash = await content.getHash(); const c = this.tombstone.get(hash); if(c !== undefined){ this.doc_cntr.update({ id: c.id, deleted_at: null, filename:filename, basepath:basepath }); return; } if(this.waiting_list.hasByHash(hash)){ console.log("Conflict!!!"); } this.waiting_list.set(content); } private async OnChanged(prev_path:string,cur_path:string){ const prev_basepath = dirname(prev_path); const prev_filename = basename(prev_path); const cur_basepath = dirname(cur_path); const cur_filename = basename(cur_path); const doc = await this.doc_cntr.findByPath(prev_basepath,prev_filename); await this.doc_cntr.update({...doc[0], basepath:cur_basepath, filename:cur_filename}); } }