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

Revision 280, 35.1 KB checked in by yasumichi, 15 years ago (diff)

first import

Line 
1/* rpackage.cc - wrapper for accessing package information
2 *
3 * Copyright (c) 2000-2003 Conectiva S/A
4 *               2002 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 Gnome APT
10 *   Copyright (C) 1998 Havoc Pennington <hp@pobox.com>
11 *
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License as
15 * published by the Free Software Foundation; either version 2 of the
16 * License, or (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
26 * USA
27 */
28
29
30#include "config.h"
31
32#include "rpackage.h"
33#include "rpackagelister.h"
34#include "pkg_acqfile.h"
35
36#include "i18n.h"
37
38#include <map>
39#include <algorithm>
40#include <fstream>
41#include <cstdio>
42#include <unistd.h>
43#include <sys/stat.h>
44#include <sys/types.h>
45#include <assert.h>
46#include <sstream>
47
48
49
50#include <apt-pkg/pkgrecords.h>
51#include <apt-pkg/depcache.h>
52#include <apt-pkg/srcrecords.h>
53#include <apt-pkg/algorithms.h>
54#include <apt-pkg/error.h>
55#include <apt-pkg/configuration.h>
56#include <apt-pkg/tagfile.h>
57#include <apt-pkg/policy.h>
58#include <apt-pkg/sptr.h>
59#include <apt-pkg/strutl.h>
60#include <apt-pkg/cacheiterators.h>
61#include <apt-pkg/pkgcache.h>
62#include <apt-pkg/versionmatch.h>
63#include <apt-pkg/version.h>
64#include <apt-pkg/policy.h>
65
66#ifdef WITH_LUA
67#include <apt-pkg/luaiface.h>
68#endif
69
70#include "raptoptions.h"
71
72
73static char descrBuffer[8192];
74
75static char *parseDescription(string descr);
76
77
78RPackage::RPackage(RPackageLister *lister, pkgDepCache *depcache,
79                   pkgRecords *records, pkgCache::PkgIterator &pkg)
80: _lister(lister), _records(records), _depcache(depcache),
81_notify(true), _boolFlags(0)
82{
83   _package = new pkgCache::PkgIterator(pkg);
84
85   pkgDepCache::StateCache & State = (*_depcache)[*_package];
86   if (State.CandVersion != NULL)
87      _defaultCandVer = State.CandVersion;
88}
89
90
91RPackage::~RPackage()
92{
93   delete _package;
94}
95
96#if 0
97void RPackage::addVirtualPackage(pkgCache::PkgIterator dep)
98{
99   _virtualPackages.push_back(dep);
100   _provides.push_back(dep.Name());
101}
102#endif
103
104const char *RPackage::section()
105{
106   const char *s = _package->Section();
107   if (s != NULL)
108      return s;
109   else
110      return _("Unknown");
111}
112
113const char *RPackage::srcPackage()
114{
115   static string _srcPkg;
116
117   pkgCache::VerIterator ver = _package->VersionList();
118   pkgRecords::Parser &rec=_records->Lookup(ver.FileList());
119   _srcPkg = rec.SourcePkg().empty()?name():rec.SourcePkg();
120 
121   return _srcPkg.c_str();;
122}
123
124
125const char *RPackage::summary()
126{
127   static string _summary;
128
129   pkgCache::VerIterator ver = _package->VersionList();
130
131   if (!ver.end()) {
132      pkgRecords::Parser & parser = _records->Lookup(ver.FileList());
133
134      _summary = parser.ShortDesc();
135      return _summary.c_str();
136   }
137   return "";
138}
139
140
141const char *RPackage::maintainer()
142{
143   static string _maintainer;
144   
145   pkgCache::VerIterator ver = _package->VersionList();
146
147   if (!ver.end()) {
148      pkgRecords::Parser & parser = _records->Lookup(ver.FileList());
149      _maintainer = parser.Maintainer();
150      return _maintainer.c_str();
151   }
152   return "";
153}
154
155
156const char *RPackage::vendor()
157{
158   return "dunno";
159}
160
161const char *RPackage::installedVersion()
162{
163   if ((*_package)->CurrentVer == 0)
164      return NULL;
165   return _package->CurrentVer().VerStr();
166}
167
168const char *RPackage::availableVersion()
169{
170   pkgDepCache::StateCache & State = (*_depcache)[*_package];
171   if (State.CandidateVer == 0)
172      return NULL;
173   return State.CandidateVerIter(*_depcache).VerStr();
174}
175
176const char *RPackage::priority()
177{
178   pkgCache::VerIterator ver = _package->VersionList();
179
180   if (ver != 0)
181      return ver.PriorityType();
182   else
183      return NULL;
184}
185
186#ifndef HAVE_RPM
187const char *RPackage::installedFiles()
188{
189   static string filelist;
190   string s;
191
192   filelist.erase(filelist.begin(), filelist.end());
193
194   string f = "/var/lib/dpkg/info/" + string(name()) + ".list";
195   if (FileExists(f)) {
196      ifstream in(f.c_str());
197      if (!in != 0)
198         return "";
199      while (in.eof() == false) {
200         getline(in, s);
201         filelist += s + "\n";
202      }
203
204      in >> filelist;
205      return filelist.c_str();
206   }
207   filelist = _("The list of installed files is only available for installed packages");
208
209   return filelist.c_str();
210}
211#else
212const char *RPackage::installedFiles()
213{
214   return "";
215}
216#endif
217
218
219const char *RPackage::description()
220{
221   static string _description;
222
223   pkgCache::VerIterator ver = _package->VersionList();
224
225   if (!ver.end()) {
226      pkgRecords::Parser & parser = _records->Lookup(ver.FileList());
227      _description = parseDescription(parser.LongDesc());
228      return _description.c_str();
229   } else {
230      return "";
231   }
232}
233
234long RPackage::installedSize()
235{
236   pkgCache::VerIterator ver = _package->CurrentVer();
237
238   if (!ver.end())
239      return ver->InstalledSize;
240   else
241      return -1;
242}
243
244long RPackage::availableInstalledSize()
245{
246   pkgDepCache::StateCache & State = (*_depcache)[*_package];
247   if (State.CandidateVer == 0)
248      return -1;
249   return State.CandidateVerIter(*_depcache)->InstalledSize;
250}
251
252long RPackage::availablePackageSize()
253{
254   pkgDepCache::StateCache & State = (*_depcache)[*_package];
255   if (State.CandidateVer == 0)
256      return -1;
257   return State.CandidateVerIter(*_depcache)->Size;
258}
259
260int RPackage::getFlags()
261{
262   int flags = 0;
263
264   pkgDepCache::StateCache &state = (*_depcache)[*_package];
265   pkgCache::VerIterator ver = _package->CurrentVer();
266
267   if (state.Install())
268      flags |= FInstall;
269
270   if (state.iFlags & pkgDepCache::ReInstall) {
271      flags |= FReInstall;
272   } else if (state.NewInstall()) { // Order matters here.
273      flags |= FNewInstall;
274   } else if (state.Upgrade()) {
275      flags |= FUpgrade;
276   } else if (state.Downgrade()) {
277      flags |= FDowngrade;
278   } else if (state.Delete()) {
279      flags |= FRemove;
280      if (state.iFlags & pkgDepCache::Purge)
281         flags |= FPurge;
282   } else if (state.Keep()) {
283      flags |= FKeep;
284   }
285
286   if (!ver.end()) {
287      flags |= FInstalled;
288
289      if (state.Upgradable() && state.CandidateVer != NULL) {
290         flags |= FOutdated;
291         if (state.Keep())
292            flags |= FHeld;
293      }
294
295      if (state.Downgrade())
296         flags |= FDowngrade;
297   }
298
299   if (state.NowBroken())
300      flags |= FNowBroken;
301
302   if (state.InstBroken())
303      flags |= FInstBroken;
304
305   if ((*_package)->Flags & (pkgCache::Flag::Important |
306                             pkgCache::Flag::Essential))
307      flags |= FImportant;
308
309   if ((*_package)->CurrentState == pkgCache::State::ConfigFiles)
310      flags |= FResidualConfig;
311
312   if (state.CandidateVer == 0 ||
313       !state.CandidateVerIter(*_depcache).Downloadable())
314      flags |= FNotInstallable;
315
316   return flags | _boolFlags;
317}
318
319#if 0
320bool RPackage::isWeakDep(pkgCache::DepIterator &dep)
321{
322   if (dep->Type != pkgCache::Dep::Suggests
323       && dep->Type != pkgCache::Dep::Recommends)
324      return false;
325   else
326      return true;
327}
328
329
330bool RPackage::enumWDeps(const char *&type, const char *&what,
331                         bool &satisfied)
332{
333   pkgCache::VerIterator ver;
334   pkgDepCache::StateCache & state = (*_depcache)[*_package];
335
336
337   if (state.Keep() || state.Held()) {
338      ver = (*_depcache)[*_package].InstVerIter(*_depcache);
339
340      if (ver.end())
341         ver = _package->VersionList();
342   } else {
343      ver = _package->VersionList();
344   }
345   if (ver.end())
346      return false;
347
348   _wdepI = ver.DependsList();
349   // uninitialized but doesn't matter, they just have to be equal
350   _wdepStart = _wdepEnd;
351
352   return nextWDeps(type, what, satisfied);
353}
354
355
356bool RPackage::nextWDeps(const char *&type, const char *&what,
357                         bool &satisfied)
358{
359   static char buffer[32];
360
361   while (1) {
362      if (_wdepStart == _wdepEnd) {
363         if (_wdepI.end())
364            return false;
365
366         _wdepI.GlobOr(_wdepStart, _wdepEnd);
367
368         snprintf(buffer, sizeof(buffer), "%s", _wdepEnd.DepType());
369      } else {
370         _wdepStart++;
371
372         snprintf(buffer, sizeof(buffer), "| %s", _wdepEnd.DepType());
373      }
374
375      satisfied = false;
376      if (!isWeakDep(_wdepEnd))
377         continue;
378
379      if (((*_depcache)[_wdepStart] & pkgDepCache::DepGInstall) ==
380          pkgDepCache::DepGInstall)
381         satisfied = true;
382
383      type = buffer;
384
385      pkgCache::PkgIterator depPkg = _wdepStart.TargetPkg();
386      what = depPkg.Name();
387
388      break;
389   }
390   return true;
391}
392#endif
393
394vector<DepInformation> RPackage::enumRDeps()
395{
396   vector<DepInformation> deps;
397   DepInformation dep;
398   pkgCache::VerIterator Cur;
399
400   for(pkgCache::DepIterator D = _package->RevDependsList(); D.end() != true; D++) {
401      // clear old values
402      dep.isOr=dep.isVirtual=false;
403      dep.name=dep.version=dep.versionComp=NULL;
404
405      // check target and or-depends status
406      pkgCache::PkgIterator Trg = D.TargetPkg();
407      if ((D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or) {
408         dep.version = _("or dependency");
409         dep.versionComp = "";
410      }
411
412      //FIXME: HACK ALARM, we need a "RDepends" type, so we use the last
413      // one in pkg-dep
414      dep.type = (pkgCache::Dep::DepType)(pkgCache::Dep::Obsoletes+1);
415      dep.name = D.ParentPkg().Name();
416
417      if(Trg->VersionList == 0)
418         dep.isVirtual=true;
419
420      deps.push_back(dep);
421   }
422   return deps;
423}
424
425#if 0
426bool RPackage::enumRDeps(const char *&dep, const char *&what)
427{
428   _rdepI = _package->RevDependsList();
429
430   _vpackI = 0;
431
432   return nextRDeps(dep, what);
433}
434
435
436bool RPackage::nextRDeps(const char *&dep, const char *&what)
437{
438   while (_rdepI.end()) {
439      if ((unsigned)_vpackI == _virtualPackages.size())
440         return false;
441
442      _rdepI = _virtualPackages[_vpackI].RevDependsList();
443      _vpackI++;
444   }
445   what = _rdepI.TargetPkg().Name();
446   dep = _rdepI.ParentPkg().Name();
447
448   _rdepI++;
449
450   return true;
451}
452#endif
453
454#if 0
455bool RPackage::enumAvailDeps(const char *&type, const char *&what,
456                             const char *&pkg, const char *&which,
457                             char *&summary, bool &satisfied)
458{
459   pkgCache::VerIterator ver;
460   //   pkgDepCache::StateCache & state = (*_depcache)[*_package];
461
462   //ver = _package->VersionList();
463   ver = (*_depcache)[*_package].CandidateVerIter(*_depcache);
464
465   if (ver.end())
466      return false;
467
468   _depI = ver.DependsList();
469   // uninitialized but doesn't matter, they just have to be equal   
470   _depStart = _depEnd;
471
472   return nextDeps(type, what, pkg, which, summary, satisfied);
473}
474
475
476vector<RPackage *> RPackage::getInstalledDeps()
477{
478   vector < RPackage *>deps;
479   pkgCache::VerIterator ver;
480
481   ver = (*_depcache)[*_package].InstVerIter(*_depcache);
482
483   if (ver.end())
484      ver = _package->VersionList();
485
486   if (ver.end())
487      return deps;
488
489   _depI = ver.DependsList();
490   // uninitialized but doesn't matter, they just have to be equal   
491
492   pkgCache::DepIterator depIter = _depI;
493   while (!depIter.end()) {
494      pkgCache::PkgIterator depPkg = depIter.TargetPkg();
495      string name = depPkg.Name();
496      deps.push_back(_lister->getPackage(name));
497      depIter++;
498   }
499
500   return deps;
501}
502
503#endif
504
505
506
507/* Mostly taken from apt-get.cc:ShowBroken() */
508string RPackage::showWhyInstBroken()
509{
510   pkgCache::DepIterator depI;
511   pkgCache::VerIterator Ver;
512   bool First = true;
513   ostringstream out;
514
515   pkgDepCache::StateCache & State = (*_depcache)[*_package];
516   Ver = State.CandidateVerIter(*_depcache);
517
518   // check if there is actually something to install
519   if (Ver == 0) {
520      ioprintf(out,
521               _
522               ("\nPackage %s has no available version, but exists in the database.\n"
523                "This typically means that the package was mentioned in a dependency and "
524                "never uploaded, has been obsoleted or is not available with the contents "
525                "of sources.list\n"), _package->Name());
526      return out.str();
527   }
528
529   for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false;) {
530      // Compute a single dependency element (glob or)
531      pkgCache::DepIterator Start;
532      pkgCache::DepIterator End;
533      D.GlobOr(Start, End);
534
535      if (_depcache->IsImportantDep(End) == false)
536         continue;
537
538      if (((*_depcache)[End] & pkgDepCache::DepGInstall) ==
539          pkgDepCache::DepGInstall)
540         continue;
541
542      bool FirstOr = true;
543      while (1) {
544         /* Show a summary of the target package if possible. In the case
545            of virtual packages we show nothing */
546         pkgCache::PkgIterator Targ = Start.TargetPkg();
547         if (Targ->ProvidesList == 0) {
548            ioprintf(out, " ");
549            pkgCache::VerIterator Ver =
550               (*_depcache)[Targ].InstVerIter(*_depcache);
551            // add minimal version information
552            string requiredVersion;
553            if(Start.TargetVer() != 0)
554               requiredVersion = "("+string(Start.CompType())+string(Start.TargetVer())+")";
555            if (Ver.end() == false) {
556               if (FirstOr == false)
557                  // TRANSLATORS: dependency error message, example:
558                  // "apt 0.5.4 but 0.5.3 is to be installed"
559                  ioprintf(out, _("\t%s %s but %s is to be installed"),
560                           Start.TargetPkg().Name(), requiredVersion.c_str(),
561                           Ver.VerStr());
562               else
563                  // TRANSLATORS: dependency error message, example:
564                  // "Depends: apt 0.5.4 but 0.5.3 is to be installed"
565                  ioprintf(out, _(" %s: %s %s but %s is to be installed"),
566                           End.DepType(), Start.TargetPkg().Name(),
567                           requiredVersion.c_str(), Ver.VerStr());
568            } else {
569               if ((*_depcache)[Targ].CandidateVerIter(*_depcache).end() ==
570                   true) {
571                  if (Targ->ProvidesList == 0)
572                     if (FirstOr == false)
573                        // TRANSLATORS: dependency error message, example:
574                        // "apt 0.5.4 but it is not installable"
575                        ioprintf(out, _("\t%s %s but it is not installable"),
576                                 Start.TargetPkg().Name(), 
577                                 requiredVersion.c_str());
578                     else
579                        // TRANSLATORS: dependency error message, example:
580                        // "Depends: apt 0.5.4  but it is not installable",
581                        ioprintf(out, "%s: %s %s but it is not installable",
582                                 End.DepType(), Start.TargetPkg().Name(),
583                                 requiredVersion.c_str());
584                  else if (FirstOr == false)
585                     // TRANSLATORS: dependency error message, example:
586                     // "apt but it is a virtual package"
587                     ioprintf(out, _("\t%s but it is a virtual package"),
588                              Start.TargetPkg().Name());
589                  else
590                     // TRANSLATORS: dependency error message, example:
591                     // "Depends: apt but it is a virtual package"
592                     ioprintf(out, _("%s: %s but it is a virtual package"),
593                              End.DepType(), Start.TargetPkg().Name());
594               } else if (FirstOr == false)
595                  // TRANSLATORS: dependency error message, example:
596                  // "apt but it is not going to be installed"
597                  ioprintf(out, _("\t%s but it is not going to be installed"),
598                           Start.TargetPkg().Name());
599               else
600                  // TRANSLATORS: dependency error message, example:
601                  // "Depends: apt but it is not going to be installed"
602                  ioprintf(out, _("%s: %s but it is not going to be installed"),
603                           End.DepType(), Start.TargetPkg().Name());
604            }
605         } else {
606            // virtual pkgs
607            if (FirstOr == false)
608               ioprintf(out, "\t%s", Start.TargetPkg().Name());
609            else
610               ioprintf(out, " %s: %s", End.DepType(),
611                        Start.TargetPkg().Name());
612            // Show a quick summary of the version requirements
613            if (Start.TargetVer() != 0)
614               ioprintf(out, " (%s %s)", Start.CompType(), Start.TargetVer());
615         }
616
617         First = false;
618         FirstOr = false;
619
620         if (Start != End)
621            ioprintf(out, _(" or"));
622         ioprintf(out, "\n");
623
624         if (Start == End)
625            break;
626         Start++;
627      }
628   }
629   return out.str();
630}
631
632
633vector<DepInformation> RPackage::enumDeps(bool useCanidateVersion)
634{
635   vector<DepInformation> deps;
636   DepInformation dep;
637   pkgCache::VerIterator Cur;
638
639   if(!useCanidateVersion)
640      Cur = (*_depcache)[*_package].InstVerIter(*_depcache);
641   if(useCanidateVersion || Cur.end())
642      Cur = (*_depcache)[*_package].CandidateVerIter(*_depcache);
643
644   // no information found
645   if(Cur.end())
646      return deps;
647
648   for(pkgCache::DepIterator D = Cur.DependsList(); D.end() != true; D++) {
649
650      // clear old values
651      dep.isOr=dep.isVirtual=dep.isSatisfied=false;
652      dep.name=dep.version=dep.versionComp=NULL;
653
654      // check target and or-depends status
655      pkgCache::PkgIterator Trg = D.TargetPkg();
656      if ((D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or)
657         dep.isOr=true;
658
659      // common information
660      dep.type = (pkgCache::Dep::DepType)D->Type;
661      dep.name = Trg.Name();
662
663      // satisfied
664      if (((*_depcache)[D] & pkgDepCache::DepGInstall) ==
665          pkgDepCache::DepGInstall)
666         dep.isSatisfied = true;
667      if (Trg->VersionList == 0) {
668         dep.isVirtual = true;
669      } else {
670         dep.version=D.TargetVer();
671         dep.versionComp=D.CompType();
672      }
673      deps.push_back(dep);
674   }
675
676   return deps;
677}
678
679bool RPackage::dependsOn(const char *pkgname)
680{
681   vector<DepInformation> deps = enumDeps();
682   for(unsigned int i=0;i<deps.size();i++)
683      if(strcmp(pkgname, deps[i].name) == 0)
684         return true;
685   return false;
686}
687
688#ifdef WITH_APT_AUTH
689bool RPackage::isTrusted()
690{
691   pkgCache::VerIterator Ver;
692   pkgDepCache::StateCache & State = (*_depcache)[*_package];
693   Ver = State.CandidateVerIter(*_depcache);
694   if (Ver == 0) {
695      cerr << "CanidateVer == 0" << endl;
696      return false;
697   }
698   pkgSourceList *Sources=_lister->getCache()->list();
699   for (pkgCache::VerFileIterator i = Ver.FileList(); i.end() == false; i++)
700   {
701      pkgIndexFile *Index;
702      if (Sources->FindIndex(i.File(),Index) == false)
703         continue;
704      if (_config->FindB("Debug::pkgAcquire::Auth", false))
705      {
706         std::cerr << "Checking index: " << Index->Describe()
707                   << "(Trusted=" << Index->IsTrusted() << ")\n";
708      }
709      if (Index->IsTrusted())
710         return true;
711   }
712   
713   return false;
714}
715#else
716// with apt-authentication we always trust that the package come from
717// a trusted source
718bool RPackage::isTrusted() 
719{ 
720   return true; 
721};
722#endif
723
724bool RPackage::wouldBreak()
725{
726   int flags = getFlags();
727   if ((flags & FRemove) || (!(flags & FInstalled) && (flags & FKeep)))
728      return false;
729   return flags & FInstBroken;
730}
731
732void RPackage::setNotify(bool flag)
733{
734   _notify = flag;
735}
736
737void RPackage::setKeep()
738{
739   _depcache->MarkKeep(*_package, false);
740   if (_notify)
741      _lister->notifyChange(this);
742   setReInstall(false);
743}
744
745
746void RPackage::setInstall()
747{
748   _depcache->MarkInstall(*_package, true);
749   pkgDepCache::StateCache & State = (*_depcache)[*_package];
750
751   // FIXME: can't we get rid of it here?
752   // if there is something wrong, try to fix it
753   if (!State.Install() || _depcache->BrokenCount() > 0) {
754      pkgProblemResolver Fix(_depcache);
755      Fix.Clear(*_package);
756      Fix.Protect(*_package);
757      Fix.Resolve(true);
758   }
759
760
761#ifdef WITH_LUA
762   _lua->SetDepCache(_depcache);
763   _lua->SetGlobal("package", ((pkgCache::Package *) * _package));
764   _lua->RunScripts("Scripts::Synaptic::SetInstall", true);
765   _lua->ResetGlobals();
766   _lua->ResetCaches();
767#endif
768
769   if (_notify)
770      _lister->notifyChange(this);
771}
772
773void RPackage::setReInstall(bool flag)
774{
775    _depcache->SetReInstall(*_package, flag);
776    if (_notify)
777        _lister->notifyChange(this);
778}
779
780
781void RPackage::setRemove(bool purge)
782{
783   pkgProblemResolver Fix(_depcache);
784
785   Fix.Clear(*_package);
786   Fix.Protect(*_package);
787   Fix.Remove(*_package);
788
789   Fix.InstallProtect();
790   Fix.Resolve(true);
791
792   _depcache->SetReInstall(*_package, false);
793   _depcache->MarkDelete(*_package, purge);
794
795   if (_notify)
796      _lister->notifyChange(this);
797}
798
799
800string RPackage::getChangelogFile(pkgAcquire *fetcher)
801{
802   string prefix;
803   string srcpkg = srcPackage();
804   string descr("Changelog for ");
805   descr+=name();
806
807   string src_section=section();
808   if(src_section.find('/')!=src_section.npos)
809      src_section=string(src_section, 0, src_section.find('/'));
810   else
811      src_section="main";
812
813   prefix+=srcpkg[0];
814   if(srcpkg.size()>3 && srcpkg[0]=='l' && srcpkg[1]=='i' && srcpkg[2]=='b')
815      prefix=std::string("lib")+srcpkg[3];
816
817   string verstr;
818   if(availableVersion() != NULL) 
819      verstr = availableVersion();
820   
821   if(verstr.find(':')!=verstr.npos)
822      verstr=string(verstr, verstr.find(':')+1);
823   char uri[512];
824   snprintf(uri,512,"http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog",
825                               src_section.c_str(),
826                               prefix.c_str(),
827                               srcpkg.c_str(),
828                               srcpkg.c_str(),
829                               verstr.c_str());
830
831   //cout << "uri is: " << uri << endl;
832
833   // no need to translate this, the changelog is in english anyway
834   string filename = RTmpDir()+"/tmp_cl";
835   ofstream out(filename.c_str());
836   out << "Failed to fetch the changelog for " << name() << endl;
837   out << "URI was: " << uri << endl;
838   out.close();
839   new pkgAcqFileSane(fetcher, uri, descr, name(), filename);
840
841   fetcher->Run();
842
843   return filename;
844}
845
846string RPackage::getCanidateOrigin()
847{
848   for(pkgCache::VerIterator Ver = _package->VersionList(); Ver.end() == false; Ver++) {
849      // we always take the first available version
850      pkgCache::VerFileIterator VF = Ver.FileList();
851      if(!VF.end()) {
852         return VF.File().Site();
853      }
854   }
855   return "";
856}
857
858
859void RPackage::setPinned(bool flag)
860{
861   struct stat stat_buf;
862
863   string File =RStateDir() + "/preferences";
864
865   _boolFlags = flag ? (_boolFlags | FPinned) : (_boolFlags & FPinned);
866
867   if (flag) {
868      // pkg already in pin-file
869      if (_roptions->getPackageLock(name()))
870         return;
871
872      // write to pin-file
873      ofstream out(File.c_str(), ios::app);
874      out << "Package: " << name() << endl;
875      // if the package is not installed, we pin it to the available version
876      // and prevent installation of this package this way
877      if(installedVersion() != NULL) 
878         out << "Pin: version " << installedVersion() << endl;
879      else
880         out << "Pin: version " << " 0.0 " << endl;
881      out << "Pin-Priority: "
882         << _config->FindI("Synaptic::DefaultPinPriority", 1001)
883         << endl << endl;
884   } else {
885      // delete package from pinning file
886      stat(File.c_str(), &stat_buf);
887      // create a tmp_pin file in the internal dir
888      string filename = RTmpDir()+"/tmp_pin";
889      FILE *out = fopen(filename.c_str(),"w");
890      if (out == NULL)
891         cerr << "error opening tmpfile: " << filename << endl;
892      FileFd Fd(File, FileFd::ReadOnly);
893      pkgTagFile TF(&Fd);
894      if (_error->PendingError() == true)
895         return;
896      pkgTagSection Tags;
897      while (TF.Step(Tags) == true) {
898         string Name = Tags.FindS("Package");
899         if (Name.empty() == true) {
900            _error->
901               Error(_
902                     ("Invalid record in the preferences file, no Package header"));
903            return;
904         }
905         if (Name != name()) {
906            TFRewriteData tfrd;
907            tfrd.Tag = 0;
908            tfrd.Rewrite = 0;
909            tfrd.NewTag = 0;
910            TFRewrite(out, Tags, TFRewritePackageOrder, &tfrd);
911            fprintf(out, "\n");
912         }
913      }
914      fflush(out);
915      rename(filename.c_str(), File.c_str());
916      chmod(File.c_str(), stat_buf.st_mode);
917      fclose(out);
918   }
919}
920
921
922// FIXME: this function is broken right now (and it never really wasn't :/
923bool RPackage::isShallowDependency(RPackage *pkg)
924{
925#if 0
926   pkgCache::DepIterator rdepI;
927
928   // check whether someone else depends on a virtual pkg of this
929   for (int i = -1; i < (int)pkg->_virtualPackages.size(); i++) {
930      if (i < 0) {
931         rdepI = pkg->_package->RevDependsList();
932      } else {
933         pkgCache::PkgIterator it = pkg->_virtualPackages[i];
934         rdepI = it.RevDependsList();
935      }
936
937      while (!rdepI.end()) {
938
939         // check whether the dependant is installed
940         if (rdepI.ParentPkg().CurrentVer().end()) {    // not installed
941            // XXX check whether its marked for install
942            rdepI++;
943            continue;
944         }
945         // check whether the dependant isn't the own package
946         if (rdepI.ParentPkg() == *_package) {
947            rdepI++;
948            continue;
949         }
950         // XXX should check for dependencies that depend on
951         // dependencies of the same package
952
953         return false;
954      }
955   }
956
957#endif
958   return true;
959}
960
961// format: first version, second archives
962vector<pair<string, string> > RPackage::getAvailableVersions()
963{
964   string VerTag;
965   vector<pair<string, string> > versions;
966
967   // Get available Versions.
968   for (pkgCache::VerIterator Ver = _package->VersionList();
969        Ver.end() == false; Ver++) {
970
971      // We always take the first available version.
972      pkgCache::VerFileIterator VF = Ver.FileList();
973      if (!VF.end()) {
974         pkgCache::PkgFileIterator File = VF.File();
975
976         if (File->Archive != 0)
977            versions.push_back(pair < string,
978                               string > (Ver.VerStr(), File.Archive()));
979         else
980            versions.push_back(pair < string,
981                               string > (Ver.VerStr(), File.Site()));
982      }
983   }
984
985   return versions;
986}
987
988
989bool RPackage::setVersion(string verTag)
990{
991   pkgVersionMatch Match(verTag, pkgVersionMatch::Version);
992   pkgCache::VerIterator Ver = Match.Find(*_package);
993
994   if (Ver.end() == true)
995      return false;
996
997   _depcache->SetCandidateVersion(Ver);
998
999   _boolFlags |= FOverrideVersion;
1000
1001   return true;
1002}
1003 
1004void RPackage::unsetVersion() 
1005{ 
1006   //cout << "set version to " << _defaultCandVer << endl;
1007   setVersion(_defaultCandVer); 
1008   _boolFlags &= ~FOverrideVersion;
1009}
1010
1011vector<string> RPackage::provides()
1012{
1013   vector<string> provides;
1014
1015   pkgDepCache::StateCache & State = (*_depcache)[*_package];
1016   if (State.CandidateVer == 0)
1017      return provides;
1018
1019   for (pkgCache::PrvIterator Prv =
1020        State.CandidateVerIter(*_depcache).ProvidesList(); Prv.end() != true;
1021        Prv++) {
1022      provides.push_back(Prv.Name());
1023   }
1024
1025   return provides;
1026}
1027
1028/* mvo: actually shallow = false does not make a lot of sense as it
1029 *      will remove packages very brutally (like removing libc6)
1030 */
1031void RPackage::setRemoveWithDeps(bool shallow, bool purge)
1032{
1033   setRemove();
1034
1035   // remove packages that this one depends on, including this
1036   pkgCache::DepIterator deps = _package->VersionList().DependsList();
1037   pkgCache::DepIterator start, end;
1038
1039   deps.GlobOr(start, end);
1040
1041   while (1) {
1042      if (start == end) {
1043         deps++;
1044         if (deps.end())
1045            break;
1046         deps.GlobOr(start, end);
1047      } else {
1048         start++;
1049      }
1050
1051      if (!_depcache->IsImportantDep(start))
1052         continue;
1053
1054
1055      pkgCache::PkgIterator depPkg = start.TargetPkg();
1056
1057      // get the real package, in case this is a virtual pkg
1058      // mvo: does this actually work :) ?
1059      if (depPkg->VersionList == 0) {
1060         if (depPkg->ProvidesList != 0) {
1061            depPkg = depPkg.ProvidesList().OwnerPkg();
1062         } else {
1063            continue;
1064         }
1065      }
1066
1067      RPackage *depackage = _lister->getPackage(depPkg);
1068      //cout << "testing(RPackage): " << depackage->name() << endl;
1069
1070      if (!depackage)
1071         continue;
1072
1073      // skip important packages
1074      if (depackage->getFlags() & FImportant)
1075         continue;
1076
1077      // skip dependencies that are dependants of other packages
1078      // if shallow=true
1079      if (shallow && !isShallowDependency(depackage)) {
1080         continue;
1081      }
1082      // set this package for removal
1083      depackage->setRemove(purge);
1084   }
1085}
1086
1087
1088// description parser stuff
1089static char *debParser(string descr)
1090{
1091   unsigned int i;
1092   string::size_type nlpos=0;
1093
1094   nlpos = descr.find('\n');
1095   // delete first line
1096   if (nlpos != string::npos)
1097      descr.erase(0, nlpos + 2);        // del "\n " too
1098
1099   while (nlpos < descr.length()) {
1100      nlpos = descr.find('\n', nlpos);
1101      if (nlpos == string::npos)
1102         break;
1103
1104      i = nlpos;
1105      // del char after '\n' (always " ")
1106      i++;
1107      descr.erase(i, 1);
1108
1109      // delete lines likes this: " .", makeing it a \n
1110      if (descr[i] == '.') {
1111         descr.erase(i, 1);
1112         nlpos++;
1113         continue;
1114      }
1115      // skip ws
1116      while (descr[++i] == ' ');
1117
1118//      // not a list, erase nl
1119//       if(!(descr[i] == '*' || descr[i] == '-' || descr[i] == 'o'))
1120//      descr.erase(nlpos,1);
1121
1122      nlpos++;
1123   }
1124   strcpy(descrBuffer, descr.c_str());
1125   return descrBuffer;
1126}
1127static char *rpmParser(string descr)
1128{
1129   string::size_type pos = descr.find('\n');
1130   // delete first line
1131   if (pos != string::npos)
1132      descr.erase(0, pos + 2);  // del "\n " too
1133
1134   strcpy(descrBuffer, descr.c_str());
1135   return descrBuffer;
1136}
1137
1138static char *stripWsParser(string descr)
1139{
1140   const char *end;
1141   const char *p;
1142
1143   p = descr.c_str();
1144   end = p + descr.size();      // mvo: hackish, but works
1145
1146
1147   int state = 0;
1148   char *pp = (char *)descrBuffer;
1149
1150   while (p != end) {
1151      switch (state) {
1152         case 0:
1153            if (*p == '\n')
1154               state = 1;
1155            else
1156               *pp++ = *p;
1157            break;
1158
1159         case 1:
1160            if (*p == ' ')
1161               state = 2;
1162            else {
1163               *pp++ = *p;
1164               state = 0;
1165            }
1166            break;
1167
1168         case 2:
1169            if (!(*p == '\n' || *p == '.')) {
1170               *pp++ = ' ';
1171               *pp++ = *p;
1172            }
1173            state = 0;
1174            break;
1175      }
1176      p++;
1177   }
1178   *pp = '\0';
1179
1180   return descrBuffer;
1181}
1182
1183
1184static char *parseDescription(string descr)
1185{
1186
1187   if (descr.size() > sizeof(descrBuffer))
1188      return "Description Too Long";
1189
1190#ifdef HAVE_RPM
1191   int parser = _config->FindI("Synaptic::descriptionParser", NO_PARSER);
1192#else
1193   int parser = _config->FindI("Synaptic::descriptionParser", DEB_PARSER);
1194#endif
1195   switch (parser) {
1196      case DEB_PARSER:
1197         return debParser(descr);
1198      case STRIP_WS_PARSER:
1199         return stripWsParser(descr);
1200      case RPM_PARSER:
1201         return rpmParser(descr);
1202      case NO_PARSER:
1203      default:
1204         strcpy(descrBuffer, descr.c_str());
1205         return descrBuffer;
1206   }
1207}
1208
1209string RPackage::component()
1210{
1211   string res;
1212#ifdef WITH_APT_AUTH
1213   // the apt-secure patch breaks File.Component
1214   const char *s = _package->Section();
1215   if(s == NULL)
1216      return "";
1217
1218   string src_section(s);
1219   if(src_section.find('/')!=src_section.npos)
1220      src_section=string(src_section, 0, src_section.find('/'));
1221   else
1222      src_section="main";
1223   res = src_section;
1224#else
1225   pkgCache::VerIterator Ver;
1226   pkgDepCache::StateCache & State = (*_depcache)[*_package];
1227   if (State.CandidateVer == 0) {
1228      //cout << "CanidateVer == 0" << endl;
1229      return "";
1230   }
1231   Ver = State.CandidateVerIter(*_depcache);
1232   pkgCache::VerFileIterator VF = Ver.FileList();
1233   pkgCache::PkgFileIterator File = VF.File();
1234
1235   if(File.Component() == NULL) {
1236      //cout << "File.Component() == NULL" << endl;
1237      return "";
1238   }
1239
1240   res = File.Component();
1241#endif
1242   return res;
1243}
1244
1245
1246
1247string RPackage::label()
1248{
1249   string res;
1250   pkgCache::VerIterator Ver;
1251   pkgDepCache::StateCache & State = (*_depcache)[*_package];
1252   if (State.CandidateVer == 0) {
1253      //cout << "CanidateVer == 0" << endl;
1254      return "";
1255   }
1256   Ver = State.CandidateVerIter(*_depcache);
1257   pkgCache::VerFileIterator VF = Ver.FileList();
1258   pkgCache::PkgFileIterator File = VF.File();
1259
1260   if(File.Label() == NULL) {
1261      //cout << "File.Component() == NULL" << endl;
1262      return "";
1263   }
1264
1265   res = File.Label();
1266
1267   return res;
1268}
1269
1270
1271// class that finds out what do display to get user
1272void RPackageStatus::init()
1273{
1274   char *status_short[N_STATUS_COUNT] = {
1275      "install", "reinstall", "upgrade", "downgrade", "remove",
1276      "purge", "available", "available-locked",
1277      "installed-updated", "installed-outdated", "installed-locked",
1278      "broken", "new"
1279   };
1280   memcpy(PackageStatusShortString, status_short, sizeof(status_short));
1281
1282   char *status_long[N_STATUS_COUNT] = {
1283      _("Marked for installation"),
1284      _("Marked for re-installation"),
1285      _("Marked for upgrade"),
1286      _("Marked for downgrade"),
1287      _("Marked for removal"),
1288      _("Marked for complete removal"),
1289      _("Not installed"),
1290      _("Not installed (locked)"),
1291      _("Installed"),
1292      _("Installed (upgradable)"),
1293      _("Installed (locked to the current version)"),
1294      _("Broken"),
1295      _("Not installed (new in repository)")
1296   };
1297   memcpy(PackageStatusLongString, status_long, sizeof(status_long));
1298
1299
1300   // check for unsupported stuff
1301   if(_config->FindB("Synaptic::mark-unsupported",true)) {
1302      string s, labels, components;
1303      markUnsupported = true;
1304
1305      // read supported labels
1306      labels = _config->Find("Synaptic::supported-label", "Debian Debian-Security");
1307      stringstream sst1(labels);
1308      while(!sst1.eof()) {
1309         sst1 >> s;
1310         supportedLabels.push_back(s);
1311      }
1312     
1313      // read supported components
1314      components = _config->Find("Synaptic::supported-components", "main updates/main");
1315      stringstream sst2(components);
1316      while(!sst2.eof()) {
1317         sst2 >> s;
1318         supportedComponents.push_back(s);
1319      }
1320   } 
1321
1322}
1323
1324bool RPackageStatus::isSupported(RPackage *pkg) 
1325{
1326   bool res = true;
1327
1328   if(markUnsupported) {
1329      bool sc, sl;
1330
1331      sc=sl=false;
1332
1333      string component = pkg->component();
1334      string label = pkg->label();
1335
1336      for(unsigned int i=0;i<supportedComponents.size();i++) {
1337         if(supportedComponents[i] == component) {
1338            sc = true;
1339            break;
1340         }
1341      }
1342      for(unsigned int i=0;i<supportedLabels.size();i++) {
1343         if(supportedLabels[i] == label) {
1344            sl = true;
1345            break;
1346         }
1347      }
1348      res = (sc & sl);
1349   }
1350
1351   return res;
1352}
1353
1354int RPackageStatus::getStatus(RPackage *pkg)
1355{
1356   int flags = pkg->getFlags();
1357   int ret = NotInstalled;
1358
1359   if (pkg->wouldBreak()) {
1360      ret = IsBroken;
1361   } else if (flags & RPackage::FNewInstall) {
1362      ret = ToInstall;
1363   } else if (flags & RPackage::FUpgrade) {
1364      ret = ToUpgrade;
1365   } else if (flags & RPackage::FReInstall) {
1366      ret = ToReInstall;
1367   } else if (flags & RPackage::FDowngrade) {
1368      ret = ToDowngrade;
1369   } else if (flags & RPackage::FPurge) {
1370      ret = ToPurge;
1371   } else if (flags & RPackage::FRemove) {
1372      ret = ToRemove;
1373   } else if (flags & RPackage::FInstalled) {
1374      if (flags & RPackage::FPinned)
1375         ret = InstalledLocked;
1376      else if (flags & RPackage::FOutdated)
1377         ret = InstalledOutdated;
1378      else
1379         ret = InstalledUpdated;
1380   } else {
1381      if (flags & RPackage::FPinned)
1382         ret = NotInstalledLocked;
1383      else if (flags & RPackage::FNew)
1384         ret = IsNew;
1385      else
1386         ret = NotInstalled;
1387   }
1388
1389   return ret;
1390}
1391
1392
1393// vim:ts=3:sw=3:et
Note: See TracBrowser for help on using the repository browser.