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
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))
74 if len(self.versions) == 1:
75 print("\t last time: "),
76 print(give_time(self.average_time())),
78 elif len(self.versions) > 1:
79 print("\t average time:"),
80 print(give_time(self.average_time())),
83 print(green_start + "unknown" + color_stop),
85 print("\n\t " + '-'*45),
87 print("\n\t time to finish:"),
89 if type(self.emerge_time) != str:
91 finish_time = self.average_time() - self.emerge_time
94 print(give_time(finish_time))
96 print(green_start + "any time now" + color_stop)
98 print(green_start + "unknown" + color_stop)
102 def print_versions(self):
103 """This prints the emerge times for different versions in the
104 'package' operating mode of the script"""
111 for p in self.versions:
112 if len(p[0]) > version_length:
113 version_length = len(p[0])
115 if len(give_time(p[1], True)) > time_length:
116 time_length = len(give_time(p[1], True))
118 for p in self.versions:
120 pad = time_length - len(give_time(p[1], True))
122 print('-'*90 + "\n" +
123 green_start + self.name + (p[0]).ljust(version_length) +
124 color_stop + " >>> " + (give_time(p[1])) + " "*pad +
125 " >>> " + give_date(p[2]))
127 print('-'*90 + "\n" + "Package " + green_start +
128 self.name + color_stop + " emerged " +
129 str(len(self.versions)) + " times.")
134 def print_pretended_times(self):
135 """This is used the print all the pretended times"""
138 print("\t" + green_start + self.name + '-' + self.version + color_stop),
140 if len(self.versions) > 1:
141 aver_time = self.average_time()
144 print("\n\taverage time: " + give_time(aver_time))
150 print("\n\t no previous emerges")
155 def print_min_max_ave(self):
156 maxi = self.max_time()
157 mini = self.min_time()
158 average = self.average_time()
159 total = self.total_time()
161 print("Max time: \t" + give_time(maxi) +
162 "\nMin time: \t" + give_time(mini) +
163 "\nAverage time: \t" + give_time(average) +
164 "\nIn total spent " + give_time(total) +
165 " emerging " + green_start + self.name + color_stop)
169 def give_time(time, nocolor=False):
170 """Converts time in seconds to human readable form"""
171 global green_start, color_stop
173 if green_start == "":
180 if type(time) == str:
181 return(green_start + "unknown" + color_stop)
184 days = time/(3600*24)
185 hours = (days - int(days))*24
186 minutes = (hours - int(hours))*60
187 seconds = (minutes - int(minutes))*60
191 minutes = int(minutes)
192 seconds = int(round(seconds))
200 pdays = (green_start + str(days) +
201 color_stop + " day ")
203 pdays = (green_start + str(days) +
204 color_stop + " days ")
207 phours = (green_start + str(hours) +
208 color_stop + " hour ")
210 phours = (green_start + str(hours) +
211 color_stop + " hours ")
214 pminutes = (green_start + str(minutes) +
215 color_stop + " minute ")
217 pminutes = (green_start + str(minutes) +
218 color_stop + " minutes ")
220 pseconds = (green_start + str(seconds) +
221 color_stop + " second ")
223 pseconds = (green_start + str(seconds) +
224 color_stop + " seconds ")
227 green_start = "\033[32m"
228 color_stop = "\033[m"
230 return (pdays + phours + pminutes + pseconds)
234 def give_date(emerge_date):
235 """Returns a date string from a standard POSIX time"""
236 date = datetime.datetime.fromtimestamp(emerge_date)
238 date = "{:%d.%m.%Y %H:%M:%S}".format(date)
245 """Attempt to open the LOGFILE."""
248 f = open(LOGFILE, 'r')
249 except IOError as detail:
257 def search_log_for_package(package_class):
258 """Searchs emerge log for given package and adds all found
259 versions with their emerge times to the class"""
264 if ((">>>" in line) and ("emerge" in line)):
265 if package_class.name in line:
267 version = line.partition(package_class.name)[2].partition(' ')[0]
268 digit = version.strip('-')[0].isdigit()
271 time_string = line.partition(">>>")
272 start_time = float(time_string[0].strip().strip(':'))
274 elif ((":::" in line) and ("completed emerge" in line)):
276 if package_class.name in line:
278 time_string = line.partition(":::")
279 stop_time = float(time_string[0].strip().strip(':'))
281 emerge_time = stop_time - start_time
283 package_class.add_version(version, emerge_time, start_time)
287 def get_package(name):
288 """Take the user-input package name and search for it
291 dirlist = os.listdir(PORTDIR)
292 possible_package = []
295 # If the given name is in the format xxx/zzz
296 # assume that xxx is the package group
298 group = name.partition('/')[0]
299 pkg = name.partition('/')[2]
300 directory = PORTDIR + group
303 dirs = os.listdir(directory)
305 possible_package.append(name)
308 # Go through the directory listing searching for anything
309 # that matches the given name
311 directory = PORTDIR + i
312 if os.path.isdir(directory):
313 dirs = os.listdir(directory)
315 possible_package.append(i + '/' + name)
318 if len(possible_package) > 1:
319 print("Multiple packages found for '" + name + "'.")
320 print("Possible packages: ")
321 for value in possible_package:
325 elif len(possible_package) == 1:
326 package = possible_package[0]
331 print("No package '" + name + "' found")
338 def list_pretended():
339 """List all the pretended packages given by emerge -p
340 output. Create a class out of each of those packages and add them
345 for line in sys.stdin:
346 if "[ebuild" in line:
347 full_name = line.partition("] ")[2].partition(' ')[0]
349 version = full_name.partition('/')[2].partition('-')[2]
350 while not version[0].isdigit():
351 version = version.partition('-')[2]
352 package_name = full_name[:-len(version)-1]
354 PACKAGES.append(package(package_name, version))
358 def list_emerge_processes():
359 """Look for the ebuild process with ps. If the process is found parse
360 the command for the package. With this package search the LOGFILE for
361 the emerge startup time."""
365 now = datetime.datetime.today()
367 for i in os.popen("ps ax"):
368 if (("ebuild.sh" in i) and ("/bin/bash" not in i)):
369 pack = i.partition('[')[2].partition(']')[0]
371 version = pack.partition('/')[2].partition('-')[2]
373 while not version[0].isdigit():
374 version = version.partition('-')[2]
376 package_name = pack[:-len(version)-1]
378 PACKAGES.append(package(package_name, version))
381 if len(PACKAGES) == 0:
382 print "No current emerge process found."
388 if ((">>>" in line) and ("emerge" in line)):
390 difference = "infinity"
393 if (p.name + '-' + p.version in line):
395 time = float(line.partition(' ')[0].strip(":"))
397 timestamp = datetime.datetime.fromtimestamp(time)
398 new_difference = (now - timestamp).total_seconds()
400 if ((new_difference < difference) or
401 (difference == "infinity")):
402 difference = new_difference
404 p.emerge_time = difference
410 def main(status, user_package=None):
411 """Main function. Hanlde all the different modes of operation."""
413 if status == "package":
414 user_package = get_package(user_package)
416 pack = package(user_package)
418 search_log_for_package(pack)
420 if len(pack.versions) != 0:
421 pack.print_versions()
422 pack.print_min_max_ave()
425 print("Package " + green_start + pack.name +
426 color_stop + " has never been emerged.")
429 elif status == "current":
430 if list_emerge_processes():
433 print "Currently emerging:"
436 search_log_for_package(p)
437 p.print_current_emerge()
440 elif status == "pretended":
443 print "This is how long these packages would take to emerge"
445 total_pretended_time = 0
448 search_log_for_package(p)
450 total_pretended_time += p.print_pretended_times()
454 print("Total emerge time of " + green_start + str(len(PACKAGES)) +
455 color_stop + " package(s): "+ give_time(total_pretended_time))
459 usage = """Usage: emerge-timer.py [package] [options]
461 Calculate emerge times from emerge log.
464 \t-c, --current \t Show time until currently compiling package finishes
465 \t-p, --pretended Calculate compile time from piped 'emerge -p' output
466 \t-h, --help \t Show this helpscreen
467 \t-q, --quiet \t Be less verbose
468 \t--no-color \t Use colorless output"""
475 if __name__ == "__main__":
477 # Set the default mode as "package"
482 for arg in sys.argv[1:]:
484 if arg == "-p" or arg == "--pretended":
487 if arg == "-c" or arg == "--current":
490 if arg == "-h" or arg == "--help":
493 if arg == "-q" or arg == "--quiet":
496 if arg == "--no-color":
501 if len(sys.argv) > 1:
502 input_package = sys.argv[1]
506 main(mode, input_package)