Fix #404: nil map error when reading env file #405

Merged
wolfogre merged 2 commits from :fix-nil-map-reading-env-file into main 2023-11-24 01:56:27 +00:00
Contributor
No description provided.
infinoid added 1 commit 2023-11-16 15:26:27 +00:00
Fix #404: nil map error when reading env file
All checks were successful
checks / check and test (pull_request) Successful in 1m25s
6d85fd69ab
lunny requested review from wolfogre 2023-11-17 06:03:17 +00:00
Owner

I think it would be more clear to fix it by:

	if cfg.Runner.EnvFile != "" {
		if stat, err := os.Stat(cfg.Runner.EnvFile); err == nil && !stat.IsDir() {
			envs, err := godotenv.Read(cfg.Runner.EnvFile)
			if err != nil {
				return nil, fmt.Errorf("read env file %q: %w", cfg.Runner.EnvFile, err)
			}
+            if cfg.Runner.Envs == nil {
+            	cfg.Runner.Envs = map[string]string{}
+            }
			for k, v := range envs {
				cfg.Runner.Envs[k] = v
			}
		}
	}
I think it would be more clear to fix it by: ```diff if cfg.Runner.EnvFile != "" { if stat, err := os.Stat(cfg.Runner.EnvFile); err == nil && !stat.IsDir() { envs, err := godotenv.Read(cfg.Runner.EnvFile) if err != nil { return nil, fmt.Errorf("read env file %q: %w", cfg.Runner.EnvFile, err) } + if cfg.Runner.Envs == nil { + cfg.Runner.Envs = map[string]string{} + } for k, v := range envs { cfg.Runner.Envs[k] = v } } } ```
Author
Contributor
+            if cfg.Runner.Envs == nil {
+            	cfg.Runner.Envs = map[string]string{}
+            }

Yeah, that's an option, I mentioned it in #404. I decided not to do it that way because then, the map is only initialized when EnvFile is set. I wondered if there would be other problems with the nil map later on. I chose to initialize it up-front because that way it is always initialized.

So I'm curious, why is it clearer that way? I think that "map is always valid; sometimes written into by yaml, sometimes written into by envfile" is clearer than "sometimes initialized by yaml, sometimes initialized by envfile, sometimes nil". I guess by "clearer" I mean "requires less guesswork".

But you're much more familiar with the project than I am. So if you still think the conditional approach is better, I will happily update the PR.

> ```diff > + if cfg.Runner.Envs == nil { > + cfg.Runner.Envs = map[string]string{} > + } > ``` Yeah, that's an option, I mentioned it in #404. I decided not to do it that way because then, the map is only initialized when EnvFile is set. I wondered if there would be other problems with the nil map later on. I chose to initialize it up-front because that way it is *always* initialized. So I'm curious, why is it clearer that way? I think that "map is always valid; sometimes written into by yaml, sometimes written into by envfile" is clearer than "sometimes initialized by yaml, sometimes initialized by envfile, sometimes nil". I guess by "clearer" I mean "requires less guesswork". But you're much more familiar with the project than I am. So if you still think the conditional approach is better, I will happily update the PR.
Owner

Just my opinion.

When developers see cfg := &Config{Runner: Runner{Envs: map[string]string{}}}, the question may come to their mind: why should we initialize the Envs map? If I want to add a new map field, should I initialize it too?
I think it could be clearer:

+            if cfg.Runner.Envs == nil {
+            	cfg.Runner.Envs = map[string]string{}
+            }
			for k, v := range envs {
				cfg.Runner.Envs[k] = v
			}

because it's easy to understand that we initialize Envs to prepare it for adding more items and to avoid panic.

If both envs and env_file are empty, I think it's OK to keep Envs as nil.

Just my opinion. When developers see `cfg := &Config{Runner: Runner{Envs: map[string]string{}}}`, the question may come to their mind: why should we initialize the `Envs` map? If I want to add a new map field, should I initialize it too? I think it could be clearer: ```diff + if cfg.Runner.Envs == nil { + cfg.Runner.Envs = map[string]string{} + } for k, v := range envs { cfg.Runner.Envs[k] = v } ``` because it's easy to understand that we initialize `Envs` to prepare it for adding more items and to avoid panic. If both `envs` and `env_file` are empty, I think it's OK to keep `Envs` as nil.
infinoid force-pushed fix-nil-map-reading-env-file from 6d85fd69ab to 3621f2824f 2023-11-22 10:50:07 +00:00 Compare
Author
Contributor

Ok, thanks. I have updated the PR.

Your opinion is interesting, thanks for sharing it. I personally always initialize maps in all cases; I see it as just part of the overhead of having a map. That way I never have to worry about nils later on.

So when I see cfg := &Config{}, the question comes to my mind: "why wasn't the Envs map initialized? Is that going to crash later when someone writes to it?" But now I see that this approach is not universal.

Ok, thanks. I have updated the PR. Your opinion is interesting, thanks for sharing it. I personally always initialize maps in all cases; I see it as just part of the overhead of having a map. That way I never have to worry about `nil`s later on. So when I see `cfg := &Config{}`, the question comes to my mind: "why wasn't the `Envs` map initialized? Is that going to crash later when someone writes to it?" But now I see that this approach is not universal.
wolfogre approved these changes 2023-11-24 01:43:52 +00:00
wolfogre added 1 commit 2023-11-24 01:43:58 +00:00
Merge branch 'main' into fix-nil-map-reading-env-file
All checks were successful
checks / check and test (pull_request) Successful in 56s
c41ede2e4d
wolfogre merged commit 934471813a into main 2023-11-24 01:56:27 +00:00
infinoid deleted branch fix-nil-map-reading-env-file 2023-11-24 09:35:44 +00:00
Sign in to join this conversation.
No description provided.