1
by Thomas-Karl Pietrowski
first import |
1 |
/*---------------------------------------------------------------------\
|
2 |
| ____ _ __ __ ___ |
|
|
3 |
| |__ / \ / / . \ . \ |
|
|
4 |
| / / \ V /| _/ _/ |
|
|
5 |
| / /__ | | | | | | |
|
|
6 |
| /_____||_| |_| |_| |
|
|
7 |
| |
|
|
8 |
\---------------------------------------------------------------------*/
|
|
9 |
/** \file zypp/sat/Repository.cc
|
|
10 |
*
|
|
11 |
*/
|
|
12 |
#include <climits> |
|
13 |
#include <iostream> |
|
14 |
||
15 |
#include "zypp/base/Logger.h" |
|
16 |
#include "zypp/base/Gettext.h" |
|
17 |
#include "zypp/base/Exception.h" |
|
18 |
#include "zypp/base/Xml.h" |
|
19 |
||
20 |
#include "zypp/AutoDispose.h" |
|
21 |
#include "zypp/Pathname.h" |
|
22 |
||
23 |
#include "zypp/sat/detail/PoolImpl.h" |
|
24 |
#include "zypp/Repository.h" |
|
5
by Thomas-Karl Pietrowski
syncing again |
25 |
#include "zypp/ResPool.h" |
26 |
#include "zypp/Product.h" |
|
1
by Thomas-Karl Pietrowski
first import |
27 |
#include "zypp/sat/Pool.h" |
28 |
||
29 |
using std::endl; |
|
30 |
||
31 |
///////////////////////////////////////////////////////////////////
|
|
32 |
namespace zypp |
|
33 |
{ ///////////////////////////////////////////////////////////////// |
|
34 |
||
35 |
const Repository Repository::noRepository; |
|
36 |
||
37 |
const std::string & Repository::systemRepoAlias() |
|
38 |
{ return sat::detail::PoolImpl::systemRepoAlias(); } |
|
39 |
||
40 |
/////////////////////////////////////////////////////////////////
|
|
41 |
||
42 |
::_Repo * Repository::get() const |
|
43 |
{ return myPool().getRepo( _id ); } |
|
44 |
||
45 |
#define NO_REPOSITORY_RETURN( VAL ) \
|
|
46 |
::_Repo * _repo( get() ); \
|
|
47 |
if ( ! _repo ) return VAL
|
|
48 |
||
49 |
#define NO_REPOSITORY_THROW( VAL ) \
|
|
50 |
::_Repo * _repo( get() ); \
|
|
51 |
if ( ! _repo ) ZYPP_THROW( VAL )
|
|
52 |
||
53 |
bool Repository::isSystemRepo() const |
|
54 |
{
|
|
55 |
NO_REPOSITORY_RETURN( false ); |
|
56 |
return myPool().isSystemRepo( _repo ); |
|
57 |
}
|
|
58 |
||
59 |
std::string Repository::alias() const |
|
60 |
{
|
|
61 |
NO_REPOSITORY_RETURN( std::string() ); |
|
62 |
if ( ! _repo->name ) |
|
63 |
return std::string(); |
|
64 |
return _repo->name; |
|
65 |
}
|
|
66 |
||
67 |
std::string Repository::name() const |
|
68 |
{ return info().name(); } |
|
69 |
||
2
by Thomas-Karl Pietrowski
syncing code with latest from github |
70 |
std::string Repository::label() const |
71 |
{ return info().label(); } |
|
72 |
||
1
by Thomas-Karl Pietrowski
first import |
73 |
int Repository::satInternalPriority() const |
74 |
{
|
|
75 |
NO_REPOSITORY_RETURN( INT_MIN ); |
|
76 |
return _repo->priority; |
|
77 |
}
|
|
78 |
||
79 |
int Repository::satInternalSubPriority() const |
|
80 |
{
|
|
81 |
NO_REPOSITORY_RETURN( INT_MIN ); |
|
82 |
return _repo->subpriority; |
|
83 |
}
|
|
84 |
||
2
by Thomas-Karl Pietrowski
syncing code with latest from github |
85 |
Repository::ContentRevision Repository::contentRevision() const |
86 |
{
|
|
87 |
NO_REPOSITORY_RETURN( ContentRevision() ); |
|
88 |
sat::LookupRepoAttr q( sat::SolvAttr::repositoryRevision, *this ); |
|
89 |
return q.empty() ? std::string() : q.begin().asString(); |
|
90 |
}
|
|
91 |
||
92 |
Repository::ContentIdentifier Repository::contentIdentifier() const |
|
93 |
{
|
|
94 |
NO_REPOSITORY_RETURN( ContentIdentifier() ); |
|
95 |
sat::LookupRepoAttr q( sat::SolvAttr::repositoryRepoid, *this ); |
|
96 |
return q.empty() ? std::string() : q.begin().asString(); |
|
97 |
}
|
|
98 |
||
99 |
bool Repository::hasContentIdentifier( const ContentIdentifier & id_r ) const |
|
100 |
{
|
|
101 |
NO_REPOSITORY_RETURN( false ); |
|
102 |
sat::LookupRepoAttr q( sat::SolvAttr::repositoryRepoid, *this ); |
|
103 |
for_( it, q.begin(), q.end() ) |
|
104 |
if ( it.asString() == id_r ) |
|
105 |
return true; |
|
106 |
return false; |
|
107 |
}
|
|
1
by Thomas-Karl Pietrowski
first import |
108 |
|
109 |
zypp::Date Repository::generatedTimestamp() const |
|
110 |
{
|
|
111 |
NO_REPOSITORY_RETURN( 0 ); |
|
112 |
sat::LookupRepoAttr q( sat::SolvAttr::repositoryTimestamp, *this ); |
|
113 |
return( q.empty() ? 0 : q.begin().asUnsigned() ); |
|
114 |
}
|
|
115 |
||
116 |
zypp::Date Repository::suggestedExpirationTimestamp() const |
|
117 |
{
|
|
118 |
NO_REPOSITORY_RETURN( 0 ); |
|
119 |
Date generated = generatedTimestamp(); |
|
120 |
if ( ! generated ) |
|
121 |
return 0; // do not calculate over a missing generated timestamp |
|
122 |
||
123 |
sat::LookupRepoAttr q( sat::SolvAttr::repositoryExpire, *this ); |
|
124 |
if ( q.empty() ) |
|
125 |
return 0; |
|
126 |
||
2
by Thomas-Karl Pietrowski
syncing code with latest from github |
127 |
return generated + Date(q.begin().asUnsigned()); |
1
by Thomas-Karl Pietrowski
first import |
128 |
}
|
129 |
||
130 |
Repository::Keywords Repository::keywords() const |
|
131 |
{
|
|
132 |
NO_REPOSITORY_RETURN( Keywords() ); |
|
133 |
return Keywords( sat::SolvAttr::repositoryKeywords, *this, sat::LookupAttr::REPO_ATTR ); |
|
134 |
}
|
|
135 |
||
2
by Thomas-Karl Pietrowski
syncing code with latest from github |
136 |
bool Repository::hasKeyword( const std::string & val_r ) const |
137 |
{
|
|
138 |
for ( const auto & val : keywords() ) |
|
139 |
if ( val == val_r ) |
|
140 |
return true; |
|
141 |
return false; |
|
142 |
}
|
|
143 |
||
1
by Thomas-Karl Pietrowski
first import |
144 |
bool Repository::maybeOutdated() const |
145 |
{
|
|
146 |
NO_REPOSITORY_RETURN( false ); |
|
147 |
// system repo is not mirrored
|
|
148 |
if ( isSystemRepo() ) |
|
149 |
return false; |
|
150 |
||
151 |
Date suggested = suggestedExpirationTimestamp(); |
|
152 |
||
153 |
// if no data, don't suggest
|
|
154 |
if ( ! suggested ) |
|
155 |
return false; |
|
156 |
||
157 |
return suggestedExpirationTimestamp() < Date::now(); |
|
158 |
}
|
|
159 |
||
2
by Thomas-Karl Pietrowski
syncing code with latest from github |
160 |
bool Repository::providesUpdatesFor( const CpeId & cpeid_r ) const |
1
by Thomas-Karl Pietrowski
first import |
161 |
{
|
162 |
NO_REPOSITORY_RETURN( false ); |
|
5
by Thomas-Karl Pietrowski
syncing again |
163 |
if ( ! cpeid_r ) |
164 |
return false; // filter queries/products without CpeId, as an empty CpeId matches ANYthing. |
|
165 |
||
166 |
// check in repository metadata
|
|
2
by Thomas-Karl Pietrowski
syncing code with latest from github |
167 |
for_( it, updatesProductBegin(), updatesProductEnd() ) |
1
by Thomas-Karl Pietrowski
first import |
168 |
{
|
2
by Thomas-Karl Pietrowski
syncing code with latest from github |
169 |
if ( compare( cpeid_r, it.cpeId(), SetRelation::subset ) ) |
170 |
return true; |
|
1
by Thomas-Karl Pietrowski
first import |
171 |
}
|
5
by Thomas-Karl Pietrowski
syncing again |
172 |
|
173 |
// check whether known products refer to this as update repo
|
|
174 |
sat::LookupRepoAttr myIds( sat::SolvAttr::repositoryRepoid, *this ); // usually just one, but... |
|
175 |
if ( ! myIds.empty() ) |
|
176 |
{
|
|
177 |
const ResPool & pool( ResPool::instance() ); |
|
178 |
for_( it, pool.byKindBegin<Product>(), pool.byKindEnd<Product>() ) |
|
179 |
{
|
|
180 |
Product::constPtr prod( (*it)->asKind<Product>() ); |
|
181 |
if ( compare( cpeid_r, prod->cpeId(), SetRelation::superset ) ) |
|
182 |
{
|
|
183 |
for_( myId, myIds.begin(), myIds.end() ) |
|
184 |
{
|
|
185 |
if ( prod->hasUpdateContentIdentifier( myId.asString() ) ) |
|
186 |
return true; |
|
187 |
}
|
|
188 |
}
|
|
189 |
}
|
|
190 |
}
|
|
1
by Thomas-Karl Pietrowski
first import |
191 |
return false; |
192 |
}
|
|
193 |
||
194 |
bool Repository::isUpdateRepo() const |
|
195 |
{
|
|
196 |
NO_REPOSITORY_RETURN( false ); |
|
5
by Thomas-Karl Pietrowski
syncing again |
197 |
|
198 |
// check in repository metadata
|
|
199 |
if ( updatesProductBegin() != updatesProductEnd() ) |
|
200 |
return true; |
|
201 |
||
202 |
// check whether known products refer to this as update repo
|
|
203 |
sat::LookupRepoAttr myIds( sat::SolvAttr::repositoryRepoid, *this ); // usually just one, but... |
|
204 |
if ( ! myIds.empty() ) |
|
205 |
{
|
|
206 |
const ResPool & pool( ResPool::instance() ); |
|
207 |
for_( it, pool.byKindBegin<Product>(), pool.byKindEnd<Product>() ) |
|
208 |
{
|
|
209 |
for_( myId, myIds.begin(), myIds.end() ) |
|
210 |
{
|
|
211 |
if ( (*it)->asKind<Product>()->hasUpdateContentIdentifier( myId.asString() ) ) |
|
212 |
return true; |
|
213 |
}
|
|
214 |
}
|
|
215 |
}
|
|
216 |
return false; |
|
1
by Thomas-Karl Pietrowski
first import |
217 |
}
|
218 |
||
219 |
bool Repository::solvablesEmpty() const |
|
220 |
{
|
|
221 |
NO_REPOSITORY_RETURN( true ); |
|
222 |
return !_repo->nsolvables; |
|
223 |
}
|
|
224 |
||
225 |
Repository::size_type Repository::solvablesSize() const |
|
226 |
{
|
|
227 |
NO_REPOSITORY_RETURN( 0 ); |
|
228 |
return _repo->nsolvables; |
|
229 |
}
|
|
230 |
||
231 |
Repository::SolvableIterator Repository::solvablesBegin() const |
|
232 |
{
|
|
233 |
NO_REPOSITORY_RETURN( make_filter_iterator( detail::ByRepository( *this ), |
|
234 |
sat::detail::SolvableIterator(), |
|
235 |
sat::detail::SolvableIterator() ) ); |
|
236 |
return make_filter_iterator( detail::ByRepository( *this ), |
|
237 |
sat::detail::SolvableIterator(_repo->start), |
|
238 |
sat::detail::SolvableIterator(_repo->end) ); |
|
239 |
}
|
|
240 |
||
241 |
Repository::SolvableIterator Repository::solvablesEnd() const |
|
242 |
{
|
|
243 |
NO_REPOSITORY_RETURN( make_filter_iterator( detail::ByRepository( *this ), |
|
244 |
sat::detail::SolvableIterator(), |
|
245 |
sat::detail::SolvableIterator() ) ); |
|
246 |
return make_filter_iterator(detail::ByRepository( *this ), |
|
247 |
sat::detail::SolvableIterator(_repo->end), |
|
248 |
sat::detail::SolvableIterator(_repo->end) ); |
|
249 |
}
|
|
250 |
||
251 |
Repository::ProductInfoIterator Repository::compatibleWithProductBegin() const |
|
252 |
{
|
|
253 |
NO_REPOSITORY_RETURN( ProductInfoIterator() ); |
|
254 |
return ProductInfoIterator( sat::SolvAttr::repositoryDistros, *this ); |
|
255 |
}
|
|
256 |
||
257 |
Repository::ProductInfoIterator Repository::compatibleWithProductEnd() const |
|
258 |
{
|
|
259 |
return ProductInfoIterator(); |
|
260 |
}
|
|
261 |
||
262 |
Repository::ProductInfoIterator Repository::updatesProductBegin() const |
|
263 |
{
|
|
264 |
NO_REPOSITORY_RETURN( ProductInfoIterator() ); |
|
265 |
return ProductInfoIterator( sat::SolvAttr::repositoryUpdates, *this ); |
|
266 |
}
|
|
267 |
||
268 |
Repository::ProductInfoIterator Repository::updatesProductEnd() const |
|
269 |
{
|
|
270 |
return ProductInfoIterator(); |
|
271 |
}
|
|
272 |
||
273 |
RepoInfo Repository::info() const |
|
274 |
{
|
|
275 |
NO_REPOSITORY_RETURN( RepoInfo() ); |
|
276 |
return myPool().repoInfo( _repo ); |
|
277 |
}
|
|
278 |
||
279 |
void Repository::setInfo( const RepoInfo & info_r ) |
|
280 |
{
|
|
281 |
NO_REPOSITORY_THROW( Exception( "Can't set RepoInfo for norepo." ) ); |
|
282 |
if ( info_r.alias() != alias() ) |
|
283 |
{
|
|
284 |
ZYPP_THROW( Exception( str::form( "RepoInfo alias (%s) does not match repository alias (%s)", |
|
285 |
info_r.alias().c_str(), alias().c_str() ) ) ); |
|
286 |
}
|
|
287 |
myPool().setRepoInfo( _repo, info_r ); |
|
288 |
MIL << *this << endl; |
|
289 |
}
|
|
290 |
||
291 |
void Repository::clearInfo() |
|
292 |
{
|
|
293 |
NO_REPOSITORY_RETURN(); |
|
294 |
myPool().setRepoInfo( _repo, RepoInfo() ); |
|
295 |
}
|
|
296 |
||
297 |
void Repository::eraseFromPool() |
|
298 |
{
|
|
299 |
NO_REPOSITORY_RETURN(); |
|
300 |
MIL << *this << " removed from pool" << endl; |
|
301 |
myPool()._deleteRepo( _repo ); |
|
302 |
_id = sat::detail::noRepoId; |
|
303 |
}
|
|
304 |
||
305 |
Repository Repository::nextInPool() const |
|
306 |
{
|
|
307 |
NO_REPOSITORY_RETURN( noRepository ); |
|
308 |
for_( it, sat::Pool::instance().reposBegin(), sat::Pool::instance().reposEnd() ) |
|
309 |
{
|
|
310 |
if ( *it == *this ) |
|
311 |
{
|
|
312 |
if ( ++it != _for_end ) |
|
313 |
return *it; |
|
314 |
break; |
|
315 |
}
|
|
316 |
}
|
|
317 |
return noRepository; |
|
318 |
}
|
|
319 |
||
320 |
void Repository::addSolv( const Pathname & file_r ) |
|
321 |
{
|
|
322 |
NO_REPOSITORY_THROW( Exception( "Can't add solvables to norepo." ) ); |
|
323 |
||
324 |
AutoDispose<FILE*> file( ::fopen( file_r.c_str(), "re" ), ::fclose ); |
|
325 |
if ( file == NULL ) |
|
326 |
{
|
|
327 |
file.resetDispose(); |
|
328 |
ZYPP_THROW( Exception( "Can't open solv-file: "+file_r.asString() ) ); |
|
329 |
}
|
|
330 |
||
331 |
if ( myPool()._addSolv( _repo, file ) != 0 ) |
|
332 |
{
|
|
333 |
ZYPP_THROW( Exception( "Error reading solv-file: "+file_r.asString() ) ); |
|
334 |
}
|
|
335 |
||
336 |
MIL << *this << " after adding " << file_r << endl; |
|
337 |
}
|
|
338 |
||
339 |
void Repository::addHelix( const Pathname & file_r ) |
|
340 |
{
|
|
341 |
NO_REPOSITORY_THROW( Exception( "Can't add solvables to norepo." ) ); |
|
342 |
||
343 |
std::string command( file_r.extension() == ".gz" ? "zcat " : "cat " ); |
|
344 |
command += file_r.asString(); |
|
345 |
||
346 |
AutoDispose<FILE*> file( ::popen( command.c_str(), "re" ), ::pclose ); |
|
347 |
if ( file == NULL ) |
|
348 |
{
|
|
349 |
file.resetDispose(); |
|
350 |
ZYPP_THROW( Exception( "Can't open helix-file: "+file_r.asString() ) ); |
|
351 |
}
|
|
352 |
||
353 |
if ( myPool()._addHelix( _repo, file ) != 0 ) |
|
354 |
{
|
|
355 |
ZYPP_THROW( Exception( "Error reading helix-file: "+file_r.asString() ) ); |
|
356 |
}
|
|
357 |
||
358 |
MIL << *this << " after adding " << file_r << endl; |
|
359 |
}
|
|
360 |
||
361 |
sat::detail::SolvableIdType Repository::addSolvables( unsigned count_r ) |
|
362 |
{
|
|
363 |
NO_REPOSITORY_THROW( Exception( "Can't add solvables to norepo.") ); |
|
364 |
return myPool()._addSolvables( _repo, count_r ); |
|
365 |
}
|
|
366 |
||
367 |
/******************************************************************
|
|
368 |
**
|
|
369 |
** FUNCTION NAME : operator<<
|
|
370 |
** FUNCTION TYPE : std::ostream &
|
|
371 |
*/
|
|
372 |
std::ostream & operator<<( std::ostream & str, const Repository & obj ) |
|
373 |
{
|
|
374 |
if ( ! obj ) |
|
375 |
return str << "noRepository"; |
|
376 |
||
377 |
return str << "sat::repo(" << obj.alias() << ")" |
|
378 |
<< "{" |
|
379 |
<< "prio " << obj.get()->priority << '.' << obj.get()->subpriority |
|
380 |
<< ", size " << obj.solvablesSize() |
|
381 |
<< "}"; |
|
382 |
}
|
|
383 |
||
384 |
std::ostream & dumpAsXmlOn( std::ostream & str, const Repository & obj ) |
|
385 |
{
|
|
386 |
return xmlout::node( str, "repository", { |
|
2
by Thomas-Karl Pietrowski
syncing code with latest from github |
387 |
{ "name", obj.name() }, |
388 |
{ "alias", obj.alias() } |
|
1
by Thomas-Karl Pietrowski
first import |
389 |
} ); |
390 |
}
|
|
391 |
||
392 |
//////////////////////////////////////////////////////////////////
|
|
393 |
namespace detail |
|
394 |
{
|
|
395 |
void RepositoryIterator::increment() |
|
396 |
{
|
|
397 |
if ( base() ) |
|
398 |
{
|
|
399 |
::_Pool * satpool = sat::Pool::instance().get(); |
|
400 |
do { |
|
401 |
++base_reference(); |
|
402 |
} while ( base() < satpool->repos+satpool->nrepos && !*base() ); |
|
403 |
}
|
|
404 |
}
|
|
405 |
} // namespace detail |
|
406 |
//////////////////////////////////////////////////////////////////
|
|
407 |
||
408 |
///////////////////////////////////////////////////////////////////
|
|
409 |
//
|
|
410 |
// Repository::ProductInfoIterator
|
|
411 |
//
|
|
412 |
///////////////////////////////////////////////////////////////////
|
|
413 |
||
414 |
Repository::ProductInfoIterator::ProductInfoIterator( sat::SolvAttr attr_r, Repository repo_r ) |
|
415 |
{ base_reference() = sat::LookupRepoAttr( attr_r, repo_r ).begin(); } |
|
416 |
||
417 |
std::string Repository::ProductInfoIterator::label() const |
|
418 |
{ return base_reference().subFind( sat::SolvAttr::repositoryProductLabel ).asString(); } |
|
419 |
||
2
by Thomas-Karl Pietrowski
syncing code with latest from github |
420 |
CpeId Repository::ProductInfoIterator::cpeId() const |
421 |
{ return CpeId( base_reference().subFind( sat::SolvAttr::repositoryProductCpeid ).asString(), CpeId::noThrow ); } |
|
1
by Thomas-Karl Pietrowski
first import |
422 |
|
423 |
/////////////////////////////////////////////////////////////////
|
|
424 |
} // namespace zypp |
|
425 |
///////////////////////////////////////////////////////////////////
|