gsutil_util: Don't retry when an object does not exist

When running with --production flag, devsever retries every request up
to 5 times. This CL fixes the error code to make sure we don't retry
on a valid error (i.e., the object does not exist).

BUG=chromium:434168
TEST=Ran a local devserver with --production

Change-Id: Iedb9a9148bc252ea4aa755976eb424e31c76d3ec
Reviewed-on: https://chromium-review.googlesource.com/230512
Tested-by: Yu-Ju Hong <yjhong@chromium.org>
Reviewed-by: Prashanth B <beeps@chromium.org>
Commit-Queue: Yu-Ju Hong <yjhong@chromium.org>
diff --git a/gsutil_util.py b/gsutil_util.py
index bf69c10..dfbd1a7 100644
--- a/gsutil_util.py
+++ b/gsutil_util.py
@@ -57,13 +57,18 @@
     stdout, stderr = proc.communicate()
     if proc.returncode == 0:
       return stdout
-    elif stderr and ('matched no objects' in stderr or
-                     'non-existent object' in stderr):
-      # TODO(sosa): Note this is a heuristic that makes us not re-attempt
-      # unnecessarily. However, if it fails, the worst that can happen is just
-      # waiting longer than necessary.
+
+    not_exist_messages = ('matched no objects', 'non-existent object',
+                          'no urls matched')
+    if (stderr and any(x in stderr.lower() for x in not_exist_messages) or
+        stdout and any(x in stdout.lower() for x in not_exist_messages)):
+      # If the object does not exist, exit now instead of wasting time
+      # on retrying. Note that `gsutil stat` prints error message to
+      # stdout instead (b/16020252), so we check both stdout and
+      # stderr.
       break
-    elif proc.returncode == 127:
+
+    if proc.returncode == 127:
       raise GSUtilError('gsutil tool not found in your path.')
 
     time.sleep(sleep_timeout)