moved to devenv
This commit is contained in:
1
.devenv/bash-bash
Symbolic link
1
.devenv/bash-bash
Symbolic link
@@ -0,0 +1 @@
|
||||
/nix/store/cgjr3kj3hs7ngznyws5qfg16c8scpys0-bash-interactive-5.3p9
|
||||
603
.devenv/bootstrap/bootstrapLib.nix
Normal file
603
.devenv/bootstrap/bootstrapLib.nix
Normal file
@@ -0,0 +1,603 @@
|
||||
# Shared library functions for devenv evaluation
|
||||
{ inputs }:
|
||||
|
||||
rec {
|
||||
# Helper to get overlays for a given input
|
||||
getOverlays =
|
||||
inputName: inputAttrs:
|
||||
let
|
||||
lib = inputs.nixpkgs.lib;
|
||||
in
|
||||
map
|
||||
(
|
||||
overlay:
|
||||
let
|
||||
input =
|
||||
inputs.${inputName} or (throw "No such input `${inputName}` while trying to configure overlays.");
|
||||
in
|
||||
input.overlays.${overlay}
|
||||
or (throw "Input `${inputName}` has no overlay called `${overlay}`. Supported overlays: ${lib.concatStringsSep ", " (builtins.attrNames input.overlays)}")
|
||||
) inputAttrs.overlays or [ ];
|
||||
|
||||
# Main function to create devenv configuration for a specific system with profiles support
|
||||
# This is the full-featured version used by default.nix
|
||||
mkDevenvForSystem =
|
||||
{ version
|
||||
, is_development_version ? false
|
||||
, require_version_match ? false
|
||||
, system
|
||||
, devenv_root
|
||||
, git_root ? null
|
||||
, devenv_dotfile
|
||||
, devenv_dotfile_path
|
||||
, devenv_tmpdir
|
||||
, devenv_runtime
|
||||
, devenv_state ? null
|
||||
, devenv_istesting ? false
|
||||
, devenv_direnvrc_latest_version
|
||||
, active_profiles ? [ ]
|
||||
, hostname
|
||||
, username
|
||||
, cli_options ? [ ]
|
||||
, skip_local_src ? false
|
||||
, secretspec ? null
|
||||
, devenv_inputs ? { }
|
||||
, devenv_imports ? [ ]
|
||||
, impure ? false
|
||||
, nixpkgs_config ? { }
|
||||
, lock_fingerprint ? null
|
||||
, primops ? { }
|
||||
}:
|
||||
let
|
||||
inherit (inputs) nixpkgs;
|
||||
lib = nixpkgs.lib;
|
||||
targetSystem = system;
|
||||
|
||||
overlays = lib.flatten (lib.mapAttrsToList getOverlays devenv_inputs);
|
||||
|
||||
# Helper to create pkgs for a given system with nixpkgs_config
|
||||
mkPkgsForSystem =
|
||||
evalSystem:
|
||||
import nixpkgs {
|
||||
system = evalSystem;
|
||||
config = nixpkgs_config // {
|
||||
# nixpkgs' check-meta.nix natively handles permittedInsecurePackages
|
||||
# via allowInsecureDefaultPredicate using the full derivation name.
|
||||
# We must NOT override allowInsecurePredicate here, as lib.getName
|
||||
# strips the version, causing mismatches with user-provided entries
|
||||
# like "openssl-1.1.1w".
|
||||
#
|
||||
# For unfree packages, nixpkgs does not natively support
|
||||
# permittedUnfreePackages, so we provide a custom predicate.
|
||||
allowUnfreePredicate =
|
||||
if nixpkgs_config.allowUnfree or false then
|
||||
(_: true)
|
||||
else if (nixpkgs_config.permittedUnfreePackages or [ ]) != [ ] then
|
||||
(pkg: builtins.elem (lib.getName pkg) (nixpkgs_config.permittedUnfreePackages or [ ]))
|
||||
else
|
||||
(_: false);
|
||||
} // lib.optionalAttrs ((nixpkgs_config.allowlistedLicenses or [ ]) != [ ]) {
|
||||
allowlistedLicenses = map (name: lib.licenses.${name}) (nixpkgs_config.allowlistedLicenses or [ ]);
|
||||
} // lib.optionalAttrs ((nixpkgs_config.blocklistedLicenses or [ ]) != [ ]) {
|
||||
blocklistedLicenses = map (name: lib.licenses.${name}) (nixpkgs_config.blocklistedLicenses or [ ]);
|
||||
};
|
||||
inherit overlays;
|
||||
};
|
||||
|
||||
pkgsBootstrap = mkPkgsForSystem targetSystem;
|
||||
|
||||
# Helper to import a path, trying .nix first then /devenv.nix
|
||||
# Returns a list of modules, including devenv.local.nix when present
|
||||
tryImport =
|
||||
resolvedPath: basePath:
|
||||
if lib.hasSuffix ".nix" basePath then
|
||||
[ (import resolvedPath) ]
|
||||
else
|
||||
let
|
||||
devenvpath = resolvedPath + "/devenv.nix";
|
||||
localpath = resolvedPath + "/devenv.local.nix";
|
||||
in
|
||||
if builtins.pathExists devenvpath then
|
||||
[ (import devenvpath) ] ++ lib.optional (builtins.pathExists localpath) (import localpath)
|
||||
else
|
||||
throw (basePath + "/devenv.nix file does not exist");
|
||||
|
||||
importModule =
|
||||
path:
|
||||
if lib.hasPrefix "path:" path then
|
||||
# path: prefix indicates a local filesystem path - strip it and import directly
|
||||
let
|
||||
actualPath = builtins.substring 5 999999 path;
|
||||
in
|
||||
tryImport (/. + actualPath) path
|
||||
else if lib.hasPrefix "/" path then
|
||||
# Absolute path - import directly (avoids input resolution and NAR hash computation)
|
||||
tryImport (/. + path) path
|
||||
else if lib.hasPrefix "./" path then
|
||||
# Relative paths are relative to devenv_root, not bootstrap directory
|
||||
let
|
||||
relPath = builtins.substring 1 255 path;
|
||||
in
|
||||
tryImport (/. + devenv_root + relPath) path
|
||||
else if lib.hasPrefix "../" path then
|
||||
# Parent relative paths also relative to devenv_root
|
||||
tryImport (/. + devenv_root + "/${path}") path
|
||||
else
|
||||
let
|
||||
paths = lib.splitString "/" path;
|
||||
name = builtins.head paths;
|
||||
input = inputs.${name} or (throw "Unknown input ${name}");
|
||||
subpath = "/${lib.concatStringsSep "/" (builtins.tail paths)}";
|
||||
devenvpath = input + subpath;
|
||||
in
|
||||
tryImport devenvpath path;
|
||||
|
||||
# Common modules shared between main evaluation and cross-system evaluation
|
||||
mkCommonModules =
|
||||
evalPkgs:
|
||||
[
|
||||
(
|
||||
{ config, ... }:
|
||||
{
|
||||
_module.args.pkgs = evalPkgs.appendOverlays (config.overlays or [ ]);
|
||||
_module.args.secretspec = secretspec;
|
||||
_module.args.devenvPrimops = primops;
|
||||
}
|
||||
)
|
||||
(inputs.devenv.modules + /top-level.nix)
|
||||
(
|
||||
{ options, ... }:
|
||||
{
|
||||
config.devenv = lib.mkMerge [
|
||||
{
|
||||
root = devenv_root;
|
||||
dotfile = devenv_dotfile;
|
||||
}
|
||||
(
|
||||
if builtins.hasAttr "cli" options.devenv then
|
||||
{
|
||||
cli.version = version;
|
||||
cli.isDevelopment = is_development_version;
|
||||
}
|
||||
else
|
||||
{
|
||||
cliVersion = version;
|
||||
}
|
||||
)
|
||||
(lib.optionalAttrs
|
||||
(builtins.hasAttr "cli" options.devenv
|
||||
&& builtins.hasAttr "requireVersionMatch" options.devenv.cli)
|
||||
{
|
||||
cli.requireVersionMatch = require_version_match;
|
||||
}
|
||||
)
|
||||
(lib.optionalAttrs (builtins.hasAttr "tmpdir" options.devenv) {
|
||||
tmpdir = devenv_tmpdir;
|
||||
})
|
||||
(lib.optionalAttrs (builtins.hasAttr "isTesting" options.devenv) {
|
||||
isTesting = devenv_istesting;
|
||||
})
|
||||
(lib.optionalAttrs (builtins.hasAttr "runtime" options.devenv) {
|
||||
runtime = devenv_runtime;
|
||||
})
|
||||
(lib.optionalAttrs (builtins.hasAttr "state" options.devenv && devenv_state != null) {
|
||||
state = lib.mkForce devenv_state;
|
||||
})
|
||||
(lib.optionalAttrs (builtins.hasAttr "direnvrcLatestVersion" options.devenv) {
|
||||
direnvrcLatestVersion = devenv_direnvrc_latest_version;
|
||||
})
|
||||
];
|
||||
}
|
||||
)
|
||||
(
|
||||
{ options, ... }:
|
||||
{
|
||||
config = lib.mkMerge [
|
||||
(lib.optionalAttrs (builtins.hasAttr "git" options) {
|
||||
git.root = git_root;
|
||||
})
|
||||
];
|
||||
}
|
||||
)
|
||||
]
|
||||
++ (lib.flatten (map importModule devenv_imports))
|
||||
++ (if !skip_local_src then (importModule (devenv_root + "/devenv.nix")) else [ ])
|
||||
++ [
|
||||
(
|
||||
let
|
||||
localPath = devenv_root + "/devenv.local.nix";
|
||||
in
|
||||
if builtins.pathExists localPath then import localPath else { }
|
||||
)
|
||||
cli_options
|
||||
];
|
||||
|
||||
# Phase 1: Base evaluation to extract profile definitions
|
||||
baseProject = lib.evalModules {
|
||||
specialArgs = inputs // {
|
||||
inherit inputs secretspec primops;
|
||||
};
|
||||
modules = mkCommonModules pkgsBootstrap;
|
||||
};
|
||||
|
||||
# Phase 2: Extract and apply profiles using extendModules with priority overrides
|
||||
project =
|
||||
let
|
||||
# Build ordered list of profile names: hostname -> user -> manual
|
||||
manualProfiles = active_profiles;
|
||||
currentHostname = hostname;
|
||||
currentUsername = username;
|
||||
hostnameProfiles = lib.optional
|
||||
(
|
||||
currentHostname != null
|
||||
&& currentHostname != ""
|
||||
&& builtins.hasAttr currentHostname (baseProject.config.profiles.hostname or { })
|
||||
) "hostname.${currentHostname}";
|
||||
userProfiles = lib.optional
|
||||
(
|
||||
currentUsername != null
|
||||
&& currentUsername != ""
|
||||
&& builtins.hasAttr currentUsername (baseProject.config.profiles.user or { })
|
||||
) "user.${currentUsername}";
|
||||
|
||||
# Ordered list of profiles to activate
|
||||
orderedProfiles = hostnameProfiles ++ userProfiles ++ manualProfiles;
|
||||
|
||||
# Resolve profile extends with cycle detection
|
||||
resolveProfileExtends =
|
||||
profileName: visited:
|
||||
if builtins.elem profileName visited then
|
||||
throw "Circular dependency detected in profile extends: ${lib.concatStringsSep " -> " visited} -> ${profileName}"
|
||||
else
|
||||
let
|
||||
profile = getProfileConfig profileName;
|
||||
extends = profile.extends or [ ];
|
||||
newVisited = visited ++ [ profileName ];
|
||||
extendedProfiles = lib.flatten (map (name: resolveProfileExtends name newVisited) extends);
|
||||
in
|
||||
extendedProfiles ++ [ profileName ];
|
||||
|
||||
# Get profile configuration by name from baseProject
|
||||
getProfileConfig =
|
||||
profileName:
|
||||
if lib.hasPrefix "hostname." profileName then
|
||||
let
|
||||
name = lib.removePrefix "hostname." profileName;
|
||||
in
|
||||
baseProject.config.profiles.hostname.${name}
|
||||
else if lib.hasPrefix "user." profileName then
|
||||
let
|
||||
name = lib.removePrefix "user." profileName;
|
||||
in
|
||||
baseProject.config.profiles.user.${name}
|
||||
else
|
||||
let
|
||||
availableProfiles = builtins.attrNames (baseProject.config.profiles or { });
|
||||
hostnameProfiles = map (n: "hostname.${n}") (
|
||||
builtins.attrNames (baseProject.config.profiles.hostname or { })
|
||||
);
|
||||
userProfiles = map (n: "user.${n}") (builtins.attrNames (baseProject.config.profiles.user or { }));
|
||||
allAvailableProfiles = availableProfiles ++ hostnameProfiles ++ userProfiles;
|
||||
in
|
||||
baseProject.config.profiles.${profileName}
|
||||
or (throw "Profile '${profileName}' not found. Available profiles: ${lib.concatStringsSep ", " allAvailableProfiles}");
|
||||
|
||||
# Fold over ordered profiles to build final list with extends
|
||||
expandedProfiles = lib.foldl'
|
||||
(
|
||||
acc: profileName:
|
||||
let
|
||||
allProfileNames = resolveProfileExtends profileName [ ];
|
||||
in
|
||||
acc ++ allProfileNames
|
||||
) [ ]
|
||||
orderedProfiles;
|
||||
|
||||
# Map over expanded profiles and apply priorities
|
||||
allPrioritizedModules = lib.imap0
|
||||
(
|
||||
index: profileName:
|
||||
let
|
||||
profilePriority = (lib.modules.defaultOverridePriority - 1) - index;
|
||||
profileConfig = getProfileConfig profileName;
|
||||
|
||||
typeNeedsOverride =
|
||||
type:
|
||||
if type == null then
|
||||
false
|
||||
else
|
||||
let
|
||||
typeName = type.name or type._type or "";
|
||||
|
||||
isLeafType = builtins.elem typeName [
|
||||
"str"
|
||||
"int"
|
||||
"bool"
|
||||
"enum"
|
||||
"path"
|
||||
"package"
|
||||
"float"
|
||||
"anything"
|
||||
];
|
||||
in
|
||||
if isLeafType then
|
||||
true
|
||||
else if typeName == "nullOr" then
|
||||
let
|
||||
innerType =
|
||||
type.elemType
|
||||
or (if type ? nestedTypes && type.nestedTypes ? elemType then type.nestedTypes.elemType else null);
|
||||
in
|
||||
if innerType != null then typeNeedsOverride innerType else false
|
||||
else
|
||||
false;
|
||||
|
||||
pathNeedsOverride =
|
||||
optionPath:
|
||||
let
|
||||
directOption = lib.attrByPath optionPath null baseProject.options;
|
||||
in
|
||||
if directOption != null && lib.isOption directOption then
|
||||
typeNeedsOverride directOption.type
|
||||
else if optionPath != [ ] then
|
||||
let
|
||||
parentPath = lib.init optionPath;
|
||||
parentOption = lib.attrByPath parentPath null baseProject.options;
|
||||
in
|
||||
if parentOption != null && lib.isOption parentOption then
|
||||
let
|
||||
freeformType = parentOption.type.freeformType or parentOption.type.nestedTypes.freeformType or null;
|
||||
elementType =
|
||||
if freeformType ? elemType then
|
||||
freeformType.elemType
|
||||
else if freeformType ? nestedTypes && freeformType.nestedTypes ? elemType then
|
||||
freeformType.nestedTypes.elemType
|
||||
else
|
||||
freeformType;
|
||||
in
|
||||
typeNeedsOverride elementType
|
||||
else
|
||||
false
|
||||
else
|
||||
false;
|
||||
|
||||
applyModuleOverride =
|
||||
config:
|
||||
if builtins.isFunction config then
|
||||
let
|
||||
wrapper = args: applyOverrideRecursive (config args) [ ];
|
||||
in
|
||||
lib.mirrorFunctionArgs config wrapper
|
||||
else
|
||||
applyOverrideRecursive config [ ];
|
||||
|
||||
applyOverrideRecursive =
|
||||
config: optionPath:
|
||||
if lib.isAttrs config && config ? _type then
|
||||
config
|
||||
else if lib.isAttrs config then
|
||||
lib.mapAttrs (name: value: applyOverrideRecursive value (optionPath ++ [ name ])) config
|
||||
else if pathNeedsOverride optionPath then
|
||||
lib.mkOverride profilePriority config
|
||||
else
|
||||
config;
|
||||
|
||||
prioritizedConfig = (
|
||||
profileConfig.module
|
||||
// {
|
||||
imports = lib.map
|
||||
(
|
||||
importItem:
|
||||
importItem
|
||||
// {
|
||||
imports = lib.map (nestedImport: applyModuleOverride nestedImport) (importItem.imports or [ ]);
|
||||
}
|
||||
)
|
||||
(profileConfig.module.imports or [ ]);
|
||||
}
|
||||
);
|
||||
in
|
||||
prioritizedConfig
|
||||
)
|
||||
expandedProfiles;
|
||||
in
|
||||
if allPrioritizedModules == [ ] then
|
||||
baseProject
|
||||
else
|
||||
baseProject.extendModules { modules = allPrioritizedModules; };
|
||||
|
||||
config = project.config;
|
||||
|
||||
# Per-container scoped re-evaluation that flips `isBuilding` for the
|
||||
# container being built. Selecting one container cannot pollute the
|
||||
# evaluation of any other operation, since each `containerBuilds.<name>`
|
||||
# is its own `extendModules` scope.
|
||||
mkContainerBuilds =
|
||||
evalProject:
|
||||
lib.genAttrs (lib.attrNames evalProject.config.containers) (
|
||||
name:
|
||||
let
|
||||
scoped = evalProject.extendModules {
|
||||
modules = [{
|
||||
container.isBuilding = lib.mkForce true;
|
||||
containers.${name}.isBuilding = lib.mkForce true;
|
||||
}];
|
||||
};
|
||||
in
|
||||
scoped.config.containers.${name}
|
||||
);
|
||||
|
||||
containerBuilds = mkContainerBuilds project;
|
||||
|
||||
# Apply config overlays to pkgs
|
||||
pkgs = pkgsBootstrap.appendOverlays (config.overlays or [ ]);
|
||||
|
||||
options = pkgs.nixosOptionsDoc {
|
||||
options = builtins.removeAttrs project.options [ "_module" ];
|
||||
warningsAreErrors = false;
|
||||
transformOptions =
|
||||
let
|
||||
isDocType =
|
||||
v:
|
||||
builtins.elem v [
|
||||
"literalDocBook"
|
||||
"literalExpression"
|
||||
"literalMD"
|
||||
"mdDoc"
|
||||
];
|
||||
in
|
||||
lib.attrsets.mapAttrs (
|
||||
_: v:
|
||||
if v ? _type && isDocType v._type then
|
||||
v.text
|
||||
else if v ? _type && v._type == "derivation" then
|
||||
v.name
|
||||
else
|
||||
v
|
||||
);
|
||||
};
|
||||
|
||||
build =
|
||||
options: config:
|
||||
lib.concatMapAttrs
|
||||
(
|
||||
name: option:
|
||||
if lib.isOption option then
|
||||
let
|
||||
typeName = option.type.name or "";
|
||||
in
|
||||
if
|
||||
builtins.elem typeName [
|
||||
"output"
|
||||
"outputOf"
|
||||
]
|
||||
then
|
||||
{
|
||||
${name} = config.${name};
|
||||
}
|
||||
else
|
||||
{ }
|
||||
else if builtins.isAttrs option && !lib.isDerivation option then
|
||||
let
|
||||
v = build option config.${name};
|
||||
in
|
||||
if v != { } then { ${name} = v; } else { }
|
||||
else
|
||||
{ }
|
||||
)
|
||||
options;
|
||||
|
||||
# Helper to evaluate devenv for a specific system (for cross-compilation, e.g. macOS building Linux containers)
|
||||
evalForSystem =
|
||||
evalSystem:
|
||||
let
|
||||
evalPkgs = mkPkgsForSystem evalSystem;
|
||||
evalProject = lib.evalModules {
|
||||
specialArgs = inputs // {
|
||||
inherit inputs secretspec primops;
|
||||
};
|
||||
modules = mkCommonModules evalPkgs;
|
||||
};
|
||||
in
|
||||
{
|
||||
config = evalProject.config;
|
||||
containerBuilds = mkContainerBuilds evalProject;
|
||||
};
|
||||
|
||||
# All supported systems for cross-compilation (lazily evaluated)
|
||||
allSystems = [
|
||||
"x86_64-linux"
|
||||
"aarch64-linux"
|
||||
"x86_64-darwin"
|
||||
"aarch64-darwin"
|
||||
];
|
||||
|
||||
# Generate perSystem entries for all systems (only evaluated when accessed)
|
||||
perSystemConfigs = lib.genAttrs allSystems (
|
||||
perSystem:
|
||||
if perSystem == targetSystem then
|
||||
{ inherit config containerBuilds; }
|
||||
else
|
||||
evalForSystem perSystem
|
||||
);
|
||||
in
|
||||
{
|
||||
inherit
|
||||
pkgs
|
||||
config
|
||||
options
|
||||
project
|
||||
;
|
||||
bash = pkgs.bash;
|
||||
shell = config.shell;
|
||||
optionsJSON = options.optionsJSON;
|
||||
info = config.info;
|
||||
ci = config.ciDerivation;
|
||||
build = build project.options config;
|
||||
devenv = {
|
||||
# Backwards compatibility: wrap config in devenv attribute for code expecting devenv.config.*
|
||||
inherit config containerBuilds;
|
||||
# perSystem structure for cross-compilation (e.g. macOS building Linux containers)
|
||||
perSystem = perSystemConfigs;
|
||||
};
|
||||
};
|
||||
|
||||
# Simplified devenv evaluation for inputs
|
||||
# This is a lightweight version suitable for evaluating an input's devenv.nix
|
||||
mkDevenvForInput =
|
||||
{
|
||||
# The input to evaluate (must have outPath and sourceInfo)
|
||||
input
|
||||
, # All resolved inputs (for specialArgs)
|
||||
allInputs
|
||||
, # System to evaluate for
|
||||
system ? builtins.currentSystem
|
||||
, # Nixpkgs to use (defaults to allInputs.nixpkgs)
|
||||
nixpkgs ? allInputs.nixpkgs or (throw "nixpkgs input required")
|
||||
, # Devenv modules (defaults to allInputs.devenv)
|
||||
devenv ? allInputs.devenv or (throw "devenv input required")
|
||||
,
|
||||
}:
|
||||
let
|
||||
devenvPath = input.outPath + "/devenv.nix";
|
||||
hasDevenv = builtins.pathExists devenvPath;
|
||||
in
|
||||
if !hasDevenv then
|
||||
throw ''
|
||||
Input does not have a devenv.nix file.
|
||||
Expected file at: ${devenvPath}
|
||||
|
||||
To use this input's devenv configuration, the input must provide a devenv.nix file.
|
||||
''
|
||||
else
|
||||
let
|
||||
pkgs = import nixpkgs {
|
||||
inherit system;
|
||||
config = { };
|
||||
};
|
||||
lib = pkgs.lib;
|
||||
|
||||
project = lib.evalModules {
|
||||
specialArgs = allInputs // {
|
||||
inputs = allInputs;
|
||||
secretspec = null;
|
||||
};
|
||||
modules = [
|
||||
(
|
||||
{ config, ... }:
|
||||
{
|
||||
_module.args.pkgs = pkgs.appendOverlays (config.overlays or [ ]);
|
||||
}
|
||||
)
|
||||
(devenv.outPath + "/src/modules/top-level.nix")
|
||||
(import devenvPath)
|
||||
];
|
||||
};
|
||||
in
|
||||
{
|
||||
inherit pkgs;
|
||||
config = project.config;
|
||||
options = project.options;
|
||||
inherit project;
|
||||
};
|
||||
}
|
||||
19
.devenv/bootstrap/default.nix
Normal file
19
.devenv/bootstrap/default.nix
Normal file
@@ -0,0 +1,19 @@
|
||||
args@{ system
|
||||
, # The project root (location of devenv.nix)
|
||||
devenv_root
|
||||
, ...
|
||||
}:
|
||||
|
||||
let
|
||||
inherit
|
||||
(import ./resolve-lock.nix {
|
||||
src = devenv_root;
|
||||
inherit system;
|
||||
})
|
||||
inputs
|
||||
;
|
||||
|
||||
bootstrapLib = import ./bootstrapLib.nix { inherit inputs; };
|
||||
in
|
||||
|
||||
bootstrapLib.mkDevenvForSystem args
|
||||
157
.devenv/bootstrap/resolve-lock.nix
Normal file
157
.devenv/bootstrap/resolve-lock.nix
Normal file
@@ -0,0 +1,157 @@
|
||||
# Adapted from https://git.lix.systems/lix-project/flake-compat/src/branch/main/default.nix
|
||||
{ src
|
||||
, system ? builtins.currentSystem or "unknown-system"
|
||||
,
|
||||
}:
|
||||
|
||||
let
|
||||
lockFilePath = src + "/devenv.lock";
|
||||
|
||||
lockFile = builtins.fromJSON (builtins.readFile lockFilePath);
|
||||
|
||||
rootSrc = {
|
||||
lastModified = 0;
|
||||
lastModifiedDate = formatSecondsSinceEpoch 0;
|
||||
# *hacker voice*: it's definitely a store path, I promise (actually a
|
||||
# nixlang path value, likely not pointing at the store).
|
||||
outPath = src;
|
||||
};
|
||||
|
||||
# Format number of seconds in the Unix epoch as %Y%m%d%H%M%S.
|
||||
formatSecondsSinceEpoch =
|
||||
t:
|
||||
let
|
||||
rem = x: y: x - x / y * y;
|
||||
days = t / 86400;
|
||||
secondsInDay = rem t 86400;
|
||||
hours = secondsInDay / 3600;
|
||||
minutes = (rem secondsInDay 3600) / 60;
|
||||
seconds = rem t 60;
|
||||
|
||||
# Courtesy of https://stackoverflow.com/a/32158604.
|
||||
z = days + 719468;
|
||||
era = (if z >= 0 then z else z - 146096) / 146097;
|
||||
doe = z - era * 146097;
|
||||
yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365;
|
||||
y = yoe + era * 400;
|
||||
doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
|
||||
mp = (5 * doy + 2) / 153;
|
||||
d = doy - (153 * mp + 2) / 5 + 1;
|
||||
m = mp + (if mp < 10 then 3 else -9);
|
||||
y' = y + (if m <= 2 then 1 else 0);
|
||||
|
||||
pad = s: if builtins.stringLength s < 2 then "0" + s else s;
|
||||
in
|
||||
"${toString y'}${pad (toString m)}${pad (toString d)}${pad (toString hours)}${pad (toString minutes)}${pad (toString seconds)}";
|
||||
|
||||
allNodes = builtins.mapAttrs
|
||||
(
|
||||
key: node:
|
||||
let
|
||||
sourceInfo =
|
||||
if key == lockFile.root then
|
||||
rootSrc
|
||||
# Path inputs pointing to project root (path = ".") should use rootSrc
|
||||
# to avoid fetchTree hashing the entire project directory
|
||||
else if node.locked.type or null == "path" && node.locked.path or null == "." then
|
||||
rootSrc
|
||||
else
|
||||
let
|
||||
locked = node.locked;
|
||||
isRelativePath = p: p != null && (builtins.substring 0 2 p == "./" || builtins.substring 0 3 p == "../");
|
||||
# Resolve relative paths against src
|
||||
resolvedLocked = locked
|
||||
// (if locked.type or null == "path" && isRelativePath (locked.path or null)
|
||||
then { path = toString src + "/${locked.path}"; }
|
||||
else { })
|
||||
// (if locked.type or null == "git" && isRelativePath (locked.url or null)
|
||||
then { url = toString src + "/${locked.url}"; }
|
||||
else { });
|
||||
in
|
||||
builtins.fetchTree (node.info or { } // removeAttrs resolvedLocked [ "dir" ]);
|
||||
|
||||
subdir = if key == lockFile.root then "" else node.locked.dir or "";
|
||||
|
||||
outPath = sourceInfo + ((if subdir == "" then "" else "/") + subdir);
|
||||
|
||||
# Resolve a input spec into a node name. An input spec is
|
||||
# either a node name, or a 'follows' path from the root
|
||||
# node.
|
||||
resolveInput =
|
||||
inputSpec: if builtins.isList inputSpec then getInputByPath lockFile.root inputSpec else inputSpec;
|
||||
|
||||
# Follow an input path (e.g. ["dwarffs" "nixpkgs"]) from the
|
||||
# root node, returning the final node.
|
||||
getInputByPath =
|
||||
nodeName: path:
|
||||
if path == [ ] then
|
||||
nodeName
|
||||
else
|
||||
getInputByPath
|
||||
# Since this could be a 'follows' input, call resolveInput.
|
||||
(resolveInput lockFile.nodes.${nodeName}.inputs.${builtins.head path})
|
||||
(builtins.tail path);
|
||||
|
||||
inputs = builtins.mapAttrs (inputName: inputSpec: allNodes.${resolveInput inputSpec}) (
|
||||
node.inputs or { }
|
||||
);
|
||||
|
||||
# Only import flake.nix for non-root nodes (root doesn't need it)
|
||||
flake = if key == lockFile.root then null else import (outPath + "/flake.nix");
|
||||
|
||||
outputs = if key == lockFile.root then { } else flake.outputs (inputs // { self = result; });
|
||||
|
||||
# Lazy devenv evaluation for this input
|
||||
devenvEval =
|
||||
let
|
||||
bootstrapLib = import ./bootstrapLib.nix { inputs = inputs; };
|
||||
in
|
||||
bootstrapLib.mkDevenvForInput {
|
||||
input = { inherit outPath sourceInfo; };
|
||||
allInputs = inputs;
|
||||
inherit system;
|
||||
};
|
||||
|
||||
result =
|
||||
outputs
|
||||
// sourceInfo
|
||||
// {
|
||||
inherit outPath;
|
||||
inherit inputs;
|
||||
inherit outputs;
|
||||
inherit sourceInfo;
|
||||
_type = "flake";
|
||||
devenv = devenvEval;
|
||||
};
|
||||
|
||||
nonFlakeResult = sourceInfo // {
|
||||
inherit outPath;
|
||||
inherit inputs;
|
||||
inherit sourceInfo;
|
||||
_type = "flake";
|
||||
devenv = devenvEval;
|
||||
};
|
||||
|
||||
in
|
||||
if node.flake or true && key != lockFile.root then
|
||||
assert builtins.isFunction flake.outputs;
|
||||
result
|
||||
else
|
||||
nonFlakeResult
|
||||
)
|
||||
lockFile.nodes;
|
||||
|
||||
result =
|
||||
if !(builtins.pathExists lockFilePath) then
|
||||
throw "${lockFilePath} does not exist"
|
||||
else if lockFile.version >= 5 && lockFile.version <= 7 then
|
||||
allNodes.${lockFile.root}
|
||||
else
|
||||
throw "lock file '${lockFilePath}' has unsupported version ${toString lockFile.version}";
|
||||
|
||||
in
|
||||
{
|
||||
inputs = result.inputs or { } // {
|
||||
self = result;
|
||||
};
|
||||
}
|
||||
1
.devenv/gc/shell
Symbolic link
1
.devenv/gc/shell
Symbolic link
@@ -0,0 +1 @@
|
||||
/nix/store/qfli8mq0fxc3lfj1w7yv00zgf8n3fa6c-devenv-shell
|
||||
1
.devenv/gc/task-config-devenv-config-task-config
Symbolic link
1
.devenv/gc/task-config-devenv-config-task-config
Symbolic link
@@ -0,0 +1 @@
|
||||
/nix/store/vsp3fis0yyfrw5zdw1r908cz5wkwy1qs-tasks.json
|
||||
0
.devenv/imports.txt
Normal file
0
.devenv/imports.txt
Normal file
10
.devenv/input-paths.txt
Normal file
10
.devenv/input-paths.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
/home/user01/Projects/score-system/.devenv/bootstrap/bootstrapLib.nix
|
||||
/home/user01/Projects/score-system/.devenv/bootstrap/default.nix
|
||||
/home/user01/Projects/score-system/.devenv/bootstrap/resolve-lock.nix
|
||||
/home/user01/Projects/score-system/devenv.local.nix
|
||||
/home/user01/Projects/score-system/devenv.lock
|
||||
/home/user01/Projects/score-system/devenv.nix
|
||||
/home/user01/Projects/score-system/devenv.yaml
|
||||
/home/user01/.config/nixpkgs/overlays
|
||||
/home/user01/.config/nixpkgs/overlays.nix
|
||||
/home/user01/Projects/score-system/.env
|
||||
1
.devenv/load-exports
Executable file
1
.devenv/load-exports
Executable file
@@ -0,0 +1 @@
|
||||
|
||||
BIN
.devenv/nix-eval-cache.db-shm
Normal file
BIN
.devenv/nix-eval-cache.db-shm
Normal file
Binary file not shown.
BIN
.devenv/nix-eval-cache.db-wal
Normal file
BIN
.devenv/nix-eval-cache.db-wal
Normal file
Binary file not shown.
12
.devenv/nixpkgs-config-f0bff968555a3434.nix
Normal file
12
.devenv/nixpkgs-config-f0bff968555a3434.nix
Normal file
@@ -0,0 +1,12 @@
|
||||
let
|
||||
cfg = {};
|
||||
getName = pkg: (builtins.parseDrvName (pkg.name or pkg.pname or "")).name;
|
||||
in cfg // {
|
||||
allowUnfreePredicate =
|
||||
if cfg.allowUnfree or false then
|
||||
(_: true)
|
||||
else if (cfg.permittedUnfreePackages or []) != [] then
|
||||
(pkg: builtins.elem (getName pkg) (cfg.permittedUnfreePackages or []))
|
||||
else
|
||||
(_: false);
|
||||
}
|
||||
1
.devenv/profile
Symbolic link
1
.devenv/profile
Symbolic link
@@ -0,0 +1 @@
|
||||
/nix/store/z7jz33yvsqvfv3qxpy2r9mp3mh0ngcvg-devenv-profile
|
||||
1
.devenv/run
Symbolic link
1
.devenv/run
Symbolic link
@@ -0,0 +1 @@
|
||||
/run/user/1000/devenv-3f21a4e
|
||||
2265
.devenv/shell-3f79910ee86ced32.sh
Executable file
2265
.devenv/shell-3f79910ee86ced32.sh
Executable file
File diff suppressed because it is too large
Load Diff
2265
.devenv/shell-7f08e6d76227994d.sh
Executable file
2265
.devenv/shell-7f08e6d76227994d.sh
Executable file
File diff suppressed because it is too large
Load Diff
2265
.devenv/shell-e893b9157f2d2e31.sh
Executable file
2265
.devenv/shell-e893b9157f2d2e31.sh
Executable file
File diff suppressed because it is too large
Load Diff
2257
.devenv/shell-env.sh
Normal file
2257
.devenv/shell-env.sh
Normal file
File diff suppressed because it is too large
Load Diff
163
.devenv/shell-rcfile.sh
Normal file
163
.devenv/shell-rcfile.sh
Normal file
@@ -0,0 +1,163 @@
|
||||
# Disable history during init so devenv internal commands don't pollute history.
|
||||
set +o history
|
||||
|
||||
# Environment diff helpers (always defined for tracking)
|
||||
|
||||
# Environment diff helpers (inspired by direnv)
|
||||
# Diff is stored in _DEVENV_DIFF env var (not a file) so each shell has its own state
|
||||
# Uses gzip+base64 encoding for compact storage
|
||||
|
||||
# Variables to ignore in diff (shell internals that change dynamically)
|
||||
__devenv_ignored_var() {
|
||||
case "$1" in
|
||||
_*|PWD|OLDPWD|SHLVL|SHELL|SHELLOPTS|BASHOPTS|BASH_*|HISTCMD|HISTFILE)
|
||||
return 0 ;;
|
||||
PS1|PS2|PS3|PS4|PROMPT|PROMPT_COMMAND|PROMPT_DIRTRIM)
|
||||
return 0 ;;
|
||||
COMP_*|READLINE_*|MAILCHECK|COLUMNS|LINES|RANDOM|SECONDS|LINENO|EPOCHSECONDS|EPOCHREALTIME|SRANDOM)
|
||||
return 0 ;;
|
||||
STARSHIP_*|__fish*|DIRENV_*|nix_saved_*)
|
||||
return 0 ;;
|
||||
*)
|
||||
return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
__devenv_capture_env() {
|
||||
# Capture exported variables using declare -p for proper escaping
|
||||
declare -p -x 2>/dev/null | LC_ALL=C sort
|
||||
}
|
||||
|
||||
__devenv_serialize_diff() {
|
||||
# Serialize diff (stdin) to base64-encoded gzip
|
||||
gzip -c | base64 -w0
|
||||
}
|
||||
|
||||
__devenv_deserialize_diff() {
|
||||
# Deserialize diff from base64-encoded gzip to stdout
|
||||
echo "$1" | base64 -d | gzip -d 2>/dev/null
|
||||
}
|
||||
|
||||
__devenv_compute_diff() {
|
||||
# Compare before ($1) and current env, return diff via _DEVENV_DIFF env var
|
||||
local before_file="$1"
|
||||
|
||||
# Create temp files
|
||||
local after_file diff_content
|
||||
after_file=$(mktemp)
|
||||
diff_content=$(mktemp)
|
||||
__devenv_capture_env > "$after_file"
|
||||
|
||||
# Build associative arrays for before/after
|
||||
local -A before_vars after_vars
|
||||
while IFS= read -r line; do
|
||||
[[ "$line" != declare\ -x\ * ]] && continue
|
||||
local vardef="${line#declare -x }"
|
||||
local var="${vardef%%=*}"
|
||||
[[ -z "$var" ]] && continue
|
||||
__devenv_ignored_var "$var" && continue
|
||||
before_vars["$var"]="$line"
|
||||
done < "$before_file"
|
||||
|
||||
while IFS= read -r line; do
|
||||
[[ "$line" != declare\ -x\ * ]] && continue
|
||||
local vardef="${line#declare -x }"
|
||||
local var="${vardef%%=*}"
|
||||
[[ -z "$var" ]] && continue
|
||||
__devenv_ignored_var "$var" && continue
|
||||
after_vars["$var"]="$line"
|
||||
done < "$after_file"
|
||||
|
||||
# Find PREV entries (vars that were modified or removed)
|
||||
for var in "${!before_vars[@]}"; do
|
||||
if [[ "${after_vars[$var]}" != "${before_vars[$var]}" ]]; then
|
||||
echo "P:${before_vars[$var]}" >> "$diff_content"
|
||||
fi
|
||||
done
|
||||
|
||||
# Find NEXT entries (vars that were added or modified)
|
||||
for var in "${!after_vars[@]}"; do
|
||||
if [[ -z "${before_vars[$var]+x}" ]]; then
|
||||
echo "N:$var" >> "$diff_content"
|
||||
elif [[ "${after_vars[$var]}" != "${before_vars[$var]}" ]]; then
|
||||
echo "N:$var" >> "$diff_content"
|
||||
fi
|
||||
done
|
||||
|
||||
# Serialize and store in env var
|
||||
_DEVENV_DIFF=$(__devenv_serialize_diff < "$diff_content")
|
||||
export _DEVENV_DIFF
|
||||
|
||||
rm -f "$after_file" "$diff_content"
|
||||
}
|
||||
|
||||
__devenv_apply_reverse_diff() {
|
||||
# Reverse the diff: restore PREV values, unset NEXT-only vars
|
||||
[[ -z "$_DEVENV_DIFF" ]] && return
|
||||
|
||||
local -A prev_vars
|
||||
local diff_content
|
||||
diff_content=$(__devenv_deserialize_diff "$_DEVENV_DIFF")
|
||||
|
||||
# First pass: collect and restore PREV declarations
|
||||
while IFS= read -r line; do
|
||||
if [[ "$line" == P:declare\ * ]]; then
|
||||
local decl="${line#P:}"
|
||||
local var="${decl#declare -x }"
|
||||
var="${var%%=*}"
|
||||
prev_vars["$var"]=1
|
||||
# Use export instead of evaluating the declare statement directly,
|
||||
# because declare -x inside a function creates a local variable
|
||||
# in bash 5.0+.
|
||||
eval "export ${decl#declare -x }" 2>/dev/null
|
||||
fi
|
||||
done <<< "$diff_content"
|
||||
|
||||
# Second pass: unset NEXT vars that were not in PREV (added vars)
|
||||
while IFS= read -r line; do
|
||||
if [[ "$line" == N:* ]]; then
|
||||
local var="${line#N:}"
|
||||
if [[ -z "${prev_vars[$var]+x}" ]]; then
|
||||
unset "$var"
|
||||
fi
|
||||
fi
|
||||
done <<< "$diff_content"
|
||||
}
|
||||
|
||||
|
||||
# Capture environment BEFORE sourcing devenv (for diff tracking)
|
||||
_devenv_before_file=$(mktemp)
|
||||
__devenv_capture_env > "$_devenv_before_file"
|
||||
|
||||
# Source the devenv environment
|
||||
source "/home/user01/Projects/score-system/.devenv/shell-env.sh"
|
||||
|
||||
# Compute and store the initial diff in _DEVENV_DIFF env var
|
||||
__devenv_compute_diff "$_devenv_before_file"
|
||||
rm -f "$_devenv_before_file"
|
||||
unset _devenv_before_file
|
||||
|
||||
# Save PATH before zsh init potentially modifies it
|
||||
export _DEVENV_PATH="$PATH"
|
||||
|
||||
# Save original ZDOTDIR so zsh init can restore it
|
||||
if [ -n "$ZDOTDIR" ]; then
|
||||
export _DEVENV_REAL_ZDOTDIR="$ZDOTDIR"
|
||||
fi
|
||||
|
||||
# Point ZDOTDIR to our init directory containing our .zshrc
|
||||
export ZDOTDIR="/home/user01/Projects/score-system/.devenv/zsh"
|
||||
|
||||
# Re-enable history before exec
|
||||
set -o history
|
||||
|
||||
# Exec into zsh (resolve via PATH if not absolute, since the devenv
|
||||
# environment may have added it after this process started)
|
||||
if [ ! -x "/run/current-system/sw/bin/zsh" ] && ! command -v "/run/current-system/sw/bin/zsh" >/dev/null 2>&1; then
|
||||
echo "devenv: error: shell '/run/current-system/sw/bin/zsh' not found" >&2
|
||||
echo "devenv: add zsh to your devenv.nix packages or set SHELL to an absolute path" >&2
|
||||
exit 1
|
||||
fi
|
||||
exec "/run/current-system/sw/bin/zsh" -i
|
||||
echo "devenv: error: failed to exec into /run/current-system/sw/bin/zsh" >&2
|
||||
exit 1
|
||||
1
.devenv/state/files.json
Normal file
1
.devenv/state/files.json
Normal file
@@ -0,0 +1 @@
|
||||
{"managedFiles":[]}
|
||||
BIN
.devenv/state/tasks.db-shm
Normal file
BIN
.devenv/state/tasks.db-shm
Normal file
Binary file not shown.
BIN
.devenv/state/tasks.db-wal
Normal file
BIN
.devenv/state/tasks.db-wal
Normal file
Binary file not shown.
6
.devenv/task-names.txt
Normal file
6
.devenv/task-names.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
devenv:container:copy
|
||||
devenv:enterShell
|
||||
devenv:enterTest
|
||||
devenv:files
|
||||
devenv:files:cleanup
|
||||
devenv:processes:server
|
||||
2464
.devenv/zsh/.zcompdump
Normal file
2464
.devenv/zsh/.zcompdump
Normal file
File diff suppressed because it is too large
Load Diff
2467
.devenv/zsh/.zcompdump-HACKSTATION-5.9.1
Normal file
2467
.devenv/zsh/.zcompdump-HACKSTATION-5.9.1
Normal file
File diff suppressed because it is too large
Load Diff
BIN
.devenv/zsh/.zcompdump-HACKSTATION-5.9.1.zwc
Normal file
BIN
.devenv/zsh/.zcompdump-HACKSTATION-5.9.1.zwc
Normal file
Binary file not shown.
6
.devenv/zsh/.zshenv
Normal file
6
.devenv/zsh/.zshenv
Normal file
@@ -0,0 +1,6 @@
|
||||
# devenv zsh .zshenv - runs before /etc/zshrc.
|
||||
# Prepend devenv profile site-functions so the system compinit (often
|
||||
# called from /etc/zshrc on nix-darwin, Debian, etc.) picks them up.
|
||||
if [ -n "$DEVENV_PROFILE" ] && [ -d "$DEVENV_PROFILE/share/zsh/site-functions" ]; then
|
||||
fpath=("$DEVENV_PROFILE/share/zsh/site-functions" $fpath)
|
||||
fi
|
||||
200
.devenv/zsh/.zshrc
Normal file
200
.devenv/zsh/.zshrc
Normal file
@@ -0,0 +1,200 @@
|
||||
# devenv zsh init - restore ZDOTDIR and source user's .zshrc
|
||||
|
||||
if [ -n "$_DEVENV_REAL_ZDOTDIR" ]; then
|
||||
ZDOTDIR="$_DEVENV_REAL_ZDOTDIR"
|
||||
unset _DEVENV_REAL_ZDOTDIR
|
||||
[ -f "$ZDOTDIR/.zshenv" ] && source "$ZDOTDIR/.zshenv"
|
||||
[ -f "$ZDOTDIR/.zshrc" ] && source "$ZDOTDIR/.zshrc"
|
||||
else
|
||||
unset ZDOTDIR
|
||||
[ -f "$HOME/.zshenv" ] && source "$HOME/.zshenv"
|
||||
[ -f "$HOME/.zshrc" ] && source "$HOME/.zshrc"
|
||||
fi
|
||||
|
||||
# Restore devenv PATH after user's .zshrc may have modified it
|
||||
export PATH="$_DEVENV_PATH"
|
||||
|
||||
# Set devenv prompt prefix
|
||||
PROMPT="(devenv) ${PROMPT}"
|
||||
|
||||
# Hot-reload hook
|
||||
|
||||
autoload -Uz add-zsh-hook
|
||||
|
||||
__devenv_reload_apply() {
|
||||
# Source new environment if a reload is pending
|
||||
if [ -f "/tmp/devenv-reload-6816.sh" ]; then
|
||||
# Shell out to bash to handle the env diff (bash syntax)
|
||||
local reload_output
|
||||
reload_output=$(bash -c '
|
||||
|
||||
# Environment diff helpers (inspired by direnv)
|
||||
# Diff is stored in _DEVENV_DIFF env var (not a file) so each shell has its own state
|
||||
# Uses gzip+base64 encoding for compact storage
|
||||
|
||||
# Variables to ignore in diff (shell internals that change dynamically)
|
||||
__devenv_ignored_var() {
|
||||
case "$1" in
|
||||
_*|PWD|OLDPWD|SHLVL|SHELL|SHELLOPTS|BASHOPTS|BASH_*|HISTCMD|HISTFILE)
|
||||
return 0 ;;
|
||||
PS1|PS2|PS3|PS4|PROMPT|PROMPT_COMMAND|PROMPT_DIRTRIM)
|
||||
return 0 ;;
|
||||
COMP_*|READLINE_*|MAILCHECK|COLUMNS|LINES|RANDOM|SECONDS|LINENO|EPOCHSECONDS|EPOCHREALTIME|SRANDOM)
|
||||
return 0 ;;
|
||||
STARSHIP_*|__fish*|DIRENV_*|nix_saved_*)
|
||||
return 0 ;;
|
||||
*)
|
||||
return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
__devenv_capture_env() {
|
||||
# Capture exported variables using declare -p for proper escaping
|
||||
declare -p -x 2>/dev/null | LC_ALL=C sort
|
||||
}
|
||||
|
||||
__devenv_serialize_diff() {
|
||||
# Serialize diff (stdin) to base64-encoded gzip
|
||||
gzip -c | base64 -w0
|
||||
}
|
||||
|
||||
__devenv_deserialize_diff() {
|
||||
# Deserialize diff from base64-encoded gzip to stdout
|
||||
echo "$1" | base64 -d | gzip -d 2>/dev/null
|
||||
}
|
||||
|
||||
__devenv_compute_diff() {
|
||||
# Compare before ($1) and current env, return diff via _DEVENV_DIFF env var
|
||||
local before_file="$1"
|
||||
|
||||
# Create temp files
|
||||
local after_file diff_content
|
||||
after_file=$(mktemp)
|
||||
diff_content=$(mktemp)
|
||||
__devenv_capture_env > "$after_file"
|
||||
|
||||
# Build associative arrays for before/after
|
||||
local -A before_vars after_vars
|
||||
while IFS= read -r line; do
|
||||
[[ "$line" != declare\ -x\ * ]] && continue
|
||||
local vardef="${line#declare -x }"
|
||||
local var="${vardef%%=*}"
|
||||
[[ -z "$var" ]] && continue
|
||||
__devenv_ignored_var "$var" && continue
|
||||
before_vars["$var"]="$line"
|
||||
done < "$before_file"
|
||||
|
||||
while IFS= read -r line; do
|
||||
[[ "$line" != declare\ -x\ * ]] && continue
|
||||
local vardef="${line#declare -x }"
|
||||
local var="${vardef%%=*}"
|
||||
[[ -z "$var" ]] && continue
|
||||
__devenv_ignored_var "$var" && continue
|
||||
after_vars["$var"]="$line"
|
||||
done < "$after_file"
|
||||
|
||||
# Find PREV entries (vars that were modified or removed)
|
||||
for var in "${!before_vars[@]}"; do
|
||||
if [[ "${after_vars[$var]}" != "${before_vars[$var]}" ]]; then
|
||||
echo "P:${before_vars[$var]}" >> "$diff_content"
|
||||
fi
|
||||
done
|
||||
|
||||
# Find NEXT entries (vars that were added or modified)
|
||||
for var in "${!after_vars[@]}"; do
|
||||
if [[ -z "${before_vars[$var]+x}" ]]; then
|
||||
echo "N:$var" >> "$diff_content"
|
||||
elif [[ "${after_vars[$var]}" != "${before_vars[$var]}" ]]; then
|
||||
echo "N:$var" >> "$diff_content"
|
||||
fi
|
||||
done
|
||||
|
||||
# Serialize and store in env var
|
||||
_DEVENV_DIFF=$(__devenv_serialize_diff < "$diff_content")
|
||||
export _DEVENV_DIFF
|
||||
|
||||
rm -f "$after_file" "$diff_content"
|
||||
}
|
||||
|
||||
__devenv_apply_reverse_diff() {
|
||||
# Reverse the diff: restore PREV values, unset NEXT-only vars
|
||||
[[ -z "$_DEVENV_DIFF" ]] && return
|
||||
|
||||
local -A prev_vars
|
||||
local diff_content
|
||||
diff_content=$(__devenv_deserialize_diff "$_DEVENV_DIFF")
|
||||
|
||||
# First pass: collect and restore PREV declarations
|
||||
while IFS= read -r line; do
|
||||
if [[ "$line" == P:declare\ * ]]; then
|
||||
local decl="${line#P:}"
|
||||
local var="${decl#declare -x }"
|
||||
var="${var%%=*}"
|
||||
prev_vars["$var"]=1
|
||||
# Use export instead of evaluating the declare statement directly,
|
||||
# because declare -x inside a function creates a local variable
|
||||
# in bash 5.0+.
|
||||
eval "export ${decl#declare -x }" 2>/dev/null
|
||||
fi
|
||||
done <<< "$diff_content"
|
||||
|
||||
# Second pass: unset NEXT vars that were not in PREV (added vars)
|
||||
while IFS= read -r line; do
|
||||
if [[ "$line" == N:* ]]; then
|
||||
local var="${line#N:}"
|
||||
if [[ -z "${prev_vars[$var]+x}" ]]; then
|
||||
unset "$var"
|
||||
fi
|
||||
fi
|
||||
done <<< "$diff_content"
|
||||
}
|
||||
|
||||
|
||||
# Reverse previous diff
|
||||
__devenv_apply_reverse_diff
|
||||
|
||||
# Capture env before sourcing new devenv
|
||||
_before=$(mktemp)
|
||||
__devenv_capture_env > "$_before"
|
||||
|
||||
# Source new devenv environment
|
||||
source "/tmp/devenv-reload-6816.sh"
|
||||
rm -f "/tmp/devenv-reload-6816.sh"
|
||||
|
||||
# Compute new diff
|
||||
__devenv_compute_diff "$_before"
|
||||
rm -f "$_before"
|
||||
|
||||
# Output current environment for the calling shell to parse
|
||||
export -p
|
||||
' 2>/dev/null)
|
||||
|
||||
# Apply the environment changes
|
||||
if [ -n "$reload_output" ]; then
|
||||
eval "$reload_output"
|
||||
fi
|
||||
|
||||
# Update saved PATH
|
||||
_DEVENV_PATH="$PATH"
|
||||
fi
|
||||
}
|
||||
|
||||
__devenv_restore_path() {
|
||||
# Restore devenv PATH (in case direnv or other tools modified it)
|
||||
export PATH="$_DEVENV_PATH"
|
||||
}
|
||||
|
||||
__devenv_precmd_hook() {
|
||||
__devenv_reload_apply
|
||||
__devenv_restore_path
|
||||
}
|
||||
add-zsh-hook precmd __devenv_precmd_hook
|
||||
|
||||
# Keybinding for manual reload
|
||||
__devenv_reload_widget() {
|
||||
__devenv_reload_apply
|
||||
zle reset-prompt
|
||||
}
|
||||
zle -N __devenv_reload_widget
|
||||
bindkey "${DEVENV_RELOAD_KEYBIND:-\\e\\C-r}" __devenv_reload_widget
|
||||
|
||||
5
cases.md
5
cases.md
@@ -1,5 +0,0 @@
|
||||
# Cases for players or something
|
||||
- player who didnt show up
|
||||
- player draws
|
||||
- events with multiple attempts (best / average)
|
||||
- how actual points are decided
|
||||
65
devenv.lock
Normal file
65
devenv.lock
Normal file
@@ -0,0 +1,65 @@
|
||||
{
|
||||
"nodes": {
|
||||
"devenv": {
|
||||
"locked": {
|
||||
"dir": "src/modules",
|
||||
"lastModified": 1781981587,
|
||||
"narHash": "sha256-xkBPfggcaDdbBl4fhHnhgVv2XPmzM2CtNBCpSwlK4fY=",
|
||||
"owner": "cachix",
|
||||
"repo": "devenv",
|
||||
"rev": "1ad4a4a03466826fc43127211c341d268efab21b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"dir": "src/modules",
|
||||
"owner": "cachix",
|
||||
"repo": "devenv",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"inputs": {
|
||||
"nixpkgs-src": "nixpkgs-src"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1781620901,
|
||||
"narHash": "sha256-UF6scQlG+6lRkZBUpn/3KNavhOo5G8kDWhjVHcno8uc=",
|
||||
"owner": "cachix",
|
||||
"repo": "devenv-nixpkgs",
|
||||
"rev": "2df109b343d3c68efd752e32a444a1d9b9f89afa",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "cachix",
|
||||
"ref": "rolling",
|
||||
"repo": "devenv-nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-src": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1781454065,
|
||||
"narHash": "sha256-d2xfDjnfRuf/xYGdu9VVRHiav/2w5hDL/5cw2TuVAXw=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "9eac87a12312b8f60dd52e1c6e1a265f6fc7f5fc",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"devenv": "devenv",
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
11
devenv.nix
Normal file
11
devenv.nix
Normal file
@@ -0,0 +1,11 @@
|
||||
{ pkgs, config, ... }: {
|
||||
languages.typescript.enable = true;
|
||||
packages = with pkgs; [
|
||||
bun
|
||||
eslint_d
|
||||
];
|
||||
env.DEVSHELL_NAME = " devenv/#fab387| Bun/yellow";
|
||||
processes = {
|
||||
server.exec = "bun run dev";
|
||||
};
|
||||
}
|
||||
0
devenv.yaml
Normal file
0
devenv.yaml
Normal file
61
flake.lock
generated
61
flake.lock
generated
@@ -1,61 +0,0 @@
|
||||
{
|
||||
"nodes": {
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1777578337,
|
||||
"narHash": "sha256-Ad49moKWeXtKBJNy2ebiTQUEgdLyvGmTeykAQ9xM+Z4=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "15f4ee454b1dce334612fa6843b3e05cf546efab",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs",
|
||||
"utils": "utils"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"utils": {
|
||||
"inputs": {
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1731533236,
|
||||
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
42
flake.nix
42
flake.nix
@@ -1,42 +0,0 @@
|
||||
{
|
||||
description = "A simple Rust development environment";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
utils.url = "github:numtide/flake-utils";
|
||||
};
|
||||
|
||||
outputs =
|
||||
{
|
||||
self,
|
||||
nixpkgs,
|
||||
utils,
|
||||
}:
|
||||
utils.lib.eachDefaultSystem (
|
||||
system:
|
||||
let
|
||||
pkgs = import nixpkgs { inherit system; };
|
||||
in
|
||||
{
|
||||
devShells.default = pkgs.mkShell {
|
||||
|
||||
name = "flake-bunshell";
|
||||
|
||||
buildInputs = with pkgs; [
|
||||
bun
|
||||
eslint_d
|
||||
];
|
||||
|
||||
# Environment variables
|
||||
shellHook = ''
|
||||
export DEVSHELL_NAME=" flake/#89dceb| Bun/yellow"
|
||||
|
||||
# Trigger zsh
|
||||
if [[ -z "$ZSH_VERSION" ]]; then
|
||||
exec zsh
|
||||
fi
|
||||
'';
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user