Skip to content

Commit 5459550

Browse files
committed
feat: use nightly prebuilt when it matches HEAD exactly
When HEAD is not at a release tag, fetch the nightly release's commit asset and only download the nightly binary when it equals the local HEAD sha, so a downloaded binary always matches the checked-out source. Otherwise fall back to building from source.
1 parent f117a1a commit 5459550

3 files changed

Lines changed: 82 additions & 19 deletions

File tree

README.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,9 @@ which commit (these are not classified as semver bumps).
7878
the build step compiles from source, which needs a **Rust toolchain** (`cargo`).
7979

8080
Prebuilt binaries are published for Linux (x86_64, aarch64) and macOS (x86_64,
81-
aarch64). Other platforms (and untagged/branch installs) build from source.
81+
aarch64), both for tagged releases and as a rolling `nightly` for `main`. Other
82+
platforms — and any checkout that doesn't exactly match a published build —
83+
compile from source.
8284

8385
## Installation
8486

@@ -97,8 +99,10 @@ falling back to compiling from source (requires `cargo`).
9799
}
98100
```
99101

100-
Pin to a release tag (e.g. `version = "*"` or `tag = "v1.0.0"`) to get a prebuilt
101-
binary; tracking a branch always builds from source.
102+
Prebuilt binaries are used whenever they're guaranteed to match your checked-out
103+
source: at a release tag (e.g. `version = "*"` / `tag = "v1.0.0"`), or — when
104+
tracking `main` — if your commit is exactly the one the latest `nightly` build
105+
was produced from. Anything else builds from source.
102106

103107
### packer.nvim
104108

doc/lockfile.txt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,11 @@ Supported lockfiles:
3535

3636
- Neovim 0.10 or newer.
3737
- The native module (a hard dependency), implemented in Rust and loaded via
38-
mlua. The build step |lockfile.download()| downloads a prebuilt binary when
39-
HEAD is at a tagged release, otherwise it builds from source, which requires a
40-
Rust toolchain (`cargo`). If the module is missing, commands report an error
41-
with build instructions.
38+
mlua. The build step |lockfile.download()| downloads a prebuilt binary that is
39+
guaranteed to match the checked-out source — at a release tag, or the rolling
40+
`nightly` build when your commit matches it exactly — and otherwise builds
41+
from source, which requires a Rust toolchain (`cargo`). If the module is
42+
missing, commands report an error with build instructions.
4243

4344
Prebuilt binaries are published for Linux (x86_64, aarch64) and macOS
4445
(x86_64, aarch64); other platforms build from source.

lua/lockfile/download.lua

Lines changed: 70 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,20 @@ local function release_tag(root)
110110
return nil
111111
end
112112

113+
--- The full commit sha at HEAD, or nil.
114+
---@param root string
115+
---@return string?
116+
local function head_sha(root)
117+
local res = vim.system({ "git", "-C", root, "rev-parse", "HEAD" }):wait()
118+
if res.code == 0 then
119+
local sha = vim.trim(res.stdout or "")
120+
if sha ~= "" then
121+
return sha
122+
end
123+
end
124+
return nil
125+
end
126+
113127
--- Download `url` to `out` with curl. Returns ok, error message.
114128
---@param url string
115129
---@param out string
@@ -176,6 +190,29 @@ local function install_prebuilt(root, tag, triple)
176190
return true, nil
177191
end
178192

193+
--- The commit sha the published `nightly` binaries were built from, fetched
194+
--- from the nightly release's `commit` asset, or nil if unavailable.
195+
---@return string?
196+
local function nightly_commit()
197+
local url = ("https://github.com/%s/releases/download/nightly/commit"):format(REPO)
198+
local tmp = vim.fn.tempname()
199+
local ok = curl(url, tmp)
200+
if not ok then
201+
return nil
202+
end
203+
local fd = io.open(tmp, "r")
204+
local sha
205+
if fd then
206+
sha = vim.trim(fd:read("*a") or "")
207+
fd:close()
208+
end
209+
pcall(vim.uv.fs_unlink, tmp)
210+
if sha and sha ~= "" then
211+
return sha
212+
end
213+
return nil
214+
end
215+
179216
--- Build the native module from source and copy it into place.
180217
---@param root string?
181218
function M.build(root)
@@ -201,23 +238,44 @@ function M.build(root)
201238
vim.notify("lockfile.nvim: built native module from source.")
202239
end
203240

204-
--- Install the native module: prefer a prebuilt binary matching the installed
205-
--- release tag, otherwise build from source.
241+
--- Install the native module. Prefers a prebuilt binary that is guaranteed to
242+
--- match the checked-out source:
243+
--- * at a release tag (v*): the matching release's binary;
244+
--- * otherwise: the `nightly` binary, but only when it was built from this
245+
--- exact commit (verified via the nightly `commit` asset).
246+
--- Falls back to building from source in every other case.
206247
function M.download_or_build()
207248
local root = plugin_root()
208-
local tag = release_tag(root)
209249
local triple = target_triple()
210250

211-
if tag and triple then
212-
local ok, err = install_prebuilt(root, tag, triple)
213-
if ok then
214-
vim.notify(("lockfile.nvim: installed prebuilt binary for %s (%s)."):format(triple, tag))
215-
return
251+
if triple then
252+
local tag = release_tag(root)
253+
if tag then
254+
local ok, err = install_prebuilt(root, tag, triple)
255+
if ok then
256+
vim.notify(("lockfile.nvim: installed prebuilt binary for %s (%s)."):format(triple, tag))
257+
return
258+
end
259+
vim.notify(
260+
("lockfile.nvim: prebuilt unavailable (%s); building from source."):format(err or "unknown"),
261+
vim.log.levels.INFO
262+
)
263+
else
264+
-- Not at a release tag: use the nightly binary only if it was built from
265+
-- exactly this commit, so the binary always matches the source.
266+
local head = head_sha(root)
267+
if head and nightly_commit() == head then
268+
local ok, err = install_prebuilt(root, "nightly", triple)
269+
if ok then
270+
vim.notify(("lockfile.nvim: installed nightly prebuilt for %s."):format(triple))
271+
return
272+
end
273+
vim.notify(
274+
("lockfile.nvim: nightly prebuilt unavailable (%s); building from source."):format(err or "unknown"),
275+
vim.log.levels.INFO
276+
)
277+
end
216278
end
217-
vim.notify(
218-
("lockfile.nvim: prebuilt unavailable (%s); building from source."):format(err or "unknown"),
219-
vim.log.levels.INFO
220-
)
221279
end
222280

223281
M.build(root)

0 commit comments

Comments
 (0)