重构: yield source 时先考虑 combo 的 user define 能力

This commit is contained in:
Aoran Zeng committed 2026-08-19 18:28:37 +08:00
1 parent 75de9cd5e4
commit 47c2e14b6e
9 files changed
+109 -74

No files matched your search

+2 -2
View File
@@ -819,7 +819,7 @@ chefs_handle_Set_Source (Dish_t *dish, const char *input, char *option)
{
if (dish_has_sub_dishes(dish))
{
chsrc_begin_combo_source_resolution (dish);
push_combo_stack (dish);
for (size_t i=0; i<xy_seq_len(dish->sub_dishes); i++)
{
@@ -830,7 +830,7 @@ chefs_handle_Set_Source (Dish_t *dish, const char *input, char *option)
br();
}
chsrc_end_combo_source_resolution ();
pop_combo_stack ();
return;
}
+2 -4
View File
@@ -414,7 +414,7 @@ chef_allow_user_define (Dish_t *dish)
xy_cant_be_null (dish);
dish->can_user_define = true;
dish->can_user_define_explain = NULL;
dish->user_define_cap_explain = NULL;
}
void
@@ -424,9 +424,7 @@ chef_deny_user_define (Dish_t *dish)
dish->can_user_define = false;
char *reason = CHINESE ? "URL将会根据内部实现重写,因此不能自定义"
: "The URL will be rewritten based on internal implementation, so it cannot be customized";
dish->can_user_define_explain = reason;
dish->user_define_cap_explain = NULL;
}
+32 -1
View File
@@ -47,7 +47,7 @@ dish_has_sub_dishes (Dish_t *dish)
bool
dish_has_source_from_mirror (Dish_t *dish, const char *mirror_code)
{
if (!dish || !dish->sources || !code)
if (!dish || !dish->sources || !mirror_code)
return false;
if (xy_streql (mirror_code, "upstream"))
@@ -102,3 +102,34 @@ subdish_sibling_has_source_from_mirror (Dish_t *dish, const char *mirror_code)
return false;
}
void
push_combo_stack (Dish_t *combo_dish)
{
if (ProgStatus.ComboStackDepth >= MaxComboStackDepth)
chsrc_breakdown ("combo dish 嵌套层级过深");
int depth = ProgStatus.ComboStackDepth;
ProgStatus.ComboStack[depth] = combo_dish;
ProgStatus.ComboBackedUpPaths[depth] = xy_seq_new ();
ProgStatus.ComboStackDepth++;
}
void
pop_combo_stack (void)
{
if (ProgStatus.ComboStackDepth <= 0)
chsrc_breakdown ("combo dish 栈已为空");
ProgStatus.ComboStackDepth--;
}
Dish_t *
current_combo_dish ()
{
if (ProgStatus.ComboStackDepth <= 0)
return NULL;
return ProgStatus.ComboStack[ProgStatus.ComboStackDepth - 1];
}
+2
View File
@@ -14,6 +14,8 @@
bool
hp_is_url (const char *str)
{
if (!str)
return false;
return (xy_str_start_with (str, "http://") || xy_str_start_with (str, "https://"));
}
+64 -58
View File
@@ -14,35 +14,13 @@
* 源的确定
* ------------------------------------------------------------*/
void
chsrc_begin_combo_source_resolution (Dish_t *dish)
{
if (ProgStatus.ComboStackDepth >= MaxComboStackDepth)
chsrc_breakdown ("combo dish 嵌套层级过深");
int depth = ProgStatus.ComboStackDepth;
ProgStatus.ComboStack[depth] = dish;
ProgStatus.ComboBackedUpPaths[depth] = xy_seq_new ();
ProgStatus.ComboStackDepth++;
}
void
chsrc_end_combo_source_resolution (void)
{
if (ProgStatus.ComboStackDepth <= 0)
chsrc_breakdown ("combo dish 栈已为空");
ProgStatus.ComboStackDepth--;
}
/**
* 用于 _setsrc() 函数,检测用户输入的镜像站 code,是否存在于该 dish 可用源中
*
* @note 一个源Source必定来自于一个Provider,所以该函数名叫 query_mirror_exist
*
* @param dish_name 菜品名
* @param input 如果用户输入 default 或者 def,则选择第一个源
* @param input 如果用户输入 `first`,则选择第一个源
*/
int
query_mirror_exist (Source_t *sources, size_t size, char *dish_name, char *input)
@@ -149,25 +127,28 @@ query_mirror_exist (Source_t *sources, size_t size, char *dish_name, 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"};
int i = 0;
while (speed > 1024.0)
{
i += 1;
speed /= 1024.0;
}
{
i += 1;
speed /= 1024.0;
}
char *buf = xy_malloc0 (64);
sprintf (buf, "%.2f %s", speed, scale[i]);
char *new = NULL;
if (i <= 1 ) new = red (buf);
if (i <= 1 )
{
new = red(buf);
}
else
{
if (i == 2 && speed < 2.00) new = yellow (buf);
else new = green (buf);
if (i == 2 && speed < 2.00) new = yellow(buf);
else new = green(buf);
}
return new;
}
@@ -181,7 +162,7 @@ to_human_readable_speed (double speed)
*
* 该函数实际原型为 char * (*)(const char*)
*/
void *
static void *
measure_speed_for_url (void *url)
{
char *time_sec = NULL;
@@ -224,7 +205,7 @@ measure_speed_for_url (void *url)
/**
* @return 返回速度speed,单位为 Byte/s
*/
double
static double
parse_and_say_curl_result (char *curl_buf)
{
/* 分隔两部分数据 */
@@ -278,7 +259,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]; /* 是否真正执行了测速 */
@@ -559,19 +540,19 @@ use_specific_mirror_or_auto_select (char *input, Dish_t *dish)
}
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;
@@ -581,22 +562,30 @@ source_has_empty_url (Source_t *source)
/**
* @brief 在 combo dish 中为当前 sub dish 解析源
*
* 用户只提供一个 code。若当前 sub dish 拥有该 code,直接使用它;否则,
* 若某个兄弟 sub dish 拥有该 code,说明该 code 仅属于另一类源,当前 sub
* dish 应自动测速选择其最快镜像。都不存在时走普通查询路径并报错。
* 用户只提供一个 mirror code,
*
* 1. 若当前 sub dish 拥有该 code,直接使用它
* 2. 若1不成立,而某个兄弟 sub dish 拥有该 code,说明该 code 仅属于另一类源,
* 当前 sub dish 应自动测速选择其最快镜像
* 3. 若1和2都不成立,则直接报错
*/
int
chsrc_resolve_combo_subdish_source (Dish_t *dish, char *option)
resolve_combo_subdish_source (Dish_t *dish, char *mirror_code)
{
if (dish_has_source_from_mirror (dish, option))
return query_mirror_exist (dish->sources, dish->sources_n, dish->aliases, option);
if (dish_has_source_from_mirror (dish, mirror_code))
return query_mirror_exist (dish->sources, dish->sources_n, dish->aliases, mirror_code);
if (subdish_sibling_has_source_from_mirror (dish, option))
return auto_select_mirror (dish->sources, dish->sources_n, dish->aliases);
if (subdish_sibling_has_source_from_mirror (dish, mirror_code))
{
chsrc_alert2 (CHINESE ? "当前子菜品没有来自所请求镜像站的源,尝试测速选择最快源"
: "Current sub dish has no source from the requested mirror, try to auto select the fastest source");
return auto_select_mirror (dish->sources, dish->sources_n, dish->aliases);
}
chsrc_breakdown (ENGLISH
? "This combo sub dish has no source from the requested mirror"
: "该 combo sub dish 没有所请求镜像站的源");
chsrc_error (CHINESE ? "所有的子菜品均没有来自所请求镜像站的源"
: "All sub dishes have no source from the requested mirror");
exit (Exit_UserCause);
return 0;
}
@@ -629,27 +618,44 @@ chsrc_yield_source (Dish_t *dish, char *option)
if (!dish->prepared) dish->preparefn();
Source_t source;
char *user_defined_url = NULL;
char *mirror_code = NULL;
if (hp_is_url (option))
{
user_defined_url = option;
}
else if (option)
{
mirror_code = option;
}
/**
* @note
* 这里的逻辑需要厘清: 这个函数本身,只会被 _setsrc() 调用,而
* combo dish 自身是没有 _setsrc() 的!所以进入到这里来的,必
* 定是 combo dish 的 sub dish 的 _setsrc()
*/
if (chsrc_in_dish_group_mode() && option)
{
if (hp_is_url (option))
Dish_t *combo_dish = current_combo_dish();
if (user_defined_url)
{
/* combo dish 传入 URL 时,支持该 sub dish 自定义 URL 的则直接使用;
* 不支持则自动选择该 sub dish 的最快源。这样 uv 可只把 URL 当作
* PyPI index,而 python-install-mirror 仍自动选择。 */
if (dish->can_user_define)
if (combo_dish->can_user_define)
{
Source_t tmp = { &UserDefinedProvider, option };
Source_t tmp = { &UserDefinedProvider, option, NULL };
source = tmp;
}
else
{
int index = auto_select_mirror (dish->sources, dish->sources_n, dish->aliases);
source = dish->sources[index];
char *default_msg = "该 combo dish 不支持用户自定义源,可能原因是:该 combo dish 的多个 sub dish 所需要的源不同,无法确定你提供的源到底适用于哪个 sub dish,因此请尝试单独为每个 sub dish 指定源 (使用 chsrc ls <dish> 查看其 sub dish 列表)";
chsrc_error (default_msg);
exit (Exit_Unsupported);
}
}
else
{
int index = chsrc_resolve_combo_subdish_source (dish, option);
int index = resolve_combo_subdish_source (dish, mirror_code);
source = dish->sources[index];
}
}
@@ -658,7 +664,7 @@ chsrc_yield_source (Dish_t *dish, char *option)
if (!(dish->can_user_define))
{
char *en_msg = "Using user-defined sources for this dish is not supported.";
char *zh_msg = dish->can_user_define_explain ? xy_2strcat ("暂不支持对该菜品使用用户自定义源,", dish->can_user_define_explain) : "暂不支持对该菜品使用用户自定义源";
char *zh_msg = dish->user_define_cap_explain ? xy_2strcat ("暂不支持对该菜品使用用户自定义源,", dish->user_define_cap_explain) : "暂不支持对该菜品使用用户自定义源";
chsrc_error (ENGLISH ? en_msg : zh_msg);
exit (Exit_Unsupported);
}
+2 -2
View File
@@ -197,8 +197,8 @@ typedef struct Dish_t
/* Features */
bool can_english; /* 是否支持英文输出 */
bool can_user_define; /* 是否支持用户自定义URL来换源 */
char *can_user_define_explain; /* 用户自定义URL的说明 */
bool can_user_define; /* 是否支持用户自定义URL来换源 */
char *user_define_cap_explain; /* 用户不能自定义URL的原因解释 */
/**
* 各作用域的支持情况
+1 -1
View File
@@ -10,7 +10,7 @@ pl_uv_pypi_index_prepare (void)
chef_prep_this_dish (pl_uv_pypi_index, gsr);
chef_set_recipe_created_on (this, "2024-12-11");
chef_set_recipe_last_updated (this, "2026-08-12");
chef_set_recipe_last_updated (this, "2026-08-19");
chef_set_chefs (this, 3, "@happy-game", "@MingriLingran", "@Mikachu2333");
chef_set_sauciers (this, 2, "@ccmywish", "@Kattos");
+2 -5
View File
@@ -26,7 +26,7 @@ pl_uv_python_build_prepare (void)
chef_prep_this_dish (pl_uv_python_build, gsr);
chef_set_recipe_created_on (this, "2026-08-02");
chef_set_recipe_last_updated (this, "2026-08-13");
chef_set_recipe_last_updated (this, "2026-08-19");
chef_set_chefs (this, 2, "@Mikachu2333", "@ccmywish");
chef_set_sauciers (this, 0);
@@ -37,10 +37,7 @@ pl_uv_python_build_prepare (void)
chef_set_default_scope (this, UserScope);
chef_deny_english (this);
chef_deny_user_define (this);
this->can_user_define_explain =
CHINESE ? "python-install-mirror 不支持手动指定,chsrc 会自动选择"
: "python-install-mirror cannot be specified manually; chsrc selects it automatically";
chef_allow_user_define (this);
def_sources_begin ()
{&UpstreamProvider, "https://github.com/astral-sh/python-build-standalone/releases/download", DelegateToUpstream},
+2 -1
View File
@@ -10,9 +10,10 @@ pl_uv_prepare (void)
chef_prep_this_dish (pl_uv, NOOP);
chef_set_recipe_created_on (this, "2026-08-12");
chef_set_recipe_last_updated (this, "2026-08-13");
chef_set_recipe_last_updated (this, "2026-08-19");
chef_set_sub_dishes (this, 2, &pl_uv_pypi_index_dish, &pl_uv_python_build_dish);
chef_deny_user_define (this);
chef_use_other_dish_sources (this, &pl_pypi_dish);
}