Copy code from apt-get to display download progress
[mspang/inapt.git] / magic.cc
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <iostream>
4 #include <cstdio>
5 #include <fstream>
6 #include <apt-pkg/pkgcache.h>
7 #include <apt-pkg/cachefile.h>
8 #include <apt-pkg/dpkgdb.h>
9 #include <apt-pkg/progress.h>
10 #include <apt-pkg/init.h>
11 #include <apt-pkg/error.h>
12 #include <apt-pkg/algorithms.h>
13 #include <apt-pkg/sptr.h>
14 #include <apt-pkg/acquire-item.h>
15
16 #include "acqprogress.h"
17
18 using namespace std;
19
20
21 bool InstallPackages(pkgCacheFile &Cache,bool ShwKept = false,bool Ask = true,
22                      bool Safety = true)
23 {
24    if (_config->FindB("APT::Get::Purge",false) == true)
25    {
26       pkgCache::PkgIterator I = Cache->PkgBegin();
27       for (; I.end() == false; I++)
28       {
29          if (I.Purge() == false && Cache[I].Mode == pkgDepCache::ModeDelete)
30             Cache->MarkDelete(I,true);
31       }
32    }
33
34    if (Cache->BrokenCount() != 0)
35    {
36       return _error->Error("Internal error, InstallPackages was called with broken packages!");
37    }
38
39    if (Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
40        Cache->BadCount() == 0)
41       return true;
42
43    if (Cache->DelCount() != 0 && _config->FindB("APT::Get::Remove",true) == false)
44       return _error->Error(("Packages need to be removed but remove is disabled."));
45
46    pkgRecords Recs(Cache);
47    if (_error->PendingError() == true)
48       return false;
49
50    FileFd Lock;
51    if (_config->FindB("Debug::NoLocking",false) == false &&
52        _config->FindB("APT::Get::Print-URIs") == false)
53    {
54       Lock.Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
55       if (_error->PendingError() == true)
56          return _error->Error(("Unable to lock the download directory"));
57    }
58
59    unsigned int width = 80;
60    AcqTextStatus status (width, 0);
61    pkgAcquire Fetcher (&status);
62
63    pkgSourceList List;
64    if (List.ReadMainList() == false)
65       return _error->Error(("The list of sources could not be read."));
66
67    SPtr<pkgPackageManager> PM= _system->CreatePM(Cache);
68    if (PM->GetArchives(&Fetcher, &List, &Recs) == false ||
69        _error->PendingError() == true)
70       return false;
71
72    if (_error->PendingError() == true)
73       return false;
74
75    while (1)
76    {
77       bool Transient = false;
78       if (_config->FindB("APT::Get::Download",true) == false)
79       {
80          for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I < Fetcher.ItemsEnd();)
81          {
82             if ((*I)->Local == true)
83             {
84                I++;
85                continue;
86             }
87
88             // Close the item and check if it was found in cache
89             (*I)->Finished();
90             if ((*I)->Complete == false)
91                Transient = true;
92
93             // Clear it out of the fetch list
94             delete *I;
95             I = Fetcher.ItemsBegin();
96          }
97       }
98
99       if (Fetcher.Run() == pkgAcquire::Failed)
100          return false;
101
102       // Print out errors
103       bool Failed = false;
104       for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
105       {
106          if ((*I)->Status == pkgAcquire::Item::StatDone &&
107              (*I)->Complete == true)
108             continue;
109
110          if ((*I)->Status == pkgAcquire::Item::StatIdle)
111          {
112             Transient = true;
113             // Failed = true;
114             continue;
115          }
116
117          fprintf(stderr,("Failed to fetch %s  %s\n"),(*I)->DescURI().c_str(),
118                  (*I)->ErrorText.c_str());
119          Failed = true;
120       }
121
122       /* If we are in no download mode and missing files and there were
123          'failures' then the user must specify -m. Furthermore, there
124          is no such thing as a transient error in no-download mode! */
125       if (Transient == true &&
126           _config->FindB("APT::Get::Download",true) == false)
127       {
128          Transient = false;
129          Failed = true;
130       }
131
132       if (_config->FindB("APT::Get::Download-Only",false) == true)
133       {
134          if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
135             return _error->Error(("Some files failed to download"));
136          //c1out << _("Download complete and in download only mode") << endl;
137          return true;
138       }
139
140       if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
141       {
142          return _error->Error(("Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?"));
143       }
144
145       if (Transient == true && Failed == true)
146          return _error->Error(("--fix-missing and media swapping is not currently supported"));
147
148       // Try to deal with missing package files
149       if (Failed == true && PM->FixMissing() == false)
150       {
151          cerr << ("Unable to correct missing packages.") << endl;
152          return _error->Error(("Aborting install."));
153       }
154
155       _system->UnLock();
156       int status_fd = _config->FindI("APT::Status-Fd",-1);
157       pkgPackageManager::OrderResult Res = PM->DoInstall(status_fd);
158       if (Res == pkgPackageManager::Failed || _error->PendingError() == true)
159          return false;
160       if (Res == pkgPackageManager::Completed)
161          return true;
162
163       // Reload the fetcher object and loop again for media swapping
164       Fetcher.Shutdown();
165       if (PM->GetArchives(&Fetcher,&List,&Recs) == false)
166          return false;
167
168       _system->Lock();
169    }
170 }
171
172
173 int main(int argc, char *argv[]) {
174
175     pkgInitConfig(*_config);
176     pkgInitSystem(*_config, _system);
177
178      _config->Set("Debug::pkgProblemResolver", true);
179
180     OpTextProgress prog;
181     pkgCacheFile cachef;
182
183     if (cachef.Open(prog) == false) {
184         _error->DumpErrors();
185         exit(1);
186     }
187
188     pkgCache *cache = cachef;
189     pkgDepCache *DCache = cachef;
190
191     for (pkgCache::PkgIterator i = cache->PkgBegin(); !i.end(); i++) {
192        if (i.CurrentVer() && !i.CurrentVer().Downloadable()) {
193                fprintf(stderr, "%s ", i.Name());
194                fprintf(stderr, "%s\n", DCache->GetCandidateVer(i).VerStr());
195        }
196     }
197
198     DCache->MarkInstall(cache->FindPkg("zsh"), true);
199     DCache->MarkInstall(cache->FindPkg("ssmtp"), true);
200     DCache->MarkInstall(cache->FindPkg("gnome"), true);
201     DCache->MarkInstall(cache->FindPkg("postfix"), true);
202     DCache->MarkDelete(cache->FindPkg("network-manager"), false);
203     DCache->MarkDelete(cache->FindPkg("gnome-games"), false);
204
205     fprintf(stderr, "\n");
206     fprintf(stderr, "inst %lu del %lu keep %lu broken %lu bad %lu\n",
207                     DCache->InstCount(), DCache->DelCount(), DCache->KeepCount(),
208                     DCache->BrokenCount(), DCache->BadCount());
209
210     for (pkgCache::PkgIterator i = cache->PkgBegin(); !i.end(); i++) {
211        if ((*DCache)[i].Install())
212          fprintf(stderr, "inst %s\n", i.Name());
213        if ((*DCache)[i].InstBroken())
214          fprintf(stderr, "instbroken %s\n", i.Name());
215        if ((*DCache)[i].NowBroken())
216          fprintf(stderr, "nowbroken %s\n", i.Name());
217     }
218
219     fprintf(stderr, "\n");
220
221     pkgProblemResolver fix (DCache);
222     fix.Protect(cache->FindPkg("ssmtp"));
223     fix.Protect(cache->FindPkg("gnome-games"));
224     fix.Protect(cache->FindPkg("network-manager"));
225     fix.Resolve();
226
227     fprintf(stderr, "\n");
228     fprintf(stderr, "inst %lu del %lu keep %lu broken %lu bad %lu\n",
229                     DCache->InstCount(), DCache->DelCount(), DCache->KeepCount(),
230                     DCache->BrokenCount(), DCache->BadCount());
231     for (pkgCache::PkgIterator i = cache->PkgBegin(); !i.end(); i++) {
232        if ((*DCache)[i].Install())
233          fprintf(stderr, "inst %s\n", i.Name());
234        if ((*DCache)[i].Delete())
235          fprintf(stderr, "del %s\n", i.Name());
236        if ((*DCache)[i].InstBroken())
237          fprintf(stderr, "instbroken %s\n", i.Name());
238        if ((*DCache)[i].NowBroken())
239          fprintf(stderr, "nowbroken %s\n", i.Name());
240     }
241
242     fprintf(stderr, "\n");
243
244
245     InstallPackages(cachef);
246 }