From 9acce5071f2093d02eb8a485fbe2c8ff6e92c958 Mon Sep 17 00:00:00 2001 From: Adrian Pronk Date: Sat, 24 Jul 2021 12:40:14 +1200 Subject: [PATCH 1/4] plumbing: config, Branch name with hash can be cloned. Fixes #309 --- plumbing/format/config/encoder.go | 2 +- plumbing/format/config/fixtures_test.go | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/plumbing/format/config/encoder.go b/plumbing/format/config/encoder.go index 4eac8968a..93dad1a56 100644 --- a/plumbing/format/config/encoder.go +++ b/plumbing/format/config/encoder.go @@ -59,7 +59,7 @@ func (e *Encoder) encodeSubsection(sectionName string, s *Subsection) error { func (e *Encoder) encodeOptions(opts Options) error { for _, o := range opts { pattern := "\t%s = %s\n" - if strings.Contains(o.Value, "\\") { + if strings.ContainsAny(o.Value, `"#\"`) || strings.HasPrefix(o.Value, " ") || strings.HasSuffix(o.Value, " ") { pattern = "\t%s = %q\n" } diff --git a/plumbing/format/config/fixtures_test.go b/plumbing/format/config/fixtures_test.go index f3533dfee..3255213a1 100644 --- a/plumbing/format/config/fixtures_test.go +++ b/plumbing/format/config/fixtures_test.go @@ -42,6 +42,24 @@ var fixtures = []*Fixture{ Text: "[core]\n\trepositoryformatversion = 0\n", Config: New().AddOption("core", "", "repositoryformatversion", "0"), }, + { + Raw: "[section]\n", + Text: `[section] + option1 = "has # hash" + option2 = "has \" quote" + option3 = "has \\ backslash" + option4 = " has leading spaces" + option5 = "has trailing spaces " + option6 = has no special characters +`, + Config: New(). + AddOption("section", "", "option1", `has # hash`). + AddOption("section", "", "option2", `has " quote`). + AddOption("section", "", "option3", `has \ backslash`). + AddOption("section", "", "option4", ` has leading spaces`). + AddOption("section", "", "option5", `has trailing spaces `). + AddOption("section", "", "option6", `has no special characters`), + }, { Raw: ` [sect1] From 437ae96746723ceac4cf6bc5bb730b4f848b79ad Mon Sep 17 00:00:00 2001 From: Adrian Pronk Date: Sat, 24 Jul 2021 12:54:53 +1200 Subject: [PATCH 2/4] plumbing: config, remove duplicated character in set --- plumbing/format/config/encoder.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plumbing/format/config/encoder.go b/plumbing/format/config/encoder.go index 93dad1a56..62921e068 100644 --- a/plumbing/format/config/encoder.go +++ b/plumbing/format/config/encoder.go @@ -59,7 +59,7 @@ func (e *Encoder) encodeSubsection(sectionName string, s *Subsection) error { func (e *Encoder) encodeOptions(opts Options) error { for _, o := range opts { pattern := "\t%s = %s\n" - if strings.ContainsAny(o.Value, `"#\"`) || strings.HasPrefix(o.Value, " ") || strings.HasSuffix(o.Value, " ") { + if strings.ContainsAny(o.Value, `"#\`) || strings.HasPrefix(o.Value, " ") || strings.HasSuffix(o.Value, " ") { pattern = "\t%s = %q\n" } From a55116466586f5396b34f5296abdd7c5e68b98b8 Mon Sep 17 00:00:00 2001 From: Adrian Pronk Date: Sun, 25 Jul 2021 17:58:36 +1200 Subject: [PATCH 3/4] plumbing: config, support correct escaping as per git-config rules --- plumbing/format/config/encoder.go | 17 +++++++++++------ plumbing/format/config/fixtures_test.go | 21 ++++++++++++++------- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/plumbing/format/config/encoder.go b/plumbing/format/config/encoder.go index 62921e068..de069aed5 100644 --- a/plumbing/format/config/encoder.go +++ b/plumbing/format/config/encoder.go @@ -11,6 +11,10 @@ type Encoder struct { w io.Writer } +var ( + subsectionReplacer = strings.NewReplacer(`"`, `\"`, `\`, `\\`) + valueReplacer = strings.NewReplacer(`"`, `\"`, `\`, `\\`, "\n", `\n`, "\t", `\t`, "\b", `\b`) +) // NewEncoder returns a new encoder that writes to w. func NewEncoder(w io.Writer) *Encoder { return &Encoder{w} @@ -48,8 +52,7 @@ func (e *Encoder) encodeSection(s *Section) error { } func (e *Encoder) encodeSubsection(sectionName string, s *Subsection) error { - //TODO: escape - if err := e.printf("[%s \"%s\"]\n", sectionName, s.Name); err != nil { + if err := e.printf("[%s \"%s\"]\n", sectionName, subsectionReplacer.Replace(s.Name)); err != nil { return err } @@ -58,12 +61,14 @@ func (e *Encoder) encodeSubsection(sectionName string, s *Subsection) error { func (e *Encoder) encodeOptions(opts Options) error { for _, o := range opts { - pattern := "\t%s = %s\n" - if strings.ContainsAny(o.Value, `"#\`) || strings.HasPrefix(o.Value, " ") || strings.HasSuffix(o.Value, " ") { - pattern = "\t%s = %q\n" + var value string + if strings.ContainsAny(o.Value, "#;\"\t\n\\") || strings.HasPrefix(o.Value, " ") || strings.HasSuffix(o.Value, " ") { + value = `"`+valueReplacer.Replace(o.Value)+`"` + } else { + value = o.Value } - if err := e.printf(pattern, o.Key, o.Value); err != nil { + if err := e.printf("\t%s = %s\n", o.Key, value); err != nil { return err } } diff --git a/plumbing/format/config/fixtures_test.go b/plumbing/format/config/fixtures_test.go index 3255213a1..899ddf714 100644 --- a/plumbing/format/config/fixtures_test.go +++ b/plumbing/format/config/fixtures_test.go @@ -48,17 +48,24 @@ var fixtures = []*Fixture{ option1 = "has # hash" option2 = "has \" quote" option3 = "has \\ backslash" - option4 = " has leading spaces" - option5 = "has trailing spaces " - option6 = has no special characters -`, + option4 = "has ; semicolon" + option5 = "has \n line-feed" + option6 = "has \t tab" + option7 = " has leading spaces" + option8 = "has trailing spaces " + option9 = has no special characters +`+"\toption10 = has unusual \x01\x7f\xc8\x80 characters\n", Config: New(). AddOption("section", "", "option1", `has # hash`). AddOption("section", "", "option2", `has " quote`). AddOption("section", "", "option3", `has \ backslash`). - AddOption("section", "", "option4", ` has leading spaces`). - AddOption("section", "", "option5", `has trailing spaces `). - AddOption("section", "", "option6", `has no special characters`), + AddOption("section", "", "option4", `has ; semicolon`). + AddOption("section", "", "option5", "has \n line-feed"). + AddOption("section", "", "option6", "has \t tab"). + AddOption("section", "", "option7", ` has leading spaces`). + AddOption("section", "", "option8", `has trailing spaces `). + AddOption("section", "", "option9", `has no special characters`). + AddOption("section", "", "option10", "has unusual \x01\x7f\u0200 characters"), }, { Raw: ` From 4efe4cbee9e0631d92ad91db23f1271058d03a46 Mon Sep 17 00:00:00 2001 From: Adrian Pronk Date: Mon, 26 Jul 2021 08:19:06 +1200 Subject: [PATCH 4/4] plumbing: config, fix broken unit tests --- plumbing/format/config/fixtures_test.go | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/plumbing/format/config/fixtures_test.go b/plumbing/format/config/fixtures_test.go index 899ddf714..2fa7840b0 100644 --- a/plumbing/format/config/fixtures_test.go +++ b/plumbing/format/config/fixtures_test.go @@ -43,8 +43,7 @@ var fixtures = []*Fixture{ Config: New().AddOption("core", "", "repositoryformatversion", "0"), }, { - Raw: "[section]\n", - Text: `[section] + Raw: `[section] option1 = "has # hash" option2 = "has \" quote" option3 = "has \\ backslash" @@ -54,7 +53,18 @@ var fixtures = []*Fixture{ option7 = " has leading spaces" option8 = "has trailing spaces " option9 = has no special characters -`+"\toption10 = has unusual \x01\x7f\xc8\x80 characters\n", + option10 = has unusual ` + "\x01\x7f\xc8\x80 characters\n", + Text: `[section] + option1 = "has # hash" + option2 = "has \" quote" + option3 = "has \\ backslash" + option4 = "has ; semicolon" + option5 = "has \n line-feed" + option6 = "has \t tab" + option7 = " has leading spaces" + option8 = "has trailing spaces " + option9 = has no special characters + option10 = has unusual ` + "\x01\x7f\xc8\x80 characters\n", Config: New(). AddOption("section", "", "option1", `has # hash`). AddOption("section", "", "option2", `has " quote`).