From 36dfbdff452ab0fe4c39ab9739f887e7ddf45bee Mon Sep 17 00:00:00 2001 From: Manuel Barrio Linares Date: Fri, 6 Feb 2026 12:20:27 -0300 Subject: [PATCH] implement progress bar for fetch-msvc using deterministic milestones --- src/utils/fetch_msvc.c | 159 ++++++++++++++++++++++++----------------- 1 file changed, 95 insertions(+), 64 deletions(-) diff --git a/src/utils/fetch_msvc.c b/src/utils/fetch_msvc.c index 2b3f2043a..fe0c915b9 100644 --- a/src/utils/fetch_msvc.c +++ b/src/utils/fetch_msvc.c @@ -63,6 +63,32 @@ static char *get_sdk_output_path(void) static int verbose_level = 0; + +static void print_progress(int percent) +{ + if (verbose_level > 0) return; + int width = 40; + if (percent > 100) percent = 100; + + printf("\rDownloading and extracting packages ["); + + const char *parts[] = { " ", "▏", "▎", "▍", "▌", "▋", "▊", "▉" }; + int total_blocks = width * 8; + int filled_blocks = (percent * total_blocks) / 100; + int full_blocks = filled_blocks / 8; + int partial_block = filled_blocks % 8; + + for (int i = 0; i < full_blocks; i++) printf("█"); + if (full_blocks < width) + { + printf("%s", parts[partial_block]); + for (int i = full_blocks + 1; i < width; i++) printf(" "); + } + + printf("] %3d%%", percent); + fflush(stdout); +} + // Minimal dirent-like structure for Windows #if PLATFORM_WINDOWS struct dirent @@ -183,11 +209,6 @@ static bool download_with_verification(const char *url, const char *name, printf("%s ... downloading", name); fflush(stdout); } - else if (verbose_level == 0) - { - printf("."); - fflush(stdout); - } const char *err = download_file(url, "", dst); if (err) { @@ -563,12 +584,57 @@ void fetch_msvc(BuildOptions *options) dir_make_recursive(out_root); dir_make_recursive(dl_root); - if (verbose_level == 0) + JSONObject **checked_pkgs = NULL; + JSONObject *sdk_comp = json_map_get(sdk_paths, sdk_key); + JSONObject *deps_obj = json_map_get(sdk_comp, "dependencies"); + if (deps_obj && deps_obj->type == J_OBJECT) { - printf("Downloading and extracting packages"); - fflush(stdout); + FOREACH(const char *, dep, deps_obj->keys) + { + JSONObject *pkg = find_package_by_id(pkgs, dep); + if (pkg) + { + vec_add(checked_pkgs, pkg); + JSONObject *p_deps = json_map_get(pkg, "dependencies"); + if (p_deps && p_deps->type == J_OBJECT) + { + FOREACH(const char *, pd_id, p_deps->keys) + { + JSONObject *ppkg = find_package_by_id(pkgs, pd_id); + if (ppkg) vec_add(checked_pkgs, ppkg); + } + } + } + } } + const char *msi_names[] = { + "Windows SDK for Windows Store Apps Libs-x86_en-us.msi", + "Windows SDK Desktop Libs x64-x86_en-us.msi", + "Universal CRT Headers Libraries and Sources-x86_en-us.msi"}; + + JSONObject *msi_packages[3] = {NULL}; + for (int i = 0; i < ELEMENTLEN(msi_names); i++) + { + FOREACH(JSONObject *, pkg, checked_pkgs) + { + JSONObject *pls = json_map_get(pkg, "payloads"); + if (!pls) continue; + FOREACH(JSONObject *, pl, pls->elements) + { + if (STRCASECMP(filename(json_map_get(pl, "fileName")->str), msi_names[i]) == 0) + { + msi_packages[i] = pkg; + break; + } + } + if (msi_packages[i]) break; + } + } + + int progress = 0; + if (verbose_level == 0) print_progress(progress); + const char *suffixes[] = {"asan.headers.base", "crt.x64.desktop.base", "crt.x64.store.base", "asan.x64.base"}; for (int i = 0; i < ELEMENTLEN(suffixes); i++) { @@ -585,70 +651,36 @@ void fetch_msvc(BuildOptions *options) extract_msvc_zip(zpath, out_root); } } - if (verbose_level == 0) - { - printf("."); - fflush(stdout); - } } + progress += 10; + print_progress(progress); } - JSONObject *sdk_comp = json_map_get(sdk_paths, sdk_key); - const char **sdk_pkg_ids = NULL; - JSONObject *deps_obj = json_map_get(sdk_comp, "dependencies"); - if (deps_obj && deps_obj->type == J_OBJECT) - { - FOREACH(const char *, dep, deps_obj->keys) vec_add(sdk_pkg_ids, dep); - } - - const char *msi_names[] = { - "Windows SDK for Windows Store Apps Libs-x86_en-us.msi", - "Windows SDK Desktop Libs x64-x86_en-us.msi", - "Universal CRT Headers Libraries and Sources-x86_en-us.msi"}; const char **cab_list = NULL; - JSONObject **checked_pkgs = NULL; - - FOREACH(const char *, sid, sdk_pkg_ids) - { - JSONObject *pkg = find_package_by_id(pkgs, sid); - if (pkg) - { - vec_add(checked_pkgs, pkg); - JSONObject *p_deps = json_map_get(pkg, "dependencies"); - if (p_deps && p_deps->type == J_OBJECT) - { - FOREACH(const char *, pd_id, p_deps->keys) - { - JSONObject *ppkg = find_package_by_id(pkgs, pd_id); - if (ppkg) vec_add(checked_pkgs, ppkg); - } - } - } - } - for (int i = 0; i < ELEMENTLEN(msi_names); i++) { - FOREACH(JSONObject *, pkg, checked_pkgs) + if (!msi_packages[i]) continue; + JSONObject *pls = json_map_get(msi_packages[i], "payloads"); + FOREACH(JSONObject *, pl, pls->elements) { - JSONObject *pls = json_map_get(pkg, "payloads"); - if (!pls) continue; - FOREACH(JSONObject *, pl, pls->elements) + const char *f_name = json_map_get(pl, "fileName")->str; + if (STRCASECMP(filename(f_name), msi_names[i]) == 0) { - const char *f_name = json_map_get(pl, "fileName")->str; - if (STRCASECMP(filename(f_name), msi_names[i]) == 0) + char *mpath = (char *)file_append_path(dl_root, msi_names[i]); + if (download_with_verification(json_map_get(pl, "url")->str, msi_names[i], mpath)) { - char *mpath = (char *)file_append_path(dl_root, msi_names[i]); - if (download_with_verification(json_map_get(pl, "url")->str, msi_names[i], mpath)) - { - get_msi_cab_list(mpath, &cab_list); - } - goto NEXT_MSI; + get_msi_cab_list(mpath, &cab_list); } + goto NEXT_MSI; } } - NEXT_MSI:; + NEXT_MSI: + progress += 10; + print_progress(progress); } + int cabs_done = 0; + int cab_count = vec_size(cab_list); FOREACH(const char *, cab, cab_list) { FOREACH(JSONObject *, pkg, checked_pkgs) @@ -665,7 +697,9 @@ void fetch_msvc(BuildOptions *options) } } } - NEXT_CAB:; + NEXT_CAB: + cabs_done++; + if (cab_count > 0) print_progress(70 + (20 * cabs_done) / cab_count); } for (int i = 0; i < ELEMENTLEN(msi_names); i++) @@ -674,16 +708,13 @@ void fetch_msvc(BuildOptions *options) if (file_exists(mpath)) { extract_msi(mpath, out_root, dl_root); - if (verbose_level == 0) - { - printf("."); - fflush(stdout); - } + print_progress(90 + (10 * (i + 1)) / ELEMENTLEN(msi_names)); } } if (verbose_level == 0) { + print_progress(100); printf(" Done.\n"); fflush(stdout); }