github.com/ddev/ddev@v1.23.2-0.20240519125000-d824ffe36ff3/pkg/ddevapp/envfile.go (about)

     1  package ddevapp
     2  
     3  import (
     4  	"fmt"
     5  	"regexp"
     6  	"strings"
     7  
     8  	"github.com/ddev/ddev/pkg/fileutil"
     9  	"github.com/joho/godotenv"
    10  )
    11  
    12  // ReadProjectEnvFile reads the .env in the project root into a envText and envMap
    13  // The map has the envFile content, but without comments
    14  func ReadProjectEnvFile(envFilePath string) (envMap map[string]string, envText string, err error) {
    15  	// envFilePath := filepath.Join(app.AppRoot, ".env")
    16  	envText, _ = fileutil.ReadFileIntoString(envFilePath)
    17  	envMap, err = godotenv.Read(envFilePath)
    18  
    19  	return envMap, envText, err
    20  }
    21  
    22  // WriteProjectEnvFile writes the passed envText into the project-root .env file
    23  // with all items in envMap changed in envText there
    24  func WriteProjectEnvFile(envFilePath string, envMap map[string]string, envText string) error {
    25  	// envFilePath := filepath.Join(app.AppRoot, ".env")
    26  	for k, v := range envMap {
    27  		// If the item is already in envText, use regex to replace it
    28  		// otherwise, append it to the envText.
    29  		// (^|[\r\n]+) - first group $1 matches the start of a line or newline characters
    30  		// #*\s* - matches optional comments with whitespaces, i.e. find lines like '# FOO=BAR'
    31  		// (%s) - second group $2 matches the variable name
    32  		exp := regexp.MustCompile(fmt.Sprintf(`(^|[\r\n]+)#*\s*(%s)=(.*)`, k))
    33  		if exp.MatchString(envText) {
    34  			// Remove comments with whitespaces here using only $1 and $2 groups
    35  			envText = exp.ReplaceAllString(envText, fmt.Sprintf(`$1$2="%s"`, v))
    36  		} else {
    37  			envText = strings.TrimSuffix(envText, "\n")
    38  			envText = fmt.Sprintf("%s\n%s=%s\n", envText, k, v)
    39  		}
    40  	}
    41  	err := fileutil.TemplateStringToFile(envText, nil, envFilePath)
    42  	if err != nil {
    43  		return err
    44  	}
    45  	return nil
    46  }