releasing package apt version 0.9.13~exp1
[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
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
e45c4617 66void PackageManagerProgressFd::StartDpkg()
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 85{
e6ad8031
MV
86}
87
88void PackageManagerProgressFd::Error(std::string PackageName,
89 unsigned int StepsDone,
90 unsigned int TotalSteps,
91 std::string ErrorMessage)
92{
93 std::ostringstream status;
94 status << "pmerror:" << PackageName
95 << ":" << (StepsDone/float(TotalSteps)*100.0)
96 << ":" << ErrorMessage
97 << std::endl;
f9935b1c 98 WriteToStatusFd(status.str());
e6ad8031
MV
99}
100
101void PackageManagerProgressFd::ConffilePrompt(std::string PackageName,
102 unsigned int StepsDone,
103 unsigned int TotalSteps,
104 std::string ConfMessage)
105{
106 std::ostringstream status;
107 status << "pmconffile:" << PackageName
108 << ":" << (StepsDone/float(TotalSteps)*100.0)
109 << ":" << ConfMessage
110 << std::endl;
f9935b1c 111 WriteToStatusFd(status.str());
e6ad8031
MV
112}
113
114
115bool PackageManagerProgressFd::StatusChanged(std::string PackageName,
116 unsigned int xStepsDone,
117 unsigned int xTotalSteps,
118 std::string pkg_action)
119{
120 StepsDone = xStepsDone;
121 StepsTotal = xTotalSteps;
122
123 // build the status str
124 std::ostringstream status;
dd640f3c 125 status << "pmstatus:" << StringSplit(PackageName, ":")[0]
e6ad8031
MV
126 << ":" << (StepsDone/float(StepsTotal)*100.0)
127 << ":" << pkg_action
128 << std::endl;
f9935b1c 129 WriteToStatusFd(status.str());
65dbd5a1
MV
130
131 if(_config->FindB("Debug::APT::Progress::PackageManagerFd", false) == true)
132 std::cerr << "progress: " << PackageName << " " << xStepsDone
133 << " " << xTotalSteps << " " << pkg_action
134 << std::endl;
135
136
e6ad8031
MV
137 return true;
138}
139
c7ea1eba
MV
140
141PackageManagerProgressDeb822Fd::PackageManagerProgressDeb822Fd(int progress_fd)
142 : StepsDone(0), StepsTotal(1)
143{
144 OutStatusFd = progress_fd;
145}
146
147void PackageManagerProgressDeb822Fd::WriteToStatusFd(std::string s)
148{
149 FileFd::Write(OutStatusFd, s.c_str(), s.size());
150}
151
790d41f6 152void PackageManagerProgressDeb822Fd::StartDpkg()
c7ea1eba
MV
153{
154 // FIXME: use SetCloseExec here once it taught about throwing
155 // exceptions instead of doing _exit(100) on failure
156 fcntl(OutStatusFd,F_SETFD,FD_CLOEXEC);
157
158 // send status information that we are about to fork dpkg
159 std::ostringstream status;
160 status << "Status: " << "progress" << std::endl
161 << "Percent: " << (StepsDone/float(StepsTotal)*100.0) << std::endl
162 << "Message: " << _("Running dpkg") << std::endl
163 << std::endl;
164 WriteToStatusFd(status.str());
165}
166
167void PackageManagerProgressDeb822Fd::Stop()
168{
c7ea1eba
MV
169}
170
171void PackageManagerProgressDeb822Fd::Error(std::string PackageName,
172 unsigned int StepsDone,
173 unsigned int TotalSteps,
174 std::string ErrorMessage)
175{
176 std::ostringstream status;
177 status << "Status: " << "Error" << std::endl
178 << "Package:" << PackageName << std::endl
179 << "Percent: " << (StepsDone/float(TotalSteps)*100.0) << std::endl
180 << "Message: " << ErrorMessage << std::endl
181 << std::endl;
182 WriteToStatusFd(status.str());
183}
184
185void PackageManagerProgressDeb822Fd::ConffilePrompt(std::string PackageName,
186 unsigned int StepsDone,
187 unsigned int TotalSteps,
188 std::string ConfMessage)
189{
190 std::ostringstream status;
191 status << "Status: " << "ConfFile" << std::endl
192 << "Package:" << PackageName << std::endl
193 << "Percent: " << (StepsDone/float(TotalSteps)*100.0) << std::endl
194 << "Message: " << ConfMessage << std::endl
195 << std::endl;
196 WriteToStatusFd(status.str());
197}
198
199
200bool PackageManagerProgressDeb822Fd::StatusChanged(std::string PackageName,
201 unsigned int xStepsDone,
202 unsigned int xTotalSteps,
203 std::string message)
204{
205 StepsDone = xStepsDone;
206 StepsTotal = xTotalSteps;
207
208 // build the status str
209 std::ostringstream status;
210 status << "Status: " << "progress" << std::endl
211 << "Package: " << PackageName << std::endl
212 << "Percent: " << (StepsDone/float(StepsTotal)*100.0) << std::endl
213 << "Message: " << message << std::endl
214 << std::endl;
215 WriteToStatusFd(status.str());
216
217 return true;
218}
219
220
db78c60c 221void PackageManagerFancy::SetupTerminalScrollArea(int nr_rows)
31f97d7b
MV
222{
223 // scroll down a bit to avoid visual glitch when the screen
224 // area shrinks by one row
225 std::cout << "\n";
226
227 // save cursor
228 std::cout << "\033[s";
229
230 // set scroll region (this will place the cursor in the top left)
231 std::cout << "\033[1;" << nr_rows - 1 << "r";
232
233 // restore cursor but ensure its inside the scrolling area
234 std::cout << "\033[u";
235 static const char *move_cursor_up = "\033[1A";
236 std::cout << move_cursor_up;
db78c60c 237
bc37330b
MV
238 // setup env for (hopefully!) ncurses
239 string s;
240 strprintf(s, "%i", nr_rows);
241 setenv("LINES", s.c_str(), 1);
242
31f97d7b
MV
243 std::flush(std::cout);
244}
245
246PackageManagerFancy::PackageManagerFancy()
247 : nr_terminal_rows(-1)
248{
249 struct winsize win;
250 if(ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&win) == 0)
251 {
252 nr_terminal_rows = win.ws_row;
253 }
254}
255
a22fdebf 256void PackageManagerFancy::Start()
31f97d7b 257{
db78c60c
MV
258 if (nr_terminal_rows > 0)
259 SetupTerminalScrollArea(nr_terminal_rows);
31f97d7b
MV
260}
261
a22fdebf 262void PackageManagerFancy::Stop()
31f97d7b 263{
db78c60c
MV
264 if (nr_terminal_rows > 0)
265 {
266 SetupTerminalScrollArea(nr_terminal_rows + 1);
31f97d7b 267
db78c60c
MV
268 // override the progress line (sledgehammer)
269 static const char* clear_screen_below_cursor = "\033[J";
270 std::cout << clear_screen_below_cursor;
271 }
31f97d7b
MV
272}
273
6c5ae8ed 274bool PackageManagerFancy::StatusChanged(std::string PackageName,
31f97d7b 275 unsigned int StepsDone,
e6ad8031
MV
276 unsigned int TotalSteps,
277 std::string HumanReadableAction)
31f97d7b 278{
e6ad8031
MV
279 if (!PackageManager::StatusChanged(PackageName, StepsDone, TotalSteps,
280 HumanReadableAction))
6c5ae8ed 281 return false;
31f97d7b
MV
282
283 int row = nr_terminal_rows;
284
285 static string save_cursor = "\033[s";
286 static string restore_cursor = "\033[u";
287
288 static string set_bg_color = "\033[42m"; // green
289 static string set_fg_color = "\033[30m"; // black
290
291 static string restore_bg = "\033[49m";
292 static string restore_fg = "\033[39m";
293
294 std::cout << save_cursor
295 // move cursor position to last row
296 << "\033[" << row << ";0f"
297 << set_bg_color
298 << set_fg_color
299 << progress_str
300 << restore_cursor
301 << restore_bg
302 << restore_fg;
303 std::flush(std::cout);
304 last_reported_progress = percentage;
6c5ae8ed
MV
305
306 return true;
31f97d7b
MV
307}
308
6c5ae8ed 309bool PackageManagerText::StatusChanged(std::string PackageName,
31f97d7b 310 unsigned int StepsDone,
e6ad8031
MV
311 unsigned int TotalSteps,
312 std::string HumanReadableAction)
31f97d7b 313{
e6ad8031 314 if (!PackageManager::StatusChanged(PackageName, StepsDone, TotalSteps, HumanReadableAction))
6c5ae8ed 315 return false;
31f97d7b
MV
316
317 std::cout << progress_str << "\r\n";
318 std::flush(std::cout);
319
320 last_reported_progress = percentage;
6c5ae8ed
MV
321
322 return true;
31f97d7b
MV
323}
324
325
c7ea1eba 326
31f97d7b
MV
327}; // namespace progress
328}; // namespace apt