From bb62df6374f16060df98713edb8bc1a6ce801520 Mon Sep 17 00:00:00 2001 From: "denis.bilenko" Date: Thu, 5 Nov 2026 11:23:38 +0000 Subject: [PATCH 1/3] Print forward-slash paths in errors on Windows; drop backslash Repls Convert local paths to forward slashes with filepath.ToSlash in user-facing messages (diagnostic locations, YAML/JSON load errors, variable overrides file errors, glob errors, duplicate library names, sync root errors, git root errors, filer errors) and in diff.py output. Remove acceptance Repls that normalized backslashes and are no longer needed. Co-authored-by: Isaac --- acceptance/apps/init/auth-mode/test.toml | 5 ----- acceptance/apps/init/binding-values/test.toml | 5 ----- acceptance/bin/diff.py | 8 ++++---- .../bundle/artifacts/globs_in_files/test.toml | 4 ---- .../bundle/artifacts/globs_invalid/test.toml | 4 ---- .../bundle/artifacts/nil_artifacts/test.toml | 4 ---- .../artifacts/same_name_libraries/test.toml | 4 ---- .../bundle/deploy/mlops-stacks/test.toml | 3 +-- .../bundle/generate/genie_space/test.toml | 4 ---- .../includes/glob_in_root_path/test.toml | 3 --- .../integration_whl/serverless/test.toml | 4 ---- .../serverless_dynamic_version/test.toml | 4 ---- .../paths/outside_root_no_sync/test.toml | 3 --- .../test.toml | 3 --- .../bundle/syncroot/dotdot-git/test.toml | 3 --- .../templates-machinery/wrong-url/test.toml | 4 ---- .../serverless-customcatalog/test.toml | 5 ----- acceptance/bundle/validate/targets/test.toml | 4 ---- .../overrides_file_complex_path/test.toml | 4 ---- .../yaml_anchors/cycle_nested/test.toml | 3 --- .../bundle/validate/yaml_anchors/test.toml | 4 ---- .../validate/yaml_duplicate_keys/test.toml | 4 ---- .../bundle/variables/file-defaults/test.toml | 4 ---- acceptance/cmd/auth/docker/host/test.toml | 3 --- .../fs/cp/file-to-nonexistent-dir/test.toml | 5 ----- acceptance/selftest/diff/test.toml | 3 --- bundle/artifacts/expand_globs.go | 2 +- bundle/config/loader/process_root_includes.go | 2 +- bundle/config/mutator/set_variables.go | 4 ++-- bundle/config/mutator/translate_paths.go | 2 +- bundle/config/root.go | 7 ++++--- bundle/libraries/same_name_libraries.go | 2 +- libs/diag/location.go | 3 ++- libs/filer/errors.go | 19 +++++++++++-------- libs/git/view.go | 2 +- 35 files changed, 29 insertions(+), 118 deletions(-) delete mode 100644 acceptance/bundle/includes/glob_in_root_path/test.toml delete mode 100644 acceptance/bundle/paths/outside_root_no_sync/test.toml delete mode 100644 acceptance/bundle/paths/pipelines_root_path_outside_sync_root/test.toml delete mode 100644 acceptance/bundle/syncroot/dotdot-git/test.toml delete mode 100644 acceptance/bundle/validate/targets/test.toml delete mode 100644 acceptance/bundle/validate/yaml_anchors/cycle_nested/test.toml delete mode 100644 acceptance/bundle/validate/yaml_anchors/test.toml delete mode 100644 acceptance/bundle/validate/yaml_duplicate_keys/test.toml delete mode 100644 acceptance/bundle/variables/file-defaults/test.toml delete mode 100644 acceptance/cmd/auth/docker/host/test.toml delete mode 100644 acceptance/selftest/diff/test.toml diff --git a/acceptance/apps/init/auth-mode/test.toml b/acceptance/apps/init/auth-mode/test.toml index b7713e67a70..18b1a88417e 100644 --- a/acceptance/apps/init/auth-mode/test.toml +++ b/acceptance/apps/init/auth-mode/test.toml @@ -1,6 +1 @@ Cloud = false - -[[Repls]] -# Fix path with reverse slashes in the output for Windows. -Old = 'TEST_TMP_DIR]\\(app-[a-z-]+)' -New = 'TEST_TMP_DIR]/${1}' diff --git a/acceptance/apps/init/binding-values/test.toml b/acceptance/apps/init/binding-values/test.toml index b7713e67a70..18b1a88417e 100644 --- a/acceptance/apps/init/binding-values/test.toml +++ b/acceptance/apps/init/binding-values/test.toml @@ -1,6 +1 @@ Cloud = false - -[[Repls]] -# Fix path with reverse slashes in the output for Windows. -Old = 'TEST_TMP_DIR]\\(app-[a-z-]+)' -New = 'TEST_TMP_DIR]/${1}' diff --git a/acceptance/bin/diff.py b/acceptance/bin/diff.py index 93c75ef882b..dbdcf313569 100755 --- a/acceptance/bin/diff.py +++ b/acceptance/bin/diff.py @@ -16,8 +16,8 @@ def main(): patterns = compile_repls() if d1.is_dir() and d2.is_dir(): - files1 = [str(p.relative_to(d1)) for p in d1.rglob("*") if p.is_file() and not p.name.startswith("LOG")] - files2 = [str(p.relative_to(d2)) for p in d2.rglob("*") if p.is_file() and not p.name.startswith("LOG")] + files1 = [p.relative_to(d1).as_posix() for p in d1.rglob("*") if p.is_file() and not p.name.startswith("LOG")] + files2 = [p.relative_to(d2).as_posix() for p in d2.rglob("*") if p.is_file() and not p.name.startswith("LOG")] else: assert d1.is_file(), d1 assert d2.is_file(), d2 @@ -31,9 +31,9 @@ def main(): p1 = d1 / f p2 = d2 / f if f not in set2: - print(f"Only in {d1}: {f}") + print(f"Only in {d1.as_posix()}: {f}") elif f not in set1: - print(f"Only in {d2}: {f}") + print(f"Only in {d2.as_posix()}: {f}") else: diff_files(patterns, p1, p2) diff --git a/acceptance/bundle/artifacts/globs_in_files/test.toml b/acceptance/bundle/artifacts/globs_in_files/test.toml index 3b639e6af69..93ee159927b 100644 --- a/acceptance/bundle/artifacts/globs_in_files/test.toml +++ b/acceptance/bundle/artifacts/globs_in_files/test.toml @@ -3,7 +3,3 @@ RecordRequests = false [[Repls]] Old = '\\\\' New = '/' - -[[Repls]] -Old = '\\' -New = '/' diff --git a/acceptance/bundle/artifacts/globs_invalid/test.toml b/acceptance/bundle/artifacts/globs_invalid/test.toml index 3b639e6af69..93ee159927b 100644 --- a/acceptance/bundle/artifacts/globs_invalid/test.toml +++ b/acceptance/bundle/artifacts/globs_invalid/test.toml @@ -3,7 +3,3 @@ RecordRequests = false [[Repls]] Old = '\\\\' New = '/' - -[[Repls]] -Old = '\\' -New = '/' diff --git a/acceptance/bundle/artifacts/nil_artifacts/test.toml b/acceptance/bundle/artifacts/nil_artifacts/test.toml index 93ee159927b..a030353d571 100644 --- a/acceptance/bundle/artifacts/nil_artifacts/test.toml +++ b/acceptance/bundle/artifacts/nil_artifacts/test.toml @@ -1,5 +1 @@ RecordRequests = false - -[[Repls]] -Old = '\\\\' -New = '/' diff --git a/acceptance/bundle/artifacts/same_name_libraries/test.toml b/acceptance/bundle/artifacts/same_name_libraries/test.toml index a17f2659f23..a030353d571 100644 --- a/acceptance/bundle/artifacts/same_name_libraries/test.toml +++ b/acceptance/bundle/artifacts/same_name_libraries/test.toml @@ -1,5 +1 @@ RecordRequests = false - -[[Repls]] -Old = '\\' -New = '/' diff --git a/acceptance/bundle/deploy/mlops-stacks/test.toml b/acceptance/bundle/deploy/mlops-stacks/test.toml index 68270828373..cbf253f7d13 100644 --- a/acceptance/bundle/deploy/mlops-stacks/test.toml +++ b/acceptance/bundle/deploy/mlops-stacks/test.toml @@ -14,7 +14,6 @@ Ignore = [ Old = "aws|azure|gcp" New = "[CLOUD_ENV_BASE]" -# $TESTDIR uses backslashes on Windows, hence the either-separator match. [[Repls]] -Old = 'bundle init .*[\\/]mlops-stacks/template' +Old = 'bundle init .*/mlops-stacks/template' New = "bundle init mlops-stacks" diff --git a/acceptance/bundle/generate/genie_space/test.toml b/acceptance/bundle/generate/genie_space/test.toml index 3e2bd6b3e12..7336116c281 100644 --- a/acceptance/bundle/generate/genie_space/test.toml +++ b/acceptance/bundle/generate/genie_space/test.toml @@ -1,9 +1,5 @@ Env.MSYS_NO_PATHCONV = "1" -[[Repls]] -Old = '\\\\' -New = '/' - [[Repls]] Old = "[0-9a-f]{32}" New = "[GENIE_SPACE_ID]" diff --git a/acceptance/bundle/includes/glob_in_root_path/test.toml b/acceptance/bundle/includes/glob_in_root_path/test.toml deleted file mode 100644 index a298217f218..00000000000 --- a/acceptance/bundle/includes/glob_in_root_path/test.toml +++ /dev/null @@ -1,3 +0,0 @@ -[[Repls]] -Old = '\\' -New = '/' diff --git a/acceptance/bundle/integration_whl/serverless/test.toml b/acceptance/bundle/integration_whl/serverless/test.toml index 46ee804dba7..49993e0c2d7 100644 --- a/acceptance/bundle/integration_whl/serverless/test.toml +++ b/acceptance/bundle/integration_whl/serverless/test.toml @@ -1,6 +1,2 @@ CloudSlow = true # serverless is only enabled if UC is enabled - -[[Repls]] -Old = '\\' -New = '/' diff --git a/acceptance/bundle/integration_whl/serverless_dynamic_version/test.toml b/acceptance/bundle/integration_whl/serverless_dynamic_version/test.toml index 920da59d1d7..98a0a7d7e84 100644 --- a/acceptance/bundle/integration_whl/serverless_dynamic_version/test.toml +++ b/acceptance/bundle/integration_whl/serverless_dynamic_version/test.toml @@ -1,5 +1 @@ # serverless is only enabled if UC is enabled - -[[Repls]] -Old = '\\' -New = '/' diff --git a/acceptance/bundle/paths/outside_root_no_sync/test.toml b/acceptance/bundle/paths/outside_root_no_sync/test.toml deleted file mode 100644 index a298217f218..00000000000 --- a/acceptance/bundle/paths/outside_root_no_sync/test.toml +++ /dev/null @@ -1,3 +0,0 @@ -[[Repls]] -Old = '\\' -New = '/' diff --git a/acceptance/bundle/paths/pipelines_root_path_outside_sync_root/test.toml b/acceptance/bundle/paths/pipelines_root_path_outside_sync_root/test.toml deleted file mode 100644 index a298217f218..00000000000 --- a/acceptance/bundle/paths/pipelines_root_path_outside_sync_root/test.toml +++ /dev/null @@ -1,3 +0,0 @@ -[[Repls]] -Old = '\\' -New = '/' diff --git a/acceptance/bundle/syncroot/dotdot-git/test.toml b/acceptance/bundle/syncroot/dotdot-git/test.toml deleted file mode 100644 index f57f83ee467..00000000000 --- a/acceptance/bundle/syncroot/dotdot-git/test.toml +++ /dev/null @@ -1,3 +0,0 @@ -[[Repls]] -Old = '\\\\myrepo' -New = '/myrepo' diff --git a/acceptance/bundle/templates-machinery/wrong-url/test.toml b/acceptance/bundle/templates-machinery/wrong-url/test.toml index b1d2d700cc5..323d9cd6691 100644 --- a/acceptance/bundle/templates-machinery/wrong-url/test.toml +++ b/acceptance/bundle/templates-machinery/wrong-url/test.toml @@ -1,7 +1,3 @@ -[[Repls]] -Old = '\\' -New = '/' - [[Repls]] Old = '/world-[0-9]+' New = '/world-123456' diff --git a/acceptance/bundle/templates/default-python/serverless-customcatalog/test.toml b/acceptance/bundle/templates/default-python/serverless-customcatalog/test.toml index a9b8e0859eb..f8f717c52af 100644 --- a/acceptance/bundle/templates/default-python/serverless-customcatalog/test.toml +++ b/acceptance/bundle/templates/default-python/serverless-customcatalog/test.toml @@ -3,8 +3,3 @@ Phase = 1 [[Server]] Pattern = "GET /api/2.1/unity-catalog/current-metastore-assignment" Response.Body = '{"default_catalog_name": "customcatalog"}' - -[[Repls]] -# windows fix -Old = '\\' -New = '/' diff --git a/acceptance/bundle/validate/targets/test.toml b/acceptance/bundle/validate/targets/test.toml deleted file mode 100644 index e9cede5e28a..00000000000 --- a/acceptance/bundle/validate/targets/test.toml +++ /dev/null @@ -1,4 +0,0 @@ -# Errors for invalid YAML print the full path of the file; normalize Windows separators. -[[Repls]] -Old = '\\' -New = '/' diff --git a/acceptance/bundle/validate/variables/overrides_file_complex_path/test.toml b/acceptance/bundle/validate/variables/overrides_file_complex_path/test.toml index ca5df96f13e..a434c0e9ca5 100644 --- a/acceptance/bundle/validate/variables/overrides_file_complex_path/test.toml +++ b/acceptance/bundle/validate/variables/overrides_file_complex_path/test.toml @@ -1,5 +1 @@ Badness = "Relative paths in variable-overrides.json resolve inconsistently: task files are resolved against the bundle root (with an error), libraries relative to the overrides file." - -[[Repls]] -Old = '\\' -New = '/' diff --git a/acceptance/bundle/validate/yaml_anchors/cycle_nested/test.toml b/acceptance/bundle/validate/yaml_anchors/cycle_nested/test.toml deleted file mode 100644 index a298217f218..00000000000 --- a/acceptance/bundle/validate/yaml_anchors/cycle_nested/test.toml +++ /dev/null @@ -1,3 +0,0 @@ -[[Repls]] -Old = '\\' -New = '/' diff --git a/acceptance/bundle/validate/yaml_anchors/test.toml b/acceptance/bundle/validate/yaml_anchors/test.toml deleted file mode 100644 index e9cede5e28a..00000000000 --- a/acceptance/bundle/validate/yaml_anchors/test.toml +++ /dev/null @@ -1,4 +0,0 @@ -# Errors for invalid YAML print the full path of the file; normalize Windows separators. -[[Repls]] -Old = '\\' -New = '/' diff --git a/acceptance/bundle/validate/yaml_duplicate_keys/test.toml b/acceptance/bundle/validate/yaml_duplicate_keys/test.toml deleted file mode 100644 index e9cede5e28a..00000000000 --- a/acceptance/bundle/validate/yaml_duplicate_keys/test.toml +++ /dev/null @@ -1,4 +0,0 @@ -# Errors for invalid YAML print the full path of the file; normalize Windows separators. -[[Repls]] -Old = '\\' -New = '/' diff --git a/acceptance/bundle/variables/file-defaults/test.toml b/acceptance/bundle/variables/file-defaults/test.toml deleted file mode 100644 index da8854775dc..00000000000 --- a/acceptance/bundle/variables/file-defaults/test.toml +++ /dev/null @@ -1,4 +0,0 @@ -# Fix for windows -[[Repls]] -Old = '\\' -New = '/' diff --git a/acceptance/cmd/auth/docker/host/test.toml b/acceptance/cmd/auth/docker/host/test.toml deleted file mode 100644 index 12e9eb5e1bc..00000000000 --- a/acceptance/cmd/auth/docker/host/test.toml +++ /dev/null @@ -1,3 +0,0 @@ -[[Repls]] -Old = '\\home\\docker\\config\.json' -New = '/home/docker/config.json' diff --git a/acceptance/cmd/fs/cp/file-to-nonexistent-dir/test.toml b/acceptance/cmd/fs/cp/file-to-nonexistent-dir/test.toml index ab359727a00..c7c6f58ed6e 100644 --- a/acceptance/cmd/fs/cp/file-to-nonexistent-dir/test.toml +++ b/acceptance/cmd/fs/cp/file-to-nonexistent-dir/test.toml @@ -1,6 +1 @@ Cloud = true - -# Local paths in errors use the OS separator. -[[Repls]] -Old = 'local\\nonexistent\\mydir' -New = 'local/nonexistent/mydir' diff --git a/acceptance/selftest/diff/test.toml b/acceptance/selftest/diff/test.toml deleted file mode 100644 index c496e138812..00000000000 --- a/acceptance/selftest/diff/test.toml +++ /dev/null @@ -1,3 +0,0 @@ -[[Repls]] -Old = '\.\.\\out_dir_b' -New = '../out_dir_b' diff --git a/bundle/artifacts/expand_globs.go b/bundle/artifacts/expand_globs.go index cc5d1f3fb60..977d7ca9a5e 100644 --- a/bundle/artifacts/expand_globs.go +++ b/bundle/artifacts/expand_globs.go @@ -25,7 +25,7 @@ func createGlobError(v dyn.Value, p dyn.Path, message string) diag.Diagnostic { return diag.Diagnostic{ Severity: diag.Error, - Summary: fmt.Sprintf("%s: %s", source, message), + Summary: fmt.Sprintf("%s: %s", filepath.ToSlash(source), message), Locations: []diag.Location{v.Location()}, Paths: dyn.ToStructPaths(p), } diff --git a/bundle/config/loader/process_root_includes.go b/bundle/config/loader/process_root_includes.go index 20e80564b0f..059b1db51dd 100644 --- a/bundle/config/loader/process_root_includes.go +++ b/bundle/config/loader/process_root_includes.go @@ -68,7 +68,7 @@ func (m *processRootIncludes) Apply(ctx context.Context, b *bundle.Bundle) diag. diags = diags.Append(diag.Diagnostic{ Severity: diag.Error, Summary: "Bundle root path contains glob pattern characters", - Detail: fmt.Sprintf("The path to the bundle root %s contains glob pattern character %q. Please remove the character from this path to use bundle commands.", b.BundleRootPath, char), + Detail: fmt.Sprintf("The path to the bundle root %s contains glob pattern character %q. Please remove the character from this path to use bundle commands.", filepath.ToSlash(b.BundleRootPath), char), }) return diags diff --git a/bundle/config/mutator/set_variables.go b/bundle/config/mutator/set_variables.go index f8f3b35394c..b930426f82d 100644 --- a/bundle/config/mutator/set_variables.go +++ b/bundle/config/mutator/set_variables.go @@ -109,13 +109,13 @@ func readVariablesFromFile(b *bundle.Bundle) (dyn.Value, diag.Diagnostics) { val, err := jsonloader.LoadJSON(f, filePath) if err != nil { - return dyn.InvalidValue, diag.FromErr(fmt.Errorf("failed to parse variables file %s: %w", filePath, err)) + return dyn.InvalidValue, diag.FromErr(fmt.Errorf("failed to parse variables file %s: %w", filepath.ToSlash(filePath), err)) } if val.Kind() != dyn.KindMap { return dyn.InvalidValue, diags.Append(diag.Diagnostic{ Severity: diag.Error, - Summary: fmt.Sprintf("failed to parse variables file %s: invalid format", filePath), + Summary: fmt.Sprintf("failed to parse variables file %s: invalid format", filepath.ToSlash(filePath)), Detail: "Variables file must be a JSON object with the following format:\n{\"var1\": \"value1\", \"var2\": \"value2\"}", }) } diff --git a/bundle/config/mutator/translate_paths.go b/bundle/config/mutator/translate_paths.go index 956d010ec95..d33656f98e1 100644 --- a/bundle/config/mutator/translate_paths.go +++ b/bundle/config/mutator/translate_paths.go @@ -155,7 +155,7 @@ func (t *translateContext) rewritePath( return "", err } if !opts.AllowPathOutsideSyncRoot && !filepath.IsLocal(localRelPath) { - return "", fmt.Errorf("path %s is not contained in sync root path", localPath) + return "", fmt.Errorf("path %s is not contained in sync root path", filepath.ToSlash(localPath)) } // Normalize paths to separated by forward slashes. diff --git a/bundle/config/root.go b/bundle/config/root.go index a64b742630e..b6428604672 100644 --- a/bundle/config/root.go +++ b/bundle/config/root.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "os" + "path/filepath" "reflect" "strings" @@ -122,13 +123,13 @@ func LoadFromBytes(path string, raw []byte) (*Root, diag.Diagnostics) { Locations: []diag.Location{le.Loc}, }} } - return nil, diag.Errorf("failed to load %s: %v", path, err) + return nil, diag.Errorf("failed to load %s: %v", filepath.ToSlash(path), err) } // Rewrite configuration tree where necessary. v, err = rewriteShorthands(v) if err != nil { - return nil, diag.Errorf("failed to rewrite %s: %v", path, err) + return nil, diag.Errorf("failed to rewrite %s: %v", filepath.ToSlash(path), err) } // Normalize dynamic configuration tree according to configuration type. @@ -137,7 +138,7 @@ func LoadFromBytes(path string, raw []byte) (*Root, diag.Diagnostics) { // Convert normalized configuration tree to typed configuration. err = r.updateWithDynamicValue(v) if err != nil { - diags = diags.Extend(diag.Errorf("failed to load %s: %v", path, err)) + diags = diags.Extend(diag.Errorf("failed to load %s: %v", filepath.ToSlash(path), err)) return nil, diags } return &r, diags diff --git a/bundle/libraries/same_name_libraries.go b/bundle/libraries/same_name_libraries.go index 722d42c7f64..0809bd91195 100644 --- a/bundle/libraries/same_name_libraries.go +++ b/bundle/libraries/same_name_libraries.go @@ -88,7 +88,7 @@ func (c checkForSameNameLibraries) Apply(ctx context.Context, b *bundle.Bundle) diags = append(diags, diag.Diagnostic{ Severity: diag.Error, Summary: "Duplicate local library names: " + lib, - Detail: "Local library names must be unique but found libraries with the same name: " + lv.fullPath + ", " + strings.Join(lv.otherPaths, ", "), + Detail: "Local library names must be unique but found libraries with the same name: " + filepath.ToSlash(lv.fullPath) + ", " + filepath.ToSlash(strings.Join(lv.otherPaths, ", ")), Locations: lv.locations, Paths: lv.paths, }) diff --git a/libs/diag/location.go b/libs/diag/location.go index 3b4a799e348..e21ebb80433 100644 --- a/libs/diag/location.go +++ b/libs/diag/location.go @@ -2,6 +2,7 @@ package diag import ( "fmt" + "path/filepath" ) type Location struct { @@ -11,5 +12,5 @@ type Location struct { } func (l Location) String() string { - return fmt.Sprintf("%s:%d:%d", l.File, l.Line, l.Column) + return fmt.Sprintf("%s:%d:%d", filepath.ToSlash(l.File), l.Line, l.Column) } diff --git a/libs/filer/errors.go b/libs/filer/errors.go index 8648502c229..9cf416b7d10 100644 --- a/libs/filer/errors.go +++ b/libs/filer/errors.go @@ -1,6 +1,9 @@ package filer -import "io/fs" +import ( + "io/fs" + "path/filepath" +) // fileAlreadyExistsError is returned when attempting to write a file at a path // that already exists, without using the OverwriteIfExists WriteMode flag. @@ -9,7 +12,7 @@ type fileAlreadyExistsError struct { } func (err fileAlreadyExistsError) Error() string { - return "file already exists: " + err.path + return "file already exists: " + filepath.ToSlash(err.path) } func (err fileAlreadyExistsError) Is(other error) bool { @@ -28,7 +31,7 @@ func (err fileDoesNotExistError) Is(other error) bool { } func (err fileDoesNotExistError) Error() string { - return "file does not exist: " + err.path + return "file does not exist: " + filepath.ToSlash(err.path) } // noSuchDirectoryError is returned when attempting to write a file to a path @@ -39,7 +42,7 @@ type noSuchDirectoryError struct { } func (err noSuchDirectoryError) Error() string { - return "no such directory: " + err.path + return "no such directory: " + filepath.ToSlash(err.path) } func (err noSuchDirectoryError) Is(other error) bool { @@ -53,7 +56,7 @@ type notADirectory struct { } func (err notADirectory) Error() string { - return "not a directory: " + err.path + return "not a directory: " + filepath.ToSlash(err.path) } func (err notADirectory) Is(other error) bool { @@ -67,7 +70,7 @@ type notAFile struct { } func (err notAFile) Error() string { - return "not a file: " + err.path + return "not a file: " + filepath.ToSlash(err.path) } func (err notAFile) Is(other error) bool { @@ -82,7 +85,7 @@ type directoryNotEmptyError struct { } func (err directoryNotEmptyError) Error() string { - return "directory not empty: " + err.path + return "directory not empty: " + filepath.ToSlash(err.path) } func (err directoryNotEmptyError) Is(other error) bool { @@ -113,7 +116,7 @@ type permissionError struct { } func (err permissionError) Error() string { - return "access denied: " + err.path + return "access denied: " + filepath.ToSlash(err.path) } func (err permissionError) Is(other error) bool { diff --git a/libs/git/view.go b/libs/git/view.go index e6d469514f1..b6be54f3017 100644 --- a/libs/git/view.go +++ b/libs/git/view.go @@ -83,7 +83,7 @@ func NewView(ctx context.Context, worktreeRoot, root vfs.Path) (*View, error) { target := root.Native() prefix := repo.rootDir.Native() if !strings.HasPrefix(target, prefix) { - return nil, fmt.Errorf("path %q is not within repository root %q", root.Native(), prefix) + return nil, fmt.Errorf("path %q is not within repository root %q", filepath.ToSlash(root.Native()), filepath.ToSlash(prefix)) } // Make target a relative path. From d8583772fee9a1b80e977ddadca4522132f7696b Mon Sep 17 00:00:00 2001 From: "denis.bilenko" Date: Thu, 5 Nov 2026 11:27:25 +0000 Subject: [PATCH 2/3] Add changelog entry Co-authored-by: Isaac --- .nextchanges/bundles/windows-forward-slash-paths.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 .nextchanges/bundles/windows-forward-slash-paths.md diff --git a/.nextchanges/bundles/windows-forward-slash-paths.md b/.nextchanges/bundles/windows-forward-slash-paths.md new file mode 100644 index 00000000000..4bb663b0657 --- /dev/null +++ b/.nextchanges/bundles/windows-forward-slash-paths.md @@ -0,0 +1 @@ +* Print paths with forward slashes in bundle and `fs` error messages on Windows. ([#7377](https://github.com/databricks/cli/pull/7377)) From 342aff24484e921d968d819ae18493b270493221 Mon Sep 17 00:00:00 2001 From: "denis.bilenko" Date: Thu, 5 Nov 2026 12:16:30 +0000 Subject: [PATCH 3/3] acc: remove comment-only test.toml, regenerate serverless-customcatalog golden The removed backslash Repl was also rewriting escaped \n and \" in notebook JSON into /n and /". Co-authored-by: Isaac --- .../integration_whl/serverless_dynamic_version/test.toml | 1 - .../default-python/serverless-customcatalog/output.txt | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) delete mode 100644 acceptance/bundle/integration_whl/serverless_dynamic_version/test.toml diff --git a/acceptance/bundle/integration_whl/serverless_dynamic_version/test.toml b/acceptance/bundle/integration_whl/serverless_dynamic_version/test.toml deleted file mode 100644 index 98a0a7d7e84..00000000000 --- a/acceptance/bundle/integration_whl/serverless_dynamic_version/test.toml +++ /dev/null @@ -1 +0,0 @@ -# serverless is only enabled if UC is enabled diff --git a/acceptance/bundle/templates/default-python/serverless-customcatalog/output.txt b/acceptance/bundle/templates/default-python/serverless-customcatalog/output.txt index 3fe9b24b805..61d683aa1ad 100644 --- a/acceptance/bundle/templates/default-python/serverless-customcatalog/output.txt +++ b/acceptance/bundle/templates/default-python/serverless-customcatalog/output.txt @@ -42,10 +42,10 @@ To get started, refer to the project README.md file and the documentation at htt --- [TESTROOT]/bundle/templates/default-python/serverless-customcatalog/../serverless/output/my_default_python/src/my_default_python_etl/explorations/sample_exploration.ipynb +++ output/my_default_python/src/my_default_python_etl/explorations/sample_exploration.ipynb @@ -38,5 +38,5 @@ - "# !!! Before performing any data analysis, make sure to run the pipeline to materialize the sample datasets. The tables referenced in this notebook depend on that step./n", - "/n", -- "display(spark.sql(/"SELECT * FROM hive_metastore.[USERNAME].sample_trips_my_default_python/"))" -+ "display(spark.sql(/"SELECT * FROM customcatalog.[USERNAME].sample_trips_my_default_python/"))" + "# !!! Before performing any data analysis, make sure to run the pipeline to materialize the sample datasets. The tables referenced in this notebook depend on that step.\n", + "\n", +- "display(spark.sql(\"SELECT * FROM hive_metastore.[USERNAME].sample_trips_my_default_python\"))" ++ "display(spark.sql(\"SELECT * FROM customcatalog.[USERNAME].sample_trips_my_default_python\"))" ] } --- [TESTROOT]/bundle/templates/default-python/serverless-customcatalog/../serverless/output/my_default_python/src/sample_notebook.ipynb