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