diff options
| -rw-r--r-- | repo_logging.py | 22 | ||||
| -rw-r--r-- | subcmds/sync.py | 191 | ||||
| -rw-r--r-- | tests/test_repo_logging.py | 31 |
3 files changed, 102 insertions, 142 deletions
diff --git a/repo_logging.py b/repo_logging.py index b748df4f..e94af7df 100644 --- a/repo_logging.py +++ b/repo_logging.py | |||
| @@ -15,7 +15,7 @@ | |||
| 15 | """Logic for printing user-friendly logs in repo.""" | 15 | """Logic for printing user-friendly logs in repo.""" |
| 16 | 16 | ||
| 17 | import logging | 17 | import logging |
| 18 | import multiprocessing | 18 | from typing import Any, List |
| 19 | 19 | ||
| 20 | from color import Coloring | 20 | from color import Coloring |
| 21 | 21 | ||
| @@ -45,31 +45,25 @@ class ConfigMock: | |||
| 45 | class RepoLogger(logging.Logger): | 45 | class RepoLogger(logging.Logger): |
| 46 | """Repo Logging Module.""" | 46 | """Repo Logging Module.""" |
| 47 | 47 | ||
| 48 | # Aggregates error-level logs. This is used to generate an error summary | 48 | def __init__(self, name: str, config=None, **kwargs): |
| 49 | # section at the end of a command execution. | ||
| 50 | errors = multiprocessing.Manager().list() | ||
| 51 | |||
| 52 | def __init__(self, name, config=None, **kwargs): | ||
| 53 | super().__init__(name, **kwargs) | 49 | super().__init__(name, **kwargs) |
| 54 | self.config = config if config else ConfigMock() | 50 | self.config = config if config else ConfigMock() |
| 55 | self.colorer = LogColoring(self.config) | 51 | self.colorer = LogColoring(self.config) |
| 56 | 52 | ||
| 57 | def error(self, msg, *args, **kwargs): | 53 | def error(self, msg: Any, *args, **kwargs): |
| 58 | """Print and aggregate error-level logs.""" | 54 | """Print and aggregate error-level logs.""" |
| 59 | colored_error = self.colorer.error(msg, *args) | 55 | colored_error = self.colorer.error(str(msg), *args) |
| 60 | RepoLogger.errors.append(colored_error) | ||
| 61 | |||
| 62 | super().error(colored_error, **kwargs) | 56 | super().error(colored_error, **kwargs) |
| 63 | 57 | ||
| 64 | def warning(self, msg, *args, **kwargs): | 58 | def warning(self, msg: Any, *args, **kwargs): |
| 65 | """Print warning-level logs with coloring.""" | 59 | """Print warning-level logs with coloring.""" |
| 66 | colored_warning = self.colorer.warning(msg, *args) | 60 | colored_warning = self.colorer.warning(str(msg), *args) |
| 67 | super().warning(colored_warning, **kwargs) | 61 | super().warning(colored_warning, **kwargs) |
| 68 | 62 | ||
| 69 | def log_aggregated_errors(self): | 63 | def log_aggregated_errors(self, errors: List[Exception]): |
| 70 | """Print all aggregated logs.""" | 64 | """Print all aggregated logs.""" |
| 71 | super().error(self.colorer.error(SEPARATOR)) | 65 | super().error(self.colorer.error(SEPARATOR)) |
| 72 | super().error( | 66 | super().error( |
| 73 | self.colorer.error("Repo command failed due to following errors:") | 67 | self.colorer.error("Repo command failed due to following errors:") |
| 74 | ) | 68 | ) |
| 75 | super().error("\n".join(RepoLogger.errors)) | 69 | super().error("\n".join(map(str, errors))) |
diff --git a/subcmds/sync.py b/subcmds/sync.py index 13c964b2..7ccd680f 100644 --- a/subcmds/sync.py +++ b/subcmds/sync.py | |||
| @@ -22,7 +22,6 @@ import netrc | |||
| 22 | import optparse | 22 | import optparse |
| 23 | import os | 23 | import os |
| 24 | import socket | 24 | import socket |
| 25 | import sys | ||
| 26 | import tempfile | 25 | import tempfile |
| 27 | import time | 26 | import time |
| 28 | from typing import List, NamedTuple, Set | 27 | from typing import List, NamedTuple, Set |
| @@ -74,6 +73,7 @@ from project import DeleteWorktreeError | |||
| 74 | from project import Project | 73 | from project import Project |
| 75 | from project import RemoteSpec | 74 | from project import RemoteSpec |
| 76 | from project import SyncBuffer | 75 | from project import SyncBuffer |
| 76 | from repo_logging import RepoLogger | ||
| 77 | from repo_trace import Trace | 77 | from repo_trace import Trace |
| 78 | import ssh | 78 | import ssh |
| 79 | from wrapper import Wrapper | 79 | from wrapper import Wrapper |
| @@ -88,6 +88,8 @@ _AUTO_GC = os.environ.get(_REPO_AUTO_GC) == "1" | |||
| 88 | 88 | ||
| 89 | _REPO_ALLOW_SHALLOW = os.environ.get("REPO_ALLOW_SHALLOW") | 89 | _REPO_ALLOW_SHALLOW = os.environ.get("REPO_ALLOW_SHALLOW") |
| 90 | 90 | ||
| 91 | logger = RepoLogger(__file__) | ||
| 92 | |||
| 91 | 93 | ||
| 92 | class _FetchOneResult(NamedTuple): | 94 | class _FetchOneResult(NamedTuple): |
| 93 | """_FetchOne return value. | 95 | """_FetchOne return value. |
| @@ -580,9 +582,10 @@ later is required to fix a server side protocol bug. | |||
| 580 | superproject_logging_data["superproject"] = False | 582 | superproject_logging_data["superproject"] = False |
| 581 | superproject_logging_data["noworktree"] = True | 583 | superproject_logging_data["noworktree"] = True |
| 582 | if opt.use_superproject is not False: | 584 | if opt.use_superproject is not False: |
| 583 | print( | 585 | logger.warning( |
| 584 | f"{m.path_prefix}: not using superproject because " | 586 | "%s: not using superproject because there is no " |
| 585 | "there is no working tree." | 587 | "working tree.", |
| 588 | m.path_prefix, | ||
| 586 | ) | 589 | ) |
| 587 | 590 | ||
| 588 | if not use_super: | 591 | if not use_super: |
| @@ -602,13 +605,13 @@ later is required to fix a server side protocol bug. | |||
| 602 | need_unload = True | 605 | need_unload = True |
| 603 | else: | 606 | else: |
| 604 | if print_messages: | 607 | if print_messages: |
| 605 | print( | 608 | logger.warning( |
| 606 | f"{m.path_prefix}: warning: Update of revisionId from " | 609 | "%s: warning: Update of revisionId from superproject " |
| 607 | "superproject has failed, repo sync will not use " | 610 | "has failed, repo sync will not use superproject to " |
| 608 | "superproject to fetch the source. ", | 611 | "fetch the source. Please resync with the " |
| 609 | "Please resync with the --no-use-superproject option " | 612 | "--no-use-superproject option to avoid this repo " |
| 610 | "to avoid this repo warning.", | 613 | "warning.", |
| 611 | file=sys.stderr, | 614 | m.path_prefix, |
| 612 | ) | 615 | ) |
| 613 | if update_result.fatal and opt.use_superproject is not None: | 616 | if update_result.fatal and opt.use_superproject is not None: |
| 614 | raise SuperprojectError() | 617 | raise SuperprojectError() |
| @@ -676,21 +679,22 @@ later is required to fix a server side protocol bug. | |||
| 676 | print("\n" + output.rstrip()) | 679 | print("\n" + output.rstrip()) |
| 677 | 680 | ||
| 678 | if not success: | 681 | if not success: |
| 679 | print( | 682 | logger.error( |
| 680 | "error: Cannot fetch %s from %s" | 683 | "error: Cannot fetch %s from %s", |
| 681 | % (project.name, project.remote.url), | 684 | project.name, |
| 682 | file=sys.stderr, | 685 | project.remote.url, |
| 683 | ) | 686 | ) |
| 684 | except KeyboardInterrupt: | 687 | except KeyboardInterrupt: |
| 685 | print(f"Keyboard interrupt while processing {project.name}") | 688 | logger.error("Keyboard interrupt while processing %s", project.name) |
| 686 | except GitError as e: | 689 | except GitError as e: |
| 687 | print("error.GitError: Cannot fetch %s" % str(e), file=sys.stderr) | 690 | logger.error("error.GitError: Cannot fetch %s", e) |
| 688 | errors.append(e) | 691 | errors.append(e) |
| 689 | except Exception as e: | 692 | except Exception as e: |
| 690 | print( | 693 | logger.error( |
| 691 | "error: Cannot fetch %s (%s: %s)" | 694 | "error: Cannot fetch %s (%s: %s)", |
| 692 | % (project.name, type(e).__name__, str(e)), | 695 | project.name, |
| 693 | file=sys.stderr, | 696 | type(e).__name__, |
| 697 | e, | ||
| 694 | ) | 698 | ) |
| 695 | del self._sync_dict[k] | 699 | del self._sync_dict[k] |
| 696 | errors.append(e) | 700 | errors.append(e) |
| @@ -887,14 +891,13 @@ later is required to fix a server side protocol bug. | |||
| 887 | if opt.network_only: | 891 | if opt.network_only: |
| 888 | # Bail out now; the rest touches the working tree. | 892 | # Bail out now; the rest touches the working tree. |
| 889 | if err_event.is_set(): | 893 | if err_event.is_set(): |
| 890 | print( | 894 | e = SyncError( |
| 891 | "\nerror: Exited sync due to fetch errors.\n", | ||
| 892 | file=sys.stderr, | ||
| 893 | ) | ||
| 894 | raise SyncError( | ||
| 895 | "error: Exited sync due to fetch errors.", | 895 | "error: Exited sync due to fetch errors.", |
| 896 | aggregate_errors=errors, | 896 | aggregate_errors=errors, |
| 897 | ) | 897 | ) |
| 898 | |||
| 899 | logger.error(e) | ||
| 900 | raise e | ||
| 898 | return _FetchMainResult([], errors) | 901 | return _FetchMainResult([], errors) |
| 899 | 902 | ||
| 900 | # Iteratively fetch missing and/or nested unregistered submodules. | 903 | # Iteratively fetch missing and/or nested unregistered submodules. |
| @@ -954,22 +957,21 @@ later is required to fix a server side protocol bug. | |||
| 954 | ) | 957 | ) |
| 955 | success = syncbuf.Finish() | 958 | success = syncbuf.Finish() |
| 956 | except GitError as e: | 959 | except GitError as e: |
| 957 | print( | 960 | logger.error( |
| 958 | "error.GitError: Cannot checkout %s: %s" | 961 | "error.GitError: Cannot checkout %s: %s", project.name, e |
| 959 | % (project.name, str(e)), | ||
| 960 | file=sys.stderr, | ||
| 961 | ) | 962 | ) |
| 962 | errors.append(e) | 963 | errors.append(e) |
| 963 | except Exception as e: | 964 | except Exception as e: |
| 964 | print( | 965 | logger.error( |
| 965 | "error: Cannot checkout %s: %s: %s" | 966 | "error: Cannot checkout %s: %s: %s", |
| 966 | % (project.name, type(e).__name__, str(e)), | 967 | project.name, |
| 967 | file=sys.stderr, | 968 | type(e).__name__, |
| 969 | e, | ||
| 968 | ) | 970 | ) |
| 969 | raise | 971 | raise |
| 970 | 972 | ||
| 971 | if not success: | 973 | if not success: |
| 972 | print("error: Cannot checkout %s" % (project.name), file=sys.stderr) | 974 | logger.error("error: Cannot checkout %s", project.name) |
| 973 | finish = time.time() | 975 | finish = time.time() |
| 974 | return _CheckoutOneResult(success, errors, project, start, finish) | 976 | return _CheckoutOneResult(success, errors, project, start, finish) |
| 975 | 977 | ||
| @@ -1088,25 +1090,27 @@ later is required to fix a server side protocol bug. | |||
| 1088 | ) | 1090 | ) |
| 1089 | if expected: | 1091 | if expected: |
| 1090 | if not opt.quiet: | 1092 | if not opt.quiet: |
| 1091 | print( | 1093 | logger.info( |
| 1092 | "\r%s: Shared project %s found, disabling pruning." | 1094 | "%s: Shared project %s found, disabling pruning.", |
| 1093 | % (relpath, project.name) | 1095 | relpath, |
| 1096 | project.name, | ||
| 1094 | ) | 1097 | ) |
| 1098 | |||
| 1095 | if git_require((2, 7, 0)): | 1099 | if git_require((2, 7, 0)): |
| 1096 | project.EnableRepositoryExtension("preciousObjects") | 1100 | project.EnableRepositoryExtension("preciousObjects") |
| 1097 | else: | 1101 | else: |
| 1098 | # This isn't perfect, but it's the best we can do with old | 1102 | # This isn't perfect, but it's the best we can do with old |
| 1099 | # git. | 1103 | # git. |
| 1100 | print( | 1104 | logger.warning( |
| 1101 | "\r%s: WARNING: shared projects are unreliable when " | 1105 | "%s: WARNING: shared projects are unreliable when " |
| 1102 | "using old versions of git; please upgrade to " | 1106 | "using old versions of git; please upgrade to " |
| 1103 | "git-2.7.0+." % (relpath,), | 1107 | "git-2.7.0+.", |
| 1104 | file=sys.stderr, | 1108 | relpath, |
| 1105 | ) | 1109 | ) |
| 1106 | project.config.SetString("gc.pruneExpire", "never") | 1110 | project.config.SetString("gc.pruneExpire", "never") |
| 1107 | else: | 1111 | else: |
| 1108 | if not opt.quiet: | 1112 | if not opt.quiet: |
| 1109 | print(f"\r{relpath}: not shared, disabling pruning.") | 1113 | logger.info("%s: not shared, disabling pruning.", relpath) |
| 1110 | project.config.SetString("extensions.preciousObjects", None) | 1114 | project.config.SetString("extensions.preciousObjects", None) |
| 1111 | project.config.SetString("gc.pruneExpire", None) | 1115 | project.config.SetString("gc.pruneExpire", None) |
| 1112 | 1116 | ||
| @@ -1303,10 +1307,9 @@ later is required to fix a server side protocol bug. | |||
| 1303 | try: | 1307 | try: |
| 1304 | old_copylinkfile_paths = json.load(fp) | 1308 | old_copylinkfile_paths = json.load(fp) |
| 1305 | except Exception: | 1309 | except Exception: |
| 1306 | print( | 1310 | logger.error( |
| 1307 | "error: %s is not a json formatted file." | 1311 | "error: %s is not a json formatted file.", |
| 1308 | % copylinkfile_path, | 1312 | copylinkfile_path, |
| 1309 | file=sys.stderr, | ||
| 1310 | ) | 1313 | ) |
| 1311 | platform_utils.remove(copylinkfile_path) | 1314 | platform_utils.remove(copylinkfile_path) |
| 1312 | raise | 1315 | raise |
| @@ -1341,7 +1344,7 @@ later is required to fix a server side protocol bug. | |||
| 1341 | 1344 | ||
| 1342 | manifest_server = manifest.manifest_server | 1345 | manifest_server = manifest.manifest_server |
| 1343 | if not opt.quiet: | 1346 | if not opt.quiet: |
| 1344 | print("Using manifest server %s" % manifest_server) | 1347 | logger.info("Using manifest server %s", manifest_server) |
| 1345 | 1348 | ||
| 1346 | if "@" not in manifest_server: | 1349 | if "@" not in manifest_server: |
| 1347 | username = None | 1350 | username = None |
| @@ -1363,15 +1366,12 @@ later is required to fix a server side protocol bug. | |||
| 1363 | if auth: | 1366 | if auth: |
| 1364 | username, _account, password = auth | 1367 | username, _account, password = auth |
| 1365 | else: | 1368 | else: |
| 1366 | print( | 1369 | logger.error( |
| 1367 | "No credentials found for %s in .netrc" | 1370 | "No credentials found for %s in .netrc", |
| 1368 | % parse_result.hostname, | 1371 | parse_result.hostname, |
| 1369 | file=sys.stderr, | ||
| 1370 | ) | 1372 | ) |
| 1371 | except netrc.NetrcParseError as e: | 1373 | except netrc.NetrcParseError as e: |
| 1372 | print( | 1374 | logger.error("Error parsing .netrc file: %s", e) |
| 1373 | "Error parsing .netrc file: %s" % e, file=sys.stderr | ||
| 1374 | ) | ||
| 1375 | 1375 | ||
| 1376 | if username and password: | 1376 | if username and password: |
| 1377 | manifest_server = manifest_server.replace( | 1377 | manifest_server = manifest_server.replace( |
| @@ -1517,10 +1517,9 @@ later is required to fix a server side protocol bug. | |||
| 1517 | 1517 | ||
| 1518 | def ValidateOptions(self, opt, args): | 1518 | def ValidateOptions(self, opt, args): |
| 1519 | if opt.force_broken: | 1519 | if opt.force_broken: |
| 1520 | print( | 1520 | logger.warning( |
| 1521 | "warning: -f/--force-broken is now the default behavior, and " | 1521 | "warning: -f/--force-broken is now the default behavior, and " |
| 1522 | "the options are deprecated", | 1522 | "the options are deprecated" |
| 1523 | file=sys.stderr, | ||
| 1524 | ) | 1523 | ) |
| 1525 | if opt.network_only and opt.detach_head: | 1524 | if opt.network_only and opt.detach_head: |
| 1526 | self.OptionParser.error("cannot combine -n and -d") | 1525 | self.OptionParser.error("cannot combine -n and -d") |
| @@ -1545,11 +1544,12 @@ later is required to fix a server side protocol bug. | |||
| 1545 | opt.prune = True | 1544 | opt.prune = True |
| 1546 | 1545 | ||
| 1547 | if opt.auto_gc is None and _AUTO_GC: | 1546 | if opt.auto_gc is None and _AUTO_GC: |
| 1548 | print( | 1547 | logger.error( |
| 1549 | f"Will run `git gc --auto` because {_REPO_AUTO_GC} is set.", | 1548 | "Will run `git gc --auto` because %s is set. %s is deprecated " |
| 1550 | f"{_REPO_AUTO_GC} is deprecated and will be removed in a ", | 1549 | "and will be removed in a future release. Use `--auto-gc` " |
| 1551 | "future release. Use `--auto-gc` instead.", | 1550 | "instead.", |
| 1552 | file=sys.stderr, | 1551 | _REPO_AUTO_GC, |
| 1552 | _REPO_AUTO_GC, | ||
| 1553 | ) | 1553 | ) |
| 1554 | opt.auto_gc = True | 1554 | opt.auto_gc = True |
| 1555 | 1555 | ||
| @@ -1626,10 +1626,10 @@ later is required to fix a server side protocol bug. | |||
| 1626 | try: | 1626 | try: |
| 1627 | platform_utils.remove(smart_sync_manifest_path) | 1627 | platform_utils.remove(smart_sync_manifest_path) |
| 1628 | except OSError as e: | 1628 | except OSError as e: |
| 1629 | print( | 1629 | logger.error( |
| 1630 | "error: failed to remove existing smart sync override " | 1630 | "error: failed to remove existing smart sync override " |
| 1631 | "manifest: %s" % e, | 1631 | "manifest: %s", |
| 1632 | file=sys.stderr, | 1632 | e, |
| 1633 | ) | 1633 | ) |
| 1634 | 1634 | ||
| 1635 | err_event = multiprocessing.Event() | 1635 | err_event = multiprocessing.Event() |
| @@ -1640,11 +1640,10 @@ later is required to fix a server side protocol bug. | |||
| 1640 | if cb: | 1640 | if cb: |
| 1641 | base = rp.GetBranch(cb).merge | 1641 | base = rp.GetBranch(cb).merge |
| 1642 | if not base or not base.startswith("refs/heads/"): | 1642 | if not base or not base.startswith("refs/heads/"): |
| 1643 | print( | 1643 | logger.warning( |
| 1644 | "warning: repo is not tracking a remote branch, so it will " | 1644 | "warning: repo is not tracking a remote branch, so it will " |
| 1645 | "not receive updates; run `repo init --repo-rev=stable` to " | 1645 | "not receive updates; run `repo init --repo-rev=stable` to " |
| 1646 | "fix.", | 1646 | "fix." |
| 1647 | file=sys.stderr, | ||
| 1648 | ) | 1647 | ) |
| 1649 | 1648 | ||
| 1650 | for m in self.ManifestList(opt): | 1649 | for m in self.ManifestList(opt): |
| @@ -1667,7 +1666,7 @@ later is required to fix a server side protocol bug. | |||
| 1667 | if opt.mp_update: | 1666 | if opt.mp_update: |
| 1668 | self._UpdateAllManifestProjects(opt, mp, manifest_name) | 1667 | self._UpdateAllManifestProjects(opt, mp, manifest_name) |
| 1669 | else: | 1668 | else: |
| 1670 | print("Skipping update of local manifest project.") | 1669 | logger.info("Skipping update of local manifest project.") |
| 1671 | 1670 | ||
| 1672 | # Now that the manifests are up-to-date, setup options whose defaults | 1671 | # Now that the manifests are up-to-date, setup options whose defaults |
| 1673 | # might be in the manifest. | 1672 | # might be in the manifest. |
| @@ -1719,12 +1718,11 @@ later is required to fix a server side protocol bug. | |||
| 1719 | if err_event.is_set(): | 1718 | if err_event.is_set(): |
| 1720 | err_network_sync = True | 1719 | err_network_sync = True |
| 1721 | if opt.fail_fast: | 1720 | if opt.fail_fast: |
| 1722 | print( | 1721 | logger.error( |
| 1723 | "\nerror: Exited sync due to fetch errors.\n" | 1722 | "error: Exited sync due to fetch errors.\n" |
| 1724 | "Local checkouts *not* updated. Resolve network issues " | 1723 | "Local checkouts *not* updated. Resolve network issues " |
| 1725 | "& retry.\n" | 1724 | "& retry.\n" |
| 1726 | "`repo sync -l` will update some local checkouts.", | 1725 | "`repo sync -l` will update some local checkouts." |
| 1727 | file=sys.stderr, | ||
| 1728 | ) | 1726 | ) |
| 1729 | raise SyncFailFastError(aggregate_errors=errors) | 1727 | raise SyncFailFastError(aggregate_errors=errors) |
| 1730 | 1728 | ||
| @@ -1742,10 +1740,7 @@ later is required to fix a server side protocol bug. | |||
| 1742 | if isinstance(e, DeleteWorktreeError): | 1740 | if isinstance(e, DeleteWorktreeError): |
| 1743 | errors.extend(e.aggregate_errors) | 1741 | errors.extend(e.aggregate_errors) |
| 1744 | if opt.fail_fast: | 1742 | if opt.fail_fast: |
| 1745 | print( | 1743 | logger.error("error: Local checkouts *not* updated.") |
| 1746 | "\nerror: Local checkouts *not* updated.", | ||
| 1747 | file=sys.stderr, | ||
| 1748 | ) | ||
| 1749 | raise SyncFailFastError(aggregate_errors=errors) | 1744 | raise SyncFailFastError(aggregate_errors=errors) |
| 1750 | 1745 | ||
| 1751 | err_update_linkfiles = False | 1746 | err_update_linkfiles = False |
| @@ -1756,9 +1751,8 @@ later is required to fix a server side protocol bug. | |||
| 1756 | errors.append(e) | 1751 | errors.append(e) |
| 1757 | err_event.set() | 1752 | err_event.set() |
| 1758 | if opt.fail_fast: | 1753 | if opt.fail_fast: |
| 1759 | print( | 1754 | logger.error( |
| 1760 | "\nerror: Local update copyfile or linkfile failed.", | 1755 | "error: Local update copyfile or linkfile failed." |
| 1761 | file=sys.stderr, | ||
| 1762 | ) | 1756 | ) |
| 1763 | raise SyncFailFastError(aggregate_errors=errors) | 1757 | raise SyncFailFastError(aggregate_errors=errors) |
| 1764 | 1758 | ||
| @@ -1781,12 +1775,10 @@ later is required to fix a server side protocol bug. | |||
| 1781 | 1775 | ||
| 1782 | # If we saw an error, exit with code 1 so that other scripts can check. | 1776 | # If we saw an error, exit with code 1 so that other scripts can check. |
| 1783 | if err_event.is_set(): | 1777 | if err_event.is_set(): |
| 1784 | # Add a new line so it's easier to read. | ||
| 1785 | print("\n", file=sys.stderr) | ||
| 1786 | 1778 | ||
| 1787 | def print_and_log(err_msg): | 1779 | def print_and_log(err_msg): |
| 1788 | self.git_event_log.ErrorEvent(err_msg) | 1780 | self.git_event_log.ErrorEvent(err_msg) |
| 1789 | print(err_msg, file=sys.stderr) | 1781 | logger.error("%s", err_msg) |
| 1790 | 1782 | ||
| 1791 | print_and_log("error: Unable to fully sync the tree") | 1783 | print_and_log("error: Unable to fully sync the tree") |
| 1792 | if err_network_sync: | 1784 | if err_network_sync: |
| @@ -1799,15 +1791,11 @@ later is required to fix a server side protocol bug. | |||
| 1799 | print_and_log("error: Checking out local projects failed.") | 1791 | print_and_log("error: Checking out local projects failed.") |
| 1800 | if err_results: | 1792 | if err_results: |
| 1801 | # Don't log repositories, as it may contain sensitive info. | 1793 | # Don't log repositories, as it may contain sensitive info. |
| 1802 | print( | 1794 | logger.error("Failing repos:\n%s", "\n".join(err_results)) |
| 1803 | "Failing repos:\n%s" % "\n".join(err_results), | ||
| 1804 | file=sys.stderr, | ||
| 1805 | ) | ||
| 1806 | # Not useful to log. | 1795 | # Not useful to log. |
| 1807 | print( | 1796 | logger.error( |
| 1808 | 'Try re-running with "-j1 --fail-fast" to exit at the first ' | 1797 | 'Try re-running with "-j1 --fail-fast" to exit at the first ' |
| 1809 | "error.", | 1798 | "error." |
| 1810 | file=sys.stderr, | ||
| 1811 | ) | 1799 | ) |
| 1812 | raise SyncError(aggregate_errors=errors) | 1800 | raise SyncError(aggregate_errors=errors) |
| 1813 | 1801 | ||
| @@ -1824,14 +1812,13 @@ later is required to fix a server side protocol bug. | |||
| 1824 | 1812 | ||
| 1825 | self._local_sync_state.PruneRemovedProjects() | 1813 | self._local_sync_state.PruneRemovedProjects() |
| 1826 | if self._local_sync_state.IsPartiallySynced(): | 1814 | if self._local_sync_state.IsPartiallySynced(): |
| 1827 | print( | 1815 | logger.warning( |
| 1828 | "warning: Partial syncs are not supported. For the best " | 1816 | "warning: Partial syncs are not supported. For the best " |
| 1829 | "experience, sync the entire tree.", | 1817 | "experience, sync the entire tree." |
| 1830 | file=sys.stderr, | ||
| 1831 | ) | 1818 | ) |
| 1832 | 1819 | ||
| 1833 | if not opt.quiet: | 1820 | if not opt.quiet: |
| 1834 | print("repo sync has finished successfully.") | 1821 | logger.info("repo sync has finished successfully.") |
| 1835 | 1822 | ||
| 1836 | 1823 | ||
| 1837 | def _PostRepoUpgrade(manifest, quiet=False): | 1824 | def _PostRepoUpgrade(manifest, quiet=False): |
| @@ -1854,7 +1841,7 @@ def _PostRepoUpgrade(manifest, quiet=False): | |||
| 1854 | 1841 | ||
| 1855 | def _PostRepoFetch(rp, repo_verify=True, verbose=False): | 1842 | def _PostRepoFetch(rp, repo_verify=True, verbose=False): |
| 1856 | if rp.HasChanges: | 1843 | if rp.HasChanges: |
| 1857 | print("info: A new version of repo is available", file=sys.stderr) | 1844 | logger.info("info: A new version of repo is available") |
| 1858 | wrapper = Wrapper() | 1845 | wrapper = Wrapper() |
| 1859 | try: | 1846 | try: |
| 1860 | rev = rp.bare_git.describe(rp.GetRevisionId()) | 1847 | rev = rp.bare_git.describe(rp.GetRevisionId()) |
| @@ -1876,18 +1863,14 @@ def _PostRepoFetch(rp, repo_verify=True, verbose=False): | |||
| 1876 | rp.work_git.reset("--keep", new_rev) | 1863 | rp.work_git.reset("--keep", new_rev) |
| 1877 | except GitError as e: | 1864 | except GitError as e: |
| 1878 | raise RepoUnhandledExceptionError(e) | 1865 | raise RepoUnhandledExceptionError(e) |
| 1879 | print("info: Restarting repo with latest version", file=sys.stderr) | 1866 | logger.info("info: Restarting repo with latest version") |
| 1880 | raise RepoChangedException(["--repo-upgraded"]) | 1867 | raise RepoChangedException(["--repo-upgraded"]) |
| 1881 | else: | 1868 | else: |
| 1882 | print( | 1869 | logger.warning("warning: Skipped upgrade to unverified version") |
| 1883 | "warning: Skipped upgrade to unverified version", | ||
| 1884 | file=sys.stderr, | ||
| 1885 | ) | ||
| 1886 | else: | 1870 | else: |
| 1887 | if verbose: | 1871 | if verbose: |
| 1888 | print( | 1872 | logger.info( |
| 1889 | "repo version %s is current" % rp.work_git.describe(HEAD), | 1873 | "repo version %s is current", rp.work_git.describe(HEAD) |
| 1890 | file=sys.stderr, | ||
| 1891 | ) | 1874 | ) |
| 1892 | 1875 | ||
| 1893 | 1876 | ||
diff --git a/tests/test_repo_logging.py b/tests/test_repo_logging.py index 5402a90b..b51e6270 100644 --- a/tests/test_repo_logging.py +++ b/tests/test_repo_logging.py | |||
| @@ -23,7 +23,6 @@ class TestRepoLogger(unittest.TestCase): | |||
| 23 | def test_error_logs_error(self): | 23 | def test_error_logs_error(self): |
| 24 | """Test if error fn outputs logs.""" | 24 | """Test if error fn outputs logs.""" |
| 25 | logger = RepoLogger(__name__) | 25 | logger = RepoLogger(__name__) |
| 26 | RepoLogger.errors[:] = [] | ||
| 27 | result = None | 26 | result = None |
| 28 | 27 | ||
| 29 | def mock_handler(log): | 28 | def mock_handler(log): |
| @@ -42,7 +41,6 @@ class TestRepoLogger(unittest.TestCase): | |||
| 42 | def test_warning_logs_error(self): | 41 | def test_warning_logs_error(self): |
| 43 | """Test if warning fn outputs logs.""" | 42 | """Test if warning fn outputs logs.""" |
| 44 | logger = RepoLogger(__name__) | 43 | logger = RepoLogger(__name__) |
| 45 | RepoLogger.errors[:] = [] | ||
| 46 | result = None | 44 | result = None |
| 47 | 45 | ||
| 48 | def mock_handler(log): | 46 | def mock_handler(log): |
| @@ -58,30 +56,9 @@ class TestRepoLogger(unittest.TestCase): | |||
| 58 | 56 | ||
| 59 | self.assertEqual(result, "You know the rules and so do I (do I)") | 57 | self.assertEqual(result, "You know the rules and so do I (do I)") |
| 60 | 58 | ||
| 61 | def test_error_aggregates_error_msg(self): | ||
| 62 | """Test if error fn aggregates error logs.""" | ||
| 63 | logger = RepoLogger(__name__) | ||
| 64 | RepoLogger.errors[:] = [] | ||
| 65 | |||
| 66 | logger.error("A full commitment's what I'm thinking of") | ||
| 67 | logger.error("You wouldn't get this from any other guy") | ||
| 68 | logger.error("I just wanna tell you how I'm feeling") | ||
| 69 | logger.error("Gotta make you understand") | ||
| 70 | |||
| 71 | self.assertEqual( | ||
| 72 | RepoLogger.errors[:], | ||
| 73 | [ | ||
| 74 | "A full commitment's what I'm thinking of", | ||
| 75 | "You wouldn't get this from any other guy", | ||
| 76 | "I just wanna tell you how I'm feeling", | ||
| 77 | "Gotta make you understand", | ||
| 78 | ], | ||
| 79 | ) | ||
| 80 | |||
| 81 | def test_log_aggregated_errors_logs_aggregated_errors(self): | 59 | def test_log_aggregated_errors_logs_aggregated_errors(self): |
| 82 | """Test if log_aggregated_errors outputs aggregated errors.""" | 60 | """Test if log_aggregated_errors outputs aggregated errors.""" |
| 83 | logger = RepoLogger(__name__) | 61 | logger = RepoLogger(__name__) |
| 84 | RepoLogger.errors[:] = [] | ||
| 85 | result = [] | 62 | result = [] |
| 86 | 63 | ||
| 87 | def mock_handler(log): | 64 | def mock_handler(log): |
| @@ -96,7 +73,13 @@ class TestRepoLogger(unittest.TestCase): | |||
| 96 | logger.error("Never gonna give you up") | 73 | logger.error("Never gonna give you up") |
| 97 | logger.error("Never gonna let you down") | 74 | logger.error("Never gonna let you down") |
| 98 | logger.error("Never gonna run around and desert you") | 75 | logger.error("Never gonna run around and desert you") |
| 99 | logger.log_aggregated_errors() | 76 | logger.log_aggregated_errors( |
| 77 | [ | ||
| 78 | "Never gonna give you up", | ||
| 79 | "Never gonna let you down", | ||
| 80 | "Never gonna run around and desert you", | ||
| 81 | ] | ||
| 82 | ) | ||
| 100 | 83 | ||
| 101 | self.assertEqual( | 84 | self.assertEqual( |
| 102 | result, | 85 | result, |
