239 lines
6.9 KiB
JavaScript
239 lines
6.9 KiB
JavaScript
/**
|
|
* remote 模块用来处理远程仓库相关事务
|
|
*/
|
|
const path = require("path")
|
|
const fs = require("fs")
|
|
const JSON5 = require('json5')
|
|
const { pipeline, Transform} = require("stream/promises");
|
|
|
|
module.exports = class Remote {
|
|
|
|
constructor() {
|
|
// this.__init()
|
|
this.func_publish = require("./publish")
|
|
this.func_install = require("./install")
|
|
}
|
|
|
|
|
|
|
|
async init() {
|
|
this.webdav = await import("webdav");
|
|
const uConfig = await $context.get("uConfig");
|
|
if ( uConfig.get("remoteServer") ){
|
|
let server = uConfig.get("remoteServer");
|
|
$logger.info("server " + server)
|
|
if ( server.startsWith("webdav") ) {
|
|
server = "http" + server.substring(6)
|
|
}
|
|
|
|
if ( uConfig.get("remoteAuth") ) {
|
|
let up = uConfig.get("remoteAuth");
|
|
$logger.info("remoteAuth " + up)
|
|
up = up.split(":", 2)
|
|
this.client = this.webdav.createClient(
|
|
server,
|
|
{
|
|
username: up[0],
|
|
password: up[1]
|
|
}
|
|
);
|
|
} else {
|
|
this.client = this.webdav.createClient(
|
|
server
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
async check() {
|
|
|
|
if ( ! this.webdav ) {
|
|
$logger.info("webdav unable")
|
|
return false
|
|
}
|
|
|
|
if ( ! this.client ) {
|
|
$logger.info("client unable")
|
|
return false
|
|
}
|
|
|
|
try {
|
|
|
|
// Get directory contents
|
|
const directoryItems = await this.client.getDirectoryContents("/");
|
|
$logger.info("directoryItems", directoryItems)
|
|
// 是否包含 index.json ?
|
|
// 不包含尝试创建
|
|
// 包含了尝试下载
|
|
const indexJsonFile = this.getIndexJson( directoryItems );
|
|
$logger.info("indexJsonFile", indexJsonFile)
|
|
if ( indexJsonFile ) {
|
|
// 包含了尝试下载
|
|
// 下载有缓存
|
|
this.download(indexJsonFile)
|
|
$logger.info("download index")
|
|
|
|
} else {
|
|
// 不包含尝试创建
|
|
await this.affireRemoteStore()
|
|
$logger.info("affireRemoteStore")
|
|
}
|
|
|
|
return true
|
|
}catch ( e ) {
|
|
$logger.error("remote check 过程中出错", e)
|
|
console.error(e)
|
|
return false
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 先对比时间和长度,有不同才会真正下载,否则使用本地缓存。
|
|
* 本地缓存路径即本地仓库路径
|
|
* @param rFile
|
|
*/
|
|
download(rFile){
|
|
const lFilePath = path.resolve($sConfig.getLocalStorePath(), rFile.filename);
|
|
if ( fs.existsSync( lFilePath ) ) {
|
|
const lFileInfo = fs.statSync(lFilePath);
|
|
if ( lFileInfo.size === rFile.length
|
|
&& lFileInfo.mtime === rFile.lastmod
|
|
) {
|
|
// 使用缓存
|
|
$logger.debug("use cache")
|
|
return true
|
|
}
|
|
}
|
|
|
|
// 下载并覆盖
|
|
// 不知道是同步还是异步
|
|
this.wDownload( rFile.filename, lFilePath );
|
|
|
|
|
|
}
|
|
|
|
async affireRemoteStore(){
|
|
// Get directory contents
|
|
const directoryItems = await this.client.getDirectoryContents("/");
|
|
// 是否包含 index.json ?
|
|
// 不包含尝试创建
|
|
// 包含了尝试下载
|
|
const indexJsonFile = this.getIndexJson( directoryItems );
|
|
if ( ! indexJsonFile ) {
|
|
// 创建 index
|
|
await this.client.putFileContents("/index.json", JSON5.stringify({
|
|
modules : [],
|
|
tmpls : [],
|
|
lists : []
|
|
}, null, 4) , { overwrite: false });
|
|
}
|
|
|
|
const modulesFolder = this.getFileInfoByName(directoryItems, "modules")
|
|
if ( ! modulesFolder ) {
|
|
// 创建文件夹
|
|
await this.client.createDirectory("/modules");
|
|
}
|
|
|
|
const tmplsFolder = this.getFileInfoByName(directoryItems, "tmpls")
|
|
if ( ! tmplsFolder ) {
|
|
// 创建文件夹
|
|
await this.client.createDirectory("/tmpls");
|
|
}
|
|
|
|
const listsFolder = this.getFileInfoByName(directoryItems, "lists")
|
|
if ( ! listsFolder ) {
|
|
// 创建文件夹
|
|
await this.client.createDirectory("/lists");
|
|
}
|
|
|
|
}
|
|
|
|
getIndexJson(items){
|
|
return this.getFileInfoByName( items, "index.json" );
|
|
}
|
|
getFileInfoByName(items, name){
|
|
if ( ! items || items.length < 1 ) {
|
|
return false;
|
|
}
|
|
for ( let item of items ) {
|
|
if ( item.basename === name ) {
|
|
return item;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
async publish(localFile, remotePath){
|
|
return await this.func_publish( this , localFile, remotePath )
|
|
}
|
|
|
|
async install(id){
|
|
return this.func_install( this, id )
|
|
}
|
|
|
|
async wUpload(from, to, debug){
|
|
const totalSize = fs.statSync(from).size;
|
|
debug ? console.log("totalSize", totalSize) : null
|
|
const rs = fs.createReadStream( from );
|
|
let wSize = 0;
|
|
let rSize = 0;
|
|
rs.on("data", (r)=>{
|
|
rSize += r.length;
|
|
debug ? console.log("r", rSize * 100 / totalSize + "%") : null
|
|
})
|
|
const ws = this.client.createWriteStream(to)
|
|
ws.on("data", (r)=>{
|
|
wSize += r.length;
|
|
debug ? console.log("w ", wSize * 100 / totalSize + "%") : null
|
|
})
|
|
await pipeline( rs, ws);
|
|
debug ? console.log("finish") : null
|
|
}
|
|
|
|
async wDownload(from, to){
|
|
$logger.info("download", from, to )
|
|
const stat = await this.client.stat(from);
|
|
const totalSize = stat.size;
|
|
let wSize = 0;
|
|
let rSize = 0;
|
|
|
|
const rs = this.client.createReadStream(from);
|
|
rs.on("data", (r)=>{
|
|
rSize += r.length;
|
|
// console.log("r", rSize * 100 / totalSize)
|
|
})
|
|
|
|
const ws = fs.createWriteStream(to);
|
|
ws.on("data", (r)=>{
|
|
wSize += r.length;
|
|
// console.log("w", wSize * 100 / totalSize)
|
|
})
|
|
return await pipeline(
|
|
rs, ws
|
|
)
|
|
}
|
|
|
|
async wMkdir(folder){
|
|
|
|
const folderfather = path.dirname( folder );
|
|
if ( ! await this.client.exists( folderfather ) ) {
|
|
// await remote.client.createDirectory( folderfather )
|
|
await this.wMkdir( folderfather )
|
|
}
|
|
|
|
if ( await this.client.exists( folder ) ) {
|
|
return
|
|
} else {
|
|
await this.client.createDirectory( folder )
|
|
}
|
|
}
|
|
|
|
async wGetModuleInfo(id){
|
|
let meta = await this.client.getFileContents("/modules/" + id + "/meta.json", { format: "text" });
|
|
let metaJson = JSON5.parse( meta );
|
|
return metaJson
|
|
}
|
|
|
|
}
|
|
|