Merge pull request #7477 from cli/jtpetty/issue-7024-take-2

Updated to sanitize asset filename prior to uploading. Fixes #7024
This commit is contained in:
Mislav Marohnić 2023-05-23 11:18:12 +02:00 committed by GitHub
commit 9846af16eb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 82 additions and 1 deletions

View file

@ -4,6 +4,7 @@ import (
"context"
"fmt"
"net/http"
"regexp"
"strings"
"github.com/MakeNowJust/heredoc"
@ -93,8 +94,9 @@ func uploadRun(opts *UploadOptions) error {
var existingNames []string
for _, a := range opts.Assets {
sanitizedFileName := sanitizeFileName(a.Name)
for _, ea := range release.Assets {
if ea.Name == a.Name {
if ea.Name == sanitizedFileName {
a.ExistingURL = ea.APIURL
existingNames = append(existingNames, ea.Name)
break
@ -122,3 +124,30 @@ func uploadRun(opts *UploadOptions) error {
return nil
}
// this method attempts to mimic the same functionality on the client that the platform does on
// uploaded assets in order to allow the --clobber logic work correctly, since that feature is
// one that only exists in the client
func sanitizeFileName(name string) string {
value := text.RemoveDiacritics(name)
// Stripped all non-ascii characters, provide default name.
if strings.HasPrefix(value, ".") {
value = "default" + value
}
// Replace special characters with the separator
value = regexp.MustCompile(`(?i)[^a-z0-9\-_\+@]+`).ReplaceAllLiteralString(value, ".")
// No more than one of the separator in a row.
value = regexp.MustCompile(`\.{2,}`).ReplaceAllLiteralString(value, ".")
// Remove leading/trailing separator.
value = strings.Trim(value, ".")
// Just file extension left, add default name.
if name != value && !strings.Contains(value, ".") {
value = "default." + value
}
return value
}

View file

@ -0,0 +1,52 @@
package upload
import (
"testing"
"github.com/stretchr/testify/assert"
)
func Test_SanitizeFileName(t *testing.T) {
tests := []struct {
name string
expected string
}{
{
name: "foo",
expected: "foo",
},
{
name: "foo bar",
expected: "foo.bar",
},
{
name: ".foo",
expected: "default.foo",
},
{
name: "Foo bar",
expected: "Foo.bar",
},
{
name: "Hello, दुनिया",
expected: "default.Hello",
},
{
name: "this+has+plusses.jpg",
expected: "this+has+plusses.jpg",
},
{
name: "this@has@at@signs.jpg",
expected: "this@has@at@signs.jpg",
},
{
name: "façade.exposé",
expected: "facade.expose",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.Equal(t, tt.expected, sanitizeFileName(tt.name))
})
}
}