1 #include <apt-pkg/configuration.h>
2 #include <apt-pkg/fileutl.h>
3 #include <apt-pkg/strutl.h>
4 #include <apt-pkg/install-progress.h>
16 PackageManager
* PackageManagerProgressFactory()
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);
22 APT::Progress::PackageManager
*progress
= NULL
;
23 if (status_deb822_fd
> 0)
24 progress
= new APT::Progress::PackageManagerProgressDeb822Fd(
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();
34 progress
= new APT::Progress::PackageManager();
38 bool PackageManager::StatusChanged(std::string PackageName
,
39 unsigned int StepsDone
,
40 unsigned int TotalSteps
,
41 std::string HumanReadableAction
)
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
);
47 if(percentage
< (last_reported_progress
+ reporting_steps
))
53 PackageManagerProgressFd::PackageManagerProgressFd(int progress_fd
)
54 : StepsDone(0), StepsTotal(1)
56 OutStatusFd
= progress_fd
;
59 void PackageManagerProgressFd::WriteToStatusFd(std::string s
)
63 FileFd::Write(OutStatusFd
, s
.c_str(), s
.size());
66 void PackageManagerProgressFd::StartDpkg()
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
);
75 // send status information that we are about to fork dpkg
76 std::ostringstream status
;
77 status
<< "pmstatus:dpkg-exec:"
78 << (StepsDone
/float(StepsTotal
)*100.0)
79 << ":" << _("Running dpkg")
81 WriteToStatusFd(status
.str());
84 void PackageManagerProgressFd::Stop()
88 void PackageManagerProgressFd::Error(std::string PackageName
,
89 unsigned int StepsDone
,
90 unsigned int TotalSteps
,
91 std::string ErrorMessage
)
93 std::ostringstream status
;
94 status
<< "pmerror:" << PackageName
95 << ":" << (StepsDone
/float(TotalSteps
)*100.0)
96 << ":" << ErrorMessage
98 WriteToStatusFd(status
.str());
101 void PackageManagerProgressFd::ConffilePrompt(std::string PackageName
,
102 unsigned int StepsDone
,
103 unsigned int TotalSteps
,
104 std::string ConfMessage
)
106 std::ostringstream status
;
107 status
<< "pmconffile:" << PackageName
108 << ":" << (StepsDone
/float(TotalSteps
)*100.0)
109 << ":" << ConfMessage
111 WriteToStatusFd(status
.str());
115 bool PackageManagerProgressFd::StatusChanged(std::string PackageName
,
116 unsigned int xStepsDone
,
117 unsigned int xTotalSteps
,
118 std::string pkg_action
)
120 StepsDone
= xStepsDone
;
121 StepsTotal
= xTotalSteps
;
123 // build the status str
124 std::ostringstream status
;
125 status
<< "pmstatus:" << StringSplit(PackageName
, ":")[0]
126 << ":" << (StepsDone
/float(StepsTotal
)*100.0)
129 WriteToStatusFd(status
.str());
131 if(_config
->FindB("Debug::APT::Progress::PackageManagerFd", false) == true)
132 std::cerr
<< "progress: " << PackageName
<< " " << xStepsDone
133 << " " << xTotalSteps
<< " " << pkg_action
141 PackageManagerProgressDeb822Fd::PackageManagerProgressDeb822Fd(int progress_fd
)
142 : StepsDone(0), StepsTotal(1)
144 OutStatusFd
= progress_fd
;
147 void PackageManagerProgressDeb822Fd::WriteToStatusFd(std::string s
)
149 FileFd::Write(OutStatusFd
, s
.c_str(), s
.size());
152 void PackageManagerProgressDeb822Fd::Start()
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
);
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
164 WriteToStatusFd(status
.str());
167 void PackageManagerProgressDeb822Fd::Stop()
171 void PackageManagerProgressDeb822Fd::Error(std::string PackageName
,
172 unsigned int StepsDone
,
173 unsigned int TotalSteps
,
174 std::string ErrorMessage
)
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
182 WriteToStatusFd(status
.str());
185 void PackageManagerProgressDeb822Fd::ConffilePrompt(std::string PackageName
,
186 unsigned int StepsDone
,
187 unsigned int TotalSteps
,
188 std::string ConfMessage
)
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
196 WriteToStatusFd(status
.str());
200 bool PackageManagerProgressDeb822Fd::StatusChanged(std::string PackageName
,
201 unsigned int xStepsDone
,
202 unsigned int xTotalSteps
,
205 StepsDone
= xStepsDone
;
206 StepsTotal
= xTotalSteps
;
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
215 WriteToStatusFd(status
.str());
221 void PackageManagerFancy::SetupTerminalScrollArea(int nr_rows
)
223 // scroll down a bit to avoid visual glitch when the screen
224 // area shrinks by one row
228 std::cout
<< "\033[s";
230 // set scroll region (this will place the cursor in the top left)
231 std::cout
<< "\033[1;" << nr_rows
- 1 << "r";
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
;
238 std::flush(std::cout
);
241 PackageManagerFancy::PackageManagerFancy()
242 : nr_terminal_rows(-1)
245 if(ioctl(STDOUT_FILENO
, TIOCGWINSZ
, (char *)&win
) == 0)
247 nr_terminal_rows
= win
.ws_row
;
251 void PackageManagerFancy::Start()
253 if (nr_terminal_rows
> 0)
254 SetupTerminalScrollArea(nr_terminal_rows
);
257 void PackageManagerFancy::Stop()
259 if (nr_terminal_rows
> 0)
261 SetupTerminalScrollArea(nr_terminal_rows
+ 1);
263 // override the progress line (sledgehammer)
264 static const char* clear_screen_below_cursor
= "\033[J";
265 std::cout
<< clear_screen_below_cursor
;
269 bool PackageManagerFancy::StatusChanged(std::string PackageName
,
270 unsigned int StepsDone
,
271 unsigned int TotalSteps
,
272 std::string HumanReadableAction
)
274 if (!PackageManager::StatusChanged(PackageName
, StepsDone
, TotalSteps
,
275 HumanReadableAction
))
278 int row
= nr_terminal_rows
;
280 static string save_cursor
= "\033[s";
281 static string restore_cursor
= "\033[u";
283 static string set_bg_color
= "\033[42m"; // green
284 static string set_fg_color
= "\033[30m"; // black
286 static string restore_bg
= "\033[49m";
287 static string restore_fg
= "\033[39m";
289 std::cout
<< save_cursor
290 // move cursor position to last row
291 << "\033[" << row
<< ";0f"
298 std::flush(std::cout
);
299 last_reported_progress
= percentage
;
304 bool PackageManagerText::StatusChanged(std::string PackageName
,
305 unsigned int StepsDone
,
306 unsigned int TotalSteps
,
307 std::string HumanReadableAction
)
309 if (!PackageManager::StatusChanged(PackageName
, StepsDone
, TotalSteps
, HumanReadableAction
))
312 std::cout
<< progress_str
<< "\r\n";
313 std::flush(std::cout
);
315 last_reported_progress
= percentage
;
322 }; // namespace progress