Make sure SymlinkFileStep deletes the existing file before overwriting it.

Summary:
I encountered this issue because I was debugging something in a downloaded
tar of a co-worker's fbandroid repo. It contained the following file:

```
~/code/andrews/fb4a2$ ls -al buck-out/gen/releasebuild-properties
lrwxrwxrwx 1 mbolin mbolin 45 Sep  3 16:10 buck-out/gen/releasebuild-properties -> /Users/andrews/fb4a/./releasebuild.properties
~/code/andrews/fb4a2$
```

As you can see, `buck-out/gen/releasebuild-properties` was a symlink, but
to a file on `andrews`'s machine, which was not on my machine. When
`SymlinkFileStep` was used to overwrite `releasebuild-properties`, it threw a
`FileAlreadyExistsException` even though we did the following to delete the
file before linking it in `SymlinkFileStep`:

  if (targetPath.toFile().exists() && !targetPath.toFile().delete()) {
    throw new HumanReadableException("Failed to delete symbolic link for %s",
        targetPath.toAbsolutePath());
  }
  context.getProjectFilesystem().createSymLink(sourcePath, targetPath);

It turns out that if `targetPath` references a symlink that points to a
non-existent file, then the `exists()` call will return `false`, which
means the `delete()` method will never get executed. When the file is not
deleted, the call to `createSymLink` will throw a `FileAlreadyExistsException`.

I'm not sure whether we could encounter this issue in ordinary usage, but it
seems like a good idea to defend against it, anyway.

Test Plan:
Created `SymlinkFileStepTest#testReplaceMalformedSymlink()`,
verified that `SymlinkFileStep.execute()` threw an exception when I ran the test,
and then fixed `SymlinkFileStep.execute()` so the test passed.
2 files changed
tree: bb7985508c7163ae84c072143beaae374f8b9515
  1. .idea/
  2. bin/
  3. config/
  4. docs/
  5. lib/
  6. pmd/
  7. scripts/
  8. src/
  9. test/
  10. testdata/
  11. third-party/
  12. .buckconfig
  13. .classpath
  14. .gitignore
  15. .project
  16. buck.iml
  17. build.xml
  18. DEFS
  19. LICENSE
  20. README.md
README.md

Buck

Buck is an Android build tool. To see what Buck can do for you, check out the documentation at http://facebook.github.io/buck/.

Installation

To build Buck, run the following:

git clone git@github.com:facebook/buck.git
cd buck
ant
./bin/buck --help

License

Apache License 2.0