diff --git a/.gitattributes b/.gitattributes index 6f006049e92d..d67974e66b69 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,7 +1,26 @@ -**/deps.nix linguist-generated +# node/js lock files +**/package-lock.json linguist-generated +**/yarn.nix linguist-generated +**/yarn.lock linguist-generated + +# Rust lock files +**/Cargo.lock linguist-generated +pkgs/build-support/rust/**/Cargo.lock -linguist-generated + +# NuGet, Gradle and others **/deps.json linguist-generated + +# Ruby lock files +**/gemset.nix linguist-generated +**/Gemfile.lock linguist-generated + +# PHP lock files +**/composer.lock linguist-generated + +# various package managers and tools +**/deps.nix linguist-generated **/deps.toml linguist-generated -**/node-packages.nix linguist-generated + pkgs/applications/editors/emacs-modes/*-generated.nix linguist-generated pkgs/development/r-modules/*-packages.nix linguist-generated diff --git a/lib/customisation.nix b/lib/customisation.nix index ce00e364ba76..e9e88aff7cb5 100644 --- a/lib/customisation.nix +++ b/lib/customisation.nix @@ -6,6 +6,8 @@ let unsafeGetAttrPos ; inherit (lib) + all + attrValues functionArgs isFunction mirrorFunctionArgs @@ -19,8 +21,6 @@ let sortOn take length - filterAttrs - flip head pipe isDerivation @@ -98,19 +98,18 @@ rec { */ overrideDerivation = drv: f: - let - newDrv = derivation (drv.drvAttrs // (f drv)); - in - flip (extendDerivation (seq drv.drvPath true)) newDrv ( + (extendDerivation (seq drv.drvPath true)) ( { meta = drv.meta or { }; - passthru = if drv ? passthru then drv.passthru else { }; + passthru = drv.passthru or { }; } // (drv.passthru or { }) - // optionalAttrs (drv ? __spliced) { - __spliced = { } // (mapAttrs (_: sDrv: overrideDerivation sDrv f) drv.__spliced); + // { + ${if drv ? __spliced then "__spliced" else null} = mapAttrs ( + _: sDrv: overrideDerivation sDrv f + ) drv.__spliced; } - ); + ) (derivation (drv.drvAttrs // (f drv))); /** `makeOverridable` takes a function from attribute set to attribute set and @@ -155,73 +154,67 @@ rec { let # Creates a functor with the same arguments as f mirrorArgs = mirrorFunctionArgs f; - # Recover overrider and additional attributes for f - # When f is a callable attribute set, - # it may contain its own `f.override` and additional attributes. - # This helper function recovers those attributes and decorate the overrider. - recoverMetadata = - if isAttrs f then - fDecorated: - # Preserve additional attributes for f - f - // fDecorated - # Decorate f.override if presented - // lib.optionalAttrs (f ? override) { - override = fdrv: makeOverridable (f.override fdrv); + + f' = + origArgs: + let + result = f origArgs; + + # Re-call the function but with different arguments + overrideArgs = mirrorArgs ( + /** + Change the arguments with which a certain function is called. + + In some cases, you may find a list of possible attributes to pass in this function's `__functionArgs` attribute, but it will not be complete for an original function like `args@{foo, ...}: ...`, which accepts arbitrary attributes. + + This function was provided by `lib.makeOverridable`. + */ + newArgs: makeOverridable f (origArgs // (if isFunction newArgs then newArgs origArgs else newArgs)) + ); + in + if isAttrs result then + result + // { + override = overrideArgs; + overrideDerivation = + fdrv: makeOverridable (mirrorArgs (args: overrideDerivation (f args) fdrv)) origArgs; + ${if result ? overrideAttrs then "overrideAttrs" else null} = + /** + Override the attributes that were passed to `mkDerivation` in order to generate this derivation. + + This function is provided by `lib.makeOverridable`, and indirectly by `callPackage` among others, in order to make the combination of `override` and `overrideAttrs` work. + Specifically, it re-adds the `override` attribute to the result of `overrideAttrs`. + + The real implementation of `overrideAttrs` is provided by `stdenv.mkDerivation`. + */ + # NOTE: part of the above documentation had to be duplicated in `mkDerivation`'s `overrideAttrs`. + # design/tech debt issue: https://github.com/NixOS/nixpkgs/issues/273815 + fdrv: makeOverridable (mirrorArgs (args: (f args).overrideAttrs fdrv)) origArgs; + } + else if isFunction result then + # Transform the result into a functor while propagating its arguments + setFunctionArgs result (functionArgs result) + // { + override = overrideArgs; } else - id; - decorate = f': recoverMetadata (mirrorArgs f'); + result; in - decorate ( - origArgs: - let - result = f origArgs; + # Recover overrider and additional attributes for f + # When f is a callable attribute set, + # it may contain its own `f.override` and additional attributes. + # This recovers those attributes and decorates the overrider. + if isAttrs f then + # Preserve additional attributes for f + f + // (mirrorArgs f') + # Decorate f.override if presented + // { + ${if f ? override then "override" else null} = fdrv: makeOverridable (f.override fdrv); + } - # Changes the original arguments with (potentially a function that returns) a set of new attributes - overrideWith = newArgs: origArgs // (if isFunction newArgs then newArgs origArgs else newArgs); - - # Re-call the function but with different arguments - overrideArgs = mirrorArgs ( - /** - Change the arguments with which a certain function is called. - - In some cases, you may find a list of possible attributes to pass in this function's `__functionArgs` attribute, but it will not be complete for an original function like `args@{foo, ...}: ...`, which accepts arbitrary attributes. - - This function was provided by `lib.makeOverridable`. - */ - newArgs: makeOverridable f (overrideWith newArgs) - ); - # Change the result of the function call by applying g to it - overrideResult = g: makeOverridable (mirrorArgs (args: g (f args))) origArgs; - in - if isAttrs result then - result - // { - override = overrideArgs; - overrideDerivation = fdrv: overrideResult (x: overrideDerivation x fdrv); - ${if result ? overrideAttrs then "overrideAttrs" else null} = - /** - Override the attributes that were passed to `mkDerivation` in order to generate this derivation. - - This function is provided by `lib.makeOverridable`, and indirectly by `callPackage` among others, in order to make the combination of `override` and `overrideAttrs` work. - Specifically, it re-adds the `override` attribute to the result of `overrideAttrs`. - - The real implementation of `overrideAttrs` is provided by `stdenv.mkDerivation`. - */ - # NOTE: part of the above documentation had to be duplicated in `mkDerivation`'s `overrideAttrs`. - # design/tech debt issue: https://github.com/NixOS/nixpkgs/issues/273815 - fdrv: overrideResult (x: x.overrideAttrs fdrv); - } - else if isFunction result then - # Transform the result into a functor while propagating its arguments - setFunctionArgs result (functionArgs result) - // { - override = overrideArgs; - } - else - result - ); + else + mirrorArgs f'; /** Call the package function in the file `fn` with the required @@ -272,6 +265,46 @@ rec { ``` */ callPackageWith = + let + makeErrorMessage = + autoArgs: fn: args: fargs: unpassedArgs: + let + # The first missing arg + arg = head ( + # Filter out the default args. We did a similar computation in the + # happy path, but we're okay recomputing it in an error case + filter (name: !fargs.${name}) (attrNames unpassedArgs) + ); + # Get a list of suggested argument names for a given missing one + getSuggestions = + arg: + pipe (autoArgs // args) [ + attrNames + # Only use ones that are at most 2 edits away. While mork would work, + # levenshteinAtMost is only fast for 2 or less. + (filter (levenshteinAtMost 2 arg)) + # Put strings with shorter distance first + (sortOn (levenshtein arg)) + # Only take the first couple results + (take 3) + # Quote all entries + (map (x: "\"" + x + "\"")) + ]; + + prettySuggestions = + suggestions: + if suggestions == [ ] then + "" + else if length suggestions == 1 then + ", did you mean ${elemAt suggestions 0}?" + else + ", did you mean ${concatStringsSep ", " (lib.init suggestions)} or ${lib.last suggestions}?"; + + loc = unsafeGetAttrPos arg fargs; + loc' = if loc != null then loc.file + ":" + toString loc.line else ""; + in + "lib.customisation.callPackageWith: Function called without required argument \"${arg}\" at ${loc'}${prettySuggestions (getSuggestions arg)}"; + in autoArgs: fn: args: let f = if isFunction fn then fn else import fn; @@ -281,62 +314,20 @@ rec { # This includes automatic ones and ones passed explicitly allArgs = intersectAttrs fargs autoArgs // args; - # a list of argument names that the function requires, but - # wouldn't be passed to it - missingArgs = - # Filter out arguments that have a default value - ( - filterAttrs (name: value: !value) - # Filter out arguments that would be passed - (removeAttrs fargs (attrNames allArgs)) - ); - - # Get a list of suggested argument names for a given missing one - getSuggestions = - arg: - pipe (autoArgs // args) [ - attrNames - # Only use ones that are at most 2 edits away. While mork would work, - # levenshteinAtMost is only fast for 2 or less. - (filter (levenshteinAtMost 2 arg)) - # Put strings with shorter distance first - (sortOn (levenshtein arg)) - # Only take the first couple results - (take 3) - # Quote all entries - (map (x: "\"" + x + "\"")) - ]; - - prettySuggestions = - suggestions: - if suggestions == [ ] then - "" - else if length suggestions == 1 then - ", did you mean ${elemAt suggestions 0}?" - else - ", did you mean ${concatStringsSep ", " (lib.init suggestions)} or ${lib.last suggestions}?"; - - errorForArg = - arg: - let - loc = unsafeGetAttrPos arg fargs; - loc' = if loc != null then loc.file + ":" + toString loc.line else ""; - in - "Function called without required argument \"${arg}\" at " - + "${loc'}${prettySuggestions (getSuggestions arg)}"; - - # Only show the error for the first missing argument - error = errorForArg (head (attrNames missingArgs)); + # arguments that weren't passed automatically to the function + unpassedArgs = removeAttrs fargs (attrNames allArgs); in - if missingArgs == { } then + # if nonempty, check if the function has defaults for those other args + if unpassedArgs == { } || all (value: value) (attrValues unpassedArgs) then makeOverridable f allArgs - # This needs to be an abort so it can't be caught with `builtins.tryEval`, - # which is used by nix-env and ofborg to filter out packages that don't evaluate. - # This way we're forced to fix such errors in Nixpkgs, - # which is especially relevant with allowAliases = false else - abort "lib.customisation.callPackageWith: ${error}"; + # Only show the error for the first missing argument + # This needs to be an abort so it can't be caught with `builtins.tryEval`, + # which is used by nix-env and ofborg to filter out packages that don't evaluate. + # This way we're forced to fix such errors in Nixpkgs, + # which is especially relevant with allowAliases = false + abort (makeErrorMessage autoArgs fn args fargs unpassedArgs); /** Like `callPackage`, but for a function that returns an attribute @@ -409,36 +400,28 @@ rec { extendDerivation = condition: passthru: drv: let - outputs = drv.outputs or [ "out" ]; - commonAttrs = drv // (listToAttrs outputsList) // { all = map (x: x.value) outputsList; } // passthru; - outputToAttrListElement = outputName: { + outputsList = map (outputName: { name = outputName; - value = - commonAttrs - // { - inherit (drv.${outputName}) type outputName; - outputSpecified = true; - drvPath = - assert condition; - drv.${outputName}.drvPath; - outPath = - assert condition; - drv.${outputName}.outPath; - } - // - # TODO: give the derivation control over the outputs. - # `overrideAttrs` may not be the only attribute that needs - # updating when switching outputs. - optionalAttrs (passthru ? overrideAttrs) { - # TODO: also add overrideAttrs when overrideAttrs is not custom, e.g. when not splicing. - overrideAttrs = f: (passthru.overrideAttrs f).${outputName}; - }; - }; - - outputsList = map outputToAttrListElement outputs; + value = commonAttrs // { + inherit (drv.${outputName}) type outputName; + outputSpecified = true; + drvPath = + assert condition; + drv.${outputName}.drvPath; + outPath = + assert condition; + drv.${outputName}.outPath; + # TODO: give the derivation control over the outputs. + # `overrideAttrs` may not be the only attribute that needs + # updating when switching outputs. + # TODO: also add overrideAttrs when overrideAttrs is not custom, e.g. when not splicing. + ${if passthru ? overrideAttrs then "overrideAttrs" else null} = + f: (passthru.overrideAttrs f).${outputName}; + }; + }) (drv.outputs or [ "out" ]); in commonAttrs // { diff --git a/lib/meta.nix b/lib/meta.nix index 3079f79f2f50..5697b915061c 100644 --- a/lib/meta.nix +++ b/lib/meta.nix @@ -367,7 +367,7 @@ rec { availableOn = platform: pkg: ((!pkg ? meta.platforms) || any (platformMatch platform) pkg.meta.platforms) - && all (elem: !platformMatch platform elem) (pkg.meta.badPlatforms or [ ]); + && ((!pkg ? meta.badPlatforms) || !(any (platformMatch platform) pkg.meta.badPlatforms)); /** Mapping of SPDX ID to the attributes in lib.licenses. diff --git a/maintainers/maintainer-list.nix b/maintainers/maintainer-list.nix index c7bca7115d77..616fcd213e92 100644 --- a/maintainers/maintainer-list.nix +++ b/maintainers/maintainer-list.nix @@ -145,6 +145,12 @@ githubId = 67933444; keys = [ { fingerprint = "B39E B98E 8860 DAFB 0567 0073 A614 B7D2 5134 987A"; } ]; }; + _0xferrous = { + email = "0xferrous@proton.me"; + github = "0xferrous"; + githubId = 213212767; + name = "0xferrous"; + }; _0xgsvs = { email = "venkat.subrahmanyam.34@gmail.com"; name = "0xgsvs"; diff --git a/nixos/lib/systemd-lib.nix b/nixos/lib/systemd-lib.nix index 13c529d53619..5c974f41dda5 100644 --- a/nixos/lib/systemd-lib.nix +++ b/nixos/lib/systemd-lib.nix @@ -67,7 +67,9 @@ rec { mkPathSafeName = replaceStrings [ "@" ":" "\\" "[" "]" ] [ "-" "-" "-" "" "" ]; # a type for options that take a unit name - unitNameType = types.strMatching "[a-zA-Z0-9@%:_.\\-]+[.](service|socket|device|mount|automount|swap|target|path|timer|scope|slice)"; + # note: redundantly escaping backslash in the bracket expression makes the regex + # slightly more portable even though POSIX doesn't require it. + unitNameType = types.strMatching "[a-zA-Z0-9@%:_.\\\\-]+[.](service|socket|device|mount|automount|swap|target|path|timer|scope|slice)"; makeUnit = name: unit: diff --git a/nixos/modules/profiles/base.nix b/nixos/modules/profiles/base.nix index fffc53c8e551..b7dd6477984e 100644 --- a/nixos/modules/profiles/base.nix +++ b/nixos/modules/profiles/base.nix @@ -53,6 +53,9 @@ # Include support for various filesystems and tools to create / manipulate them. boot.supportedFilesystems = lib.mkMerge [ [ + "ext2" + "ext3" + "ext4" "btrfs" "cifs" "f2fs" diff --git a/pkgs/applications/editors/vim/plugins/generated.nix b/pkgs/applications/editors/vim/plugins/generated.nix index 335435b85d9a..17a92f2c1640 100644 --- a/pkgs/applications/editors/vim/plugins/generated.nix +++ b/pkgs/applications/editors/vim/plugins/generated.nix @@ -15539,6 +15539,19 @@ final: prev: { meta.hydraPlatforms = [ ]; }; + run-nvim = buildVimPlugin { + pname = "run.nvim"; + version = "2.0.0"; + src = fetchgit { + url = "https://codeberg.org/ssnoer/run.nvim"; + tag = "v2.0.0"; + hash = "sha256-MTxhhcD6lHLJCfwaivKF9reeUrMog/8I2kJarNWz5Kk="; + }; + meta.homepage = "https://codeberg.org/ssnoer/run.nvim"; + meta.license = lib.licenses.unfree; + meta.hydraPlatforms = [ ]; + }; + runner-nvim = buildVimPlugin { pname = "runner-nvim"; version = "0-unstable-2026-02-11"; diff --git a/pkgs/applications/editors/vim/plugins/overrides.nix b/pkgs/applications/editors/vim/plugins/overrides.nix index 6a9830ab6808..4093605bc22a 100644 --- a/pkgs/applications/editors/vim/plugins/overrides.nix +++ b/pkgs/applications/editors/vim/plugins/overrides.nix @@ -3899,6 +3899,18 @@ assertNoAdditions { }; }); + run-nvim = super.run-nvim.overrideAttrs { + dependencies = [ + self.telescope-nvim + ]; + + checkInputs = [ + # Transitive depedency of telescope.nvim + # Issue: https://github.com/NixOS/nixpkgs/issues/394939 + self.plenary-nvim + ]; + }; + rust-tools-nvim = super.rust-tools-nvim.overrideAttrs { dependencies = [ self.nvim-lspconfig ]; }; diff --git a/pkgs/applications/editors/vim/plugins/vim-plugin-names b/pkgs/applications/editors/vim/plugins/vim-plugin-names index e13118523ecf..312dbb311486 100644 --- a/pkgs/applications/editors/vim/plugins/vim-plugin-names +++ b/pkgs/applications/editors/vim/plugins/vim-plugin-names @@ -1108,6 +1108,7 @@ https://github.com/rose-pine/neovim/,main,rose-pine https://github.com/seblyng/roslyn.nvim/,, https://github.com/keith/rspec.vim/,, https://github.com/ccarpita/rtorrent-syntax-file/,, +https://codeberg.org/ssnoer/run.nvim,, https://github.com/TheLazyCat00/runner-nvim/,, https://github.com/simrat39/rust-tools.nvim/,, https://github.com/rust-lang/rust.vim/,, diff --git a/pkgs/by-name/ab/abcmidi/package.nix b/pkgs/by-name/ab/abcmidi/package.nix index 6d5dd308d444..326184e817ec 100644 --- a/pkgs/by-name/ab/abcmidi/package.nix +++ b/pkgs/by-name/ab/abcmidi/package.nix @@ -6,13 +6,13 @@ stdenv.mkDerivation (finalAttrs: { pname = "abcmidi"; - version = "2026.02.24"; + version = "2026.04.26"; src = fetchFromGitHub { owner = "sshlien"; repo = "abcmidi"; tag = finalAttrs.version; - hash = "sha256-Hy0ICuMK4pCaJn/36QwkCfEI5kgmkWyr9V4RhMpGQes="; + hash = "sha256-d3mzAMFohBppduP25FUWmmQFFCo5lnP5LFLcoVFwjn0="; }; # TODO: remove once https://github.com/sshlien/abcmidi/pull/15 merged diff --git a/pkgs/by-name/az/azure-cli/extensions-manual.nix b/pkgs/by-name/az/azure-cli/extensions-manual.nix index aa55f0912bf6..f5a5a332784b 100644 --- a/pkgs/by-name/az/azure-cli/extensions-manual.nix +++ b/pkgs/by-name/az/azure-cli/extensions-manual.nix @@ -192,7 +192,7 @@ chmod +x $out/${python3.sitePackages}/azext_confcom/bin/genpolicy-linux ''; meta = { - maintainers = with lib.maintainers; [ miampf ]; + maintainers = [ ]; platforms = lib.platforms.linux; # confcom is linux only }; }; diff --git a/pkgs/by-name/bi/bitwarden-desktop/package.nix b/pkgs/by-name/bi/bitwarden-desktop/package.nix index 926bfdde293d..1409c8e06c67 100644 --- a/pkgs/by-name/bi/bitwarden-desktop/package.nix +++ b/pkgs/by-name/bi/bitwarden-desktop/package.nix @@ -134,7 +134,7 @@ buildNpmPackage' rec { patchShebangs apps/desktop/node_modules pushd apps/desktop/desktop_native/napi - npm run build + npm run build -- --release popd pushd apps/desktop/desktop_native/proxy diff --git a/pkgs/by-name/bu/bun/package.nix b/pkgs/by-name/bu/bun/package.nix index fc5b4064c6e3..928ec621b10e 100644 --- a/pkgs/by-name/bu/bun/package.nix +++ b/pkgs/by-name/bu/bun/package.nix @@ -17,7 +17,7 @@ }: stdenvNoCC.mkDerivation (finalAttrs: { - version = "1.3.11"; + version = "1.3.13"; pname = "bun"; src = @@ -81,19 +81,19 @@ stdenvNoCC.mkDerivation (finalAttrs: { sources = { "aarch64-darwin" = fetchurl { url = "https://github.com/oven-sh/bun/releases/download/bun-v${finalAttrs.version}/bun-darwin-aarch64.zip"; - hash = "sha256-b1o0Z+2crsR5W/eM1HZQfZ+HDH1XuGyUX8szgSZ3L/w="; + hash = "sha256-VGfj9l26Umuf6pjwzOBO+vwMY+Fpcz7Ce4dqOtMtoZA="; }; "aarch64-linux" = fetchurl { url = "https://github.com/oven-sh/bun/releases/download/bun-v${finalAttrs.version}/bun-linux-aarch64.zip"; - hash = "sha256-0TlE2hKlPsx0v2pyC9HQTEVVwDjf5CI2U1anvkdpH98="; + hash = "sha256-cLrkGzkIsKEg4eWMXIrzDnSvrjuNEbDT/djnh937SyI="; }; "x86_64-darwin" = fetchurl { url = "https://github.com/oven-sh/bun/releases/download/bun-v${finalAttrs.version}/bun-darwin-x64-baseline.zip"; - hash = "sha256-+2c5sIv1RVDtqnyCTNWy3KRbagav70CEQwh6YxBfb40="; + hash = "sha256-qYumpIDyL9qbNDYmuQak4mqlNhi/hdK8WSjs8rpF8O0="; }; "x86_64-linux" = fetchurl { url = "https://github.com/oven-sh/bun/releases/download/bun-v${finalAttrs.version}/bun-linux-x64.zip"; - hash = "sha256-hhG6k1r4hvBabzh0ChUWAybBXl1dB63vlmEwtEk2B+0="; + hash = "sha256-ecB3H6i5LDOq5B4VoODTB+qZ0OLwAxfHHGxTI3p44lo="; }; }; updateScript = writeShellScript "update-bun" '' diff --git a/pkgs/by-name/c2/c2patool/package.nix b/pkgs/by-name/c2/c2patool/package.nix index 9c9ac59711a5..185dc7932140 100644 --- a/pkgs/by-name/c2/c2patool/package.nix +++ b/pkgs/by-name/c2/c2patool/package.nix @@ -10,16 +10,16 @@ rustPlatform.buildRustPackage (finalAttrs: { pname = "c2patool"; - version = "0.26.50"; + version = "0.26.55"; src = fetchFromGitHub { owner = "contentauth"; repo = "c2pa-rs"; tag = "c2patool-v${finalAttrs.version}"; - hash = "sha256-4I+q+6gz+xNz+lhxyC14hZ8yyYG4qzT8TtkLxl8Y71g="; + hash = "sha256-QsBS5J35R4/e6JzuurPo0WzHfDunu7mkdrBFLlY165g="; }; - cargoHash = "sha256-Fp+EuxrPx817wjzzq8+f6vBzBe5vyhkXGRsaEqTa/Jo="; + cargoHash = "sha256-3rRSFHtQVzXeK+k+A5XW+cMvrxamkxDy57PO6SG6E8E="; # use the non-vendored openssl env.OPENSSL_NO_VENDOR = 1; diff --git a/pkgs/by-name/co/codex-acp/hashes.json b/pkgs/by-name/co/codex-acp/hashes.json deleted file mode 100644 index c816627693e9..000000000000 --- a/pkgs/by-name/co/codex-acp/hashes.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "version": "0.9.4", - "hash": "sha256-sVmy7t1+z88WmYuupVmUA3GYA2kkv3nY7Z3Ic99f5UY=", - "cargoHash": "sha256-Ik6pewc6f+cmVKiqVj1g0h7cIxLhE6xOd9p/ySo/EPg=", - "codexRev": "c34b30a3c128bb75fcec27ef838c93c99b92fc61", - "codexSrcHash": "sha256-SnJHiecKNCHhkiMpbsEwpUarpKLpxn1JOHLHy2vgRog=", - "nodeVersionHash": "sha256-q/bOpgF6/0K3MDKXAC+bi1Rb/vCHNhKZpNDbhyYH+oc=" -} diff --git a/pkgs/by-name/co/codex-acp/librusty_v8.nix b/pkgs/by-name/co/codex-acp/librusty_v8.nix new file mode 100644 index 000000000000..c2f00c5fe62e --- /dev/null +++ b/pkgs/by-name/co/codex-acp/librusty_v8.nix @@ -0,0 +1,24 @@ +# auto-generated file -- DO NOT EDIT! +{ + lib, + stdenv, + fetchurl, +}: + +fetchurl { + name = "librusty_v8-146.4.0"; + url = "https://github.com/denoland/rusty_v8/releases/download/v146.4.0/librusty_v8_release_${stdenv.hostPlatform.rust.rustcTarget}.a.gz"; + hash = + { + x86_64-linux = "sha256-5ktNmeSuKTouhGJEqJuAF4uhA4LBP7WRwfppaPUpEVM="; + aarch64-linux = "sha256-2/FlsHyBvbBUvARrQ9I+afz3vMGkwbW0d2mDpxBi7Ng="; + x86_64-darwin = "sha256-YwzSQPG77NsHFBfcGDh6uBz2fFScHFFaC0/Pnrpke7c="; + aarch64-darwin = "sha256-v+LJvjKlbChUbw+WWCXuaPv2BkBfMQzE4XtEilaM+Yo="; + } + .${stdenv.hostPlatform.system} + or (throw "librusty_v8 146.4.0 is not available for ${stdenv.hostPlatform.system}"); + meta = { + version = "146.4.0"; + sourceProvenance = with lib.sourceTypes; [ binaryNativeCode ]; + }; +} diff --git a/pkgs/by-name/co/codex-acp/package.nix b/pkgs/by-name/co/codex-acp/package.nix index 7d2b617c86f9..04b17ef411ac 100644 --- a/pkgs/by-name/co/codex-acp/package.nix +++ b/pkgs/by-name/co/codex-acp/package.nix @@ -1,60 +1,50 @@ { lib, stdenv, + callPackage, fetchFromGitHub, - fetchurl, rustPlatform, pkg-config, openssl, libcap, + bubblewrap, + librusty_v8 ? callPackage ./librusty_v8.nix { }, }: let - versionData = builtins.fromJSON (builtins.readFile ./hashes.json); - inherit (versionData) - version - hash - cargoHash - codexRev - codexSrcHash - nodeVersionHash - ; - - # codex-core uses include_str!("../../../../node-version.txt"), so we need - # to place node-version.txt at the vendored workspace root. - nodeVersionFile = fetchurl { - url = "https://raw.githubusercontent.com/zed-industries/codex/${codexRev}/codex-rs/node-version.txt"; - hash = nodeVersionHash; - }; - - # codex-linux-sandbox compiles a patched bubblewrap source tree from - # codex-rs/vendor/bubblewrap. Cargo vendoring flattens workspace layout, - # so this directory must be provided explicitly. + # codex-acp 0.12.0 pins openai/codex rust-v0.124.0 in Cargo.lock. + codexRev = "e9fb49366c93a1478ec71cc41ecee415a197d036"; + codexHash = "sha256-YFnzzwCm9/b30qLDMbkf/rEizuTjeqdCgoBZeS0wNBo="; codexSrc = fetchFromGitHub { - owner = "zed-industries"; + owner = "openai"; repo = "codex"; rev = codexRev; - hash = codexSrcHash; + hash = codexHash; }; in -rustPlatform.buildRustPackage { +rustPlatform.buildRustPackage (finalAttrs: { pname = "codex-acp"; - inherit version; + version = "0.12.0"; src = fetchFromGitHub { owner = "zed-industries"; repo = "codex-acp"; - rev = "v${version}"; - inherit hash; + tag = "v${finalAttrs.version}"; + hash = "sha256-qPqg95FpXHBtyHBJtrfJUwu9GokfmOJgKgqLKQ48u+8="; }; - inherit cargoHash; + cargoHash = "sha256-/BZ82qiTy/mPwhf5v5CFrNSB6AxCRFdmHB72L0+KjJw="; - preBuild = '' - cp ${nodeVersionFile} "$NIX_BUILD_TOP/codex-acp-${version}-vendor/node-version.txt" + # fetchCargoVendor only keeps the individual git crate subtrees, so restore + # the workspace-root file that codex-core includes via ../../../../node-version.txt. + postPatch = '' + cp ${codexSrc}/codex-rs/node-version.txt "$cargoDepsCopy/source-git-0/node-version.txt" ''; - env = lib.optionalAttrs stdenv.hostPlatform.isLinux { - CODEX_BWRAP_SOURCE_DIR = "${codexSrc}/codex-rs/vendor/bubblewrap"; + env = { + RUSTY_V8_ARCHIVE = librusty_v8; + } + // lib.optionalAttrs stdenv.hostPlatform.isLinux { + CODEX_BWRAP_SOURCE_DIR = "${bubblewrap.src}"; }; nativeBuildInputs = [ @@ -70,16 +60,16 @@ rustPlatform.buildRustPackage { doCheck = false; - passthru.updateScript = ./update.py; + passthru.updateScript = ./update.sh; meta = { description = "An ACP-compatible coding agent powered by Codex"; homepage = "https://github.com/zed-industries/codex-acp"; - changelog = "https://github.com/zed-industries/codex-acp/releases/tag/v${version}"; + changelog = "https://github.com/zed-industries/codex-acp/releases/tag/v${finalAttrs.version}"; license = lib.licenses.asl20; maintainers = with lib.maintainers; [ tlvince ]; platforms = lib.platforms.unix; sourceProvenance = with lib.sourceTypes; [ fromSource ]; mainProgram = "codex-acp"; }; -} +}) diff --git a/pkgs/by-name/co/codex-acp/update.py b/pkgs/by-name/co/codex-acp/update.py deleted file mode 100755 index 38ef25c5ab45..000000000000 --- a/pkgs/by-name/co/codex-acp/update.py +++ /dev/null @@ -1,216 +0,0 @@ -#!/usr/bin/env nix-shell -#!nix-shell -I nixpkgs=./. -i python3 -p python3 nix cacert - -"""Update script for codex-acp package. - -codex-acp depends on crates from zed-industries/codex via a git dependency. -To keep the Nix expression up to date, we need to: -- update codex-acp source hash, -- extract the pinned codex git revision from Cargo.lock, -- refresh node-version.txt hash for that codex revision, -- refresh codex source hash for vendored bubblewrap on Linux, -- recompute cargoHash. -""" - -from __future__ import annotations - -import json -import os -import re -import subprocess -import tarfile -import tempfile -import urllib.request -from pathlib import Path - -SCRIPT_DIR = Path(__file__).resolve().parent -NIXPKGS_ROOT = SCRIPT_DIR.parents[4] -HASHES_FILE = SCRIPT_DIR / "hashes.json" - -OWNER = "zed-industries" -REPO = "codex-acp" -DUMMY_CARGO_HASH = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=" -ANSI_ESCAPE_RE = re.compile(r"\x1b\[[0-9;]*m") - - -def run(cmd: list[str], cwd: Path | None = None) -> str: - result = subprocess.run( - cmd, - cwd=str(cwd) if cwd else None, - check=False, - capture_output=True, - text=True, - ) - if result.returncode != 0: - output = result.stderr.strip() or result.stdout.strip() - msg = f"Command failed ({result.returncode}): {' '.join(cmd)}" - if output: - msg = f"{msg}\n{output}" - raise RuntimeError(msg) - return result.stdout.strip() - - -def github_request(url: str) -> dict: - headers = { - "Accept": "application/vnd.github+json", - } - token = os.environ.get("GITHUB_TOKEN") - if token: - headers["Authorization"] = f"Bearer {token}" - - req = urllib.request.Request(url, headers=headers) - with urllib.request.urlopen(req) as response: - return json.loads(response.read().decode("utf-8")) - - -def fetch_latest_release(owner: str, repo: str) -> str: - data = github_request(f"https://api.github.com/repos/{owner}/{repo}/releases/latest") - tag_name = data["tag_name"] - return tag_name[1:] if tag_name.startswith("v") else tag_name - - -def version_key(version: str) -> tuple[int, ...]: - parts = re.findall(r"\d+", version) - return tuple(int(part) for part in parts) - - -def should_update(current: str, latest: str) -> bool: - return version_key(latest) > version_key(current) - - -def load_hashes(path: Path) -> dict[str, str]: - with path.open() as f: - return json.load(f) - - -def save_hashes(path: Path, data: dict[str, str]) -> None: - with path.open("w") as f: - json.dump(data, f, indent=2) - f.write("\n") - - -def prefetch_sri(url: str, *, unpack: bool = False) -> str: - cmd = ["nix-prefetch-url", "--type", "sha256"] - if unpack: - cmd.append("--unpack") - cmd.append(url) - - raw_hash = run(cmd, cwd=NIXPKGS_ROOT) - return run( - [ - "nix", - "--extra-experimental-features", - "nix-command", - "hash", - "to-sri", - "--type", - "sha256", - raw_hash, - ], - cwd=NIXPKGS_ROOT, - ) - - -def extract_codex_rev_from_tarball(tag: str) -> str: - """Extract zed-industries/codex git revision from codex-acp Cargo.lock.""" - url = f"https://github.com/{OWNER}/{REPO}/archive/refs/tags/{tag}.tar.gz" - - with tempfile.TemporaryDirectory() as tmpdir: - tarball_path = Path(tmpdir) / "source.tar.gz" - urllib.request.urlretrieve(url, tarball_path) - - with tarfile.open(tarball_path, "r:gz") as tar: - for member in tar.getmembers(): - if not member.name.endswith("Cargo.lock"): - continue - cargo_lock = tar.extractfile(member) - if cargo_lock is None: - continue - - content = cargo_lock.read().decode("utf-8") - match = re.search(r"zed-industries/codex\?branch=acp#([a-f0-9]+)", content) - if match: - return match.group(1) - - raise RuntimeError("Could not extract codex git revision from Cargo.lock") - - -def calculate_dependency_hash(attr_path: str) -> str: - result = subprocess.run( - ["nix-build", "--no-out-link", "-A", attr_path], - cwd=str(NIXPKGS_ROOT), - check=False, - capture_output=True, - text=True, - ) - output = ANSI_ESCAPE_RE.sub("", f"{result.stdout}\n{result.stderr}") - - match = re.search(r"got:\s*(sha256-[A-Za-z0-9+/=]+)", output) - if match: - return match.group(1) - - if result.returncode == 0: - raise RuntimeError("nix-build unexpectedly succeeded with placeholder cargoHash") - - raise RuntimeError("Failed to parse cargoHash from nix-build output") - - -def main() -> None: - data = load_hashes(HASHES_FILE) - current = data["version"] - latest = fetch_latest_release(OWNER, REPO) - - print(f"Current: {current}, Latest: {latest}") - - if not should_update(current, latest): - print("Already up to date") - return - - tag = f"v{latest}" - print(f"Updating codex-acp to {latest}...") - - source_url = f"https://github.com/{OWNER}/{REPO}/archive/refs/tags/{tag}.tar.gz" - print("Calculating source hash...") - source_hash = prefetch_sri(source_url, unpack=True) - print(f" hash: {source_hash}") - - print("Extracting codex git revision from Cargo.lock...") - codex_rev = extract_codex_rev_from_tarball(tag) - print(f" codexRev: {codex_rev}") - - codex_src_url = f"https://github.com/zed-industries/codex/archive/{codex_rev}.tar.gz" - print("Calculating codex source hash...") - codex_src_hash = prefetch_sri(codex_src_url, unpack=True) - print(f" codexSrcHash: {codex_src_hash}") - - node_version_url = ( - f"https://raw.githubusercontent.com/zed-industries/codex/{codex_rev}/" - "codex-rs/node-version.txt" - ) - print("Calculating node-version.txt hash...") - node_version_hash = prefetch_sri(node_version_url, unpack=False) - print(f" nodeVersionHash: {node_version_hash}") - - data = { - "version": latest, - "hash": source_hash, - "cargoHash": DUMMY_CARGO_HASH, - "codexRev": codex_rev, - "codexSrcHash": codex_src_hash, - "nodeVersionHash": node_version_hash, - } - save_hashes(HASHES_FILE, data) - - print("Calculating cargoHash...") - attr_path = os.environ.get("UPDATE_NIX_ATTR_PATH", "codex-acp") - cargo_hash = calculate_dependency_hash(attr_path) - print(f" cargoHash: {cargo_hash}") - - data["cargoHash"] = cargo_hash - save_hashes(HASHES_FILE, data) - - print(f"Updated to {latest}") - - -if __name__ == "__main__": - main() diff --git a/pkgs/by-name/co/codex-acp/update.sh b/pkgs/by-name/co/codex-acp/update.sh new file mode 100755 index 000000000000..401c252abe13 --- /dev/null +++ b/pkgs/by-name/co/codex-acp/update.sh @@ -0,0 +1,198 @@ +#!/usr/bin/env nix-shell +#!nix-shell -i bash -p bash cacert common-updater-scripts coreutils curl gnutar jq nix-update + +set -euo pipefail + +PACKAGE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +NIXPKGS_ROOT="$(realpath "$PACKAGE_DIR/../../../..")" +PACKAGE_NIX="$PACKAGE_DIR/package.nix" +LIBRUSTY_V8_NIX="$PACKAGE_DIR/librusty_v8.nix" +ATTR_PATH=codex-acp +OWNER="zed-industries" +REPO="codex-acp" + +github_api_get() { + local url="$1" + local curl_args=( + --fail + --silent + --show-error + -H "Accept: application/vnd.github+json" + ) + + if [[ -n "${GITHUB_TOKEN:-}" ]]; then + curl_args+=(-H "Authorization: Bearer ${GITHUB_TOKEN}") + fi + + curl "${curl_args[@]}" "$url" +} + +normalize_version() { + local version="$1" + echo "${version#v}" +} + +prefetch_sri() { + local url="$1" + local unpack="${2:-false}" + local raw_hash + local args=(--type sha256) + + if [[ "$unpack" == "true" ]]; then + args+=(--unpack) + fi + + raw_hash="$(nix-prefetch-url "${args[@]}" "$url")" + nix hash convert --to sri --hash-algo sha256 "$raw_hash" +} + +parse_release_metadata() { + local cargo_lock="$1" + local codex_metadata codex_tag codex_rev v8_version + + codex_metadata="$( + sed -nE 's|.*git\+https://github\.com/openai/codex\?tag=([^#"]+)#([0-9a-f]+).*|\1 \2|p' "$cargo_lock" \ + | head -n1 + )" + if [[ -z "$codex_metadata" ]]; then + echo "Could not find pinned openai/codex dependency in Cargo.lock" >&2 + return 1 + fi + read -r codex_tag codex_rev <<<"$codex_metadata" + if [[ -z "$codex_tag" || -z "$codex_rev" ]]; then + echo "Could not parse pinned openai/codex dependency in Cargo.lock" >&2 + return 1 + fi + + v8_version="$( + awk ' + /^\[\[package\]\]$/ { in_pkg = 1; is_v8 = 0; next } + in_pkg && /^name = "v8"$/ { is_v8 = 1; next } + in_pkg && is_v8 && /^version = "/ { + gsub(/^version = "/, "") + gsub(/"$/, "") + print + exit + } + ' "$cargo_lock" + )" + if [[ -z "$v8_version" ]]; then + echo "Could not find v8 package version in Cargo.lock" >&2 + return 1 + fi + + printf '%s\n%s\n%s\n' "$codex_tag" "$codex_rev" "$v8_version" +} + +update_codex_pins() { + local tmp + tmp="$(mktemp)" + + awk -v codex_rev="$CODEX_REV" -v codex_hash="$CODEX_HASH" ' + /codexRev = "[0-9a-f]+";/ { + rev_count++ + sub(/codexRev = "[0-9a-f]+";/, "codexRev = \"" codex_rev "\";") + } + /codexHash = "sha256-[^"]+";/ { + hash_count++ + sub(/codexHash = "sha256-[^"]+";/, "codexHash = \"" codex_hash "\";") + } + { print } + END { + if (rev_count != 1) { + print "Failed to update codexRev in package.nix" > "/dev/stderr" + exit 1 + } + if (hash_count != 1) { + print "Failed to update codexHash in package.nix" > "/dev/stderr" + exit 1 + } + } + ' "$PACKAGE_NIX" >"$tmp" + + mv "$tmp" "$PACKAGE_NIX" +} + +write_librusty_v8_nix() { + cat >"$LIBRUSTY_V8_NIX" <