-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvalidate_project.py
More file actions
101 lines (84 loc) · 2.71 KB
/
Copy pathvalidate_project.py
File metadata and controls
101 lines (84 loc) · 2.71 KB
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#!/usr/bin/env python3
"""
Validate Xcode workspace/project file is not corrupted.
Author: Deszip
Usage:
python validate_project.py
python validate_project.py <workspace_or_project_path>
Uses xcodebuild -list to parse the project the same way
Xcode does. Exits 0 if valid, 1 if corrupted.
"""
import subprocess
import sys
import os
import time
DEFAULT_WORKSPACE = "ReaddleDocs2.xcworkspace"
def validate(path):
"""Run xcodebuild -list to validate the project file."""
if path.endswith('.xcworkspace'):
flag = '-workspace'
elif path.endswith('.xcodeproj'):
flag = '-project'
else:
print(f"Error: Unrecognized format: {path}")
print("Expected .xcworkspace or .xcodeproj")
return False
if not os.path.exists(path):
print(f"Error: Path not found: {path}")
return False
print(f"Validating: {path}")
print(f"Running: xcodebuild -list {flag} {path}")
print()
start = time.time()
result = subprocess.run(
["xcodebuild", "-list", flag, path],
capture_output=True,
text=True,
timeout=120,
)
elapsed = time.time() - start
# Check for "Unable to open project" even on exit 0
combined = (result.stdout or '') + (result.stderr or '')
if 'Unable to open project file' in combined:
print(
f"FAILED — unable to open project "
f"({elapsed:.1f}s)"
)
print()
for line in combined.strip().split('\n'):
if 'Unable to open' in line or 'WARNING' in line:
print(f" {line.strip()}")
return False
if result.returncode == 0:
lines = result.stdout.strip().split('\n')
print(f"OK — project is valid ({elapsed:.1f}s)")
print(f" {len(lines)} lines of output")
return True
else:
print(f"FAILED — project is corrupted ({elapsed:.1f}s)")
print()
# Show the error
stderr = result.stderr.strip()
if stderr:
for line in stderr.split('\n')[:20]:
print(f" {line}")
stdout = result.stdout.strip()
if stdout:
for line in stdout.split('\n')[:10]:
print(f" {line}")
return False
def main():
path = sys.argv[1] if len(sys.argv) > 1 else DEFAULT_WORKSPACE
try:
success = validate(path)
except subprocess.TimeoutExpired:
print("FAILED — xcodebuild timed out (120s)")
success = False
except FileNotFoundError:
print("Error: xcodebuild not found.")
print("Install Xcode Command Line Tools:")
print(" xcode-select --install")
success = False
sys.exit(0 if success else 1)
if __name__ == '__main__':
main()