@@ -54,6 +54,11 @@ func InitConfig(dir string, writer io.Writer) (created bool, err error) {
54
54
Commit : plansdk .DefaultNixpkgsCommit ,
55
55
},
56
56
}
57
+ if featureflag .EnvConfig .Enabled () {
58
+ // TODO: after removing feature flag we can decide if we want
59
+ // to have omitempty for Env in Config or not.
60
+ config .Env = map [string ]string {}
61
+ }
57
62
// package suggestion
58
63
pkgsToSuggest , err := initrec .Get (dir )
59
64
if err != nil {
@@ -517,12 +522,11 @@ func (d *Devbox) GenerateDockerfile(force bool) error {
517
522
}
518
523
519
524
// generates a .envrc file that makes direnv integration convenient
520
- func (d * Devbox ) GenerateEnvrc (force bool ) error {
525
+ func (d * Devbox ) GenerateEnvrc (force bool , source string ) error {
521
526
envrcfilePath := filepath .Join (d .projectDir , ".envrc" )
522
527
filesExist := fileutil .Exists (envrcfilePath )
523
528
// confirm .envrc doesn't exist and don't overwrite an existing .envrc
524
529
if force || ! filesExist {
525
- // .envrc file creation
526
530
if commandExists ("direnv" ) {
527
531
// prompt for direnv allow
528
532
var result string
@@ -535,17 +539,22 @@ func (d *Devbox) GenerateEnvrc(force bool) error {
535
539
}
536
540
537
541
if strings .ToLower (result ) == "y" {
538
- if ! filesExist { // don't overwrite an existing .envrc
539
- err := generate .CreateEnvrc (tmplFS , d .projectDir )
540
- if err != nil {
541
- return errors .WithStack (err )
542
- }
542
+ // .envrc file creation
543
+ err := generate .CreateEnvrc (tmplFS , d .projectDir )
544
+ if err != nil {
545
+ return errors .WithStack (err )
543
546
}
544
547
cmd := exec .Command ("direnv" , "allow" )
545
548
err = cmd .Run ()
546
549
if err != nil {
547
550
return errors .WithStack (err )
548
551
}
552
+ } else if source == "generate" {
553
+ // .envrc file creation
554
+ err := generate .CreateEnvrc (tmplFS , d .projectDir )
555
+ if err != nil {
556
+ return errors .WithStack (err )
557
+ }
549
558
}
550
559
}
551
560
} else {
@@ -747,6 +756,13 @@ func (d *Devbox) computeNixEnv() (map[string]string, error) {
747
756
748
757
env ["PATH" ] = fmt .Sprintf ("%s:%s:%s:%s" , pluginVirtenvPath , nixProfilePath , nixPath , hostPath )
749
758
759
+ if featureflag .EnvConfig .Enabled () {
760
+ // Include env variables in config
761
+ for k , v := range d .configEnvs (env ) {
762
+ env [k ] = v
763
+ }
764
+ }
765
+
750
766
return env , nil
751
767
}
752
768
@@ -881,6 +897,35 @@ func (d *Devbox) pluginVirtenvPath() string {
881
897
return filepath .Join (d .projectDir , plugin .VirtenvBinPath )
882
898
}
883
899
900
+ // configEnvs takes the computed env variables (nix + plugin) and adds env
901
+ // variables defined in Config. It also parses variables in config
902
+ // that are referenced by $VAR or ${VAR} and replaces them with
903
+ // their value in the computed env variables. Note, this doesn't
904
+ // allow env variables from outside the shell to be referenced so
905
+ // no leaked variables are caused by this function.
906
+ func (d * Devbox ) configEnvs (computedEnv map [string ]string ) map [string ]string {
907
+ mapperfunc := func (value string ) string {
908
+ // Special variables that should return correct value
909
+ switch value {
910
+ case "PWD" :
911
+ return d .ProjectDir ()
912
+ }
913
+ // check if referenced variables exists in computed environment
914
+ if v , ok := computedEnv [value ]; ok {
915
+ return v
916
+ }
917
+ return ""
918
+ }
919
+ configEnvs := map [string ]string {}
920
+ // Include env variables in config
921
+ for key , value := range d .cfg .Env {
922
+ // parse values for "$VAR" or "${VAR}"
923
+ parsedValue := os .Expand (value , mapperfunc )
924
+ configEnvs [key ] = parsedValue
925
+ }
926
+ return configEnvs
927
+ }
928
+
884
929
// Move to a utility package?
885
930
func IsDevboxShellEnabled () bool {
886
931
inDevboxShell , err := strconv .ParseBool (os .Getenv ("DEVBOX_SHELL_ENABLED" ))
0 commit comments