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
This commit is contained in:
parent
0ec64e5df7
commit
ead7ef6e3b
1 changed files with 27 additions and 14 deletions
|
@ -189,6 +189,7 @@ func runBazel(ctx Context, config Config) {
|
||||||
// currently hardcoded as ninja_build.output_root.
|
// currently hardcoded as ninja_build.output_root.
|
||||||
bazelNinjaBuildOutputRoot := filepath.Join(outputBasePath, "..", "out")
|
bazelNinjaBuildOutputRoot := filepath.Join(outputBasePath, "..", "out")
|
||||||
|
|
||||||
|
ctx.Println("Creating output symlinks..")
|
||||||
symlinkOutdir(ctx, config, bazelNinjaBuildOutputRoot, ".")
|
symlinkOutdir(ctx, config, bazelNinjaBuildOutputRoot, ".")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,27 +202,39 @@ func symlinkOutdir(ctx Context, config Config, rootPath string, relativePath str
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Fatal(err)
|
ctx.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, f := range files {
|
for _, f := range files {
|
||||||
|
// The original Bazel file path
|
||||||
destPath := filepath.Join(destDir, f.Name())
|
destPath := filepath.Join(destDir, f.Name())
|
||||||
|
|
||||||
|
// The desired Soong file path
|
||||||
srcPath := filepath.Join(config.OutDir(), relativePath, f.Name())
|
srcPath := filepath.Join(config.OutDir(), relativePath, f.Name())
|
||||||
if statResult, err := os.Stat(srcPath); err == nil {
|
|
||||||
if statResult.Mode().IsDir() && f.IsDir() {
|
destLstatResult, destLstatErr := os.Lstat(destPath)
|
||||||
// Directory under OutDir already exists, so recurse on its contents.
|
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()))
|
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 {
|
} else {
|
||||||
// File is a directory in one location but not the other. Raise an error.
|
// Ignore other pre-existing src files (could be pre-existing files, directories, symlinks, ...)
|
||||||
ctx.Fatalf("Could not link %s to %s due to conflict", srcPath, destPath)
|
// 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 {
|
} 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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue