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