aboutsummaryrefslogtreecommitdiff
path: root/lib/python
diff options
context:
space:
mode:
authorErovia <Erovia@users.noreply.github.com>2021-07-10 16:04:50 +0100
committerGitHub <noreply@github.com>2021-07-10 16:04:50 +0100
commite05f9c4a08cef384989cd20ebe27b66622912055 (patch)
tree6f12e99f42b031a986d9b77638723beaff51e6d1 /lib/python
parent789be4f1145c56253629808967e31be14c99820e (diff)
downloadqmk_firmware-e05f9c4a08cef384989cd20ebe27b66622912055.tar.gz
qmk_firmware-e05f9c4a08cef384989cd20ebe27b66622912055.zip
CLI: Add git and venv info to doctor's output (#13405)
Most of the checks are saved from zvecr's retired 'up/status' subcommand PR.
Diffstat (limited to 'lib/python')
-rwxr-xr-xlib/python/qmk/cli/doctor/main.py45
-rw-r--r--lib/python/qmk/commands.py71
-rw-r--r--lib/python/qmk/constants.py3
3 files changed, 111 insertions, 8 deletions
diff --git a/lib/python/qmk/cli/doctor/main.py b/lib/python/qmk/cli/doctor/main.py
index 5e93fad36..6a31ccdfd 100755
--- a/lib/python/qmk/cli/doctor/main.py
+++ b/lib/python/qmk/cli/doctor/main.py
@@ -9,8 +9,9 @@ from milc import cli
9from milc.questions import yesno 9from milc.questions import yesno
10 10
11from qmk import submodules 11from qmk import submodules
12from qmk.constants import QMK_FIRMWARE 12from qmk.constants import QMK_FIRMWARE, QMK_FIRMWARE_UPSTREAM
13from .check import CheckStatus, check_binaries, check_binary_versions, check_submodules, check_git_repo 13from .check import CheckStatus, check_binaries, check_binary_versions, check_submodules
14from qmk.commands import git_check_repo, git_get_branch, git_is_dirty, git_get_remotes, git_check_deviation, in_virtualenv
14 15
15 16
16def os_tests(): 17def os_tests():
@@ -32,6 +33,37 @@ def os_tests():
32 return CheckStatus.WARNING 33 return CheckStatus.WARNING
33 34
34 35
36def git_tests():
37 """Run Git-related checks
38 """
39 status = CheckStatus.OK
40
41 # Make sure our QMK home is a Git repo
42 git_ok = git_check_repo()
43 if not git_ok:
44 cli.log.warning("{fg_yellow}QMK home does not appear to be a Git repository! (no .git folder)")
45 status = CheckStatus.WARNING
46 else:
47 git_branch = git_get_branch()
48 if git_branch:
49 cli.log.info('Git branch: %s', git_branch)
50 git_dirty = git_is_dirty()
51 if git_dirty:
52 cli.log.warning('{fg_yellow}Git has unstashed/uncommitted changes.')
53 status = CheckStatus.WARNING
54 git_remotes = git_get_remotes()
55 if 'upstream' not in git_remotes.keys() or QMK_FIRMWARE_UPSTREAM not in git_remotes['upstream'].get('url', ''):
56 cli.log.warning('{fg_yellow}The official repository does not seem to be configured as git remote "upstream".')
57 status = CheckStatus.WARNING
58 else:
59 git_deviation = git_check_deviation(git_branch)
60 if git_branch in ['master', 'develop'] and git_deviation:
61 cli.log.warning('{fg_yellow}The local "%s" branch contains commits not found in the upstream branch.', git_branch)
62 status = CheckStatus.WARNING
63
64 return status
65
66
35@cli.argument('-y', '--yes', action='store_true', arg_only=True, help='Answer yes to all questions.') 67@cli.argument('-y', '--yes', action='store_true', arg_only=True, help='Answer yes to all questions.')
36@cli.argument('-n', '--no', action='store_true', arg_only=True, help='Answer no to all questions.') 68@cli.argument('-n', '--no', action='store_true', arg_only=True, help='Answer no to all questions.')
37@cli.subcommand('Basic QMK environment checks') 69@cli.subcommand('Basic QMK environment checks')
@@ -49,12 +81,11 @@ def doctor(cli):
49 81
50 status = os_tests() 82 status = os_tests()
51 83
52 # Make sure our QMK home is a Git repo 84 status = git_tests()
53 git_ok = check_git_repo()
54 85
55 if git_ok == CheckStatus.WARNING: 86 venv = in_virtualenv()
56 cli.log.warning("QMK home does not appear to be a Git repository! (no .git folder)") 87 if venv:
57 status = CheckStatus.WARNING 88 cli.log.info('CLI installed in virtualenv.')
58 89
59 # Make sure the basic CLI tools we need are available and can be executed. 90 # Make sure the basic CLI tools we need are available and can be executed.
60 bin_ok = check_binaries() 91 bin_ok = check_binaries()
diff --git a/lib/python/qmk/commands.py b/lib/python/qmk/commands.py
index 104c87545..8ff8501bf 100644
--- a/lib/python/qmk/commands.py
+++ b/lib/python/qmk/commands.py
@@ -2,6 +2,7 @@
2""" 2"""
3import json 3import json
4import os 4import os
5import sys
5import shutil 6import shutil
6from pathlib import Path 7from pathlib import Path
7from subprocess import DEVNULL 8from subprocess import DEVNULL
@@ -10,7 +11,7 @@ from time import strftime
10from milc import cli 11from milc import cli
11 12
12import qmk.keymap 13import qmk.keymap
13from qmk.constants import KEYBOARD_OUTPUT_PREFIX 14from qmk.constants import QMK_FIRMWARE, KEYBOARD_OUTPUT_PREFIX
14from qmk.json_schema import json_load 15from qmk.json_schema import json_load
15 16
16time_fmt = '%Y-%m-%d-%H:%M:%S' 17time_fmt = '%Y-%m-%d-%H:%M:%S'
@@ -237,3 +238,71 @@ def parse_configurator_json(configurator_file):
237 user_keymap['layout'] = aliases[orig_keyboard]['layouts'][user_keymap['layout']] 238 user_keymap['layout'] = aliases[orig_keyboard]['layouts'][user_keymap['layout']]
238 239
239 return user_keymap 240 return user_keymap
241
242
243def git_check_repo():
244 """Checks that the .git directory exists inside QMK_HOME.
245
246 This is a decent enough indicator that the qmk_firmware directory is a
247 proper Git repository, rather than a .zip download from GitHub.
248 """
249 dot_git_dir = QMK_FIRMWARE / '.git'
250
251 return dot_git_dir.is_dir()
252
253
254def git_get_branch():
255 """Returns the current branch for a repo, or None.
256 """
257 git_branch = cli.run(['git', 'branch', '--show-current'])
258 if not git_branch.returncode != 0 or not git_branch.stdout:
259 # Workaround for Git pre-2.22
260 git_branch = cli.run(['git', 'rev-parse', '--abbrev-ref', 'HEAD'])
261
262 if git_branch.returncode == 0:
263 return git_branch.stdout.strip()
264
265
266def git_is_dirty():
267 """Returns 1 if repo is dirty, or 0 if clean
268 """
269 git_diff_staged_cmd = ['git', 'diff', '--quiet']
270 git_diff_unstaged_cmd = [*git_diff_staged_cmd, '--cached']
271
272 unstaged = cli.run(git_diff_staged_cmd)
273 staged = cli.run(git_diff_unstaged_cmd)
274
275 return unstaged.returncode != 0 or staged.returncode != 0
276
277
278def git_get_remotes():
279 """Returns the current remotes for a repo.
280 """
281 remotes = {}
282
283 git_remote_show_cmd = ['git', 'remote', 'show']
284 git_remote_get_cmd = ['git', 'remote', 'get-url']
285
286 git_remote_show = cli.run(git_remote_show_cmd)
287 if git_remote_show.returncode == 0:
288 for name in git_remote_show.stdout.splitlines():
289 git_remote_name = cli.run([*git_remote_get_cmd, name])
290 remotes[name.strip()] = {"url": git_remote_name.stdout.strip()}
291
292 return remotes
293
294
295def git_check_deviation(active_branch):
296 """Return True if branch has custom commits
297 """
298 cli.run(['git', 'fetch', 'upstream', active_branch])
299 deviations = cli.run(['git', '--no-pager', 'log', f'upstream/{active_branch}...{active_branch}'])
300 return bool(deviations.returncode)
301
302
303def in_virtualenv():
304 """Check if running inside a virtualenv.
305 Based on https://stackoverflow.com/a/1883251
306 """
307 active_prefix = getattr(sys, "base_prefix", None) or getattr(sys, "real_prefix", None) or sys.prefix
308 return active_prefix != sys.prefix
diff --git a/lib/python/qmk/constants.py b/lib/python/qmk/constants.py
index be5ce5d4e..1078f4ad5 100644
--- a/lib/python/qmk/constants.py
+++ b/lib/python/qmk/constants.py
@@ -6,6 +6,9 @@ from pathlib import Path
6# The root of the qmk_firmware tree. 6# The root of the qmk_firmware tree.
7QMK_FIRMWARE = Path.cwd() 7QMK_FIRMWARE = Path.cwd()
8 8
9# Upstream repo url
10QMK_FIRMWARE_UPSTREAM = 'qmk/qmk_firmware'
11
9# This is the number of directories under `qmk_firmware/keyboards` that will be traversed. This is currently a limitation of our make system. 12# This is the number of directories under `qmk_firmware/keyboards` that will be traversed. This is currently a limitation of our make system.
10MAX_KEYBOARD_SUBFOLDERS = 5 13MAX_KEYBOARD_SUBFOLDERS = 5
11 14