From 3f4f5217118540a92da02e19040f29c6c939c2a1 Mon Sep 17 00:00:00 2001 From: Cole Faust Date: Tue, 4 Apr 2023 15:12:22 -0700 Subject: [PATCH] Fix issue merging bp2build files with handcrafted ones It was possible for the merged content to end up back in the bp2build generated file because there was a symlink from the symlink forest to the bp2build generated file. Remove the symlink if it exists. Bug: 276349152 Test: m bp2build, add a handcrafted file in the same folder as a Android.bp file, m bp2build again, check that the symlink forest version is not a symlink Change-Id: Id64aa3addebcf0c6b1728389f21ae246796aaf8d --- bp2build/symlink_forest.go | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/bp2build/symlink_forest.go b/bp2build/symlink_forest.go index aac5e7d2c..e3878b16c 100644 --- a/bp2build/symlink_forest.go +++ b/bp2build/symlink_forest.go @@ -25,6 +25,7 @@ import ( "sync/atomic" "android/soong/shared" + "github.com/google/blueprint/pathtools" ) @@ -123,6 +124,34 @@ func mergeBuildFiles(output string, srcBuildFile string, generatedBuildFile stri } newContents = append(newContents, srcBuildFileContent...) + // Say you run bp2build 4 times: + // - The first time there's only an Android.bp file. bp2build will convert it to a build file + // under out/soong/bp2build, then symlink from the forest to that generated file + // - Then you add a handcrafted BUILD file in the same directory. bp2build will merge this with + // the generated one, and write the result to the output file in the forest. But the output + // file was a symlink to out/soong/bp2build from the previous step! So we erroneously update + // the file in out/soong/bp2build instead. So far this doesn't cause any problems... + // - You run a 3rd bp2build with no relevant changes. Everything continues to work. + // - You then add a comment to the handcrafted BUILD file. This causes a merge with the + // generated file again. But since we wrote to the generated file in step 2, the generated + // file has an old copy of the handcrafted file in it! This probably causes duplicate bazel + // targets. + // To solve this, if we see that the output file is a symlink from a previous build, remove it. + stat, err := os.Lstat(output) + if err != nil && !os.IsNotExist(err) { + return err + } else if err == nil { + if stat.Mode()&os.ModeSymlink == os.ModeSymlink { + if verbose { + fmt.Fprintf(os.Stderr, "Removing symlink so that we can replace it with a merged file: %s\n", output) + } + err = os.Remove(output) + if err != nil { + return err + } + } + } + return pathtools.WriteFileIfChanged(output, newContents, 0666) }