mirror of
https://github.com/RubyMetric/chsrc
synced 2026-10-25 17:36:32 +08:00
重构: yield source 时先考虑 combo 的 user define 能力
This commit is contained in:
9 files changed
+109
-74
No files matched your search
+2
-2
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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];
|
||||
}
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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的原因解释 */
|
||||
|
||||
/**
|
||||
* 各作用域的支持情况
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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},
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
Reference in new issue
Block a user