Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Metadata Manager] merge all event handler #48

Merged
merged 19 commits into from
Sep 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
2cbf43b
[Event Handler] create watcher for event handling
khlee025 Sep 18, 2022
c079739
[Metadata Manager] track the path of event target file
khlee025 Sep 20, 2022
5f9053b
[Metadata Manager] add event exception for .meta directory
khlee025 Sep 21, 2022
25cfa8e
Merge branch 'manager' of https://github.com/SSDC-AndroMETA/ONE-vscod…
khlee025 Sep 21, 2022
d60ec21
[Metadata Manager] add function to access metadata
khlee025 Sep 21, 2022
7e53dc5
[Metadata Manager] add baseline code to implement of event handler
khlee025 Sep 22, 2022
a0fecde
[Metadata Manager] Add delete event handler
smj53 Sep 23, 2022
cb6ad97
Merge branch 'metamanager/event' into metamanager/delete
khlee025 Sep 23, 2022
b8c5ac4
Merge pull request #36 from SSDC-AndroMETA/metamanager/delete
khlee025 Sep 23, 2022
bcbde19
[Metadata Manager] add change event function name
khlee025 Sep 23, 2022
eeda625
Merge branch 'metamanager/event' of https://github.com/SSDC-AndroMETA…
khlee025 Sep 23, 2022
2690965
[Metadata Manager] add change event function
khlee025 Sep 23, 2022
53dba3d
[Metadata Manager] add delete API to merge functions
khlee025 Sep 23, 2022
090ed4b
[Metadata Manager] merge request
khlee025 Sep 23, 2022
2fbafb6
[Metadata Manager] fix package-lock.json
khlee025 Sep 23, 2022
12bd062
[Metadata Manager] add create event handler
khlee025 Sep 26, 2022
6b234cc
[Metadata Manager] resolve the conflict from merge
khlee025 Sep 26, 2022
bd745ab
[Metadata Manager] fix event handler using modified API
khlee025 Sep 27, 2022
07e396c
[Metadata Manager] fix the bug
khlee025 Sep 27, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

