Skip to content

Commit

Permalink
Use encoding/csv to when parsing selector record (#4515)
Browse files Browse the repository at this point in the history
* Use encoding/csv to when parsing selector record

`encoding/csv` allows us to handle selectors with commas in them which
our naive parser embarassingly didn't such as:
```
repository.properties['github/primary_language'] in ['TypeScript', 'Go'
```

Fixes: #4514

* Enable LazyQuotes in the CSV parser to handle uneven quoting

* Use backticks to avoid escaping quotes
  • Loading branch information
jhrozek authored Sep 19, 2024
1 parent 4bd3303 commit 66044f9
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 2 deletions.
8 changes: 7 additions & 1 deletion internal/db/profile_selector_scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package db

import (
"encoding/csv"
"fmt"
"strings"
)
Expand All @@ -37,7 +38,12 @@ func (s *ProfileSelector) Scan(value interface{}) error {
str = strings.TrimSuffix(str, ")")

// Split the string by commas to get the individual field values
parts := strings.Split(str, ",")
cr := csv.NewReader(strings.NewReader(str))
cr.LazyQuotes = true // Enable LazyQuotes to allow for uneven number of quotes
parts, err := cr.Read()
if err != nil {
return fmt.Errorf("failed to scan SelectorInfo: %v", err)
}

// Assign the values to the struct fields
if len(parts) != 5 {
Expand Down
33 changes: 32 additions & 1 deletion internal/db/profile_selector_scan_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ import (
"github.com/stretchr/testify/assert"
)

// TestScan tests the Scan method of the ProfileSelector struct
// for more tests that exercise the retrieval of a profile with selectors that also happens to use Scan
// see TestProfileListWithSelectors
func TestScan(t *testing.T) {
t.Parallel()

Expand All @@ -35,7 +38,7 @@ func TestScan(t *testing.T) {
}{
{
name: "Valid input with all fields",
input: []byte(fmt.Sprintf("(%s,%s,repository,\"entity.name == \"\"test/test\"\" && repository.is_fork != true\",\"comment1\")", selectorId, profileId)),
input: []byte(fmt.Sprintf(`(%s,%s,repository,"entity.name == ""test/test"" && repository.is_fork != true","comment1")`, selectorId, profileId)),
expected: ProfileSelector{
ID: selectorId,
ProfileID: profileId,
Expand All @@ -47,6 +50,34 @@ func TestScan(t *testing.T) {
Comment: "comment1",
},
},
{
name: "Valid input with commas in the selector",
input: []byte(fmt.Sprintf(`(%s,%s,repository,"repository.properties['github/primary_language'] in ['TypeScript', 'Go']","comment1")`, selectorId, profileId)),
expected: ProfileSelector{
ID: selectorId,
ProfileID: profileId,
Entity: NullEntities{
Valid: true,
Entities: EntitiesRepository,
},
Selector: "repository.properties['github/primary_language'] in ['TypeScript', 'Go']",
Comment: "comment1",
},
},
{
name: "Comment includes uneven quotes",
input: []byte(fmt.Sprintf(`(%s,%s,repository,"repository.name == foo",""comment1")`, selectorId, profileId)),
expected: ProfileSelector{
ID: selectorId,
ProfileID: profileId,
Entity: NullEntities{
Valid: true,
Entities: EntitiesRepository,
},
Selector: "repository.name == foo",
Comment: "comment1",
},
},
}

for _, tc := range tc {
Expand Down

0 comments on commit 66044f9

Please sign in to comment.