From c1997265e1a52a98029edebf17303e67e946968f Mon Sep 17 00:00:00 2001 From: Aoran Zeng Date: Thu, 6 Mar 2025 20:27:56 +0800 Subject: [PATCH] Make the framework compile separately --- src/framework/core.c | 212 +++++++++-------------------------------- src/framework/mirror.c | 22 ++++- src/framework/mirror.h | 22 +++++ src/framework/struct.h | 14 +-- 4 files changed, 90 insertions(+), 180 deletions(-) create mode 100644 src/framework/mirror.h diff --git a/src/framework/core.c b/src/framework/core.c index 12f1fba..413f923 100644 --- a/src/framework/core.c +++ b/src/framework/core.c @@ -11,16 +11,12 @@ * Created On : <2023-08-29> * Last Modified : <2025-03-06> * - * chsrc framework + * core implementation of chsrc framework * ------------------------------------------------------------*/ -#include "xy.h" -#include "struct.h" +#include "chsrc-framework.h" #include "mirror.c" -#define App_Name "chsrc" - -static int chsrc_get_cpucore (); bool ProgMode_CMD_Measure = false; bool ProgMode_CMD_Reset = false; @@ -28,80 +24,21 @@ bool ProgMode_CMD_Reset = false; bool ProgMode_Target_Group = false; int ProgMode_Leader_Selected_Index = -1; -/* 此时 chsrc_run() 不再是recipe中指定要运行的一个外部命令,而是作为一个功能实现的支撑 */ bool ProgMode_Run_as_a_Service = false; -enum ChgType_t -{ - ChgType_Auto, - ChgType_Reset, - ChgType_SemiAuto, - ChgType_Manual, - ChgType_Untested -}; + enum ChgType_t ProgMode_ChgType = ChgType_Auto; -/* 命令行选项 */ bool CliOpt_IPv6 = false; bool CliOpt_Locally = false; bool CliOpt_InEnglish = false; bool CliOpt_DryRun = false; bool CliOpt_NoColor = false; -/** - * -local 的含义是启用 *项目级* 换源 - * - * 每个 target 对 [-local] 的支持情况可使用 | chsrc ls | 来查看 - * - * - * 1. 默认不使用该选项时,含义是 *全局* 换源, - * - * 全局分为 (1)系统级 (2)用户级 - * - * 大多数第三方配置软件往往默认进行的是 *用户级* 的配置。所以 chsrc 首先将尝试使用 *用户级* 配置 - * - * 2. 若不存在 *用户级* 的配置,chsrc 将采用 *系统级* 的配置 - * - * 3. 最终效果本质由第三方软件决定,如 poetry 默认实现的就是项目级的换源 - */ -#define Exit_OK 0 -#define Exit_Fatal 1 -#define Exit_Unknown 2 -#define Exit_Unsupported 3 -#define Exit_UserCause 4 -#define Exit_MaintainerCause 5 -#define Exit_ExternalError 6 -#define chsrc_log(str) xy_log(App_Name,str) -#define chsrc_succ(str) xy_succ(App_Name,str) -#define chsrc_info(str) xy_info(App_Name,str) -#define chsrc_warn(str) xy_warn(App_Name,str) -#define chsrc_error(str) xy_error(App_Name,str) -#define chsrc_debug(str) xy_warn(App_Name "(DEBUG)",str) -#define chsrc_verbose(str) xy_info(App_Name "(VERBOSE)",str) - -#define red(str) xy_str_to_red(str) -#define blue(str) xy_str_to_blue(str) -#define green(str) xy_str_to_green(str) -#define yellow(str) xy_str_to_yellow(str) -#define purple(str) xy_str_to_purple(str) -#define bold(str) xy_str_to_bold(str) -#define bdred(str) xy_str_to_bold(xy_str_to_red(str)) -#define bdblue(str) xy_str_to_bold(xy_str_to_blue(str)) -#define bdgreen(str) xy_str_to_bold(xy_str_to_green(str)) -#define bdyellow(str) xy_str_to_bold(xy_str_to_yellow(str)) -#define bdpurple(str) xy_str_to_bold(xy_str_to_purple(str)) - -// 2系列都是带有括号的 -#define chsrc_succ2(str) xy_succ_brkt(App_Name,CliOpt_InEnglish?"SUCCEED":"成功",str) -#define chsrc_log2(str) xy_info_brkt(App_Name,"LOG",str) -#define chsrc_warn2(str) xy_warn_brkt(App_Name,CliOpt_InEnglish?"WARN":"警告",str) -#define chsrc_error2(str) xy_error_brkt(App_Name,CliOpt_InEnglish?"ERROR":"错误",str) -#define chsrc_debug2(str) xy_warn_brkt(App_Name,"DEBUG",str) -#define chsrc_verbose2(str) xy_info_brkt(App_Name,"VERBOSE",str) void chsrc_note2 (const char *str) @@ -110,16 +47,16 @@ chsrc_note2 (const char *str) xy_log_brkt (yellow(App_Name), bdyellow(msg), yellow(str)); } -void -chsrc_log_write (const char *filename) +static void +log_write_op (const char *filename) { char *msg = CliOpt_InEnglish ? "WRITE" : "写入"; xy_log_brkt (blue(App_Name), bdblue(msg), blue(filename)); } -void -chsrc_log_backup (const char *filename) +static void +log_backup_op (const char *filename) { char *msg = CliOpt_InEnglish ? "BACKUP" : "备份"; @@ -131,10 +68,8 @@ chsrc_log_backup (const char *filename) #define NoMark "x" #define HalfYesMark "⍻" -/** - * @translation Done - */ -void + +static void log_check_result (const char *check_what, const char *check_type, bool exist) { char *chk_msg = NULL; @@ -168,10 +103,7 @@ log_check_result (const char *check_what, const char *check_type, bool exist) } -/** - * @translation Done - */ -void +static void log_cmd_result (bool result, int exit_status) { char *run_msg = NULL; @@ -220,16 +152,14 @@ is_url (const char *str) /** * 检测二进制程序是否存在 * + * @param prog_name 要检测的二进制程序名 + * * @param check_cmd 检测 `prog_name` 是否存在的一段命令,一般来说,填 `prog_name` 本身即可, * 但是某些情况下,需要使用其他命令绕过一些特殊情况,比如 python 这个命令在Windows上 * 会自动打开 Microsoft Store,需避免 - * - * @param prog_name 要检测的二进制程序名 - * - * @translation Done */ bool -query_program_exist (char *check_cmd, char *prog_name, int mode) +chsrc_query_program_exist (char *prog_name, char *check_cmd, int mode) { char *which = check_cmd; @@ -267,7 +197,7 @@ bool chsrc_check_program (char *prog_name) { char *quiet_cmd = xy_str_to_quietcmd (xy_2strjoin (prog_name, " --version")); - return query_program_exist (quiet_cmd, prog_name, Noisy_When_Exist|Noisy_When_NonExist); + return chsrc_query_program_exist (prog_name, quiet_cmd, Noisy_When_Exist|Noisy_When_NonExist); } /** @@ -281,7 +211,7 @@ bool chsrc_check_program_quietly (char *prog_name) { char *quiet_cmd = xy_str_to_quietcmd (xy_2strjoin (prog_name, " --version")); - return query_program_exist (quiet_cmd, prog_name, Quiet_When_Exist|Quiet_When_NonExist); + return chsrc_query_program_exist (prog_name, quiet_cmd, Quiet_When_Exist|Quiet_When_NonExist); } /** @@ -292,7 +222,7 @@ bool chsrc_check_program_quietly_when_exist (char *prog_name) { char *quiet_cmd = xy_str_to_quietcmd (xy_2strjoin (prog_name, " --version")); - return query_program_exist (quiet_cmd, prog_name, Quiet_When_Exist|Noisy_When_NonExist); + return chsrc_query_program_exist (prog_name, quiet_cmd, Quiet_When_Exist|Noisy_When_NonExist); } @@ -306,7 +236,7 @@ void chsrc_ensure_program (char *prog_name) { char *quiet_cmd = xy_str_to_quietcmd (xy_2strjoin (prog_name, " --version")); - bool exist = query_program_exist (quiet_cmd, prog_name, Quiet_When_Exist|Noisy_When_NonExist); + bool exist = chsrc_query_program_exist (prog_name, quiet_cmd, Quiet_When_Exist|Noisy_When_NonExist); if (exist) { // OK, nothing should be done @@ -346,7 +276,6 @@ chsrc_check_file (char *path) * @param target 目标名 * @param input 如果用户输入 default 或者 def,则选择第一个源 */ -#define find_mirror(s, input) query_provider_exist(s##_sources, s##_sources_n, (char*)#s+3, input) int query_provider_exist (Source_t *sources, size_t size, char *target, char *input) { @@ -433,7 +362,7 @@ query_provider_exist (Source_t *sources, size_t size, char *target, char *input) * * @param speed 单位为Byte/s */ -char * +static char * to_human_readable_speed (double speed) { char *scale[] = {"Byte/s", "KByte/s", "MByte/s", "GByte/s", "TByte/s"}; @@ -465,7 +394,7 @@ to_human_readable_speed (double speed) * * 该函数实际原型为 char * (*)(const char*) */ -void * +static void * measure_speed_for_url (void *url) { char *time_sec = NULL; @@ -510,7 +439,7 @@ measure_speed_for_url (void *url) /** * @return 返回速度speed,单位为 Byte/s */ -double +static double parse_and_say_curl_result (char *curl_buf) { // 分隔两部分数据 @@ -535,7 +464,7 @@ parse_and_say_curl_result (char *curl_buf) } -int +static int get_max_ele_idx_in_dbl_ary (double *array, int size) { double maxval = array[0]; @@ -558,7 +487,7 @@ get_max_ele_idx_in_dbl_ary (double *array, int size) * @param size 待测源的数量 * @param[out] speed_records 速度值记录,单位为Byte/s */ -void +static void measure_speed_for_every_source (Source_t sources[], int size, double speed_records[]) { // bool get_measured[size]; /* 是否真正执行了测速 */ @@ -655,7 +584,6 @@ measure_speed_for_every_source (Source_t sources[], int size, double speed_recor /** * 自动测速选择镜像站和源 */ -#define auto_select_mirror(s) select_mirror_autoly(s##_sources, s##_sources_n, (char*)#s+3) int select_mirror_autoly (Source_t *sources, size_t size, const char *target_name) { @@ -760,73 +688,33 @@ select_mirror_autoly (Source_t *sources, size_t size, const char *target_name) } -#define use_specific_mirror_or_auto_select(input, s) \ - (NULL!=(input)) ? find_mirror(s, input) : auto_select_mirror(s) - -bool +static bool source_is_upstream (Source_t *source) { return xy_streql (source->mirror->code, "upstream"); } -bool +static bool source_is_userdefine (Source_t *source) { return xy_streql (source->mirror->code, "user"); } -bool +static bool source_has_empty_url (Source_t *source) { return source->url == NULL; } -bool +static bool is_reset_mode () { return ProgMode_CMD_Reset; } -/** - * 用户*只可能*通过下面5种方式来换源,无论哪一种都会返回一个 Source_t 出来 - * option: - * 1. 用户指定某个 Mirror Code - * 2. NULL: 用户什么都没指定 (将测速选择最快镜像) - * 3. 用户给了一个 URL - * 4. ChgType_Reset - * 选用了Leader target - * 5. ProgMode_Leader_Selected_Index 将给出所选索引 - * - * @dependency 变量 option - */ -#define chsrc_yield_for_the_source(for_what) \ - if (ProgMode_Target_Group==true && ProgMode_Leader_Selected_Index==-1) \ - { \ - ProgMode_Leader_Selected_Index = use_specific_mirror_or_auto_select (option, for_what); \ - source = for_what##_sources[ProgMode_Leader_Selected_Index]; \ - } \ - else if (ProgMode_Target_Group==true && ProgMode_Leader_Selected_Index!=-1) \ - { \ - source = for_what##_sources[ProgMode_Leader_Selected_Index]; \ - } \ - else if (is_url (option)) \ - { \ - Source_t __tmp = { &UserDefinedProvider, option }; \ - source = __tmp; \ - } \ - else \ - { \ - int __index = use_specific_mirror_or_auto_select (option, for_what); \ - source = for_what##_sources[__index]; \ - } - -#define chsrc_yield_source(for_what) \ - Source_t source; \ - chsrc_yield_for_the_source(for_what) - #define hr() say ("--------------------------------"); @@ -838,11 +726,9 @@ is_reset_mode () * 1. 告知用户选择了什么源和镜像 * 2. 对选择的源和镜像站进行一定的校验 * - * @translation Done */ -#define chsrc_confirm_source confirm_source(&source) void -confirm_source (Source_t *source) +chsrc_confirm_source (Source_t *source) { // 由于实现问题,我们把本应该独立出去的上游默认源,也放在了可以换源的数组中,而且放在第一个 // chsrc 已经规避用户使用未实现的 `chsrc reset` @@ -870,7 +756,6 @@ confirm_source (Source_t *source) hr(); } -#define chsrc_yield_source_and_confirm(for_what) chsrc_yield_source(for_what);chsrc_confirm_source void @@ -1055,12 +940,9 @@ not_root: } -#define RunOpt_Default 0x0000 // 默认若命令运行失败,直接退出 -#define RunOpt_Dont_Notify_On_Success 0x0010 // 运行成功不提示用户,只有运行失败时才提示用户 -#define RunOpt_No_Last_New_Line 0x0100 // 不输出最后的空行 -#define RunOpt_Dont_Abort_On_Failure 0x1000 // 命令运行失败也不退出 -static void + +void chsrc_run (const char *cmd, int run_option) { if (ProgMode_Run_as_a_Service) @@ -1107,7 +989,7 @@ chsrc_run (const char *cmd, int run_option) static void -chsrc_run_as_a_service (const char *cmd) +_chsrc_run_as_a_service (const char *cmd) { int run_option = RunOpt_Default; ProgMode_Run_as_a_Service = true; @@ -1116,7 +998,7 @@ chsrc_run_as_a_service (const char *cmd) ProgMode_Run_as_a_Service = false; } -static void +void chsrc_view_file (const char *path) { char *cmd = NULL; @@ -1130,10 +1012,10 @@ chsrc_view_file (const char *path) cmd = xy_2strjoin ("cat ", path); } - chsrc_run_as_a_service (cmd); + _chsrc_run_as_a_service (cmd); } -static void +void chsrc_ensure_dir (const char *dir) { dir = xy_normalize_path (dir); @@ -1156,14 +1038,14 @@ chsrc_ensure_dir (const char *dir) char *cmd = xy_2strjoin (mkdir_cmd, dir); cmd = xy_str_to_quietcmd (cmd); - chsrc_run_as_a_service (cmd); + _chsrc_run_as_a_service (cmd); char *msg = CliOpt_InEnglish ? "Directory doesn't exist, created automatically " : "目录不存在,已自动创建 "; chsrc_note2 (xy_2strjoin (msg, dir)); } -static void +void chsrc_append_to_file (const char *str, const char *filename) { if (CliOpt_DryRun) @@ -1199,7 +1081,7 @@ chsrc_append_to_file (const char *str, const char *filename) log_anyway: /* 输出recipe指定的文件名 */ - chsrc_log_write (filename); + log_write_op (filename); /* char *cmd = NULL; @@ -1215,7 +1097,7 @@ log_anyway: */ } -static void +void chsrc_prepend_to_file (const char *str, const char *filename) { if (CliOpt_DryRun) @@ -1236,14 +1118,14 @@ chsrc_prepend_to_file (const char *str, const char *filename) { cmd = xy_strjoin (4, "sed -i '1i ", str, "' ", file); } - chsrc_run_as_a_service (cmd); + _chsrc_run_as_a_service (cmd); log_anyway: /* 输出recipe指定的文件名 */ - chsrc_log_write (filename); + log_write_op (filename); } -static void +void chsrc_overwrite_file (const char *str, const char *filename) { if (CliOpt_DryRun) @@ -1264,14 +1146,14 @@ chsrc_overwrite_file (const char *str, const char *filename) { cmd = xy_strjoin (4, "echo '", str, "' > ", file); } - chsrc_run_as_a_service (cmd); + _chsrc_run_as_a_service (cmd); log_anyway: /* 输出recipe指定的文件名 */ - chsrc_log_write (filename); + log_write_op (filename); } -static void +void chsrc_backup (const char *path) { if (CliOpt_DryRun) @@ -1324,17 +1206,17 @@ chsrc_backup (const char *path) } } - chsrc_run_as_a_service (cmd); + _chsrc_run_as_a_service (cmd); log_anyway: - chsrc_log_backup (path); + log_backup_op (path); } /** * 检查过程中全程保持安静 */ -static char * +char * chsrc_get_cpuarch () { char *ret; @@ -1388,7 +1270,7 @@ chsrc_get_cpuarch () } -static int +int chsrc_get_cpucore () { int cores = 2; diff --git a/src/framework/mirror.c b/src/framework/mirror.c index 4c67d62..0de9039 100644 --- a/src/framework/mirror.c +++ b/src/framework/mirror.c @@ -7,9 +7,11 @@ * Contributors : Shengwei Chen <414685209@qq.com> * | * Created On : <2023-08-29> - * Last Modified : <2025-03-04> + * Last Modified : <2025-03-06> * * 通用镜像站 + * + * 该文件仅作为 core.c 实现的一部分 * ------------------------------------------------------------*/ #define Big_File_ubuntu "/24.04/ubuntu-24.04.1-desktop-amd64.iso" // 5.8 GB @@ -17,6 +19,22 @@ #define Big_File_archlinux "/iso/latest/archlinux-x86_64.iso" // 800 MB #define Big_File_deepin "/20.9/deepin-desktop-community-20.9-amd64.iso" // 4 GB +SourceProvider_t UserDefinedProvider = +{ + "user", "用户自定义", "用户自定义", NULL, + {SKIP, "用户自定义源不测速", "SKIP for user-defined source", NULL} +}; + + +SourceProvider_t UpstreamProvider = +{ + /* 引入新的上游默认源时,请使下面第一行的前三个字段保持不变,只添加第四个字段,可使用 def_upstream 宏 */ + "upstream", "Upstream", "上游默认源", NULL, + /* 引入新的上游默认源时,请完全修改下面这个结构体,可使用 def_need_measure_info 宏 */ + {SKIP, "URL未知,邀您参与贡献!", "URL unknown, welcome to contribute!", NULL} +}; + + /** * 教育网镜像 * @@ -110,7 +128,7 @@ Scau = {NotSkip, NA, NA, "https://mirrors.scau.edu.cn/ubuntu-releases" Big_File_ubuntu} }, -NJTech = +Njtech = { "njtech", "NJTech", "南京工业大学开源软件镜像站", "https://mirrors.njtech.edu.cn/", {NotSkip, NA, NA, "https://mirrors.njtech.edu.cn/ubuntu-releases" Big_File_ubuntu} diff --git a/src/framework/mirror.h b/src/framework/mirror.h new file mode 100644 index 0000000..ee50ea0 --- /dev/null +++ b/src/framework/mirror.h @@ -0,0 +1,22 @@ +/** ------------------------------------------------------------ + * SPDX-License-Identifier: GPL-3.0-or-later + * ------------------------------------------------------------- + * File Name : mirror.h + * File Authors : Aoran Zeng + * | Heng Guo <2085471348@qq.com> + * Contributors : Shengwei Chen <414685209@qq.com> + * | + * Created On : <2023-08-29> + * Last Modified : <2025-03-06> + * + * 该头文件仅由 chsrc-framework.h 包含 + * ------------------------------------------------------------*/ + +extern SourceProvider_t UpstreamProvider; +extern SourceProvider_t UserDefinedProvider; + +extern MirrorSite_t MirrorZ, +Tuna, Sjtug_Zhiyuan, Zju, Lzuoss, Jlu, Bfsu, Pku, Bjtu, +Sustech, Ustc, Hust, Iscas, Scau, Njtech, Nyist, Sdu, Cqupt, Nju; + +extern MirrorSite_t Ali, Tencent, Huawei, Volcengine, Netease, Sohu; diff --git a/src/framework/struct.h b/src/framework/struct.h index 6904839..5d749f7 100644 --- a/src/framework/struct.h +++ b/src/framework/struct.h @@ -7,7 +7,7 @@ * Contributors : Shengwei Chen <414685209@qq.com> * | * Created On : <2023-08-29> - * Last Modified : <2024-12-18> + * Last Modified : <2025-03-06> * * chsrc struct * ------------------------------------------------------------*/ @@ -38,22 +38,10 @@ SourceProvider_t; typedef SourceProvider_t MirrorSite_t; -SourceProvider_t UpstreamProvider = -{ - /* 引入新的上游默认源时,请使下面第一行的前三个字段保持不变,只添加第四个字段,可使用 def_upstream 宏 */ - "upstream", "Upstream", "上游默认源", NULL, - /* 引入新的上游默认源时,请完全修改下面这个结构体,可使用 def_need_measure_info 宏 */ - {SKIP, "URL未知,邀您参与贡献!", "URL unknown, welcome to contribute!", NULL} -}; #define def_upstream "upstream", "Upstream", "上游默认源" #define def_need_measure_info {SKIP, "缺乏较大的测速对象,邀您参与贡献!", "Lack of large object URL, welcome to contribute!", NULL} -SourceProvider_t UserDefinedProvider = -{ - "user", "用户自定义", "用户自定义", NULL, - {SKIP, "用户自定义源不测速", "SKIP for user-defined source", NULL} -}; typedef struct Source_t