chore: satisfy CI fmt/clippy gates; make the release publish step idempotent
Docker / publish (push) Canceled after 0s
Release / crates-io (push) Canceled after 0s
Release / release (macos-14, aarch64-apple-darwin) (push) Canceled after 0s
Release / release (ubuntu-latest, x86_64-unknown-linux-gnu) (push) Canceled after 0s
Release / release (windows-latest, x86_64-pc-windows-msvc) (push) Canceled after 0s

`cargo fmt --all -- --check` and `cargo clippy --all-targets -- -D warnings` are
CI gates and both were failing on this release's code.

- rustfmt across the files touched by the release
- `.split('/').last()` walks the whole iterator on a DoubleEndedIterator; use
  `.next_back()` (4 sites in the setup/featured + delete handlers)
- `set_progress` had two identical branches; the intent is "take the first
  reading, then only move forward", which is one condition

release.yml published unconditionally on a version tag, so a version already on
crates.io (released by hand, or a re-run of the job) failed the workflow — a
version can never be re-uploaded. It now checks the registry and skips instead.
This commit is contained in:
infosave2007
2026-08-06 18:18:21 +03:00
parent 9ec8861464
commit 32ce2f7ed7
5 changed files with 193 additions and 49 deletions
+76 -18
View File
@@ -206,10 +206,9 @@ impl JobStore {
if let Some(j) = self.jobs.lock().unwrap().get_mut(id) {
let f = frac.clamp(0.0, 1.0);
let cur = j.progress.unwrap_or(0.0);
// monotonic only — never go backwards (curl reprints, re-download)
if f > cur + 0.001 {
j.progress = Some(f);
} else if j.progress.is_none() {
// monotonic only — never go backwards (curl reprints, re-download),
// but an unset bar takes whatever the first reading is
if j.progress.is_none() || f > cur + 0.001 {
j.progress = Some(f);
}
if !phase.is_empty() {
@@ -306,7 +305,9 @@ impl JobStore {
let key = format!("{}::{}", j.repo, j.variant.clone().unwrap_or_default());
match map.get(&key) {
Some(prev) if prev.started >= j.started => {}
_ => { map.insert(key, j); }
_ => {
map.insert(key, j);
}
}
}
let mut v: Vec<Job> = map.into_values().collect();
@@ -434,7 +435,11 @@ pub async fn hf_repo_variants(id: &str, token: Option<&str>) -> Vec<(String, u64
let sz = item
.get("size")
.and_then(|v| v.as_u64())
.or_else(|| item.get("lfs").and_then(|l| l.get("size")).and_then(|v| v.as_u64()))
.or_else(|| {
item.get("lfs")
.and_then(|l| l.get("size"))
.and_then(|v| v.as_u64())
})
.unwrap_or(0);
if sz == 0 {
continue;
@@ -559,7 +564,8 @@ async fn download_cmf_repo(
}
let mut cmf_files: Vec<(String, u64)> = Vec::new();
let mut sharded_dirs: std::collections::HashMap<String, Vec<String>> = std::collections::HashMap::new();
let mut sharded_dirs: std::collections::HashMap<String, Vec<String>> =
std::collections::HashMap::new();
let mut dir_sizes: std::collections::HashMap<String, u64> = std::collections::HashMap::new();
if let Ok(resp) = req.send().await {
if resp.status().is_success() {
@@ -573,13 +579,20 @@ async fn download_cmf_repo(
let sz = item
.get("size")
.and_then(|v| v.as_u64())
.or_else(|| item.get("lfs").and_then(|l| l.get("size")).and_then(|v| v.as_u64()))
.or_else(|| {
item.get("lfs")
.and_then(|l| l.get("size"))
.and_then(|v| v.as_u64())
})
.unwrap_or(0);
if path.to_ascii_lowercase().ends_with(".cmf") {
cmf_files.push((path.to_string(), sz));
} else if path.contains('/') && path.starts_with("parts-") {
let top = path.split('/').next().unwrap_or(path).to_string();
sharded_dirs.entry(top.clone()).or_default().push(path.to_string());
sharded_dirs
.entry(top.clone())
.or_default()
.push(path.to_string());
*dir_sizes.entry(top).or_default() += sz;
}
}
@@ -591,12 +604,19 @@ async fn download_cmf_repo(
// Decide what to download: single .cmf file vs sharded variant directory
let is_sharded = !sharded_dirs.is_empty();
let chosen_variant = variant.as_deref().map(|v| v.trim()).filter(|v| !v.is_empty());
let chosen_variant = variant
.as_deref()
.map(|v| v.trim())
.filter(|v| !v.is_empty());
if is_sharded {
// pick variant: explicit > first alphabetically
let target_dir = if let Some(v) = chosen_variant {
if sharded_dirs.contains_key(v) { v.to_string() } else { sharded_dirs.keys().next().cloned().unwrap_or_default() }
if sharded_dirs.contains_key(v) {
v.to_string()
} else {
sharded_dirs.keys().next().cloned().unwrap_or_default()
}
} else {
// prefer smallest? use first sorted
let mut keys: Vec<String> = sharded_dirs.keys().cloned().collect();
@@ -611,9 +631,23 @@ async fn download_cmf_repo(
return;
}
let total_sz = dir_sizes.get(&target_dir).copied().unwrap_or(0);
let q = if target_dir.contains("q2tp") { "Q2TP" } else if target_dir.contains("q4tp") { "Q4TP" } else { "READY_CMF" };
let q = if target_dir.contains("q2tp") {
"Q2TP"
} else if target_dir.contains("q4tp") {
"Q4TP"
} else {
"READY_CMF"
};
store.update_quant(&id, q.to_string());
store.push_line(&id, format!("→ downloading {} ({} files, {}) from HuggingFace...", target_dir, files.len(), format_bytes(total_sz)));
store.push_line(
&id,
format!(
"→ downloading {} ({} files, {}) from HuggingFace...",
target_dir,
files.len(),
format_bytes(total_sz)
),
);
store.set_total(&id, total_sz);
store.set_progress(&id, 0.001, "downloading".into());
@@ -635,7 +669,13 @@ async fn download_cmf_repo(
let url = format!("https://huggingface.co/{repo}/resolve/main/{rel}");
store.push_line(&id, format!(" [{}/{}] {filename}", idx + 1, files.len()));
let mut cmd = tokio::process::Command::new("curl");
cmd.arg("-f").arg("-L").arg("-s").arg("-S").arg("-o").arg(&dest).arg(&url);
cmd.arg("-f")
.arg("-L")
.arg("-s")
.arg("-S")
.arg("-o")
.arg(&dest)
.arg(&url);
if let Some(t) = &hf_token {
cmd.arg("-H").arg(format!("Authorization: Bearer {t}"));
}
@@ -758,7 +798,11 @@ async fn download_cmf_repo(
.unwrap_or(0)
};
store.push_line(&id, {
let sz = if total > 0 { format!(" ({})", format_bytes(total)) } else { String::new() };
let sz = if total > 0 {
format!(" ({})", format_bytes(total))
} else {
String::new()
};
format!("→ downloading {cmf_path}{sz} from HuggingFace...")
});
store.set_total(&id, total);
@@ -773,7 +817,12 @@ async fn download_cmf_repo(
let _poller = spawn_size_poller(store.clone(), id.clone(), output_abs.clone());
let mut cmd = tokio::process::Command::new("curl");
cmd.arg("-f").arg("-L").arg("-s").arg("-S").arg("-o").arg(&output_abs);
cmd.arg("-f")
.arg("-L")
.arg("-s")
.arg("-S")
.arg("-o")
.arg(&output_abs);
if let Some(t) = &hf_token {
cmd.arg("-H").arg(format!("Authorization: Bearer {t}"));
@@ -905,7 +954,12 @@ pub fn start_import(store: Arc<JobStore>, cfg: &CmfCfg, p: ImportParams) -> Resu
sanitize(&p.name)
};
// for sharded variants make output distinct (e.g. DeepSeek parts-q2tp vs q4tp); single-file CMF ignores variant
if let Some(v) = p.variant.as_deref().map(|s| s.trim()).filter(|s| !s.is_empty()) {
if let Some(v) = p
.variant
.as_deref()
.map(|s| s.trim())
.filter(|s| !s.is_empty())
{
if v.starts_with("parts-") {
let vs = sanitize(v);
if !base.ends_with(&vs) {
@@ -921,7 +975,11 @@ pub fn start_import(store: Arc<JobStore>, cfg: &CmfCfg, p: ImportParams) -> Resu
.map(|d| d.join(format!("{base}.cmf")).to_string_lossy().to_string())
.unwrap_or_else(|_| output.clone());
let id = gen_id(&format!("{}::{}", p.repo, p.variant.as_deref().unwrap_or("")));
let id = gen_id(&format!(
"{}::{}",
p.repo,
p.variant.as_deref().unwrap_or("")
));
// if same repo/variant is already running, don't reset progress — just return it
if let Some(existing) = store.get(&id) {
if existing.state == "running" {