]> git.saurik.com Git - apt.git/blobdiff - cmdline/apt-get.cc
cmdline/apt-get.cc: create the mkdtemp dir in /tmp
[apt.git] / cmdline / apt-get.cc
index dac0d42a8d2f1a2b47876aa967d100729e008fc2..53def383de0071279dfd4f18e23bac2e5cb75f8c 100644 (file)
@@ -844,9 +844,11 @@ struct TryToRemove {
    pkgCacheFile* Cache;
    pkgProblemResolver* Fix;
    bool FixBroken;
+   bool PurgePkgs;
    unsigned long AutoMarkChanged;
 
-   TryToRemove(pkgCacheFile &Cache, pkgProblemResolver &PM) : Cache(&Cache), Fix(&PM) {};
+   TryToRemove(pkgCacheFile &Cache, pkgProblemResolver &PM) : Cache(&Cache), Fix(&PM),
+                               PurgePkgs(_config->FindB("APT::Get::Purge", false)) {};
 
    void operator() (pkgCache::VerIterator const &Ver)
    {
@@ -856,10 +858,11 @@ struct TryToRemove {
       Fix->Protect(Pkg);
       Fix->Remove(Pkg);
 
-      if (Pkg->CurrentVer == 0)
+      if ((Pkg->CurrentVer == 0 && PurgePkgs == false) ||
+         (PurgePkgs == true && Pkg->CurrentState == pkgCache::State::NotInstalled))
         ioprintf(c1out,_("Package %s is not installed, so not removed\n"),Pkg.FullName(true).c_str());
       else
-        Cache->GetDepCache()->MarkDelete(Pkg,_config->FindB("APT::Get::Purge",false));
+        Cache->GetDepCache()->MarkDelete(Pkg, PurgePkgs);
    }
 };
                                                                        /*}}}*/
@@ -1081,13 +1084,13 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
       return false;
 
    // Read the source list
-   pkgSourceList List;
-   if (List.ReadMainList() == false)
-      return _error->Error(_("The list of sources could not be read."));
+   if (Cache.BuildSourceList() == false)
+      return false;
+   pkgSourceList *List = Cache.GetSourceList();
    
    // Create the package manager and prepare to download
    SPtr<pkgPackageManager> PM= _system->CreatePM(Cache);
-   if (PM->GetArchives(&Fetcher,&List,&Recs) == false || 
+   if (PM->GetArchives(&Fetcher,List,&Recs) == false || 
        _error->PendingError() == true)
       return false;
 
@@ -1103,17 +1106,25 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
    
    // Number of bytes
    if (DebBytes != FetchBytes)
+      //TRANSLATOR: The required space between number and unit is already included
+      // in the replacement strings, so %sB will be correctly translate in e.g. 1,5 MB
       ioprintf(c1out,_("Need to get %sB/%sB of archives.\n"),
               SizeToStr(FetchBytes).c_str(),SizeToStr(DebBytes).c_str());
    else if (DebBytes != 0)
+      //TRANSLATOR: The required space between number and unit is already included
+      // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB
       ioprintf(c1out,_("Need to get %sB of archives.\n"),
               SizeToStr(DebBytes).c_str());
 
    // Size delta
    if (Cache->UsrSize() >= 0)
+      //TRANSLATOR: The required space between number and unit is already included
+      // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB
       ioprintf(c1out,_("After this operation, %sB of additional disk space will be used.\n"),
               SizeToStr(Cache->UsrSize()).c_str());
    else
+      //TRANSLATOR: The required space between number and unit is already included
+      // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB
       ioprintf(c1out,_("After this operation, %sB disk space will be freed.\n"),
               SizeToStr(-1*Cache->UsrSize()).c_str());
 
@@ -1303,7 +1314,7 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
       
       // Reload the fetcher object and loop again for media swapping
       Fetcher.Shutdown();
-      if (PM->GetArchives(&Fetcher,&List,&Recs) == false)
+      if (PM->GetArchives(&Fetcher,List,&Recs) == false)
         return false;
       
       _system->Lock();
@@ -1539,11 +1550,13 @@ bool DoUpdate(CommandLine &CmdL)
 {
    if (CmdL.FileSize() != 1)
       return _error->Error(_("The update command takes no arguments"));
-   
+
+   CacheFile Cache;
+
    // Get the source list
-   pkgSourceList List;
-   if (List.ReadMainList() == false)
+   if (Cache.BuildSourceList() == false)
       return false;
+   pkgSourceList *List = Cache.GetSourceList();
 
    // Create the progress
    AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
@@ -1561,7 +1574,7 @@ bool DoUpdate(CommandLine &CmdL)
 
       // Populate it with the source selection and get all Indexes 
       // (GetAll=true)
-      if (List.GetIndexes(&Fetcher,true) == false)
+      if (List->GetIndexes(&Fetcher,true) == false)
         return false;
 
       pkgAcquire::UriIterator I = Fetcher.UriBegin();
@@ -1572,9 +1585,8 @@ bool DoUpdate(CommandLine &CmdL)
    }
 
    // do the work
-   CacheFile Cache;
    if (_config->FindB("APT::Get::Download",true) == true)
-       ListUpdate(Stat, List);
+       ListUpdate(Stat, *List);
 
    // Rebuild the cache.   
    if (Cache.BuildCaches() == false)
@@ -1651,7 +1663,7 @@ bool DoAutomaticRemove(CacheFile &Cache)
    if (doAutoRemove == false && (autoremovelist.empty() == false || autoRemoveCount != 0))
    {
       if (smallList == false)
-        ShowList(c1out, P_("The following package is automatically installed and is no longer required:",
+        ShowList(c1out, P_("The following package was automatically installed and is no longer required:",
                  "The following packages were automatically installed and are no longer required:",
                  autoRemoveCount), autoremovelist, autoremoveversions);
       else
@@ -2186,13 +2198,13 @@ bool DoSource(CommandLine &CmdL)
       return _error->Error(_("Must specify at least one package to fetch source for"));
    
    // Read the source list
-   pkgSourceList List;
-   if (List.ReadMainList() == false)
-      return _error->Error(_("The list of sources could not be read."));
+   if (Cache.BuildSourceList() == false)
+      return false;
+   pkgSourceList *List = Cache.GetSourceList();
    
    // Create the text record parsers
    pkgRecords Recs(Cache);
-   pkgSrcRecords SrcRecs(List);
+   pkgSrcRecords SrcRecs(*List);
    if (_error->PendingError() == true)
       return false;
 
@@ -2336,9 +2348,13 @@ bool DoSource(CommandLine &CmdL)
    
    // Number of bytes
    if (DebBytes != FetchBytes)
+      //TRANSLATOR: The required space between number and unit is already included
+      // in the replacement strings, so %sB will be correctly translate in e.g. 1,5 MB
       ioprintf(c1out,_("Need to get %sB/%sB of source archives.\n"),
               SizeToStr(FetchBytes).c_str(),SizeToStr(DebBytes).c_str());
    else
+      //TRANSLATOR: The required space between number and unit is already included
+      // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB
       ioprintf(c1out,_("Need to get %sB of source archives.\n"),
               SizeToStr(DebBytes).c_str());
    
@@ -2477,13 +2493,13 @@ bool DoBuildDep(CommandLine &CmdL)
       return _error->Error(_("Must specify at least one package to check builddeps for"));
    
    // Read the source list
-   pkgSourceList List;
-   if (List.ReadMainList() == false)
-      return _error->Error(_("The list of sources could not be read."));
+   if (Cache.BuildSourceList() == false)
+      return false;
+   pkgSourceList *List = Cache.GetSourceList();
    
    // Create the text record parsers
    pkgRecords Recs(Cache);
-   pkgSrcRecords SrcRecs(List);
+   pkgSrcRecords SrcRecs(*List);
    if (_error->PendingError() == true)
       return false;
 
@@ -2717,6 +2733,113 @@ bool DoBuildDep(CommandLine &CmdL)
    return true;
 }
                                                                        /*}}}*/
+// DownloadChangelog - Download the changelog                          /*{{{*/
+// ---------------------------------------------------------------------
+bool DownloadChangelog(CacheFile &CacheFile, pkgAcquire &Fetcher, pkgCache::VerIterator V, string targetfile)
+{
+   string srcpkg;
+   string prefix;
+   string descr;
+   string src_section;
+   string verstr;
+   string server;
+   string path;
+
+   // data structures we need
+   pkgRecords Recs(CacheFile);
+   pkgCache::PkgIterator Pkg = V.ParentPkg();
+   pkgRecords::Parser &rec=Recs.Lookup(V.FileList());
+
+   // build uri
+   srcpkg = rec.SourcePkg().empty() ? Pkg.Name() : rec.SourcePkg();
+   strprintf(descr, _("Changelog for %s"), srcpkg.c_str());
+   // FIXME: we actually need the source section here
+   src_section= Pkg.Section();
+   if(src_section.find('/')!=src_section.npos)
+      src_section=string(src_section, 0, src_section.find('/'));
+   else
+      src_section="main";
+
+   prefix+=srcpkg[0];
+   if(srcpkg.size()>3 && srcpkg[0]=='l' && srcpkg[1]=='i' && srcpkg[2]=='b')
+      prefix=std::string("lib")+srcpkg[3];
+
+   verstr = V.VerStr();
+   if(verstr.find(':')!=verstr.npos)
+      verstr=string(verstr, verstr.find(':')+1);
+
+   // make the server configurable
+   server = _config->Find("Apt::Changelogs::Server",
+                          "http://packages.debian.org/");
+   // ... but not the format string to avoid all possible attacks
+   strprintf(path, "/changelogs/pool/%s/%s/%s/%s_%s/changelog", src_section.c_str(), prefix.c_str(), srcpkg.c_str(), srcpkg.c_str(), verstr.c_str());
+   // get it
+   new pkgAcqFile(&Fetcher, server+path, "", 0, descr, srcpkg, "ignored", targetfile);
+   int res = Fetcher.Run();
+
+   if (FileExists(targetfile))
+      return true;
+
+   // error
+   return _error->Error("changelog download failed");
+}
+                                                                       /*}}}*/
+// DisplayFileInPager - Display File with pager                                /*{{{*/
+void DisplayFileInPager(string filename)
+{
+   pid_t Process = ExecFork();
+   if (Process == 0)
+   {
+      const char *Args[3];
+      Args[0] = "/usr/bin/sensible-pager";
+      Args[1] = filename.c_str();
+      Args[2] = 0;
+      execvp(Args[0],(char **)Args);
+      exit(100);
+   }
+         
+   // Wait for the subprocess
+   ExecWait(Process, "sensible-pager", false);
+}
+                                                                       /*}}}*/
+// DoChangelog - Get changelog from the command line                   /*{{{*/
+// ---------------------------------------------------------------------
+bool DoChangelog(CommandLine &CmdL)
+{
+   CacheFile Cache;
+   if (Cache.ReadOnlyOpen() == false)
+      return false;
+   
+   APT::CacheSetHelper helper(c0out);
+   APT::VersionSet verset = APT::VersionSet::FromCommandLine(Cache,
+               CmdL.FileList + 1, APT::VersionSet::CANDIDATE, helper);
+   pkgAcquire Fetcher;
+   AcqTextStatus Stat(ScreenWidth, _config->FindI("quiet",0));
+   Fetcher.Setup(&Stat);
+
+   if (verset.empty() == true)
+      return false;
+   char *tmpdir = mkdtemp(strdup("/tmp/apt-changelog-XXXXXX"));
+   if (tmpdir == NULL) {
+      return _error->Errno("mkdtemp", "mkdtemp failed");
+   }
+   
+   for (APT::VersionSet::const_iterator Ver = verset.begin(); 
+        Ver != verset.end(); 
+        ++Ver) 
+   {
+      string changelogfile = string(tmpdir) + "changelog";
+      if (DownloadChangelog(Cache, Fetcher, Ver, changelogfile))
+         DisplayFileInPager(changelogfile);
+      // cleanup temp file
+      unlink(changelogfile.c_str());
+   }
+   // clenaup tmp dir
+   rmdir(tmpdir);
+   free(tmpdir);
+   return true;
+}
+                                                                       /*}}}*/
 // DoMoo - Never Ask, Never Tell                                       /*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -2830,22 +2953,6 @@ bool ShowHelp(CommandLine &CmdL)
    return true;
 }
                                                                        /*}}}*/
-// GetInitialize - Initialize things for apt-get                       /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-void GetInitialize()
-{
-   _config->Set("quiet",0);
-   _config->Set("help",false);
-   _config->Set("APT::Get::Download-Only",false);
-   _config->Set("APT::Get::Simulate",false);
-   _config->Set("APT::Get::Assume-Yes",false);
-   _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                                /*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -2923,6 +3030,7 @@ int main(int argc,const char *argv[])                                     /*{{{*/
                                    {"autoclean",&DoAutoClean},
                                    {"check",&DoCheck},
                                   {"source",&DoSource},
+                                   {"changelog",&DoChangelog},
                                   {"moo",&DoMoo},
                                   {"help",&ShowHelp},
                                    {0,0}};