Capstone.VersionGuard (Capstone v0.33.3)

Copy Markdown View Source

Fails loudly when the Capstone.Config actually on the code path came from an older capstone than this project's own dependency tree pins.

capstone ships both as a Mix archive (mix archive.install hex capstone, giving mix capstone.new) and as a project's own dependency (giving the engine that keeps that project upgradable). Both can put a :capstone application on the same VM's code path at once — a developer's globally-installed archive, and the project-local build the project's own dependency resolves — and only one wins a same-named-module collision. Which one wins is decided by Mix's code path ordering, not by intent, so the only safe check is: whichever :capstone is actually LOADED right now, is its version at least what this project's own mix.lock pins?

A newer loaded version than the pin is fine (capstone's guarantees hold forward) — only OLDER is the dangerous direction, since it can silently reintroduce a fixed bug or omit a schema field the pinned version added.

Summary

Functions

Raises Mix.Error if the loaded :capstone is older than the version this project's mix.lock pins for it. A no-op — returns :ok without comparing anything — when either side is unavailable: no :capstone loaded at all, or no hex-sourced lock entry (a path: dependency, as during capstone's own pre-publish development, or no dependency on it at all — the case for this repository itself, which IS :capstone rather than depending on it).

Functions

verify!(spec_fun \\ &Application.spec/2, lock_fun \\ &Lock.read/0)

@spec verify!((atom(), atom() -> charlist() | nil), (-> map())) :: :ok

Raises Mix.Error if the loaded :capstone is older than the version this project's mix.lock pins for it. A no-op — returns :ok without comparing anything — when either side is unavailable: no :capstone loaded at all, or no hex-sourced lock entry (a path: dependency, as during capstone's own pre-publish development, or no dependency on it at all — the case for this repository itself, which IS :capstone rather than depending on it).

The two lookups are injected as the RAW Application/Mix.Dep.Lock calls, not pre-resolved values, so a test can supply fake raw data and genuinely exercise every branch of loaded_version/1 and locked_version/1 — including the {:hex, ...} decode, which no test could reach if the injected value were already the resolved string.