summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAravind Vasudevan <aravindvasudev@google.com>2023-08-31 20:57:31 +0000
committerLUCI <gerrit-scoped@luci-project-accounts.iam.gserviceaccount.com>2023-08-31 22:29:51 +0000
commite914ec293a414dc6cf092c1323c1c059943e706f (patch)
tree165d9228c6d98bfa8e1c23e22bbdc1d297ae111c
parent1e9f7b9e9ef473305d10a26a48138bc6ad38ccf6 (diff)
downloadgit-repo-e914ec293a414dc6cf092c1323c1c059943e706f.tar.gz
sync: Use repo logger within sync
Bug: b/292704435 Change-Id: Iceb3ad5111e656a1ff9730ae5deb032a9b43b4a5 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/383454 Commit-Queue: Aravind Vasudevan <aravindvasudev@google.com> Tested-by: Aravind Vasudevan <aravindvasudev@google.com> Reviewed-by: Mike Frysinger <vapier@google.com>
-rw-r--r--repo_logging.py22
-rw-r--r--subcmds/sync.py191
-rw-r--r--tests/test_repo_logging.py31
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
17import logging 17import logging
18import multiprocessing 18from typing import Any, List
19 19
20from color import Coloring 20from color import Coloring
21 21
@@ -45,31 +45,25 @@ class ConfigMock:
45class RepoLogger(logging.Logger): 45class 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
22import optparse 22import optparse
23import os 23import os
24import socket 24import socket
25import sys
26import tempfile 25import tempfile
27import time 26import time
28from typing import List, NamedTuple, Set 27from typing import List, NamedTuple, Set
@@ -74,6 +73,7 @@ from project import DeleteWorktreeError
74from project import Project 73from project import Project
75from project import RemoteSpec 74from project import RemoteSpec
76from project import SyncBuffer 75from project import SyncBuffer
76from repo_logging import RepoLogger
77from repo_trace import Trace 77from repo_trace import Trace
78import ssh 78import ssh
79from wrapper import Wrapper 79from 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
91logger = RepoLogger(__file__)
92
91 93
92class _FetchOneResult(NamedTuple): 94class _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
1837def _PostRepoUpgrade(manifest, quiet=False): 1824def _PostRepoUpgrade(manifest, quiet=False):
@@ -1854,7 +1841,7 @@ def _PostRepoUpgrade(manifest, quiet=False):
1854 1841
1855def _PostRepoFetch(rp, repo_verify=True, verbose=False): 1842def _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,