re-add APT::Keep-Fds:: for the dpkg status-fd in dpkgpm.cc as we always need this
[ntk/apt.git] / apt-pkg / iprogress.cc
CommitLineData
e6ad8031
MV
1#include <apt-pkg/configuration.h>
2#include <apt-pkg/fileutl.h>
31f97d7b
MV
3#include <apt-pkg/iprogress.h>
4#include <apt-pkg/strutl.h>
e6ad8031 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
MV
31PackageManagerProgressFd::PackageManagerProgressFd(int progress_fd)
32{
33 OutStatusFd = progress_fd;
34}
35
f9935b1c
MV
36void PackageManagerProgressFd::WriteToStatusFd(std::string s)
37{
38 if(OutStatusFd <= 0)
39 return;
40 FileFd::Write(OutStatusFd, s.c_str(), s.size());
41}
42
a22fdebf 43void PackageManagerProgressFd::Start()
e6ad8031 44{
5e9458e2
MV
45 if(OutStatusFd <= 0)
46 return;
47
48 // FIXME: use SetCloseExec here once it taught about throwing
49 // exceptions instead of doing _exit(100) on failure
50 fcntl(OutStatusFd,F_SETFD,FD_CLOEXEC);
e6ad8031
MV
51
52 // send status information that we are about to fork dpkg
f9935b1c
MV
53 std::ostringstream status;
54 status << "pmstatus:dpkg-exec:"
55 << (StepsDone/float(StepsTotal)*100.0)
56 << ":" << _("Running dpkg")
57 << std::endl;
58 WriteToStatusFd(status.str());
e6ad8031
MV
59}
60
a22fdebf 61void PackageManagerProgressFd::Stop()
e6ad8031
MV
62{
63 // clear the Keep-Fd again
64 _config->Clear("APT::Keep-Fds", OutStatusFd);
65}
66
67void PackageManagerProgressFd::Error(std::string PackageName,
68 unsigned int StepsDone,
69 unsigned int TotalSteps,
70 std::string ErrorMessage)
71{
72 std::ostringstream status;
73 status << "pmerror:" << PackageName
74 << ":" << (StepsDone/float(TotalSteps)*100.0)
75 << ":" << ErrorMessage
76 << std::endl;
f9935b1c 77 WriteToStatusFd(status.str());
e6ad8031
MV
78}
79
80void PackageManagerProgressFd::ConffilePrompt(std::string PackageName,
81 unsigned int StepsDone,
82 unsigned int TotalSteps,
83 std::string ConfMessage)
84{
85 std::ostringstream status;
86 status << "pmconffile:" << PackageName
87 << ":" << (StepsDone/float(TotalSteps)*100.0)
88 << ":" << ConfMessage
89 << std::endl;
f9935b1c 90 WriteToStatusFd(status.str());
e6ad8031
MV
91}
92
93
94bool PackageManagerProgressFd::StatusChanged(std::string PackageName,
95 unsigned int xStepsDone,
96 unsigned int xTotalSteps,
97 std::string pkg_action)
98{
99 StepsDone = xStepsDone;
100 StepsTotal = xTotalSteps;
101
102 // build the status str
103 std::ostringstream status;
104 status << "pmstatus:" << PackageName
105 << ":" << (StepsDone/float(StepsTotal)*100.0)
106 << ":" << pkg_action
107 << std::endl;
f9935b1c 108 WriteToStatusFd(status.str());
e6ad8031
MV
109 return true;
110}
111
db78c60c 112void PackageManagerFancy::SetupTerminalScrollArea(int nr_rows)
31f97d7b
MV
113{
114 // scroll down a bit to avoid visual glitch when the screen
115 // area shrinks by one row
116 std::cout << "\n";
117
118 // save cursor
119 std::cout << "\033[s";
120
121 // set scroll region (this will place the cursor in the top left)
122 std::cout << "\033[1;" << nr_rows - 1 << "r";
123
124 // restore cursor but ensure its inside the scrolling area
125 std::cout << "\033[u";
126 static const char *move_cursor_up = "\033[1A";
127 std::cout << move_cursor_up;
db78c60c 128
31f97d7b
MV
129 std::flush(std::cout);
130}
131
132PackageManagerFancy::PackageManagerFancy()
133 : nr_terminal_rows(-1)
134{
135 struct winsize win;
136 if(ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&win) == 0)
137 {
138 nr_terminal_rows = win.ws_row;
139 }
140}
141
a22fdebf 142void PackageManagerFancy::Start()
31f97d7b 143{
db78c60c
MV
144 if (nr_terminal_rows > 0)
145 SetupTerminalScrollArea(nr_terminal_rows);
31f97d7b
MV
146}
147
a22fdebf 148void PackageManagerFancy::Stop()
31f97d7b 149{
db78c60c
MV
150 if (nr_terminal_rows > 0)
151 {
152 SetupTerminalScrollArea(nr_terminal_rows + 1);
31f97d7b 153
db78c60c
MV
154 // override the progress line (sledgehammer)
155 static const char* clear_screen_below_cursor = "\033[J";
156 std::cout << clear_screen_below_cursor;
157 }
31f97d7b
MV
158}
159
6c5ae8ed 160bool PackageManagerFancy::StatusChanged(std::string PackageName,
31f97d7b 161 unsigned int StepsDone,
e6ad8031
MV
162 unsigned int TotalSteps,
163 std::string HumanReadableAction)
31f97d7b 164{
e6ad8031
MV
165 if (!PackageManager::StatusChanged(PackageName, StepsDone, TotalSteps,
166 HumanReadableAction))
6c5ae8ed 167 return false;
31f97d7b
MV
168
169 int row = nr_terminal_rows;
170
171 static string save_cursor = "\033[s";
172 static string restore_cursor = "\033[u";
173
174 static string set_bg_color = "\033[42m"; // green
175 static string set_fg_color = "\033[30m"; // black
176
177 static string restore_bg = "\033[49m";
178 static string restore_fg = "\033[39m";
179
180 std::cout << save_cursor
181 // move cursor position to last row
182 << "\033[" << row << ";0f"
183 << set_bg_color
184 << set_fg_color
185 << progress_str
186 << restore_cursor
187 << restore_bg
188 << restore_fg;
189 std::flush(std::cout);
190 last_reported_progress = percentage;
6c5ae8ed
MV
191
192 return true;
31f97d7b
MV
193}
194
6c5ae8ed 195bool PackageManagerText::StatusChanged(std::string PackageName,
31f97d7b 196 unsigned int StepsDone,
e6ad8031
MV
197 unsigned int TotalSteps,
198 std::string HumanReadableAction)
31f97d7b 199{
e6ad8031 200 if (!PackageManager::StatusChanged(PackageName, StepsDone, TotalSteps, HumanReadableAction))
6c5ae8ed 201 return false;
31f97d7b
MV
202
203 std::cout << progress_str << "\r\n";
204 std::flush(std::cout);
205
206 last_reported_progress = percentage;
6c5ae8ed
MV
207
208 return true;
31f97d7b
MV
209}
210
211
212}; // namespace progress
213}; // namespace apt