repo: Add support for standalone manifests

Added --standalone_manifest to repo tool. If set, the
manifest is downloaded directly from the appropriate source
(currently, we only support GS) and used instead of creating
a manifest git checkout. The manifests.git repo is still created to
keep track of various config but is marked as being for a standalone
manifest so that the repo tool doesn't try to run networked git
commands in it.

BUG=b:192664812
TEST=existing tests (no coverage), manual runs

Change-Id: I84378cbc7f8e515eabeccdde9665efc8cd2a9d21
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/312942
Tested-by: Jack Neus <jackneus@google.com>
Reviewed-by: Mike Frysinger <vapier@google.com>
diff --git a/fetch.py b/fetch.py
new file mode 100644
index 0000000..5b9997a
--- /dev/null
+++ b/fetch.py
@@ -0,0 +1,38 @@
+# Copyright (C) 2021 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""This module contains functions used to fetch files from various sources."""
+
+import subprocess
+import sys
+from urllib.parse import urlparse
+
+def fetch_file(url):
+  """Fetch a file from the specified source using the appropriate protocol.
+
+  Returns:
+    The contents of the file as bytes.
+  """
+  scheme = urlparse(url).scheme
+  if scheme == 'gs':
+    cmd = ['gsutil', 'cat', url]
+    try:
+      result = subprocess.run(
+          cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+      return result.stdout
+    except subprocess.CalledProcessError as e:
+      print('fatal: error running "gsutil": %s' % e.output,
+            file=sys.stderr)
+    sys.exit(1)
+  raise ValueError('unsupported url %s' % url)