Skip to content

Commit ab1e623

Browse files
pi-anldpgeorge
authored andcommitted
tools/codeformat: By default only check/update on current git branch.
It can be difficult using the codeformat.py tool when there are other files in the repository not currently matching the standard. For developers, running over the entire repo can throw up a large list of changes in a local git which can lead to inclusion of unrelated changes in commits if they're added accidentally. If the files arg is used to trim down the list of files scanned, it runs a risk of missing some files they've modified. In CI, it means that PR's can fail on codeformat for issues that aren't related to that PR. This change adds a git query in the codeformat tool by default to only work on the list of files that have been modified in the current branch. This can still be overridden by the files arg to run over all files still, eg. python3 tools/codeformat.py -v '**'.
1 parent fc86070 commit ab1e623

File tree

1 file changed

+54
-2
lines changed

1 file changed

+54
-2
lines changed

tools/codeformat.py

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@
5454
PY_EXTS = (".py",)
5555

5656

57+
MAIN_BRANCH = "master"
58+
BASE_BRANCH = os.environ.get("GITHUB_BASE_REF", MAIN_BRANCH)
59+
60+
5761
def list_files(paths, exclusions=None, prefix=""):
5862
files = set()
5963
for pattern in paths:
@@ -105,12 +109,58 @@ def fixup_c(filename):
105109
assert not dedent_stack, filename
106110

107111

112+
def query_git_files(verbose):
113+
def cmd_result_set(cmd):
114+
ret = subprocess.run(cmd, capture_output=True).stdout.strip().decode()
115+
if not ret:
116+
return set()
117+
return {f.strip() for f in ret.split("\n")}
118+
119+
try:
120+
ret = set()
121+
122+
# Check locally modified files
123+
dirty = cmd_result_set(["git", "status", "--porcelain"])
124+
ret = {line.split(" ", 1)[-1] for line in dirty}
125+
126+
# Current commit and branch
127+
current_commit = (
128+
subprocess.run(["git", "rev-parse", "HEAD"], capture_output=True)
129+
.stdout.strip()
130+
.decode()
131+
)
132+
current_branches = cmd_result_set(["git", "branch", "--contains", current_commit])
133+
if MAIN_BRANCH in current_branches:
134+
if ret:
135+
if verbose:
136+
print("Local changes detected, only scanning them.")
137+
return ret
138+
139+
# We're on clean master, run on entire repo
140+
if verbose:
141+
print("Scanning whole repository")
142+
return None
143+
144+
# List the files modified on current branch
145+
if verbose:
146+
print("Scanning changes from current branch and any local changes")
147+
ret |= cmd_result_set(["git", "diff", "--relative", "--name-only", BASE_BRANCH])
148+
return ret
149+
except:
150+
# Git not available, run on entire repo
151+
return None
152+
153+
108154
def main():
109155
cmd_parser = argparse.ArgumentParser(description="Auto-format C and Python files.")
110156
cmd_parser.add_argument("-c", action="store_true", help="Format C code only")
111157
cmd_parser.add_argument("-p", action="store_true", help="Format Python code only")
112158
cmd_parser.add_argument("-v", action="store_true", help="Enable verbose output")
113-
cmd_parser.add_argument("files", nargs="*", help="Run on specific globs")
159+
cmd_parser.add_argument(
160+
"files",
161+
nargs="*",
162+
help="Run on specific globs. If not specied current branch changes will be used",
163+
)
114164
args = cmd_parser.parse_args()
115165

116166
# Setting only one of -c or -p disables the other. If both or neither are set, then do both.
@@ -122,7 +172,9 @@ def main():
122172
if args.files:
123173
files = list_files(args.files)
124174
else:
125-
files = list_files(PATHS, EXCLUSIONS, TOP)
175+
files = query_git_files(verbose=args.v)
176+
if not files:
177+
files = list_files(PATHS, EXCLUSIONS, TOP)
126178

127179
# Extract files matching a specific language.
128180
def lang_files(exts):

0 commit comments

Comments
 (0)