Support CpeId in Repository and Product attributes (Fate#316160)
[platform/upstream/libzypp.git] / zypp / Repository.cc
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"
25 #include "zypp/sat/Pool.h"
26
27 using std::endl;
28
29 ///////////////////////////////////////////////////////////////////
30 namespace zypp
31 { /////////////////////////////////////////////////////////////////
32
33     const Repository Repository::noRepository;
34
35     const std::string & Repository::systemRepoAlias()
36     { return sat::detail::PoolImpl::systemRepoAlias(); }
37
38     /////////////////////////////////////////////////////////////////
39
40     ::_Repo * Repository::get() const
41     { return myPool().getRepo( _id ); }
42
43 #define NO_REPOSITORY_RETURN( VAL ) \
44     ::_Repo * _repo( get() ); \
45     if ( ! _repo ) return VAL
46
47 #define NO_REPOSITORY_THROW( VAL ) \
48     ::_Repo * _repo( get() ); \
49     if ( ! _repo ) ZYPP_THROW( VAL )
50
51     bool Repository::isSystemRepo() const
52     {
53         NO_REPOSITORY_RETURN( false );
54         return myPool().isSystemRepo( _repo );
55     }
56
57     std::string Repository::alias() const
58     {
59       NO_REPOSITORY_RETURN( std::string() );
60       if ( ! _repo->name )
61         return std::string();
62       return _repo->name;
63     }
64
65     std::string Repository::name() const
66     { return info().name(); }
67
68     int Repository::satInternalPriority() const
69     {
70       NO_REPOSITORY_RETURN( INT_MIN );
71       return _repo->priority;
72     }
73
74     int Repository::satInternalSubPriority() const
75     {
76       NO_REPOSITORY_RETURN( INT_MIN );
77       return _repo->subpriority;
78     }
79
80     Repository::ContentRevision Repository::contentRevision() const
81     {
82       NO_REPOSITORY_RETURN( ContentRevision() );
83       sat::LookupRepoAttr q( sat::SolvAttr::repositoryRevision, *this );
84       return q.empty() ? std::string() : q.begin().asString();
85     }
86
87     Repository::ContentIdentifier Repository::contentIdentifier() const
88     {
89       NO_REPOSITORY_RETURN( ContentIdentifier() );
90       sat::LookupRepoAttr q( sat::SolvAttr::repositoryRepoid, *this );
91       return q.empty() ? std::string() : q.begin().asString();
92     }
93
94     zypp::Date Repository::generatedTimestamp() const
95     {
96       NO_REPOSITORY_RETURN( 0 );
97       sat::LookupRepoAttr q( sat::SolvAttr::repositoryTimestamp, *this );
98       return( q.empty() ? 0 : q.begin().asUnsigned() );
99     }
100
101     zypp::Date Repository::suggestedExpirationTimestamp() const
102     {
103       NO_REPOSITORY_RETURN( 0 );
104       Date generated = generatedTimestamp();
105       if ( ! generated )
106         return 0; // do not calculate over a missing generated timestamp
107
108       sat::LookupRepoAttr q( sat::SolvAttr::repositoryExpire, *this );
109       if ( q.empty() )
110         return 0;
111
112       return generated + Date(q.begin().asUnsigned());
113     }
114
115     Repository::Keywords Repository::keywords() const
116     {
117       NO_REPOSITORY_RETURN( Keywords() );
118       return Keywords( sat::SolvAttr::repositoryKeywords, *this, sat::LookupAttr::REPO_ATTR );
119     }
120
121     bool Repository::hasKeyword( const std::string & val_r ) const
122     {
123       for ( const auto & val : keywords() )
124         if ( val == val_r )
125           return true;
126       return false;
127     }
128
129     bool Repository::maybeOutdated() const
130     {
131       NO_REPOSITORY_RETURN( false );
132       // system repo is not mirrored
133       if ( isSystemRepo() )
134         return false;
135
136       Date suggested = suggestedExpirationTimestamp();
137
138       // if no data, don't suggest
139       if ( ! suggested )
140         return false;
141
142       return suggestedExpirationTimestamp() < Date::now();
143     }
144
145     bool Repository::providesUpdatesFor( const CpeId & cpeid_r ) const
146     {
147       NO_REPOSITORY_RETURN( false );
148       for_( it, updatesProductBegin(), updatesProductEnd() )
149       {
150         if ( cpeid_r.match( it.cpeId() ) == CpeId::Match::subset )
151           return true;
152       }
153       return false;
154     }
155
156     bool Repository::isUpdateRepo() const
157     {
158       NO_REPOSITORY_RETURN( false );
159       return ( updatesProductBegin() != updatesProductEnd() );
160     }
161
162     bool Repository::solvablesEmpty() const
163     {
164       NO_REPOSITORY_RETURN( true );
165       return !_repo->nsolvables;
166     }
167
168     Repository::size_type Repository::solvablesSize() const
169     {
170       NO_REPOSITORY_RETURN( 0 );
171       return _repo->nsolvables;
172     }
173
174     Repository::SolvableIterator Repository::solvablesBegin() const
175     {
176       NO_REPOSITORY_RETURN( make_filter_iterator( detail::ByRepository( *this ),
177                             sat::detail::SolvableIterator(),
178                             sat::detail::SolvableIterator() ) );
179       return make_filter_iterator( detail::ByRepository( *this ),
180                                    sat::detail::SolvableIterator(_repo->start),
181                                    sat::detail::SolvableIterator(_repo->end) );
182     }
183
184     Repository::SolvableIterator Repository::solvablesEnd() const
185     {
186       NO_REPOSITORY_RETURN( make_filter_iterator( detail::ByRepository( *this ),
187                             sat::detail::SolvableIterator(),
188                             sat::detail::SolvableIterator() ) );
189       return make_filter_iterator(detail::ByRepository( *this ),
190                                   sat::detail::SolvableIterator(_repo->end),
191                                   sat::detail::SolvableIterator(_repo->end) );
192     }
193
194     Repository::ProductInfoIterator Repository::compatibleWithProductBegin() const
195     {
196       NO_REPOSITORY_RETURN( ProductInfoIterator() );
197       return ProductInfoIterator( sat::SolvAttr::repositoryDistros, *this );
198     }
199
200     Repository::ProductInfoIterator Repository::compatibleWithProductEnd() const
201     {
202       return ProductInfoIterator();
203     }
204
205     Repository::ProductInfoIterator Repository::updatesProductBegin() const
206     {
207       NO_REPOSITORY_RETURN( ProductInfoIterator() );
208       return ProductInfoIterator( sat::SolvAttr::repositoryUpdates, *this );
209     }
210
211     Repository::ProductInfoIterator Repository::updatesProductEnd() const
212     {
213       return ProductInfoIterator();
214     }
215
216     RepoInfo Repository::info() const
217     {
218       NO_REPOSITORY_RETURN( RepoInfo() );
219       return myPool().repoInfo( _repo );
220     }
221
222     void Repository::setInfo( const RepoInfo & info_r )
223     {
224         NO_REPOSITORY_THROW( Exception( "Can't set RepoInfo for norepo." ) );
225         if ( info_r.alias() != alias() )
226         {
227             ZYPP_THROW( Exception( str::form( "RepoInfo alias (%s) does not match repository alias (%s)",
228                                               info_r.alias().c_str(), alias().c_str() ) ) );
229         }
230         myPool().setRepoInfo( _repo, info_r );
231         MIL << *this << endl;
232     }
233
234     void Repository::clearInfo()
235     {
236         NO_REPOSITORY_RETURN();
237         myPool().setRepoInfo( _repo, RepoInfo() );
238     }
239
240     void Repository::eraseFromPool()
241     {
242         NO_REPOSITORY_RETURN();
243         MIL << *this << " removed from pool" << endl;
244         myPool()._deleteRepo( _repo );
245         _id = sat::detail::noRepoId;
246     }
247
248     Repository Repository::nextInPool() const
249     {
250       NO_REPOSITORY_RETURN( noRepository );
251       for_( it, sat::Pool::instance().reposBegin(), sat::Pool::instance().reposEnd() )
252       {
253         if ( *it == *this )
254         {
255           if ( ++it != _for_end )
256             return *it;
257           break;
258         }
259       }
260       return noRepository;
261     }
262
263     void Repository::addSolv( const Pathname & file_r )
264     {
265       NO_REPOSITORY_THROW( Exception( "Can't add solvables to norepo." ) );
266
267       AutoDispose<FILE*> file( ::fopen( file_r.c_str(), "re" ), ::fclose );
268       if ( file == NULL )
269       {
270         file.resetDispose();
271         ZYPP_THROW( Exception( "Can't open solv-file: "+file_r.asString() ) );
272       }
273
274       if ( myPool()._addSolv( _repo, file ) != 0 )
275       {
276         ZYPP_THROW( Exception( "Error reading solv-file: "+file_r.asString() ) );
277       }
278
279       MIL << *this << " after adding " << file_r << endl;
280     }
281
282     void Repository::addHelix( const Pathname & file_r )
283     {
284       NO_REPOSITORY_THROW( Exception( "Can't add solvables to norepo." ) );
285
286       std::string command( file_r.extension() == ".gz" ? "zcat " : "cat " );
287       command += file_r.asString();
288
289       AutoDispose<FILE*> file( ::popen( command.c_str(), "re" ), ::pclose );
290       if ( file == NULL )
291       {
292         file.resetDispose();
293         ZYPP_THROW( Exception( "Can't open helix-file: "+file_r.asString() ) );
294       }
295
296       if ( myPool()._addHelix( _repo, file ) != 0 )
297       {
298         ZYPP_THROW( Exception( "Error reading helix-file: "+file_r.asString() ) );
299       }
300
301       MIL << *this << " after adding " << file_r << endl;
302     }
303
304     sat::detail::SolvableIdType Repository::addSolvables( unsigned count_r )
305     {
306         NO_REPOSITORY_THROW( Exception( "Can't add solvables to norepo.") );
307         return myPool()._addSolvables( _repo, count_r );
308     }
309
310     /******************************************************************
311      **
312      ** FUNCTION NAME : operator<<
313      ** FUNCTION TYPE : std::ostream &
314      */
315     std::ostream & operator<<( std::ostream & str, const Repository & obj )
316     {
317         if ( ! obj )
318             return str << "noRepository";
319
320         return str << "sat::repo(" << obj.alias() << ")"
321                    << "{"
322                    << "prio " << obj.get()->priority << '.' << obj.get()->subpriority
323                    << ", size " << obj.solvablesSize()
324                    << "}";
325     }
326
327     std::ostream & dumpAsXmlOn( std::ostream & str, const Repository & obj )
328     {
329       return xmlout::node( str, "repository", {
330         { "alias", obj.name() },
331         { "name", obj.alias() }
332       } );
333     }
334
335     //////////////////////////////////////////////////////////////////
336     namespace detail
337     {
338       void RepositoryIterator::increment()
339       {
340         if ( base() )
341         {
342           ::_Pool * satpool = sat::Pool::instance().get();
343           do {
344             ++base_reference();
345           } while ( base() < satpool->repos+satpool->nrepos && !*base() );
346         }
347       }
348     } // namespace detail
349     //////////////////////////////////////////////////////////////////
350
351     ///////////////////////////////////////////////////////////////////
352     //
353     // Repository::ProductInfoIterator
354     //
355     ///////////////////////////////////////////////////////////////////
356
357     Repository::ProductInfoIterator::ProductInfoIterator( sat::SolvAttr attr_r, Repository repo_r )
358     { base_reference() = sat::LookupRepoAttr( attr_r, repo_r ).begin(); }
359
360     std::string Repository::ProductInfoIterator::label() const
361     { return base_reference().subFind( sat::SolvAttr::repositoryProductLabel ).asString(); }
362
363     CpeId Repository::ProductInfoIterator::cpeId() const
364     { return CpeId( base_reference().subFind( sat::SolvAttr::repositoryProductCpeid ).asString(), CpeId::noThrow ); }
365
366     /////////////////////////////////////////////////////////////////
367 } // namespace zypp
368 ///////////////////////////////////////////////////////////////////