4 import sys, subprocess, datetime, os
7 PORTDIR = "/usr/portage/"
8 LOGFILE = "/var/log/emerge.log"
12 green_start = "\033[32m"
19 def organize_times(time):
20 """Takes the emerge time in seconds, organizes it into
21 days, hours, minutes or seconds and finally prints that out."""
24 hours = (days - int(days))*24
25 minutes = (hours - int(hours))*60
26 seconds = (minutes - int(minutes))*60
30 minutes = int(minutes)
31 seconds = int(round(seconds))
34 print_days = (green_start + str(days) + color_stop + " day")
40 print_hours = (green_start + str(hours) + color_stop + " hour")
46 print_minutes = (green_start + str(minutes) + color_stop + " minute")
51 printable_sec = (green_start + str(seconds) + color_stop + " second")
58 def get_date(emerge_start):
59 """Take the emerge startup time in seconds and turn it into a
62 date = datetime.datetime.fromtimestamp(emerge_start)
65 month = str(date.month)
67 weekday = date.weekday()
69 if weekday == 0: weekday = 'Mon '
70 if weekday == 1: weekday = 'Tue '
71 if weekday == 2: weekday = 'Wed '
72 if weekday == 3: weekday = 'Thu '
73 if weekday == 4: weekday = 'Fri '
74 if weekday == 5: weekday = 'Sat '
75 if weekday == 6: weekday = 'Sun '
78 minute = str(date.minute)
79 second = str(date.second)
81 # This is in the format 'Mon 23.05.2011 00:20:14'
83 date = weekday + "{:%d.%m.%Y %H:%M:%S}".format(date)
89 def list_all_packages():
90 """Go through PORTDIR and create a list of all the packages in portage"""
92 root = os.listdir(PORTDIR)
95 for package_group in root:
96 group_dir = PORTDIR + package_group
97 if (os.path.isdir(group_dir)
98 and (package_group != "licenses")
99 and (package_group != "metadata")):
101 name_dir = os.listdir(group_dir)
103 for package_name in name_dir:
104 if ".xml" not in package_name:
106 all_packages.append((package_group +
114 def get_package(name):
115 """Take the user-input package name and search for it
118 dirlist = os.listdir(PORTDIR)
119 possible_package = []
122 # If the given name is in the format xxx/zzz
123 # assume that xxx is the package group
125 group = name.partition('/')[0]
126 pkg = name.partition('/')[2]
127 directory = PORTDIR + group
130 dirs = os.listdir(directory)
132 possible_package.append(name)
135 # Go through the directory listing searching for anything
136 # that matches the given name
138 directory = PORTDIR + i
139 if os.path.isdir(directory):
140 dirs = os.listdir(directory)
142 possible_package.append(i + '/' + name)
145 if len(possible_package) > 1:
146 print("Multiple packages found for '" + name + "'.")
147 print("Possible packages: ")
148 for value in possible_package:
152 elif len(possible_package) == 1:
153 package = possible_package[0]
158 print("No package '" + name + "' found")
165 def print_times(package, times, silent):
166 """Print the maximum/minimum/average times of the given emerge package.
167 If we're in the 'current emerge stage' (the 'silent' flag is True)
168 print the appropriate comment for that package."""
175 # This should be True if we're in current emerge stage
178 print("\t no previous emerges found for this package"),
181 elif len(times) == 1:
182 print("\t previous emerge time:\t"),
183 organize_times(times[0][0])
184 print("(only one emerge previously)"),
188 print("\t average emerge time:\t"),
193 organize_times(all_times/len(times))
195 return all_times/len(times)
199 print(green_start + package + color_stop + " emerged once")
202 print(green_start + package + color_stop + " emerged " + green_start +
203 str(len(times)) + color_stop + " times\n")
206 organize_times(times[0][0])
207 print "at", times[0][1]
210 organize_times(times[len(times)-1][0])
211 print "at", times[len(times)-1][1]
217 print "Average time\t",
218 organize_times(all_times/len(times))
221 print "In total spent\t",
222 organize_times(all_times)
223 print("emerging " + green_start +
224 package + color_stop)
229 """Attempt to open the LOGFILE."""
232 f = open(LOGFILE, 'r')
233 except IOError as detail:
241 def list_emerge_processes(f):
242 """Look for the ebuild process with ps. If the process is found parse
243 the command for the package. With this package search the LOGFILE for
244 the emerge startup time."""
246 now = datetime.datetime.today()
249 for i in os.popen("ps ax"):
250 if (("ebuild" in i) and ("/bin/bash" not in i)):
251 pack = i.partition('[')[2].partition(']')[0]
253 packages.append([pack, 12*3600])
257 if ((">>>" in line) and ("emerge" in line)):
261 time = float(line.partition(' ')[0].strip(":"))
263 timestamp = datetime.datetime.fromtimestamp(time)
264 difference = (now - timestamp).total_seconds()
266 if difference < p[1]:
270 if len(packages) == 0:
271 print "No current emerge process found."
274 print_current_emerges(f, packages)
279 def print_current_emerges(f, packages):
280 """Print the current packages that are being merged with the
281 current emerge time."""
283 all_packages = list_all_packages()
285 print("Currently emerging: ")
288 print("\t" + green_start + p[0] + color_stop),
289 print("\n\t current emerge time:\t"),
295 for i in all_packages:
297 average_time = main_loop(f, i, True)
299 if average_time != 0:
300 print("\n\t " + '-'*45 + "\n\t time to finish: \t"),
301 if (average_time - p[1]) < 0:
302 print(green_start + "Any time now" + color_stop),
304 organize_times(average_time - p[1])
309 def list_pretended(f):
310 """Print the average times of pretended packages"""
312 all_packages = list_all_packages()
315 for line in sys.stdin:
316 if "[ebuild" in line:
317 full_name = line.partition('] ')[2].partition(' ')[0]
319 for i in all_packages:
321 packages.append((i, full_name[len(i):]))
323 if len(packages) == 0:
326 print "This is how long these packages would take to emerge"
329 for pack in packages:
331 print('\t' + green_start + pack[0] + pack[1] + color_stop)
333 all_time += main_loop(f, pack[0], True)
339 print("Total emerge time of " + green_start + str(len(packages)) +
340 color_stop + " packages:"),
341 organize_times(all_time)
346 def main_loop(f, package, silent):
347 """The main loop which parses the LOGFILE and if needed prints out emerge times."""
349 f.seek(0) # Seek to the beginning of the file
358 if ((package in string) and (len(string) > len(package)+1)
359 and (string[len(package)+1].isdigit())):
360 full_package = st[st.index(string)]
363 if ((">>>" in line) and ("emerge" in line)):
364 time_string = line.partition(">>>")
365 time = float(time_string[0].strip().strip(":"))
368 if (":::" in line) and ("completed emerge" in line):
369 time_string = line.partition(":::")
370 time2 = float(time_string[0].strip().strip(":"))
373 emerge_time = time2-time
375 date = get_date(time)
379 print(str(len(times)+1) + "."),
380 print(green_start + full_package + color_stop + " >>> "
383 organize_times(emerge_time)
387 times.append((emerge_time, date))
391 average_time = print_times(package, times, silent)
397 """Change between current emerge stage and normal operating stage."""
401 if status == 'current':
402 list_emerge_processes(f)
404 elif status == 'pretended':
410 package = get_package(package_name)
414 main_loop(f, package, False)
420 if __name__ == "__main__":
422 if len(sys.argv) == 1:
426 elif sys.argv[1] == "-p":
430 elif ((sys.argv[1] == "-h") or (sys.argv[1] == "--help")):
431 print("Usage: emerge-timer.py [options] [package]\n\nOptions:\n"
432 + green_start + "\t-p" + color_stop +
433 "\tcalculate compile time from piped 'emerge -p' output\n" +
434 green_start + "\t[none]" + color_stop +
435 "\tShow average emerge times for currently compiling packages.")
438 if len(sys.argv) > 1:
439 package_name = sys.argv[1]