source: projects/synaptic/trunk/common/rpackagelister.cc @ 280

Revision 280, 48.1 KB checked in by yasumichi, 13 years ago (diff)

first import

Line 
1/* rpackagelister.cc - package cache and list manipulation
2 *
3 * Copyright (c) 2000-2003 Conectiva S/A
4 *               2002-2004 Michael Vogt <mvo@debian.org>
5 *
6 * Author: Alfredo K. Kojima <kojima@conectiva.com.br>
7 *         Michael Vogt <mvo@debian.org>
8 *
9 * Portions Taken from apt-get
10 *   Copyright (C) Jason Gunthorpe
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License as
14 * published by the Free Software Foundation; either version 2 of the
15 * License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
25 * USA
26 */
27
28#include "config.h"
29
30#include <cassert>
31#include <stdlib.h>
32#include <unistd.h>
33#include <map>
34#include <sstream>
35#include <dirent.h>
36#include <sys/stat.h>
37#include <unistd.h>
38#include <time.h>
39
40#include "rpackagelister.h"
41#include "rpackagecache.h"
42#include "rpackagefilter.h"
43#include "rconfiguration.h"
44#include "raptoptions.h"
45#include "rinstallprogress.h"
46#include "rcacheactor.h"
47
48#include <apt-pkg/error.h>
49#include <apt-pkg/progress.h>
50#include <apt-pkg/algorithms.h>
51#include <apt-pkg/pkgrecords.h>
52#include <apt-pkg/configuration.h>
53#include <apt-pkg/acquire.h>
54#include <apt-pkg/acquire-item.h>
55#include <apt-pkg/clean.h>
56
57#include <apt-pkg/sourcelist.h>
58#include <apt-pkg/pkgsystem.h>
59#include <apt-pkg/strutl.h>
60
61#ifdef WITH_LUA
62#include <apt-pkg/luaiface.h>
63#endif
64
65#include <algorithm>
66#include <cstdio>
67
68#include "sections_trans.h"
69
70#include "i18n.h"
71
72using namespace std;
73
74RPackageLister::RPackageLister()
75   : _records(0), _progMeter(new OpProgress)
76{
77   _cache = new RPackageCache();
78
79   _searchData.pattern = NULL;
80   _searchData.isRegex = false;
81   _viewMode = _config->FindI("Synaptic::ViewMode", 0);
82   _updating = true;
83   _sortMode = LIST_SORT_NAME;
84
85   // keep order in sync with rpackageview.h
86   _views.push_back(new RPackageViewSections(_packages));
87   _views.push_back(new RPackageViewStatus(_packages));
88   _filterView = new RPackageViewFilter(_packages);
89   _views.push_back(_filterView);
90   _searchView =  new RPackageViewSearch(_packages);
91   _views.push_back(_searchView);   
92   //_views.push_back(new RPackageViewAlphabetic(_packages));
93
94   if (_viewMode >= _views.size())
95      _viewMode = 0;
96   _selectedView = _views[_viewMode];
97
98   memset(&_searchData, 0, sizeof(_searchData));
99
100   _pkgStatus.init();
101
102   cleanCommitLog();
103#if 0
104   string Recommends = _config->Find("Synaptic::RecommendsFile",
105                                     "/etc/apt/metadata");
106   if (FileExists(Recommends))
107      _actors.push_back(new RCacheActorRecommends(this, Recommends));
108#endif
109}
110
111RPackageLister::~RPackageLister()
112{
113   for (vector<RCacheActor *>::iterator I = _actors.begin();
114        I != _actors.end(); I++)
115      delete(*I);
116
117   delete _cache;
118}
119
120void RPackageLister::setView(unsigned int index)
121{
122   // only save this config if it is not a search
123   if(index != PACKAGE_VIEW_SEARCH)
124      _config->Set("Synaptic::ViewMode", index);
125
126   if(index < _views.size())
127      _selectedView = _views[index];
128   else
129      _selectedView = _views[0];
130}
131
132vector<string> RPackageLister::getViews()
133{
134   vector<string> views;
135   for (unsigned int i = 0; i != _views.size(); i++)
136      views.push_back(_views[i]->getName());
137   return views;
138}
139
140vector<string> RPackageLister::getSubViews()
141{
142   return _selectedView->getSubViews();
143}
144
145bool RPackageLister::setSubView(string newSubView)
146{
147   if(newSubView.empty())
148      _selectedView->showAll();
149   else
150      _selectedView->setSelected(newSubView);
151   notifyPreChange(NULL);
152
153   reapplyFilter();
154
155   notifyPostChange(NULL);
156
157   return true;
158}
159
160static string getServerErrorMessage(string errm)
161{
162   string msg;
163   string::size_type pos = errm.find("server said");
164   if (pos != string::npos) {
165      msg = string(errm.c_str() + pos + sizeof("server said"));
166      if (msg[0] == ' ')
167         msg = msg.c_str() + 1;
168   }
169   return msg;
170}
171
172void RPackageLister::notifyPreChange(RPackage *pkg)
173{
174   for (vector<RPackageObserver *>::const_iterator I =
175        _packageObservers.begin(); I != _packageObservers.end(); I++) {
176      (*I)->notifyPreFilteredChange();
177   }
178}
179
180void RPackageLister::notifyPostChange(RPackage *pkg)
181{
182   reapplyFilter();
183
184
185   for (vector<RPackageObserver *>::const_iterator I =
186        _packageObservers.begin(); I != _packageObservers.end(); I++) {
187      (*I)->notifyPostFilteredChange();
188   }
189
190   if (pkg != NULL) {
191      for (vector<RPackageObserver *>::const_iterator I =
192           _packageObservers.begin(); I != _packageObservers.end(); I++) {
193         (*I)->notifyChange(pkg);
194      }
195   }
196}
197
198void RPackageLister::notifyChange(RPackage *pkg)
199{
200   notifyPreChange(pkg);
201   notifyPostChange(pkg);
202}
203
204void RPackageLister::unregisterObserver(RPackageObserver *observer)
205{
206
207   vector<RPackageObserver *>::iterator I;
208   I = find(_packageObservers.begin(), _packageObservers.end(), observer);
209   if (I != _packageObservers.end())
210      _packageObservers.erase(I);
211}
212
213void RPackageLister::registerObserver(RPackageObserver *observer)
214{
215   _packageObservers.push_back(observer);
216}
217
218
219void RPackageLister::notifyCacheOpen()
220{
221   undoStack.clear();
222   redoStack.clear();
223   for (vector<RCacheObserver *>::const_iterator I =
224        _cacheObservers.begin(); I != _cacheObservers.end(); I++) {
225      (*I)->notifyCacheOpen();
226   }
227
228}
229
230void RPackageLister::notifyCachePreChange()
231{
232   for (vector<RCacheObserver *>::const_iterator I =
233        _cacheObservers.begin(); I != _cacheObservers.end(); I++) {
234      (*I)->notifyCachePreChange();
235   }
236}
237
238void RPackageLister::notifyCachePostChange()
239{
240   for (vector<RCacheObserver *>::const_iterator I =
241        _cacheObservers.begin(); I != _cacheObservers.end(); I++) {
242      (*I)->notifyCachePostChange();
243   }
244}
245
246void RPackageLister::unregisterCacheObserver(RCacheObserver *observer)
247{
248   vector<RCacheObserver *>::iterator I;
249   I = find(_cacheObservers.begin(), _cacheObservers.end(), observer);
250   if (I != _cacheObservers.end())
251      _cacheObservers.erase(I);
252}
253
254void RPackageLister::registerCacheObserver(RCacheObserver *observer)
255{
256   _cacheObservers.push_back(observer);
257}
258
259bool RPackageLister::check()
260{
261   if (_cache->deps() == NULL)
262      return false;
263   // Nothing is broken
264   if (_cache->deps()->BrokenCount() != 0) {
265      return false;
266   }
267
268   return true;
269}
270
271bool RPackageLister::upgradable()
272{
273   return _cache != NULL && _cache->deps() != NULL;
274}
275
276bool RPackageLister::openCache(bool lock)
277{
278   static bool firstRun = true;
279
280   // Flush old errors
281   _error->Discard();
282
283   if (!_cache->open(*_progMeter,lock)) {
284      _progMeter->Done();
285      _cacheValid = false;
286      return false;
287   }
288   _progMeter->Done();
289
290   pkgDepCache *deps = _cache->deps();
291
292   // Apply corrections for half-installed packages
293   if (pkgApplyStatus(*deps) == false) {
294      _cacheValid = false;
295      return _error->Error(_("Internal error opening cache (%d). "
296                             "Please report."), 1);
297   }
298
299   if (_error->PendingError()) {
300      _cacheValid = false;
301      return _error->Error(_("Internal error opening cache (%d). "
302                             "Please report."), 2);
303   }
304
305#ifdef HAVE_RPM
306   // APT used to have a bug where the destruction order made
307   // this code segfault. APT-RPM has the right fix for this. -- niemeyer
308   if (_records)
309      delete _records;
310#endif
311
312   _records = new pkgRecords(*deps);
313   if (_error->PendingError()) {
314      _cacheValid = false;
315      return _error->Error(_("Internal error opening cache (%d). "
316                             "Please report."), 3);
317   }
318
319   for (vector<RPackage *>::iterator I = _packages.begin();
320        I != _packages.end(); I++)
321      delete (*I);
322
323   int packageCount = deps->Head().PackageCount;
324   _packages.resize(packageCount);
325
326   _packagesIndex.clear();
327   _packagesIndex.resize(packageCount, -1);
328
329   string pkgName;
330   int count = 0;
331
332   _installedCount = 0;
333
334   map<string, RPackage *> pkgmap;
335   set<string> sectionSet;
336
337   for (unsigned int i = 0; i != _views.size(); i++)
338      _views[i]->clear();
339
340   pkgCache::PkgIterator I;
341   for (I = deps->PkgBegin(); I.end() != true; I++) {
342
343      if (I->CurrentVer != 0)
344         _installedCount++;
345      else if (I->VersionList == 0)
346         continue; // Exclude virtual packages.
347
348      RPackage *pkg = new RPackage(this, deps, _records, I);
349      _packagesIndex[I->ID] = count;
350      _packages[count++] = pkg;
351
352      pkgName = pkg->name();
353
354      pkgmap[pkgName] = pkg;
355
356      // Find out about new packages.
357      if (firstRun) {
358         packageNames.insert(pkgName);
359         // check for saved-new status
360         if (_roptions->getPackageNew(pkgName.c_str()))
361            pkg->setNew(true);
362      } else if (packageNames.find(pkgName) == packageNames.end()) {
363         pkg->setNew();
364         _roptions->setPackageNew(pkgName.c_str());
365         packageNames.insert(pkgName);
366      } else  if (_roptions->getPackageNew(pkgName.c_str())) {
367         pkg->setNew(true);
368      }
369
370      if (_roptions->getPackageLock(pkgName.c_str())) 
371         pkg->setPinned(true);
372
373      for (unsigned int i = 0; i != _views.size(); i++)
374         _views[i]->addPackage(pkg);
375
376      // Gather list of sections.
377      if (I.Section())
378         sectionSet.insert(I.Section());
379#if 0 // may confuse users
380      else
381         cerr << "Package " << I.Name() << " has no section?!" << endl;
382#endif
383   }
384
385   // Truncate due to virtual packages which were skipped above.
386   _packages.resize(count);
387
388   applyInitialSelection();
389
390   _updating = false;
391
392   reapplyFilter();
393
394   // mvo: put it here for now
395   notifyCacheOpen();
396
397   firstRun = false;
398
399   _cacheValid = true;
400   return true;
401}
402
403
404
405void RPackageLister::applyInitialSelection()
406{
407   _roptions->rereadOrphaned();
408   _roptions->rereadDebconf();
409
410   for (unsigned i = 0; i < _packages.size(); i++) {
411
412      if (_roptions->getPackageOrphaned(_packages[i]->name()))
413         _packages[i]->setOrphaned(true);
414   }
415}
416
417RPackage *RPackageLister::getPackage(pkgCache::PkgIterator &iter)
418{
419   int index = _packagesIndex[iter->ID];
420   if (index != -1)
421      return _packages[index];
422   return NULL;
423}
424
425RPackage *RPackageLister::getPackage(string name)
426{
427   pkgCache::PkgIterator pkg = _cache->deps()->FindPkg(name);
428   if (pkg.end() == false)
429      return getPackage(pkg);
430   return NULL;
431}
432
433int RPackageLister::getPackageIndex(RPackage *pkg)
434{
435   return _packagesIndex[(*pkg->package())->ID];
436}
437
438int RPackageLister::getViewPackageIndex(RPackage *pkg)
439{
440   return _viewPackagesIndex[(*pkg->package())->ID];
441}
442
443bool RPackageLister::fixBroken()
444{
445   if (_cache->deps() == NULL)
446      return false;
447
448   if (_cache->deps()->BrokenCount() == 0)
449      return true;
450
451   if (pkgFixBroken(*_cache->deps()) == false
452       || _cache->deps()->BrokenCount() != 0)
453      return _error->Error(_("Unable to correct dependencies"));
454   if (pkgMinimizeUpgrade(*_cache->deps()) == false)
455      return _error->Error(_("Unable to mark upgrades\nCheck your system for errors."));
456
457   reapplyFilter();
458
459   return true;
460}
461
462
463bool RPackageLister::upgrade()
464{
465   if (pkgAllUpgrade(*_cache->deps()) == false) {
466      return _error->
467         Error(_("Internal Error, AllUpgrade broke stuff. Please report."));
468   }
469#ifdef WITH_LUA
470   _lua->SetDepCache(_cache->deps());
471   _lua->RunScripts("Scripts::Synaptic::Upgrade", false);
472   _lua->ResetCaches();
473#endif
474
475   //reapplyFilter();
476   notifyChange(NULL);
477
478   return true;
479}
480
481
482bool RPackageLister::distUpgrade()
483{
484   if (pkgDistUpgrade(*_cache->deps()) == false) {
485      cout << _("dist upgrade Failed") << endl;
486      return false;
487   }
488#ifdef WITH_LUA
489   _lua->SetDepCache(_cache->deps());
490   _lua->RunScripts("Scripts::Synaptic::DistUpgrade", false);
491   _lua->ResetCaches();
492#endif
493
494   //reapplyFilter();
495   notifyChange(NULL);
496
497   return true;
498}
499
500static void qsSortByName(vector<RPackage *> &packages, int start, int end)
501{
502   int i, j;
503   RPackage *pivot, *tmp;
504
505   i = start;
506   j = end;
507   pivot = packages[(i + j) / 2];
508   do {
509      while (strcoll(packages[i]->name(), pivot->name()) < 0)
510         i++;
511      while (strcoll(pivot->name(), packages[j]->name()) < 0)
512         j--;
513      if (i <= j) {
514         tmp = packages[i];
515         packages[i] = packages[j];
516         packages[j] = tmp;
517         i++;
518         j--;
519      }
520   } while (i <= j);
521
522   if (start < j)
523      qsSortByName(packages, start, j);
524   if (i < end)
525      qsSortByName(packages, i, end);
526}
527
528void RPackageLister::reapplyFilter()
529{
530   // PORTME
531   if (_updating)
532      return;
533
534   //   cout << "RPackageLister::reapplyFilter()" << endl;
535
536   _viewPackages.clear();
537   _viewPackagesIndex.clear();
538   _viewPackagesIndex.resize(_packagesIndex.size(), -1);
539
540   for (RPackageView::iterator I = _selectedView->begin();
541        I != _selectedView->end(); I++) {
542      if (*I) {
543         _viewPackagesIndex[(*(*I)->package())->ID] = _viewPackages.size();
544         _viewPackages.push_back(*I);
545      }
546   }
547
548   sortPackages(_sortMode);
549}
550
551static const int status_sort_magic = (  RPackage::FInstalled
552                                      | RPackage::FOutdated
553                                      | RPackage::FNew);
554struct statusSortFunc {
555   bool operator() (RPackage *x, RPackage *y) {
556      return (x->getFlags() & (status_sort_magic))  <
557             (y->getFlags() & (status_sort_magic));
558}};
559
560struct instSizeSortFunc {
561   bool operator() (RPackage *x, RPackage *y) {
562      return x->installedSize() < y->installedSize();
563}};
564
565struct dlSizeSortFunc {
566   bool operator() (RPackage *x, RPackage *y) {
567      return x->availablePackageSize() < y->availablePackageSize();
568}};
569
570struct componentSortFunc {
571   bool operator() (RPackage *x, RPackage *y) {
572      return x->component() < y->component();
573}};
574
575struct sectionSortFunc {
576   bool operator() (RPackage *x, RPackage *y) {
577      return x->section() < y->section();
578}};
579
580// version string compare
581int verstrcmp(const char *x, const char *y)
582{
583   if(x && y)
584      return strcmp(x,y) < 0;
585   
586   // if we compare with a non-existring version
587   if(y == NULL)
588      return false;
589   return true;
590}
591
592struct versionSortFunc {
593   bool operator() (RPackage *x, RPackage *y) {
594      return verstrcmp(y->availableVersion(),
595                       x->availableVersion());
596   }
597};
598
599struct instVersionSortFunc {
600   bool operator() (RPackage *x, RPackage *y) {
601      return verstrcmp(y->installedVersion(),
602                       x->installedVersion());
603}};
604
605struct supportedSortFunc {
606 protected:
607   bool _ascent;
608   RPackageStatus _status;
609 public:
610   supportedSortFunc(bool ascent, RPackageStatus &s) 
611      : _ascent(ascent), _status(s) {};
612   bool operator() (RPackage *x, RPackage *y) {
613      if(_ascent)
614         return _status.isSupported(y) < _status.isSupported(x);
615      else
616         return _status.isSupported(y) > _status.isSupported(x);
617   }
618};
619
620
621
622void RPackageLister::sortPackages(vector<RPackage *> &packages, 
623                                  listSortMode mode)
624{
625   _sortMode = mode;
626   if (packages.empty())
627      return;
628
629   switch(mode) {
630   case LIST_SORT_NAME:
631      qsSortByName(packages, 0, packages.size() - 1);
632      break;
633   case LIST_SORT_SIZE_ASC:
634      stable_sort(packages.begin(), packages.end(), 
635                  sortFunc<instSizeSortFunc>(true));
636      break;
637   case LIST_SORT_SIZE_DES:
638      stable_sort(packages.begin(), packages.end(), 
639                  sortFunc<instSizeSortFunc>(false));
640      break;
641   case LIST_SORT_DLSIZE_ASC:
642      stable_sort(packages.begin(), packages.end(), 
643                  sortFunc<dlSizeSortFunc>(true));
644      break;
645   case LIST_SORT_DLSIZE_DES:
646      stable_sort(packages.begin(), packages.end(), 
647                  sortFunc<dlSizeSortFunc>(false));
648      break;
649   case LIST_SORT_COMPONENT_ASC:
650      qsSortByName(packages, 0, packages.size() - 1);
651      stable_sort(packages.begin(), packages.end(), 
652                  sortFunc<componentSortFunc>(true));
653      break;
654   case LIST_SORT_COMPONENT_DES:
655      qsSortByName(packages, 0, packages.size() - 1);
656      stable_sort(packages.begin(), packages.end(),               
657                  sortFunc<componentSortFunc>(false));
658      break;
659   case LIST_SORT_SECTION_ASC:
660      qsSortByName(packages, 0, packages.size() - 1);
661      stable_sort(packages.begin(), packages.end(), 
662                  sortFunc<sectionSortFunc>(true));
663      break;
664   case LIST_SORT_SECTION_DES:
665      qsSortByName(packages, 0, packages.size() - 1);
666      stable_sort(packages.begin(), packages.end(), 
667                  sortFunc<sectionSortFunc>(false));
668      break;
669   case LIST_SORT_STATUS_ASC:
670      qsSortByName(packages, 0, packages.size() - 1);
671      stable_sort(packages.begin(), packages.end(), 
672                  sortFunc<statusSortFunc>(true));
673      break;
674   case LIST_SORT_STATUS_DES:
675      qsSortByName(packages, 0, packages.size() - 1);
676      stable_sort(packages.begin(), packages.end(), 
677                  sortFunc<statusSortFunc>(false));
678      break;
679   case LIST_SORT_SUPPORTED_ASC:
680      qsSortByName(packages, 0, packages.size() - 1);
681      stable_sort(packages.begin(), packages.end(), 
682                  supportedSortFunc(true, _pkgStatus));
683      break;
684   case LIST_SORT_SUPPORTED_DES:
685      qsSortByName(packages, 0, packages.size() - 1);
686      stable_sort(packages.begin(), packages.end(), 
687                  supportedSortFunc(false, _pkgStatus));
688      break;
689   case LIST_SORT_VERSION_ASC:
690      stable_sort(packages.begin(), packages.end(), 
691                  sortFunc<versionSortFunc>(true));
692      break;
693   case LIST_SORT_VERSION_DES:
694      stable_sort(packages.begin(), packages.end(), 
695                  sortFunc<versionSortFunc>(false));
696      break;
697   case LIST_SORT_INST_VERSION_ASC:
698      stable_sort(packages.begin(), packages.end(), 
699                  sortFunc<instVersionSortFunc>(true));
700      break;
701   case LIST_SORT_INST_VERSION_DES:
702      stable_sort(packages.begin(), packages.end(), 
703                  sortFunc<instVersionSortFunc>(false));
704      break;
705   }
706}
707
708int RPackageLister::findPackage(const char *pattern)
709{
710   if (_searchData.isRegex)
711      regfree(&_searchData.regex);
712
713   if (_searchData.pattern)
714      free(_searchData.pattern);
715
716   _searchData.pattern = strdup(pattern);
717
718   if (!_config->FindB("Synaptic::UseRegexp", false) ||
719       regcomp(&_searchData.regex, pattern, REG_EXTENDED | REG_ICASE) != 0) {
720      _searchData.isRegex = false;
721   } else {
722      _searchData.isRegex = true;
723   }
724   _searchData.last = -1;
725
726   return findNextPackage();
727}
728
729
730int RPackageLister::findNextPackage()
731{
732   if (!_searchData.pattern) {
733      if (_searchData.last >= (int)_viewPackages.size())
734         _searchData.last = -1;
735      return ++_searchData.last;
736   }
737
738   int len = strlen(_searchData.pattern);
739
740   for (unsigned i = _searchData.last + 1; i < _viewPackages.size(); i++) {
741      if (_searchData.isRegex) {
742         if (regexec(&_searchData.regex, _viewPackages[i]->name(),
743                     0, NULL, 0) == 0) {
744            _searchData.last = i;
745            return i;
746         }
747      } else {
748         if (strncasecmp(_searchData.pattern, _viewPackages[i]->name(),
749                         len) == 0) {
750            _searchData.last = i;
751            return i;
752         }
753      }
754   }
755   return -1;
756}
757
758void RPackageLister::getStats(int &installed, int &broken,
759                              int &toInstall, int &toReInstall,
760                              int &toRemove,  double &sizeChange)
761{
762   pkgDepCache *deps = _cache->deps();
763
764   if (deps != NULL) {
765      sizeChange = deps->UsrSize();
766     
767      //FIXME: toReInstall not reported?
768      installed = _installedCount;
769      broken = deps->BrokenCount();
770      toInstall = deps->InstCount();
771      toRemove = deps->DelCount();
772   } else
773      sizeChange = installed = broken = toInstall = toRemove = 0;
774}
775
776
777void RPackageLister::getDownloadSummary(int &dlCount, double &dlSize)
778{
779   dlCount = 0;
780   dlSize = _cache->deps()->DebSize();
781}
782
783
784void RPackageLister::getSummary(int &held, int &kept, int &essential,
785                                int &toInstall, int &toReInstall,
786                                int &toUpgrade, int &toRemove,
787                                int &toDowngrade, int &unauthenticated,
788                                double &sizeChange)
789{
790   pkgDepCache *deps = _cache->deps();
791   unsigned i;
792
793   held = 0;
794   kept = 0;
795   essential = 0;
796   toInstall = 0;
797   toReInstall = 0;
798   toUpgrade = 0;
799   toDowngrade = 0;
800   toRemove = 0;
801   unauthenticated =0;
802
803   for (i = 0; i < _packages.size(); i++) {
804      int flags = _packages[i]->getFlags();
805
806      // These flags will never be set together.
807      int status = flags & (RPackage::FKeep |
808                            RPackage::FNewInstall |
809                            RPackage::FReInstall |
810                            RPackage::FUpgrade |
811                            RPackage::FDowngrade |
812                            RPackage::FRemove);
813
814#ifdef WITH_APT_AUTH
815      switch(status) {
816      case RPackage::FNewInstall:
817      case RPackage::FInstall:
818      case RPackage::FReInstall:
819      case RPackage::FUpgrade:
820         if(!_packages[i]->isTrusted()) 
821            unauthenticated++;
822         break;
823      }
824#endif
825
826      switch (status) {
827         case RPackage::FKeep:
828            if (flags & RPackage::FHeld)
829               held++;
830            else
831               kept++;
832            break;
833         case RPackage::FNewInstall:
834            toInstall++;
835            break;
836         case RPackage::FReInstall:
837            toReInstall++;
838            break;
839         case RPackage::FUpgrade:
840            toUpgrade++;
841            break;
842         case RPackage::FDowngrade:
843            toDowngrade++;
844            break;
845         case RPackage::FRemove:
846            if (flags & RPackage::FImportant)
847               essential++;
848            toRemove++;
849            break;
850      }
851   }
852
853   sizeChange = deps->UsrSize();
854}
855
856
857
858struct bla:public binary_function<RPackage *, RPackage *, bool> {
859   bool operator() (RPackage *a, RPackage *b) {
860      return strcmp(a->name(), b->name()) < 0;
861   }
862};
863
864void RPackageLister::saveUndoState(pkgState &state)
865{
866   undoStack.push_front(state);
867   redoStack.clear();
868
869#ifdef HAVE_RPM
870   unsigned int maxStackSize = _config->FindI("Synaptic::undoStackSize", 3);
871#else
872   unsigned int maxStackSize = _config->FindI("Synaptic::undoStackSize", 20);
873#endif
874   while (undoStack.size() > maxStackSize)
875      undoStack.pop_back();
876}
877
878void RPackageLister::saveUndoState()
879{
880   pkgState state;
881   saveState(state);
882   saveUndoState(state);
883}
884
885
886void RPackageLister::undo()
887{
888   pkgState state;
889   if (undoStack.empty())
890      return;
891
892   saveState(state);
893   redoStack.push_front(state);
894
895   state = undoStack.front();
896   undoStack.pop_front();
897
898   restoreState(state);
899}
900
901void RPackageLister::redo()
902{
903   //cout << "RPackageLister::redo()" << endl;
904   pkgState state;
905   if (redoStack.empty()) {
906      //cout << "redoStack empty" << endl;
907      return;
908   }
909   saveState(state);
910   undoStack.push_front(state);
911
912   state = redoStack.front();
913   redoStack.pop_front();
914   restoreState(state);
915}
916
917
918#ifdef HAVE_RPM
919void RPackageLister::saveState(RPackageLister::pkgState &state)
920{
921   state.Save(_cache->deps());
922}
923
924void RPackageLister::restoreState(RPackageLister::pkgState &state)
925{
926   state.Restore();
927}
928
929bool RPackageLister::getStateChanges(RPackageLister::pkgState &state,
930                                     vector<RPackage *> &toKeep,
931                                     vector<RPackage *> &toInstall,
932                                     vector<RPackage *> &toReInstall,
933                                     vector<RPackage *> &toUpgrade,
934                                     vector<RPackage *> &toRemove,
935                                     vector<RPackage *> &toDowngrade,
936                                     vector<RPackage *> &notAuthenticated,
937                                     vector<RPackage *> &exclude,
938                                     bool sorted)
939{
940   bool changed = false;
941
942   state.UnIgnoreAll();
943   if (exclude.empty() == false) {
944      for (vector<RPackage *>::iterator I = exclude.begin();
945           I != exclude.end(); I++)
946         state.Ignore(*(*I)->package());
947   }
948
949   pkgDepCache &Cache = *_cache->deps();
950   for (unsigned int i = 0; i != _packages.size(); i++) {
951      RPackage *RPkg = _packages[i];
952      pkgCache::PkgIterator &Pkg = *RPkg->package();
953      pkgDepCache::StateCache & PkgState = Cache[Pkg];
954      if (PkgState.Mode != state[Pkg].Mode && state.Ignored(Pkg) == false) {
955         if (PkgState.Upgrade()) {
956            toUpgrade.push_back(RPkg);
957            changed = true;
958         } else if (PkgState.NewInstall()) {
959            toInstall.push_back(RPkg);
960            changed = true;
961         } else if (PkgState.Install()) {
962             toReInstall.push_back(RPkg);
963             changed = true;
964         } else if (PkgState.Delete()) {
965            toRemove.push_back(RPkg);
966            changed = true;
967         } else if (PkgState.Keep()) {
968            toKeep.push_back(RPkg);
969            changed = true;
970         } else if (PkgState.Downgrade()) {
971            toDowngrade.push_back(RPkg);
972            changed = true;
973         }
974      }
975   }
976
977   if (sorted == true && changed == true) {
978      if (toKeep.empty() == false)
979         sort(toKeep.begin(), toKeep.end(), bla());
980      if (toInstall.empty() == false)
981         sort(toInstall.begin(), toInstall.end(), bla());
982      if (toReInstall.empty() == false)
983         sort(toReInstall.begin(), toReInstall.end(), bla());
984      if (toUpgrade.empty() == false)
985         sort(toUpgrade.begin(), toUpgrade.end(), bla());
986      if (toRemove.empty() == false)
987         sort(toRemove.begin(), toRemove.end(), bla());
988      if (toDowngrade.empty() == false)
989         sort(toDowngrade.begin(), toDowngrade.end(), bla());
990   }
991
992   return changed;
993}
994#else
995void RPackageLister::saveState(RPackageLister::pkgState &state)
996{
997   //cout << "RPackageLister::saveState()" << endl;
998   state.clear();
999   state.reserve(_packages.size());
1000   for (unsigned i = 0; i < _packages.size(); i++) {
1001      state.push_back(_packages[i]->getFlags());
1002   }
1003}
1004
1005void RPackageLister::restoreState(RPackageLister::pkgState &state)
1006{
1007   pkgDepCache *deps = _cache->deps();
1008
1009   for (unsigned i = 0; i < _packages.size(); i++) {
1010      RPackage *pkg = _packages[i];
1011      int flags = pkg->getFlags();
1012      int oldflags = state[i];
1013
1014      if (oldflags != flags) {
1015         if (oldflags & RPackage::FReInstall) {
1016            deps->MarkInstall(*(pkg->package()), true);
1017            deps->SetReInstall(*(pkg->package()), false);
1018         } else if (oldflags & RPackage::FInstall) {
1019            deps->MarkInstall(*(pkg->package()), true);
1020         } else if (oldflags & RPackage::FRemove) {
1021            deps->MarkDelete(*(pkg->package()), oldflags & RPackage::FPurge);
1022         } else if (oldflags & RPackage::FKeep) {
1023            deps->MarkKeep(*(pkg->package()), false);
1024         }
1025      }
1026   }
1027   notifyChange(NULL);
1028}
1029
1030
1031bool RPackageLister::getStateChanges(RPackageLister::pkgState &state,
1032                                     vector<RPackage *> &toKeep,
1033                                     vector<RPackage *> &toInstall,
1034                                     vector<RPackage *> &toReInstall,
1035                                     vector<RPackage *> &toUpgrade,
1036                                     vector<RPackage *> &toRemove,
1037                                     vector<RPackage *> &toDowngrade,
1038                                     vector<RPackage *> &notAuthenticated,
1039                                     vector<RPackage *> &exclude,
1040                                     bool sorted)
1041{
1042   bool changed = false;
1043
1044   for (unsigned i = 0; i < _packages.size(); i++) {
1045      int flags = _packages[i]->getFlags();
1046
1047      if (state[i] != flags) {
1048
1049         // These flags will never be set together.
1050         int status = flags & (RPackage::FHeld |
1051                               RPackage::FNewInstall |
1052                               RPackage::FReInstall |
1053                               RPackage::FUpgrade |
1054                               RPackage::FDowngrade |
1055                               RPackage::FRemove);
1056
1057         // add packages to the not-authenticated list if they are going to
1058         // be installed in some way
1059         switch(status) {
1060         case RPackage::FNewInstall:
1061         case RPackage::FReInstall:
1062         case RPackage::FUpgrade:
1063         case RPackage::FDowngrade:
1064            if(!_packages[i]->isTrusted()) {
1065               notAuthenticated.push_back(_packages[i]);
1066               changed = true;
1067            }
1068         }
1069         
1070         if(find(exclude.begin(), exclude.end(),_packages[i]) != exclude.end())
1071            continue;
1072
1073         switch (status) {
1074            case RPackage::FNewInstall:
1075               toInstall.push_back(_packages[i]);
1076               changed = true;
1077               break;
1078
1079            case RPackage::FReInstall:
1080               toReInstall.push_back(_packages[i]);
1081               changed = true;
1082               break;
1083
1084            case RPackage::FUpgrade:
1085               toUpgrade.push_back(_packages[i]);
1086               changed = true;
1087               break;
1088
1089            case RPackage::FRemove:
1090               toRemove.push_back(_packages[i]);
1091               changed = true;
1092               break;
1093
1094            case RPackage::FKeep:
1095               toKeep.push_back(_packages[i]);
1096               changed = true;
1097               break;
1098
1099            case RPackage::FDowngrade:
1100               toDowngrade.push_back(_packages[i]);
1101               changed = true;
1102               break;
1103         }
1104      }
1105   }
1106
1107   if (sorted == true && changed == true) {
1108      if (toKeep.empty() == false)
1109         sort(toKeep.begin(), toKeep.end(), bla());
1110      if (toInstall.empty() == false)
1111         sort(toInstall.begin(), toInstall.end(), bla());
1112      if (toReInstall.empty() == false)
1113         sort(toReInstall.begin(), toReInstall.end(), bla());
1114      if (toUpgrade.empty() == false)
1115         sort(toUpgrade.begin(), toUpgrade.end(), bla());
1116      if (toRemove.empty() == false)
1117         sort(toRemove.begin(), toRemove.end(), bla());
1118      if (toDowngrade.empty() == false)
1119         sort(toDowngrade.begin(), toDowngrade.end(), bla());
1120
1121   }
1122
1123   return changed;
1124}
1125#endif
1126
1127void RPackageLister::getDetailedSummary(vector<RPackage *> &held,
1128                                        vector<RPackage *> &kept,
1129                                        vector<RPackage *> &essential,
1130                                        vector<RPackage *> &toInstall,
1131                                        vector<RPackage *> &toReInstall,
1132                                        vector<RPackage *> &toUpgrade,
1133                                        vector<RPackage *> &toRemove,
1134                                        vector<RPackage *> &toPurge,
1135                                        vector<RPackage *> &toDowngrade,
1136#ifdef WITH_APT_AUTH
1137                                        vector<string> &notAuthenticated,
1138#endif
1139                                        double &sizeChange)
1140{
1141   pkgDepCache *deps = _cache->deps();
1142
1143   for (unsigned int i = 0; i < _packages.size(); i++) {
1144      RPackage *pkg = _packages[i];
1145      int flags = pkg->getFlags();
1146
1147      // These flags will never be set together.
1148      int status = flags & (RPackage::FKeep |
1149                            RPackage::FNewInstall |
1150                            RPackage::FReInstall |
1151                            RPackage::FUpgrade |
1152                            RPackage::FDowngrade |
1153                            RPackage::FRemove);
1154
1155      switch (status) {
1156
1157         case RPackage::FKeep:
1158            if (flags & RPackage::FHeld)
1159               held.push_back(pkg);
1160            else
1161               kept.push_back(pkg);
1162            break;
1163
1164         case RPackage::FNewInstall:
1165            toInstall.push_back(pkg);
1166            break;
1167
1168         case RPackage::FReInstall:
1169            toReInstall.push_back(pkg);
1170            break;
1171
1172         case RPackage::FUpgrade:
1173            toUpgrade.push_back(pkg);
1174            break;
1175
1176         case RPackage::FDowngrade:
1177            toDowngrade.push_back(pkg);
1178            break;
1179
1180         case RPackage::FRemove:
1181            if (flags & RPackage::FImportant)
1182               essential.push_back(pkg);
1183            else if(flags & RPackage::FPurge)
1184               toPurge.push_back(pkg);
1185            else
1186               toRemove.push_back(pkg);
1187            break;
1188      }
1189   }
1190
1191   sort(kept.begin(), kept.end(), bla());
1192   sort(toInstall.begin(), toInstall.end(), bla());
1193   sort(toReInstall.begin(), toReInstall.end(), bla());
1194   sort(toUpgrade.begin(), toUpgrade.end(), bla());
1195   sort(essential.begin(), essential.end(), bla());
1196   sort(toRemove.begin(), toRemove.end(), bla());
1197   sort(toPurge.begin(), toPurge.end(), bla());
1198   sort(held.begin(), held.end(), bla());
1199#ifdef WITH_APT_AUTH
1200   pkgAcquire Fetcher(NULL);
1201   pkgPackageManager *PM = _system->CreatePM(_cache->deps());
1202   if (!PM->GetArchives(&Fetcher, _cache->list(), _records))
1203      return;
1204   for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); 
1205        I < Fetcher.ItemsEnd(); ++I) {
1206      if (!(*I)->IsTrusted()) {
1207         notAuthenticated.push_back(string((*I)->ShortDesc()));
1208      }
1209   }
1210#else
1211   sizeChange = deps->UsrSize();
1212#endif
1213}
1214
1215bool RPackageLister::updateCache(pkgAcquireStatus *status, string &error)
1216{
1217   assert(_cache->list() != NULL);
1218   // Get the source list
1219   //pkgSourceList List;
1220#ifdef HAVE_RPM
1221   _cache->list()->ReadMainList();
1222#else
1223   _cache->list()->Read(_config->FindFile("Dir::Etc::sourcelist"));
1224#endif
1225   // Lock the list directory
1226   FileFd Lock;
1227   if (_config->FindB("Debug::NoLocking", false) == false) {
1228      Lock.Fd(GetLock(_config->FindDir("Dir::State::Lists") + "lock"));
1229      //cout << "lock in : " << _config->FindDir("Dir::State::Lists") << endl;
1230      if (_error->PendingError() == true)
1231         return _error->Error(_("Unable to lock the list directory"));
1232   }
1233
1234   _updating = true;
1235
1236   // Create the download object
1237   pkgAcquire Fetcher(status);
1238
1239   bool Failed = false;
1240
1241#if HAVE_RPM
1242   if (_cache->list()->GetReleases(&Fetcher) == false)
1243      return false;
1244   Fetcher.Run();
1245   for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin();
1246        I != Fetcher.ItemsEnd(); I++) {
1247      if ((*I)->Status == pkgAcquire::Item::StatDone)
1248         continue;
1249      (*I)->Finished();
1250      Failed = true;
1251   }
1252   if (Failed == true)
1253      _error->Warning(_("Release files for some repositories could not be "
1254                        "retrieved or authenticated. Such repositories are "
1255                        "being ignored."));
1256#endif /* HAVE_RPM */
1257
1258   if (!_cache->list()->GetIndexes(&Fetcher))
1259      return false;
1260
1261   // Run it
1262   if (Fetcher.Run() == pkgAcquire::Failed)
1263      return false;
1264
1265
1266
1267   //bool AuthFailed = false;
1268   Failed = false;
1269   string failedURI;/* = _("Some index files failed to download, they "
1270                        "have been ignored, or old ones used instead:\n");
1271                    */
1272   for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin();
1273        I != Fetcher.ItemsEnd(); I++) {
1274      if ((*I)->Status == pkgAcquire::Item::StatDone)
1275         continue;
1276      (*I)->Finished();
1277      if((*I)->ErrorText.empty())
1278         failedURI += (*I)->DescURI() + "\n";
1279      else
1280         failedURI += (*I)->DescURI() + ": " + (*I)->ErrorText + "\n";
1281      Failed = true;
1282   }
1283
1284   // Clean out any old list files
1285   if (_config->FindB("APT::Get::List-Cleanup", true) == true) {
1286      if (Fetcher.Clean(_config->FindDir("Dir::State::lists")) == false ||
1287          Fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/") ==
1288          false)
1289         return false;
1290   }
1291   if (Failed == true) {
1292      //cout << failedURI << endl;
1293      error = failedURI;
1294      //_error->Error(failedURI.c_str());
1295      return false; 
1296   }
1297   return true;
1298}
1299
1300
1301
1302bool RPackageLister::commitChanges(pkgAcquireStatus *status,
1303                                   RInstallProgress *iprog)
1304{
1305   FileFd lock;
1306   int numPackages = 0;
1307   int numPackagesTotal;
1308   bool Ret = true;
1309
1310   _updating = true;
1311
1312   if (!lockPackageCache(lock))
1313      return false;
1314
1315   if(_config->FindB("Synaptic::Log::Changes",true))
1316      makeCommitLog();
1317
1318   pkgAcquire fetcher(status);
1319
1320   assert(_cache->list() != NULL);
1321   // Read the source list
1322#ifdef HAVE_RPM
1323   if (_cache->list()->ReadMainList() == false) {
1324      _userDialog->
1325         warning(_("Ignoring invalid record(s) in sources.list file!"));
1326   }
1327#else
1328   if (_cache->list()->Read(_config->FindFile("Dir::Etc::sourcelist")) ==
1329       false) {
1330      _userDialog->
1331         warning(_("Ignoring invalid record(s) in sources.list file!"));
1332   }
1333#endif
1334
1335   pkgPackageManager *PM;
1336   PM = _system->CreatePM(_cache->deps());
1337   RPackageManager *rPM = new RPackageManager(PM);
1338
1339   if (!PM->GetArchives(&fetcher, _cache->list(), _records) ||
1340       _error->PendingError())
1341      goto gave_wood;
1342
1343   // ripped from apt-get
1344   while (1) {
1345      bool Transient = false;
1346
1347      if (fetcher.Run() == pkgAcquire::Failed)
1348         goto gave_wood;
1349
1350      string serverError;
1351
1352      numPackagesTotal = 0;
1353
1354      // Print out errors
1355      bool Failed = false;
1356      for (pkgAcquire::ItemIterator I = fetcher.ItemsBegin();
1357           I != fetcher.ItemsEnd(); I++) {
1358
1359         numPackagesTotal += 1;
1360         
1361         if ((*I)->Status == pkgAcquire::Item::StatDone && (*I)->Complete) {
1362            numPackages += 1;
1363            continue;
1364         }
1365
1366         if ((*I)->Status == pkgAcquire::Item::StatIdle) {
1367            Transient = true;
1368            continue;
1369         }
1370
1371         (*I)->Finished();
1372
1373         string errm = (*I)->ErrorText;
1374         ostringstream tmp;
1375    // TRANSLATORS: Error message after a failed download.
1376    //              The first %s is the URL and the second
1377    //              one is a detailed error message that
1378    //              is provided by apt
1379         ioprintf(tmp, _("Failed to fetch %s\n  %s\n\n"), 
1380                  (*I)->DescURI().c_str(), errm.c_str());
1381
1382         serverError = getServerErrorMessage(errm);
1383
1384         _error->Warning(tmp.str().c_str());
1385         Failed = true;
1386      }
1387
1388      if (_config->FindB("Volatile::Download-Only", false)) {
1389         _updating = false;
1390         return !Failed;
1391      }
1392
1393      if (Failed) {
1394         string message;
1395
1396         if (Transient)
1397            goto gave_wood;
1398
1399         if (numPackages == 0)
1400             goto gave_wood;
1401
1402         message =
1403            _("Some of the packages could not be retrieved from the server(s).\n");
1404         if (!serverError.empty())
1405            message += "(" + serverError + ")\n";
1406         message += _("Do you want to continue, ignoring these packages?");
1407
1408         if (!_userDialog->confirm(message.c_str()))
1409            goto gave_wood;
1410      }
1411      // Try to deal with missing package files
1412      if (Failed == true && PM->FixMissing() == false) {
1413         _error->Error(_("Unable to correct missing packages"));
1414         goto gave_wood;
1415      }
1416      // need this so that we first fetch everything and then install (for CDs)
1417      if (Transient == false
1418          || _config->FindB("Acquire::CDROM::Copy-All", false) == false) {
1419
1420         if (Transient == true) {
1421            // We must do that in a system independent way. */
1422            _config->Set("RPM::Install-Options::", "--nodeps");
1423         }
1424
1425         _cache->releaseLock();
1426         pkgPackageManager::OrderResult Res =
1427                   iprog->start(rPM, numPackages, numPackagesTotal);
1428         if (Res == pkgPackageManager::Failed || _error->PendingError()) {
1429            if (Transient == false)
1430               goto gave_wood;
1431            Ret = false;
1432            // TODO: We must not discard errors here. The right
1433            //       solution is to use an "error stack", as
1434            //       implemented in apt-rpm.
1435            //_error->DumpErrors();
1436            _error->Discard();
1437         }
1438         if (Res == pkgPackageManager::Completed)
1439            break;
1440
1441         numPackages = 0;
1442
1443         _cache->lock();
1444      }
1445      // Reload the fetcher object and loop again for media swapping
1446      fetcher.Shutdown();
1447
1448      if (!PM->GetArchives(&fetcher, _cache->list(), _records))
1449         goto gave_wood;
1450   }
1451
1452   //cout << _("Finished.")<<endl;
1453
1454
1455   // erase downloaded packages
1456   cleanPackageCache();
1457
1458   if(_config->FindB("Synaptic::Log::Changes",true))
1459      writeCommitLog();
1460
1461   delete PM;
1462   delete rPM;
1463   return Ret;
1464
1465 gave_wood:
1466   delete PM;
1467   delete rPM;
1468   return false;
1469}
1470
1471void RPackageLister::writeCommitLog()
1472{
1473   struct tm *t = localtime(&_logTime);
1474   ostringstream tmp;
1475   ioprintf(tmp, "%.4i-%.2i-%.2i.%.2i%.2i%.2i.log", 1900+t->tm_year, 
1476            t->tm_mon+1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
1477
1478   string logfile = RLogDir() + tmp.str();
1479   FILE *f = fopen(logfile.c_str(),"w+");
1480   if(f == NULL) {
1481      _error->Error("Failed to write commit log");
1482      return;
1483   }
1484   fputs(_logEntry.c_str(), f);
1485   fclose(f);
1486
1487}
1488
1489void RPackageLister::cleanCommitLog()
1490{
1491   int maxKeep = _config->FindI("Synaptic::delHistory", -1);
1492   //cout << "RPackageLister::cleanCommitLog(): " << maxKeep << endl;
1493   if(maxKeep < 0)
1494      return;
1495   
1496   string logfile, entry;
1497   struct stat buf;
1498   struct dirent *dent;
1499   time_t now = time(NULL);
1500   DIR *dir = opendir(RLogDir().c_str());
1501   while((dent=readdir(dir)) != NULL) {
1502      entry = string(dent->d_name);
1503      if(logfile == "." || logfile == "..")
1504         continue;
1505      logfile = RLogDir()+entry;
1506      if(stat(logfile.c_str(), &buf) != 0) {
1507         cerr << "logfile: " << logfile << endl;
1508         perror("cleanCommitLog(), stat: ");
1509         continue;
1510      }
1511      if((buf.st_mtime+(60*60*24*maxKeep)) < now) {
1512//       cout << "older than " << maxKeep << " days: " << logfile << endl;
1513//       cout << "now: " << now
1514//            << " ctime: " << buf.st_mtime+(60*60*24*maxKeep) << endl;
1515         unlink(logfile.c_str());
1516      }
1517
1518   }
1519   closedir(dir);
1520}
1521
1522void RPackageLister::makeCommitLog()
1523{
1524   time(&_logTime);
1525   _logEntry = string("Commit Log for ") + string(ctime(&_logTime)) + string("\n");
1526   _logEntry.reserve(2*8192); // make it big by default
1527
1528   vector<RPackage *> held;
1529   vector<RPackage *> kept;
1530   vector<RPackage *> essential;
1531   vector<RPackage *> toInstall;
1532   vector<RPackage *> toReInstall;
1533   vector<RPackage *> toUpgrade;
1534   vector<RPackage *> toRemove;
1535   vector<RPackage *> toPurge;
1536   vector<RPackage *> toDowngrade;
1537#ifdef WITH_APT_AUTH
1538   vector<string> notAuthenticated;
1539#endif
1540
1541   double sizeChange;
1542
1543   getDetailedSummary(held, kept, essential,
1544                      toInstall,toReInstall,toUpgrade, 
1545                      toRemove, toPurge, toDowngrade, 
1546#ifdef WITH_APT_AUTH
1547                      notAuthenticated,
1548#endif
1549                      sizeChange);
1550
1551   if(essential.size() > 0) {
1552      //_logEntry += _("\n<b>Removed the following ESSENTIAL packages:</b>\n");
1553      _logEntry += _("\nRemoved the following ESSENTIAL packages:\n");
1554      for (vector<RPackage *>::const_iterator p = essential.begin();
1555           p != essential.end(); p++) {
1556         _logEntry += (*p)->name() + string("\n");
1557      }
1558   }
1559   
1560   if(toDowngrade.size() > 0) {
1561      //_logEntry += _("\n<b>Downgraded the following packages:</b>\n");
1562      _logEntry += _("\nDowngraded the following packages:\n");
1563      for (vector<RPackage *>::const_iterator p = toDowngrade.begin();
1564           p != toDowngrade.end(); p++) {
1565         _logEntry += (*p)->name() + string("\n");
1566      }
1567   }
1568
1569   if(toPurge.size() > 0) {
1570      //_logEntry += _("\n<b>Completely removed the following packages:</b>\n");
1571      _logEntry += _("\nCompletely removed the following packages:\n");
1572      for (vector<RPackage *>::const_iterator p = toPurge.begin();
1573           p != toPurge.end(); p++) {
1574         _logEntry += (*p)->name() + string("\n");
1575      }
1576   }
1577
1578   if(toRemove.size() > 0) {
1579      //_logEntry += _("\n<b>Removed the following packages:</b>\n");
1580      _logEntry += _("\nRemoved the following packages:\n");
1581      for (vector<RPackage *>::const_iterator p = toRemove.begin();
1582           p != toRemove.end(); p++) {
1583         _logEntry += (*p)->name() + string("\n");
1584      }
1585   }
1586
1587   if(toUpgrade.size() > 0) {
1588      //_logEntry += _("\n<b>Upgraded the following packages:</b>\n");
1589      _logEntry += _("\nUpgraded the following packages:\n");
1590      for (vector<RPackage *>::const_iterator p = toUpgrade.begin();
1591           p != toUpgrade.end(); p++) {
1592         _logEntry += (*p)->name() + string(" (") + (*p)->installedVersion() 
1593            + string(")") + string(" to ") + (*p)->availableVersion() 
1594            + string("\n");
1595      }
1596   }
1597
1598   if(toInstall.size() > 0) {
1599      //_logEntry += _("\n<b>Installed the following packages:</b>\n");
1600      _logEntry += _("\nInstalled the following packages:\n");
1601      for (vector<RPackage *>::const_iterator p = toInstall.begin();
1602           p != toInstall.end(); p++) {
1603         _logEntry += (*p)->name() + string(" (") + (*p)->availableVersion() 
1604            + string(")") + string("\n");
1605      }
1606   }
1607
1608   if(toReInstall.size() > 0) {
1609      //_logEntry += _("\n<b>Reinstalled the following packages:</b>\n");
1610      _logEntry += _("\nReinstalled the following packages:\n");
1611      for (vector<RPackage*>::const_iterator p = toReInstall.begin(); 
1612           p != toReInstall.end(); p++) {
1613         _logEntry += (*p)->name() + string(" (") + (*p)->availableVersion() 
1614            + string(")") + string("\n");
1615      }
1616   }
1617}
1618
1619bool RPackageLister::lockPackageCache(FileFd &lock)
1620{
1621   // Lock the archive directory
1622
1623   if (_config->FindB("Debug::NoLocking", false) == false) {
1624      lock.Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
1625      //cout << "lock is: " << _config->FindDir("Dir::Cache::Archives") << endl;
1626      if (_error->PendingError() == true)
1627         return _error->Error(_("Unable to lock the download directory"));
1628   }
1629
1630   return true;
1631}
1632
1633
1634bool RPackageLister::cleanPackageCache(bool forceClean)
1635{
1636   FileFd lock;
1637
1638   if (_config->FindB("Synaptic::CleanCache", false) || forceClean) {
1639
1640      lockPackageCache(lock);
1641
1642      pkgAcquire Fetcher;
1643      Fetcher.Clean(_config->FindDir("Dir::Cache::archives"));
1644      Fetcher.Clean(_config->FindDir("Dir::Cache::archives") + "partial/");
1645   } else if (_config->FindB("Synaptic::AutoCleanCache", false)) {
1646
1647      lockPackageCache(lock);
1648
1649      pkgArchiveCleaner cleaner;
1650
1651      bool res;
1652
1653      res = cleaner.Go(_config->FindDir("Dir::Cache::archives"),
1654                       *_cache->deps());
1655
1656      if (!res)
1657         return false;
1658
1659      res = cleaner.Go(_config->FindDir("Dir::Cache::archives") + "partial/",
1660                       *_cache->deps());
1661
1662      if (!res)
1663         return false;
1664
1665   } else {
1666      // mvo: nothing?
1667   }
1668
1669   return true;
1670}
1671
1672
1673bool RPackageLister::writeSelections(ostream &out, bool fullState)
1674{
1675   for (unsigned i = 0; i < _packages.size(); i++) {
1676      int flags = _packages[i]->getFlags();
1677
1678      // Full state saves all installed packages.
1679      if (flags & RPackage::FInstall ||
1680          fullState && (flags &RPackage::FInstalled)) {
1681         out << _packages[i]->name() << "\t\tinstall" << endl;
1682      } else if (flags & RPackage::FRemove) {
1683         out << _packages[i]->name() << "\t\tdeinstall" << endl;
1684      }
1685   }
1686
1687   return true;
1688}
1689
1690bool RPackageLister::readSelections(istream &in)
1691{
1692   char Buffer[300];
1693   int CurLine = 0;
1694   enum Action {
1695      ACTION_INSTALL,
1696      ACTION_UNINSTALL
1697   };
1698   map<string, int> actionMap;
1699
1700   while (in.eof() == false) {
1701      in.getline(Buffer, sizeof(Buffer));
1702      CurLine++;
1703
1704      if (in.fail() && !in.eof())
1705         return _error->Error(_("Line %u too long in markings file."),
1706                              CurLine);
1707
1708      _strtabexpand(Buffer, sizeof(Buffer));
1709      _strstrip(Buffer);
1710
1711      const char *C = Buffer;
1712
1713      // Comment or blank
1714      if (C[0] == '#' || C[0] == 0)
1715         continue;
1716
1717      string PkgName;
1718      if (ParseQuoteWord(C, PkgName) == false)
1719         return _error->Error(_("Malformed line %u in markings file"),
1720                              CurLine);
1721      string Action;
1722      if (ParseQuoteWord(C, Action) == false)
1723         return _error->Error(_("Malformed line %u in markings file"),
1724                              CurLine);
1725
1726      if (Action[0] == 'i') {
1727         actionMap[PkgName] = ACTION_INSTALL;
1728      } else if (Action[0] == 'u' || Action[0] == 'd') {
1729         actionMap[PkgName] = ACTION_UNINSTALL;
1730      }
1731   }
1732
1733   if (actionMap.empty() == false) {
1734      int Size = actionMap.size();
1735      _progMeter->OverallProgress(0, Size, Size, _("Setting markings..."));
1736      _progMeter->SubProgress(Size);
1737      pkgDepCache &Cache = *_cache->deps();
1738      pkgProblemResolver Fix(&Cache);
1739      // XXX Should protect whatever is already selected in the cache.
1740      pkgCache::PkgIterator Pkg;
1741      int Pos = 0;
1742      for (map<string, int>::const_iterator I = actionMap.begin();
1743           I != actionMap.end(); I++) {
1744         Pkg = Cache.FindPkg((*I).first);
1745         if (Pkg.end() == false) {
1746            Fix.Clear(Pkg);
1747            Fix.Protect(Pkg);
1748            switch ((*I).second) {
1749               case ACTION_INSTALL:
1750                  if(_config->FindB("Volatile::SetSelectionsNoFix","false"))
1751                     Cache.MarkInstall(Pkg, false);
1752                  else
1753                     Cache.MarkInstall(Pkg, true);
1754                  break;
1755
1756               case ACTION_UNINSTALL:
1757                  Fix.Remove(Pkg);
1758                  Cache.MarkDelete(Pkg, false);
1759                  break;
1760            }
1761         }
1762         if ((Pos++) % 5 == 0)
1763            _progMeter->Progress(Pos);
1764      }
1765#ifdef WITH_LUA
1766      _lua->SetDepCache(_cache->deps());
1767      _lua->RunScripts("Scripts::Synaptic::ReadSelections", false);
1768      _lua->ResetCaches();
1769#endif
1770      _progMeter->Done();
1771      Fix.InstallProtect();
1772      Fix.Resolve(true);
1773   }
1774
1775   return true;
1776}
1777
1778// vim:ts=3:sw=3:et
Note: See TracBrowser for help on using the repository browser.