summaryrefslogtreecommitdiff
path: root/cmdline
diff options
context:
space:
mode:
Diffstat (limited to 'cmdline')
-rw-r--r--cmdline/apt-cache.cc100
-rw-r--r--cmdline/apt-get.cc68
-rwxr-xr-xcmdline/apt-mark63
3 files changed, 206 insertions, 25 deletions
diff --git a/cmdline/apt-cache.cc b/cmdline/apt-cache.cc
index aea9ebeba..74fa71cba 100644
--- a/cmdline/apt-cache.cc
+++ b/cmdline/apt-cache.cc
@@ -71,6 +71,12 @@ void LocalitySort(pkgCache::VerFile **begin,
{
qsort(begin,Count,Size,LocalityCompare);
}
+
+void LocalitySort(pkgCache::DescFile **begin,
+ unsigned long Count,size_t Size)
+{
+ qsort(begin,Count,Size,LocalityCompare);
+}
/*}}}*/
// UnMet - Show unmet dependencies /*{{{*/
// ---------------------------------------------------------------------
@@ -182,7 +188,14 @@ bool DumpPackage(CommandLine &CmdL)
{
cout << Cur.VerStr();
for (pkgCache::VerFileIterator Vf = Cur.FileList(); Vf.end() == false; Vf++)
- cout << "(" << Vf.File().FileName() << ")";
+ cout << " (" << Vf.File().FileName() << ")";
+ cout << endl;
+ for (pkgCache::DescIterator D = Cur.DescriptionList(); D.end() == false; D++)
+ {
+ cout << " Description Language: " << D.LanguageCode() << endl
+ << " File: " << D.FileList().File().FileName() << endl
+ << " MD5: " << D.md5() << endl;
+ }
cout << endl;
}
@@ -277,11 +290,15 @@ bool Stats(CommandLine &Cmd)
cout << _("Total distinct versions: ") << Cache.Head().VersionCount << " (" <<
SizeToStr(Cache.Head().VersionCount*Cache.Head().VersionSz) << ')' << endl;
+ cout << _("Total Distinct Descriptions: ") << Cache.Head().DescriptionCount << " (" <<
+ SizeToStr(Cache.Head().DescriptionCount*Cache.Head().DescriptionSz) << ')' << endl;
cout << _("Total dependencies: ") << Cache.Head().DependsCount << " (" <<
SizeToStr(Cache.Head().DependsCount*Cache.Head().DependencySz) << ')' << endl;
cout << _("Total ver/file relations: ") << Cache.Head().VerFileCount << " (" <<
SizeToStr(Cache.Head().VerFileCount*Cache.Head().VerFileSz) << ')' << endl;
+ cout << _("Total Desc/File relations: ") << Cache.Head().DescFileCount << " (" <<
+ SizeToStr(Cache.Head().DescFileCount*Cache.Head().DescFileSz) << ')' << endl;
cout << _("Total Provides mappings: ") << Cache.Head().ProvidesCount << " (" <<
SizeToStr(Cache.Head().ProvidesCount*Cache.Head().ProvidesSz) << ')' << endl;
@@ -344,6 +361,12 @@ bool Dump(CommandLine &Cmd)
for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; D++)
cout << " Depends: " << D.TargetPkg().Name() << ' ' <<
DeNull(D.TargetVer()) << endl;
+ for (pkgCache::DescIterator D = V.DescriptionList(); D.end() == false; D++)
+ {
+ cout << " Description Language: " << D.LanguageCode() << endl
+ << " File: " << D.FileList().File().FileName() << endl
+ << " MD5: " << D.md5() << endl;
+ }
}
}
@@ -1192,17 +1215,50 @@ bool DisplayRecord(pkgCache::VerIterator V)
if (_error->PendingError() == true)
return false;
- // Read the record and then write it out again.
+ // Read the record
unsigned char *Buffer = new unsigned char[GCache->HeaderP->MaxVerFileSize+1];
Buffer[V.FileList()->Size] = '\n';
if (PkgF.Seek(V.FileList()->Offset) == false ||
- PkgF.Read(Buffer,V.FileList()->Size) == false ||
- fwrite(Buffer,1,V.FileList()->Size+1,stdout) < (size_t)(V.FileList()->Size+1))
+ PkgF.Read(Buffer,V.FileList()->Size) == false)
{
delete [] Buffer;
return false;
}
-
+
+ // Get a pointer to start of Description field
+ const unsigned char *DescP = (unsigned char*)strstr((char*)Buffer, "Description:");
+
+ // Write all but Description
+ if (fwrite(Buffer,1,DescP - Buffer,stdout) < (size_t)(DescP - Buffer))
+ {
+ delete [] Buffer;
+ return false;
+ }
+
+ // Show the right description
+ pkgRecords Recs(*GCache);
+ pkgCache::DescIterator Desc = V.TranslatedDescription();
+ pkgRecords::Parser &P = Recs.Lookup(Desc.FileList());
+ cout << "Description" << ( (strcmp(Desc.LanguageCode(),"") != 0) ? "-" : "" ) << Desc.LanguageCode() << ": " << P.LongDesc();
+
+ // Find the first field after the description (if there is any)
+ for(DescP++;DescP != &Buffer[V.FileList()->Size];DescP++)
+ {
+ if(*DescP == '\n' && *(DescP+1) != ' ')
+ {
+ // write the rest of the buffer
+ const unsigned char *end=&Buffer[V.FileList()->Size];
+ if (fwrite(DescP,1,end-DescP,stdout) < (size_t)(end-DescP))
+ {
+ delete [] Buffer;
+ return false;
+ }
+
+ break;
+ }
+ }
+ // write a final newline (after the description)
+ cout<<endl;
delete [] Buffer;
return true;
@@ -1211,9 +1267,9 @@ bool DisplayRecord(pkgCache::VerIterator V)
// Search - Perform a search /*{{{*/
// ---------------------------------------------------------------------
/* This searches the package names and pacakge descriptions for a pattern */
-struct ExVerFile
+struct ExDescFile
{
- pkgCache::VerFile *Vf;
+ pkgCache::DescFile *Df;
bool NameMatch;
};
@@ -1253,35 +1309,35 @@ bool Search(CommandLine &CmdL)
return false;
}
- ExVerFile *VFList = new ExVerFile[Cache.HeaderP->PackageCount+1];
- memset(VFList,0,sizeof(*VFList)*Cache.HeaderP->PackageCount+1);
+ ExDescFile *DFList = new ExDescFile[Cache.HeaderP->PackageCount+1];
+ memset(DFList,0,sizeof(*DFList)*Cache.HeaderP->PackageCount+1);
// Map versions that we want to write out onto the VerList array.
for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
{
- VFList[P->ID].NameMatch = NumPatterns != 0;
+ DFList[P->ID].NameMatch = NumPatterns != 0;
for (unsigned I = 0; I != NumPatterns; I++)
{
if (regexec(&Patterns[I],P.Name(),0,0,0) == 0)
- VFList[P->ID].NameMatch &= true;
+ DFList[P->ID].NameMatch &= true;
else
- VFList[P->ID].NameMatch = false;
+ DFList[P->ID].NameMatch = false;
}
// Doing names only, drop any that dont match..
- if (NamesOnly == true && VFList[P->ID].NameMatch == false)
+ if (NamesOnly == true && DFList[P->ID].NameMatch == false)
continue;
// Find the proper version to use.
pkgCache::VerIterator V = Plcy.GetCandidateVer(P);
if (V.end() == false)
- VFList[P->ID].Vf = V.FileList();
+ DFList[P->ID].Df = V.DescriptionList().FileList();
}
// Include all the packages that provide matching names too
for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
{
- if (VFList[P->ID].NameMatch == false)
+ if (DFList[P->ID].NameMatch == false)
continue;
for (pkgCache::PrvIterator Prv = P.ProvidesList() ; Prv.end() == false; Prv++)
@@ -1289,18 +1345,18 @@ bool Search(CommandLine &CmdL)
pkgCache::VerIterator V = Plcy.GetCandidateVer(Prv.OwnerPkg());
if (V.end() == false)
{
- VFList[Prv.OwnerPkg()->ID].Vf = V.FileList();
- VFList[Prv.OwnerPkg()->ID].NameMatch = true;
+ DFList[Prv.OwnerPkg()->ID].Df = V.DescriptionList().FileList();
+ DFList[Prv.OwnerPkg()->ID].NameMatch = true;
}
}
}
-
- LocalitySort(&VFList->Vf,Cache.HeaderP->PackageCount,sizeof(*VFList));
+
+ LocalitySort(&DFList->Df,Cache.HeaderP->PackageCount,sizeof(*DFList));
// Iterate over all the version records and check them
- for (ExVerFile *J = VFList; J->Vf != 0; J++)
+ for (ExDescFile *J = DFList; J->Df != 0; J++)
{
- pkgRecords::Parser &P = Recs.Lookup(pkgCache::VerFileIterator(Cache,J->Vf));
+ pkgRecords::Parser &P = Recs.Lookup(pkgCache::DescFileIterator(Cache,J->Df));
bool Match = true;
if (J->NameMatch == false)
@@ -1331,7 +1387,7 @@ bool Search(CommandLine &CmdL)
}
}
- delete [] VFList;
+ delete [] DFList;
for (unsigned I = 0; I != NumPatterns; I++)
regfree(&Patterns[I]);
if (ferror(stdout))
diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc
index d4a6bee32..8b3c68573 100644
--- a/cmdline/apt-get.cc
+++ b/cmdline/apt-get.cc
@@ -60,6 +60,7 @@
#include <errno.h>
#include <regex.h>
#include <sys/wait.h>
+#include <sstream>
/*}}}*/
using namespace std;
@@ -995,7 +996,7 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
cerr << _("Unable to correct missing packages.") << endl;
return _error->Error(_("Aborting install."));
}
-
+
_system->UnLock();
int status_fd = _config->FindI("APT::Status-Fd",-1);
pkgPackageManager::OrderResult Res = PM->DoInstall(status_fd);
@@ -1386,6 +1387,52 @@ bool DoUpdate(CommandLine &CmdL)
return true;
}
/*}}}*/
+// DoAutomaticRemove - Remove all automatic unused packages /*{{{*/
+// ---------------------------------------------------------------------
+/* Remove unused automatic packages */
+bool DoAutomaticRemove(CacheFile &Cache)
+{
+ if(_config->FindI("Debug::pkgAutoRemove",false))
+ std::cout << "DoAutomaticRemove()" << std::endl;
+
+ if (_config->FindB("APT::Get::Remove",true) == false)
+ return _error->Error(_("We are not supposed to delete stuff, can't "
+ "start AutoRemover"));
+
+ {
+ pkgDepCache::ActionGroup group(*Cache);
+
+ // look over the cache to see what can be removed
+ for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); ! Pkg.end(); ++Pkg)
+ {
+ if (Cache[Pkg].Garbage)
+ {
+ if(Pkg.CurrentVer() != 0 || Cache[Pkg].Install())
+ fprintf(stdout,"We could delete %s\n", Pkg.Name());
+
+ if(Pkg.CurrentVer() != 0 && Pkg->CurrentState != pkgCache::State::ConfigFiles)
+ Cache->MarkDelete(Pkg, _config->FindB("APT::Get::Purge", false));
+ else
+ Cache->MarkKeep(Pkg, false, false);
+ }
+ }
+ }
+
+ // Now see if we destroyed anything
+ if (Cache->BrokenCount() != 0)
+ {
+ c1out << _("Hmm, seems like the AutoRemover destroyed something which really\n"
+ "shouldn't happen. Please file a bug report against apt.") << endl;
+ c1out << endl;
+ c1out << _("The following information may help to resolve the situation:") << endl;
+ c1out << endl;
+ ShowBroken(c1out,Cache,false);
+
+ return _error->Error(_("Internal Error, AutoRemover broke stuff"));
+ }
+ return true;
+}
+
// DoUpgrade - Upgrade all packages /*{{{*/
// ---------------------------------------------------------------------
/* Upgrade all packages without installing new packages or erasing old
@@ -1428,6 +1475,11 @@ bool DoInstall(CommandLine &CmdL)
bool DefRemove = false;
if (strcasecmp(CmdL.FileList[0],"remove") == 0)
DefRemove = true;
+ else if (strcasecmp(CmdL.FileList[0], "autoremove") == 0)
+ {
+ _config->Set("APT::Get::AutomaticRemove", "true");
+ DefRemove = true;
+ }
for (const char **I = CmdL.FileList + 1; *I != 0; I++)
{
@@ -1577,6 +1629,11 @@ bool DoInstall(CommandLine &CmdL)
return _error->Error(_("Broken packages"));
}
+ if (_config->FindB("APT::Get::AutomaticRemove")) {
+ if (!DoAutomaticRemove(Cache))
+ return false;
+ }
+
/* Print out a list of packages that are going to be installed extra
to what the user asked */
if (Cache->InstCount() != ExpectedInst)
@@ -1596,8 +1653,8 @@ bool DoInstall(CommandLine &CmdL)
if (*J == 0) {
List += string(I.Name()) + " ";
- VersionsList += string(Cache[I].CandVersion) + "\n";
- }
+ VersionsList += string(Cache[I].CandVersion) + "\n";
+ }
}
ShowList(c1out,_("The following extra packages will be installed:"),List,VersionsList);
@@ -1714,6 +1771,8 @@ bool DoDSelectUpgrade(CommandLine &CmdL)
if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false)
return false;
+ pkgDepCache::ActionGroup group(Cache);
+
// Install everything with the install flag set
pkgCache::PkgIterator I = Cache->PkgBegin();
for (;I.end() != true; I++)
@@ -2466,6 +2525,7 @@ void GetInitialize()
_config->Set("APT::Get::Fix-Broken",false);
_config->Set("APT::Get::Force-Yes",false);
_config->Set("APT::Get::List-Cleanup",true);
+ _config->Set("APT::Get::AutomaticRemove",false);
}
/*}}}*/
// SigWinch - Window size change signal handler /*{{{*/
@@ -2521,6 +2581,7 @@ int main(int argc,const char *argv[])
{0,"remove","APT::Get::Remove",0},
{0,"only-source","APT::Get::Only-Source",0},
{0,"arch-only","APT::Get::Arch-Only",0},
+ {0,"auto-remove","APT::Get::AutomaticRemove",0},
{0,"allow-unauthenticated","APT::Get::AllowUnauthenticated",0},
{'c',"config-file",0,CommandLine::ConfigFile},
{'o',"option",0,CommandLine::ArbItem},
@@ -2529,6 +2590,7 @@ int main(int argc,const char *argv[])
{"upgrade",&DoUpgrade},
{"install",&DoInstall},
{"remove",&DoInstall},
+ {"autoremove",&DoInstall},
{"dist-upgrade",&DoDistUpgrade},
{"dselect-upgrade",&DoDSelectUpgrade},
{"build-dep",&DoBuildDep},
diff --git a/cmdline/apt-mark b/cmdline/apt-mark
new file mode 100755
index 000000000..533ed8715
--- /dev/null
+++ b/cmdline/apt-mark
@@ -0,0 +1,63 @@
+#!/usr/bin/python
+
+from optparse import OptionParser
+
+try:
+ import apt_pkg
+except ImportError:
+ print "Error importing apt_pkg, is python-apt installed?"
+
+import sys
+import os.path
+
+actions = { "markauto" : 1,
+ "unmarkauto": 0
+ }
+
+if __name__ == "__main__":
+ apt_pkg.init()
+
+ # option parsing
+ parser = OptionParser()
+ parser.usage = "%prog [options] {markauto|unmarkauto} packages..."
+ parser.add_option("-f", "--file", action="store", type="string",
+ dest="filename",
+ help="read/write a different file")
+ parser.add_option("-v", "--verbose",
+ action="store_true", dest="verbose", default=False,
+ help="print verbose status messages to stdout")
+ (options, args) = parser.parse_args()
+ if len(args) < 2:
+ parser.error("not enough argument")
+
+ # get pkgs to change
+ if args[0] not in actions.keys():
+ parser.error("first argument must be 'markauto' or 'unmarkauto'")
+ pkgs = args[1:]
+ action = actions[args[0]]
+
+ # get the state-file
+ if not options.filename:
+ STATE_FILE = apt_pkg.Config.FindDir("Dir::State") + "extended_states"
+ else:
+ STATE_FILE=options.state_file
+
+ # open the statefile
+ if os.path.exists(STATE_FILE):
+ tagfile = apt_pkg.ParseTagFile(open(STATE_FILE))
+ outfile = open(STATE_FILE+".tmp","w")
+ while tagfile.Step():
+ pkgname = tagfile.Section.get("Package")
+ autoInst = tagfile.Section.get("Auto-Installed")
+ if pkgname in pkgs:
+ if options.verbose:
+ print "changing %s to %s" % (pkgname,action)
+ newsec = apt_pkg.RewriteSection(tagfile.Section,
+ [],
+ [ ("Auto-Installed",str(action)) ]
+ )
+ outfile.write(newsec+"\n")
+ else:
+ outfile.write(str(tagfile.Section)+"\n")
+ # all done, rename the tmpfile
+ os.rename(outfile.name, STATE_FILE)