mirror of
https://onedev.site.tesses.net/crosslang/crosslangextras
synced 2026-02-08 17:15:45 +00:00
231 lines
8.0 KiB
Plaintext
231 lines
8.0 KiB
Plaintext
/^ The CrossLang Package Manager Client ^/
|
|
class Tesses.CrossLang.PackageManager
|
|
{
|
|
private configRoot;
|
|
private packageCache;
|
|
/^ Work offline (defaults to false) ^/
|
|
public Offline = false;
|
|
|
|
/^ Construct the Package Manager ^/
|
|
public PackageManager()
|
|
{
|
|
this.configRoot = Env.CrossLangConfig;
|
|
this.packageCache = this.configRoot / "PackageCache";
|
|
|
|
FS.Local.CreateDirectory(this.packageCache);
|
|
}
|
|
/^ Parse package filename ^/
|
|
public ParseFileName(name)
|
|
{
|
|
|
|
var index = name.LastIndexOf('.');
|
|
if(index == -1) throw "We expect an extension";
|
|
if(name.Substring(index) != ".crvm") throw "We expect the extension .crvm";
|
|
name = name.Substring(0,index);
|
|
//Name-VERSION-[dev|alpha|beta|prod]
|
|
|
|
var lastIndex = name.LastIndexOf('-');
|
|
var verStage = name.Substring(lastIndex+1);
|
|
var versionStr = verStage;
|
|
if(verStage == "dev" || verStage == "alpha" || verStage == "beta" || verStage == "prod")
|
|
{
|
|
var lastIndex2 = name.LastIndexOf('-', lastIndex-1);
|
|
return {
|
|
Name = name.Substring(0,lastIndex2),
|
|
Version = name.Substring(lastIndex2+1)
|
|
};
|
|
}
|
|
else
|
|
{
|
|
return {
|
|
Name = name.Substring(0,lastIndex),
|
|
Version = name.Substring(lastIndex+1)
|
|
};
|
|
}
|
|
}
|
|
/^ Get package servers list ^/
|
|
public GetPackageServers()
|
|
{
|
|
var packageConfigFile = configRoot / "package_servers.json";
|
|
|
|
if(FS.Local.RegularFileExists(packageConfigFile))
|
|
{
|
|
return Json.Decode(FS.ReadAllText(FS.Local, packageConfigFile));
|
|
}
|
|
return ["https://cpkg.tesseslanguage.com/"];
|
|
}
|
|
/^ Get a package (returns bytearray of package data or null if not found), use GetLatest to get the latest version ^/
|
|
public GetPackage(name, version)
|
|
{
|
|
var v = Version.Parse(version);
|
|
var useCache = v.Stage != "dev";
|
|
var pkgFile = packageCache / name / v.ToString();
|
|
|
|
if(useCache && FS.Local.RegularFileExists(pkgFile))
|
|
{
|
|
return FS.ReadAllBytes(FS.Local,pkgFile);
|
|
}
|
|
if(this.Offline) return null;
|
|
|
|
each(var item : this.GetPackageServers())
|
|
{
|
|
//https://cpkg.tesseslanguage.com/api/v1/download?name=MyPackage&version=1.0.0.0-prod
|
|
var uri = $"{item.TrimEnd('/')}/api/v1/download?name={Net.Http.UrlEncode(name)}&version={Net.Http.UrlEncode(version)}";
|
|
Console.WriteLine($"Downloading: {name} {version} from {item}");
|
|
var req = Net.Http.MakeRequest(uri);
|
|
if(req.StatusCode == 200)
|
|
{
|
|
var strm = new MemoryStream(true);
|
|
req.CopyToStream(strm);
|
|
|
|
if(useCache) {
|
|
FS.Local.CreateDirectory(packageCache / name);
|
|
var f = FS.Local.OpenFile(pkgFile,"wb");
|
|
strm.Seek(0,0);
|
|
strm.CopyTo(f);
|
|
f.Close();
|
|
}
|
|
var data = strm.GetBytes();
|
|
strm.Close();
|
|
req.Close();
|
|
return data;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
/^ Get the latest version of a package ^/
|
|
public GetLatest(name)
|
|
{
|
|
var pkgServers = this.GetPackageServers();
|
|
if(this.Offline || pkgServers.Count == 0)
|
|
{
|
|
//user has declared they are offline or don't have packageServers look through packages locally
|
|
var version = new Version(0,0,0,0,"dev");
|
|
var configRoot = Env.CrossLangConfig;
|
|
var dir = configRoot / "PackageCache" / name;
|
|
if(FS.Local.DirectoryExists(dir))
|
|
each(var f : FS.Local.EnumeratePaths(dir))
|
|
{
|
|
var v = Version.Parse(f.GetFileName());
|
|
if(v >= version)
|
|
{
|
|
version = v;
|
|
}
|
|
}
|
|
|
|
if(version.VersionInt == 0) return null;
|
|
return version.ToString();
|
|
}
|
|
else
|
|
{
|
|
each(var item : pkgServers)
|
|
{
|
|
var uri = $"{item.TrimEnd('/')}/api/v1/latest?name={Net.Http.UrlEncode(name)}";
|
|
var req = Net.Http.MakeRequest(uri);
|
|
if(req.StatusCode == 200)
|
|
{
|
|
var res0 = req.ReadAsString();
|
|
|
|
var res = Json.Decode(res0);
|
|
req.Close();
|
|
return res.version;
|
|
}
|
|
}
|
|
|
|
}
|
|
return null;
|
|
}
|
|
/^
|
|
Search for packages based on query
|
|
Options is a {"server": "SERVER_URL", "type": "lib", "pluginHost": "yourPluginHost","offset":0,"limit": 20}
|
|
^/
|
|
public Search(query, $options)
|
|
{
|
|
options = options ?? {};
|
|
|
|
var urlBase = "/api/v1/search?q={Net.Http.UrlEncode(query)}";
|
|
if(TypeOf(options.type) == "String") urlBase += $"&type={Net.Http.UrlEncode(options.type)}";
|
|
if(TypeOf(options.pluginHost) == "String") urlBase += "&pluginHost={Net.Http.UrlEncode(options.pluginHost)}";
|
|
if(TypeOf(options.offset) == "Long") urlBase += $"&offset={options.offset}";
|
|
if(TypeOf(options.limit) == "Long") urlBase += $"&limit={options.limit}";
|
|
|
|
func handle(server)
|
|
{
|
|
var req = Net.Http.MakeRequest($"{server.TrimEnd('/')}{urlBase}");
|
|
if(req.StatusCode==200)
|
|
{
|
|
try {
|
|
var res2=Json.Decode(req.ReadAsString());
|
|
return res2.packages;
|
|
}catch(ex) {
|
|
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
if(TypeOf(options.server) == "String")
|
|
return handle(options.server) ?? [];
|
|
else {
|
|
each(var item : this.GetPackageServers())
|
|
{
|
|
var r = handle(item);
|
|
if(TypeOf(r) == "List") return r;
|
|
|
|
}
|
|
return [];
|
|
}
|
|
|
|
}
|
|
/^
|
|
Download a plugin to directory
|
|
returns true if succeeds or false if it fails
|
|
^/
|
|
public DownloadPlugin(dirFS, name, version)
|
|
{
|
|
var pkg = this.GetPackage(name,version.ToString());
|
|
if(pkg == null) return false;
|
|
var ms = new MemoryStream(true);
|
|
ms.WriteBlock(pkg,0,pkg.Count);
|
|
ms.Seek(0,0);
|
|
var vm = VM.LoadExecutable(ms);
|
|
ms.Close();
|
|
var info = {};
|
|
try{info=Json.Decode(vm.Info);}catch(ex){}
|
|
var short_name = TypeOf(info.short_name) == "String" ? info.short_name : name;
|
|
dirFS.CreateDirectory(/short_name);
|
|
each(var file : dirFS.EnumeratePaths(/short_name))
|
|
{
|
|
if(file.GetExtension() == ".crvm" && dirFS.FileExists(file))
|
|
{
|
|
dirFS.DeleteFile(file);
|
|
}
|
|
}
|
|
FS.WriteAllBytes(dirFS,/short_name/$"{short_name}.crvm", pkg);
|
|
|
|
func dlDeps(_vm)
|
|
{
|
|
each(var dep : _vm.Dependencies)
|
|
{
|
|
var path = /short_name/$"{dep.Name}-{dep.Version.ToString()}";
|
|
if(!dirFs.RegularFileExists(path))
|
|
{
|
|
var pkg2 = this.GetPackage(dep.Name,dep.Version.ToString());
|
|
if(pkg2 == null) return false;
|
|
FS.WriteAllBytes(dirFS,path,pkg2);
|
|
var ms2 = new MemoryStream(true);
|
|
ms2.WriteBlock(pkg2,0,pkg2.Count);
|
|
ms2.Seek(0,0);
|
|
var vm2 = VM.LoadExecutable(ms2);
|
|
ms2.Close();
|
|
dlDeps(vm2);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
return dlDeps(vm);
|
|
}
|
|
} |