diff options
| author | Gavin Mak <gavinmak@google.com> | 2025-06-17 20:15:50 -0700 |
|---|---|---|
| committer | LUCI <gerrit-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2025-06-23 16:06:34 -0700 |
| commit | 99b5a17f2c951fe5979100c36e7e1dbb4c61b36c (patch) | |
| tree | 4fce4f07d92e1b3a6d1c85611a045ead3517066c | |
| parent | df3c4017f9a81e268b23728c273e1c8cd8957434 (diff) | |
| download | git-repo-99b5a17f2c951fe5979100c36e7e1dbb4c61b36c.tar.gz | |
sync: Share final error handling logic between sync modesv2.56
Dedupe error reporting logic for phased and interleaved sync modes by
extracting it into _ReportErrors.
Error reporting will now distinguish between network and local failures
and lists the specific repos that failed in each phase.
Bug: 421935613
Change-Id: I4604a83943dbbd71d979158d7a1c4b8c243347d2
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/484541
Tested-by: Gavin Mak <gavinmak@google.com>
Reviewed-by: Scott Lee <ddoman@google.com>
Commit-Queue: Gavin Mak <gavinmak@google.com>
| -rw-r--r-- | subcmds/sync.py | 99 |
1 files changed, 72 insertions, 27 deletions
diff --git a/subcmds/sync.py b/subcmds/sync.py index 3d4ab75c..20d75dc8 100644 --- a/subcmds/sync.py +++ b/subcmds/sync.py | |||
| @@ -2054,6 +2054,46 @@ later is required to fix a server side protocol bug. | |||
| 2054 | raise SyncFailFastError(aggregate_errors=errors) | 2054 | raise SyncFailFastError(aggregate_errors=errors) |
| 2055 | return err_update_projects, err_update_linkfiles | 2055 | return err_update_projects, err_update_linkfiles |
| 2056 | 2056 | ||
| 2057 | def _ReportErrors( | ||
| 2058 | self, | ||
| 2059 | errors, | ||
| 2060 | err_network_sync=False, | ||
| 2061 | failing_network_repos=None, | ||
| 2062 | err_checkout=False, | ||
| 2063 | failing_checkout_repos=None, | ||
| 2064 | err_update_projects=False, | ||
| 2065 | err_update_linkfiles=False, | ||
| 2066 | ): | ||
| 2067 | """Logs detailed error messages and raises a SyncError.""" | ||
| 2068 | |||
| 2069 | def print_and_log(err_msg): | ||
| 2070 | self.git_event_log.ErrorEvent(err_msg) | ||
| 2071 | logger.error("%s", err_msg) | ||
| 2072 | |||
| 2073 | print_and_log("error: Unable to fully sync the tree") | ||
| 2074 | if err_network_sync: | ||
| 2075 | print_and_log("error: Downloading network changes failed.") | ||
| 2076 | if failing_network_repos: | ||
| 2077 | logger.error( | ||
| 2078 | "Failing repos (network):\n%s", | ||
| 2079 | "\n".join(sorted(failing_network_repos)), | ||
| 2080 | ) | ||
| 2081 | if err_update_projects: | ||
| 2082 | print_and_log("error: Updating local project lists failed.") | ||
| 2083 | if err_update_linkfiles: | ||
| 2084 | print_and_log("error: Updating copyfiles or linkfiles failed.") | ||
| 2085 | if err_checkout: | ||
| 2086 | print_and_log("error: Checking out local projects failed.") | ||
| 2087 | if failing_checkout_repos: | ||
| 2088 | logger.error( | ||
| 2089 | "Failing repos (checkout):\n%s", | ||
| 2090 | "\n".join(sorted(failing_checkout_repos)), | ||
| 2091 | ) | ||
| 2092 | logger.error( | ||
| 2093 | 'Try re-running with "-j1 --fail-fast" to exit at the first error.' | ||
| 2094 | ) | ||
| 2095 | raise SyncError(aggregate_errors=errors) | ||
| 2096 | |||
| 2057 | def _SyncPhased( | 2097 | def _SyncPhased( |
| 2058 | self, | 2098 | self, |
| 2059 | opt, | 2099 | opt, |
| @@ -2130,29 +2170,14 @@ later is required to fix a server side protocol bug. | |||
| 2130 | 2170 | ||
| 2131 | # If we saw an error, exit with code 1 so that other scripts can check. | 2171 | # If we saw an error, exit with code 1 so that other scripts can check. |
| 2132 | if err_event.is_set(): | 2172 | if err_event.is_set(): |
| 2133 | 2173 | self._ReportErrors( | |
| 2134 | def print_and_log(err_msg): | 2174 | errors, |
| 2135 | self.git_event_log.ErrorEvent(err_msg) | 2175 | err_network_sync=err_network_sync, |
| 2136 | logger.error("%s", err_msg) | 2176 | err_checkout=err_checkout, |
| 2137 | 2177 | failing_checkout_repos=err_results, | |
| 2138 | print_and_log("error: Unable to fully sync the tree") | 2178 | err_update_projects=err_update_projects, |
| 2139 | if err_network_sync: | 2179 | err_update_linkfiles=err_update_linkfiles, |
| 2140 | print_and_log("error: Downloading network changes failed.") | ||
| 2141 | if err_update_projects: | ||
| 2142 | print_and_log("error: Updating local project lists failed.") | ||
| 2143 | if err_update_linkfiles: | ||
| 2144 | print_and_log("error: Updating copyfiles or linkfiles failed.") | ||
| 2145 | if err_checkout: | ||
| 2146 | print_and_log("error: Checking out local projects failed.") | ||
| 2147 | if err_results: | ||
| 2148 | # Don't log repositories, as it may contain sensitive info. | ||
| 2149 | logger.error("Failing repos:\n%s", "\n".join(err_results)) | ||
| 2150 | # Not useful to log. | ||
| 2151 | logger.error( | ||
| 2152 | 'Try re-running with "-j1 --fail-fast" to exit at the first ' | ||
| 2153 | "error." | ||
| 2154 | ) | 2180 | ) |
| 2155 | raise SyncError(aggregate_errors=errors) | ||
| 2156 | 2181 | ||
| 2157 | @classmethod | 2182 | @classmethod |
| 2158 | def _SyncOneProject(cls, opt, project_index, project) -> _SyncResult: | 2183 | def _SyncOneProject(cls, opt, project_index, project) -> _SyncResult: |
| @@ -2375,8 +2400,16 @@ later is required to fix a server side protocol bug. | |||
| 2375 | err_event.set() | 2400 | err_event.set() |
| 2376 | if result.fetch_error: | 2401 | if result.fetch_error: |
| 2377 | errors.append(result.fetch_error) | 2402 | errors.append(result.fetch_error) |
| 2403 | self._interleaved_err_network = True | ||
| 2404 | self._interleaved_err_network_results.append( | ||
| 2405 | result.relpath | ||
| 2406 | ) | ||
| 2378 | if result.checkout_error: | 2407 | if result.checkout_error: |
| 2379 | errors.append(result.checkout_error) | 2408 | errors.append(result.checkout_error) |
| 2409 | self._interleaved_err_checkout = True | ||
| 2410 | self._interleaved_err_checkout_results.append( | ||
| 2411 | result.relpath | ||
| 2412 | ) | ||
| 2380 | 2413 | ||
| 2381 | if not ret and opt.fail_fast: | 2414 | if not ret and opt.fail_fast: |
| 2382 | if pool: | 2415 | if pool: |
| @@ -2407,6 +2440,12 @@ later is required to fix a server side protocol bug. | |||
| 2407 | 2. Projects that share git objects are processed serially to prevent | 2440 | 2. Projects that share git objects are processed serially to prevent |
| 2408 | race conditions. | 2441 | race conditions. |
| 2409 | """ | 2442 | """ |
| 2443 | # Temporary state for tracking errors in interleaved mode. | ||
| 2444 | self._interleaved_err_network = False | ||
| 2445 | self._interleaved_err_network_results = [] | ||
| 2446 | self._interleaved_err_checkout = False | ||
| 2447 | self._interleaved_err_checkout_results = [] | ||
| 2448 | |||
| 2410 | err_event = multiprocessing.Event() | 2449 | err_event = multiprocessing.Event() |
| 2411 | synced_relpaths = set() | 2450 | synced_relpaths = set() |
| 2412 | project_list = list(all_projects) | 2451 | project_list = list(all_projects) |
| @@ -2520,17 +2559,23 @@ later is required to fix a server side protocol bug. | |||
| 2520 | 2559 | ||
| 2521 | pm.end() | 2560 | pm.end() |
| 2522 | 2561 | ||
| 2523 | self._UpdateManifestLists(opt, err_event, errors) | 2562 | err_update_projects, err_update_linkfiles = self._UpdateManifestLists( |
| 2563 | opt, err_event, errors | ||
| 2564 | ) | ||
| 2524 | if not self.outer_client.manifest.IsArchive: | 2565 | if not self.outer_client.manifest.IsArchive: |
| 2525 | self._GCProjects(project_list, opt, err_event) | 2566 | self._GCProjects(project_list, opt, err_event) |
| 2526 | 2567 | ||
| 2527 | self._PrintManifestNotices(opt) | 2568 | self._PrintManifestNotices(opt) |
| 2528 | if err_event.is_set(): | 2569 | if err_event.is_set(): |
| 2529 | # TODO(b/421935613): Log errors better like SyncPhased. | 2570 | self._ReportErrors( |
| 2530 | logger.error( | 2571 | errors, |
| 2531 | "error: Unable to fully sync the tree in interleaved mode." | 2572 | err_network_sync=self._interleaved_err_network, |
| 2573 | failing_network_repos=self._interleaved_err_network_results, | ||
| 2574 | err_checkout=self._interleaved_err_checkout, | ||
| 2575 | failing_checkout_repos=self._interleaved_err_checkout_results, | ||
| 2576 | err_update_projects=err_update_projects, | ||
| 2577 | err_update_linkfiles=err_update_linkfiles, | ||
| 2532 | ) | 2578 | ) |
| 2533 | raise SyncError(aggregate_errors=errors) | ||
| 2534 | 2579 | ||
| 2535 | 2580 | ||
| 2536 | def _PostRepoUpgrade(manifest, quiet=False): | 2581 | def _PostRepoUpgrade(manifest, quiet=False): |
