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