1
0
Fork 0
mirror of https://github.com/nix-community/home-manager.git synced 2025-11-08 19:46:05 +01:00

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";
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 = ''
Primary {env}`GOPATH` relative to
{env}`HOME`. It will be exported first and therefore
used by default by the Go tooling.
Controls which modules the 'go' command considers to be private (not
available publicly) and should therefore not use the proxy or checksum database.
'';
};
extraGoPaths = mkOption {
type = types.listOf types.str;
default = [ ];
example = [
"extraGoPath1"
"extraGoPath2"
};
};
default = { };
example = lib.literalExpression ''
{
GOPATH = [
"''${config.home.homeDirectory}/mygo"
"/another/go"
"/yet/another/go"
];
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 = [
GOPRIVATE = [
"*.corp.example.com"
"rsc.io/private"
];
CXX = "g++";
GCCGO = "gccgo";
GOAMD64 = "v1";
GOARCH = "amd64";
GOAUTH = "netrc";
};
'';
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,33 +138,43 @@ in
};
};
config = mkIf cfg.enable (
config =
let
firstGoPath = lib.elemAt (lib.splitString ":" cfg.env.GOPATH) 0;
finalEnv = lib.filterAttrs (_: v: v != "") cfg.env;
in
mkIf cfg.enable (
lib.mkMerge [
{
home.packages = [ cfg.package ];
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 =
home.file = mkIf (cfg.packages != { }) (
let
goPath = if cfg.goPath != null then cfg.goPath else "go";
mkSrc = n: v: { "${goPath}/src/${n}".source = v; };
mainGoPath = if (cfg.env.GOPATH != "") then firstGoPath else "go";
mkSrc = n: v: { "${mainGoPath}/src/${n}".source = v; };
in
lib.foldl' (a: b: a // b) { } (lib.mapAttrsToList mkSrc cfg.packages);
lib.foldl' (a: b: a // b) { } (lib.mapAttrsToList mkSrc cfg.packages)
);
}
(mkIf (cfg.goPath != null) {
home.sessionVariables.GOPATH = lib.concatStringsSep ":" (
map builtins.toPath (
map (path: "${config.home.homeDirectory}/${path}") ([ cfg.goPath ] ++ cfg.extraGoPaths)
)
);
})
(mkIf (cfg.env != { }) {
xdg.configFile."go/env" = {
enable = !pkgs.stdenv.hostPlatform.isDarwin;
source = keyValueFormat.generate "go-env" finalEnv;
};
(mkIf (cfg.goBin != null) {
home.sessionVariables.GOBIN = builtins.toPath "${config.home.homeDirectory}/${cfg.goBin}";
})
(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) {

View file

@ -1 +1,9 @@
{ go-telemetry = ./go-telemetry.nix; }
{
go-telemetry = ./go-telemetry.nix;
go-example-config = ./example-config.nix;
go-suboptions-unset = ./suboptions-unset.nix;
go-packages-default-gopath = ./packages-default-gopath.nix;
go-packages-custom-gopath = ./packages-custom-gopath.nix;
go-packages-invalid-main-gopath = ./packages-invalid-main-gopath.nix;
go-old-options = ./old-options.nix;
}

View file

@ -0,0 +1,7 @@
CXX=g++
GCCGO=gccgo
GOAMD64=v1
GOARCH=amd64
GOAUTH=netrc
GOPATH=/home/hm-user/mygo:/another/go:/yet/another/go
GOPRIVATE=*.corp.example.com,rsc.io/private

View file

@ -0,0 +1,3 @@
GOBIN=/home/hm-user/.local/bin.go
GOPATH=/home/hm-user/mygo:/home/hm-user/another/go:/home/hm-user/yet/another/go
GOPRIVATE=*.corp.example.com,rsc.io/private

View file

@ -0,0 +1,5 @@
CXX=g++
GCCGO=gccgo
GOAMD64=v1
GOARCH=amd64
GOAUTH=netrc

View file

@ -0,0 +1,33 @@
{ pkgs, config, ... }:
{
programs.go = {
enable = true;
env = {
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";
};
};
nmt.script =
let
goCfgDir = if !pkgs.stdenv.isDarwin then ".config/go" else "Library/Application Support/go";
in
''
assertFileExists "home-files/${goCfgDir}/env"
assertFileContent "home-files/${goCfgDir}/env" \
${./env}
'';
}

View file

@ -0,0 +1,40 @@
{
lib,
options,
pkgs,
config,
...
}:
{
programs.go = {
enable = true;
goPath = "mygo";
extraGoPaths = [
"another/go"
"yet/another/go"
];
goBin = ".local/bin.go";
goPrivate = [
"*.corp.example.com"
"rsc.io/private"
];
};
test.asserts.warnings.expected = [
"The option `programs.go.goPrivate' defined in ${lib.showFiles options.programs.go.goPrivate.files} has been renamed to `programs.go.env.GOPRIVATE'."
"The option `programs.go.goBin' defined in ${lib.showFiles options.programs.go.goBin.files} has been changed to `programs.go.env.GOBIN' that has a different type. Please read `programs.go.env.GOBIN' documentation and update your configuration accordingly."
"The option `programs.go.extraGoPaths' defined in ${lib.showFiles options.programs.go.extraGoPaths.files} has been changed to `programs.go.env.GOPATH' that has a different type. Please read `programs.go.env.GOPATH' documentation and update your configuration accordingly."
"The option `programs.go.goPath' defined in ${lib.showFiles options.programs.go.goPath.files} has been changed to `programs.go.env.GOPATH' that has a different type. Please read `programs.go.env.GOPATH' documentation and update your configuration accordingly."
];
nmt.script =
let
goCfgDir = if !pkgs.stdenv.isDarwin then ".config/go" else "Library/Application\ Support/go";
in
''
assertFileExists "home-files/${goCfgDir}/env"
assertFileContent "home-files/${goCfgDir}/env" \
${./env-old-options}
'';
}

View file

@ -0,0 +1,22 @@
{ config, ... }:
{
programs.go = {
enable = true;
env.GOPATH = [
"${config.home.homeDirectory}/mygo"
"/another/go"
"/yet/another/go"
];
packages = {
"golang.org/x/text" = ./packages/text;
"golang.org/x/time" = ./packages/time;
};
};
nmt.script = ''
assertFileExists home-files/mygo/src/golang.org/x/text/main.go
assertFileExists home-files/mygo/src/golang.org/x/time/main.go
'';
}

View file

@ -0,0 +1,14 @@
{
programs.go = {
enable = true;
packages = {
"golang.org/x/text" = ./packages/text;
"golang.org/x/time" = ./packages/time;
};
};
nmt.script = ''
assertFileExists home-files/go/src/golang.org/x/text/main.go
assertFileExists home-files/go/src/golang.org/x/time/main.go
'';
}

View file

@ -0,0 +1,20 @@
{ config, ... }:
{
programs.go = {
enable = true;
env.GOPATH = [
"/not/my/home/mygo"
"/another/go"
"/yet/another/go"
];
packages = {
"golang.org/x/text" = ./packages/text;
"golang.org/x/time" = ./packages/time;
};
};
test.asserts.assertions.expected = [
"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."
];
}

View file

@ -0,0 +1,7 @@
package main
import "fmt"
func main() {
fmt.Println("Hello Home-Manager from 'text'!")
}

View file

@ -0,0 +1,7 @@
package main
import "fmt"
func main() {
fmt.Println("Hello Home-Manager from 'time'!")
}

View file

@ -0,0 +1,24 @@
{ pkgs, config, ... }:
{
programs.go = {
enable = true;
env = {
CXX = "g++";
GCCGO = "gccgo";
GOAMD64 = "v1";
GOARCH = "amd64";
GOAUTH = "netrc";
};
};
nmt.script =
let
goCfgDir = if !pkgs.stdenv.isDarwin then ".config/go" else "Library/Application\ Support/go";
in
''
assertFileExists "home-files/${goCfgDir}/env"
assertFileContent "home-files/${goCfgDir}/env" \
${./env-suboptions-unset}
'';
}