Add nix 2.31 support

DzmingLi
Feb 18, 2026, 2:28 PM
QA5XRI3RVPCTT2JJIKIGMUF5JKMQGGWCAU4CN7676O72C5BVWY6QC

Dependencies

  • [2] MJEMOITM Fix record in flake test
  • [3] YCBIN3NH Update nixpkgs
  • [4] UYCSZQO6 README.md: Add section about source archives
  • [5] G2QYHQFB README.md: Make nixpkgs the primary way to get the package
  • [6] EXXP5DBS Build system support for Lix
  • [7] NXYGNBPO Compiles with Lix (untested)
  • [8] PDUL2QU3 Add nixfeat.h
  • [9] XG7SZQ5V Build package with unstable Nix by default
  • [10] N2RTQC4P Build with Meson instead of CMake
  • [11] RPUKW357 Fix build for Nix 2.23
  • [12] YW5FM2MI Put code for new Nix versions at the top in if/else macros
  • [13] DYNXZQZV Uncouple some of the logic from Nix library and add basic tests
  • [14] GCOWWL5G Crusty debug header
  • [15] U5AKEHEQ Fix build for Nix 2.19 to 2.21
  • [16] 3KEFKH5F Import existing code
  • [17] 6PXIKDCN Add note about runtime dependency on Pijul
  • [18] GIEUXXMH Initial commit
  • [19] NQT3HEZH Add README.md
  • [20] 7YS2X7JJ Fix compilation against older Nix versions (tested with 2.13.6)
  • [21] BBPDFO4L Add check to make sure plugin works
  • [22] HZA67MNO Fix build for Nix 2.24
  • [23] ALEHIM7Q Fix plugin path in readme
  • [24] R7SYZNQF Check multiple Nix versions
  • [25] SNHMHWHL Add reference to nix-extras package
  • [26] 2NVQXNBS Update nixpkgs and remove broken/unsupported Nix versions
  • [27] XGCRPWKL Move repo interaction into separate source file
  • [28] 65LJ73XH Fix build with Nix 2.22
  • [29] ABMNOOZ7 nix.settings instead of nix.options
  • [30] WUA27ICQ Add notes about Nix patch and using compatible Nix version
  • [31] KEPVL66D Partially fix build on Mac
  • [32] H5RKFV7Y Don't directly execute Pijul from fetcher

