service/dap: Add support for empty string in substitutePath (#3088)
This changes adds the support to replace relative paths sources with "" as rapresenting current directory.
For example:
Rule like '{from: "", to: "/my/project"}' will map path "src/my/code.go" into "/my/project/src/my/code.go"
Rule like '{from: "/my/project", to: ""}' will map path "/my/project/src/my/code.go" into "src/my/code.go"
Fixes #3082
This commit is contained in:
parent
f82d225bdb
commit
20df19e33b
@ -41,6 +41,7 @@ func SplitQuotedFields(in string, quote rune) []string {
|
|||||||
} else if unicode.IsSpace(ch) {
|
} else if unicode.IsSpace(ch) {
|
||||||
r = append(r, buf.String())
|
r = append(r, buf.String())
|
||||||
buf.Reset()
|
buf.Reset()
|
||||||
|
state = inSpace
|
||||||
} else {
|
} else {
|
||||||
buf.WriteRune(ch)
|
buf.WriteRune(ch)
|
||||||
}
|
}
|
||||||
@ -60,7 +61,7 @@ func SplitQuotedFields(in string, quote rune) []string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if buf.Len() != 0 {
|
if state == inField || buf.Len() != 0 {
|
||||||
r = append(r, buf.String())
|
r = append(r, buf.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -21,18 +21,52 @@ func TestSplitQuotedFields(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSplitDoubleQuotedFields(t *testing.T) {
|
func TestSplitDoubleQuotedFields(t *testing.T) {
|
||||||
in := `field"A" "fieldB" fie"l'd"C "field\"D" "yet another field"`
|
tests := []struct {
|
||||||
tgt := []string{"fieldA", "fieldB", "fiel'dC", "field\"D", "yet another field"}
|
name string
|
||||||
out := SplitQuotedFields(in, '"')
|
in string
|
||||||
|
expected []string
|
||||||
if len(tgt) != len(out) {
|
}{
|
||||||
t.Fatalf("expected %#v, got %#v (len mismatch)", tgt, out)
|
{
|
||||||
|
name: "generic test case",
|
||||||
|
in: `field"A" "fieldB" fie"l'd"C "field\"D" "yet another field"`,
|
||||||
|
expected: []string{"fieldA", "fieldB", "fiel'dC", "field\"D", "yet another field"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "with empty string in the end",
|
||||||
|
in: `field"A" "" `,
|
||||||
|
expected: []string{"fieldA", ""},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "with empty string at the beginning",
|
||||||
|
in: ` "" field"A"`,
|
||||||
|
expected: []string{"", "fieldA"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "lots of spaces",
|
||||||
|
in: ` field"A" `,
|
||||||
|
expected: []string{"fieldA"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "only empty string",
|
||||||
|
in: ` "" "" "" """" "" `,
|
||||||
|
expected: []string{"", "", "", "", ""},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
in := tt.in
|
||||||
|
tgt := tt.expected
|
||||||
|
out := SplitQuotedFields(in, '"')
|
||||||
|
if len(tgt) != len(out) {
|
||||||
|
t.Fatalf("expected %#v, got %#v (len mismatch)", tgt, out)
|
||||||
|
}
|
||||||
|
|
||||||
for i := range tgt {
|
for i := range tgt {
|
||||||
if tgt[i] != out[i] {
|
if tgt[i] != out[i] {
|
||||||
t.Fatalf(" expected %#v, got %#v (mismatch at %d)", tgt, out, i)
|
t.Fatalf(" expected %#v, got %#v (mismatch at %d)", tgt, out, i)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -498,13 +498,19 @@ func SubstitutePath(path string, rules [][2]string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise check if it's a directory prefix.
|
// Otherwise check if it's a directory prefix.
|
||||||
if !strings.HasSuffix(from, separator) {
|
if from != "" && !strings.HasSuffix(from, separator) {
|
||||||
from = from + separator
|
from = from + separator
|
||||||
}
|
}
|
||||||
if !strings.HasSuffix(to, separator) {
|
if to != "" && !strings.HasSuffix(to, separator) {
|
||||||
to = to + separator
|
to = to + separator
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(path, from) {
|
|
||||||
|
// Expand relative paths with the specified prefix
|
||||||
|
if from == "" && !filepath.IsAbs(path) {
|
||||||
|
return strings.Replace(path, from, to, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if from != "" && strings.HasPrefix(path, from) {
|
||||||
return strings.Replace(path, from, to, 1)
|
return strings.Replace(path, from, to, 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package locspec
|
package locspec
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -66,3 +67,57 @@ func TestFunctionLocationParsing(t *testing.T) {
|
|||||||
assertNormalLocationSpec(t, "github.com/go-delve/delve/pkg/proc.Process.Continue:10", NormalLocationSpec{"github.com/go-delve/delve/pkg/proc.Process.Continue", &FuncLocationSpec{PackageName: "github.com/go-delve/delve/pkg/proc", ReceiverName: "Process", BaseName: "Continue"}, 10})
|
assertNormalLocationSpec(t, "github.com/go-delve/delve/pkg/proc.Process.Continue:10", NormalLocationSpec{"github.com/go-delve/delve/pkg/proc.Process.Continue", &FuncLocationSpec{PackageName: "github.com/go-delve/delve/pkg/proc", ReceiverName: "Process", BaseName: "Continue"}, 10})
|
||||||
assertNormalLocationSpec(t, "github.com/go-delve/delve/pkg/proc.Continue:10", NormalLocationSpec{"github.com/go-delve/delve/pkg/proc.Continue", &FuncLocationSpec{PackageName: "github.com/go-delve/delve/pkg/proc", BaseName: "Continue"}, 10})
|
assertNormalLocationSpec(t, "github.com/go-delve/delve/pkg/proc.Continue:10", NormalLocationSpec{"github.com/go-delve/delve/pkg/proc.Continue", &FuncLocationSpec{PackageName: "github.com/go-delve/delve/pkg/proc", BaseName: "Continue"}, 10})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func assertSubstitutePathEqual(t *testing.T, expected string, substituted string) {
|
||||||
|
if expected != substituted {
|
||||||
|
t.Fatalf("Expected substitutedPath to be %s got %s instead", expected, substituted)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSubstitutePathUnix(t *testing.T) {
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
t.Skip("Skipping unix SubstitutePath test in windows")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Relative paths mapping
|
||||||
|
assertSubstitutePathEqual(t, "/my/asb/folder/relative/path", SubstitutePath("relative/path", [][2]string{{"", "/my/asb/folder/"}}))
|
||||||
|
assertSubstitutePathEqual(t, "/already/abs/path", SubstitutePath("/already/abs/path", [][2]string{{"", "/my/asb/folder/"}}))
|
||||||
|
assertSubstitutePathEqual(t, "relative/path", SubstitutePath("/my/asb/folder/relative/path", [][2]string{{"/my/asb/folder/", ""}}))
|
||||||
|
assertSubstitutePathEqual(t, "/another/folder/relative/path", SubstitutePath("/another/folder/relative/path", [][2]string{{"/my/asb/folder/", ""}}))
|
||||||
|
assertSubstitutePathEqual(t, "my/path", SubstitutePath("relative/path/my/path", [][2]string{{"relative/path", ""}}))
|
||||||
|
assertSubstitutePathEqual(t, "/abs/my/path", SubstitutePath("/abs/my/path", [][2]string{{"abs/my", ""}}))
|
||||||
|
|
||||||
|
// Absolute paths mapping
|
||||||
|
assertSubstitutePathEqual(t, "/new/mapping/path", SubstitutePath("/original/path", [][2]string{{"/original", "/new/mapping"}}))
|
||||||
|
assertSubstitutePathEqual(t, "/no/change/path", SubstitutePath("/no/change/path", [][2]string{{"/original", "/new/mapping"}}))
|
||||||
|
assertSubstitutePathEqual(t, "/folder/should_not_be_replaced/path", SubstitutePath("/folder/should_not_be_replaced/path", [][2]string{{"should_not_be_replaced", ""}}))
|
||||||
|
|
||||||
|
// Mix absolute and relative mapping
|
||||||
|
assertSubstitutePathEqual(t, "/new/mapping/path", SubstitutePath("/original/path", [][2]string{{"", "/my/asb/folder/"}, {"/my/asb/folder/", ""}, {"/original", "/new/mapping"}}))
|
||||||
|
assertSubstitutePathEqual(t, "/my/asb/folder/path", SubstitutePath("path", [][2]string{{"/original", "/new/mapping"}, {"", "/my/asb/folder/"}, {"/my/asb/folder/", ""}}))
|
||||||
|
assertSubstitutePathEqual(t, "path", SubstitutePath("/my/asb/folder/path", [][2]string{{"/original", "/new/mapping"}, {"/my/asb/folder/", ""}, {"", "/my/asb/folder/"}}))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSubstitutePathWindows(t *testing.T) {
|
||||||
|
if runtime.GOOS != "windows" {
|
||||||
|
t.Skip("Skipping windows SubstitutePath test in unix")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Relative paths mapping
|
||||||
|
assertSubstitutePathEqual(t, "c:\\my\\asb\\folder\\relative\\path", SubstitutePath("relative\\path", [][2]string{{"", "c:\\my\\asb\\folder\\"}}))
|
||||||
|
assertSubstitutePathEqual(t, "f:\\already\\abs\\path", SubstitutePath("F:\\already\\abs\\path", [][2]string{{"", "c:\\my\\asb\\folder\\"}}))
|
||||||
|
assertSubstitutePathEqual(t, "relative\\path", SubstitutePath("C:\\my\\asb\\folder\\relative\\path", [][2]string{{"c:\\my\\asb\\folder\\", ""}}))
|
||||||
|
assertSubstitutePathEqual(t, "f:\\another\\folder\\relative\\path", SubstitutePath("F:\\another\\folder\\relative\\path", [][2]string{{"c:\\my\\asb\\folder\\", ""}}))
|
||||||
|
assertSubstitutePathEqual(t, "my\\path", SubstitutePath("relative\\path\\my\\path", [][2]string{{"relative\\path", ""}}))
|
||||||
|
assertSubstitutePathEqual(t, "c:\\abs\\my\\path", SubstitutePath("c:\\abs\\my\\path", [][2]string{{"abs\\my", ""}}))
|
||||||
|
|
||||||
|
// Absolute paths mapping
|
||||||
|
assertSubstitutePathEqual(t, "c:\\new\\mapping\\path", SubstitutePath("D:\\original\\path", [][2]string{{"d:\\original", "c:\\new\\mapping"}}))
|
||||||
|
assertSubstitutePathEqual(t, "f:\\no\\change\\path", SubstitutePath("F:\\no\\change\\path", [][2]string{{"d:\\original", "c:\\new\\mapping"}}))
|
||||||
|
assertSubstitutePathEqual(t, "c:\\folder\\should_not_be_replaced\\path", SubstitutePath("c:\\folder\\should_not_be_replaced\\path", [][2]string{{"should_not_be_replaced", ""}}))
|
||||||
|
|
||||||
|
// Mix absolute and relative mapping
|
||||||
|
assertSubstitutePathEqual(t, "c:\\new\\mapping\\path", SubstitutePath("D:\\original\\path", [][2]string{{"", "c:\\my\\asb\\folder\\"}, {"c:\\my\\asb\\folder\\", ""}, {"d:\\original", "c:\\new\\mapping"}}))
|
||||||
|
assertSubstitutePathEqual(t, "c:\\my\\asb\\folder\\path\\", SubstitutePath("path\\", [][2]string{{"d:\\original", "c:\\new\\mapping"}, {"", "c:\\my\\asb\\folder\\"}, {"c:\\my\\asb\\folder\\", ""}}))
|
||||||
|
assertSubstitutePathEqual(t, "path", SubstitutePath("C:\\my\\asb\\folder\\path", [][2]string{{"d:\\original", "c:\\new\\mapping"}, {"c:\\my\\asb\\folder\\", ""}, {"", "c:\\my\\asb\\folder\\"}}))
|
||||||
|
}
|
||||||
|
|||||||
@ -95,6 +95,74 @@ func TestConfigureSetSubstitutePath(t *testing.T) {
|
|||||||
},
|
},
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "add rule from empty string",
|
||||||
|
args: args{
|
||||||
|
args: &launchAttachArgs{
|
||||||
|
substitutePathClientToServer: [][2]string{},
|
||||||
|
substitutePathServerToClient: [][2]string{},
|
||||||
|
},
|
||||||
|
rest: `"" /path/to/client/dir`,
|
||||||
|
},
|
||||||
|
wantRules: [][2]string{{"", "/path/to/client/dir"}},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "add rule to empty string",
|
||||||
|
args: args{
|
||||||
|
args: &launchAttachArgs{
|
||||||
|
substitutePathClientToServer: [][2]string{},
|
||||||
|
substitutePathServerToClient: [][2]string{},
|
||||||
|
},
|
||||||
|
rest: `/path/to/client/dir ""`,
|
||||||
|
},
|
||||||
|
wantRules: [][2]string{{"/path/to/client/dir", ""}},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "add rule from empty string(multiple)",
|
||||||
|
args: args{
|
||||||
|
args: &launchAttachArgs{
|
||||||
|
substitutePathClientToServer: [][2]string{
|
||||||
|
{"/path/to/client/dir/a", "/path/to/server/dir/a"},
|
||||||
|
{"/path/to/client/dir/b", "/path/to/server/dir/b"},
|
||||||
|
},
|
||||||
|
substitutePathServerToClient: [][2]string{
|
||||||
|
{"/path/to/server/dir/a", "/path/to/client/dir/a"},
|
||||||
|
{"/path/to/server/dir/b", "/path/to/client/dir/b"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rest: `"" /path/to/client/dir/c`,
|
||||||
|
},
|
||||||
|
wantRules: [][2]string{
|
||||||
|
{"/path/to/client/dir/a", "/path/to/server/dir/a"},
|
||||||
|
{"/path/to/client/dir/b", "/path/to/server/dir/b"},
|
||||||
|
{"", "/path/to/client/dir/c"},
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "add rule to empty string(multiple)",
|
||||||
|
args: args{
|
||||||
|
args: &launchAttachArgs{
|
||||||
|
substitutePathClientToServer: [][2]string{
|
||||||
|
{"/path/to/client/dir/a", "/path/to/server/dir/a"},
|
||||||
|
{"/path/to/client/dir/b", "/path/to/server/dir/b"},
|
||||||
|
},
|
||||||
|
substitutePathServerToClient: [][2]string{
|
||||||
|
{"/path/to/server/dir/a", "/path/to/client/dir/a"},
|
||||||
|
{"/path/to/server/dir/b", "/path/to/client/dir/b"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rest: `/path/to/client/dir/c ""`,
|
||||||
|
},
|
||||||
|
wantRules: [][2]string{
|
||||||
|
{"/path/to/client/dir/a", "/path/to/server/dir/a"},
|
||||||
|
{"/path/to/client/dir/b", "/path/to/server/dir/b"},
|
||||||
|
{"/path/to/client/dir/c", ""},
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
// Test modify rule.
|
// Test modify rule.
|
||||||
{
|
{
|
||||||
name: "modify rule",
|
name: "modify rule",
|
||||||
@ -108,6 +176,30 @@ func TestConfigureSetSubstitutePath(t *testing.T) {
|
|||||||
wantRules: [][2]string{{"/path/to/client/dir", "/new/path/to/server/dir"}},
|
wantRules: [][2]string{{"/path/to/client/dir", "/new/path/to/server/dir"}},
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "modify rule with from as empty string",
|
||||||
|
args: args{
|
||||||
|
args: &launchAttachArgs{
|
||||||
|
substitutePathClientToServer: [][2]string{{"", "/path/to/server/dir"}},
|
||||||
|
substitutePathServerToClient: [][2]string{{"/path/to/server/dir", ""}},
|
||||||
|
},
|
||||||
|
rest: `"" /new/path/to/server/dir`,
|
||||||
|
},
|
||||||
|
wantRules: [][2]string{{"", "/new/path/to/server/dir"}},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "modify rule with to as empty string",
|
||||||
|
args: args{
|
||||||
|
args: &launchAttachArgs{
|
||||||
|
substitutePathClientToServer: [][2]string{{"/path/to/client/dir", ""}},
|
||||||
|
substitutePathServerToClient: [][2]string{{"", "/path/to/client/dir"}},
|
||||||
|
},
|
||||||
|
rest: `/path/to/client/dir ""`,
|
||||||
|
},
|
||||||
|
wantRules: [][2]string{{"/path/to/client/dir", ""}},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "modify rule (multiple)",
|
name: "modify rule (multiple)",
|
||||||
args: args{
|
args: args{
|
||||||
@ -132,6 +224,54 @@ func TestConfigureSetSubstitutePath(t *testing.T) {
|
|||||||
},
|
},
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "modify rule with from as empty string(multiple)",
|
||||||
|
args: args{
|
||||||
|
args: &launchAttachArgs{
|
||||||
|
substitutePathClientToServer: [][2]string{
|
||||||
|
{"/path/to/client/dir/a", "/path/to/server/dir/a"},
|
||||||
|
{"", "/path/to/server/dir/b"},
|
||||||
|
{"/path/to/client/dir/c", "/path/to/server/dir/b"},
|
||||||
|
},
|
||||||
|
substitutePathServerToClient: [][2]string{
|
||||||
|
{"/path/to/server/dir/a", "/path/to/client/dir/a"},
|
||||||
|
{"/path/to/server/dir/b", ""},
|
||||||
|
{"/path/to/server/dir/b", "/path/to/client/dir/c"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rest: `"" /new/path`,
|
||||||
|
},
|
||||||
|
wantRules: [][2]string{
|
||||||
|
{"/path/to/client/dir/a", "/path/to/server/dir/a"},
|
||||||
|
{"", "/new/path"},
|
||||||
|
{"/path/to/client/dir/c", "/path/to/server/dir/b"},
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "modify rule with to as empty string(multiple)",
|
||||||
|
args: args{
|
||||||
|
args: &launchAttachArgs{
|
||||||
|
substitutePathClientToServer: [][2]string{
|
||||||
|
{"/path/to/client/dir/a", "/path/to/server/dir/a"},
|
||||||
|
{"/path/to/client/dir/b", "/path/to/server/dir/b"},
|
||||||
|
{"/path/to/client/dir/c", "/path/to/server/dir/b"},
|
||||||
|
},
|
||||||
|
substitutePathServerToClient: [][2]string{
|
||||||
|
{"/path/to/server/dir/a", "/path/to/client/dir/a"},
|
||||||
|
{"/path/to/server/dir/b", "/path/to/client/dir/b"},
|
||||||
|
{"/path/to/server/dir/b", "/path/to/client/dir/c"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rest: `/path/to/client/dir/b ""`,
|
||||||
|
},
|
||||||
|
wantRules: [][2]string{
|
||||||
|
{"/path/to/client/dir/a", "/path/to/server/dir/a"},
|
||||||
|
{"/path/to/client/dir/b", ""},
|
||||||
|
{"/path/to/client/dir/c", "/path/to/server/dir/b"},
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
// Test delete rule.
|
// Test delete rule.
|
||||||
{
|
{
|
||||||
name: "delete rule",
|
name: "delete rule",
|
||||||
@ -145,6 +285,18 @@ func TestConfigureSetSubstitutePath(t *testing.T) {
|
|||||||
wantRules: [][2]string{},
|
wantRules: [][2]string{},
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "delete rule, empty string",
|
||||||
|
args: args{
|
||||||
|
args: &launchAttachArgs{
|
||||||
|
substitutePathClientToServer: [][2]string{{"", "/path/to/server/dir"}},
|
||||||
|
substitutePathServerToClient: [][2]string{{"/path/to/server/dir", ""}},
|
||||||
|
},
|
||||||
|
rest: `""`,
|
||||||
|
},
|
||||||
|
wantRules: [][2]string{},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
// Test invalid input.
|
// Test invalid input.
|
||||||
{
|
{
|
||||||
name: "error on empty args",
|
name: "error on empty args",
|
||||||
|
|||||||
@ -189,7 +189,9 @@ type LaunchAttachCommonConfig struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SubstitutePath defines a mapping from a local path to the remote path.
|
// SubstitutePath defines a mapping from a local path to the remote path.
|
||||||
// Both 'from' and 'to' must be specified and non-empty.
|
// Both 'from' and 'to' must be specified and non-null.
|
||||||
|
// Empty values can be used to add or remove absolute path prefixes when mapping.
|
||||||
|
// For example, mapping with empy 'to' can be used to work with binaries with trimmed paths.
|
||||||
type SubstitutePath struct {
|
type SubstitutePath struct {
|
||||||
// The local path to be replaced when passing paths to the debugger.
|
// The local path to be replaced when passing paths to the debugger.
|
||||||
From string `json:"from,omitempty"`
|
From string `json:"from,omitempty"`
|
||||||
@ -199,7 +201,10 @@ type SubstitutePath struct {
|
|||||||
|
|
||||||
func (m *SubstitutePath) UnmarshalJSON(data []byte) error {
|
func (m *SubstitutePath) UnmarshalJSON(data []byte) error {
|
||||||
// use custom unmarshal to check if both from/to are set.
|
// use custom unmarshal to check if both from/to are set.
|
||||||
type tmpType SubstitutePath
|
type tmpType struct {
|
||||||
|
From *string
|
||||||
|
To *string
|
||||||
|
}
|
||||||
var tmp tmpType
|
var tmp tmpType
|
||||||
|
|
||||||
if err := json.Unmarshal(data, &tmp); err != nil {
|
if err := json.Unmarshal(data, &tmp); err != nil {
|
||||||
@ -208,10 +213,10 @@ func (m *SubstitutePath) UnmarshalJSON(data []byte) error {
|
|||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if tmp.From == "" || tmp.To == "" {
|
if tmp.From == nil || tmp.To == nil {
|
||||||
return errors.New("'substitutePath' requires both 'from' and 'to' entries")
|
return errors.New("'substitutePath' requires both 'from' and 'to' entries")
|
||||||
}
|
}
|
||||||
*m = SubstitutePath(tmp)
|
*m = SubstitutePath{*tmp.From, *tmp.To}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user