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