vendor/debian/makefile: apply 6f3c4e33 for debian/makefile as well
[ntk/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
61f954bf
MV
16
17/* Return a APT::Progress::PackageManager based on the global
18 * apt configuration (i.e. APT::Status-Fd and APT::Status-deb822-Fd)
19 */
bd5f39b3
MV
20PackageManager* PackageManagerProgressFactory()
21{
22 // select the right progress
23 int status_fd = _config->FindI("APT::Status-Fd", -1);
24 int status_deb822_fd = _config->FindI("APT::Status-deb822-Fd", -1);
25
26 APT::Progress::PackageManager *progress = NULL;
27 if (status_deb822_fd > 0)
28 progress = new APT::Progress::PackageManagerProgressDeb822Fd(
29 status_deb822_fd);
30 else if (status_fd > 0)
31 progress = new APT::Progress::PackageManagerProgressFd(status_fd);
32 else if(_config->FindB("Dpkg::Progress-Fancy", false) == true)
33 progress = new APT::Progress::PackageManagerFancy();
34 else if (_config->FindB("Dpkg::Progress",
35 _config->FindB("DpkgPM::Progress", false)) == true)
36 progress = new APT::Progress::PackageManagerText();
37 else
38 progress = new APT::Progress::PackageManager();
39 return progress;
40}
41
6c5ae8ed 42bool PackageManager::StatusChanged(std::string PackageName,
e6ad8031
MV
43 unsigned int StepsDone,
44 unsigned int TotalSteps,
45 std::string HumanReadableAction)
6c5ae8ed
MV
46{
47 int reporting_steps = _config->FindI("DpkgPM::Reporting-Steps", 1);
48 percentage = StepsDone/(float)TotalSteps * 100.0;
49 strprintf(progress_str, _("Progress: [%3i%%]"), (int)percentage);
50
51 if(percentage < (last_reported_progress + reporting_steps))
52 return false;
53
54 return true;
55}
56
e6ad8031 57PackageManagerProgressFd::PackageManagerProgressFd(int progress_fd)
65dbd5a1 58 : StepsDone(0), StepsTotal(1)
e6ad8031
MV
59{
60 OutStatusFd = progress_fd;
61}
62
f9935b1c
MV
63void PackageManagerProgressFd::WriteToStatusFd(std::string s)
64{
65 if(OutStatusFd <= 0)
66 return;
67 FileFd::Write(OutStatusFd, s.c_str(), s.size());
68}
69
e45c4617 70void PackageManagerProgressFd::StartDpkg()
e6ad8031 71{
5e9458e2
MV
72 if(OutStatusFd <= 0)
73 return;
74
75 // FIXME: use SetCloseExec here once it taught about throwing
76 // exceptions instead of doing _exit(100) on failure
77 fcntl(OutStatusFd,F_SETFD,FD_CLOEXEC);
e6ad8031
MV
78
79 // send status information that we are about to fork dpkg
f9935b1c
MV
80 std::ostringstream status;
81 status << "pmstatus:dpkg-exec:"
82 << (StepsDone/float(StepsTotal)*100.0)
83 << ":" << _("Running dpkg")
84 << std::endl;
85 WriteToStatusFd(status.str());
e6ad8031
MV
86}
87
a22fdebf 88void PackageManagerProgressFd::Stop()
e6ad8031 89{
e6ad8031
MV
90}
91
92void PackageManagerProgressFd::Error(std::string PackageName,
93 unsigned int StepsDone,
94 unsigned int TotalSteps,
95 std::string ErrorMessage)
96{
97 std::ostringstream status;
98 status << "pmerror:" << PackageName
99 << ":" << (StepsDone/float(TotalSteps)*100.0)
100 << ":" << ErrorMessage
101 << std::endl;
f9935b1c 102 WriteToStatusFd(status.str());
e6ad8031
MV
103}
104
105void PackageManagerProgressFd::ConffilePrompt(std::string PackageName,
106 unsigned int StepsDone,
107 unsigned int TotalSteps,
108 std::string ConfMessage)
109{
110 std::ostringstream status;
111 status << "pmconffile:" << PackageName
112 << ":" << (StepsDone/float(TotalSteps)*100.0)
113 << ":" << ConfMessage
114 << std::endl;
f9935b1c 115 WriteToStatusFd(status.str());
e6ad8031
MV
116}
117
118
119bool PackageManagerProgressFd::StatusChanged(std::string PackageName,
120 unsigned int xStepsDone,
121 unsigned int xTotalSteps,
122 std::string pkg_action)
123{
124 StepsDone = xStepsDone;
125 StepsTotal = xTotalSteps;
126
127 // build the status str
128 std::ostringstream status;
dd640f3c 129 status << "pmstatus:" << StringSplit(PackageName, ":")[0]
e6ad8031
MV
130 << ":" << (StepsDone/float(StepsTotal)*100.0)
131 << ":" << pkg_action
132 << std::endl;
f9935b1c 133 WriteToStatusFd(status.str());
65dbd5a1
MV
134
135 if(_config->FindB("Debug::APT::Progress::PackageManagerFd", false) == true)
136 std::cerr << "progress: " << PackageName << " " << xStepsDone
137 << " " << xTotalSteps << " " << pkg_action
138 << std::endl;
139
140
e6ad8031
MV
141 return true;
142}
143
c7ea1eba
MV
144
145PackageManagerProgressDeb822Fd::PackageManagerProgressDeb822Fd(int progress_fd)
146 : StepsDone(0), StepsTotal(1)
147{
148 OutStatusFd = progress_fd;
149}
150
151void PackageManagerProgressDeb822Fd::WriteToStatusFd(std::string s)
152{
153 FileFd::Write(OutStatusFd, s.c_str(), s.size());
154}
155
790d41f6 156void PackageManagerProgressDeb822Fd::StartDpkg()
c7ea1eba
MV
157{
158 // FIXME: use SetCloseExec here once it taught about throwing
159 // exceptions instead of doing _exit(100) on failure
160 fcntl(OutStatusFd,F_SETFD,FD_CLOEXEC);
161
162 // send status information that we are about to fork dpkg
163 std::ostringstream status;
164 status << "Status: " << "progress" << std::endl
165 << "Percent: " << (StepsDone/float(StepsTotal)*100.0) << std::endl
166 << "Message: " << _("Running dpkg") << std::endl
167 << std::endl;
168 WriteToStatusFd(status.str());
169}
170
171void PackageManagerProgressDeb822Fd::Stop()
172{
c7ea1eba
MV
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
bc37330b
MV
242 // setup env for (hopefully!) ncurses
243 string s;
244 strprintf(s, "%i", nr_rows);
245 setenv("LINES", s.c_str(), 1);
246
31f97d7b
MV
247 std::flush(std::cout);
248}
249
250PackageManagerFancy::PackageManagerFancy()
251 : nr_terminal_rows(-1)
252{
253 struct winsize win;
254 if(ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&win) == 0)
255 {
256 nr_terminal_rows = win.ws_row;
257 }
258}
259
a22fdebf 260void PackageManagerFancy::Start()
31f97d7b 261{
db78c60c
MV
262 if (nr_terminal_rows > 0)
263 SetupTerminalScrollArea(nr_terminal_rows);
31f97d7b
MV
264}
265
a22fdebf 266void PackageManagerFancy::Stop()
31f97d7b 267{
db78c60c
MV
268 if (nr_terminal_rows > 0)
269 {
270 SetupTerminalScrollArea(nr_terminal_rows + 1);
31f97d7b 271
db78c60c
MV
272 // override the progress line (sledgehammer)
273 static const char* clear_screen_below_cursor = "\033[J";
274 std::cout << clear_screen_below_cursor;
275 }
31f97d7b
MV
276}
277
6c5ae8ed 278bool PackageManagerFancy::StatusChanged(std::string PackageName,
31f97d7b 279 unsigned int StepsDone,
e6ad8031
MV
280 unsigned int TotalSteps,
281 std::string HumanReadableAction)
31f97d7b 282{
e6ad8031
MV
283 if (!PackageManager::StatusChanged(PackageName, StepsDone, TotalSteps,
284 HumanReadableAction))
6c5ae8ed 285 return false;
31f97d7b
MV
286
287 int row = nr_terminal_rows;
288
289 static string save_cursor = "\033[s";
290 static string restore_cursor = "\033[u";
291
292 static string set_bg_color = "\033[42m"; // green
293 static string set_fg_color = "\033[30m"; // black
294
295 static string restore_bg = "\033[49m";
296 static string restore_fg = "\033[39m";
297
298 std::cout << save_cursor
299 // move cursor position to last row
300 << "\033[" << row << ";0f"
301 << set_bg_color
302 << set_fg_color
303 << progress_str
304 << restore_cursor
305 << restore_bg
306 << restore_fg;
307 std::flush(std::cout);
308 last_reported_progress = percentage;
6c5ae8ed
MV
309
310 return true;
31f97d7b
MV
311}
312
6c5ae8ed 313bool PackageManagerText::StatusChanged(std::string PackageName,
31f97d7b 314 unsigned int StepsDone,
e6ad8031
MV
315 unsigned int TotalSteps,
316 std::string HumanReadableAction)
31f97d7b 317{
e6ad8031 318 if (!PackageManager::StatusChanged(PackageName, StepsDone, TotalSteps, HumanReadableAction))
6c5ae8ed 319 return false;
31f97d7b
MV
320
321 std::cout << progress_str << "\r\n";
322 std::flush(std::cout);
323
324 last_reported_progress = percentage;
6c5ae8ed
MV
325
326 return true;
31f97d7b
MV
327}
328
329
c7ea1eba 330
31f97d7b
MV
331}; // namespace progress
332}; // namespace apt