Report better errors when a project revision is invalid

If a manifest specifies an invalid revision property, give the
user a better error message detaling the problem, instead of an
ugly Python traceback with a strange Git error message.

Bug: REPO-2
Signed-off-by: Shawn O. Pearce <sop@google.com>
diff --git a/error.py b/error.py
index 029e122..6b9dff4 100644
--- a/error.py
+++ b/error.py
@@ -17,6 +17,10 @@
   """Failed to parse the manifest file.
   """
 
+class ManifestInvalidRevisionError(Exception):
+  """The revision value in a project is incorrect.
+  """
+
 class EditorError(Exception):
   """Unspecified error from the user's text editor.
   """
diff --git a/main.py b/main.py
index be8da01..f8fcfe2 100755
--- a/main.py
+++ b/main.py
@@ -29,6 +29,7 @@
 
 from command import InteractiveCommand, PagedCommand
 from editor import Editor
+from error import ManifestInvalidRevisionError
 from error import NoSuchProjectError
 from error import RepoChangedException
 from manifest import Manifest
@@ -94,6 +95,9 @@
     copts, cargs = cmd.OptionParser.parse_args(argv)
     try:
       cmd.Execute(copts, cargs)
+    except ManifestInvalidRevisionError, e:
+      print >>sys.stderr, 'error: %s' % str(e)
+      sys.exit(1)
     except NoSuchProjectError, e:
       if e.name:
         print >>sys.stderr, 'error: project %s not found' % e.name
diff --git a/project.py b/project.py
index 4780316..8cdb8b1 100644
--- a/project.py
+++ b/project.py
@@ -25,6 +25,7 @@
 from git_command import GitCommand
 from git_config import GitConfig, IsId
 from error import GitError, ImportError, UploadError
+from error import ManifestInvalidRevisionError
 from remote import Remote
 
 HEAD    = 'HEAD'
@@ -582,6 +583,12 @@
 
     rem = self.GetRemote(self.remote.name)
     rev = rem.ToLocal(self.revision)
+    try:
+      self.bare_git.rev_parse('--verify', '%s^0' % rev)
+    except GitError:
+      raise ManifestInvalidRevisionError(
+        'revision %s in %s not found' % (self.revision, self.name))
+
     branch = self.CurrentBranch
 
     if branch is None: