-
Notifications
You must be signed in to change notification settings - Fork 0
/
mp-fix-clt
executable file
·83 lines (65 loc) · 2.79 KB
/
mp-fix-clt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#!/usr/bin/env python3
"""
Fix Xcode Command Line Tools installation for MacPorts, according to:
https://trac.macports.org/wiki/ProblemHotlist#reinstall-clt
Download the command line tools package from the Apple Developer site.
If the version of the CLT you need is not listed at the developer site, but
an older version is, reinstalling that will restore the package receipts. Then
just run Software Update to trigger the update to the newer version.
Or, on Mac OS X 10.9 or greater, Software Update can reinstall the package:
- `sudo touch /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress`
- `softwareupdate -l`
- Run Software Update
- `sudo rm /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress`
"""
import re
import sys
from contextlib import contextmanager
from pathlib import Path
from sh import softwareupdate
softwareupdate = softwareupdate.bake(_err_to_out=True)
CLT_IOD_PATH = Path("/tmp/.com.apple.dt.CommandLineTools"
".installondemand.in-progress")
FOUND = "Software Update found the following new or updated software:"
NOT_FOUND = "No new software available."
RECORD_RE = re.compile(r"^\*\s+(.+(?:\n\s+.+)+)$", re.MULTILINE)
ITEM_RE = re.compile(r"\s*(?P<key>\w+):\s+(?P<value>[^,\n]+)", re.MULTILINE)
CLT_TITLE = "Command Line Tools for Xcode"
@contextmanager
def clt_installondemand():
"""Trigger the Command Line Tools for Xcode Install on Demand."""
CLT_IOD_PATH.touch()
try:
yield
finally:
CLT_IOD_PATH.unlink()
def parse_swupdate_list(sulist):
"""Parse the `softwareupdate --list` result."""
for record in RECORD_RE.findall(sulist):
yield dict(ITEM_RE.findall(record))
def main():
# Trigger CLT Install on Demand
with clt_installondemand():
# Check for software updates
result = (softwareupdate("--list")
.stdout.decode(sys.stdin.encoding))
if FOUND in result:
clt_labels = list(swupdate.get("Label")
for swupdate in parse_swupdate_list(result)
if swupdate["Title"] == CLT_TITLE)
if (not clt_labels):
raise Exception("Found no software updates "
f"for {CLT_TITLE}")
elif (len(clt_labels) > 1):
raise Exception("Found multiple software updates "
f"for {CLT_TITLE}: {clt_labels}")
else:
# Install CLT
print(f"Found software update: {clt_labels[0]}.")
result = (softwareupdate("--install", clt_labels[0])
.stdout.decode(sys.stdin.encoding))
print(result)
else:
raise Exception(f"Found no software updates: {result}")
if __name__ == "__main__":
main()