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"""
313 for line in sys.stdin:
314 if "[ebuild" in line:
315 full_name = line.partition('] ')[2].partition(' ')[0]
317 version = full_name.partition('/')[2].partition('-')[2]
318 while not version[0].isdigit():
319 version = version.partition('-')[2]
321 package_name = full_name[:-len(version)-1]
323 packages.append((package_name, '-' + version))
326 if len(packages) == 0:
329 print "This is how long these packages would take to emerge"
332 for pack in packages:
334 print('\t' + green_start + pack[0] + pack[1] + color_stop)
336 all_time += main_loop(f, pack[0], True)
342 print("Total emerge time of " + green_start + str(len(packages)) +
343 color_stop + " packages:"),
344 organize_times(all_time)
349 def main_loop(f, package, silent):
350 """The main loop which parses the LOGFILE and if needed prints out emerge times."""
352 f.seek(0) # Seek to the beginning of the file
357 if ((">>>" in line) and ("emerge" in line)):
359 version = line.partition(package)[2].partition(' ')[0]
361 if version.strip('-')[0].isdigit():
362 full_package = package + version
364 time_string = line.partition(">>>")
365 start_time = float(time_string[0].strip().strip(':'))
368 elif ((":::" in line) and ("completed emerge" in line)):
370 if version.strip('-')[0].isdigit():
372 time_string = line.partition(":::")
373 end_time = float(time_string[0].strip().strip(':'))
376 emerge_time = end_time - start_time
378 date = get_date(start_time)
382 print(str(len(times)+1) + ". " +
383 green_start + full_package + color_stop +
384 " >>> " + date + " >>> "),
386 organize_times(emerge_time)
391 times.append((emerge_time, date))
394 average_time = print_times(package, times, silent)
400 """Change between current emerge stage and normal operating stage."""
404 if status == 'current':
405 list_emerge_processes(f)
407 elif status == 'pretended':
413 package = get_package(package_name)
417 main_loop(f, package, False)
423 if __name__ == "__main__":
425 if len(sys.argv) == 1:
429 elif sys.argv[1] == "-p":
433 elif ((sys.argv[1] == "-h") or (sys.argv[1] == "--help")):
434 print("Usage: emerge-timer.py [options] [package]\n\nOptions:\n"
435 + green_start + "\t-p" + color_stop +
436 "\tcalculate compile time from piped 'emerge -p' output\n" +
437 green_start + "\t[none]" + color_stop +
438 "\tShow average emerge times for currently compiling packages.")
441 if len(sys.argv) > 1:
442 package_name = sys.argv[1]