-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy patheups_local.py
179 lines (138 loc) · 5.52 KB
/
eups_local.py
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
import subprocess
import numpy as np
import sys
GITMAP = {
"nothing to commit, working tree clean": "✅",
"Untracked files:": "🤷♂️ untracked files",
"Changes not staged for commit:": "❌ unstaged work",
"Parsing failed": "⛔️",
"diverged": "🔀 diverged",
# detached done differently due to detach point in value
}
def show(text):
for line in text.split('\n'):
print(line)
def print_results(packages, paths, branches, statuses, sorting=''):
"""Print the results
Default sorting is alphabetical by package name (also 'p')
Use 't' to sort by ticket
Use 's' to sort by status
"""
packages = np.array(packages)
paths = np.array(paths)
branches = np.array(branches)
statuses = np.array(statuses)
if sorting == '' or sorting == 'p':
inds = packages.argsort()
elif sorting == 't':
inds = branches.argsort()
elif sorting == 's':
inds = statuses.argsort()[::-1] # bad stuff first
paddings = []
paddings.append(max([len(x) for x in packages]) + 2)
paddings.append(max([len(x) for x in paths]) + 2)
paddings.append(max([len(x) for x in branches]) + 3)
for package, path, branch, status in zip(packages[inds], paths[inds], branches[inds], statuses[inds]):
print(f"{package:{paddings[0]}} {path:{paddings[1]}} {branch:{paddings[2]}} {status}")
def fetchAndCheckMaster(path):
"""
Examples:
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working tree clean
On branch master
Your branch is behind 'origin/master' by 4 commits, and can be fast-forwarded.
(use "git pull" to update your local branch)
nothing to commit, working tree clean
"""
fetchCmd = f"git --git-dir={path}/.git --work-tree={path} fetch"
_ = subprocess.check_output(fetchCmd.split(), universal_newlines=True)
statusCmd = f"git --git-dir={path}/.git --work-tree={path} status"
newGitOutput = subprocess.check_output(statusCmd.split(), universal_newlines=True)
line2 = newGitOutput.split('\n')[1]
if line2 == "Your branch is up to date with 'origin/master'.":
line3 = newGitOutput.split('\n')[3]
if line3 in GITMAP.keys():
return GITMAP[line3]
else:
return GITMAP["Parsing failed"]
if line2.startswith("Your branch is behind 'origin/master' by"):
line2 = line2.replace("Your branch is behind 'origin/master' by ", "")
n = line2.split()[0]
status = f"✅ ⬇️ {n} commits"
return status
return "??? - master parse fail"
def parseGitOutput(gitOutput, path):
# Should maybe switch to using --porcelain for the initial status stuff
branch = gitOutput.split('\n')[0].split()[2] # always the third word of first line?
if branch == "at":
line1 = gitOutput.split('\n')[0]
line2 = gitOutput.split('\n')[1]
if line1.startswith('HEAD detached'): # check it is really detached
branch = "n/a - detached"
status = f'🔪 at {line1.split()[3]}'
if line2 == "nothing to commit, working tree clean":
status += " ✅"
else:
status += " ❌"
return branch, status
if branch == 'master':
status = fetchAndCheckMaster(path)
return branch, status
try:
line3 = gitOutput.split('\n')[3]
if line3.endswith('respectively.'):
return branch, GITMAP['diverged']
status = GITMAP[line3]
except KeyError:
print(f"Failed to map the following git status for branch {branch}:")
print('---------')
show(gitOutput)
print('---------')
status = "⛔️"
return branch, status
def getLocalPackagesFromEupsOutput(eupsOutput):
lines = [line for line in eupsOutput.split('\n') if "LOCAL" in line]
packages, paths = [], []
for line in lines:
ret = line.split()
assert len(ret) == 3
packages.append(ret[0])
paths.append(ret[1][6:])
return packages, paths
def getBranchAndStatus(package, path):
cmd = f"git --git-dir={path}/.git --work-tree={path} status"
gitOutput = subprocess.check_output(cmd.split(), universal_newlines=True)
branch, status = parseGitOutput(gitOutput, path)
return branch, status
def dumpGITMAP():
for k, v in GITMAP.items():
print(f"{v} : {k}")
if __name__ == "__main__":
# worst argparser ever, but - and -- are both OK, and command just has to
# begin with the right letter. It was quicker than remembering how to use
# argparse properly - don't judge me.
args = sys.argv
sorting = ''
if len(args) > 1:
sorting = args[1]
sorting = sorting.replace('-', '')
sorting = sorting[0]
if sorting == '?':
dumpGITMAP()
exit()
assert sorting in ['p', 's', 't']
cmd = 'eups list -s'
eupsOutput = subprocess.check_output(cmd.split(), universal_newlines=True)
packages, paths = getLocalPackagesFromEupsOutput(eupsOutput)
if len(packages) == 0:
print("No local packages were found to be setup. If you think this is a lie try")
print("eups list -s | grep LOCAL")
exit()
branches, statuses = [], []
for package, path in zip(packages, paths):
branch, status = getBranchAndStatus(package, path)
branches.append(branch)
statuses.append(status)
assert len(packages) == len(paths) == len(branches) == len(statuses)
print_results(packages, paths, branches, statuses, sorting)