changed: better formatting in `onyx pkg`
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sat, 13 May 2023 02:00:30 +0000 (21:00 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sat, 13 May 2023 02:00:30 +0000 (21:00 -0500)
CHANGELOG
core/encoding/ini.onyx
scripts/core_tests.onyx
scripts/onyx-pkg.onyx

index c4a2405677ac3f54df56b021b7cfd53cab9da487..35a477df76e081ee3efc45f75834e3ab84f6e717 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -18,6 +18,7 @@ Changes:
     - Instead, an error is produced when the function is called.
 * API for time remains the same, but reduced dependencies on external time things,
     like strftime, localtime and mktime.
+* Ergnomic improvements to `onyx pkg`.
 
 Bugfixes:
 * Fixed missing `use core` in `optional.onyx`.
@@ -25,6 +26,7 @@ Bugfixes:
 * Fixed missing newline in `onyx help build` documentation.
 * Fixed WASI compilation due to misconfigured environment code.
 * Fixed WASI `__dir_open` permissions.
+* Fixed `core.encoding.ini` clearing the temporary allocator.
 
 
 
index ab935ee78cc94c14103031edf70a8e7a7186e157..56576c8a2b6be65d456cc1e8bd8ed4c5deecba7a 100644 (file)
@@ -91,7 +91,7 @@ parse_ini_file_inner :: (r: &io.Reader, output_ptr: any) -> (IniParseResult, Ini
         output.type = (cast(&info.Type_Info_Pointer) t).to;
     }
 
-    defer alloc.clear_temp_allocator();
+    alloc.arena.auto(dest=#(context.temp_allocator));
 
     active_item_ptr  := null;
     active_item_type := void;
index 526ee8b1eccd021d5350fb45499d33f285a32c25..eefbc138dde0991ac1b48ebe02877155b84797a6 100644 (file)
@@ -2,7 +2,7 @@
 
 #load "core/std"
 
-use core
+use core {package, test}
 
 #inject core {
     Running_Tests :: true 
index c96a803dc6355ae6548e25d2018831bd584b1588..1201edee32db60640a6c7a32cb3eb60ed9df2b20 100644 (file)
@@ -53,7 +53,7 @@ main :: (args: [] cstr) {
 
     if command_tag.tag.require_config_file {
         if !load_config_file() {
-            eprintf("Failed to open {}.\n", global_arguments.config_file);
+            error_print("Failed to open {}.\n", global_arguments.config_file);
             os.exit(1);
         }
 
@@ -103,7 +103,7 @@ run_help_command :: (args: [] cstr) {
 #tag Command.{ "init", "Initialize a new project.", "", require_config_file=false }
 run_init_command :: (args: [] cstr) {
     if os.file_exists(global_arguments.config_file) {
-        eprintf("Config file present; project already initialized.\n");
+        error_print("Config file present; project already initialized.\n");
         return;
     }
 
@@ -148,7 +148,7 @@ verion           Semantic version number (Major.Minor.Patch). If omitted, the mo
 }
 run_add_command :: (args: [] cstr) {
     if args.count < 1 {
-        eprintf("Expected package name.");
+        error_print("Expected package URL");
         return;
     }
 
@@ -158,7 +158,7 @@ run_add_command :: (args: [] cstr) {
     version: SemVer;
     if args.count > 1 {
         if !conv.parse_any(&version, string.as_str(args[1])) {
-            eprintf("Failed to parse version number given: {}\n", string.as_str(args[1]));
+            error_print("Failed to parse version number given: {}\n", string.as_str(args[1]));
             return;
         }
 
@@ -167,14 +167,14 @@ run_add_command :: (args: [] cstr) {
     }
 
     if config.dependencies.dependencies->has(dep) {
-        eprintf("Dependency '{}' already specified at version '{}'.\n", dep, config.dependencies.dependencies[dep]);
+        error_print("Dependency '{}' already specified at version '{}'.\n", dep, config.dependencies.dependencies[dep]);
 
     } elseif version->is_zero() {
-        printf("Unable to find latest version of '{}'.\n", dep);
+        error_print("Unable to find latest version of '{}'\n", string.as_str(args[0]));
 
     } else {
         config.dependencies.dependencies[dep] = version;
-        printf("Added dependency '{}' at version {}.\n", dep, version);
+        info_print("Added", "'{}' version {}\n", dep, version);
     }
 }
 
@@ -185,7 +185,7 @@ package-or-url   Git repository name or package name on disk to remove.
 }
 run_remove_command :: (args: [] cstr) {
     if args.count < 1 {
-        eprintf("Expected package name.");
+        error_print("Expected package name.");
         return;
     }
 
@@ -205,7 +205,7 @@ run_remove_command :: (args: [] cstr) {
         }
     }
 
-    eprintf("Dependency '{}' is not currently used.\n", dep);
+    error_print("Dependency '{}' is not currently used.\n", dep);
 }
 
 #tag Command.{ "show", "Show dependencies and versions.", "" }
@@ -232,11 +232,13 @@ run_show_command :: (args: [] cstr) {
 #tag Command.{ "update", "Update dependencies to newest compatible versions.", "" }
 // @Feature // Add "locked" dependencies that will never update?
 run_update_command :: (args: [] cstr) {
-    printf("Updating dependencies to newest compatible versions.\n");
+    info_print("Info", "Updating dependencies to newest compatible versions.\n");
     for& config.dependencies.dependencies.entries {
         new_version := Git.get_latest_compatible_version(it.key, it.value);
 
-        printf("{}: {} -> {}\n", it.key, it.value, new_version);
+        if it.value != new_version {
+            info_print("Update", "{}  {} -> {}\n", it.key, it.value, new_version);
+        }
 
         it.value = new_version;
     }
@@ -284,7 +286,7 @@ run_sync_command :: (args: [] cstr) {
 
         success, installed_folder := install_package(to_install.pack, to_install.downgrade_if_necessary);
         if !success {
-            eprintf("Aborting sync.\n");
+            error_print("Aborting sync.\n");
             return;
         }
 
@@ -297,25 +299,27 @@ run_sync_command :: (args: [] cstr) {
             result, error := encoding.ini.parse_ini_file(&r, &inner_config);
 
             if result != .Success {
-                eprintf("Failed to parse onyx-pkg.ini in {}. Skipping...\n", to_install.repo);
+                error_print("Misconfigured onyx-pkg.ini in '{}'. Omitting.\n", to_install.repo);
                 continue;
             }
         }
 
         if inner_config.metadata.version->is_zero() {
-            eprintf("Failed to parse onyx-pkg.ini in {}. Skipping...\n", to_install.repo);
+            error_print("Misconfigured parse onyx-pkg.ini in '{}'. Omitting.\n", to_install.repo);
             continue;
         }
 
         for& inner_config.dependencies.dependencies.entries {
             if dependencies_installed->has(it.key) {
+                // TODO : Check if this is right? Could this accidentally forcefully upgrade a package?
                 if it.value->is_newer(dependencies_installed[it.key]) {
                     uninstall_package(.{it.key, it.value});
                     dependencies_installed->delete(it.key);
                     dependencies_to_install << .{ .{it.key, it.value}, false };
 
                 } elseif !(it.value->is_compatible(dependencies_installed[it.key])) {
-                    eprintf("Different major versions of {} being used!\n", it.key);
+                    // TODO: Explain this more
+                    error_print("Different major versions of '{}' being used!\n", it.key);
                     os.exit(1);
                 }
             } else {
@@ -333,6 +337,7 @@ run_sync_command :: (args: [] cstr) {
             if it.type != .Directory do continue;
 
             if !array.contains(needed_dependency_folders, it->name()) {
+                info_print("Remove", "{}\n", it->name());
                 package_folder := tprintf("{}/{}", config.config.lib_source_directory, it->name());
                 attempt_remove_native_library(package_folder);
                 os.remove_directory(package_folder);
@@ -348,7 +353,7 @@ package-or-url   Git repository name or package name on disk to remove.
 }
 run_rebuild_command :: (args: [] cstr)  {
     if args.count < 1 {
-        eprintf("Expected package name.");
+        error_print("Expected package name.");
         return;
     }
 
@@ -359,10 +364,12 @@ run_rebuild_command :: (args: [] cstr)  {
         folder = config.dependency_folders.folders[dep];
     }
 
-    if rebuild_native_library(folder) {
-        printf("Successfully rebuilt {}.\n", dep);
+    info_print("Rebuild", "{}\n", dep);
+    if success, err := rebuild_native_library(folder); success {
+        info_print("Rebuilt", "{}\n", dep);
     } else {
-        printf("Failed to rebuild {}.\n", dep);
+        error_print("Rebuild failed.\n", dep);
+        println(err);
         os.exit(1);
     }
 }
@@ -372,6 +379,7 @@ run_publish_command :: (args: [] cstr) {
     // @TODO // Better error handling and reporting, as this is a delicate process.
 
     if !os.dir_exists(".git") {
+        error_print("Not in Git repository.\n");
         printf("It does not look like you are in a Git repository. In order to publish packages\n");
         printf("with onyx-pkg, you have to initailize a Git repository in the current directory.\n\n");
         return;
@@ -413,11 +421,11 @@ run_publish_command :: (args: [] cstr) {
 
     store_config_file();
 
-    printf("Creating new published version...\n");
+    info_print("Publishing", "Creating new published version\n");
     if Git.publish_version() {
-        printf("Successfully published new version.\n");
+        info_print("Published", "Successfully published new version.\n");
     } else {
-        printf("Failed to publish new version.\n");
+        error_print("Failed to publish new version.\n");
     }
 }
 
@@ -489,22 +497,23 @@ install_package :: (pack: Package, downgrade_if_necessary := false) -> (bool, in
             installed_version := get_installed_version_of_package(folder_name);
 
             if installed_version == pack.version {
-                printf("{} is already installed at version {}.\n", pack.repo, installed_version);
+                info_print("Exists", "{}  {}\n", pack.repo, installed_version);
                 return true, folder_name;
             }
 
             if installed_version->is_newer(pack.version) && !downgrade_if_necessary {
-                eprintf("Refusing to downgrade package {} from version {} to {}.\n", pack.repo, installed_version, pack.version);
+                error_print("Refusing to downgrade '{}' from {} to {}.\n", pack.repo, installed_version, pack.version);
             }
 
+            // :PRETTY
             verb := "Upgrading" if pack.version->is_newer(installed_version) else "Downgrading";
-            printf("{} package {} from version {} to {}.\n", verb, pack.repo, installed_version, pack.version);
+            info_print(verb, "{}  {} -> {}\n", pack.repo, installed_version, pack.version);
             uninstall_package(pack);
         }
     }
 
     if !Git.clone_version(pack.repo, pack.version) {
-        eprintf("Failed to fetch {} version {}.\n", pack.repo, pack.version);
+        error_print("Failed to fetch {} version {}.\n", pack.repo, pack.version);
         return false, "";
     }
 
@@ -546,9 +555,10 @@ attempt_remove_native_library :: (package_folder: str) -> bool {
     return true;
 }
 
-rebuild_native_library :: (folder: str) -> bool {
+rebuild_native_library :: (folder: str) -> (bool, str) {
     attempt_remove_native_library(tprintf("{}/{}", config.config.lib_source_directory, folder));
-    return run_native_library_installation(folder);
+    success, build_error := run_native_library_installation(folder);
+    return success, build_error;
 }
 
 get_installed_version_of_package :: (package_path: str) -> SemVer {
@@ -565,32 +575,37 @@ get_installed_version_of_package :: (package_path: str) -> SemVer {
     return .{0, 0, 0};
 }
 
-run_native_library_installation :: (folder: str) -> bool {
+run_native_library_installation :: (folder: str) -> (bool, str) {
     inner_config: Config;
     for os.with_file(tprintf("{}/{}/onyx-pkg.ini", config.config.lib_source_directory, folder)) {
         r := io.reader_make(it);
         result, error := encoding.ini.parse_ini_file(&r, &inner_config);
 
-        if result != .Success do return false;
-        if string.empty(inner_config.native_library.build_cmd) do return true;
+        if result != .Success do return false, "";
+        if string.empty(inner_config.native_library.build_cmd) do return true, "";
 
         args := string.split(inner_config.native_library.build_cmd, #char " ", context.temp_allocator);
         cmd  := args[0];
         args  = args[1 .. args.count];
 
         installed_dest := tprintf("{}/{}", config.config.lib_source_directory, folder);
-        build_proc     := os.process_spawn(cmd, args, starting_directory=installed_dest);
-        build_result   := os.process_wait(&build_proc);
 
-        if build_result != .Success {
-            eprintf("Failed to build native library in {}.\n", folder);
-            return false;
+        {
+            build_proc     := os.process_spawn(cmd, args, starting_directory=installed_dest);
+            build_reader := io.reader_make(&build_proc);
+            defer io.reader_free(&build_reader);
+
+            build_result   := os.process_wait(&build_proc);
+            if build_result != .Success {
+                error_print("Failed to build native library in {}.\n", folder);
+                return false, build_reader->read_all();
+            }
         }
 
         if !os.dir_exists(config.config.lib_bin_directory) {
             if !os.dir_create(config.config.lib_bin_directory) {
-                eprintf("Failed to create native library directory, {}.\n", config.config.lib_bin_directory);
-                return false;
+                error_print("Failed to create native library directory, {}.\n", config.config.lib_bin_directory);
+                return false, "";
             }
         }
 
@@ -599,10 +614,10 @@ run_native_library_installation :: (folder: str) -> bool {
         success := os.rename_file(source_path, dest_path);
 
         if !success {
-            eprintf("Failed to move native library to final destination.\n {} -> {}\n", source_path, dest_path);
+            error_print("Failed to move native library to final destination.\n {} -> {}\n", source_path, dest_path);
         }
 
-        return success;
+        return success, "";
     }
 }
 
@@ -796,7 +811,7 @@ Git :: struct {
     }
 
     clone_version :: (repo: str, version: SemVer) -> bool {
-        printf("Fetching {} version {}...\n", repo, version);
+        info_print("Fetch", "{}  {}\n", repo, version);
 
         version_str := tprintf("v{}", version);
         full_dest   := tprintf("{}/{}", config.config.lib_source_directory, ".cloned");
@@ -828,7 +843,7 @@ Git :: struct {
                 }
 
                 if !successfully_parsed {
-                    eprintf("Unknown destination directory and failed to find onyx-pkg.ini in {}.\n", repo);
+                    error_print("Unknown destination directory and failed to find onyx-pkg.ini in {}.\n", repo);
                     os.remove_directory(full_dest);
                     return false;
                 }
@@ -840,13 +855,13 @@ Git :: struct {
             // Move the cloned repository to its permanent location.
             actual_dest := tprintf("{}/{}", config.config.lib_source_directory, install_dest);
             if os.dir_exists(actual_dest) {
-                eprintf("Expected {} to not exist when fetching {}.\n", actual_dest, repo);
+                error_print("Expected {} to not exist when fetching '{}'.\n", actual_dest, repo);
                 os.remove_directory(full_dest);
                 return false;
             }
 
             if !os.dir_rename(full_dest, actual_dest) {
-                eprintf("Failed to move temporary package to final destination when fetching {}.\n", repo);
+                error_print("Failed to move temporary package to final destination when fetching '{}'.\n", repo);
                 os.remove_directory(full_dest);
                 return false;
             }
@@ -854,7 +869,7 @@ Git :: struct {
             // Remove the .git folder, as it is unneeded.
             unnecessary_git_dir := tprintf("{}/.git", actual_dest);
             if !os.remove_directory(unnecessary_git_dir) {
-                eprintf("Failed to delete .git folder of {}.\n", repo);
+                error_print("Failed to delete .git folder of '{}'.\n", repo);
                 return false;
             }
 
@@ -1008,3 +1023,49 @@ store_config_file :: () -> bool {
 }
 
 
+Color_Print :: struct {
+    Color :: enum {
+        Black;
+        Red;
+        Green;
+        Yellow;
+        Blue;
+        Purple;
+        Cyan;
+        White;
+        __Unused;
+        Default;
+    }
+
+    color: Color;
+    text: str;
+}
+
+color_print :: (segments: ..Color_Print) {
+    for segments {
+        printf("\x1b[3{}m{}", cast(u32) it.color, it.text);
+    }
+
+    print("\x1b[0m");
+}
+
+error_print :: (text: str, va: ..any) {
+    buf: [1024] u8;
+    color_print(
+        .{ .Red, "       Error  " },
+        .{ .Default, conv.format_va(buf, text, cast([] any) va) }
+    );
+}
+
+info_print :: (verb: str, text: str, va: ..any) {
+    buf: [1024] u8;
+
+    // HACK
+    for 12 - verb.length do print(" ");
+
+    color_print(
+        .{ .Green, tprintf("{}  ", verb) },
+        .{ .Default, conv.format_va(buf, text, cast([] any) va) }
+    );
+}
+