summaryrefslogtreecommitdiffstats
path: root/repo_trace.py
diff options
context:
space:
mode:
authorGavin Mak <gavinmak@google.com>2023-03-11 06:46:20 +0000
committerLUCI <gerrit-scoped@luci-project-accounts.iam.gserviceaccount.com>2023-03-22 17:46:28 +0000
commitea2e330e43c182dc16b0111ebc69ee5a71ee4ce1 (patch)
treedc33ba0e56825b3e007d0589891756724725a465 /repo_trace.py
parent1604cf255f8c1786a23388db6d5277ac7949a24a (diff)
downloadgit-repo-ea2e330e43c182dc16b0111ebc69ee5a71ee4ce1.tar.gz
Format codebase with black and check formatting in CQ
Apply rules set by https://gerrit-review.googlesource.com/c/git-repo/+/362954/ across the codebase and fix any lingering errors caught by flake8. Also check black formatting in run_tests (and CQ). Bug: b/267675342 Change-Id: I972d77649dac351150dcfeb1cd1ad0ea2efc1956 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/363474 Reviewed-by: Mike Frysinger <vapier@google.com> Tested-by: Gavin Mak <gavinmak@google.com> Commit-Queue: Gavin Mak <gavinmak@google.com>
Diffstat (limited to 'repo_trace.py')
-rw-r--r--repo_trace.py184
1 files changed, 94 insertions, 90 deletions
diff --git a/repo_trace.py b/repo_trace.py
index 1ba86c79..49462174 100644
--- a/repo_trace.py
+++ b/repo_trace.py
@@ -29,138 +29,142 @@ from contextlib import ContextDecorator
29import platform_utils 29import platform_utils
30 30
31# Env var to implicitly turn on tracing. 31# Env var to implicitly turn on tracing.
32REPO_TRACE = 'REPO_TRACE' 32REPO_TRACE = "REPO_TRACE"
33 33
34# Temporarily set tracing to always on unless user expicitly sets to 0. 34# Temporarily set tracing to always on unless user expicitly sets to 0.
35_TRACE = os.environ.get(REPO_TRACE) != '0' 35_TRACE = os.environ.get(REPO_TRACE) != "0"
36_TRACE_TO_STDERR = False 36_TRACE_TO_STDERR = False
37_TRACE_FILE = None 37_TRACE_FILE = None
38_TRACE_FILE_NAME = 'TRACE_FILE' 38_TRACE_FILE_NAME = "TRACE_FILE"
39_MAX_SIZE = 70 # in MiB 39_MAX_SIZE = 70 # in MiB
40_NEW_COMMAND_SEP = '+++++++++++++++NEW COMMAND+++++++++++++++++++' 40_NEW_COMMAND_SEP = "+++++++++++++++NEW COMMAND+++++++++++++++++++"
41 41
42 42
43def IsTraceToStderr(): 43def IsTraceToStderr():
44 """Whether traces are written to stderr.""" 44 """Whether traces are written to stderr."""
45 return _TRACE_TO_STDERR 45 return _TRACE_TO_STDERR
46 46
47 47
48def IsTrace(): 48def IsTrace():
49 """Whether tracing is enabled.""" 49 """Whether tracing is enabled."""
50 return _TRACE 50 return _TRACE
51 51
52 52
53def SetTraceToStderr(): 53def SetTraceToStderr():
54 """Enables tracing logging to stderr.""" 54 """Enables tracing logging to stderr."""
55 global _TRACE_TO_STDERR 55 global _TRACE_TO_STDERR
56 _TRACE_TO_STDERR = True 56 _TRACE_TO_STDERR = True
57 57
58 58
59def SetTrace(): 59def SetTrace():
60 """Enables tracing.""" 60 """Enables tracing."""
61 global _TRACE 61 global _TRACE
62 _TRACE = True 62 _TRACE = True
63 63
64 64
65def _SetTraceFile(quiet): 65def _SetTraceFile(quiet):
66 """Sets the trace file location.""" 66 """Sets the trace file location."""
67 global _TRACE_FILE 67 global _TRACE_FILE
68 _TRACE_FILE = _GetTraceFile(quiet) 68 _TRACE_FILE = _GetTraceFile(quiet)
69 69
70 70
71class Trace(ContextDecorator): 71class Trace(ContextDecorator):
72 """Used to capture and save git traces.""" 72 """Used to capture and save git traces."""
73 73
74 def _time(self): 74 def _time(self):
75 """Generate nanoseconds of time in a py3.6 safe way""" 75 """Generate nanoseconds of time in a py3.6 safe way"""
76 return int(time.time() * 1e+9) 76 return int(time.time() * 1e9)
77 77
78 def __init__(self, fmt, *args, first_trace=False, quiet=True): 78 def __init__(self, fmt, *args, first_trace=False, quiet=True):
79 """Initialize the object. 79 """Initialize the object.
80 80
81 Args: 81 Args:
82 fmt: The format string for the trace. 82 fmt: The format string for the trace.
83 *args: Arguments to pass to formatting. 83 *args: Arguments to pass to formatting.
84 first_trace: Whether this is the first trace of a `repo` invocation. 84 first_trace: Whether this is the first trace of a `repo` invocation.
85 quiet: Whether to suppress notification of trace file location. 85 quiet: Whether to suppress notification of trace file location.
86 """ 86 """
87 if not IsTrace(): 87 if not IsTrace():
88 return 88 return
89 self._trace_msg = fmt % args 89 self._trace_msg = fmt % args
90 90
91 if not _TRACE_FILE: 91 if not _TRACE_FILE:
92 _SetTraceFile(quiet) 92 _SetTraceFile(quiet)
93 93
94 if first_trace: 94 if first_trace:
95 _ClearOldTraces() 95 _ClearOldTraces()
96 self._trace_msg = f'{_NEW_COMMAND_SEP} {self._trace_msg}' 96 self._trace_msg = f"{_NEW_COMMAND_SEP} {self._trace_msg}"
97 97
98 def __enter__(self): 98 def __enter__(self):
99 if not IsTrace(): 99 if not IsTrace():
100 return self 100 return self
101 101
102 print_msg = f'PID: {os.getpid()} START: {self._time()} :{self._trace_msg}\n' 102 print_msg = (
103 f"PID: {os.getpid()} START: {self._time()} :{self._trace_msg}\n"
104 )
103 105
104 with open(_TRACE_FILE, 'a') as f: 106 with open(_TRACE_FILE, "a") as f:
105 print(print_msg, file=f) 107 print(print_msg, file=f)
106 108
107 if _TRACE_TO_STDERR: 109 if _TRACE_TO_STDERR:
108 print(print_msg, file=sys.stderr) 110 print(print_msg, file=sys.stderr)
109 111
110 return self 112 return self
111 113
112 def __exit__(self, *exc): 114 def __exit__(self, *exc):
113 if not IsTrace(): 115 if not IsTrace():
114 return False 116 return False
115 117
116 print_msg = f'PID: {os.getpid()} END: {self._time()} :{self._trace_msg}\n' 118 print_msg = (
119 f"PID: {os.getpid()} END: {self._time()} :{self._trace_msg}\n"
120 )
117 121
118 with open(_TRACE_FILE, 'a') as f: 122 with open(_TRACE_FILE, "a") as f:
119 print(print_msg, file=f) 123 print(print_msg, file=f)
120 124
121 if _TRACE_TO_STDERR: 125 if _TRACE_TO_STDERR:
122 print(print_msg, file=sys.stderr) 126 print(print_msg, file=sys.stderr)
123 127
124 return False 128 return False
125 129
126 130
127def _GetTraceFile(quiet): 131def _GetTraceFile(quiet):
128 """Get the trace file or create one.""" 132 """Get the trace file or create one."""
129 # TODO: refactor to pass repodir to Trace. 133 # TODO: refactor to pass repodir to Trace.
130 repo_dir = os.path.dirname(os.path.dirname(__file__)) 134 repo_dir = os.path.dirname(os.path.dirname(__file__))
131 trace_file = os.path.join(repo_dir, _TRACE_FILE_NAME) 135 trace_file = os.path.join(repo_dir, _TRACE_FILE_NAME)
132 if not quiet: 136 if not quiet:
133 print(f'Trace outputs in {trace_file}', file=sys.stderr) 137 print(f"Trace outputs in {trace_file}", file=sys.stderr)
134 return trace_file 138 return trace_file
135 139
136 140
137def _ClearOldTraces(): 141def _ClearOldTraces():
138 """Clear the oldest commands if trace file is too big.""" 142 """Clear the oldest commands if trace file is too big."""
139 try: 143 try:
140 with open(_TRACE_FILE, 'r', errors='ignore') as f: 144 with open(_TRACE_FILE, "r", errors="ignore") as f:
141 if os.path.getsize(f.name) / (1024 * 1024) <= _MAX_SIZE: 145 if os.path.getsize(f.name) / (1024 * 1024) <= _MAX_SIZE:
146 return
147 trace_lines = f.readlines()
148 except FileNotFoundError:
142 return 149 return
143 trace_lines = f.readlines() 150
144 except FileNotFoundError: 151 while sum(len(x) for x in trace_lines) / (1024 * 1024) > _MAX_SIZE:
145 return 152 for i, line in enumerate(trace_lines):
146 153 if "END:" in line and _NEW_COMMAND_SEP in line:
147 while sum(len(x) for x in trace_lines) / (1024 * 1024) > _MAX_SIZE: 154 trace_lines = trace_lines[i + 1 :]
148 for i, line in enumerate(trace_lines): 155 break
149 if 'END:' in line and _NEW_COMMAND_SEP in line: 156 else:
150 trace_lines = trace_lines[i + 1:] 157 # The last chunk is bigger than _MAX_SIZE, so just throw everything
151 break 158 # away.
152 else: 159 trace_lines = []
153 # The last chunk is bigger than _MAX_SIZE, so just throw everything away. 160
154 trace_lines = [] 161 while trace_lines and trace_lines[-1] == "\n":
155 162 trace_lines = trace_lines[:-1]
156 while trace_lines and trace_lines[-1] == '\n': 163 # Write to a temporary file with a unique name in the same filesystem
157 trace_lines = trace_lines[:-1] 164 # before replacing the original trace file.
158 # Write to a temporary file with a unique name in the same filesystem 165 temp_dir, temp_prefix = os.path.split(_TRACE_FILE)
159 # before replacing the original trace file. 166 with tempfile.NamedTemporaryFile(
160 temp_dir, temp_prefix = os.path.split(_TRACE_FILE) 167 "w", dir=temp_dir, prefix=temp_prefix, delete=False
161 with tempfile.NamedTemporaryFile('w', 168 ) as f:
162 dir=temp_dir, 169 f.writelines(trace_lines)
163 prefix=temp_prefix, 170 platform_utils.rename(f.name, _TRACE_FILE)
164 delete=False) as f:
165 f.writelines(trace_lines)
166 platform_utils.rename(f.name, _TRACE_FILE)