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.sh" in i) and ("/bin/bash" not in i)):
251 pack = i.partition('[')[2].partition(']')[0]
253 version = pack.partition('/')[2].partition('-')[2]
255 while not version[0].isdigit():
256 version = version.partition('-')[2]
258 package_name = pack[:-len(version)-1]
260 packages.append([package_name, '-'+version, 12*3600])
264 if ((">>>" in line) and ("emerge" in line)):
266 if (p[0]+p[1] in line):
268 time = float(line.partition(' ')[0].strip(":"))
270 timestamp = datetime.datetime.fromtimestamp(time)
271 difference = (now - timestamp).total_seconds()
273 if difference < p[2]:
277 if len(packages) == 0:
278 print "No current emerge process found."
281 print_current_emerges(f, packages)
286 def print_current_emerges(f, packages):
287 """Print the current packages that are being merged with the
288 current emerge time."""
291 print("Currently emerging: ")
294 print("\t" + green_start + p[0] + p[1] + color_stop),
295 print("\n\t current emerge time:\t"),
300 average_time = main_loop(f, p[0], True)
302 if average_time != 0:
303 print("\n\t " + '-'*45 + "\n\t time to finish: \t"),
305 if (average_time - p[2]) < 0:
306 print(green_start + "Any time now" + color_stop),
309 organize_times(average_time - p[2])
315 def list_pretended(f):
316 """Print the average times of pretended packages"""
319 for line in sys.stdin:
320 if "[ebuild" in line:
321 full_name = line.partition('] ')[2].partition(' ')[0]
323 version = full_name.partition('/')[2].partition('-')[2]
324 while not version[0].isdigit():
325 version = version.partition('-')[2]
327 package_name = full_name[:-len(version)-1]
329 packages.append((package_name, '-' + version))
332 if len(packages) == 0:
335 print "This is how long these packages would take to emerge"
338 for pack in packages:
340 print('\t' + green_start + pack[0] + pack[1] + color_stop)
342 all_time += main_loop(f, pack[0], True)
347 if len(packages) > 1:
348 print("Total emerge time of " + green_start + str(len(packages)) +
349 color_stop + " packages:"),
350 organize_times(all_time)
355 def main_loop(f, package, silent):
356 """The main loop which parses the LOGFILE and if needed prints out emerge times."""
358 f.seek(0) # Seek to the beginning of the file
363 if ((">>>" in line) and ("emerge" in line)):
365 version = line.partition(package)[2].partition(' ')[0]
367 if version.strip('-')[0].isdigit():
368 full_package = package + version
370 time_string = line.partition(">>>")
371 start_time = float(time_string[0].strip().strip(':'))
374 elif ((":::" in line) and ("completed emerge" in line)):
376 if version.strip('-')[0].isdigit():
378 time_string = line.partition(":::")
379 end_time = float(time_string[0].strip().strip(':'))
382 emerge_time = end_time - start_time
384 date = get_date(start_time)
388 print(str(len(times)+1) + ". " +
389 green_start + full_package + color_stop +
390 " >>> " + date + " >>> "),
392 organize_times(emerge_time)
397 times.append((emerge_time, date))
400 average_time = print_times(package, times, silent)
406 """Change between current emerge stage and normal operating stage."""
410 if status == 'current':
411 list_emerge_processes(f)
413 elif status == 'pretended':
419 package = get_package(package_name)
423 main_loop(f, package, False)
429 if __name__ == "__main__":
431 if len(sys.argv) == 1:
435 elif sys.argv[1] == "-p":
439 elif ((sys.argv[1] == "-h") or (sys.argv[1] == "--help")):
440 print("Usage: emerge-timer.py [options] [package]\n\nOptions:\n"
441 + green_start + "\t-p" + color_stop +
442 "\tcalculate compile time from piped 'emerge -p' output\n" +
443 green_start + "\t[none]" + color_stop +
444 "\tShow average emerge times for currently compiling packages.")
447 if len(sys.argv) > 1:
448 package_name = sys.argv[1]