diff --git a/addon/flamenco/operators.py b/addon/flamenco/operators.py index 093173a0..7a979230 100644 --- a/addon/flamenco/operators.py +++ b/addon/flamenco/operators.py @@ -307,7 +307,9 @@ class FLAMENCO_OT_submit_job(FlamencoOpMixin, bpy.types.Operator): ), ) - return checkout_root / blendfile.name # TODO: get relative to the checkout dir. + # Having Shaman enabled on the Manager automatically creates a variable + # "jobs" that will resolve to the checkout directory. + return PurePosixPath("{jobs}") / checkout_root / blendfile.name def _on_bat_pack_msg(self, context: bpy.types.Context, msg: _Message) -> set[str]: from .bat import interface as bat_interface diff --git a/internal/manager/api_impl/varrepl_test.go b/internal/manager/api_impl/varrepl_test.go index 46647133..02c0dbfa 100644 --- a/internal/manager/api_impl/varrepl_test.go +++ b/internal/manager/api_impl/varrepl_test.go @@ -3,6 +3,7 @@ package api_impl // SPDX-License-Identifier: GPL-3.0-or-later import ( + "path" "testing" "github.com/stretchr/testify/assert" @@ -95,3 +96,20 @@ func TestReplacePathsUnknownOS(t *testing.T) { ) assert.Equal(t, "{hey}/haha", replacedTask.Commands[2].Parameters["otherpath"]) } + +func TestReplaceJobsVariable(t *testing.T) { + worker := persistence.Worker{Platform: "linux"} + + // Having the Shaman enabled should create an implicit variable "{jobs}". + conf := config.GetTestConfig(func(c *config.Conf) { + c.Shaman.Enabled = true + c.Shaman.StoragePath = "/path/to/shaman/storage" + }) + + task := varreplTestTask() + task.Commands[2].Parameters["filepath"] = "{jobs}/path/in/shaman.blend" + + replacedTask := replaceTaskVariables(&conf, task, worker) + expectPath := path.Join(conf.Shaman.CheckoutPath(), "path/in/shaman.blend") + assert.Equal(t, expectPath, replacedTask.Commands[2].Parameters["filepath"]) +} diff --git a/internal/manager/config/settings.go b/internal/manager/config/settings.go index 8044fbdd..43f0c4f2 100644 --- a/internal/manager/config/settings.go +++ b/internal/manager/config/settings.go @@ -8,6 +8,7 @@ import ( "io" "os" "path" + "path/filepath" "runtime" "strings" "time" @@ -180,6 +181,7 @@ func DefaultConfig(override ...func(c *Conf)) Conf { for _, overrideFunc := range override { overrideFunc(&c) } + c.addImplicitVariables() c.constructVariableLookupTable(zerolog.TraceLevel) return c } @@ -222,6 +224,7 @@ func loadConf(filename string, overrides ...func(c *Conf)) (Conf, error) { overrideFunc(&c) } + c.addImplicitVariables() c.constructVariableLookupTable(zerolog.DebugLevel) c.parseURLs() c.checkDatabase() @@ -231,6 +234,31 @@ func loadConf(filename string, overrides ...func(c *Conf)) (Conf, error) { return c, nil } +func (c *Conf) addImplicitVariables() { + if !c.Shaman.Enabled { + return + } + + // Shaman adds a variable to allow job submission to create + // checkout-dir-relative paths. + shamanCheckoutPath := c.Shaman.CheckoutPath() + absPath, err := filepath.Abs(shamanCheckoutPath) + if err != nil { + log.Error().Err(err).Msg("unable to find absolute path of Shaman checkout path") + absPath = shamanCheckoutPath + } + c.Variables["jobs"] = Variable{ + IsTwoWay: false, + Values: []VariableValue{ + { + Audience: VariableAudienceAll, + Platform: VariablePlatformAll, + Value: absPath, + }, + }, + } +} + func (c *Conf) constructVariableLookupTable(logLevel zerolog.Level) { lookup := map[VariableAudience]map[VariablePlatform]map[string]string{} @@ -330,8 +358,8 @@ func (c *Conf) ExpandVariables(valueToExpand string, audience VariableAudience, } varsForPlatform := map[string]string{} - updateMap(varsForPlatform, platformsForAudience[platform]) updateMap(varsForPlatform, platformsForAudience[VariablePlatformAll]) + updateMap(varsForPlatform, platformsForAudience[platform]) if varsForPlatform == nil { log.Warn(). diff --git a/internal/manager/config/settings_test.go b/internal/manager/config/settings_test.go index b701b235..6220dd71 100644 --- a/internal/manager/config/settings_test.go +++ b/internal/manager/config/settings_test.go @@ -40,3 +40,17 @@ func TestVariableValidation(t *testing.T) { // TODO: Test two-way variables. Even though they're not currently in the // default configuration, they should work. + +func TestShamanImplicitVariables(t *testing.T) { + c := DefaultConfig(func(c *Conf) { + // Having the Shaman enabled should create an implicit variable "{jobs}". + c.Shaman.Enabled = true + c.Shaman.StoragePath = "/path/to/shaman/storage" + }) + + if !assert.Contains(t, c.Variables, "jobs") { + t.FailNow() + } + assert.False(t, c.Variables["jobs"].IsTwoWay) + assert.Equal(t, c.Shaman.CheckoutPath(), c.Variables["jobs"].Values[0].Value) +}