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)) 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 deleted file mode 100644 index 920da59d1d7..00000000000 --- a/acceptance/bundle/integration_whl/serverless_dynamic_version/test.toml +++ /dev/null @@ -1,5 +0,0 @@ -# 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/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 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.