1 #include <apt-pkg/configuration.h>
2 #include <apt-pkg/fileutl.h>
3 #include <apt-pkg/strutl.h>
5 #include <apt-private/private-progress.h>
10 #include <sys/ioctl.h>
17 bool PackageManager::StatusChanged(std::string PackageName
,
18 unsigned int StepsDone
,
19 unsigned int TotalSteps
,
20 std::string HumanReadableAction
)
22 int reporting_steps
= _config
->FindI("DpkgPM::Reporting-Steps", 1);
23 percentage
= StepsDone
/(float)TotalSteps
* 100.0;
24 strprintf(progress_str
, _("Progress: [%3i%%]"), (int)percentage
);
26 if(percentage
< (last_reported_progress
+ reporting_steps
))
32 PackageManagerProgressFd::PackageManagerProgressFd(int progress_fd
)
33 : StepsDone(0), StepsTotal(1)
35 OutStatusFd
= progress_fd
;
38 void PackageManagerProgressFd::WriteToStatusFd(std::string s
)
42 FileFd::Write(OutStatusFd
, s
.c_str(), s
.size());
45 void PackageManagerProgressFd::Start()
50 // FIXME: use SetCloseExec here once it taught about throwing
51 // exceptions instead of doing _exit(100) on failure
52 fcntl(OutStatusFd
,F_SETFD
,FD_CLOEXEC
);
54 // send status information that we are about to fork dpkg
55 std::ostringstream status
;
56 status
<< "pmstatus:dpkg-exec:"
57 << (StepsDone
/float(StepsTotal
)*100.0)
58 << ":" << _("Running dpkg")
60 WriteToStatusFd(status
.str());
63 void PackageManagerProgressFd::Stop()
65 // clear the Keep-Fd again
66 _config
->Clear("APT::Keep-Fds", OutStatusFd
);
69 void PackageManagerProgressFd::Error(std::string PackageName
,
70 unsigned int StepsDone
,
71 unsigned int TotalSteps
,
72 std::string ErrorMessage
)
74 std::ostringstream status
;
75 status
<< "pmerror:" << PackageName
76 << ":" << (StepsDone
/float(TotalSteps
)*100.0)
77 << ":" << ErrorMessage
79 WriteToStatusFd(status
.str());
82 void PackageManagerProgressFd::ConffilePrompt(std::string PackageName
,
83 unsigned int StepsDone
,
84 unsigned int TotalSteps
,
85 std::string ConfMessage
)
87 std::ostringstream status
;
88 status
<< "pmconffile:" << PackageName
89 << ":" << (StepsDone
/float(TotalSteps
)*100.0)
92 WriteToStatusFd(status
.str());
96 bool PackageManagerProgressFd::StatusChanged(std::string PackageName
,
97 unsigned int xStepsDone
,
98 unsigned int xTotalSteps
,
99 std::string pkg_action
)
101 StepsDone
= xStepsDone
;
102 StepsTotal
= xTotalSteps
;
104 // build the status str
105 std::ostringstream status
;
106 status
<< "pmstatus:" << StringSplit(PackageName
, ":")[0]
107 << ":" << (StepsDone
/float(StepsTotal
)*100.0)
110 WriteToStatusFd(status
.str());
112 if(_config
->FindB("Debug::APT::Progress::PackageManagerFd", false) == true)
113 std::cerr
<< "progress: " << PackageName
<< " " << xStepsDone
114 << " " << xTotalSteps
<< " " << pkg_action
122 PackageManagerProgressDeb822Fd::PackageManagerProgressDeb822Fd(int progress_fd
)
123 : StepsDone(0), StepsTotal(1)
125 OutStatusFd
= progress_fd
;
128 void PackageManagerProgressDeb822Fd::WriteToStatusFd(std::string s
)
130 FileFd::Write(OutStatusFd
, s
.c_str(), s
.size());
133 void PackageManagerProgressDeb822Fd::Start()
135 // FIXME: use SetCloseExec here once it taught about throwing
136 // exceptions instead of doing _exit(100) on failure
137 fcntl(OutStatusFd
,F_SETFD
,FD_CLOEXEC
);
139 // send status information that we are about to fork dpkg
140 std::ostringstream status
;
141 status
<< "Status: " << "progress" << std::endl
142 << "Percent: " << (StepsDone
/float(StepsTotal
)*100.0) << std::endl
143 << "Message: " << _("Running dpkg") << std::endl
145 WriteToStatusFd(status
.str());
148 void PackageManagerProgressDeb822Fd::Stop()
150 // clear the Keep-Fd again
151 _config
->Clear("APT::Keep-Fds", OutStatusFd
);
154 void PackageManagerProgressDeb822Fd::Error(std::string PackageName
,
155 unsigned int StepsDone
,
156 unsigned int TotalSteps
,
157 std::string ErrorMessage
)
159 std::ostringstream status
;
160 status
<< "Status: " << "Error" << std::endl
161 << "Package:" << PackageName
<< std::endl
162 << "Percent: " << (StepsDone
/float(TotalSteps
)*100.0) << std::endl
163 << "Message: " << ErrorMessage
<< std::endl
165 WriteToStatusFd(status
.str());
168 void PackageManagerProgressDeb822Fd::ConffilePrompt(std::string PackageName
,
169 unsigned int StepsDone
,
170 unsigned int TotalSteps
,
171 std::string ConfMessage
)
173 std::ostringstream status
;
174 status
<< "Status: " << "ConfFile" << std::endl
175 << "Package:" << PackageName
<< std::endl
176 << "Percent: " << (StepsDone
/float(TotalSteps
)*100.0) << std::endl
177 << "Message: " << ConfMessage
<< std::endl
179 WriteToStatusFd(status
.str());
183 bool PackageManagerProgressDeb822Fd::StatusChanged(std::string PackageName
,
184 unsigned int xStepsDone
,
185 unsigned int xTotalSteps
,
188 StepsDone
= xStepsDone
;
189 StepsTotal
= xTotalSteps
;
191 // build the status str
192 std::ostringstream status
;
193 status
<< "Status: " << "progress" << std::endl
194 << "Package: " << PackageName
<< std::endl
195 << "Percent: " << (StepsDone
/float(StepsTotal
)*100.0) << std::endl
196 << "Message: " << message
<< std::endl
198 WriteToStatusFd(status
.str());
204 void PackageManagerFancy::SetupTerminalScrollArea(int nr_rows
)
206 // scroll down a bit to avoid visual glitch when the screen
207 // area shrinks by one row
211 std::cout
<< "\033[s";
213 // set scroll region (this will place the cursor in the top left)
214 std::cout
<< "\033[1;" << nr_rows
- 1 << "r";
216 // restore cursor but ensure its inside the scrolling area
217 std::cout
<< "\033[u";
218 static const char *move_cursor_up
= "\033[1A";
219 std::cout
<< move_cursor_up
;
221 std::flush(std::cout
);
224 PackageManagerFancy::PackageManagerFancy()
225 : nr_terminal_rows(-1)
228 if(ioctl(STDOUT_FILENO
, TIOCGWINSZ
, (char *)&win
) == 0)
230 nr_terminal_rows
= win
.ws_row
;
234 void PackageManagerFancy::Start()
236 if (nr_terminal_rows
> 0)
237 SetupTerminalScrollArea(nr_terminal_rows
);
240 void PackageManagerFancy::Stop()
242 if (nr_terminal_rows
> 0)
244 SetupTerminalScrollArea(nr_terminal_rows
+ 1);
246 // override the progress line (sledgehammer)
247 static const char* clear_screen_below_cursor
= "\033[J";
248 std::cout
<< clear_screen_below_cursor
;
252 bool PackageManagerFancy::StatusChanged(std::string PackageName
,
253 unsigned int StepsDone
,
254 unsigned int TotalSteps
,
255 std::string HumanReadableAction
)
257 if (!PackageManager::StatusChanged(PackageName
, StepsDone
, TotalSteps
,
258 HumanReadableAction
))
261 int row
= nr_terminal_rows
;
263 static string save_cursor
= "\033[s";
264 static string restore_cursor
= "\033[u";
266 static string set_bg_color
= "\033[42m"; // green
267 static string set_fg_color
= "\033[30m"; // black
269 static string restore_bg
= "\033[49m";
270 static string restore_fg
= "\033[39m";
272 std::cout
<< save_cursor
273 // move cursor position to last row
274 << "\033[" << row
<< ";0f"
281 std::flush(std::cout
);
282 last_reported_progress
= percentage
;
287 bool PackageManagerText::StatusChanged(std::string PackageName
,
288 unsigned int StepsDone
,
289 unsigned int TotalSteps
,
290 std::string HumanReadableAction
)
292 if (!PackageManager::StatusChanged(PackageName
, StepsDone
, TotalSteps
, HumanReadableAction
))
295 std::cout
<< progress_str
<< "\r\n";
296 std::flush(std::cout
);
298 last_reported_progress
= percentage
;
305 }; // namespace progress