summaryrefslogtreecommitdiff
path: root/src/cmdline/cmdline_show_broken.cc
blob: 822f800c8e297e092305047c6aa4fb41de82cd0a (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
127
128
129
130
131
132
133
134
135
// 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>

using namespace std;

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

  cout << " " << pkg.FullName(true) << " :";

  if(ver.end() == true)
    {
      cout << endl;
      return;
    }

  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;

              cout << first.TargetPkg().FullName(true);

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

	      // 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;
}