]> git.itanic.dy.fi Git - emerge-timer/blob - emerge-timer.py
Quit the current emerge block is no emerge is found
[emerge-timer] / emerge-timer.py
1 #!/usr/bin/python
2
3
4 import sys, subprocess, datetime, os, re
5
6
7 PORTDIR = "/usr/portage/"
8 LOGFILE = "/var/log/emerge.log"
9
10 green_start = "\033[32m"
11 color_stop = "\033[m"
12
13 packages = []
14
15
16 class package:
17     def __init__(self, name, version=0):
18         self.name = name
19         self.version = version
20         self.versions = []
21         self.emerge_time = 12*3600
22
23     def add_version(self, version, emerge_time, emerge_date):
24
25         self.versions.append((version, emerge_time, emerge_date))
26
27
28     def average_time(self):
29         total_time = 0
30         for i in self.versions:
31             total_time += i[1]
32
33         average_time = total_time/len(self.versions)
34
35         return average_time
36
37     def total_time(self):
38         total_time = 0
39         for i in self.versions:
40             total_time += i[1]
41
42         return total_time
43
44
45     def max_time(self):
46         self.versions.sort()
47
48         return self.versions[len(self.versions)-1][1]
49
50
51     def min_time(self):
52         self.versions.sort()
53
54         return self.versions[0][1]
55
56
57     def print_current_emerge(self):
58
59         print("\t" + green_start + self.name + '-' + self.version +
60               color_stop + "\n\t current time: " + self.time(self.emerge_time) +
61               "\n\t average time: "),
62
63         if len(self.versions) > 1:
64             print(self.time(self.average_time())),
65         else:
66             print("unknown"),
67
68         print("\n\t " + '-'*45),
69
70         finish_time = self.average_time() - self.emerge_time
71
72         print("\n\t time to finish: "),
73
74         if finish_time > 0:
75             print(self.time(finish_time))
76         else:
77             print("any time now")
78
79
80     def print_versions(self):
81         for p in self.versions:
82             print('-'*90 + "\n" +
83                   green_start + self.name + p[0] + color_stop + "  >>>  " +
84                   self.time(p[1]) + "  >>>  " +
85                   self.date(p[2]))
86         print('-'*90 + "\n" + "Package " + green_start + self.name + color_stop +
87               " emerged " + str(len(self.versions)) + " times.")
88         print
89
90     def print_pretended_times(self):
91         print("\t" + green_start + self.name + '-' + self.version + color_stop),
92
93         if len(self.versions) > 1:
94             print("\n\taverage time: " + self.time(self.average_time()))
95         else:
96             print("\n\t no previous emerges")
97
98
99     def print_min_max_ave(self):
100         maxi = self.max_time()
101         mini = self.min_time()
102         average = self.average_time()
103         total = self.total_time()
104
105         print("Max time: \t" + self.time(maxi) +
106               "\nMin time: \t" + self.time(mini) +
107               "\nAverage time: \t" + self.time(average) +
108               "\nIn total spent " + self.time(total) +
109               " emerging " + green_start + self.name + color_stop)
110
111     def time(self, time):
112
113         days = time/(3600*24)
114         hours = (days - int(days))*24
115         minutes = (hours - int(hours))*60
116         seconds = (minutes - int(minutes))*60
117
118         days = int(days)
119         hours = int(hours)
120         minutes = int(minutes)
121         seconds = int(round(seconds))
122
123         pdays = str()
124         phours = str()
125         pminutes = str()
126         pseconds = str()
127
128         if days > 0:
129             pdays = (green_start + str(days) + color_stop + " day ")
130             if days != 1:
131                 pdays = (green_start + str(days) + color_stop + " days ")
132
133         if hours > 0:
134             phours = (green_start + str(hours) + color_stop + " hour ")
135             if hours != 1:
136                 phours = (green_start + str(hours) + color_stop + " hours ")
137
138         if minutes > 0:
139             pminutes = (green_start + str(minutes) + color_stop + " minute ")
140             if minutes != 1:
141                 pminutes = (green_start + str(minutes) + color_stop + " minutes ")
142
143         pseconds = (green_start + str(seconds) + color_stop + " second ")
144         if seconds != 1:
145             pseconds = (green_start + str(seconds) + color_stop + " seconds ")
146
147         return (pdays + phours + pminutes + pseconds)
148
149
150     def date(self, emerge_date):
151         date = datetime.datetime.fromtimestamp(emerge_date)
152
153         year = str(date.year)
154         month = str(date.month)
155         day = str(date.day)
156         hour = str(date.hour)
157         minute = str(date.minute)
158         second = str(date.second)
159
160         date = "{:%d.%m.%Y %H:%M:%S}".format(date)
161
162         return date
163
164
165
166 def open_log():
167     """Attempt to open the LOGFILE."""
168
169     try:
170         f = open(LOGFILE, 'r')
171     except IOError as detail:
172         print detail
173         sys.exit(1)
174     finally:
175         return f
176
177
178
179 def search_log_for_package(package_class):
180
181     log = open_log()
182
183     for line in log:
184         if ((">>>" in line) and ("emerge" in line)):
185             if package_class.name in line:
186                 version = line.partition(package_class.name)[2].partition(' ')[0]
187                 digit = version.strip('-')[0].isdigit()
188
189                 if digit:
190                     time_string = line.partition(">>>")
191                     start_time = float(time_string[0].strip().strip(':'))
192
193         elif ((":::" in line) and ("completed emerge" in line)):
194             if package_class.name in line:
195                 if digit:
196                     time_string = line.partition(":::")
197                     stop_time = float(time_string[0].strip().strip(':'))
198
199                     emerge_time = stop_time - start_time
200
201                     package_class.add_version(version, emerge_time, start_time)
202
203
204 def get_package(name):
205     """Take the user-input package name and search for it
206     in PORTDIR. """
207
208     dirlist = os.listdir(PORTDIR)
209     possible_package = []
210
211
212     # If the given name is in the format xxx/zzz
213     # assume that xxx is the package group
214     if '/' in name:
215         group = name.partition('/')[0]
216         pkg = name.partition('/')[2]
217         directory = PORTDIR + group
218
219         if group in dirlist:
220             dirs = os.listdir(directory)
221             if pkg in dirs:
222                 possible_package.append(name)
223
224
225     # Go through the directory listing searching for anything
226     # that matches the given name
227     for i in dirlist:
228         directory = PORTDIR + i
229         if os.path.isdir(directory):
230             dirs = os.listdir(directory)
231             if name in dirs:
232                 possible_package.append(i + '/' + name)
233
234
235     if len(possible_package) > 1:
236         print("Multiple packages found for '" + name + "'.")
237         print("Possible packages: ")
238         for value in possible_package:
239             print("\t" + value)
240
241
242     elif len(possible_package) == 1:
243         package = possible_package[0]
244         return package
245
246
247     else:
248         print("No package '" + name + "' found")
249
250
251     sys.exit(1)
252
253
254 def list_pretended():
255     log = open_log()
256
257     for line in sys.stdin:
258         if "[ebuild" in line:
259             full_name = line.partition("] ")[2].partition(' ')[0]
260
261             version = full_name.partition('/')[2].partition('-')[2]
262             while not version[0].isdigit():
263                 version = version.partition('-')[2]
264             package_name = full_name[:-len(version)-1]
265
266             packages.append(package(package_name, version))
267
268
269 def list_emerge_processes():
270     """Look for the ebuild process with ps. If the process is found parse
271     the command for the package. With this package search the LOGFILE for
272     the emerge startup time."""
273
274     f = open_log()
275
276     now = datetime.datetime.today()
277
278     for i in os.popen("ps ax"):
279         if (("ebuild.sh" in i) and ("/bin/bash" not in i)):
280             pack = i.partition('[')[2].partition(']')[0]
281
282             version = pack.partition('/')[2].partition('-')[2]
283
284             while not version[0].isdigit():
285                 version = version.partition('-')[2]
286
287             package_name = pack[:-len(version)-1]
288
289             packages.append(package(package_name, version))
290
291
292     if len(packages) == 0:
293         print "No current emerge process found."
294         sys.exit(0)
295
296
297     for line in f:
298         if ((">>>" in line) and ("emerge" in line)):
299             for p in packages:
300                 if (p.name + '-' + p.version in line):
301
302                     time = float(line.partition(' ')[0].strip(":"))
303
304                     timestamp = datetime.datetime.fromtimestamp(time)
305                     difference = (now - timestamp).total_seconds()
306
307                     if difference < p.emerge_time:
308                         p.emerge_time = difference
309
310
311
312
313
314 def main(status, user_package=None):
315
316     if status == "package":
317         user_package = get_package(user_package)
318
319         pack = package(user_package)
320
321         search_log_for_package(pack)
322         pack.print_versions()
323         pack.print_min_max_ave()
324
325
326     elif status == "current":
327         list_emerge_processes()
328
329         print "Currently emerging:"
330
331         for p in packages:
332             search_log_for_package(p)
333             p.print_current_emerge()
334
335
336     elif status == "pretended":
337         list_pretended()
338
339         print "This is how long these packages would take to emerge"
340
341         for p in packages:
342             search_log_for_package(p)
343             p.print_pretended_times()
344             print
345
346
347 if __name__ == "__main__":
348
349     if len(sys.argv) == 1:
350         main("current")
351         sys.exit(1)
352
353     elif sys.argv[1] == "-p":
354         main("pretended")
355         sys.exit(1)
356
357     elif len(sys.argv) > 1:
358         main("package", sys.argv[1])
359