summaryrefslogtreecommitdiff
path: root/src/cmdline/cmdline_show_broken.cc
blob: 768cadb305ad90b9cc841e602acd3748462a59aa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// cmdline_show_broken.cc
//
//   Copyright 2004 Daniel Burrows

#include "cmdline_show_broken.h"

#include "cmdline_common.h"

#include <aptitude.h>

#include <generic/apt/apt.h>

#include <apt-pkg/pkgcache.h>

#include <stdio.h>
#include <string.h>

void show_broken_deps(pkgCache::PkgIterator pkg)
{
  unsigned int indent=strlen(pkg.Name())+3;
  bool is_first_dep=true;
  pkgCache::VerIterator ver=(*apt_cache_file)[pkg].InstVerIter(*apt_cache_file);

  printf("  %s:", pkg.Name());
  for(pkgCache::DepIterator dep=ver.DependsList(); !dep.end(); ++dep)
    {
      pkgCache::DepIterator first=dep, prev=dep;

      while(dep->CompareOp & pkgCache::Dep::Or)
	++dep;

      // Yep, it's broken.
      if(dep.IsCritical() &&
	 !((*apt_cache_file)[dep]&pkgDepCache::DepGInstall))
	{		  
	  bool is_first_of_or=true;
	  // Iterate over the OR group, print out the information.

	  do
	    {
	      if(!is_first_dep)
		for(unsigned int i=0; i<indent; ++i)
		  printf(" ");

	      is_first_dep=false;

	      if(!is_first_of_or)
		for(unsigned int i=0; i<strlen(dep.DepType())+3; ++i)
		  printf(" ");
	      else
		printf(" %s: ", first.DepType());

	      is_first_of_or=false;

	      if(first.TargetVer())
		printf("%s (%s %s)", first.TargetPkg().Name(), first.CompType(), first.TargetVer());
	      else
		printf("%s", first.TargetPkg().Name());

	      // FIXME: handle virtual packages sanely.
	      pkgCache::PkgIterator target=first.TargetPkg();
	      // Don't skip real packages which are provided.
	      if(!target.VersionList().end())
		{
		  printf(" ");

		  pkgCache::VerIterator ver=(*apt_cache_file)[target].InstVerIter(*apt_cache_file);

		  if(!ver.end()) // ok, it's installable.
		    {
		      if((*apt_cache_file)[target].Install())
			printf(_("but %s is to be installed."),
			       ver.VerStr());
		      else if((*apt_cache_file)[target].Upgradable())
			printf(_("but %s is installed and it is kept back."),
			       target.CurrentVer().VerStr());
		      else
			printf(_("but %s is installed."),
			       target.CurrentVer().VerStr());
		    }
		  else
		    {
		      pkgCache::VerIterator cand = (*apt_cache_file)[target].CandidateVerIter(*apt_cache_file);
		      if(cand.end())
			printf(_("but it is not installable."));
		      else
			printf(_("but it is not going to be installed."));
		    }
		}
	      else
		// FIXME: do something sensible here!
		printf(_(" which is a virtual package."));

	      if(first!=dep)
		printf(_(" or"));

	      printf("\n");

	      prev=first;
	      ++first;
	    } while(prev!=dep);
	}
    }
}

bool show_broken()
{
  pkgvector broken;
  for(pkgCache::PkgIterator i=(*apt_cache_file)->PkgBegin();
      !i.end(); ++i)
    {
      if((*apt_cache_file)[i].InstBroken())
	broken.push_back(i);
    }

  if(!broken.empty())
    {
      printf(_("The following packages have unmet dependencies:\n"));

      for(pkgvector::iterator pkg=broken.begin(); pkg!=broken.end(); ++pkg)
	show_broken_deps(*pkg);
      return false;
    }

  return true;
}