git cl creds-check: add reporting.

BUG=689543

Change-Id: I2c5dd9e1ef4a23ba805c8c057ad44c87cfb65a5b
Reviewed-on: https://chromium-review.googlesource.com/455782
Commit-Queue: Andrii Shyshkalov <tandrii@chromium.org>
Reviewed-by: Michael Achenbach <machenbach@chromium.org>
diff --git a/git_cl.py b/git_cl.py
index aa2238a..c3e564f 100755
--- a/git_cl.py
+++ b/git_cl.py
@@ -3566,6 +3566,11 @@
       prefix = prefix[:-len('-review')]
     return prefix + '.' + self._GOOGLESOURCE
 
+  def _canonical_gerrit_googlesource_host(self, host):
+    git_host = self._canonical_git_googlesource_host(host)
+    prefix = git_host.split('.', 1)[0]
+    return prefix + '-review.' + self._GOOGLESOURCE
+
   def has_generic_host(self):
     """Returns whether generic .googlesource.com has been configured.
 
@@ -3624,6 +3629,63 @@
           hosts.add(host)
     return hosts
 
+  @staticmethod
+  def print_hosts(hosts, extra_column_func=None):
+    hosts = sorted(hosts)
+    assert hosts
+    if extra_column_func is None:
+      extras = [''] * len(hosts)
+    else:
+      extras = [extra_column_func(host) for host in hosts]
+    tmpl = '    %%-%ds %%-%ds' % (max(map(len, hosts)), max(map(len, extras)))
+    for he in zip(hosts, extras):
+      print(tmpl % he)
+    print()
+
+  def find_and_report_problems(self):
+    """Returns True if there was at least one problem, else False."""
+    problems = [False]
+    def add_problem():
+      if not problems[0]:
+        print('.gitcookies problem report:\n')
+      problems[0] = True
+
+    if self.has_generic_host():
+      add_problem()
+      print('  .googlesource.com record detected\n'
+            '    Chrome Infrastructure team recommends to list full host names '
+            'explicitly.\n')
+
+    dups = self.get_duplicated_hosts()
+    if dups:
+      add_problem()
+      print('  The following hosts were defined twice:\n')
+      self.print_hosts(dups)
+
+    partial = self.get_partially_configured_hosts()
+    if partial:
+      add_problem()
+      print('  Credentials should come in pairs for Git and Gerrit hosts. '
+            'These hosts are missing:')
+      self.print_hosts(partial)
+
+    conflicting = self.get_conflicting_hosts()
+    if conflicting:
+      add_problem()
+      print('  The following Git hosts have differing credentials from their '
+            'Gerrit counterparts:\n')
+      self.print_hosts(conflicting, lambda host: '%s vs %s' %
+                       tuple(self._get_git_gerrit_identity_pairs()[host]))
+
+    wrong = self.get_hosts_with_wrong_identities()
+    if wrong:
+      add_problem()
+      print('  These hosts likely use wrong identity:\n')
+      self.print_hosts(wrong, lambda host: '%s but %s recommended' %
+                       (self._get_git_gerrit_identity_pairs()[host][0],
+                        self._EXPECTED_HOST_IDENTITY_DOMAINS[host]))
+    return problems[0]
+
 
 def CMDcreds_check(parser, args):
   """Checks credentials and suggests changes."""
@@ -3635,11 +3697,13 @@
   checker = _GitCookiesChecker()
   checker.ensure_configured_gitcookies()
 
-  print('Your .netrc and .gitcookies have credentails for these hosts:')
+  print('Your .netrc and .gitcookies have credentials for these hosts:')
   checker.print_current_creds(include_netrc=True)
 
-  # TODO(tandrii): add report && autofixes.
-  return 0
+  if not checker.find_and_report_problems():
+    print('\nNo problems detected in your .gitcookies')
+    return 0
+  return 1
 
 
 @subcommand.usage('[repo root containing codereview.settings]')
@@ -5068,7 +5132,7 @@
     if not patchset:
       parser.error('Codereview doesn\'t know about issue %s. '
                    'No access to issue or wrong issue number?\n'
-                   'Either upload first, or pass --patchset explicitely' %
+                   'Either upload first, or pass --patchset explicitly' %
                    cl.GetIssue())
 
     # TODO(tandrii): Checking local patchset against remote patchset is only