go: use env file instead of home.sessionVariables (#7751)

This commit is contained in:
Aguirre Matteo 2025-09-14 00:25:31 +00:00 committed by GitHub
parent 987b114082
commit 768a7042a6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 301 additions and 80 deletions

View file

@ -9,22 +9,41 @@ let
literalExpression
mkIf
mkOption
mkChangedOptionModule
mkRenamedOptionModule
types
;
cfg = config.programs.go;
keyValueFormat = pkgs.formats.keyValue { };
modeFileContent = "${cfg.telemetry.mode} ${cfg.telemetry.date}";
in
{
meta.maintainers = [ lib.maintainers.rvolosatovs ];
imports = [
(mkChangedOptionModule [ "programs" "go" "goPath" ] [ "programs" "go" "env" "GOPATH" ] (config: [
"${config.home.homeDirectory}/${config.programs.go.goPath}"
]))
(mkChangedOptionModule [ "programs" "go" "extraGoPaths" ] [ "programs" "go" "env" "GOPATH" ] (
config:
lib.mkOrder 1500 (map (x: "${config.home.homeDirectory}/${x}") config.programs.go.extraGoPaths)
))
(mkChangedOptionModule [ "programs" "go" "goBin" ] [ "programs" "go" "env" "GOBIN" ] (
config: "${config.home.homeDirectory}/${config.programs.go.goBin}"
))
(mkRenamedOptionModule [ "programs" "go" "goPrivate" ] [ "programs" "go" "env" "GOPRIVATE" ])
];
options = {
programs.go = {
enable = lib.mkEnableOption "Go";
package = lib.mkPackageOption pkgs "go" { };
package = lib.mkPackageOption pkgs "go" { nullable = true; };
packages = mkOption {
type = with types; attrsOf path;
@ -38,49 +57,51 @@ in
description = "Packages to add to GOPATH.";
};
goPath = mkOption {
type = with types; nullOr str;
default = null;
example = "go";
description = ''
Primary {env}`GOPATH` relative to
{env}`HOME`. It will be exported first and therefore
used by default by the Go tooling.
env = mkOption {
type = types.submodule {
freeformType = with types; attrsOf str;
options = {
GOPATH = mkOption {
type = with types; either str (listOf str);
apply = x: lib.concatStringsSep ":" (lib.toList x);
default = "";
description = "List of directories that should be used by the Go tooling.";
};
GOPRIVATE = mkOption {
type = with types; either str (listOf str);
apply = x: lib.concatStringsSep "," (lib.toList x);
default = "";
description = ''
Controls which modules the 'go' command considers to be private (not
available publicly) and should therefore not use the proxy or checksum database.
'';
};
};
};
default = { };
example = lib.literalExpression ''
{
GOPATH = [
"''${config.home.homeDirectory}/mygo"
"/another/go"
"/yet/another/go"
];
GOPRIVATE = [
"*.corp.example.com"
"rsc.io/private"
];
CXX = "g++";
GCCGO = "gccgo";
GOAMD64 = "v1";
GOARCH = "amd64";
GOAUTH = "netrc";
};
'';
};
extraGoPaths = mkOption {
type = types.listOf types.str;
default = [ ];
example = [
"extraGoPath1"
"extraGoPath2"
];
description = ''
Extra {env}`GOPATH`s relative to {env}`HOME` appended
after [](#opt-programs.go.goPath), if that option is set.
'';
};
goBin = mkOption {
type = with types; nullOr str;
default = null;
example = ".local/bin.go";
description = "GOBIN relative to HOME";
};
goPrivate = mkOption {
type = with types; listOf str;
default = [ ];
example = [
"*.corp.example.com"
"rsc.io/private"
];
description = ''
The {env}`GOPRIVATE` environment variable controls
which modules the go command considers to be private (not
available publicly) and should therefore not use the proxy
or checksum database.
Environment variables for Go. All the available options
can be found running 'go env'.
'';
};
@ -117,46 +138,56 @@ in
};
};
config = mkIf cfg.enable (
lib.mkMerge [
{
home.packages = [ cfg.package ];
config =
let
firstGoPath = lib.elemAt (lib.splitString ":" cfg.env.GOPATH) 0;
finalEnv = lib.filterAttrs (_: v: v != "") cfg.env;
in
mkIf cfg.enable (
lib.mkMerge [
{
assertions = [
{
assertion =
cfg.packages != { } -> cfg.env.GOPATH != "" -> lib.hasPrefix config.home.homeDirectory firstGoPath;
message = "The first element of `programs.go.env.GOPATH must be an absolute path that points to a directory inside ${config.home.homeDirectory} if `programs.go.packages` is set.";
}
];
home.packages = mkIf (cfg.package != null) [ cfg.package ];
home.file =
let
goPath = if cfg.goPath != null then cfg.goPath else "go";
mkSrc = n: v: { "${goPath}/src/${n}".source = v; };
in
lib.foldl' (a: b: a // b) { } (lib.mapAttrsToList mkSrc cfg.packages);
}
home.file = mkIf (cfg.packages != { }) (
let
mainGoPath = if (cfg.env.GOPATH != "") then firstGoPath else "go";
(mkIf (cfg.goPath != null) {
home.sessionVariables.GOPATH = lib.concatStringsSep ":" (
map builtins.toPath (
map (path: "${config.home.homeDirectory}/${path}") ([ cfg.goPath ] ++ cfg.extraGoPaths)
)
);
})
mkSrc = n: v: { "${mainGoPath}/src/${n}".source = v; };
in
lib.foldl' (a: b: a // b) { } (lib.mapAttrsToList mkSrc cfg.packages)
);
}
(mkIf (cfg.goBin != null) {
home.sessionVariables.GOBIN = builtins.toPath "${config.home.homeDirectory}/${cfg.goBin}";
})
(mkIf (cfg.env != { }) {
xdg.configFile."go/env" = {
enable = !pkgs.stdenv.hostPlatform.isDarwin;
source = keyValueFormat.generate "go-env" finalEnv;
};
(mkIf (cfg.goPrivate != [ ]) {
home.sessionVariables.GOPRIVATE = lib.concatStringsSep "," cfg.goPrivate;
})
home.file."Library/Application Support/go/env" = {
enable = pkgs.stdenv.hostPlatform.isDarwin;
source = keyValueFormat.generate "go-env" finalEnv;
};
})
(mkIf (cfg.telemetry.mode != null) {
home.file."Library/Application Support/go/telemetry/mode" = {
enable = pkgs.stdenv.hostPlatform.isDarwin;
text = modeFileContent;
};
(mkIf (cfg.telemetry.mode != null) {
home.file."Library/Application Support/go/telemetry/mode" = {
enable = pkgs.stdenv.hostPlatform.isDarwin;
text = modeFileContent;
};
xdg.configFile."go/telemetry/mode" = {
enable = !pkgs.stdenv.hostPlatform.isDarwin;
text = modeFileContent;
};
})
]
);
xdg.configFile."go/telemetry/mode" = {
enable = !pkgs.stdenv.hostPlatform.isDarwin;
text = modeFileContent;
};
})
]
);
}