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.
|
||||
bazelNinjaBuildOutputRoot := filepath.Join(outputBasePath, "..", "out")
|
||||
|
||||
ctx.Println("Creating output symlinks..")
|
||||
symlinkOutdir(ctx, config, bazelNinjaBuildOutputRoot, ".")
|
||||
}
|
||||
|
||||
|
@ -201,27 +202,39 @@ func symlinkOutdir(ctx Context, config Config, rootPath string, relativePath str
|
|||
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.
|
||||
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)
|
||||
|
||||
destLstatResult, destLstatErr := os.Lstat(destPath)
|
||||
if destLstatErr != nil {
|
||||
ctx.Fatalf("Unable to Lstat dest %s: %s", destPath, destLstatErr)
|
||||
}
|
||||
} else if os.IsNotExist(err) {
|
||||
// Create symlink srcPath -> fullDestPath.
|
||||
os.Symlink(destPath, srcPath)
|
||||
|
||||
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 {
|
||||
ctx.Fatalf("Unable to stat %s: %s", srcPath, err)
|
||||
// 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(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