171 changes: 89 additions & 82 deletions src/MetadataManager/EventManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import * as crypto from 'crypto';
/* istanbul ignore next */
export class MetadataEventManager {
private fileWatcher = vscode.workspace.createFileSystemWatcher(`**/*`); // glob pattern
private pathToHashObj:any;

public static didHideExtra: boolean = false;

Expand All @@ -60,50 +61,13 @@ export class MetadataEventManager {
}

const provider = new MetadataEventManager(workspaceRoot, context.extension.extensionKind);

// let timerId: NodeJS.Timeout | undefined=undefined;

// let uri = vscode.Uri.file("/home/pjt01/Workspace/Test_space/a.log") //string to vscode.Uri(type)
// let path = uri.fsPath; // file:///home/pjt01/Workspace/Test_space/a.log // vscode.Uri(type) to string
// provider.fileWatcher.onDidCreate(async uri => {
// console.log(uri); provider.refresh('Create'); // test code
// // case 1. Contents change event (when uri already in pathToHash)
// // case 2. Baseline event (when create file in file system or copy from external source)
// // case 3. Rename or Move File (processing like case 1 or ignore)
// // case 4. Generate Product from ONE (processing like case 1 or ignore)
// if (uri.fsPath.endsWith('a.log')){
// let path='a.log';
// console.log(1);
// let hash=await Metadata.contentHash(path);
// console.log(hash);
// let content=await Metadata.getMetadata(hash);
// console.log(content);
// content['b.log']="Test";
// await Metadata.setMetadata(hash, content);
// }
// }),
// vscode.workspace.onDidRenameFiles(uri => {
// provider.refresh('Rename'); //test code

// if(provider.isValidFile(uri['files'][0]['oldUri'].fsPath) && provider.isValidFile(uri['files'][0]['newUri'].fsPath)){
// // case 1. file rename > command event
// console.log('Yes Rename');
// }
// else if(fs.statSync(uri['files'][0]['newUri'].fsPath).isDirectory()){
// // case 2. Directory check > child(pathToHash) updated & command event
// console.log('Directory Rename');
// }
// else{
// // case 3. ignore
// console.log('No Rename');
// }
// }),
let timerId:NodeJS.Timeout | undefined=undefined;

let registrations = [
provider.fileWatcher.onDidChange(async uri => {
provider.refresh('Change'); // test code
console.log('onDidChange '+uri.fsPath);
if(workspaceRoot){ await provider.changeEvent(workspaceRoot.fsPath, uri.fsPath);}
if(workspaceRoot){ await provider.changeEvent(uri);}
}),
provider.fileWatcher.onDidDelete(async uri => { // To Semi Jeong
// FIXME: declare PathToHash instance outside of the function (i.e. make instance member variable)
Expand Down Expand Up @@ -136,55 +100,39 @@ export class MetadataEventManager {
provider.refresh('Create'); // test code
console.log('onDidCreate '+uri.fsPath);
MetadataEventManager.createUri=uri;
let relPath=vscode.workspace.asRelativePath(uri);
// case 1. [File] Contents change event (refer to pathToHash)
// case 2(ignore). [File] Move contents > Processing in Delete
// case 3(ignore). [Dir] Move contents > Processing in Delete (reconginition Dir when Dir+File moved)
// case 4. [File] Copy many files
// case 5. [Dir] Copy with files > Serch all the file in the Dir
// case 4. [File] Generate Product from ONE (processing like case 1 or ignore)
if(fs.statSync(uri.fsPath).isDirectory()){
//provider.createDir(); (1) call search > listup files > while [case4]
await provider.createDirEvent(uri);
}
else if(provider.isValidFile(uri.fsPath)){
//if(pathToHash()){await provider.changeEvent(workspaceRoot.fsPath, uri.fsPath }
//else{}
else if(Metadata.isValidFile(uri)){
if(provider.pathToHashObj.getPathToHash(uri)&&workspaceRoot){await provider.changeEvent(uri);}
else{await provider.createFileEvent(uri);}
}


//if dir
// [case 5] > (1) call search > listup files > while [case4]
//else files
// validcheck(endswith)
// pathToHash search [case 1] > (1) call contentHash (2) change pathToHash (3) deactivate hash from pathToHash (4) insert hash from contentHash
// [case 4] > (1) call contentHash (2) getMetadata (3) compare to path(activate?) > Yes(ignore), No(Setup)
let temp=await vscode.workspace.findFiles('a.log/**');
console.log(temp);
timerId=setTimeout(()=>{MetadataEventManager.createUri=undefined; console.log('test '+ MetadataEventManager.createUri);},0);
////// case 1. [File] Contents change event (refer to pathToHash)
////// case 2(ignore). [File] Move contents > Processing in Delete
////// case 3(ignore). [Dir] Move contents > Processing in Delete (reconginition Dir when Dir+File moved)
// case 4. [File] Copy many files
// case 5. [Dir] Copy with files > Serch all the file in the Dir
// *if already exist, ignore the creation events.
// *always new path.
// *
// case 4. [File] Generate Product from ONE (processing like case 1 or ignore)
}),
];

registrations.forEach(disposable => context.subscriptions.push(disposable));
}

constructor(private workspaceRoot: vscode.Uri | undefined, private _extensionKind: vscode.ExtensionKind) {
PathToHash.getInstance().then(data=>{this.pathToHashObj=data});
}

refresh(message: string): void {
vscode.window.showInformationMessage(message);
}

isValidFile(path: string): boolean{
let ends=['.pb','.onnx','.tflite','.circle','.cfg','.log'];
return ends.some((x)=>path.endsWith(x));
}

async changeEvent(root: string, path: string): Promise<void> {
async changeEvent(uri:vscode.Uri): Promise<void> {
// case 1. [File] Contents change event
const relativePath = path.split(root+'/')[1];
const uri = vscode.Uri.file(path);
const relativePath = vscode.workspace.asRelativePath(uri);
console.log(uri);
console.log(1, relativePath);

Expand All @@ -204,7 +152,7 @@ export class MetadataEventManager {
if(metadata[relativePath]) { // TODO: change path to filename
// step 4. If exists, deactivate (set deleted_time) that path.
// FIXME: Do we need to deactivate it from pathToHash too? > If we deactivate pathToHash, if rename event came, we cannot specify what hash value the path is for.
metadata[relativePath]["deleted_time"] = new Date();
metadata[relativePath]["is_deleted"] = true;
console.log(6, metadata);
// await Metadata.setMetadata(beforehash, metadata);
}
Expand All @@ -224,30 +172,89 @@ export class MetadataEventManager {
console.log(9, await Metadata.getMetadata(afterhash));

const afterMetadata: any = {};
const filename: any = path.split('/').pop();
const stats: any = await MetadataEventManager.getStats(afterhash);
const filename: any = relativePath.split('/').pop();
const stats: any = await MetadataEventManager.getStats(uri);
console.log(stats);

afterMetadata[filename] = {};
afterMetadata[filename]["name"] = filename.split(".")[0];
afterMetadata[filename]["file_extension"] = filename.split(".")[1];
afterMetadata[filename]["create_time"] = stats.birthtime;
afterMetadata[filename]["modified_time"] = stats.mtime;
afterMetadata[filename]["deleted_time"] = "삭제 시각(date)"; // TODO: 빈문자열?
afterMetadata[relativePath] = {};
afterMetadata[relativePath]["name"] = filename;
afterMetadata[relativePath]["file_extension"] = filename.split(".")[1];
afterMetadata[relativePath]["create_time"] = stats.birthtime;
afterMetadata[relativePath]["modified_time"] = stats.mtime;
afterMetadata[relativePath]["is_deleted"] = false;
await Metadata.setMetadata(afterhash, afterMetadata);

console.log(11, await Metadata.getMetadata(afterhash));
//afterMetadata[path]=data;
}

public static getStats(hash:any) {
public static getStats(uri:vscode.Uri) {
return new Promise(function (resolve, reject) {
fs.stat(vscode.Uri.file(obtainWorkspaceRoot()).fsPath + `/.meta/hash_objects/${hash.substring(0, 2)}/${hash.substring(2)}.json`, function (err, stats) {
fs.stat(uri.fsPath, function (err, stats) {
if (err) {
return reject(err);
}
return resolve(stats);
});
});
}
}

async createDirEvent(uri:vscode.Uri){
//(1) call search
let fileList=await vscode.workspace.findFiles('**'+uri.fsPath+'/*.{pb,log,onnx,tflite,circle,cfg}');
fileList.forEach((uri)=>{
this.createFileEvent(uri);
})
}

async createFileEvent(uri:vscode.Uri){
//(1) refer to getPathToHash
let relPath=vscode.workspace.asRelativePath(uri);

//(2) insert PathToHash
await this.pathToHashObj.addPath(uri);
let newHash=await this.pathToHashObj.getPathToHash(uri);

//(3) Hash로 getMetadata
let metadata=await Metadata.getMetadata(newHash);
//(4) Metadata Exist (searching with Hash)? (activate | deactivate) : copy format
if(Object.keys(metadata).length !== 0){ // metadata exist
if(metadata[relPath]){
if (!metadata[relPath]["is_deleted"]) return; // path already activate. ignore this case
metadata[relPath]["is_deleted"]=false; // path deactive > activate
}
else{ // for copy format
const keyList=Object.keys(metadata);
const keyResult=keyList.filter(key=> !metadata[key]["is_deleted"]) // find activate. or last key of KeyList;

//data copy
let data=metadata[keyList[keyList.length-1]];
if(keyResult.length){ data=metadata[keyResult[0]]; }
else {data["is_deleted"]=false;}


//data update
const stats: any = await MetadataEventManager.getStats(uri);
data["name"]=uri.fsPath.split('/').pop();
data["file_extension"]=uri.fsPath.split('.').pop();
data["created_time"]=stats.birthtime;
data["modified_time"]=stats.mtime;

metadata[relPath]=data;
}
}
else{ // metadata doesn't exist : common file
const splitPath=uri.fsPath.split('.');
const stats: any = await MetadataEventManager.getStats(uri);

metadata[relPath]={
"name":uri.fsPath.split('/').pop(),
"file_extension": uri.fsPath.split('.').pop(),
"created_time": stats.birthtime,
"modified_time": stats.mtime,
"is_deleted": false,
};
}
//(6) Metadata Generation
await Metadata.setMetadata(newHash,metadata);
}
}
37 changes: 27 additions & 10 deletions src/MetadataManager/metadataAPI.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import * as vscode from 'vscode';
import * as crypto from 'crypto';
import * as fs from 'fs';
import { obtainWorkspaceRoot } from '../Utils/Helpers';
import { PathToHash } from './pathToHash';

Expand All @@ -22,7 +24,8 @@ interface Data{
"is_deleted" : boolean
}

export class Metadata {

export class Metadata{
private _disposables: vscode.Disposable[] = [];
constructor() { }
public static register(context: vscode.ExtensionContext): void {
Expand Down Expand Up @@ -179,13 +182,13 @@ export class Metadata {
const relationUri = vscode.Uri.joinPath(vscode.workspace.workspaceFolders[0].uri, ".meta/relation.json");
const relationJSON: any = JSON.parse(Buffer.from(await vscode.workspace.fs.readFile(relationUri)).toString());

// 반환 객체 생성
// Return Object generation
const relations: Relation = {
"selected" : "",
"relationData" : []
};

// 현재 노드 메타데이터 불러오기
// load metadata of target node

const nowMetadata: any = await this.getMetadata(nowHash);

Expand All @@ -194,7 +197,7 @@ export class Metadata {
relations.relationData.push({ "id": nowHash, "parent": relationJSON[nowHash].parent, "representIdx": 0, "dataList": this.getDataList(nowMetadata) });


// 부모 노드 찾기
// find parents node
let tempHash: string = relationJSON[nowHash].parent;
while (true) {

Expand All @@ -210,7 +213,7 @@ export class Metadata {
}
}

// 자식 노드 찾기
// find child node
let tempHashs: string[] = relationJSON[nowHash].children;
while (true) {
let hashs: string[] = [];
Expand All @@ -237,15 +240,22 @@ export class Metadata {
}

//get all Metadata of same hash object by hash
//This function should be called after building PathToHash.
public static async getMetadata(hash: string) {
if (vscode.workspace.workspaceFolders !== undefined) {
const metaUri = vscode.Uri.joinPath(vscode.workspace.workspaceFolders[0].uri, `.meta/hash_objects/${hash.substring(0, 2)}/${hash.substring(2)}.json`);
return JSON.parse(Buffer.from(await vscode.workspace.fs.readFile(metaUri)).toString());
const metaUri = vscode.Uri.joinPath(vscode.workspace.workspaceFolders[0].uri, `.meta/hash_objects/${hash.substring(0, 2)}/${hash.substring(2)}.json`);
if(!fs.existsSync(metaUri.fsPath)) {
await vscode.workspace.fs.writeFile(metaUri,Buffer.from(JSON.stringify({}, null, 4),'utf8'));
return {};
}
else {
return JSON.parse(Buffer.from(await vscode.workspace.fs.readFile(metaUri)).toString());
}
}
}

//set all Metadata of same hash object by hash
public static async setMetadata(hash: string | undefined, value: object) { //.meta 기준 relative path [=== workspace assert 로직이 필요할 것 같다.]
public static async setMetadata(hash: string | undefined, value: object) {
const workspaceroot=obtainWorkspaceRoot();
if(hash){
const Uri = vscode.Uri.joinPath(vscode.Uri.file(workspaceroot), `.meta/hash_objects/${hash.substring(0, 2)}/${hash.substring(2)}.json`);
Expand All @@ -266,12 +276,19 @@ export class Metadata {
"toolchain_version": element.toolchain_version,
"is_deleted":element.is_deleted
};

dataList.push(data);
}

return dataList;
}
// public static d_getFilesUnderDir(path: string): string[] { // to Semi Jeong : is this function really needed?
// if (Metadata.d_isDir(path)) {
// // FIXME: what will be returned when we call?
// return ['test/while_000.log', 'test/while_000 copy.log'];
// }
// return []; // 파일일 때
// }

// return dataList;
}


7 changes: 4 additions & 3 deletions src/MetadataManager/pathToHash.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as vscode from 'vscode';
import * as crypto from 'crypto';
import { ConsoleReporter } from '@vscode/test-electron';

export class PathToHash{
private static instance: PathToHash;
Expand Down Expand Up @@ -83,19 +84,19 @@ export class PathToHash{
public isFile(uri: vscode.Uri): boolean {
const relativeFolderPath = vscode.workspace.asRelativePath(uri);
console.log(`PathToHash::isFile():: relativeFolderPath=${relativeFolderPath}`);
const hash = this.getPathToHash(relativeFolderPath);
const hash = this.getPathToHash(uri);
console.log(typeof(hash) === 'string')
return typeof(hash) === 'string';
}

public exists(uri: vscode.Uri): boolean {
return this.getPathToHash(vscode.workspace.asRelativePath(uri)) !== undefined;
return this.getPathToHash(uri) !== undefined;
}

public getFilesUnderFolder(uri: vscode.Uri): vscode.Uri[] {
const relativeFolderPath = vscode.workspace.asRelativePath(uri);
console.log(`PathToHash::getFilesUnderFolder():: relativeFolderPath=${relativeFolderPath}`);
const folder = this.getPathToHash(relativeFolderPath);
const folder = this.getPathToHash(uri);
const files: vscode.Uri[] = [];
if (typeof (folder) === 'string') {
// not a folder
Expand Down