Make the parser output include line numbers
[mspang/inapt.git] / inapt.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 "inapt.h"
17 #include "acqprogress.h"
18
19 using namespace std;
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 int main(int argc, char *argv[]) {
173
174     vector<inapt_action> actions;
175
176     pkgInitConfig(*_config);
177     pkgInitSystem(*_config, _system);
178
179      _config->Set("Debug::pkgProblemResolver", true);
180
181     OpTextProgress prog;
182     pkgCacheFile cachef;
183
184     if (cachef.Open(prog) == false) {
185         _error->DumpErrors();
186         exit(1);
187     }
188
189     pkgCache *cache = cachef;
190     pkgDepCache *DCache = cachef;
191
192     scanner(&actions);
193
194     for (vector<inapt_action>::iterator i = actions.begin(); i < actions.end(); i++) {
195         switch(i->action) {
196             case inapt_action::INSTALL:
197                 DCache->MarkInstall(cache->FindPkg(i->package), true);
198                 break;
199             case inapt_action::REMOVE:
200                 break;
201         }
202     }
203
204     for (vector<inapt_action>::iterator i = actions.begin(); i < actions.end(); i++) {
205         switch(i->action) {
206             case inapt_action::INSTALL:
207                 printf("install %s %s:%d\n", i->package, i->filename, i->linenum);
208                 DCache->MarkInstall(cache->FindPkg(i->package), false);
209                 break;
210             case inapt_action::REMOVE:
211                 printf("remove %s %s:%d\n", i->package, i->filename, i->linenum);
212                 DCache->MarkDelete(cache->FindPkg(i->package), false);
213                 break;
214         }
215     }
216
217     fprintf(stderr, "\n");
218     fprintf(stderr, "nondownloadable packages:\n");
219     for (pkgCache::PkgIterator i = cache->PkgBegin(); !i.end(); i++) {
220        if (i.CurrentVer() && !i.CurrentVer().Downloadable()) {
221                fprintf(stderr, "%s ", i.Name());
222                fprintf(stderr, "%s\n", DCache->GetCandidateVer(i).VerStr());
223        }
224     }
225
226     fprintf(stderr, "\n");
227     fprintf(stderr, "inst %lu del %lu keep %lu broken %lu bad %lu\n",
228                     DCache->InstCount(), DCache->DelCount(), DCache->KeepCount(),
229                     DCache->BrokenCount(), DCache->BadCount());
230
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].InstBroken())
235          fprintf(stderr, "instbroken %s\n", i.Name());
236        if ((*DCache)[i].NowBroken())
237          fprintf(stderr, "nowbroken %s\n", i.Name());
238     }
239
240     fprintf(stderr, "\n");
241
242     pkgProblemResolver fix (DCache);
243
244     for (vector<inapt_action>::iterator i = actions.begin(); i < actions.end(); i++)
245             fix.Protect(cache->FindPkg(i->package));
246     for (vector<inapt_action>::iterator i = actions.begin(); i < actions.end(); i++)
247             fix.Protect(cache->FindPkg(i->package));
248     fix.Resolve();
249
250     fprintf(stderr, "\n");
251     fprintf(stderr, "inst %lu del %lu keep %lu broken %lu bad %lu\n",
252                     DCache->InstCount(), DCache->DelCount(), DCache->KeepCount(),
253                     DCache->BrokenCount(), DCache->BadCount());
254     for (pkgCache::PkgIterator i = cache->PkgBegin(); !i.end(); i++) {
255        if ((*DCache)[i].Install())
256          fprintf(stderr, "inst %s\n", i.Name());
257        if ((*DCache)[i].Delete())
258          fprintf(stderr, "del %s\n", i.Name());
259        if ((*DCache)[i].InstBroken())
260          fprintf(stderr, "instbroken %s\n", i.Name());
261        if ((*DCache)[i].NowBroken())
262          fprintf(stderr, "nowbroken %s\n", i.Name());
263     }
264
265     fprintf(stderr, "\n");
266
267     InstallPackages(cachef);
268 }