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)
90 def get_package(name):
91 """Take the user-input package name and search for it
94 dirlist = os.listdir(PORTDIR)
98 # If the given name is in the format xxx/zzz
99 # assume that xxx is the package group
101 group = name.partition('/')[0]
102 pkg = name.partition('/')[2]
103 directory = PORTDIR + group
106 dirs = os.listdir(directory)
108 possible_package.append(name)
111 # Go through the directory listing searching for anything
112 # that matches the given name
114 directory = PORTDIR + i
115 if os.path.isdir(directory):
116 dirs = os.listdir(directory)
118 possible_package.append(i + '/' + name)
121 if len(possible_package) > 1:
122 print("Multiple packages found for '" + name + "'.")
123 print("Possible packages: ")
124 for value in possible_package:
128 elif len(possible_package) == 1:
129 package = possible_package[0]
134 print("No package '" + name + "' found")
141 def print_times(package, times, silent):
142 """Print the maximum/minimum/average times of the given emerge package.
143 If we're in the 'current emerge stage' (the 'silent' flag is True)
144 print the appropriate comment for that package."""
151 # This should be True if we're in current emerge stage
154 print("\t no previous emerges found for this package"),
157 elif len(times) == 1:
158 print("\t previous emerge time:\t"),
159 organize_times(times[0][0])
160 print("(only one emerge previously)"),
164 print("\t average emerge time:\t"),
169 organize_times(all_times/len(times))
171 return all_times/len(times)
175 print(green_start + package + color_stop + " emerged once")
178 print(green_start + package + color_stop + " emerged " + green_start +
179 str(len(times)) + color_stop + " times\n")
182 organize_times(times[0][0])
183 print "at", times[0][1]
186 organize_times(times[len(times)-1][0])
187 print "at", times[len(times)-1][1]
193 print "Average time\t",
194 organize_times(all_times/len(times))
197 print "In total spent\t",
198 organize_times(all_times)
199 print("emerging " + green_start +
200 package + color_stop)
205 """Attempt to open the LOGFILE."""
208 f = open(LOGFILE, 'r')
209 except IOError as detail:
217 def list_emerge_processes(f):
218 """Look for the ebuild process with ps. If the process is found parse
219 the command for the package. With this package search the LOGFILE for
220 the emerge startup time."""
222 now = datetime.datetime.today()
225 for i in os.popen("ps ax"):
226 if (("ebuild.sh" in i) and ("/bin/bash" not in i)):
227 pack = i.partition('[')[2].partition(']')[0]
229 version = pack.partition('/')[2].partition('-')[2]
231 while not version[0].isdigit():
232 version = version.partition('-')[2]
234 package_name = pack[:-len(version)-1]
236 packages.append([package_name, '-'+version, 12*3600])
240 if ((">>>" in line) and ("emerge" in line)):
242 if (p[0]+p[1] in line):
244 time = float(line.partition(' ')[0].strip(":"))
246 timestamp = datetime.datetime.fromtimestamp(time)
247 difference = (now - timestamp).total_seconds()
249 if difference < p[2]:
253 if len(packages) == 0:
254 print "No current emerge process found."
257 print_current_emerges(f, packages)
262 def print_current_emerges(f, packages):
263 """Print the current packages that are being merged with the
264 current emerge time."""
267 print("Currently emerging: ")
270 print("\t" + green_start + p[0] + p[1] + color_stop),
271 print("\n\t current emerge time:\t"),
276 average_time = main_loop(f, p[0], True)
278 if average_time != 0:
279 print("\n\t " + '-'*45 + "\n\t time to finish: \t"),
281 if (average_time - p[2]) < 0:
282 print(green_start + "Any time now" + color_stop),
285 organize_times(average_time - p[2])
291 def list_pretended(f):
292 """Print the average times of pretended packages"""
295 for line in sys.stdin:
296 if "[ebuild" in line:
297 full_name = line.partition('] ')[2].partition(' ')[0]
299 version = full_name.partition('/')[2].partition('-')[2]
300 while not version[0].isdigit():
301 version = version.partition('-')[2]
303 package_name = full_name[:-len(version)-1]
305 packages.append((package_name, '-' + version))
308 if len(packages) == 0:
311 print "This is how long these packages would take to emerge"
314 for pack in packages:
316 print('\t' + green_start + pack[0] + pack[1] + color_stop)
318 all_time += main_loop(f, pack[0], True)
323 if len(packages) > 1:
324 print("Total emerge time of " + green_start + str(len(packages)) +
325 color_stop + " packages:"),
326 organize_times(all_time)
331 def main_loop(f, package, silent):
332 """The main loop which parses the LOGFILE and if needed prints out emerge times."""
334 f.seek(0) # Seek to the beginning of the file
339 if ((">>>" in line) and ("emerge" in line)):
341 version = line.partition(package)[2].partition(' ')[0]
343 if version.strip('-')[0].isdigit():
344 full_package = package + version
346 time_string = line.partition(">>>")
347 start_time = float(time_string[0].strip().strip(':'))
350 elif ((":::" in line) and ("completed emerge" in line)):
352 if version.strip('-')[0].isdigit():
354 time_string = line.partition(":::")
355 end_time = float(time_string[0].strip().strip(':'))
358 emerge_time = end_time - start_time
360 date = get_date(start_time)
364 print(str(len(times)+1) + ". " +
365 green_start + full_package + color_stop +
366 " >>> " + date + " >>> "),
368 organize_times(emerge_time)
373 times.append((emerge_time, date))
376 average_time = print_times(package, times, silent)
382 """Change between current emerge stage and normal operating stage."""
386 if status == 'current':
387 list_emerge_processes(f)
389 elif status == 'pretended':
395 package = get_package(package_name)
399 main_loop(f, package, False)
405 if __name__ == "__main__":
407 if len(sys.argv) == 1:
411 elif sys.argv[1] == "-p":
415 elif ((sys.argv[1] == "-h") or (sys.argv[1] == "--help")):
416 print("Usage: emerge-timer.py [options] [package]\n\nOptions:\n"
417 + green_start + "\t-p" + color_stop +
418 "\tcalculate compile time from piped 'emerge -p' output\n" +
419 green_start + "\t[none]" + color_stop +
420 "\tShow average emerge times for currently compiling packages.")
423 if len(sys.argv) > 1:
424 package_name = sys.argv[1]