guise-ui 1.5.3

A component library for gpui, Zed's GPU-accelerated UI framework: a themed palette, sizing tokens, 130+ composable components, a reactive state layer, and an in-app Safari-style inspector.
Documentation
//! HTTPS fetching via `curl`, shared by the release check and asset downloads.
//!
//! `curl` rather than an HTTP crate because it is already on every macOS and
//! Linux machine, and because it keeps guise's dependency list at gpui. Defense
//! in depth: https only (on redirects too), a size cap on in-memory bodies, and
//! `--` so a URL beginning with `-` can't be read as an option.

use std::path::Path;
use std::process::Command;
use std::time::Duration;

/// Cap for in-memory bodies (the release JSON): 8 MiB.
const MAX_BYTES: &str = "8388608";

/// How often to sample the partial file while a download runs. Fast enough for a
/// progress bar that looks live, slow enough to be free.
const SAMPLE: Duration = Duration::from_millis(120);

/// Fetch `url` into memory (small JSON bodies only — capped at [`MAX_BYTES`]).
pub(crate) fn bytes(url: &str, user_agent: &str) -> Result<Vec<u8>, String> {
  if !url.starts_with("https://") {
    return Err("refusing non-https url".to_string());
  }
  let out = Command::new("curl")
    .args([
      "-sL",
      "--fail",
      "--proto",
      "=https",
      "--proto-redir",
      "=https",
      "--max-filesize",
      MAX_BYTES,
      "-H",
      "Accept: application/vnd.github+json",
      "-H",
    ])
    .arg(format!("User-Agent: {user_agent}"))
    .args(["--", url])
    .output()
    .map_err(|e| format!("curl: {e}"))?;
  if out.status.success() {
    Ok(out.stdout)
  } else {
    Err(format!("fetch failed ({})", out.status))
  }
}

/// Download `url` to `dest`, reporting bytes written as they land.
///
/// `curl` runs as a child rather than a blocking `output()` call so the partial
/// file can be sampled while it writes — the feed already gave us the asset's
/// total size, so polling the file length is all a real progress bar needs, and
/// it beats parsing curl's progress meter out of stderr.
///
/// `expected` is that size (0 when unknown). A finished download that doesn't
/// match it is reported as a failure: a truncated `.dmg` fails to mount, and a
/// truncated AppImage would be renamed over a working install.
pub(crate) fn file(
  url: &str,
  dest: &Path,
  expected: u64,
  user_agent: &str,
  on_progress: &dyn Fn(u64),
) -> Result<(), String> {
  if !url.starts_with("https://") {
    return Err("refusing non-https download".to_string());
  }
  // Never write *through* whatever is already at `dest`: curl -o follows a
  // symlink, and on the AppImage path the staged file is renamed over the
  // running binary, so a planted link would end up being what gets executed.
  let _ = std::fs::remove_file(dest);
  let mut child = Command::new("curl")
    .args([
      "-sL",
      "--fail",
      "--proto",
      "=https",
      "--proto-redir",
      "=https",
      // No --max-time: a large asset on a slow link is legitimate. These
      // bound being *stuck* instead — no connection in 30s, or under
      // 1 KiB/s for a solid minute — so a dead network fails the install
      // rather than parking the prompt in "Updating…" forever.
      "--connect-timeout",
      "30",
      "--speed-limit",
      "1024",
      "--speed-time",
      "60",
      "-o",
    ])
    .arg(dest)
    .arg("-H")
    .arg(format!("User-Agent: {user_agent}"))
    .args(["--", url])
    .spawn()
    .map_err(|e| format!("curl: {e}"))?;

  let status = loop {
    match child.try_wait() {
      Ok(Some(status)) => break status,
      Ok(None) => {
        on_progress(std::fs::metadata(dest).map(|m| m.len()).unwrap_or(0));
        std::thread::sleep(SAMPLE);
      }
      // `Child` has no Drop that reaps or kills, so bailing out here would
      // leave curl running and still writing to `dest` — and a retry would
      // then race a second curl against the first over the same path. Take
      // the process and the partial file down together.
      Err(e) => {
        let _ = child.kill();
        let _ = child.wait();
        let _ = std::fs::remove_file(dest);
        return Err(format!("curl: {e}"));
      }
    }
  };
  if !status.success() {
    let _ = std::fs::remove_file(dest);
    return Err(format!("download failed ({status})"));
  }

  let got = std::fs::metadata(dest).map(|m| m.len()).unwrap_or(0);
  if expected > 0 && got != expected {
    let _ = std::fs::remove_file(dest);
    return Err(format!(
      "download is incomplete ({got} of {expected} bytes)"
    ));
  }
  on_progress(got);
  Ok(())
}