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 Name Job ID Coverage
  Test
passed checks-py2 #105847

00:05:08

passed checks-py3 #105848

00:03:18

passed rust-cargo-test-py2 #105849

00:02:00

passed rust-cargo-test-py3 #105850

00:01:55

passed test-py2 #105851

00:24:24

passed test-py2-chg #105857

00:24:08

failed test-py2-pure #105853

00:24:32

passed test-py2-rust #105855

00:21:51

passed test-py3 #105852

00:13:07

failed test-py3-pure #105854

00:15:06

passed test-py3-rust #105856

00:09:50

 
Name Stage Failure
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
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