diff --git a/lib/transform/transform.go b/lib/transform/transform.go index 0ae81cea5..6428f58b9 100644 --- a/lib/transform/transform.go +++ b/lib/transform/transform.go @@ -165,13 +165,13 @@ func transformPathSegment(s string, t transform) (string, error) { if err != nil { return s, err } - return truncateChars(s, max, false), nil + return truncateChars(s, max, false) case ConvTruncateKeepExtension: max, err := strconv.Atoi(t.value) if err != nil { return s, err } - return truncateChars(s, max, true), nil + return truncateChars(s, max, true) case ConvTruncateBytes: max, err := strconv.Atoi(t.value) if err != nil { @@ -266,19 +266,23 @@ func splitExtension(remote string) (base, exts string) { return base, exts } -func truncateChars(s string, max int, keepExtension bool) string { +func truncateChars(s string, max int, keepExtension bool) (string, error) { if max <= 0 { - return s + return s, nil } if utf8.RuneCountInString(s) <= max { - return s + return s, nil } exts := "" if keepExtension { s, exts = splitExtension(s) } + keep := max - utf8.RuneCountInString(exts) + if keep <= 0 { + return "", errors.New("extension is longer than the truncation limit") + } runes := []rune(s) - return string(runes[:max-utf8.RuneCountInString(exts)]) + exts + return string(runes[:keep]) + exts, nil } // truncateBytes is like truncateChars but counts the number of bytes, not UTF-8 characters diff --git a/lib/transform/transform_test.go b/lib/transform/transform_test.go index c10eaf1b9..9dc7ec74d 100644 --- a/lib/transform/transform_test.go +++ b/lib/transform/transform_test.go @@ -134,6 +134,9 @@ func TestVarious(t *testing.T) { {"stories/Вот русское предложение, в котором байтов больше, чем символов.txt", "stories/Вот русское предложение, в котором бай", []string{"truncate_bytes=70"}}, {"stories/Вот русское предложение, в котором байтов больше, чем символов.txt", "stories/Вот русское предложение, в котором байтов больше, чем си.txt", []string{"truncate_keep_extension=60"}}, {"stories/Вот русское предложение, в котором байтов больше, чем символов.txt", "stories/Вот русское предложение, в котором б.txt", []string{"truncate_bytes_keep_extension=70"}}, + // the extension alone exceeds the limit, so there is nothing valid to return + {"stories/photo.jpeg", "stories/photo.jpeg", []string{"all,truncate_keep_extension=3"}}, + {"stories/a.tar.gz", "stories/a.tar.gz", []string{"all,truncate_keep_extension=2"}}, {"stories/The Quick Brown Fox!.txt", "stories/The Quick Brown Fox!.txt", []string{"all,command=echo"}}, {"stories/The Quick Brown Fox!.txt", "stories/The Quick Brown Fox!.txt-" + time.Now().Local().Format("20060102"), []string{"date=-{YYYYMMDD}"}}, {"stories/The Quick Brown Fox!.txt", "stories/The Quick Brown Fox!.txt-" + time.Now().Local().Format("2006-01-02 0304PM"), []string{"date=-{macfriendlytime}"}},