databricks-cli/bundle/artifacts/expand_globs.go

110 lines
2.4 KiB
Go

package artifacts
import (
"context"
"fmt"
"path/filepath"
"github.com/databricks/cli/bundle"
"github.com/databricks/cli/libs/diag"
"github.com/databricks/cli/libs/dyn"
)
type expandGlobs struct {
name string
}
func (m *expandGlobs) Name() string {
return fmt.Sprintf("artifacts.ExpandGlobs(%s)", m.name)
}
func createGlobError(v dyn.Value, p dyn.Path, message string) diag.Diagnostic {
// The pattern contained in v is an absolute path.
// Make it relative to the value's location to make it more readable.
source := v.MustString()
if l := v.Location(); l.File != "" {
rel, err := filepath.Rel(filepath.Dir(l.File), source)
if err == nil {
source = rel
}
}
return diag.Diagnostic{
Severity: diag.Error,
Summary: fmt.Sprintf("%s: %s", source, message),
LocationPathPairs: []diag.LocationPathPair{
{
L: v.Location(),
P: p,
},
},
}
}
func (m *expandGlobs) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics {
// Base path for this mutator.
// This path is set with the list of expanded globs when done.
base := dyn.NewPath(
dyn.Key("artifacts"),
dyn.Key(m.name),
dyn.Key("files"),
)
// Pattern to match the source key in the files sequence.
pattern := dyn.NewPatternFromPath(base).Append(
dyn.AnyIndex(),
dyn.Key("source"),
)
var diags diag.Diagnostics
err := b.Config.Mutate(func(v dyn.Value) (dyn.Value, error) {
var output []dyn.Value
_, err := dyn.MapByPattern(v, pattern, func(p dyn.Path, v dyn.Value) (dyn.Value, error) {
if v.Kind() != dyn.KindString {
return v, nil
}
source := v.MustString()
// Expand any glob reference in files source path
matches, err := filepath.Glob(source)
if err != nil {
diags = diags.Append(createGlobError(v, p, err.Error()))
// Continue processing and leave this value unchanged.
return v, nil
}
if len(matches) == 0 {
diags = diags.Append(createGlobError(v, p, "no matching files"))
// Continue processing and leave this value unchanged.
return v, nil
}
for _, match := range matches {
output = append(output, dyn.V(
map[string]dyn.Value{
"source": dyn.NewValue(match, v.Locations()),
},
))
}
return v, nil
})
if err != nil || diags.HasError() {
return v, err
}
// Set the expanded globs back into the configuration.
return dyn.SetByPath(v, base, dyn.V(output))
})
if err != nil {
return diag.FromErr(err)
}
return diags
}