Fix the two compile errors, and let `just fetch` find the release itself
Space::new takes no arguments; size it with width/height instead. And button::link returns Builder<_, Hyperlink> where the rest return Builder<_, Text>, so the match arms never unified — finish each one into an Element where it is built. `just fetch` with no tag now resolves the newest v* tag with git ls-remote (over SSH, so no token needed for that part) and verifies the checksum the workflow publishes beside each tarball. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
e289b31 parent: d2c4134 modified
README.md +3 -2 | @@ -61,8 +61,9 @@ proc onView(ctx: pointer; b: Builder) {.cdecl.} = | ||
| 61 | 61 | The demo needs `nim/libcosmic_ffi.so`. Take it from a release: |
| 62 | 62 | |
| 63 | 63 | ```bash |
| 64 | -export RICKUB_TOKEN=... # the repo is private | |
| 65 | -just fetch <asset-url-from-the-release-page> | |
| 64 | +export RICKUB_TOKEN=... # the repo is private | |
| 65 | +just fetch # newest v* tag on the remote | |
| 66 | +just fetch v0.1.2 # or a specific one | |
| 66 | 67 | just run |
| 67 | 68 | ``` |
| 68 | 69 | |
| @@ -61,8 +61,9 @@ proc onView(ctx: pointer; b: Builder) {.cdecl.} = | |||
| 61 | The demo needs `nim/libcosmic_ffi.so`. Take it from a release: | 61 | The demo needs `nim/libcosmic_ffi.so`. Take it from a release: |
| 62 | 62 | ||
| 63 | ```bash | 63 | ```bash |
| 64 | -export RICKUB_TOKEN=... # the repo is private | 64 | +export RICKUB_TOKEN=... # the repo is private |
| 65 | -just fetch <asset-url-from-the-release-page> | 65 | +just fetch # newest v* tag on the remote |
| 66 | +just fetch v0.1.2 # or a specific one | ||
| 66 | just run | 67 | just run |
| 67 | ``` | 68 | ``` |
| 68 | 69 | ||
modified
cosmic_ffi/src/lib.rs +24 -12 | @@ -223,7 +223,12 @@ pub unsafe extern "C" fn cosmic_fill(b: *mut Builder) { | ||
| 223 | 223 | /// A blank gap of `w` by `h` pixels. |
| 224 | 224 | #[no_mangle] |
| 225 | 225 | pub unsafe extern "C" fn cosmic_space(b: *mut Builder, w: f32, h: f32) { |
| 226 | - builder!(b).leaf(widget::Space::new(Length::Fixed(w), Length::Fixed(h)).into()) | |
| 226 | + builder!(b).leaf( | |
| 227 | + widget::Space::new() | |
| 228 | + .width(Length::Fixed(w)) | |
| 229 | + .height(Length::Fixed(h)) | |
| 230 | + .into(), | |
| 231 | + ) | |
| 227 | 232 | } |
| 228 | 233 | |
| 229 | 234 | /// Text styles for [`cosmic_text`], matching COSMIC's type scale. |
| @@ -266,17 +271,24 @@ pub const BUTTON_LINK: i32 = 4; | ||
| 266 | 271 | pub unsafe extern "C" fn cosmic_button(b: *mut Builder, style: i32, label: *const c_char, id: i32) { |
| 267 | 272 | let b = builder!(b); |
| 268 | 273 | let s = str_or(label, ""); |
| 269 | - let button = match style { | |
| 270 | - BUTTON_SUGGESTED => widget::button::suggested(s), | |
| 271 | - BUTTON_DESTRUCTIVE => widget::button::destructive(s), | |
| 272 | - BUTTON_TEXT => widget::button::text(s), | |
| 273 | - BUTTON_LINK => widget::button::link(s), | |
| 274 | - _ => widget::button::standard(s), | |
| 275 | - }; | |
| 276 | - b.leaf(if id < 0 { | |
| 277 | - button.into() | |
| 278 | - } else { | |
| 279 | - button.on_press(Message::Pressed(id)).into() | |
| 274 | + // Each constructor returns a differently-typed `button::Builder`, so the | |
| 275 | + // arms cannot unify: finish each one into an Element where it is built. | |
| 276 | + macro_rules! finish { | |
| 277 | + ($button:expr) => {{ | |
| 278 | + let button = $button; | |
| 279 | + if id < 0 { | |
| 280 | + button.into() | |
| 281 | + } else { | |
| 282 | + button.on_press(Message::Pressed(id)).into() | |
| 283 | + } | |
| 284 | + }}; | |
| 285 | + } | |
| 286 | + b.leaf(match style { | |
| 287 | + BUTTON_SUGGESTED => finish!(widget::button::suggested(s)), | |
| 288 | + BUTTON_DESTRUCTIVE => finish!(widget::button::destructive(s)), | |
| 289 | + BUTTON_TEXT => finish!(widget::button::text(s)), | |
| 290 | + BUTTON_LINK => finish!(widget::button::link(s)), | |
| 291 | + _ => finish!(widget::button::standard(s)), | |
| 280 | 292 | }) |
| 281 | 293 | } |
| 282 | 294 | |
| @@ -223,7 +223,12 @@ pub unsafe extern "C" fn cosmic_fill(b: *mut Builder) { | |||
| 223 | /// A blank gap of `w` by `h` pixels. | 223 | /// A blank gap of `w` by `h` pixels. |
| 224 | #[no_mangle] | 224 | #[no_mangle] |
| 225 | pub unsafe extern "C" fn cosmic_space(b: *mut Builder, w: f32, h: f32) { | 225 | pub unsafe extern "C" fn cosmic_space(b: *mut Builder, w: f32, h: f32) { |
| 226 | - builder!(b).leaf(widget::Space::new(Length::Fixed(w), Length::Fixed(h)).into()) | 226 | + builder!(b).leaf( |
| 227 | + widget::Space::new() | ||
| 228 | + .width(Length::Fixed(w)) | ||
| 229 | + .height(Length::Fixed(h)) | ||
| 230 | + .into(), | ||
| 231 | + ) | ||
| 227 | } | 232 | } |
| 228 | 233 | ||
| 229 | /// Text styles for [`cosmic_text`], matching COSMIC's type scale. | 234 | /// Text styles for [`cosmic_text`], matching COSMIC's type scale. |
| @@ -266,17 +271,24 @@ pub const BUTTON_LINK: i32 = 4; | |||
| 266 | pub unsafe extern "C" fn cosmic_button(b: *mut Builder, style: i32, label: *const c_char, id: i32) { | 271 | pub unsafe extern "C" fn cosmic_button(b: *mut Builder, style: i32, label: *const c_char, id: i32) { |
| 267 | let b = builder!(b); | 272 | let b = builder!(b); |
| 268 | let s = str_or(label, ""); | 273 | let s = str_or(label, ""); |
| 269 | - let button = match style { | 274 | + // Each constructor returns a differently-typed `button::Builder`, so the |
| 270 | - BUTTON_SUGGESTED => widget::button::suggested(s), | 275 | + // arms cannot unify: finish each one into an Element where it is built. |
| 271 | - BUTTON_DESTRUCTIVE => widget::button::destructive(s), | 276 | + macro_rules! finish { |
| 272 | - BUTTON_TEXT => widget::button::text(s), | 277 | + ($button:expr) => {{ |
| 273 | - BUTTON_LINK => widget::button::link(s), | 278 | + let button = $button; |
| 274 | - _ => widget::button::standard(s), | 279 | + if id < 0 { |
| 275 | - }; | 280 | + button.into() |
| 276 | - b.leaf(if id < 0 { | 281 | + } else { |
| 277 | - button.into() | 282 | + button.on_press(Message::Pressed(id)).into() |
| 278 | - } else { | 283 | + } |
| 279 | - button.on_press(Message::Pressed(id)).into() | 284 | + }}; |
| 285 | + } | ||
| 286 | + b.leaf(match style { | ||
| 287 | + BUTTON_SUGGESTED => finish!(widget::button::suggested(s)), | ||
| 288 | + BUTTON_DESTRUCTIVE => finish!(widget::button::destructive(s)), | ||
| 289 | + BUTTON_TEXT => finish!(widget::button::text(s)), | ||
| 290 | + BUTTON_LINK => finish!(widget::button::link(s)), | ||
| 291 | + _ => finish!(widget::button::standard(s)), | ||
| 280 | }) | 292 | }) |
| 281 | } | 293 | } |
| 282 | 294 | ||
modified
justfile +29 -4 | @@ -1,6 +1,9 @@ | ||
| 1 | 1 | # cosmicnim tasks. `just` on its own runs the demo. |
| 2 | 2 | |
| 3 | 3 | so := "nim/libcosmic_ffi.so" |
| 4 | +export REMOTE := "rickub" | |
| 5 | +export BASE_URL := "https://git.rickub.com/nandi/cosmicnim" | |
| 6 | +export TARGET := "x86_64-unknown-linux-gnu" | |
| 4 | 7 | |
| 5 | 8 | default: run |
| 6 | 9 | |
| @@ -24,17 +27,39 @@ rust-check: | ||
| 24 | 27 | fmt: |
| 25 | 28 | cd cosmic_ffi && cargo fmt |
| 26 | 29 | |
| 27 | -# Install a release tarball's .so from its asset URL (needs $RICKUB_TOKEN) | |
| 28 | -fetch url: | |
| 30 | +# Install the .so from a release. No tag means the newest v* tag on the remote. | |
| 31 | +fetch tag="": | |
| 32 | + #!/usr/bin/env bash | |
| 33 | + set -euo pipefail | |
| 34 | + : "${RICKUB_TOKEN:?export RICKUB_TOKEN with a token that can read releases}" | |
| 35 | + tag="{{tag}}" | |
| 36 | + if [ -z "$tag" ]; then | |
| 37 | + # The remote is the source of truth; local tags may be stale or absent. | |
| 38 | + tag=$(git ls-remote --tags --refs "$REMOTE" 'v*' \ | |
| 39 | + | awk -F/ '{print $NF}' | sort -V | tail -1) | |
| 40 | + [ -n "$tag" ] || { echo "no v* tags on $REMOTE" >&2; exit 1; } | |
| 41 | + echo "latest release is $tag" | |
| 42 | + fi | |
| 43 | + just fetch-url "$BASE_URL/releases/download/$tag/cosmic_ffi-$tag-$TARGET.tar.gz" | |
| 44 | + | |
| 45 | +# Install the .so from an explicit asset URL (needs $RICKUB_TOKEN). | |
| 46 | +fetch-url url: | |
| 29 | 47 | #!/usr/bin/env bash |
| 30 | 48 | set -euo pipefail |
| 31 | 49 | : "${RICKUB_TOKEN:?export RICKUB_TOKEN with a token that can read releases}" |
| 32 | 50 | tmp=$(mktemp -d) |
| 33 | 51 | trap 'rm -rf "$tmp"' EXIT |
| 34 | - curl -fsSL -H "Authorization: Bearer $RICKUB_TOKEN" -o "$tmp/asset.tar.gz" "{{url}}" | |
| 52 | + auth=(-H "Authorization: Bearer $RICKUB_TOKEN") | |
| 53 | + curl -fsSL "${auth[@]}" -o "$tmp/asset.tar.gz" "{{url}}" | |
| 54 | + # The workflow publishes a checksum beside every tarball; use it if it is there. | |
| 55 | + if curl -fsSL "${auth[@]}" -o "$tmp/asset.sha256" "{{url}}.sha256" 2>/dev/null; then | |
| 56 | + (cd "$tmp" && sed "s| .*| asset.tar.gz|" asset.sha256 | sha256sum -c -) | |
| 57 | + else | |
| 58 | + echo "no .sha256 alongside the asset; skipping checksum" >&2 | |
| 59 | + fi | |
| 35 | 60 | tar xzf "$tmp/asset.tar.gz" -C "$tmp" |
| 36 | 61 | cp "$tmp"/cosmic_ffi-*/libcosmic_ffi.so {{so}} |
| 37 | - @echo "installed {{so}}" | |
| 62 | + echo "installed {{so}}" | |
| 38 | 63 | |
| 39 | 64 | # Cut a release by pushing a tag with git (an API-made tag triggers no CI) |
| 40 | 65 | tag version: |
| @@ -1,6 +1,9 @@ | |||
| 1 | # cosmicnim tasks. `just` on its own runs the demo. | 1 | # cosmicnim tasks. `just` on its own runs the demo. |
| 2 | 2 | ||
| 3 | so := "nim/libcosmic_ffi.so" | 3 | so := "nim/libcosmic_ffi.so" |
| 4 | +export REMOTE := "rickub" | ||
| 5 | +export BASE_URL := "https://git.rickub.com/nandi/cosmicnim" | ||
| 6 | +export TARGET := "x86_64-unknown-linux-gnu" | ||
| 4 | 7 | ||
| 5 | default: run | 8 | default: run |
| 6 | 9 | ||
| @@ -24,17 +27,39 @@ rust-check: | |||
| 24 | fmt: | 27 | fmt: |
| 25 | cd cosmic_ffi && cargo fmt | 28 | cd cosmic_ffi && cargo fmt |
| 26 | 29 | ||
| 27 | -# Install a release tarball's .so from its asset URL (needs $RICKUB_TOKEN) | 30 | +# Install the .so from a release. No tag means the newest v* tag on the remote. |
| 28 | -fetch url: | 31 | +fetch tag="": |
| 32 | + #!/usr/bin/env bash | ||
| 33 | + set -euo pipefail | ||
| 34 | + : "${RICKUB_TOKEN:?export RICKUB_TOKEN with a token that can read releases}" | ||
| 35 | + tag="{{tag}}" | ||
| 36 | + if [ -z "$tag" ]; then | ||
| 37 | + # The remote is the source of truth; local tags may be stale or absent. | ||
| 38 | + tag=$(git ls-remote --tags --refs "$REMOTE" 'v*' \ | ||
| 39 | + | awk -F/ '{print $NF}' | sort -V | tail -1) | ||
| 40 | + [ -n "$tag" ] || { echo "no v* tags on $REMOTE" >&2; exit 1; } | ||
| 41 | + echo "latest release is $tag" | ||
| 42 | + fi | ||
| 43 | + just fetch-url "$BASE_URL/releases/download/$tag/cosmic_ffi-$tag-$TARGET.tar.gz" | ||
| 44 | + | ||
| 45 | +# Install the .so from an explicit asset URL (needs $RICKUB_TOKEN). | ||
| 46 | +fetch-url url: | ||
| 29 | #!/usr/bin/env bash | 47 | #!/usr/bin/env bash |
| 30 | set -euo pipefail | 48 | set -euo pipefail |
| 31 | : "${RICKUB_TOKEN:?export RICKUB_TOKEN with a token that can read releases}" | 49 | : "${RICKUB_TOKEN:?export RICKUB_TOKEN with a token that can read releases}" |
| 32 | tmp=$(mktemp -d) | 50 | tmp=$(mktemp -d) |
| 33 | trap 'rm -rf "$tmp"' EXIT | 51 | trap 'rm -rf "$tmp"' EXIT |
| 34 | - curl -fsSL -H "Authorization: Bearer $RICKUB_TOKEN" -o "$tmp/asset.tar.gz" "{{url}}" | 52 | + auth=(-H "Authorization: Bearer $RICKUB_TOKEN") |
| 53 | + curl -fsSL "${auth[@]}" -o "$tmp/asset.tar.gz" "{{url}}" | ||
| 54 | + # The workflow publishes a checksum beside every tarball; use it if it is there. | ||
| 55 | + if curl -fsSL "${auth[@]}" -o "$tmp/asset.sha256" "{{url}}.sha256" 2>/dev/null; then | ||
| 56 | + (cd "$tmp" && sed "s| .*| asset.tar.gz|" asset.sha256 | sha256sum -c -) | ||
| 57 | + else | ||
| 58 | + echo "no .sha256 alongside the asset; skipping checksum" >&2 | ||
| 59 | + fi | ||
| 35 | tar xzf "$tmp/asset.tar.gz" -C "$tmp" | 60 | tar xzf "$tmp/asset.tar.gz" -C "$tmp" |
| 36 | cp "$tmp"/cosmic_ffi-*/libcosmic_ffi.so {{so}} | 61 | cp "$tmp"/cosmic_ffi-*/libcosmic_ffi.so {{so}} |
| 37 | - @echo "installed {{so}}" | 62 | + echo "installed {{so}}" |
| 38 | 63 | ||
| 39 | # Cut a release by pushing a tag with git (an API-made tag triggers no CI) | 64 | # Cut a release by pushing a tag with git (an API-made tag triggers no CI) |
| 40 | tag version: | 65 | tag version: |