From 993635b3b073e0658896ddc75af96dccfe3e6c10 Mon Sep 17 00:00:00 2001 From: Kray-G Date: Mon, 12 Jul 2021 18:18:43 +0900 Subject: [PATCH] refs #232: updated for PackageManager. --- ChangeLog.md | 8 +-- include/ir.h | 1 + lib/exec/kip.kx | 8 ++- lib/std/pkg/Develop.kx | 148 +++++++++++++++++++++++++++++++++++++++++ src/lexer.c | 16 ++++- src/main_kxcmd.c | 16 ++++- src/mainlib.c | 11 ++- 7 files changed, 196 insertions(+), 12 deletions(-) create mode 100644 lib/std/pkg/Develop.kx diff --git a/ChangeLog.md b/ChangeLog.md index 43aa26ae3..578bf1648 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -3,6 +3,7 @@ ## V1.2.0 (Future Planned) * Planned. + * Support Cryptography library. * Support GUI library. * Support OpenCV library. * Support HTTP Server library. @@ -10,11 +11,9 @@ ## V1.1.0 (Current Development Version) * Planned - * Support Package Manager. - * Support Cryptography library. + * #232: Support Package Manager. * New Features - * Supported SAT solver by picosat. - * Supported SemanticVersion class with `using SemanticVersion;`. + * #275: Supported SAT solver by picosat. * Improvements/Enhancements * #261: Separated binary modules in extlib to another repository & reduced a repository size. * #255: Improved the `operator[]` in `Range`. @@ -24,6 +23,7 @@ * #273: Supported `read`/`write` in `File`. * #290: Supported `chmod` in `File`. * Small improvements and enhancements as follows without managing by issues. + * Supported SemanticVersion class with `using SemanticVersion;`. * Supported putting a comma at the end of an argument's list for both declaration and calling. * Added operators of `==` and `!=` in Boolean class. * Supported `String#isIntegerString`. diff --git a/include/ir.h b/include/ir.h index 1baac7db3..40ccfa4ad 100644 --- a/include/ir.h +++ b/include/ir.h @@ -888,6 +888,7 @@ typedef struct kx_options_ { int exception_detail_info:1; int debug_mode:1; int debug_step:1; + int dev_mode:1; uint16_t case_threshold; uint16_t max_call_depth; } kx_options_t; diff --git a/lib/exec/kip.kx b/lib/exec/kip.kx index 5e9899499..694a43abb 100644 --- a/lib/exec/kip.kx +++ b/lib/exec/kip.kx @@ -362,6 +362,10 @@ class KinxPackageLibraryManager(repoMgr_) { } private listRemotePackages(info, key) { + if (!info) { + Kip.errorln("No package(%{key}) found"); + return; + } var list = getRemotePackages(info); Kip.info("* ", key) if (key); list.each { @@ -488,7 +492,7 @@ class KinxPackageLibraryManager(repoMgr_) { // Auto detaction of exec candidate. var candidates = []; Directory.walk(packagedir / "bin") { &(f) - if (f.extension() == ".kx") { + if (f.extension() == ".kx" && !f.stem().endsWith("-dev")) { candidates.push(f.filename()); } }; @@ -543,7 +547,7 @@ class KinxPackageLibraryManager(repoMgr_) { var packagebase = $pkgpath / name; Directory.walk(packagebase) { &(packagedir) Directory.walk(packagedir / "bin") { &(f) - if (f.extension() == ".kx") { + if (f.extension() == ".kx" && !f.stem().endsWith("-dev")) { var dst = $kinxpath / f.stem() + (exe ? ".exe" : ""); if (File.exists(dst)) { if (removeFile(dst)) { diff --git a/lib/std/pkg/Develop.kx b/lib/std/pkg/Develop.kx new file mode 100644 index 000000000..9cb31ccf7 --- /dev/null +++ b/lib/std/pkg/Develop.kx @@ -0,0 +1,148 @@ + +class DevelopPackageUpdater(pkgname, version) { + + const DEF_FILE_NAME = "kxpackage.def"; + var defFile_ = $pkgpath / DEF_FILE_NAME; + var root_ = $pkgpath / pkgname / version; + var candidates_; + + private initialize() { + @root = root_; + System.println("$PKGPATH: ", root_); + } + + private saveDef(data) { + File.open(defFile_, File.WRITE) { &(f: File) + data.keySet().each { + if (data[_1]) { + f.println("%s = %s" % _1 % data[_1]); + } + }; + }; + } + + private loadDef() { + return File.load(defFile_).split(/\r?\n/).map { => _1.split('=').map { => _1.trim() } } + .reduce({ &(r, e) + r[e[0]] = e[1]; + return r; + }, {}); + } + + private removeFile(file) { + System.try({ => File.remove(file) }).else({ => System.println("Failed to remove: %s" % file) }); + return !File.exists(file); + } + + private removeDir(dir) { + var success = true; + Directory.walk(dir) { &(f) + if (File.isDirectory(f)) { + removeDir(f); + } + if (!removeFile(f)) { + success = false; + } + }; + if (!removeFile(dir)) { + success = false; + } + return success; + } + + public dircopy(file1, file2) { + if (File.isDirectory(file1)) { + if (file1 == "dev") { + file2 = file2.parentPath() / "bin"; + } + System.println("Copying a directory : ", file1); + if (!File.exists(file2)) { + File.mkdir(file2); + } + Directory.walk(file1) { + dircopy(_1, file2 / _1.filename()); + }; + } else { + System.println("Copying a file : ", file1); + File.copy(file1, file2); + } + } + + private isExecutable(file) { + if (File.isDirectory(file)) { + return false; + } + if (file.extension() == ".sh") { + return true; + } + var header = File.read(file, 4); + return header == <0x7f, 0x45, 0x4c, 0x46>; + } + + private makeExecutableCandidates() { + var candidates; + if (File.exists(root_ / "bin")) { + candidates = []; + Directory.walk(root_ / "bin") { &(f) + if (f.extension() == ".kx" && f.stem().endsWith("-dev")) { + candidates.push(f.filename()); + } + }; + } + return candidates; + } + + private removeExecutableCandidates() { + candidates_ = makeExecutableCandidates(); + if (candidates_.isDefined) { + var exe = File.exists($kinxpath / "kxrepl.exe"); + candidates_.each { + var dst = $kinxpath / _1.stem() + (exe ? ".exe" : ""); + if (File.exists(dst) && removeFile(dst)) { + System.println("Removed an executable of %{dst.filename().bold().yellow()}"); + } + }; + } + } + + private makeDevExecutable() { + candidates_ = makeExecutableCandidates(); + if (candidates_.isDefined) { + Directory.recursiveWalk(root_ / "bin") { &(f) + if (isExecutable(f)) { + File.chmod(f, 755); + System.println("Made the file of %{_1.filename().bold().yellow()} executable"); + } + }; + [ "kxrepl", "kxrepl.exe" ].each { &(exefile) + var src = $kinxpath / exefile; + var exe = exefile.extension() == ".exe"; + if (File.exists(src)) { + candidates_.each { + var dst = $kinxpath / _1.stem() + (exe ? ".exe" : ""); + if (File.exists(dst)) { + removeFile(dst); + } + File.copy(src.replace("\\", "/"), dst.replace("\\", "/")); + File.chmod(dst, 755); + System.println("Generated a command of %{dst.filename().bold().yellow()}"); + }; + } + }; + } + } + + public update(code) { + removeExecutableCandidates(); + if (File.exists(root_)) { + removeDir(root_); + } + code(this); + makeDevExecutable(); + + var def = loadDef(); + def[pkgname] = version; + saveDef(def); + } + +} diff --git a/src/lexer.c b/src/lexer.c index e2467a7a5..6ca4a021a 100644 --- a/src/lexer.c +++ b/src/lexer.c @@ -137,6 +137,18 @@ static void pop_package_version(const char *key) } } +static int set_package_devmode(const char *pkgname, int pos) +{ + if (g_parse_ctx && g_parse_ctx->options.dev_mode) { + kx_strbuf[pos++] = '-'; + kx_strbuf[pos++] = 'd'; + kx_strbuf[pos++] = 'e'; + kx_strbuf[pos++] = 'v'; + kx_strbuf[pos] = 0; + } + return pos; +} + static int set_package_version(const char *pkgname, int pos) { khint_t k = kh_get(package, g_packages, pkgname); @@ -295,12 +307,12 @@ static int process_using(void) while (pos < POSMAX && (kx_is_filechar(kx_lexinfo) || kx_lexinfo.ch == '*')) { if (is_package) { if (is_package_version == 0 && kx_lexinfo.ch == '.') { - kx_strbuf[pos] = 0; + pos = set_package_devmode(pkgname, pos); pkgname = kx_const_str(g_parse_ctx, kx_strbuf + is_package_namepos); pos = set_package_version(pkgname, pos); is_package_version = 2; } else if (is_package_version == 0 && kx_lexinfo.ch == '(') { - kx_strbuf[pos] = 0; + pos = set_package_devmode(pkgname, pos); pkgname = kx_const_str(g_parse_ctx, kx_strbuf + is_package_namepos); is_package_version = 1; kx_strbuf[pos++] = PATH_DELCH; diff --git a/src/main_kxcmd.c b/src/main_kxcmd.c index d817bbd6c..3ec3f41a6 100644 --- a/src/main_kxcmd.c +++ b/src/main_kxcmd.c @@ -17,6 +17,13 @@ } \ /**/ +int ends_with(const char *str, const char *suffix) +{ + size_t len1 = strlen(str); + size_t len2 = strlen(suffix); + return len1 >= len2 && strcmp(str + len1 - len2, suffix) == 0; +} + char *make_cmd_name(const char *av0) { int start = 0, end = 0, len = 0; @@ -37,8 +44,13 @@ char *make_exec_name(const char *av0) int start = 0, end = 0, len = 0; MAKE_START_END_LEN(av0, start, end, len); char *cmdname = kx_calloc(len + (7/* --exec: */ + 2), sizeof(char)); - strcpy(cmdname, "--exec:"); - strncpy(cmdname + 7, av0 + start, len); + if (ends_with(av0, "-dev") || ends_with(av0, "-dev.exe")) { + strcpy(cmdname, "--dev:"); + strncpy(cmdname + 6, av0 + start, len); + } else { + strcpy(cmdname, "--exec:"); + strncpy(cmdname + 7, av0 + start, len); + } return cmdname; } diff --git a/src/mainlib.c b/src/mainlib.c index f98df2bf7..1ef86d0db 100644 --- a/src/mainlib.c +++ b/src/mainlib.c @@ -373,6 +373,13 @@ DllExport int do_main(int ac, char **av) goto END_OF_OPT; } break; + } else if (!strcmp(lname, "dev")) { + ctx->options.dev_mode = 1; + if (param[0]) { + execname = param; + goto END_OF_OPT; + } + break; } break; case 'q': @@ -538,6 +545,8 @@ DllExport int do_main(int ac, char **av) } kx_trace(ctx, 0, "[cleanup] terminating the program...\n"); + r = error_code >= 0 ? error_code : r; + kx_trace(ctx, 0, "[done:status] %d\n", r); g_terminated = 1; free_package_info(); context_cleanup(ctx); @@ -552,8 +561,6 @@ DllExport int do_main(int ac, char **av) #if defined(_WIN32) || defined(_WIN64) WSACleanup(); #endif - r = error_code >= 0 ? error_code : r; - kx_trace(ctx, 0, "[done:status] %d\n", r); return r; }