Use lstat instead of stat to avoid permissions issues when creating symlinks.
Also refactor symlink code slightly and add some more error checking.
Test: Manually.
Change-Id: I75119707cdf497e5690ac57abd814c8f18cab1f8
diff --git a/ui/build/bazel.go b/ui/build/bazel.go
index 910131a..1cab8f8 100644
--- a/ui/build/bazel.go
+++ b/ui/build/bazel.go
@@ -189,6 +189,7 @@
// currently hardcoded as ninja_build.output_root.
bazelNinjaBuildOutputRoot := filepath.Join(outputBasePath, "..", "out")
+ ctx.Println("Creating output symlinks..")
symlinkOutdir(ctx, config, bazelNinjaBuildOutputRoot, ".")
}
@@ -201,27 +202,39 @@
if err != nil {
ctx.Fatal(err)
}
+
for _, f := range files {
+ // The original Bazel file path
destPath := filepath.Join(destDir, f.Name())
+
+ // The desired Soong file path
srcPath := filepath.Join(config.OutDir(), relativePath, f.Name())
- if statResult, err := os.Stat(srcPath); err == nil {
- if statResult.Mode().IsDir() && f.IsDir() {
- // Directory under OutDir already exists, so recurse on its contents.
+
+ destLstatResult, destLstatErr := os.Lstat(destPath)
+ if destLstatErr != nil {
+ ctx.Fatalf("Unable to Lstat dest %s: %s", destPath, destLstatErr)
+ }
+
+ srcLstatResult, srcLstatErr := os.Lstat(srcPath)
+
+ if srcLstatErr == nil {
+ if srcLstatResult.IsDir() && destLstatResult.IsDir() {
+ // src and dest are both existing dirs - recurse on the dest dir contents...
symlinkOutdir(ctx, config, rootPath, filepath.Join(relativePath, f.Name()))
- } else if !statResult.Mode().IsDir() && !f.IsDir() {
- // File exists both in source and destination, and it's not a directory
- // in either location. Do nothing.
- // This can arise for files which are generated under OutDir outside of
- // soong_build, such as .bootstrap files.
} else {
- // File is a directory in one location but not the other. Raise an error.
- ctx.Fatalf("Could not link %s to %s due to conflict", srcPath, destPath)
+ // Ignore other pre-existing src files (could be pre-existing files, directories, symlinks, ...)
+ // This can arise for files which are generated under OutDir outside of soong_build, such as .bootstrap files.
+ // FIXME: This might cause a problem later e.g. if a symlink in the build graph changes...
}
- } else if os.IsNotExist(err) {
- // Create symlink srcPath -> fullDestPath.
- os.Symlink(destPath, srcPath)
} else {
- ctx.Fatalf("Unable to stat %s: %s", srcPath, err)
+ if !os.IsNotExist(srcLstatErr) {
+ ctx.Fatalf("Unable to Lstat src %s: %s", srcPath, srcLstatErr)
+ }
+
+ // src does not exist, so try to create a src -> dest symlink (i.e. a Soong path -> Bazel path symlink)
+ if symlinkErr := os.Symlink(destPath, srcPath); symlinkErr != nil {
+ ctx.Fatalf("Unable to create symlink %s -> %s due to error %s", srcPath, destPath, symlinkErr)
+ }
}
}
}