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)
64 weekday = date.weekday()
66 if weekday == 0: weekday = 'Mon '
67 if weekday == 1: weekday = 'Tue '
68 if weekday == 2: weekday = 'Wed '
69 if weekday == 3: weekday = 'Thu '
70 if weekday == 4: weekday = 'Fri '
71 if weekday == 5: weekday = 'Sat '
72 if weekday == 6: weekday = 'Sun '
75 # This is in the format 'Mon 23.05.2011 00:20:14'
77 date = weekday + "{:%d.%m.%Y %H:%M:%S}".format(date)
84 def get_package(name):
85 """Take the user-input package name and search for it
88 dirlist = os.listdir(PORTDIR)
92 # If the given name is in the format xxx/zzz
93 # assume that xxx is the package group
95 group = name.partition('/')[0]
96 pkg = name.partition('/')[2]
97 directory = PORTDIR + group
100 dirs = os.listdir(directory)
102 possible_package.append(name)
105 # Go through the directory listing searching for anything
106 # that matches the given name
108 directory = PORTDIR + i
109 if os.path.isdir(directory):
110 dirs = os.listdir(directory)
112 possible_package.append(i + '/' + name)
115 if len(possible_package) > 1:
116 print("Multiple packages found for '" + name + "'.")
117 print("Possible packages: ")
118 for value in possible_package:
122 elif len(possible_package) == 1:
123 package = possible_package[0]
128 print("No package '" + name + "' found")
135 def print_times(package, times, silent):
136 """Print the maximum/minimum/average times of the given emerge package.
137 If we're in the 'current emerge stage' (the 'silent' flag is True)
138 print the appropriate comment for that package."""
145 # This should be True if we're in current emerge stage
148 print("\t no previous emerges found for this package"),
151 elif len(times) == 1:
152 print("\t previous emerge time:\t"),
153 organize_times(times[0][0])
154 print("(" + green_start + "1" + color_stop + ")"),
158 print("\t average emerge time:\t"),
163 organize_times(all_times/len(times))
164 print("(" + green_start + str(len(times)) + color_stop + ")"),
165 return all_times/len(times)
169 print(green_start + package + color_stop + " emerged once")
172 print(green_start + package + color_stop + " emerged " + green_start +
173 str(len(times)) + color_stop + " times\n")
176 organize_times(times[0][0])
177 print "at", times[0][1]
180 organize_times(times[len(times)-1][0])
181 print "at", times[len(times)-1][1]
187 print "Average time\t",
188 organize_times(all_times/len(times))
191 print "In total spent\t",
192 organize_times(all_times)
193 print("emerging " + green_start +
194 package + color_stop)
199 """Attempt to open the LOGFILE."""
202 f = open(LOGFILE, 'r')
203 except IOError as detail:
211 def list_emerge_processes(f):
212 """Look for the ebuild process with ps. If the process is found parse
213 the command for the package. With this package search the LOGFILE for
214 the emerge startup time."""
216 now = datetime.datetime.today()
219 for i in os.popen("ps ax"):
220 if (("ebuild.sh" in i) and ("/bin/bash" not in i)):
221 pack = i.partition('[')[2].partition(']')[0]
223 version = pack.partition('/')[2].partition('-')[2]
225 while not version[0].isdigit():
226 version = version.partition('-')[2]
228 package_name = pack[:-len(version)-1]
230 packages.append([package_name, '-'+version, 12*3600])
234 if ((">>>" in line) and ("emerge" in line)):
236 if (p[0]+p[1] in line):
238 time = float(line.partition(' ')[0].strip(":"))
240 timestamp = datetime.datetime.fromtimestamp(time)
241 difference = (now - timestamp).total_seconds()
243 if difference < p[2]:
247 if len(packages) == 0:
248 print "No current emerge process found."
251 print_current_emerges(f, packages)
256 def print_current_emerges(f, packages):
257 """Print the current packages that are being merged with the
258 current emerge time."""
261 print("Currently emerging: ")
264 print("\t" + green_start + p[0] + p[1] + color_stop),
265 print("\n\t current emerge time:\t"),
270 average_time = main_loop(f, p[0], True)
272 if average_time != 0:
273 print("\n\t " + '-'*45 + "\n\t time to finish: \t"),
275 if (average_time - p[2]) < 0:
276 print(green_start + "Any time now" + color_stop),
279 organize_times(average_time - p[2])
285 def list_pretended(f):
286 """Print the average times of pretended packages"""
289 for line in sys.stdin:
290 if "[ebuild" in line:
291 full_name = line.partition('] ')[2].partition(' ')[0]
293 version = full_name.partition('/')[2].partition('-')[2]
294 while not version[0].isdigit():
295 version = version.partition('-')[2]
297 package_name = full_name[:-len(version)-1]
299 packages.append((package_name, '-' + version))
302 if len(packages) == 0:
305 print "This is how long these packages would take to emerge"
308 for pack in packages:
310 print('\t' + green_start + pack[0] + pack[1] + color_stop)
312 all_time += main_loop(f, pack[0], True)
317 if len(packages) > 1:
318 print("Total emerge time of " + green_start + str(len(packages)) +
319 color_stop + " packages:"),
320 organize_times(all_time)
325 def main_loop(f, package, silent):
326 """The main loop which parses the LOGFILE and if needed prints out emerge times."""
328 f.seek(0) # Seek to the beginning of the file
333 if ((">>>" in line) and ("emerge" in line)):
335 version = line.partition(package)[2].partition(' ')[0]
337 if version.strip('-')[0].isdigit():
338 full_package = package + version
340 time_string = line.partition(">>>")
341 start_time = float(time_string[0].strip().strip(':'))
344 elif ((":::" in line) and ("completed emerge" in line)):
346 if version.strip('-')[0].isdigit():
348 time_string = line.partition(":::")
349 end_time = float(time_string[0].strip().strip(':'))
352 emerge_time = end_time - start_time
354 date = get_date(start_time)
358 print(str(len(times)+1) + ". " +
359 green_start + full_package + color_stop +
360 " >>> " + date + " >>> "),
362 organize_times(emerge_time)
367 times.append((emerge_time, date))
370 average_time = print_times(package, times, silent)
376 """Change between current emerge stage and normal operating stage."""
380 if status == 'current':
381 list_emerge_processes(f)
383 elif status == 'pretended':
389 package = get_package(package_name)
393 main_loop(f, package, False)
399 if __name__ == "__main__":
401 if len(sys.argv) == 1:
405 elif sys.argv[1] == "-p":
409 elif ((sys.argv[1] == "-h") or (sys.argv[1] == "--help")):
410 print("Usage: emerge-timer.py [options] [package]\n\nOptions:\n"
411 + green_start + "\t-p" + color_stop +
412 "\tcalculate compile time from piped 'emerge -p' output\n" +
413 green_start + "\t[none]" + color_stop +
414 "\tShow average emerge times for currently compiling packages.")
417 if len(sys.argv) > 1:
418 package_name = sys.argv[1]