Make two-way variable replacement case-insensitive

The conversion from a known path prefix to a variable is now done in a
case-insensitive way. This means that if the variable `{storage}` has
value `S:\Flamenco`, a path `s:\flamenco\project\file.blend` will be
recognised and replaced with `{storage}\project\file.blend`.

This happens uniformly, regardless of the platform. So also on Linux,
which has a case-sensitive filesystem, this matching is done in a
case-insensitive way. It is very unlikely that a Flamenco configuration
has two separate variables, for paths that only differ in their case.

Fixes: #104336 Drive letter case mismatch causes two way variables not
to work correctly
This commit is contained in:
Sybren A. Stüvel 2025-02-14 18:44:50 +01:00
parent fb65e55c98
commit 3fb73c6c9a
2 changed files with 31 additions and 1 deletions

View File

@ -50,11 +50,15 @@ func (c *Conf) NewVariableExpander(audience VariableAudience, platform VariableP
// ValueToVariableReplacer replaces any variable values it recognises in
// valueToConvert to the actual variable. For example, `/path/to/file.blend` can
// be changed to `{my_storage}/file.blend`.
//
// Matching is done in a case-insensitive way on all platforms, because some
// filesystems are case-insensitive. It is very unlikely that there will be two
// variables for two paths, only differing in their case.
func (vvc *ValueToVariableReplacer) Replace(valueToConvert string) string {
result := valueToConvert
for varName, varValue := range vvc.twoWayVars {
if !isValueMatch(result, varValue) {
if !isValueMatch(strings.ToLower(result), strings.ToLower(varValue)) {
continue
}
result = vvc.join(varName, result[len(varValue):])

View File

@ -50,3 +50,29 @@ func TestExpandTwowayVariablesMixedSlashes(t *testing.T) {
assert.Equal(t, `/shared/flamenco/shot/file.blend`, expanderLnx.Expand(`{shared}\shot\file.blend`))
assert.Equal(t, `/shared/flamenco/shot/file.blend`, expanderLnx.Expand(`{shared}/shot/file.blend`))
}
func TestReplaceTwowayVariablesMixedCase(t *testing.T) {
c := DefaultConfig(func(c *Conf) {
c.Variables["shared"] = Variable{
IsTwoWay: true,
Values: []VariableValue{
{Value: "/shared/flamenco", Platform: VariablePlatformLinux},
{Value: `Y:\shared\flamenco`, Platform: VariablePlatformWindows},
},
}
})
replacerWin := c.NewVariableToValueConverter(VariableAudienceWorkers, VariablePlatformWindows)
// Both uppercase and lowercase drive letter should match.
assert.Equal(t, `{shared}\shot\file.blend`, replacerWin.Replace(`y:\shared\flamenco\shot\file.blend`),
"Lower-case drive letter should match")
assert.Equal(t, `{shared}\shot\file.blend`, replacerWin.Replace(`Y:\shared\flamenco\shot\file.blend`),
"Same-case drive letter should match")
// Both uppercase and lowercase path should match.
assert.Equal(t, `{shared}\shot\file.blend`, replacerWin.Replace(`Y:\SHARED\flamenco\shot\file.blend`),
"Upper case 1st directory component should match")
assert.Equal(t, `{shared}\SHOT\file.blend`, replacerWin.Replace(`Y:\shared\FLAMENCO\SHOT\file.blend`),
"Upper case 2nd directory component should match")
}