You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@seata.apache.org by te...@apache.org on 2026/09/22 13:45:00 UTC

(incubator-seata-go) branch master updated: fix(config): parse config format from the last filename extension (#1186)

This is an automated email from the ASF dual-hosted git repository.

thunguo pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-seata-go.git


The following commit(s) were added to refs/heads/master by this push:
     new 2ae56fb1 fix(config): parse config format from the last filename extension (#1186)
2ae56fb1 is described below

commit 2ae56fb1bc0e7804b0c4ece8a82ef9eece4d97a5
Author: Cheyne Chen <ch...@outlook.com>
AuthorDate: Tue Sep 22 21:44:54 2026 +0800

    fix(config): parse config format from the last filename extension (#1186)
    
    * fix(config): parse config format from the last filename extension (#1177)
    
    resolverFilePath used the second dot-separated token as the suffix, so
    seatago.prod.yaml was treated as "prod" and LoadPath panicked at startup.
    
    * test(config): reset flags before recover and simplify hidden-file check
    
    Review feedback on #1186: keep flag.CommandLine reset if LoadPath panics, and treat ext == base as no format suffix.
    
    Co-authored-by: Cursor <cu...@cursor.com>
    
    ---------
    
    Co-authored-by: Ethan <xi...@apache.org>
    Co-authored-by: Cursor <cu...@cursor.com>
---
 pkg/client/config.go      | 16 +++++++------
 pkg/client/config_test.go | 57 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 66 insertions(+), 7 deletions(-)

diff --git a/pkg/client/config.go b/pkg/client/config.go
index 9b056093..439b8cc3 100644
--- a/pkg/client/config.go
+++ b/pkg/client/config.go
@@ -165,15 +165,17 @@ func getJsonConfigResolver(bytes []byte) *koanf.Koanf {
 	return k
 }
 
-// resolverFilePath resolver file path
-// eg: give a ./conf/seatago.yaml return seatago and yaml
+// resolverFilePath returns the file name without the last extension, and the last
+// extension in lower case. A missing extension defaults to yaml.
+// e.g. ./conf/seatago.prod.yaml -> ("seatago.prod", "yaml")
 func resolverFilePath(path string) (name, suffix string) {
-	paths := strings.Split(path, "/")
-	fileName := strings.Split(paths[len(paths)-1], ".")
-	if len(fileName) < 2 {
-		return fileName[0], yamlSuffix
+	base := filepath.Base(path)
+	ext := filepath.Ext(base)
+	// filepath.Ext(".seatago") == ".seatago"; treat that as no format suffix.
+	if ext == "" || ext == base {
+		return base, yamlSuffix
 	}
-	return fileName[0], fileName[1]
+	return strings.TrimSuffix(base, ext), strings.ToLower(strings.TrimPrefix(ext, "."))
 }
 
 // getConfigResolver get config resolver
diff --git a/pkg/client/config_test.go b/pkg/client/config_test.go
index e980f30b..897b73be 100644
--- a/pkg/client/config_test.go
+++ b/pkg/client/config_test.go
@@ -20,12 +20,69 @@ package client
 import (
 	"flag"
 	"os"
+	"path/filepath"
 	"testing"
 	"time"
 
 	"github.com/stretchr/testify/assert"
 )
 
+func TestResolverFilePath(t *testing.T) {
+	tests := []struct {
+		name       string
+		path       string
+		wantName   string
+		wantSuffix string
+		skipName   bool
+	}{
+		{name: "single dot yaml", path: "./conf/seatago.yaml", wantName: "seatago", wantSuffix: yamlSuffix},
+		{name: "single dot yml", path: "../../testdata/conf/seatago.yml", wantName: "seatago", wantSuffix: ymlSuffix},
+		{name: "multiple dots yaml", path: "./conf/seatago.prod.yaml", wantName: "seatago.prod", wantSuffix: yamlSuffix},
+		{name: "versioned yml", path: "app.v2.yml", wantName: "app.v2", wantSuffix: ymlSuffix},
+		{name: "json", path: "seatago.json", wantName: "seatago", wantSuffix: jsonSuffix},
+		{name: "toml", path: "seatago.toml", wantName: "seatago", wantSuffix: tomlSuffix},
+		{name: "upper case yaml", path: "seatago.YAML", wantName: "seatago", wantSuffix: yamlSuffix},
+		{name: "upper case yml", path: "seatago.YML", wantName: "seatago", wantSuffix: ymlSuffix},
+		{name: "upper case json", path: "config.JSON", wantName: "config", wantSuffix: jsonSuffix},
+		{name: "upper case toml", path: "config.TOML", wantName: "config", wantSuffix: tomlSuffix},
+		{name: "no extension", path: "seatago", wantName: "seatago", wantSuffix: yamlSuffix},
+		{name: "no extension in dir", path: "./conf/seatago", wantName: "seatago", wantSuffix: yamlSuffix},
+		{name: "hidden yaml", path: ".seatago.yaml", wantName: ".seatago", wantSuffix: yamlSuffix},
+		{name: "hidden no extra extension", path: ".seatago", wantName: ".seatago", wantSuffix: yamlSuffix},
+		{name: "windows style yaml", path: `C:\conf\seatago.prod.yaml`, wantSuffix: yamlSuffix, skipName: true},
+		{name: "windows style yml", path: `C:\conf\seatago.yml`, wantSuffix: ymlSuffix, skipName: true},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			gotName, gotSuffix := resolverFilePath(tt.path)
+			if !tt.skipName {
+				assert.Equal(t, tt.wantName, gotName)
+			}
+			assert.Equal(t, tt.wantSuffix, gotSuffix)
+		})
+	}
+}
+
+func TestLoadPath_FilenameWithMultipleDots(t *testing.T) {
+	src, err := os.ReadFile("../../testdata/conf/seatago.yml")
+	assert.NoError(t, err)
+
+	path := filepath.Join(t.TempDir(), "seatago.prod.yaml")
+	assert.NoError(t, os.WriteFile(path, src, 0o600))
+
+	defer func() {
+		flag.CommandLine = flag.NewFlagSet(os.Args[0], flag.ExitOnError)
+		if r := recover(); r != nil {
+			t.Fatalf("valid .yaml filename panicked: %v", r)
+		}
+	}()
+
+	cfg := LoadPath(path)
+	assert.NotNil(t, cfg)
+	assert.Equal(t, "applicationName", cfg.ApplicationID)
+}
+
 func TestLoadPath(t *testing.T) {
 	cfg := LoadPath("../../testdata/conf/seatago.yml")
 	assert.NotNil(t, cfg)


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@seata.apache.org
For additional commands, e-mail: notifications-help@seata.apache.org