diff: add a `--tool` flag to use external diffing tools

Diffing using an external tool is a very important use case and used a lot.
Currently in mercurial the only way to do so is to use the extdiff extension.
This approach is not extendable as extdiff kind of rewrites all the diff logic
and plug in it's specific things. Also that can be re-used in other commands.

This patch introduces a `--tool` flag to diff command which we be added by
extdiff extension. It wraps the core diff code and is extensible.

Also having `diff --tool` is better UI than `extdiff`, something which I like in
git.

In future, I will like to refactor existing extdiff logic to use `diff --tool`
logic. But before that, I am more interested in adding external tool
functionality to all places where we show a diff, for example: export, log etc.

Differential Revision: https://phab.mercurial-scm.org/D8972
11 jobs for topic/default/extdiff-refactor in 30 minutes and 52 seconds (queued for 26 minutes and 10 seconds)
latest
Status Job ID Name Coverage
  Test
passed #105847
checks-py2

00:05:08

passed #105848
checks-py3

00:03:18

passed #105849
rust-cargo-test-py2

00:02:00

passed #105850
rust-cargo-test-py3

00:01:55

passed #105851
test-py2

00:24:24

passed #105857
test-py2-chg

00:24:08

failed #105853
test-py2-pure

00:24:32

passed #105855
test-py2-rust

00:21:51

passed #105852
test-py3

00:13:07

failed #105854
test-py3-pure

00:15:06

passed #105856
test-py3-rust

00:09:50

 
Name Stage Failure
failed
test-py2-pure Test
Skipped test-sqlitestore.t: missing feature: sqlite3 module is available
Skipped test-verify-repo-operations.py: missing feature: allow slow tests (use --allow-slow-tests)
Skipped test-wireproto-exchangev2-shallow.t: missing feature: sqlite3 module is available
Failed test-share-safe.t: output changed
# Ran 880 tests, 58 skipped, 1 failed.
python hash seed: 3292142228
Running after_script
Uploading artifacts for failed job
ERROR: Job failed: exit code 1
failed
test-py3-pure Test
Skipped test-sqlitestore.t: missing feature: sqlite3 module is available
Skipped test-verify-repo-operations.py: missing feature: allow slow tests (use --allow-slow-tests)
Skipped test-wireproto-exchangev2-shallow.t: missing feature: sqlite3 module is available
Failed test-share-safe.t: output changed
# Ran 874 tests, 64 skipped, 1 failed.
python hash seed: 1771110873
Running after_script
Uploading artifacts for failed job
ERROR: Job failed: exit code 1