4 import sys, datetime, os
7 PORTDIR = "/usr/portage/"
8 LOGFILE = "/var/log/emerge.log"
11 green_start = "\033[32m"
21 def __init__(self, name, version=0):
23 self.version = version
25 self.emerge_time = 12*3600
28 def add_version(self, version, emerge_time, emerge_date):
29 """Add version to the class version list"""
30 self.versions.append((version, emerge_time, emerge_date))
33 def average_time(self):
34 """Return average time from class version list"""
36 for i in self.versions:
39 average_time = total_time/len(self.versions)
45 """Return total time from class version list"""
47 for i in self.versions:
54 """Return maximum time from class version list"""
57 return self.versions[len(self.versions)-1][1]
61 """Return minimum time from class version list"""
64 return self.versions[0][1]
67 def print_current_emerge(self):
68 """Function used to print all the current emerge stuff"""
70 print("\t" + green_start + self.name + '-' + self.version +
71 color_stop + "\n\t current time: " + give_time(self.emerge_time) +
72 "\n\t average time: "),
74 if len(self.versions) > 1:
75 print(give_time(self.average_time())),
79 print("\n\t " + '-'*45),
81 finish_time = self.average_time() - self.emerge_time
83 print("\n\t time to finish: "),
86 print(give_time(finish_time))
92 def print_versions(self):
93 """This prints the emerge times for different versions in the
94 normal operating mode of the script"""
101 for p in self.versions:
102 if len(p[0]) > version_length:
103 version_length = len(p[0])
105 if len(give_time(p[1], True)) > time_length:
106 time_length = len(give_time(p[1], True))
108 for p in self.versions:
110 pad = time_length - len(give_time(p[1], True))
112 print('-'*90 + "\n" +
113 green_start + self.name + (p[0]).ljust(version_length) +
114 color_stop + " >>> " + (give_time(p[1])) + " "*pad +
115 " >>> " + give_date(p[2]))
117 print('-'*90 + "\n" + "Package " + green_start +
118 self.name + color_stop + " emerged " +
119 str(len(self.versions)) + " times.")
124 def print_pretended_times(self):
125 """This is used the print all the pretended times"""
128 print("\t" + green_start + self.name + '-' + self.version + color_stop),
130 if len(self.versions) > 1:
131 aver_time = self.average_time()
134 print("\n\taverage time: " + give_time(aver_time))
140 print("\n\t no previous emerges")
145 def print_min_max_ave(self):
146 maxi = self.max_time()
147 mini = self.min_time()
148 average = self.average_time()
149 total = self.total_time()
151 print("Max time: \t" + give_time(maxi) +
152 "\nMin time: \t" + give_time(mini) +
153 "\nAverage time: \t" + give_time(average) +
154 "\nIn total spent " + give_time(total) +
155 " emerging " + green_start + self.name + color_stop)
159 def give_time(time, nocolor=False):
160 """Converts time in seconds to human readable form"""
161 global green_start, color_stop
163 if green_start == "":
170 days = time/(3600*24)
171 hours = (days - int(days))*24
172 minutes = (hours - int(hours))*60
173 seconds = (minutes - int(minutes))*60
177 minutes = int(minutes)
178 seconds = int(round(seconds))
186 pdays = (green_start + str(days) +
187 color_stop + " day ")
189 pdays = (green_start + str(days) +
190 color_stop + " days ")
193 phours = (green_start + str(hours) +
194 color_stop + " hour ")
196 phours = (green_start + str(hours) +
197 color_stop + " hours ")
200 pminutes = (green_start + str(minutes) +
201 color_stop + " minute ")
203 pminutes = (green_start + str(minutes) +
204 color_stop + " minutes ")
206 pseconds = (green_start + str(seconds) +
207 color_stop + " second ")
209 pseconds = (green_start + str(seconds) +
210 color_stop + " seconds ")
213 green_start = "\033[32m"
214 color_stop = "\033[m"
216 return (pdays + phours + pminutes + pseconds)
220 def give_date(emerge_date):
221 """Returns a date string from a standard POSIX time"""
222 date = datetime.datetime.fromtimestamp(emerge_date)
224 date = "{:%d.%m.%Y %H:%M:%S}".format(date)
231 """Attempt to open the LOGFILE."""
234 f = open(LOGFILE, 'r')
235 except IOError as detail:
243 def search_log_for_package(package_class):
244 """Searchs emerge log for given package and adds all found
245 versions with their emerge times to the class"""
250 if ((">>>" in line) and ("emerge" in line)):
251 if package_class.name in line:
253 version = line.partition(package_class.name)[2].partition(' ')[0]
254 digit = version.strip('-')[0].isdigit()
257 time_string = line.partition(">>>")
258 start_time = float(time_string[0].strip().strip(':'))
260 elif ((":::" in line) and ("completed emerge" in line)):
262 if package_class.name in line:
264 time_string = line.partition(":::")
265 stop_time = float(time_string[0].strip().strip(':'))
267 emerge_time = stop_time - start_time
269 package_class.add_version(version, emerge_time, start_time)
273 def get_package(name):
274 """Take the user-input package name and search for it
277 dirlist = os.listdir(PORTDIR)
278 possible_package = []
281 # If the given name is in the format xxx/zzz
282 # assume that xxx is the package group
284 group = name.partition('/')[0]
285 pkg = name.partition('/')[2]
286 directory = PORTDIR + group
289 dirs = os.listdir(directory)
291 possible_package.append(name)
294 # Go through the directory listing searching for anything
295 # that matches the given name
297 directory = PORTDIR + i
298 if os.path.isdir(directory):
299 dirs = os.listdir(directory)
301 possible_package.append(i + '/' + name)
304 if len(possible_package) > 1:
305 print("Multiple packages found for '" + name + "'.")
306 print("Possible packages: ")
307 for value in possible_package:
311 elif len(possible_package) == 1:
312 package = possible_package[0]
317 print("No package '" + name + "' found")
324 def list_pretended():
325 """List all the pretended packages given by emerge -p
326 output. Create a class out of each of those packages and add them
331 for line in sys.stdin:
332 if "[ebuild" in line:
333 full_name = line.partition("] ")[2].partition(' ')[0]
335 version = full_name.partition('/')[2].partition('-')[2]
336 while not version[0].isdigit():
337 version = version.partition('-')[2]
338 package_name = full_name[:-len(version)-1]
340 PACKAGES.append(package(package_name, version))
344 def list_emerge_processes():
345 """Look for the ebuild process with ps. If the process is found parse
346 the command for the package. With this package search the LOGFILE for
347 the emerge startup time."""
351 now = datetime.datetime.today()
353 for i in os.popen("ps ax"):
354 if (("ebuild.sh" in i) and ("/bin/bash" not in i)):
355 pack = i.partition('[')[2].partition(']')[0]
357 version = pack.partition('/')[2].partition('-')[2]
359 while not version[0].isdigit():
360 version = version.partition('-')[2]
362 package_name = pack[:-len(version)-1]
364 PACKAGES.append(package(package_name, version))
367 if len(PACKAGES) == 0:
368 print "No current emerge process found."
373 if ((">>>" in line) and ("emerge" in line)):
375 if (p.name + '-' + p.version in line):
377 time = float(line.partition(' ')[0].strip(":"))
379 timestamp = datetime.datetime.fromtimestamp(time)
380 difference = (now - timestamp).total_seconds()
382 if difference < p.emerge_time:
383 p.emerge_time = difference
387 def main(status, user_package=None):
388 """Main function. Hanlde all the different modes of operation."""
390 if status == "package":
391 user_package = get_package(user_package)
393 pack = package(user_package)
395 search_log_for_package(pack)
396 pack.print_versions()
397 pack.print_min_max_ave()
400 elif status == "current":
401 list_emerge_processes()
403 print "Currently emerging:"
406 search_log_for_package(p)
407 p.print_current_emerge()
410 elif status == "pretended":
413 print "This is how long these packages would take to emerge"
415 total_pretended_time = 0
418 search_log_for_package(p)
420 total_pretended_time += p.print_pretended_times()
424 print("Total emerge time of " + green_start + str(len(PACKAGES)) +
425 color_stop + " package(s): "+ give_time(total_pretended_time))
429 usage = """Usage: emerge-timer.py [package] [options]
431 Calculate emerge times from emerge log.
434 \t-c, --current \t Show time until currently compiling package finishes
435 \t-p, --pretended Calculate compile time from piped 'emerge -p' output
436 \t-h, --help \t Show this helpscreen
437 \t-q, --quiet \t Be less verbose
438 \t--no-color \t Use colorless output"""
445 if __name__ == "__main__":
447 # Set the default mode as "package"
452 for arg in sys.argv[1:]:
454 if arg == "-p" or arg == "--pretended":
457 if arg == "-c" or arg == "--current":
460 if arg == "-h" or arg == "--help":
463 if arg == "-q" or arg == "--quiet":
466 if arg == "--no-color":
471 if len(sys.argv) > 1:
472 input_package = sys.argv[1]
476 main(mode, input_package)