Merge tag 'v2.31' into stable

Required fix is merged upstream, now in upstream/stable history:
commit tools/repo@802cd0c6 "sync: Fix undefined variable in _FetchOne".

repo v2.31

* tag 'v2.31': (54 commits)
  tests: drop old unittest.main logic
  sync: fix manifest sync-j handling
  sync: Fix undefined variable in _FetchOne
  sync: finish marking REPO_AUTO_GC=1 as deprecated.
  test_manifest_config_properties: use assertEqual
  sync: cleanup output when not doing GC
  Revert "sync: save any cruft after calling git gc."
  sync: mark REPO_AUTO_GC=1 as deprecated.
  Fix ManifestProject.partial_clone_exclude property.
  release-process: update to use ./release/sign-tag.py
  wrapper.py: Replacing load_module() with exec_module()
  Fixed wrapper related warnings in tests
  test_capture: allow both Unix and Windows line sep
  test_bad_path_name_checks: allow Windows path sep
  test: Fix char encoding issues on windows
  test: fix path seperator errors on windows
  tox: Allow passing positional arguments
  trace: make test timeout after 2min
  tox: Make all tests timeout after 5min
  Update GH Action test-ci.yml dependencies
  ...

Change-Id: I693caeee6b0a4e7b35c9b9a8c859ee964a8bce4c
diff --git a/docs/manifest-format.md b/docs/manifest-format.md
index bcdf5a8..729c58d 100644
--- a/docs/manifest-format.md
+++ b/docs/manifest-format.md
@@ -392,6 +392,8 @@
 Attribute `clone-depth`: Set the depth to use when fetching this
 project.  If specified, this value will override any value given
 to repo init with the --depth option on the command line.
+Exception: If --depth -1 is set, `clone-depth` will be ignored and all
+checkouts will be unshallowed.
 
 Attribute `force-path`: Set to true to force this project to create the
 local mirror repository according to its `path` attribute (if supplied)
diff --git a/project.py b/project.py
index 619cdfd..4022d84 100644
--- a/project.py
+++ b/project.py
@@ -1223,10 +1223,14 @@
     if tags is None:
       tags = self.sync_tags
 
-    if self.clone_depth:
+    repo_depth = self.manifest.manifestProject.depth
+    if repo_depth == "-1":
+      # -1 enforces full history and overrides the depth set per project.
+      depth = repo_depth
+    elif self.clone_depth:
       depth = self.clone_depth
     else:
-      depth = self.manifest.manifestProject.depth
+      depth = repo_depth
 
     # See if we can skip the network fetch entirely.
     remote_fetched = False
@@ -2107,6 +2111,10 @@
     if self.manifest.IsMirror or self.relpath == '.repo/repo':
       depth = None
 
+    # -1 is a dummy value to force unshallowing all projects.
+    if depth == "-1":
+      depth = None
+
     if depth:
       current_branch_only = True
 
@@ -3947,8 +3955,9 @@
     """
     # Opt.depth will be non-None if user actually passed --depth to repo init.
     if depth is not None:
-      if depth > 0:
-        # Positive values will set the depth.
+      if depth > 0 or depth == -1:
+        # Positive values will set the depth. -1 is a dummy value for forcing
+        # unshallow checkouts.
         depth = str(depth)
       else:
         # Negative numbers will clear the depth; passing None to SetString
diff --git a/repo b/repo
index 18649b8..9556832 100755
--- a/repo
+++ b/repo
@@ -361,7 +361,9 @@
                    help='dissociate from reference mirrors after clone')
   group.add_option('--depth', type='int', default=None,
                    help='create a shallow clone with given depth; '
-                        'see git clone')
+                        'see git clone. Set to -1 to force unshallow '
+                        'clones/checkouts of all projects, overriding '
+                        'per-project attributes.')
   group.add_option('--partial-clone', action='store_true',
                    help='perform partial clone (https://git-scm.com/'
                         'docs/gitrepository-layout#_code_partialclone_code)')