#!/usr/bin/python import sys, datetime, os PORTDIR = "/usr/portage/" LOGFILE = "/var/log/emerge.log" green_start = "\033[32m" color_stop = "\033[m" packages = [] class package: def __init__(self, name, version=0): self.name = name self.version = version self.versions = [] self.emerge_time = 12*3600 def add_version(self, version, emerge_time, emerge_date): self.versions.append((version, emerge_time, emerge_date)) def average_time(self): total_time = 0 for i in self.versions: total_time += i[1] average_time = total_time/len(self.versions) return average_time def total_time(self): total_time = 0 for i in self.versions: total_time += i[1] return total_time def max_time(self): self.versions.sort() return self.versions[len(self.versions)-1][1] def min_time(self): self.versions.sort() return self.versions[0][1] def print_current_emerge(self): print("\t" + green_start + self.name + '-' + self.version + color_stop + "\n\t current time: " + self.time(self.emerge_time) + "\n\t average time: "), if len(self.versions) > 1: print(self.time(self.average_time())), else: print("unknown"), print("\n\t " + '-'*45), finish_time = self.average_time() - self.emerge_time print("\n\t time to finish: "), if finish_time > 0: print(self.time(finish_time)) else: print("any time now") def print_versions(self): for p in self.versions: print('-'*90 + "\n" + green_start + self.name + p[0] + color_stop + " >>> " + self.time(p[1]) + " >>> " + self.date(p[2])) print('-'*90 + "\n" + "Package " + green_start + self.name + color_stop + " emerged " + str(len(self.versions)) + " times.") print def print_pretended_times(self): print("\t" + green_start + self.name + '-' + self.version + color_stop), if len(self.versions) > 1: print("\n\taverage time: " + self.time(self.average_time())) else: print("\n\t no previous emerges") def print_min_max_ave(self): maxi = self.max_time() mini = self.min_time() average = self.average_time() total = self.total_time() print("Max time: \t" + self.time(maxi) + "\nMin time: \t" + self.time(mini) + "\nAverage time: \t" + self.time(average) + "\nIn total spent " + self.time(total) + " emerging " + green_start + self.name + color_stop) def time(self, time): days = time/(3600*24) hours = (days - int(days))*24 minutes = (hours - int(hours))*60 seconds = (minutes - int(minutes))*60 days = int(days) hours = int(hours) minutes = int(minutes) seconds = int(round(seconds)) pdays = str() phours = str() pminutes = str() pseconds = str() if days > 0: pdays = (green_start + str(days) + color_stop + " day ") if days != 1: pdays = (green_start + str(days) + color_stop + " days ") if hours > 0: phours = (green_start + str(hours) + color_stop + " hour ") if hours != 1: phours = (green_start + str(hours) + color_stop + " hours ") if minutes > 0: pminutes = (green_start + str(minutes) + color_stop + " minute ") if minutes != 1: pminutes = (green_start + str(minutes) + color_stop + " minutes ") pseconds = (green_start + str(seconds) + color_stop + " second ") if seconds != 1: pseconds = (green_start + str(seconds) + color_stop + " seconds ") return (pdays + phours + pminutes + pseconds) def date(self, emerge_date): date = datetime.datetime.fromtimestamp(emerge_date) year = str(date.year) month = str(date.month) day = str(date.day) hour = str(date.hour) minute = str(date.minute) second = str(date.second) date = "{:%d.%m.%Y %H:%M:%S}".format(date) return date def open_log(): """Attempt to open the LOGFILE.""" try: f = open(LOGFILE, 'r') except IOError as detail: print detail sys.exit(1) finally: return f def search_log_for_package(package_class): log = open_log() for line in log: if ((">>>" in line) and ("emerge" in line)): if package_class.name in line: version = line.partition(package_class.name)[2].partition(' ')[0] digit = version.strip('-')[0].isdigit() if digit: time_string = line.partition(">>>") start_time = float(time_string[0].strip().strip(':')) elif ((":::" in line) and ("completed emerge" in line)): if package_class.name in line: if digit: time_string = line.partition(":::") stop_time = float(time_string[0].strip().strip(':')) emerge_time = stop_time - start_time package_class.add_version(version, emerge_time, start_time) def get_package(name): """Take the user-input package name and search for it in PORTDIR. """ dirlist = os.listdir(PORTDIR) possible_package = [] # If the given name is in the format xxx/zzz # assume that xxx is the package group if '/' in name: group = name.partition('/')[0] pkg = name.partition('/')[2] directory = PORTDIR + group if group in dirlist: dirs = os.listdir(directory) if pkg in dirs: possible_package.append(name) # Go through the directory listing searching for anything # that matches the given name for i in dirlist: directory = PORTDIR + i if os.path.isdir(directory): dirs = os.listdir(directory) if name in dirs: possible_package.append(i + '/' + name) if len(possible_package) > 1: print("Multiple packages found for '" + name + "'.") print("Possible packages: ") for value in possible_package: print("\t" + value) elif len(possible_package) == 1: package = possible_package[0] return package else: print("No package '" + name + "' found") sys.exit(1) def list_pretended(): log = open_log() for line in sys.stdin: if "[ebuild" in line: full_name = line.partition("] ")[2].partition(' ')[0] version = full_name.partition('/')[2].partition('-')[2] while not version[0].isdigit(): version = version.partition('-')[2] package_name = full_name[:-len(version)-1] packages.append(package(package_name, version)) def list_emerge_processes(): """Look for the ebuild process with ps. If the process is found parse the command for the package. With this package search the LOGFILE for the emerge startup time.""" f = open_log() now = datetime.datetime.today() for i in os.popen("ps ax"): if (("ebuild.sh" in i) and ("/bin/bash" not in i)): pack = i.partition('[')[2].partition(']')[0] version = pack.partition('/')[2].partition('-')[2] while not version[0].isdigit(): version = version.partition('-')[2] package_name = pack[:-len(version)-1] packages.append(package(package_name, version)) if len(packages) == 0: print "No current emerge process found." sys.exit(0) for line in f: if ((">>>" in line) and ("emerge" in line)): for p in packages: if (p.name + '-' + p.version in line): time = float(line.partition(' ')[0].strip(":")) timestamp = datetime.datetime.fromtimestamp(time) difference = (now - timestamp).total_seconds() if difference < p.emerge_time: p.emerge_time = difference def main(status, user_package=None): if status == "package": user_package = get_package(user_package) pack = package(user_package) search_log_for_package(pack) pack.print_versions() pack.print_min_max_ave() elif status == "current": list_emerge_processes() print "Currently emerging:" for p in packages: search_log_for_package(p) p.print_current_emerge() elif status == "pretended": list_pretended() print "This is how long these packages would take to emerge" for p in packages: search_log_for_package(p) p.print_pretended_times() print if __name__ == "__main__": if len(sys.argv) == 1: main("current") sys.exit(1) elif sys.argv[1] == "-p": main("pretended") sys.exit(1) elif len(sys.argv) > 1: main("package", sys.argv[1])