Homebrew/homebrew — pull request #27899 by jacknagel (2014-03-27 04:31:52+00:00)
Title: UX issue when `brew link` encounters conflicts

I'm working on moving the error handling in `Pathname#make_relative_symlink` to a different layer. By doing this we can remove knowledge of higher level concepts like formula and `brew ` from Pathname, and provide more useful errors, e.g. instead of saying "if this file is from another formula, you may need to `brew unlink` it" we can tell the user specifically what formula to unlink.

Anyway, while doing this I noticed a problem with the existing code. Given conflicting formulae (I'll use `git-flow` and `git-flow-avh`), here is what I see when I try to `brew link` one with the other already linked:

```
$ brew link git-flow
Linking /usr/local/Cellar/git-flow/0.4.1... Warning: Could not link git-flow. Unlinking...

Error: Could not symlink file: /usr/local/Cellar/git-flow/0.4.1/etc/bash_completion.d/git-flow-completion.bash
Target /usr/local/etc/bash_completion.d/git-flow-completion.bash already exists. You may need to delete it.
To force the link and overwrite all other conflicting files, do:
brew link --overwrite formula_name

To list all files that would be deleted:
brew link --overwrite --dry-run formula_name
```

but what I expected to see is:

```
$ brew link git-flow
Linking /usr/local/Cellar/git-flow/0.4.1...
Warning: Could not link git-flow. Unlinking...

Error: Could not symlink file: /usr/local/Cellar/git-flow/0.4.1/etc/bash_completion.d/git-flow-completion.bash
Target /usr/local/etc/bash_completion.d/git-flow-completion.bash already exists as a symlink to ../../Cellar/git-flow-avh/1.7.0/etc/bash_completion.d/git-flow-completion.bash.
If this file is from another formula, you may need to
`brew unlink` it. Otherwise, you may want to delete it.
To force the link and overwrite all other conflicting files, do:
brew link --overwrite formula_name

To list all files that would be deleted:
brew link --overwrite --dry-run formula_name
```

In other words, there are really three cases:

(1) the target is a symlink that resolves to a file or directory that exists
(2) the target is a regular file or directory
(3) the target is a broken symlink

but we currently treat (1) and (2) the same and only print the `brew unlink` advice for (3).

This pull request does two things:

* treat case (1) like we currently treat (3)
* instead of dying when we encounter (3), simply remove the broken symlink and try to make the link again.

/cc @mistydemeo