@@ -110,6 +110,20 @@ local function release_tag(root)
110110 return nil
111111end
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
177191end
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 ?
181218function M .build (root )
@@ -201,23 +238,44 @@ function M.build(root)
201238 vim .notify (" lockfile.nvim: built native module from source." )
202239end
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.
206247function 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