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 bool PackageManager::StatusChanged(std::string PackageName
,
17 unsigned int StepsDone
,
18 unsigned int TotalSteps
,
19 std::string HumanReadableAction
)
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
);
25 if(percentage
< (last_reported_progress
+ reporting_steps
))
31 PackageManagerProgressFd::PackageManagerProgressFd(int progress_fd
)
32 : StepsDone(0), StepsTotal(1)
34 OutStatusFd
= progress_fd
;
37 void PackageManagerProgressFd::WriteToStatusFd(std::string s
)
41 FileFd::Write(OutStatusFd
, s
.c_str(), s
.size());
44 void PackageManagerProgressFd::Start()
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
);
53 // send status information that we are about to fork dpkg
54 std::ostringstream status
;
55 status
<< "pmstatus:dpkg-exec:"
56 << (StepsDone
/float(StepsTotal
)*100.0)
57 << ":" << _("Running dpkg")
59 WriteToStatusFd(status
.str());
62 void PackageManagerProgressFd::Stop()
64 // clear the Keep-Fd again
65 _config
->Clear("APT::Keep-Fds", OutStatusFd
);
68 void PackageManagerProgressFd::Error(std::string PackageName
,
69 unsigned int StepsDone
,
70 unsigned int TotalSteps
,
71 std::string ErrorMessage
)
73 std::ostringstream status
;
74 status
<< "pmerror:" << PackageName
75 << ":" << (StepsDone
/float(TotalSteps
)*100.0)
76 << ":" << ErrorMessage
78 WriteToStatusFd(status
.str());
81 void PackageManagerProgressFd::ConffilePrompt(std::string PackageName
,
82 unsigned int StepsDone
,
83 unsigned int TotalSteps
,
84 std::string ConfMessage
)
86 std::ostringstream status
;
87 status
<< "pmconffile:" << PackageName
88 << ":" << (StepsDone
/float(TotalSteps
)*100.0)
91 WriteToStatusFd(status
.str());
95 bool PackageManagerProgressFd::StatusChanged(std::string PackageName
,
96 unsigned int xStepsDone
,
97 unsigned int xTotalSteps
,
98 std::string pkg_action
)
100 StepsDone
= xStepsDone
;
101 StepsTotal
= xTotalSteps
;
103 // build the status str
104 std::ostringstream status
;
105 status
<< "pmstatus:" << StringSplit(PackageName
, ":")[0]
106 << ":" << (StepsDone
/float(StepsTotal
)*100.0)
109 WriteToStatusFd(status
.str());
111 if(_config
->FindB("Debug::APT::Progress::PackageManagerFd", false) == true)
112 std::cerr
<< "progress: " << PackageName
<< " " << xStepsDone
113 << " " << xTotalSteps
<< " " << pkg_action
121 PackageManagerProgressDeb822Fd::PackageManagerProgressDeb822Fd(int progress_fd
)
122 : StepsDone(0), StepsTotal(1)
124 OutStatusFd
= progress_fd
;
127 void PackageManagerProgressDeb822Fd::WriteToStatusFd(std::string s
)
129 FileFd::Write(OutStatusFd
, s
.c_str(), s
.size());
132 void PackageManagerProgressDeb822Fd::Start()
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
);
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
144 WriteToStatusFd(status
.str());
147 void PackageManagerProgressDeb822Fd::Stop()
149 // clear the Keep-Fd again
150 _config
->Clear("APT::Keep-Fds", OutStatusFd
);
153 void PackageManagerProgressDeb822Fd::Error(std::string PackageName
,
154 unsigned int StepsDone
,
155 unsigned int TotalSteps
,
156 std::string ErrorMessage
)
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
164 WriteToStatusFd(status
.str());
167 void PackageManagerProgressDeb822Fd::ConffilePrompt(std::string PackageName
,
168 unsigned int StepsDone
,
169 unsigned int TotalSteps
,
170 std::string ConfMessage
)
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
178 WriteToStatusFd(status
.str());
182 bool PackageManagerProgressDeb822Fd::StatusChanged(std::string PackageName
,
183 unsigned int xStepsDone
,
184 unsigned int xTotalSteps
,
187 StepsDone
= xStepsDone
;
188 StepsTotal
= xTotalSteps
;
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
197 WriteToStatusFd(status
.str());
203 void PackageManagerFancy::SetupTerminalScrollArea(int nr_rows
)
205 // scroll down a bit to avoid visual glitch when the screen
206 // area shrinks by one row
210 std::cout
<< "\033[s";
212 // set scroll region (this will place the cursor in the top left)
213 std::cout
<< "\033[1;" << nr_rows
- 1 << "r";
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
;
220 std::flush(std::cout
);
223 PackageManagerFancy::PackageManagerFancy()
224 : nr_terminal_rows(-1)
227 if(ioctl(STDOUT_FILENO
, TIOCGWINSZ
, (char *)&win
) == 0)
229 nr_terminal_rows
= win
.ws_row
;
233 void PackageManagerFancy::Start()
235 if (nr_terminal_rows
> 0)
236 SetupTerminalScrollArea(nr_terminal_rows
);
239 void PackageManagerFancy::Stop()
241 if (nr_terminal_rows
> 0)
243 SetupTerminalScrollArea(nr_terminal_rows
+ 1);
245 // override the progress line (sledgehammer)
246 static const char* clear_screen_below_cursor
= "\033[J";
247 std::cout
<< clear_screen_below_cursor
;
251 bool PackageManagerFancy::StatusChanged(std::string PackageName
,
252 unsigned int StepsDone
,
253 unsigned int TotalSteps
,
254 std::string HumanReadableAction
)
256 if (!PackageManager::StatusChanged(PackageName
, StepsDone
, TotalSteps
,
257 HumanReadableAction
))
260 int row
= nr_terminal_rows
;
262 static string save_cursor
= "\033[s";
263 static string restore_cursor
= "\033[u";
265 static string set_bg_color
= "\033[42m"; // green
266 static string set_fg_color
= "\033[30m"; // black
268 static string restore_bg
= "\033[49m";
269 static string restore_fg
= "\033[39m";
271 std::cout
<< save_cursor
272 // move cursor position to last row
273 << "\033[" << row
<< ";0f"
280 std::flush(std::cout
);
281 last_reported_progress
= percentage
;
286 bool PackageManagerText::StatusChanged(std::string PackageName
,
287 unsigned int StepsDone
,
288 unsigned int TotalSteps
,
289 std::string HumanReadableAction
)
291 if (!PackageManager::StatusChanged(PackageName
, StepsDone
, TotalSteps
, HumanReadableAction
))
294 std::cout
<< progress_str
<< "\r\n";
295 std::flush(std::cout
);
297 last_reported_progress
= percentage
;
304 }; // namespace progress