pw_env_setup: Allow using existing cipd client

Add --use-existing-cipd which will cause the cipd part of env setup to
use a 'cipd' executable already in PATH instead of downloading it anew.
This will be used in CI/CQ where pulling down the cipd client is an
infrequent but occasional failure, and there's a guarantee of an
existing 'cipd' executable anyway.

Tested by adding --use-existing-cipd to bootstrap.sh and it worked. Then
removed because most Pigweed developers won't have 'cipd' already
somewhere else in their PATH.

Change-Id: Ieb5d505c47211e1c63338067ccd7de2006a0ad82
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/45021
Commit-Queue: Rob Mohr <mohrr@google.com>
Pigweed-Auto-Submit: Rob Mohr <mohrr@google.com>
Reviewed-by: Alexei Frolov <frolv@google.com>
diff --git a/pw_env_setup/py/pw_env_setup/env_setup.py b/pw_env_setup/py/pw_env_setup/env_setup.py
index 1890a78..9c397a0 100755
--- a/pw_env_setup/py/pw_env_setup/env_setup.py
+++ b/pw_env_setup/py/pw_env_setup/env_setup.py
@@ -178,7 +178,8 @@
     def __init__(self, pw_root, cipd_cache_dir, shell_file, quiet, install_dir,
                  use_pigweed_defaults, cipd_package_file, virtualenv_root,
                  virtualenv_requirements, virtualenv_gn_target,
-                 virtualenv_gn_out_dir, json_file, project_root, config_file):
+                 virtualenv_gn_out_dir, json_file, project_root, config_file,
+                 use_existing_cipd):
         self._env = environment.Environment()
         self._project_root = project_root
         self._pw_root = pw_root
@@ -207,6 +208,8 @@
 
         self._json_file = json_file
 
+        self._use_existing_cipd = use_existing_cipd
+
         setup_root = os.path.join(pw_root, 'pw_env_setup', 'py',
                                   'pw_env_setup')
 
@@ -384,15 +387,24 @@
         return 0
 
     def cipd(self, spin):
+        """Set up cipd and install cipd packages."""
+
         install_dir = os.path.join(self._install_dir, 'cipd')
 
-        try:
-            cipd_client = cipd_wrapper.init(install_dir, silent=True)
-        except cipd_wrapper.UnsupportedPlatform as exc:
-            return result_func(('    {!r}'.format(exc), ))(
-                _Result.Status.SKIPPED,
-                '    abandoning CIPD setup',
-            )
+        # There's no way to get to the UnsupportedPlatform exception if this
+        # flag is set, but this flag should only be set in LUCI builds which
+        # will always have CIPD.
+        if self._use_existing_cipd:
+            cipd_client = 'cipd'
+
+        else:
+            try:
+                cipd_client = cipd_wrapper.init(install_dir, silent=True)
+            except cipd_wrapper.UnsupportedPlatform as exc:
+                return result_func(('    {!r}'.format(exc), ))(
+                    _Result.Status.SKIPPED,
+                    '    abandoning CIPD setup',
+                )
 
         package_files, glob_warnings = _process_globs(self._cipd_package_file)
         result = result_func(glob_warnings)
@@ -574,6 +586,12 @@
         default=None,
     )
 
+    parser.add_argument(
+        '--use-existing-cipd',
+        help='Use cipd executable from the environment instead of fetching it.',
+        action='store_true',
+    )
+
     args = parser.parse_args(argv)
 
     others = (