import fsys; import JSON; namespace fsys.asar; var canonicalize = ..fsys.path.canonicalize; var lower = ..string.lower; var push = ..table.push; class writer{ ctor(){ this.allFiles ={} this.map = {} }; add = function(path){ path = canonicalize(path); if( this.filter && !this.filter(path) ) return; var lowPath = lower(path); if(this.map[lowPath] ) return; this.map[lowPath] = true; push(this.allFiles,path); if( !..fsys.isDir(path) ) return; return ..fsys.enum(path,"*.*",this._fsysEnumCallback,false); }; _fsysEnumCallback = function(dir,filename,fullpath){ return this.add(fullpath) }; remove = function(path){ if(this.rootDirectory && !..string.indexOf(path,":") ){ path = ..io.joinpath(this.rootDirectory,path) } path = lower( canonicalize(path) ) var dir = ..fsys.path.addBackslash(path) var t = this.allFiles; var count = 0; for(i=#t;1;-1){ var f = lower(t[i]); if((f===path) || (..string.startsWith(f,dir) )){ ..table.remove(t,i); this.map[f] = null; count++; } } return count; }; clear = function(){ this.allFiles = {}; this.map = {}; this.totalSize = null; this.info = null; }; pack = function(asarpath){ for(path,size,progress in this.eachPack(asarpath)){} }; eachPack = function(asarpath,buf){ if(! ( asarpath ?..string.endsWith(asarpath,".asar",true) ) ) error("文件后缀名必须是 .asar",2); return ..fiber.generator(this.eachPackeFiber,asarpath,buf); }; createInfo = function(){ if(!#this.allFiles) { return null, "未添加任何文件"; } ..table.sort(this.allFiles,function(b){ return #owner < #b; }) if(!this.rootDirectory){ if(!..fsys.isDir(this.allFiles[1] ) ){ this.rootDirectory = ..fsys.getParentDir( this.allFiles[1] ); } else { this.rootDirectory = this.allFiles[1]; } } var allFiles = this.allFiles; var info = {files={}}; var path,fullpath,filename; var offset = 0; for(i=1;#allFiles;1){ fullpath = allFiles[i]; path = ..fsys.path.relative(fullpath,this.rootDirectory,false); if(!#path){ continue; }; if( path == "." ) continue; var t = ..string.split(path,"\/"); var f = info.files; for(i=1;#t-1;1){ if!(#t[i]) continue; if(!f[ t[i] ]) { f[ t[i] ] = { files = {} }; }; f = f[ t[i] ].files; } filename = t[ #t ]; if( f[ filename ] ) continue; if( ..fsys.isDir(fullpath) ){ f[ filename ] = { files = {} }; } else { var fi = {}; fi.offset = tostring(offset); var file = ..io.file(fullpath,"rb"); if(!file) { return null, "打开文件失败" + fullpath; } fi.size = file.size(1); offset = offset + fi.size; f[ filename ] = fi; file.close(); } } this.totalSize = offset; this.info = info; return info; }; treeData = function(){ this.lasterr = null; var info,err = this.createInfo(); if(!info) return null,err; var treeData = {}; var enumInfo; enumInfo = function(info,td,parent){ for(k,v in info.files){ if( v.files ){ var children = {text = k;path = v.path} push(td,children); enumInfo(v,children,v.path); } else { push(td,{text = k;path = v.path;size = v.size}); } } } enumInfo(this.info,treeData); return treeData; }; eachPackeFiber = function(asarpath,buf){ this.lasterr = null; var info,err = this.createInfo(); if(!info){ this.lasterr = ..string.concat("创建asar文件头时遇到错误,",err); return null; } var asarfile = ..io.file(asarpath,"w+b"); if(!asarfile){ this.lasterr = "创建asar文件失败"; return null; } var json = ..JSON.stringify(info); var header = { struct headerSize = { INT pickleOjectSize = 4; INT size; } struct headerJson = { INT pickleOjectSize = #json - (#json %4) + 4 + 4; INT size = #json; } } header.headerSize.size = header.headerJson.pickleOjectSize + 4; asarfile.write(header); asarfile.write(json); asarfile.seek("set",header.headerSize.size+8/*..raw.sizeof(h.headerSize)*/) if(!buf) buf = ..raw.buffer(0xA00000); var allFiles = this.allFiles; var totalReadSize = 0; var path,fullpath; for(i=1;#allFiles;1){ fullpath = allFiles[i]; path = ..fsys.path.relative(fullpath,this.rootDirectory,false); if( path == "." ) continue; if(! ..fsys.isDir(fullpath) ){ var file = ..io.file(fullpath,"rb"); if(!file) { asarfile.close(); this.lasterr = "打开文件失败" + fullpath; return null; } while( var readSize; readSize = file.readBuffer(buf); readSize ) { totalReadSize = totalReadSize + readSize; asarfile.writeBuffer(buf,readSize); ..fiber.yield (path,totalReadSize,totalReadSize/this.totalSize); } file.close(); } } asarfile.close(); } } /**intellisense() fsys.asar.writer() = 创建asar文件打包生成器\n!fsys_asar_writer. !fsys_asar_writer.add(__) = 添加文件或目录到asar文件 !fsys_asar_writer.remove(__) = 在已添加的asar的文件列表中移除文件或目录\n返回删除的文件数目 !fsys_asar_writer.pack(.(输出路径) = 直接打包为asar文件\n输出路径必须使用.asar后缀\n如果需要获取进度,请使用eachPack迭代器 !fsys_asar_writer.eachPack(输出路径,buffer) = @for(path,size,progress in ??.eachPack("/test.asar")){ __/*path为正在处理的文件相对路径\nsize是已处理的文件大小\nprogress是进度,0到1之间的小数\n输出路径必须使用.asar后缀,可选在参数@2中指定 buffer*/ } !fsys_asar_writer.filter = @.filter = function(path){ return __/*参数为待添加文件路径,返回布尔值控制是否继续添加*/; } !fsys_asar_writer.totalSize = 在写入asar文件之前,totalSize会更新为所有文件的字节数总和 !fsys_asar_writer.allFiles = 所有准备添加到asar文件中的文件路径 !fsys_asar_writer.rootDirectory = 指定根目录,如果不指定则自动生成此属性\n\n自动生成规则为:\n所有添加的文件路径中取最短路径,如果是目录则设为根路径,\n否则将其父目录设为根路径 !fsys_asar_writer.lasterr = 执行成功此属性为空,否则是错误信息 !fsys_asar_writer.treeData() = 对已添加的文件生成可在treeview控件中显示的数据表 !fsys_asar_writer.createInfo() = 创建文件目录,成功返回this.info\n失败返回null,错误信息 !fsys_asar_writer.info = createInfo函数生成的asar文件目录 !fsys_asar_writer.clear() = 清空所有文件 end intellisense**/