Change contents

  • edit in src/nixfeat.h at line 3
    [8.105][8.105:377]()
    #ifdef NIX_IS_CPPNIX
    #if NIX_VERSION >= 0x021800
    #define NIX_INPUTFROMURL_HAS_REQUIRETREE_PARAM
    #endif
    #if NIX_VERSION >= 0x021900
    #define NIX_HAS_PROCESSES_H
    #define NIX_INPUTSCHEME_EXTERNAL_URI_CHECKS
    #define NIX_GETSOURCEPATH_IS_CONST
    #define NIX_HAS_PUTFILE
    #endif
  • replacement in src/nixfeat.h at line 4
    [8.378][8.378:527]()
    #if NIX_VERSION >= 0x022000
    #define NIX_HAS_POSIX_SOURCE_ACCESSOR_H
    #define NIX_STORE_PARAM_IS_STORE_REF
    #define NIX_POSIX_SOURCE_ACCESSOR_V1
    #endif
    [8.378]
    [8.527]
    // Feature detection removed - targeting Nix 2.31 only
  • edit in src/nixfeat.h at line 6
    [8.528][8.528:759]()
    #if NIX_VERSION >= 0x022100
    #define NIX_HAS_FS_INPUT_ACCESSOR_H
    #define NIX_INPUTSCHEME_EXTERNAL_LOCKED_CHECKS
    #define NIX_POSIX_SOURCE_ACCESSOR_V2
    #define NIX_CANONPATH_HAS_SLASH_OP
    #else
    #define NIX_INPUTSCHEME_HAS_PRIVATE_FETCH
  • edit in src/nixfeat.h at line 7
    [8.766][8.766:1126](),[8.1126][8.1126:1311]()
    #if NIX_VERSION >= 0x022200
    #define NIX_HAS_LOOKUPPATH
    #endif
    #if NIX_VERSION >= 0x022300
    #define NIX_HAS_STORE_PATH_ACCESSOR_H
    #define NIX_INPUTSCHEME_USES_SOURCE_ACCESSOR
    #define NIX_HAS_CACHE_KEY_TYPE
    #define NIX_POSIX_SOURCE_ACCESSOR_V3
    #endif
    #if NIX_VERSION >= 0x022400
    #define NIX_INPUTFROMURL_HAS_SETTINGS_PARAM
    #define NIX_POSIX_SOURCE_ACCESSOR_V4
    #endif
    #endif
    #ifdef NIX_IS_LIX
    #define NIX_INPUTFROMURL_HAS_REQUIRETREE_PARAM
    #define NIX_HAS_PROCESSES_H
    #define NIX_GETSOURCEPATH_IS_CONST
    #define NIX_HAS_PUTFILE
    #endif
    #endif
  • edit in src/meson.build at line 10
    [9.245][9.245:362]()
    if nix_main_dep.version().version_compare('<=2.22')
    lib_extra_cppflags += ['-DHAVE_STRUCT_DIRENT_D_TYPE']
    endif
  • replacement in src/meson.build at line 23
    [9.660][9.660:775]()
    f'-DNIX_VERSION=(((0x@nix_major_version@)<<16) | ((0x@nix_minor_version@)<<8) | (0x@nix_patch_version@))',
    [9.660]
    [6.27]
    f'-DNIX_VERSION=(((@nix_major_version@)<<16) | ((@nix_minor_version@)<<8) | (@nix_patch_version@))',
  • edit in src/fetcher.cpp at line 3
    [9.2275][7.0:21]()
    #include "nixfeat.h"
  • replacement in src/fetcher.cpp at line 8
    [9.73][9.73:169](),[9.60][9.169:170](),[9.169][9.169:170](),[9.170][7.22:61](),[7.61][9.89:133](),[9.89][9.89:133](),[9.133][7.62:99](),[7.99][9.28:62](),[9.28][9.28:62](),[9.62][7.100:143](),[9.92][9.161:200](),[7.143][9.161:200](),[9.161][9.161:200]()
    #include <cache.hh>
    #include <fetch-settings.hh>
    #include <fetchers.hh>
    #include <store-api.hh>
    #ifdef NIX_HAS_POSIX_SOURCE_ACCESSOR_H
    #include <posix-source-accessor.hh>
    #endif
    #ifdef NIX_HAS_STORE_PATH_ACCESSOR_H
    #include <store-path-accessor.hh>
    #elif defined(NIX_HAS_FS_INPUT_ACCESSOR_H)
    #include <fs-input-accessor.hh>
    #endif
    [9.73]
    [9.200]
    #include <nix/fetchers/cache.hh>
    #include <nix/fetchers/fetch-settings.hh>
    #include <nix/fetchers/fetchers.hh>
    #include <nix/fetchers/store-path-accessor.hh>
    #include <nix/store/store-api.hh>
    #include <nix/util/posix-source-accessor.hh>
  • edit in src/fetcher.cpp at line 32
    [9.956][7.144:193]()
    #if defined(NIX_INPUTFROMURL_HAS_SETTINGS_PARAM)
  • edit in src/fetcher.cpp at line 33
    [9.163][7.194:248](),[9.193][9.28:141](),[7.248][9.28:141](),[9.28][9.28:141](),[9.141][9.64:153](),[9.64][9.64:153](),[9.1063][9.160:167]()
    #elif defined(NIX_INPUTFROMURL_HAS_REQUIRETREE_PARAM)
    [[nodiscard]] std::optional<Input> inputFromURL(const ParsedURL &url, bool requireTree) const override
    #else
    [[nodiscard]] std::optional<Input> inputFromURL(const ParsedURL &url) const override
    #endif
  • edit in src/fetcher.cpp at line 57
    [9.1702][7.249:298]()
    #if defined(NIX_INPUTFROMURL_HAS_SETTINGS_PARAM)
  • edit in src/fetcher.cpp at line 58
    [9.270][9.270:276](),[9.276][9.1702:1740](),[9.1702][9.1702:1740](),[9.1740][9.277:284]()
    #else
    return inputFromAttrs(attrs);
    #endif
  • edit in src/fetcher.cpp at line 62
    [9.1747][7.299:348]()
    #if defined(NIX_INPUTFROMURL_HAS_SETTINGS_PARAM)
  • edit in src/fetcher.cpp at line 63
    [9.428][9.428:434](),[9.434][9.1747:1836](),[9.1747][9.1747:1836](),[9.1836][9.435:442]()
    #else
    [[nodiscard]] std::optional<Input> inputFromAttrs(const Attrs &attrs) const override
    #endif
  • edit in src/fetcher.cpp at line 68
    [9.1922][9.1922:1933](),[9.1933][7.349:393](),[9.229][9.1933:2221](),[7.393][9.1933:2221](),[9.1933][9.1933:2221]()
    }
    #ifndef NIX_INPUTSCHEME_EXTERNAL_URI_CHECKS
    for (const auto &[name, _] : attrs) {
    if (name != "type"sv && name != "url"sv && name != "channel"sv && name != "state"sv && name != "narHash"sv && name != "lastModified"sv) {
    throw Error("unsupported Pijul input attribute '%s'"s, name);
    }
  • edit in src/fetcher.cpp at line 69
    [9.2231][9.230:237]()
    #endif
  • edit in src/fetcher.cpp at line 72
    [9.2277][7.394:443]()
    #if defined(NIX_INPUTFROMURL_HAS_SETTINGS_PARAM)
  • edit in src/fetcher.cpp at line 73
    [9.502][9.502:508](),[9.508][9.2277:2298](),[9.2277][9.2277:2298](),[9.2298][9.509:516]()
    #else
    Input input;
    #endif
  • edit in src/fetcher.cpp at line 75
    [9.2328][7.444:491](),[9.265][9.2328:2467](),[7.491][9.2328:2467](),[9.2328][9.2328:2467](),[9.2467][9.266:273](),[9.273][9.2467:2468](),[9.2467][9.2467:2468]()
    #ifndef NIX_INPUTSCHEME_EXTERNAL_LOCKED_CHECKS
    if (maybeGetStrAttr(input.attrs, "channel") && maybeGetStrAttr(input.attrs, "state")) {
    input.locked = true;
    }
    #endif
  • edit in src/fetcher.cpp at line 80
    [9.2497][7.492:536](),[9.301][9.2497:2651](),[7.536][9.2497:2651](),[9.2497][9.2497:2651](),[9.2651][9.302:309](),[9.309][9.2651:2652](),[9.2651][9.2651:2652]()
    #ifndef NIX_INPUTSCHEME_EXTERNAL_URI_CHECKS
    [[nodiscard]] bool hasAllInfo(const Input &input) const override
    {
    return maybeGetIntAttr(input.attrs, "lastModified").has_value();
    }
    #endif
  • replacement in src/fetcher.cpp at line 103
    [9.3215][7.537:578](),[7.578][9.338:434](),[9.338][9.338:434](),[9.434][9.3215:3301](),[9.3215][9.3215:3301](),[9.3301][9.435:442]()
    #ifdef NIX_INPUTSCHEME_HAS_PRIVATE_FETCH
    std::pair<StorePath, Input> fetchToStore(ref<Store> store, const Input &_input) const
    #else
    std::pair<StorePath, Input> fetch(ref<Store> store, const Input &_input) override
    #endif
    [9.3215]
    [9.3301]
    std::optional<std::filesystem::path> getSourcePath(const Input &input) const override
  • edit in src/fetcher.cpp at line 107
    [9.153][9.3307:3655](),[9.3307][9.3307:3655](),[9.3655][9.154:171](),[9.171][9.3655:3661](),[9.3655][9.3655:3661](),[9.3661][9.3661:3662](),[9.3662][7.579:613](),[7.613][9.471:550](),[9.471][9.471:550](),[9.550][9.3662:3729](),[9.3662][9.3662:3729](),[9.3729][9.551:558](),[9.558][9.3729:3735](),[9.3729][9.3729:3735](),[9.3735][9.172:191]()
    if (auto localPath = getSourcePath(_input)) {
    return fetchLocal(store, _input, *localPath);
    } else {
    auto [storePath, infoAttrs] = doFetch(store, _input);
    Input input(_input);
    mergeAttrs(input.attrs, std::move(infoAttrs));
    return {std::move(storePath), input};
    }
    DBG_END
    }
    #ifdef NIX_GETSOURCEPATH_IS_CONST
    std::optional<Path> getSourcePath(const Input &input) const override
    #else
    std::optional<Path> getSourcePath(const Input &input) override
    #endif
    {
    DBG_BEGIN
  • edit in src/fetcher.cpp at line 118
    [9.560][7.614:637]()
    #ifdef NIX_HAS_PUTFILE
  • replacement in src/fetcher.cpp at line 125
    [9.799][7.638:672](),[7.672][9.827:964](),[9.827][9.827:964]()
    #ifdef NIX_CANONPATH_HAS_SLASH_OP
    writeFile((CanonPath(*root) / path).abs(), contents);
    #else
    writeFile((CanonPath(*root) + path).abs(), contents);
    #endif
    [9.799]
    [9.964]
    auto rootStr = root->string();
    writeFile((CanonPath(rootStr) / path).abs(), contents);
    record(*commitMsg, rootStr, {Path(path.rel())});
  • edit in src/fetcher.cpp at line 129
    [9.965][9.2316:2371](),[9.2371][9.230:231]()
    record(*commitMsg, *root, {Path(path.rel())});
  • edit in src/fetcher.cpp at line 130
    [9.247][9.1146:1158](),[9.2239][9.1146:1158](),[9.2371][9.1146:1158](),[9.1146][9.1146:1158](),[9.1158][9.3937:4058](),[9.3937][9.3937:4058](),[9.4058][9.1159:1223](),[9.1223][9.4134:4135](),[9.4134][9.4134:4135](),[9.4135][9.2372:2428]()
    }
    #else
    void markChangedFile(const Input &input, std::string_view file, std::optional<std::string> commitMsg) override
    {
    auto root = getSourcePath(input);
    assert(root);
    record(*commitMsg, *root, {std::string(file)});
  • edit in src/fetcher.cpp at line 131
    [9.1376][9.1376:1383]()
    #endif
  • edit in src/fetcher.cpp at line 132
    [9.1384][7.673:716]()
    #ifdef NIX_INPUTSCHEME_EXTERNAL_URI_CHECKS
  • edit in src/fetcher.cpp at line 141
    [9.1632][9.1632:1639]()
    #endif
  • edit in src/fetcher.cpp at line 142
    [9.1640][7.717:763]()
    #ifdef NIX_INPUTSCHEME_EXTERNAL_LOCKED_CHECKS
  • edit in src/fetcher.cpp at line 149
    [9.1831][7.764:808]()
    #ifdef NIX_INPUTSCHEME_USES_SOURCE_ACCESSOR
  • edit in src/fetcher.cpp at line 150
    [9.229][9.229:235](),[9.235][9.1831:1938](),[9.1831][9.1831:1938](),[9.1938][9.236:243]()
    #else
    std::pair<ref<InputAccessor>, Input> getAccessor(ref<Store> store, const Input &_input) const override
    #endif
  • edit in src/fetcher.cpp at line 152
    [9.302][9.1944:1973](),[9.1944][9.1944:1973]()
    Input input(_input);
  • replacement in src/fetcher.cpp at line 153
    [9.1974][9.1974:2032]()
    auto [storePath, _] = fetchToStore(store, input);
    [9.1974]
    [9.2032]
    auto [storePath, input] = fetchToStoreImpl(store, _input);
  • edit in src/fetcher.cpp at line 156
    [9.2098]
    [9.303]
  • edit in src/fetcher.cpp at line 159
    [9.4322][9.2099:2106]()
    #endif
  • replacement in src/fetcher.cpp at line 161
    [9.4451][9.2107:2200]()
    static std::pair<StorePath, Attrs> doFetch(const ref<Store> &_store, const Input &input)
    [9.4332]
    [9.4543]
    std::pair<StorePath, Input> fetchToStoreImpl(ref<Store> store, const Input &_input) const
    {
    DBG_BEGIN
    if (auto localPath = getSourcePath(_input)) {
    return fetchLocal(store, _input, *localPath);
    } else {
    auto [storePath, infoAttrs] = doFetchCached(store, _input);
    Input input(_input);
    mergeAttrs(input.attrs, std::move(infoAttrs));
    return {std::move(storePath), input};
    }
    DBG_END
    }
    static std::pair<StorePath, Attrs> doFetchCached(ref<Store> store, const Input &input)
  • edit in src/fetcher.cpp at line 182
    [9.338][7.809:845](),[7.845][9.2229:2310](),[9.2229][9.2229:2310]()
    #ifdef NIX_STORE_PARAM_IS_STORE_REF
    Store &store = *_store;
    #else
    const auto &store = _store;
    #endif
  • edit in src/fetcher.cpp at line 183
    [9.2311]
    [9.4549]
    auto cache = input.settings->getCache();
  • replacement in src/fetcher.cpp at line 186
    [9.4594][9.4594:4701]()
    const auto url = parseURL(getStrAttr(input.attrs, "url"));
    const auto &repoUrl = url.base;
    [9.4594]
    [9.4701]
    auto url = parseURL(getStrAttr(input.attrs, "url"));
    auto baseUrl = url;
    baseUrl.query.clear();
    const auto repoUrl = baseUrl.to_string();
  • edit in src/fetcher.cpp at line 193
    [9.4838][7.846:876]()
    #ifdef NIX_HAS_CACHE_KEY_TYPE
  • replacement in src/fetcher.cpp at line 194
    [9.311][9.311:317](),[9.317][9.4970:5004](),[9.4970][9.4970:5004](),[9.5004][9.318:325](),[9.325][9.5004:5035](),[9.5004][9.5004:5035]()
    #else
    std::optional<Attrs> key;
    #endif
    bool isLocked = false;
    [9.311]
    [9.5035]
    bool isLockedInput = false;
  • replacement in src/fetcher.cpp at line 197
    [9.5068][9.5068:5097]()
    isLocked = true;
    [9.5068]
    [9.5097]
    isLockedInput = true;
  • replacement in src/fetcher.cpp at line 199
    [9.5098][7.877:907](),[7.907][9.354:506](),[9.354][9.354:506]()
    #ifdef NIX_HAS_CACHE_KEY_TYPE
    key = {"pijul", {
    {"name", name},
    {"channel", *channel},
    {"state", *state},
    }};
    [9.5098]
    [9.506]
    Attrs keyAttrs;
    keyAttrs.emplace("name"s, name);
    keyAttrs.emplace("channel"s, *channel);
    keyAttrs.emplace("state"s, *state);
    key = Cache::Key{"pijul"sv, std::move(keyAttrs)};
  • replacement in src/fetcher.cpp at line 205
    [9.507][9.507:578](),[9.578][9.578:653]()
    if (auto res = getCache()->lookupStorePath(*key, store)) {
    return {std::move(res->storePath), std::move(res->value)};
    [9.507]
    [9.653]
    if (auto res = cache->lookupStorePath(*key, *store)) {
    return std::make_pair(std::move(res->storePath), std::move(res->value));
  • edit in src/fetcher.cpp at line 208
    [9.667][9.667:673](),[9.673][9.5098:5473](),[9.5098][9.5098:5473](),[9.5473][9.674:681]()
    #else
    key = {
    {"type", "pijul"},
    {"name", name},
    {"channel", *channel},
    {"state", *state},
    };
    if (auto res = getCache()->lookup(store, *key)) {
    auto &[infoAttrs, storePath] = *res;
    return {std::move(storePath), std::move(infoAttrs)};
    }
    #endif
  • replacement in src/fetcher.cpp at line 210
    [9.5484][7.908:938](),[7.938][9.710:826](),[9.710][9.710:826]()
    #ifdef NIX_HAS_CACHE_KEY_TYPE
    const Cache::Key impureKey{"pijul", {
    {"name", name},
    {"url", repoUrl},
    }};
    [9.5484]
    [9.826]
    Attrs impureKeyAttrs;
    impureKeyAttrs.emplace("name"s, name);
    impureKeyAttrs.emplace("url"s, repoUrl);
    const Cache::Key impureKey{"pijul"sv, std::move(impureKeyAttrs)};
  • replacement in src/fetcher.cpp at line 215
    [9.827][9.827:899]()
    if (auto res = getCache()->lookupStorePath(impureKey, store)) {
    [9.827]
    [9.899]
    if (auto res = cache->lookupStorePath(impureKey, *store)) {
  • replacement in src/fetcher.cpp at line 219
    [9.1076][9.1076:1150]()
    return {std::move(res->storePath), std::move(infoAttrs)};
    [9.1076]
    [9.1150]
    return std::make_pair(std::move(res->storePath), std::move(infoAttrs));
  • edit in src/fetcher.cpp at line 222
    [9.1174][9.1174:1311]()
    #else
    const Attrs impureKey{
    {"type", "pijul"},
    {"name", name},
    {"url", repoUrl},
    };
  • replacement in src/fetcher.cpp at line 223
    [9.1312][9.5484:5596](),[9.5484][9.5484:5596]()
    if (auto res = getCache()->lookup(store, impureKey)) {
    auto &[infoAttrs, storePath] = *res;
    [9.1312]
    [9.5596]
    auto [storePath, rs] = doFetchClone(store, name, repoUrl, channel, state);
  • edit in src/fetcher.cpp at line 225
    [9.5597][9.5597:5824](),[9.5824][9.1313:1320](),[9.1320][9.5824:5825](),[9.5824][9.5824:5825](),[9.5825][9.2312:2391](),[9.2391][9.5903:5904](),[9.5903][9.5903:5904]()
    if ((!channel || *channel == getStrAttr(infoAttrs, "channel")) && (!state || *state == getStrAttr(infoAttrs, "state"))) {
    return {std::move(storePath), std::move(infoAttrs)};
    }
    }
    #endif
    auto [storePath, rs] = doFetch(_store, name, repoUrl, channel, state);
  • replacement in src/fetcher.cpp at line 226
    [9.5924][7.939:969](),[7.969][9.1349:1433](),[9.1349][9.1349:1433](),[9.1433][9.5924:6026](),[9.5924][9.5924:6026](),[9.6026][9.1434:1441]()
    #ifdef NIX_HAS_CACHE_KEY_TYPE
    key = {"pijul", {
    {"name", name},
    }};
    #else
    key = {
    {"type", "pijul"},
    {"name", name},
    };
    #endif
    [9.5924]
    [9.6026]
    Attrs keyAttrs;
    keyAttrs.emplace("name"s, name);
    key = Cache::Key{"pijul"sv, std::move(keyAttrs)};
  • replacement in src/fetcher.cpp at line 231
    [9.6037][7.970:1000](),[7.1000][9.1470:1508](),[9.1470][9.1470:1508](),[9.1508][9.6037:6062](),[9.6037][9.6037:6062](),[9.6062][9.1509:1516](),[9.1516][9.6062:6198](),[9.6062][9.6062:6198]()
    #ifdef NIX_HAS_CACHE_KEY_TYPE
    mergeAttrs(key->second,
    #else
    mergeAttrs(*key,
    #endif
    {
    {"channel", rs.channel},
    {"state", rs.state},
    });
    [9.6037]
    [9.6198]
    Attrs toMerge;
    toMerge.emplace("channel"s, rs.channel);
    toMerge.emplace("state"s, rs.state);
    mergeAttrs(key->second, std::move(toMerge));
  • replacement in src/fetcher.cpp at line 236
    [9.6199][9.6199:6377]()
    Attrs infoAttrs = {
    {"channel", std::move(rs.channel)},
    {"state", std::move(rs.state)},
    {"lastModified", rs.lastModified},
    };
    [9.6199]
    [9.6377]
    Attrs infoAttrs;
    infoAttrs.emplace("channel"s, std::move(rs.channel));
    infoAttrs.emplace("state"s, std::move(rs.state));
    infoAttrs.emplace("lastModified"s, rs.lastModified);
  • replacement in src/fetcher.cpp at line 241
    [9.6378][9.6378:6403](),[9.6403][7.1001:1031](),[7.1031][9.1545:1617](),[9.1545][9.1545:1617](),[9.1617][9.1617:1623](),[9.1623][9.6403:6479](),[9.6403][9.6403:6479](),[9.6479][9.1624:1631]()
    if (!isLocked) {
    #ifdef NIX_HAS_CACHE_KEY_TYPE
    getCache()->upsert(impureKey, store, infoAttrs, storePath);
    #else
    getCache()->add(store, impureKey, infoAttrs, storePath, false);
    #endif
    [9.6378]
    [9.6479]
    if (!isLockedInput) {
    cache->upsert(impureKey, *store, infoAttrs, storePath);
  • replacement in src/fetcher.cpp at line 245
    [9.6490][7.1032:1062](),[7.1062][9.1660:1723](),[9.1660][9.1660:1723](),[9.1723][9.1723:1729](),[9.1729][9.6490:6556](),[9.6490][9.6490:6556](),[9.6556][9.1730:1737]()
    #ifdef NIX_HAS_CACHE_KEY_TYPE
    getCache()->upsert(*key, store, infoAttrs, storePath);
    #else
    getCache()->add(store, *key, infoAttrs, storePath, true);
    #endif
    [9.6490]
    [9.6556]
    cache->upsert(*key, *store, infoAttrs, storePath);
  • replacement in src/fetcher.cpp at line 247
    [9.6557][9.6557:6618]()
    return {std::move(storePath), std::move(infoAttrs)};
    [9.6557]
    [9.339]
    return std::make_pair(std::move(storePath), std::move(infoAttrs));
  • replacement in src/fetcher.cpp at line 251
    [9.6625][9.6625:7072]()
    static std::pair<StorePath, RepoStatus> doFetch(const ref<Store> &store,
    const std::string_view &inputName,
    const std::string_view &repoUrl,
    const std::optional<std::string_view> &channel,
    const std::optional<std::string_view> &state)
    [9.6625]
    [9.7072]
    static std::pair<StorePath, RepoStatus> doFetchClone(ref<Store> store,
    const std::string_view &inputName,
    const std::string_view &repoUrl,
    const std::optional<std::string_view> &channel,
    const std::optional<std::string_view> &state)
  • edit in src/fetcher.cpp at line 276
    [9.7976][7.1063:1105]()
    #if defined(NIX_POSIX_SOURCE_ACCESSOR_V3)
  • edit in src/fetcher.cpp at line 278
    [9.1891][7.1106:1150](),[7.1150][9.2420:2577](),[9.1921][9.2420:2577](),[9.2420][9.2420:2577](),[9.2577][7.1151:1195](),[7.1195][9.2607:2745](),[9.2607][9.2607:2745](),[9.2745][9.7976:8040](),[9.7976][9.7976:8040](),[9.8040][9.2746:2753]()
    #elif defined(NIX_POSIX_SOURCE_ACCESSOR_V2)
    auto [accessor, canonPath] = PosixSourceAccessor::createAtRoot(repoDir);
    auto storePath = store->addToStore(inputName, accessor, canonPath);
    #elif defined(NIX_POSIX_SOURCE_ACCESSOR_V1)
    PosixSourceAccessor accessor;
    auto storePath = store->addToStore(inputName, accessor, CanonPath::fromCwd(repoDir));
    #else
    auto storePath = store->addToStore(inputName, repoDir);
    #endif
  • replacement in src/fetcher.cpp at line 283
    [9.8102][9.2429:2543]()
    static std::pair<StorePath, Input> fetchLocal(const ref<Store> &store, const Input &_input, const Path &path)
    [9.8102]
    [9.8228]
    static std::pair<StorePath, Input> fetchLocal(ref<Store> store, const Input &_input, const std::filesystem::path &localPath)
  • replacement in src/fetcher.cpp at line 292
    [9.8563][9.2350:2390]()
    bool dirty = isRepoDirty(path);
    [9.8563]
    [9.8664]
    bool dirty = isRepoDirty(localPath.string());
  • replacement in src/fetcher.cpp at line 295
    [9.8774][7.1196:1239](),[7.1239][9.545:687](),[9.545][9.545:687](),[9.687][9.8819:8882](),[9.8819][9.8819:8882]()
    #ifdef NIX_INPUTFROMURL_HAS_SETTINGS_PARAM
    auto settings = *input.settings;
    #else
    auto settings = fetchSettings;
    #endif
    if (!settings.allowDirty) {
    throw Error("Pijul tree '%s' is dirty", path);
    [9.8774]
    [9.8882]
    if (!_input.settings->allowDirty) {
    throw Error("Pijul tree '%s' is dirty", localPath.string());
  • replacement in src/fetcher.cpp at line 299
    [9.8897][9.688:726](),[9.726][9.8940:8996](),[9.8940][9.8940:8996]()
    if (settings.warnDirty) {
    warn("Pijul tree '%s' is dirty", path);
    [9.8897]
    [9.8996]
    if (_input.settings->warnDirty) {
    warn("Pijul tree '%s' is dirty", localPath.string());
  • replacement in src/fetcher.cpp at line 304
    [9.9021][9.2391:2435]()
    auto files = getTrackedFiles(path);
    [9.9021]
    [9.9128]
    auto files = getTrackedFiles(localPath.string());
  • replacement in src/fetcher.cpp at line 306
    [9.9129][9.9129:9175]()
    Path actualPath(absPath(Path(path)));
    [9.9129]
    [9.9175]
    Path actualPath(absPath(Path(localPath.string())));
  • replacement in src/fetcher.cpp at line 324
    [9.9697][7.1356:1398](),[7.1398][9.755:938](),[9.755][9.755:938](),[9.938][7.1399:1443](),[9.968][9.1950:2126](),[7.1443][9.1950:2126](),[9.1950][9.1950:2126](),[9.2126][7.1444:1488](),[7.1488][9.2782:2987](),[9.2156][9.2782:2987](),[9.2782][9.2782:2987](),[9.2987][7.1489:1563]()
    #if defined(NIX_POSIX_SOURCE_ACCESSOR_V4)
    auto storePath = store->addToStore(input.getName(), {getFSSourceAccessor(), CanonPath(actualPath)}, ContentAddressMethod::Raw::NixArchive, HashAlgorithm::SHA256, {}, filter);
    #elif defined(NIX_POSIX_SOURCE_ACCESSOR_V3)
    auto storePath = store->addToStore(input.getName(), {getFSSourceAccessor(), CanonPath(actualPath)}, FileIngestionMethod::Recursive, HashAlgorithm::SHA256, {}, filter);
    #elif defined(NIX_POSIX_SOURCE_ACCESSOR_V1)
    PosixSourceAccessor accessor;
    auto storePath = store->addToStore(input.getName(), accessor, CanonPath{actualPath}, FileIngestionMethod::Recursive, HashAlgorithm::SHA256, {}, filter);
    #else
    #ifdef NIX_IS_LIX
    const auto htSHA256 = HashType::SHA256;
    #endif
    [9.9697]
    [7.1563]
    auto sourcePath = PosixSourceAccessor::createAtRoot(actualPath);
    auto storePath = store->addToStore(input.getName(), sourcePath, ContentAddressMethod::Raw::NixArchive, HashAlgorithm::SHA256, {}, filter);
  • edit in src/fetcher.cpp at line 327
    [7.1564][9.9697:9820](),[9.2987][9.9697:9820](),[9.9697][9.9697:9820](),[9.9820][9.2988:2995](),[9.2995][9.9820:9821](),[9.9820][9.9820:9821]()
    auto storePath = store->addToStore(input.getName(), actualPath, FileIngestionMethod::Recursive, htSHA256, filter);
    #endif
  • replacement in src/fetcher.cpp at line 328
    [9.9835][9.9835:9895]()
    const auto [state, timestamp] = getState(path);
    [9.9835]
    [9.9895]
    const auto [state, timestamp] = getState(localPath.string());
  • edit in src/fetcher.cpp at line 369
    [9.12882][7.1565:1583]()
    #ifdef NIX_IS_LIX
  • edit in src/fetcher.cpp at line 370
    [7.1646][7.1646:1652](),[7.1652][9.12882:12945](),[9.12882][9.12882:12945](),[9.12945][7.1653:1660]()
    #else
    registerInputScheme(std::make_unique<PijulInputScheme>());
    #endif
  • replacement in src/debug.h at line 8
    [9.594][9.594:616]()
    #include <logging.hh>
    [9.594]
    [9.616]
    #include <nix/util/logging.hh>
  • replacement in src/compat.h at line 5
    [9.2675][9.2675:2715]()
    #include <error.hh>
    #include <types.hh>
    [9.2675]
    [9.2715]
    #include <nix/util/error.hh>
    #include <nix/util/types.hh>
  • edit in src/compat.cpp at line 3
    [9.1838][7.1661:1682]()
    #include "nixfeat.h"
  • replacement in src/compat.cpp at line 5
    [9.3987][7.1683:1710](),[7.1710][9.4015:4039](),[9.4015][9.4015:4039]()
    #ifdef NIX_HAS_PROCESSES_H
    #include <processes.hh>
    [9.3987]
    [9.4039]
    #include <nix/util/processes.hh>
  • edit in src/compat.cpp at line 7
    [9.4045][9.4045:4077]()
    #include <util.hh>
    #endif
    #else
  • edit in src/compat.cpp at line 31
    [9.4508][7.1745:1776]()
    #if NIX_HAS_LOOKUPPATH
  • edit in src/compat.cpp at line 32
    [9.64][9.64:78](),[9.78][9.4508:4536](),[9.4508][9.4508:4536](),[9.4536][9.79:94]()
    #else
    .searchPath = true,
    #endif
  • replacement in meson.build at line 31
    [6.680][6.680:729]()
    nix_main_dep = d
    nix_impl = impl
    [6.680]
    [6.729]
    if d.found()
    nix_main_dep = d
    nix_impl = impl
    endif
  • replacement in meson.build at line 37
    [6.745][6.745:766]()
    if not d.found()
    [6.745]
    [6.766]
    if not nix_main_dep.found()
  • replacement in flake.nix at line 3
    [9.50][9.50:96]()
    nixpkgs.url = "nixpkgs/nixpkgs-unstable";
    [9.50]
    [9.96]
    nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
  • replacement in flake.nix at line 18
    [9.13706][3.10:100]()
    nix-plugin-pijul = pkgs.callPackage ./package.nix {nix = pkgs.nixVersions.latest;};
    [9.13706]
    [9.13766]
    nix-plugin-pijul = pkgs.callPackage ./package.nix {};
  • edit in flake.nix at line 20
    [9.13774][9.0:1](),[9.1][9.0:116](),[9.116][9.98:163](),[9.98][9.98:163](),[9.163][9.117:133](),[9.133][9.184:253](),[9.184][9.184:253](),[9.253][2.0:29](),[2.29][9.253:460](),[9.253][9.253:460](),[9.460][2.30:73]()
    checks = eachSystem (pkgs: let
    localRepoCheck = nix:
    pkgs.runCommand "localRepoCheck-${nix.name}"
    {
    nativeBuildInputs = [
    pkgs.pijul
    nix
    ];
    }
    ''
    export HOME=$(mktemp -d)
    export EDITOR=true
    pijul identity new --no-link --no-prompt --display-name 'Test User' --email 'test@example.com'
    pijul init repo
    cd repo
    echo "it works" > foo
    pijul add foo
    pijul record --message 'Add foo'
  • edit in flake.nix at line 21
    [9.505][9.505:543](),[9.543][9.134:270](),[9.270][9.655:915](),[9.655][9.655:915](),[9.915][9.915:916](),[9.916][9.916:949](),[9.949][9.271:280](),[9.850][9.850:909](),[9.909][9.0:177](),[9.177][3.101:389](),[9.177][9.949:957](),[3.389][9.949:957](),[9.909][9.949:957](),[9.949][9.949:957]()
    output=$(
    nix \
    --option plugin-files ${self.packages.${pkgs.system}.nix-plugin-pijul.override {inherit nix;}}/lib/nix/plugins/pijul.so \
    --extra-experimental-features 'nix-command flakes' \
    eval --impure --raw --expr "builtins.readFile ((builtins.fetchTree \"pijul+file://$PWD\") + \"/foo\")"
    )
    echo $output
    [[ "$output" = "it works" ]]
    mkdir $out
    '';
    in {
    nix_2_18 = localRepoCheck pkgs.nixVersions.nix_2_18;
    nix_2_19 = localRepoCheck pkgs.nixVersions.nix_2_19;
    nix_2_20 = localRepoCheck pkgs.nixVersions.nix_2_20;
    nix_2_21 = localRepoCheck pkgs.nixVersions.nix_2_21;
    nix_2_22 = localRepoCheck pkgs.nixVersions.nix_2_22;
    nix_2_23 = localRepoCheck pkgs.nixVersions.nix_2_23;
    nix_2_24 = localRepoCheck pkgs.nixVersions.nix_2_24;
    stable = localRepoCheck pkgs.nixVersions.stable;
    latest = localRepoCheck pkgs.nixVersions.latest;
    });
  • replacement in flake.lock at line 5
    [9.476][3.391:501](),[9.288][9.586:612](),[3.501][9.586:612](),[9.586][9.586:612]()
    "lastModified": 1729658218,
    "narHash": "sha256-9Rg+AqLqvqqJniP/OQB3GtgXoAd8IlazsHp97va042Y=",
    "owner": "NixOS",
    [9.476]
    [9.612]
    "lastModified": 1771008912,
    "narHash": "sha256-gf2AmWVTs8lEq7z/3ZAsgnZDhWIckkb+ZnAo5RzSxJg=",
    "owner": "nixos",
  • replacement in flake.lock at line 9
    [9.639][3.502:561]()
    "rev": "dfffb2e7a52d29a0ef8e21ec8a0f30487b227f1a",
    [9.639]
    [9.698]
    "rev": "a82ccc39b39b621151d6732718e3e250109076fa",
  • replacement in flake.lock at line 13
    [9.752][9.752:839]()
    "id": "nixpkgs",
    "ref": "nixpkgs-unstable",
    "type": "indirect"
    [9.752]
    [9.839]
    "owner": "nixos",
    "ref": "nixos-unstable",
    "repo": "nixpkgs",
    "type": "github"
  • replacement in README.md at line 19
    [9.525][9.0:471](),[9.471][4.0:13](),[4.13][4.13:14](),[4.14][4.14:105]()
    NB: The fetcher from this plugin does not automatically get used when running
    nix commands (e.g. `nix build`) in a Pijul repository, since this is hardcoded
    for Git and Mercurial in Nix. For this, I have a patch that adds the relevant
    code for Pijul, it's available as
    [nix-pijul](https://git.sr.ht/~dblsaiko/nix-extras/tree/master/item/packages/nix-pijul.nix)
    in my *nix-extras* flake. It replaces the normal Nix installation and can be
    used in addition to this plugin.
    ## Releases
    Released version archives are available [here](https://dblsaiko.net/pub/nix-plugin-pijul).
    [9.525]
    [9.471]
    **Requires Nix 2.25+.** The plugin executes pijul to actually fetch
    repositories, make sure that is available in the PATH.
  • replacement in README.md at line 24
    [9.1][5.0:37]()
    The package is available in nixpkgs:
    [9.1]
    [9.60]
    Build from the NUR:
  • replacement in README.md at line 27
    [9.65][5.38:75]()
    % nix build nixpkgs#nix-plugin-pijul
    [9.65]
    [9.125]
    nix-build -A nix-plugin-pijul https://github.com/DzmingLi/nur-packages/archive/master.tar.gz
  • replacement in README.md at line 30
    [9.540][9.473:597]()
    Add the built pijul.so module to plugin-files in nix.conf. Make sure it is built
    for the Nix version you are using it with.
    [9.540]
    [9.599]
    Or build from source:
  • edit in README.md at line 32
    [9.600][9.0:99](),[9.99][5.76:141](),[5.141][9.99:100](),[9.99][9.99:100]()
    The plugin executes pijul to actually fetch repositories, make sure
    that is available in the PATH.
    The package is also available as part of my *nix-extras* flake:
  • replacement in README.md at line 33
    [5.146][5.146:206]()
    % nix build sourcehut:~dblsaiko/nix-extras#nix-plugin-pijul
    [5.146]
    [5.206]
    pijul clone https://nest.pijul.com/DzmingLi/nix-plugin-pijul
    cd nix-plugin-pijul
    nix build
  • replacement in README.md at line 38
    [5.211][9.100:141](),[9.100][9.100:141]()
    ### NixOS (with the nix-extras overlay):
    [5.211]
    [9.607]
    Add the built pijul.so module to plugin-files in nix.conf. Make sure it is built
    for the Nix version you are using it with.
    ### NixOS
  • replacement in README.md at line 44
    [9.615][9.636:659]()
    {pkgs, config, ...}: {
    [9.615]
    [9.142]
    {pkgs, config, ...}:
    let
    nur = import (builtins.fetchTarball "https://github.com/DzmingLi/nur-packages/archive/master.tar.gz") { inherit pkgs; };
    in {
  • replacement in README.md at line 49
    [9.187][9.659:911](),[9.659][9.659:911]()
    nix.settings.plugin-files = "${pkgs.nix-plugin-pijul.override { nix = config.nix.package; }}/lib/nix/plugins/pijul.so";
    # Optional: Use the patched Nix to automatically use Pijul fetcher in local
    # repositories
    nix.package = pkgs.nix-pijul;
    [9.187]
    [9.686]
    nix.settings.plugin-files = "${nur.nix-plugin-pijul}/lib/nix/plugins/pijul.so";
  • replacement in README.md at line 60
    [9.917][9.917:1004]()
    nix-plugin-pijul.url = "pijul+https://nest.pijul.com/dblsaiko/nix-plugin-pijul";
    [9.917]
    [9.1004]
    nix-plugin-pijul.url = "pijul+https://nest.pijul.com/DzmingLi/nix-plugin-pijul";
  • replacement in README.md at line 62
    [9.1011][9.1011:1014]()
    [9.1011]
    [9.1014]
  • replacement in README.md at line 71
    [9.1109][9.1109:1142]()
    Code based on the [pijul fetcher
    [9.1109]
    [9.1142]
    - [dblsaiko](https://git.sr.ht/~dblsaiko) — original author
    - Code based on the [pijul fetcher