sync: Share final error handling logic between sync modes
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>
This commit is contained in:
parent
df3c4017f9
commit
99b5a17f2c
1 changed files with 72 additions and 27 deletions
|
@ -2054,6 +2054,46 @@ later is required to fix a server side protocol bug.
|
||||||
raise SyncFailFastError(aggregate_errors=errors)
|
raise SyncFailFastError(aggregate_errors=errors)
|
||||||
return err_update_projects, err_update_linkfiles
|
return err_update_projects, err_update_linkfiles
|
||||||
|
|
||||||
|
def _ReportErrors(
|
||||||
|
self,
|
||||||
|
errors,
|
||||||
|
err_network_sync=False,
|
||||||
|
failing_network_repos=None,
|
||||||
|
err_checkout=False,
|
||||||
|
failing_checkout_repos=None,
|
||||||
|
err_update_projects=False,
|
||||||
|
err_update_linkfiles=False,
|
||||||
|
):
|
||||||
|
"""Logs detailed error messages and raises a SyncError."""
|
||||||
|
|
||||||
|
def print_and_log(err_msg):
|
||||||
|
self.git_event_log.ErrorEvent(err_msg)
|
||||||
|
logger.error("%s", err_msg)
|
||||||
|
|
||||||
|
print_and_log("error: Unable to fully sync the tree")
|
||||||
|
if err_network_sync:
|
||||||
|
print_and_log("error: Downloading network changes failed.")
|
||||||
|
if failing_network_repos:
|
||||||
|
logger.error(
|
||||||
|
"Failing repos (network):\n%s",
|
||||||
|
"\n".join(sorted(failing_network_repos)),
|
||||||
|
)
|
||||||
|
if err_update_projects:
|
||||||
|
print_and_log("error: Updating local project lists failed.")
|
||||||
|
if err_update_linkfiles:
|
||||||
|
print_and_log("error: Updating copyfiles or linkfiles failed.")
|
||||||
|
if err_checkout:
|
||||||
|
print_and_log("error: Checking out local projects failed.")
|
||||||
|
if failing_checkout_repos:
|
||||||
|
logger.error(
|
||||||
|
"Failing repos (checkout):\n%s",
|
||||||
|
"\n".join(sorted(failing_checkout_repos)),
|
||||||
|
)
|
||||||
|
logger.error(
|
||||||
|
'Try re-running with "-j1 --fail-fast" to exit at the first error.'
|
||||||
|
)
|
||||||
|
raise SyncError(aggregate_errors=errors)
|
||||||
|
|
||||||
def _SyncPhased(
|
def _SyncPhased(
|
||||||
self,
|
self,
|
||||||
opt,
|
opt,
|
||||||
|
@ -2130,29 +2170,14 @@ later is required to fix a server side protocol bug.
|
||||||
|
|
||||||
# If we saw an error, exit with code 1 so that other scripts can check.
|
# If we saw an error, exit with code 1 so that other scripts can check.
|
||||||
if err_event.is_set():
|
if err_event.is_set():
|
||||||
|
self._ReportErrors(
|
||||||
def print_and_log(err_msg):
|
errors,
|
||||||
self.git_event_log.ErrorEvent(err_msg)
|
err_network_sync=err_network_sync,
|
||||||
logger.error("%s", err_msg)
|
err_checkout=err_checkout,
|
||||||
|
failing_checkout_repos=err_results,
|
||||||
print_and_log("error: Unable to fully sync the tree")
|
err_update_projects=err_update_projects,
|
||||||
if err_network_sync:
|
err_update_linkfiles=err_update_linkfiles,
|
||||||
print_and_log("error: Downloading network changes failed.")
|
|
||||||
if err_update_projects:
|
|
||||||
print_and_log("error: Updating local project lists failed.")
|
|
||||||
if err_update_linkfiles:
|
|
||||||
print_and_log("error: Updating copyfiles or linkfiles failed.")
|
|
||||||
if err_checkout:
|
|
||||||
print_and_log("error: Checking out local projects failed.")
|
|
||||||
if err_results:
|
|
||||||
# Don't log repositories, as it may contain sensitive info.
|
|
||||||
logger.error("Failing repos:\n%s", "\n".join(err_results))
|
|
||||||
# Not useful to log.
|
|
||||||
logger.error(
|
|
||||||
'Try re-running with "-j1 --fail-fast" to exit at the first '
|
|
||||||
"error."
|
|
||||||
)
|
)
|
||||||
raise SyncError(aggregate_errors=errors)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _SyncOneProject(cls, opt, project_index, project) -> _SyncResult:
|
def _SyncOneProject(cls, opt, project_index, project) -> _SyncResult:
|
||||||
|
@ -2375,8 +2400,16 @@ later is required to fix a server side protocol bug.
|
||||||
err_event.set()
|
err_event.set()
|
||||||
if result.fetch_error:
|
if result.fetch_error:
|
||||||
errors.append(result.fetch_error)
|
errors.append(result.fetch_error)
|
||||||
|
self._interleaved_err_network = True
|
||||||
|
self._interleaved_err_network_results.append(
|
||||||
|
result.relpath
|
||||||
|
)
|
||||||
if result.checkout_error:
|
if result.checkout_error:
|
||||||
errors.append(result.checkout_error)
|
errors.append(result.checkout_error)
|
||||||
|
self._interleaved_err_checkout = True
|
||||||
|
self._interleaved_err_checkout_results.append(
|
||||||
|
result.relpath
|
||||||
|
)
|
||||||
|
|
||||||
if not ret and opt.fail_fast:
|
if not ret and opt.fail_fast:
|
||||||
if pool:
|
if pool:
|
||||||
|
@ -2407,6 +2440,12 @@ later is required to fix a server side protocol bug.
|
||||||
2. Projects that share git objects are processed serially to prevent
|
2. Projects that share git objects are processed serially to prevent
|
||||||
race conditions.
|
race conditions.
|
||||||
"""
|
"""
|
||||||
|
# Temporary state for tracking errors in interleaved mode.
|
||||||
|
self._interleaved_err_network = False
|
||||||
|
self._interleaved_err_network_results = []
|
||||||
|
self._interleaved_err_checkout = False
|
||||||
|
self._interleaved_err_checkout_results = []
|
||||||
|
|
||||||
err_event = multiprocessing.Event()
|
err_event = multiprocessing.Event()
|
||||||
synced_relpaths = set()
|
synced_relpaths = set()
|
||||||
project_list = list(all_projects)
|
project_list = list(all_projects)
|
||||||
|
@ -2520,17 +2559,23 @@ later is required to fix a server side protocol bug.
|
||||||
|
|
||||||
pm.end()
|
pm.end()
|
||||||
|
|
||||||
self._UpdateManifestLists(opt, err_event, errors)
|
err_update_projects, err_update_linkfiles = self._UpdateManifestLists(
|
||||||
|
opt, err_event, errors
|
||||||
|
)
|
||||||
if not self.outer_client.manifest.IsArchive:
|
if not self.outer_client.manifest.IsArchive:
|
||||||
self._GCProjects(project_list, opt, err_event)
|
self._GCProjects(project_list, opt, err_event)
|
||||||
|
|
||||||
self._PrintManifestNotices(opt)
|
self._PrintManifestNotices(opt)
|
||||||
if err_event.is_set():
|
if err_event.is_set():
|
||||||
# TODO(b/421935613): Log errors better like SyncPhased.
|
self._ReportErrors(
|
||||||
logger.error(
|
errors,
|
||||||
"error: Unable to fully sync the tree in interleaved mode."
|
err_network_sync=self._interleaved_err_network,
|
||||||
|
failing_network_repos=self._interleaved_err_network_results,
|
||||||
|
err_checkout=self._interleaved_err_checkout,
|
||||||
|
failing_checkout_repos=self._interleaved_err_checkout_results,
|
||||||
|
err_update_projects=err_update_projects,
|
||||||
|
err_update_linkfiles=err_update_linkfiles,
|
||||||
)
|
)
|
||||||
raise SyncError(aggregate_errors=errors)
|
|
||||||
|
|
||||||
|
|
||||||
def _PostRepoUpgrade(manifest, quiet=False):
|
def _PostRepoUpgrade(manifest, quiet=False):
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue