summaryrefslogtreecommitdiffstats
path: root/apt-pkg/update.cc
blob: 1bf818ad716e62176a6e8165c0a7f3c267833910 (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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
// Include Files							/*{{{*/
#include <config.h>

#include <apt-pkg/acquire-item.h>
#include <apt-pkg/acquire.h>
#include <apt-pkg/configuration.h>
#include <apt-pkg/error.h>
#include <apt-pkg/fileutl.h>
#include <apt-pkg/sourcelist.h>
#include <apt-pkg/strutl.h>
#include <apt-pkg/update.h>

#include <string>

#include <apti18n.h>
									/*}}}*/

using namespace std;

// ListUpdate - construct Fetcher and update the cache files		/*{{{*/
// ---------------------------------------------------------------------
/* This is a simple wrapper to update the cache. it will fetch stuff
 * from the network (or any other sources defined in sources.list)
 */
bool ListUpdate(pkgAcquireStatus &Stat, 
		pkgSourceList &List, 
		int PulseInterval)
{
   pkgAcquire Fetcher(&Stat);
   if (Fetcher.GetLock(_config->FindDir("Dir::State::Lists")) == false)
      return false;

   // Populate it with the source selection
   if (List.GetIndexes(&Fetcher) == false)
	 return false;

   return AcquireUpdate(Fetcher, PulseInterval, true);
}
									/*}}}*/
// AcquireUpdate - take Fetcher and update the cache files		/*{{{*/
// ---------------------------------------------------------------------
/* This is a simple wrapper to update the cache with a provided acquire
 * If you only need control over Status and the used SourcesList use
 * ListUpdate method instead.
 */
bool AcquireUpdate(pkgAcquire &Fetcher, int const PulseInterval,
		   bool const RunUpdateScripts, bool const ListCleanup)
{
   enum class ErrorMode
   {
      Persistent,
      Any
   };
   std::string errorModeS = _config->Find("APT::Update::Error-Mode", "persistent");
   ErrorMode errorMode = ErrorMode::Persistent;
   if (errorModeS == "persistent")
      errorMode = ErrorMode::Persistent;
   else if (errorModeS == "any")
      errorMode = ErrorMode::Any;
   else
      return _error->Error("Unknown update error mode %s", errorModeS.c_str());

   // Run scripts
   if (RunUpdateScripts == true)
      RunScripts("APT::Update::Pre-Invoke");

   pkgAcquire::RunResult res;
   if(PulseInterval > 0)
      res = Fetcher.Run(PulseInterval);
   else
      res = Fetcher.Run();

   bool const errorsWereReported = (res == pkgAcquire::Failed);
   bool Failed = errorsWereReported;
   bool TransientNetworkFailure = false;
   bool AllFailed = true;
   for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); 
	I != Fetcher.ItemsEnd(); ++I)
   {
      switch ((*I)->Status)
      {
	 case pkgAcquire::Item::StatDone:
	    AllFailed = false;
	    continue;
	 case pkgAcquire::Item::StatTransientNetworkError:
	    if (errorMode == ErrorMode::Any)
	       Failed = true;
	    else
	       TransientNetworkFailure = true;
	    break;
	 case pkgAcquire::Item::StatIdle:
	 case pkgAcquire::Item::StatFetching:
	 case pkgAcquire::Item::StatError:
	 case pkgAcquire::Item::StatAuthError:
	    Failed = true;
	    break;
      }

      (*I)->Finished();

      if (errorsWereReported)
	 continue;

      ::URI uri((*I)->DescURI());
      uri.User.clear();
      uri.Password.clear();
      if ((*I)->Local)
	 uri.Path = DeQuoteString(uri.Path);
      std::string const descUri = std::string(uri);
      // Show an error for non-transient failures, otherwise only warn
      if ((*I)->Status == pkgAcquire::Item::StatTransientNetworkError && errorMode != ErrorMode::Any)
	 _error->Warning(_("Failed to fetch %s  %s"), descUri.c_str(),
			(*I)->ErrorText.c_str());
      else
	 _error->Error(_("Failed to fetch %s  %s"), descUri.c_str(),
	       (*I)->ErrorText.c_str());
   }

   // Clean out any old list files
   // Keep "APT::Get::List-Cleanup" name for compatibility, but
   // this is really a global option for the APT library now
   if (!TransientNetworkFailure && !Failed && ListCleanup == true &&
       (_config->FindB("APT::Get::List-Cleanup",true) == true &&
	_config->FindB("APT::List-Cleanup",true) == true))
   {
      if (Fetcher.Clean(_config->FindDir("Dir::State::lists")) == false ||
	  Fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/") == false)
	 // something went wrong with the clean
	 return false;
   }

   bool Res = true;

   if (errorsWereReported == true)
      Res = false;
   else if (TransientNetworkFailure == true)
      Res = _error->Warning(_("Some index files failed to download. They have been ignored, or old ones used instead."));
   else if (Failed == true)
      Res = _error->Error(_("Some index files failed to download. They have been ignored, or old ones used instead."));

   // Run the success scripts if all was fine
   if (RunUpdateScripts == true)
   {
      if(AllFailed == false)
	 RunScripts("APT::Update::Post-Invoke-Success");

      // Run the other scripts
      RunScripts("APT::Update::Post-Invoke");
   }
   return Res;
}
									/*}}}*/