]> git.saurik.com Git - apt.git/blame - apt-pkg/install-progress.cc
restore ABI and prepare next ABI via #if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
[apt.git] / apt-pkg / install-progress.cc
CommitLineData
e6ad8031
MV
1#include <apt-pkg/configuration.h>
2#include <apt-pkg/fileutl.h>
31f97d7b 3#include <apt-pkg/strutl.h>
af36becc 4#include <apt-pkg/install-progress.h>
c7ea1eba 5
6c5ae8ed 6#include <apti18n.h>
31f97d7b
MV
7
8#include <termios.h>
9#include <sys/ioctl.h>
e6ad8031 10#include <sstream>
5e9458e2 11#include <fcntl.h>
31f97d7b
MV
12
13namespace APT {
14namespace Progress {
15
bd5f39b3
MV
16PackageManager* PackageManagerProgressFactory()
17{
18 // select the right progress
19 int status_fd = _config->FindI("APT::Status-Fd", -1);
20 int status_deb822_fd = _config->FindI("APT::Status-deb822-Fd", -1);
21
22 APT::Progress::PackageManager *progress = NULL;
23 if (status_deb822_fd > 0)
24 progress = new APT::Progress::PackageManagerProgressDeb822Fd(
25 status_deb822_fd);
26 else if (status_fd > 0)
27 progress = new APT::Progress::PackageManagerProgressFd(status_fd);
28 else if(_config->FindB("Dpkg::Progress-Fancy", false) == true)
29 progress = new APT::Progress::PackageManagerFancy();
30 else if (_config->FindB("Dpkg::Progress",
31 _config->FindB("DpkgPM::Progress", false)) == true)
32 progress = new APT::Progress::PackageManagerText();
33 else
34 progress = new APT::Progress::PackageManager();
35 return progress;
36}
37
6c5ae8ed 38bool PackageManager::StatusChanged(std::string PackageName,
e6ad8031
MV
39 unsigned int StepsDone,
40 unsigned int TotalSteps,
41 std::string HumanReadableAction)
6c5ae8ed
MV
42{
43 int reporting_steps = _config->FindI("DpkgPM::Reporting-Steps", 1);
44 percentage = StepsDone/(float)TotalSteps * 100.0;
45 strprintf(progress_str, _("Progress: [%3i%%]"), (int)percentage);
46
47 if(percentage < (last_reported_progress + reporting_steps))
48 return false;
49
50 return true;
51}
52
e6ad8031 53PackageManagerProgressFd::PackageManagerProgressFd(int progress_fd)
65dbd5a1 54 : StepsDone(0), StepsTotal(1)
e6ad8031
MV
55{
56 OutStatusFd = progress_fd;
57}
58
f9935b1c
MV
59void PackageManagerProgressFd::WriteToStatusFd(std::string s)
60{
61 if(OutStatusFd <= 0)
62 return;
63 FileFd::Write(OutStatusFd, s.c_str(), s.size());
64}
65
a22fdebf 66void PackageManagerProgressFd::Start()
e6ad8031 67{
5e9458e2
MV
68 if(OutStatusFd <= 0)
69 return;
70
71 // FIXME: use SetCloseExec here once it taught about throwing
72 // exceptions instead of doing _exit(100) on failure
73 fcntl(OutStatusFd,F_SETFD,FD_CLOEXEC);
e6ad8031
MV
74
75 // send status information that we are about to fork dpkg
f9935b1c
MV
76 std::ostringstream status;
77 status << "pmstatus:dpkg-exec:"
78 << (StepsDone/float(StepsTotal)*100.0)
79 << ":" << _("Running dpkg")
80 << std::endl;
81 WriteToStatusFd(status.str());
e6ad8031
MV
82}
83
a22fdebf 84void PackageManagerProgressFd::Stop()
e6ad8031
MV
85{
86 // clear the Keep-Fd again
87 _config->Clear("APT::Keep-Fds", OutStatusFd);
88}
89
90void PackageManagerProgressFd::Error(std::string PackageName,
91 unsigned int StepsDone,
92 unsigned int TotalSteps,
93 std::string ErrorMessage)
94{
95 std::ostringstream status;
96 status << "pmerror:" << PackageName
97 << ":" << (StepsDone/float(TotalSteps)*100.0)
98 << ":" << ErrorMessage
99 << std::endl;
f9935b1c 100 WriteToStatusFd(status.str());
e6ad8031
MV
101}
102
103void PackageManagerProgressFd::ConffilePrompt(std::string PackageName,
104 unsigned int StepsDone,
105 unsigned int TotalSteps,
106 std::string ConfMessage)
107{
108 std::ostringstream status;
109 status << "pmconffile:" << PackageName
110 << ":" << (StepsDone/float(TotalSteps)*100.0)
111 << ":" << ConfMessage
112 << std::endl;
f9935b1c 113 WriteToStatusFd(status.str());
e6ad8031
MV
114}
115
116
117bool PackageManagerProgressFd::StatusChanged(std::string PackageName,
118 unsigned int xStepsDone,
119 unsigned int xTotalSteps,
120 std::string pkg_action)
121{
122 StepsDone = xStepsDone;
123 StepsTotal = xTotalSteps;
124
125 // build the status str
126 std::ostringstream status;
dd640f3c 127 status << "pmstatus:" << StringSplit(PackageName, ":")[0]
e6ad8031
MV
128 << ":" << (StepsDone/float(StepsTotal)*100.0)
129 << ":" << pkg_action
130 << std::endl;
f9935b1c 131 WriteToStatusFd(status.str());
65dbd5a1
MV
132
133 if(_config->FindB("Debug::APT::Progress::PackageManagerFd", false) == true)
134 std::cerr << "progress: " << PackageName << " " << xStepsDone
135 << " " << xTotalSteps << " " << pkg_action
136 << std::endl;
137
138
e6ad8031
MV
139 return true;
140}
141
c7ea1eba
MV
142
143PackageManagerProgressDeb822Fd::PackageManagerProgressDeb822Fd(int progress_fd)
144 : StepsDone(0), StepsTotal(1)
145{
146 OutStatusFd = progress_fd;
147}
148
149void PackageManagerProgressDeb822Fd::WriteToStatusFd(std::string s)
150{
151 FileFd::Write(OutStatusFd, s.c_str(), s.size());
152}
153
154void PackageManagerProgressDeb822Fd::Start()
155{
156 // FIXME: use SetCloseExec here once it taught about throwing
157 // exceptions instead of doing _exit(100) on failure
158 fcntl(OutStatusFd,F_SETFD,FD_CLOEXEC);
159
160 // send status information that we are about to fork dpkg
161 std::ostringstream status;
162 status << "Status: " << "progress" << std::endl
163 << "Percent: " << (StepsDone/float(StepsTotal)*100.0) << std::endl
164 << "Message: " << _("Running dpkg") << std::endl
165 << std::endl;
166 WriteToStatusFd(status.str());
167}
168
169void PackageManagerProgressDeb822Fd::Stop()
170{
171 // clear the Keep-Fd again
172 _config->Clear("APT::Keep-Fds", OutStatusFd);
173}
174
175void PackageManagerProgressDeb822Fd::Error(std::string PackageName,
176 unsigned int StepsDone,
177 unsigned int TotalSteps,
178 std::string ErrorMessage)
179{
180 std::ostringstream status;
181 status << "Status: " << "Error" << std::endl
182 << "Package:" << PackageName << std::endl
183 << "Percent: " << (StepsDone/float(TotalSteps)*100.0) << std::endl
184 << "Message: " << ErrorMessage << std::endl
185 << std::endl;
186 WriteToStatusFd(status.str());
187}
188
189void PackageManagerProgressDeb822Fd::ConffilePrompt(std::string PackageName,
190 unsigned int StepsDone,
191 unsigned int TotalSteps,
192 std::string ConfMessage)
193{
194 std::ostringstream status;
195 status << "Status: " << "ConfFile" << std::endl
196 << "Package:" << PackageName << std::endl
197 << "Percent: " << (StepsDone/float(TotalSteps)*100.0) << std::endl
198 << "Message: " << ConfMessage << std::endl
199 << std::endl;
200 WriteToStatusFd(status.str());
201}
202
203
204bool PackageManagerProgressDeb822Fd::StatusChanged(std::string PackageName,
205 unsigned int xStepsDone,
206 unsigned int xTotalSteps,
207 std::string message)
208{
209 StepsDone = xStepsDone;
210 StepsTotal = xTotalSteps;
211
212 // build the status str
213 std::ostringstream status;
214 status << "Status: " << "progress" << std::endl
215 << "Package: " << PackageName << std::endl
216 << "Percent: " << (StepsDone/float(StepsTotal)*100.0) << std::endl
217 << "Message: " << message << std::endl
218 << std::endl;
219 WriteToStatusFd(status.str());
220
221 return true;
222}
223
224
db78c60c 225void PackageManagerFancy::SetupTerminalScrollArea(int nr_rows)
31f97d7b
MV
226{
227 // scroll down a bit to avoid visual glitch when the screen
228 // area shrinks by one row
229 std::cout << "\n";
230
231 // save cursor
232 std::cout << "\033[s";
233
234 // set scroll region (this will place the cursor in the top left)
235 std::cout << "\033[1;" << nr_rows - 1 << "r";
236
237 // restore cursor but ensure its inside the scrolling area
238 std::cout << "\033[u";
239 static const char *move_cursor_up = "\033[1A";
240 std::cout << move_cursor_up;
db78c60c 241
31f97d7b
MV
242 std::flush(std::cout);
243}
244
245PackageManagerFancy::PackageManagerFancy()
246 : nr_terminal_rows(-1)
247{
248 struct winsize win;
249 if(ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&win) == 0)
250 {
251 nr_terminal_rows = win.ws_row;
252 }
253}
254
a22fdebf 255void PackageManagerFancy::Start()
31f97d7b 256{
db78c60c
MV
257 if (nr_terminal_rows > 0)
258 SetupTerminalScrollArea(nr_terminal_rows);
31f97d7b
MV
259}
260
a22fdebf 261void PackageManagerFancy::Stop()
31f97d7b 262{
db78c60c
MV
263 if (nr_terminal_rows > 0)
264 {
265 SetupTerminalScrollArea(nr_terminal_rows + 1);
31f97d7b 266
db78c60c
MV
267 // override the progress line (sledgehammer)
268 static const char* clear_screen_below_cursor = "\033[J";
269 std::cout << clear_screen_below_cursor;
270 }
31f97d7b
MV
271}
272
6c5ae8ed 273bool PackageManagerFancy::StatusChanged(std::string PackageName,
31f97d7b 274 unsigned int StepsDone,
e6ad8031
MV
275 unsigned int TotalSteps,
276 std::string HumanReadableAction)
31f97d7b 277{
e6ad8031
MV
278 if (!PackageManager::StatusChanged(PackageName, StepsDone, TotalSteps,
279 HumanReadableAction))
6c5ae8ed 280 return false;
31f97d7b
MV
281
282 int row = nr_terminal_rows;
283
284 static string save_cursor = "\033[s";
285 static string restore_cursor = "\033[u";
286
287 static string set_bg_color = "\033[42m"; // green
288 static string set_fg_color = "\033[30m"; // black
289
290 static string restore_bg = "\033[49m";
291 static string restore_fg = "\033[39m";
292
293 std::cout << save_cursor
294 // move cursor position to last row
295 << "\033[" << row << ";0f"
296 << set_bg_color
297 << set_fg_color
298 << progress_str
299 << restore_cursor
300 << restore_bg
301 << restore_fg;
302 std::flush(std::cout);
303 last_reported_progress = percentage;
6c5ae8ed
MV
304
305 return true;
31f97d7b
MV
306}
307
6c5ae8ed 308bool PackageManagerText::StatusChanged(std::string PackageName,
31f97d7b 309 unsigned int StepsDone,
e6ad8031
MV
310 unsigned int TotalSteps,
311 std::string HumanReadableAction)
31f97d7b 312{
e6ad8031 313 if (!PackageManager::StatusChanged(PackageName, StepsDone, TotalSteps, HumanReadableAction))
6c5ae8ed 314 return false;
31f97d7b
MV
315
316 std::cout << progress_str << "\r\n";
317 std::flush(std::cout);
318
319 last_reported_progress = percentage;
6c5ae8ed
MV
320
321 return true;
31f97d7b
MV
322}
323
324
c7ea1eba 325
31f97d7b
MV
326}; // namespace progress
327}; // namespace apt