Add OAuth2 support for end users (i.e. 3-legged flow with the browser).

This CL introduces new top level command for managing cached auth tokens:
  $ depot-tools-auth login codereview.chromium.org
  $ depot-tools-auth info codereview.chromium.org
  $ depot-tools-auth logout codereview.chromium.org

All scripts that use rietveld.Rietveld internally should be able to use cached
credentials created by 'depot-tools-auth' subcommand. Also 'depot-tools-auth'
is the only way to run login flow. If some scripts stumbles over expired or
revoked token, it dies with the error, asking user to run
'depot-tools-auth login <hostname>'.

Password login is still default. OAuth2 can be enabled by passing --oauth2 to
all scripts.

R=maruel@chromium.org
BUG=356813

Review URL: https://codereview.chromium.org/1074673002

git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@294764 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/git_cl.py b/git_cl.py
index 5484713..d4486e5 100755
--- a/git_cl.py
+++ b/git_cl.py
@@ -2062,6 +2062,15 @@
     base_branch = cl.GetCommonAncestorWithUpstream()
     args = [base_branch, 'HEAD']
 
+  # Make sure authenticated to Rietveld before running expensive hooks. It is
+  # a fast, best efforts check. Rietveld still can reject the authentication
+  # during the actual upload.
+  if not settings.GetIsGerrit() and auth_config.use_oauth2:
+    authenticator = auth.get_authenticator_for_host(
+        cl.GetRietveldServer(), auth_config)
+    if not authenticator.has_cached_credentials():
+      raise auth.LoginRequiredError(cl.GetRietveldServer())
+
   # Apply watchlists on upload.
   change = cl.GetChange(base_branch, None)
   watchlist = watchlists.Watchlists(change.RepositoryRoot())
@@ -3179,6 +3188,8 @@
   dispatcher = subcommand.CommandDispatcher(__name__)
   try:
     return dispatcher.execute(OptionParser(), argv)
+  except auth.AuthenticationError as e:
+    DieWithError(str(e))
   except urllib2.HTTPError, e:
     if e.code != 500:
       raise