- count installs vs upgrades + repackages correctly for progress bar usage
[apt.git] / apt-pkg / rpm / rpmshowprogress.cc
1
2 #include <stdio.h>
3 #include <rpm/rpmlib.h>
4 #include <apti18n.h>
5
6 #include "rpmshowprogress.h"
7
8 static int hashesTotal = 0;
9 static int hashesCurrent = 0;
10 static int progressCurrent = 0;
11 static int progressTotal = 0;
12
13 int packagesTotal;
14
15 static void printHash(const unsigned long amount, const unsigned long total)
16 {
17     int hashesNeeded;
18
19     hashesTotal = (isatty (STDOUT_FILENO) ? 44 : 50);
20
21     if (hashesCurrent != hashesTotal) {
22         float pct = (total ? (((float) amount) / total) : 1.0);
23         hashesNeeded = (int) ((hashesTotal * pct) + 0.5);
24         while (hashesNeeded > hashesCurrent) {
25             if (isatty (STDOUT_FILENO)) {
26                 int i;
27                 for (i = 0; i < hashesCurrent; i++)
28                     (void) putchar ('#');
29                 for (; i < hashesTotal; i++)
30                     (void) putchar (' ');
31                 fprintf(stdout, "(%3d%%)", (int)((100 * pct) + 0.5));
32                 for (i = 0; i < (hashesTotal + 6); i++)
33                     (void) putchar ('\b');
34             } else
35                 fprintf(stdout, "#");
36
37             hashesCurrent++;
38         }
39         (void) fflush(stdout);
40
41         if (hashesCurrent == hashesTotal) {
42             int i;
43             progressCurrent++;
44             if (isatty(STDOUT_FILENO)) {
45                 for (i = 1; i < hashesCurrent; i++)
46                     (void) putchar ('#');
47                 pct = (progressTotal
48                     ? (((float) progressCurrent) / progressTotal)
49                     : 1);
50                 fprintf(stdout, " [%3d%%]", (int)((100 * pct) + 0.5));
51             }
52             fprintf(stdout, "\n");
53         }
54         (void) fflush(stdout);
55     }
56 }
57
58 #if RPM_VERSION < 0x040000
59 void * rpmpmShowProgress(const Header h,
60 #else
61 void * rpmpmShowProgress(const void * arg, 
62 #endif
63                         const rpmCallbackType what,
64                         const unsigned long amount,
65                         const unsigned long total,
66                         const void * pkgKey, void * data)
67 {
68 #if RPM_VERSION >= 0x040000
69     Header h = (Header) arg;
70 #endif
71
72     char * s;
73     int flags = (int) ((long)data);
74     void * rc = NULL;
75     const char * filename = (const char *) pkgKey;
76     static FD_t fd = NULL;
77     static rpmCallbackType state;
78     static bool repackage;
79
80     switch (what) {
81     case RPMCALLBACK_INST_OPEN_FILE:
82         if (filename == NULL || filename[0] == '\0')
83             return NULL;
84         fd = Fopen(filename, "r.ufdio");
85         if (fd)
86             fd = fdLink(fd, "persist (showProgress)");
87         return fd;
88         /*@notreached@*/ break;
89
90     case RPMCALLBACK_INST_CLOSE_FILE:
91         fd = fdFree(fd, "persist (showProgress)");
92         if (fd) {
93             (void) Fclose(fd);
94             fd = NULL;
95         }
96         break;
97
98     case RPMCALLBACK_INST_START:
99         hashesCurrent = 0;
100         if (h == NULL || !(flags & INSTALL_LABEL))
101             break;
102
103         if (state != what && repackage == false) {
104             state = what;
105             fprintf(stdout, "%s\n", _("Installing / Updating..."));
106             (void) fflush(stdout);
107         }
108
109         if (flags & INSTALL_HASH) {
110             s = headerSprintf(h, "%{NAME}.%{ARCH}",
111                                 rpmTagTable, rpmHeaderFormats, NULL);
112             if (isatty (STDOUT_FILENO))
113                 fprintf(stdout, "%4d:%-23.23s", progressCurrent + 1, s);
114             else
115                 fprintf(stdout, "%-28.28s", s);
116             (void) fflush(stdout);
117             free(s);
118             s = NULL;
119         } else {
120             s = headerSprintf(h, "%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}",
121                                   rpmTagTable, rpmHeaderFormats, NULL);
122             fprintf(stdout, "%s\n", s);
123             (void) fflush(stdout);
124             free(s);
125             s = NULL;
126         }
127         break;
128
129     case RPMCALLBACK_TRANS_PROGRESS:
130     case RPMCALLBACK_INST_PROGRESS:
131         if (flags & INSTALL_PERCENT)
132             fprintf(stdout, "%%%% %f\n", (double) (total
133                                 ? ((((float) amount) / total) * 100)
134                                 : 100.0));
135         else if (flags & INSTALL_HASH)
136             printHash(amount, total);
137         (void) fflush(stdout);
138         break;
139
140     case RPMCALLBACK_TRANS_START:
141         state = what;
142         repackage = false;
143         hashesCurrent = 0;
144         progressTotal = 1;
145         progressCurrent = 0;
146         if (!(flags & INSTALL_LABEL))
147             break;
148         if (flags & INSTALL_HASH)
149             fprintf(stdout, "%-28s", _("Preparing..."));
150         else
151             fprintf(stdout, "%s\n", _("Preparing..."));
152         (void) fflush(stdout);
153         break;
154
155     case RPMCALLBACK_TRANS_STOP:
156         if (flags & INSTALL_HASH)
157             printHash(1, 1);    /* Fixes "preparing..." progress bar */
158         progressTotal = packagesTotal;
159         progressCurrent = 0;
160         break;
161
162     case RPMCALLBACK_REPACKAGE_START:
163         hashesCurrent = 0;
164         progressCurrent = 0;
165         repackage = true;
166         if (!(flags & INSTALL_LABEL))
167             break;
168         if (flags & INSTALL_HASH)
169             fprintf(stdout, "%-28s\n", _("Repackaging..."));
170         else
171             fprintf(stdout, "%s\n", _("Repackaging..."));
172         (void) fflush(stdout);
173         break;
174
175     case RPMCALLBACK_REPACKAGE_PROGRESS:
176         if (amount && (flags & INSTALL_HASH))
177             printHash(1, 1);    /* Fixes "preparing..." progress bar */
178         break;
179
180     case RPMCALLBACK_REPACKAGE_STOP:
181         progressTotal = total;
182         progressCurrent = total;
183         if (flags & INSTALL_HASH)
184             printHash(1, 1);    /* Fixes "preparing..." progress bar */
185         progressTotal = packagesTotal;
186         repackage = false;
187         break;
188
189     case RPMCALLBACK_UNINST_PROGRESS:
190         break;
191     case RPMCALLBACK_UNINST_START:
192         hashesCurrent = 0;
193         if (!(flags & INSTALL_LABEL))
194             break;
195         if (state != what) {
196             state = what;
197             fprintf(stdout, "%s\n", _("Removing / Cleaning up..."));
198             (void) fflush(stdout);
199         }
200         break;
201
202     case RPMCALLBACK_UNINST_STOP:
203         if (h == NULL || !(flags & INSTALL_LABEL))
204             break;
205         s = headerSprintf(h, "%{NAME}.%{ARCH}", rpmTagTable, rpmHeaderFormats, NULL);
206         if (flags & INSTALL_HASH) {
207             fprintf(stdout, "%4d:%-23.23s", progressCurrent + 1, s);
208             printHash(1, 1);
209         } else {
210             fprintf(stdout, "%-28.28s", s);
211         }
212         fflush(stdout);
213         s = NULL;
214         break;
215     default: // Fall through
216         break;
217     }
218  
219     return rc;
220 }       
221