summaryrefslogtreecommitdiff
path: root/cmdline
diff options
context:
space:
mode:
Diffstat (limited to 'cmdline')
-rw-r--r--cmdline/apt-get.cc319
-rwxr-xr-xcmdline/apt-mark63
2 files changed, 255 insertions, 127 deletions
diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc
index 64882e3e8..9e7071988 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,155 +1475,168 @@ 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++)
+ // new scope for the ActionGroup
{
- // Duplicate the string
- unsigned int Length = strlen(*I);
- char S[300];
- if (Length >= sizeof(S))
- continue;
- strcpy(S,*I);
-
- // See if we are removing and special indicators..
- bool Remove = DefRemove;
- char *VerTag = 0;
- bool VerIsRel = false;
- while (Cache->FindPkg(S).end() == true)
+ pkgDepCache::ActionGroup group(Cache);
+ for (const char **I = CmdL.FileList + 1; *I != 0; I++)
{
- // Handle an optional end tag indicating what to do
- if (Length >= 1 && S[Length - 1] == '-')
- {
- Remove = true;
- S[--Length] = 0;
+ // Duplicate the string
+ unsigned int Length = strlen(*I);
+ char S[300];
+ if (Length >= sizeof(S))
continue;
- }
-
- if (Length >= 1 && S[Length - 1] == '+')
+ strcpy(S,*I);
+
+ // See if we are removing and special indicators..
+ bool Remove = DefRemove;
+ char *VerTag = 0;
+ bool VerIsRel = false;
+ while (Cache->FindPkg(S).end() == true)
{
- Remove = false;
- S[--Length] = 0;
- continue;
- }
+ // Handle an optional end tag indicating what to do
+ if (Length >= 1 && S[Length - 1] == '-')
+ {
+ Remove = true;
+ S[--Length] = 0;
+ continue;
+ }
- char *Slash = strchr(S,'=');
- if (Slash != 0)
- {
- VerIsRel = false;
- *Slash = 0;
- VerTag = Slash + 1;
- }
+ if (Length >= 1 && S[Length - 1] == '+')
+ {
+ Remove = false;
+ S[--Length] = 0;
+ continue;
+ }
- Slash = strchr(S,'/');
- if (Slash != 0)
- {
- VerIsRel = true;
- *Slash = 0;
- VerTag = Slash + 1;
- }
+ char *Slash = strchr(S,'=');
+ if (Slash != 0)
+ {
+ VerIsRel = false;
+ *Slash = 0;
+ VerTag = Slash + 1;
+ }
- break;
- }
+ Slash = strchr(S,'/');
+ if (Slash != 0)
+ {
+ VerIsRel = true;
+ *Slash = 0;
+ VerTag = Slash + 1;
+ }
+
+ break;
+ }
- // Locate the package
- pkgCache::PkgIterator Pkg = Cache->FindPkg(S);
- Packages++;
- if (Pkg.end() == true)
- {
- // Check if the name is a regex
- const char *I;
- for (I = S; *I != 0; I++)
- if (*I == '?' || *I == '*' || *I == '|' ||
- *I == '[' || *I == '^' || *I == '$')
- break;
- if (*I == 0)
- return _error->Error(_("Couldn't find package %s"),S);
+ // Locate the package
+ pkgCache::PkgIterator Pkg = Cache->FindPkg(S);
+ Packages++;
+ if (Pkg.end() == true)
+ {
+ // Check if the name is a regex
+ const char *I;
+ for (I = S; *I != 0; I++)
+ if (*I == '?' || *I == '*' || *I == '|' ||
+ *I == '[' || *I == '^' || *I == '$')
+ break;
+ if (*I == 0)
+ return _error->Error(_("Couldn't find package %s"),S);
- // Regexs must always be confirmed
- ExpectedInst += 1000;
+ // Regexs must always be confirmed
+ ExpectedInst += 1000;
- // Compile the regex pattern
- regex_t Pattern;
- int Res;
- if ((Res = regcomp(&Pattern,S,REG_EXTENDED | REG_ICASE |
- REG_NOSUB)) != 0)
- {
- char Error[300];
- regerror(Res,&Pattern,Error,sizeof(Error));
- return _error->Error(_("Regex compilation error - %s"),Error);
- }
+ // Compile the regex pattern
+ regex_t Pattern;
+ int Res;
+ if ((Res = regcomp(&Pattern,S,REG_EXTENDED | REG_ICASE |
+ REG_NOSUB)) != 0)
+ {
+ char Error[300];
+ regerror(Res,&Pattern,Error,sizeof(Error));
+ return _error->Error(_("Regex compilation error - %s"),Error);
+ }
- // Run over the matches
- bool Hit = false;
- for (Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
- {
- if (regexec(&Pattern,Pkg.Name(),0,0,0) != 0)
- continue;
+ // Run over the matches
+ bool Hit = false;
+ for (Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
+ {
+ if (regexec(&Pattern,Pkg.Name(),0,0,0) != 0)
+ continue;
- ioprintf(c1out,_("Note, selecting %s for regex '%s'\n"),
- Pkg.Name(),S);
+ ioprintf(c1out,_("Note, selecting %s for regex '%s'\n"),
+ Pkg.Name(),S);
+ if (VerTag != 0)
+ if (TryToChangeVer(Pkg,Cache,VerTag,VerIsRel) == false)
+ return false;
+
+ Hit |= TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix,
+ ExpectedInst,false);
+ }
+ regfree(&Pattern);
+
+ if (Hit == false)
+ return _error->Error(_("Couldn't find package %s"),S);
+ }
+ else
+ {
if (VerTag != 0)
if (TryToChangeVer(Pkg,Cache,VerTag,VerIsRel) == false)
return false;
-
- Hit |= TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix,
- ExpectedInst,false);
- }
- regfree(&Pattern);
-
- if (Hit == false)
- return _error->Error(_("Couldn't find package %s"),S);
- }
- else
- {
- if (VerTag != 0)
- if (TryToChangeVer(Pkg,Cache,VerTag,VerIsRel) == false)
+ if (TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix,ExpectedInst) == false)
return false;
- if (TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix,ExpectedInst) == false)
- return false;
- }
- }
+ }
+ }
- /* If we are in the Broken fixing mode we do not attempt to fix the
- problems. This is if the user invoked install without -f and gave
- packages */
- if (BrokenFix == true && Cache->BrokenCount() != 0)
- {
- c1out << _("You might want to run `apt-get -f install' to correct these:") << endl;
- ShowBroken(c1out,Cache,false);
+ /* If we are in the Broken fixing mode we do not attempt to fix the
+ problems. This is if the user invoked install without -f and gave
+ packages */
+ if (BrokenFix == true && Cache->BrokenCount() != 0)
+ {
+ c1out << _("You might want to run `apt-get -f install' to correct these:") << endl;
+ ShowBroken(c1out,Cache,false);
- return _error->Error(_("Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution)."));
- }
+ return _error->Error(_("Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution)."));
+ }
- // Call the scored problem resolver
- Fix.InstallProtect();
- if (Fix.Resolve(true) == false)
- _error->Discard();
+ // Call the scored problem resolver
+ Fix.InstallProtect();
+ if (Fix.Resolve(true) == false)
+ _error->Discard();
- // Now we check the state of the packages,
- if (Cache->BrokenCount() != 0)
- {
- c1out <<
- _("Some packages could not be installed. This may mean that you have\n"
- "requested an impossible situation or if you are using the unstable\n"
- "distribution that some required packages have not yet been created\n"
- "or been moved out of Incoming.") << endl;
- if (Packages == 1)
+ // Now we check the state of the packages,
+ if (Cache->BrokenCount() != 0)
{
- c1out << endl;
c1out <<
- _("Since you only requested a single operation it is extremely likely that\n"
- "the package is simply not installable and a bug report against\n"
- "that package should be filed.") << endl;
- }
+ _("Some packages could not be installed. This may mean that you have\n"
+ "requested an impossible situation or if you are using the unstable\n"
+ "distribution that some required packages have not yet been created\n"
+ "or been moved out of Incoming.") << endl;
+ if (Packages == 1)
+ {
+ c1out << endl;
+ c1out <<
+ _("Since you only requested a single operation it is extremely likely that\n"
+ "the package is simply not installable and a bug report against\n"
+ "that package should be filed.") << endl;
+ }
+
+ c1out << _("The following information may help to resolve the situation:") << endl;
+ c1out << endl;
+ ShowBroken(c1out,Cache,false);
+ return _error->Error(_("Broken packages"));
+ }
+ }
+ if (_config->FindB("APT::Get::AutomaticRemove")) {
+ if (!DoAutomaticRemove(Cache))
+ return false;
+ }
- c1out << _("The following information may help to resolve the situation:") << endl;
- c1out << endl;
- ShowBroken(c1out,Cache,false);
- return _error->Error(_("Broken packages"));
- }
-
/* Print out a list of packages that are going to be installed extra
to what the user asked */
if (Cache->InstCount() != ExpectedInst)
@@ -1596,8 +1656,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);
@@ -1732,6 +1792,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++)
@@ -2484,6 +2546,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 /*{{{*/
@@ -2539,6 +2602,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},
@@ -2547,6 +2611,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)