comment updated
[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 <iostream>
13
14 #include "zypp/base/Logger.h"
15 #include "zypp/base/Gettext.h"
16 #include "zypp/base/Exception.h"
17
18 #include "zypp/AutoDispose.h"
19 #include "zypp/Pathname.h"
20
21 #include "zypp/sat/detail/PoolImpl.h"
22 #include "zypp/Repository.h"
23 #include "zypp/sat/Pool.h"
24
25 using std::endl;
26
27 ///////////////////////////////////////////////////////////////////
28 namespace zypp
29 { /////////////////////////////////////////////////////////////////
30
31     const Repository Repository::noRepository;
32
33     const std::string & Repository::systemRepoAlias()
34     { return sat::detail::PoolImpl::systemRepoAlias(); }
35
36     /////////////////////////////////////////////////////////////////
37
38     ::_Repo * Repository::get() const
39     { return myPool().getRepo( _id ); }
40
41 #define NO_REPOSITORY_RETURN( VAL ) \
42     ::_Repo * _repo( get() ); \
43     if ( ! _repo ) return VAL
44
45 #define NO_REPOSITORY_THROW( VAL ) \
46     ::_Repo * _repo( get() ); \
47     if ( ! _repo ) ZYPP_THROW( VAL )
48
49     bool Repository::isSystemRepo() const
50     {
51         NO_REPOSITORY_RETURN( false );
52         return myPool().isSystemRepo( _repo );
53     }
54
55     std::string Repository::alias() const
56     {
57       NO_REPOSITORY_RETURN( std::string() );
58       if ( ! _repo->name )
59         return std::string();
60       return _repo->name;
61     }
62
63     zypp::Date Repository::generatedTimestamp() const
64     {
65       NO_REPOSITORY_RETURN( 0 );
66       sat::LookupRepoAttr q( sat::SolvAttr::repositoryTimestamp, *this );
67       return( q.empty() ? 0 : q.begin().asUnsigned() );
68     }
69
70     zypp::Date Repository::suggestedExpirationTimestamp() const
71     {
72       NO_REPOSITORY_RETURN( 0 );
73       Date generated = generatedTimestamp();
74       if ( ! generated )
75         return 0; // do not calculate over a missing generated timestamp
76
77       sat::LookupRepoAttr q( sat::SolvAttr::repositoryExpire, *this );
78       if ( q.empty() )
79         return 0;
80
81       return generated + q.begin().asUnsigned();
82     }
83
84     Repository::Keywords Repository::keywords() const
85     {
86       NO_REPOSITORY_RETURN( Keywords() );
87       return Keywords( sat::SolvAttr::repositoryKeywords, *this, sat::LookupAttr::REPO_ATTR );
88     }
89
90     bool Repository::maybeOutdated() const
91     {
92       NO_REPOSITORY_RETURN( false );
93       // system repo is not mirrored
94       if ( isSystemRepo() )
95         return false;
96
97       Date suggested = suggestedExpirationTimestamp();
98
99       // if no data, don't suggest
100       if ( ! suggested )
101         return false;
102
103       return suggestedExpirationTimestamp() < Date::now();
104     }
105
106     bool Repository::providesUpdatesFor( const std::string &key ) const
107     {
108       NO_REPOSITORY_RETURN( false );
109
110       for_( it,
111             updatesProductBegin(),
112             updatesProductEnd() )
113       {
114         // FIXME implement real CPE matching here
115         // someday
116         if ( key == it.cpeId() )
117           return true;
118       }
119
120       return false;
121     }
122
123     bool Repository::isUpdateRepo() const
124     {
125       NO_REPOSITORY_RETURN( false );
126       return ( updatesProductBegin() != updatesProductEnd() );
127     }
128
129     bool Repository::solvablesEmpty() const
130     {
131       NO_REPOSITORY_RETURN( true );
132       return !_repo->nsolvables;
133     }
134
135     Repository::size_type Repository::solvablesSize() const
136     {
137       NO_REPOSITORY_RETURN( 0 );
138       return _repo->nsolvables;
139     }
140
141     Repository::SolvableIterator Repository::solvablesBegin() const
142     {
143       NO_REPOSITORY_RETURN( make_filter_iterator( detail::ByRepository( *this ),
144                             sat::detail::SolvableIterator(),
145                             sat::detail::SolvableIterator() ) );
146       return make_filter_iterator( detail::ByRepository( *this ),
147                                    sat::detail::SolvableIterator(_repo->start),
148                                    sat::detail::SolvableIterator(_repo->end) );
149     }
150
151     Repository::SolvableIterator Repository::solvablesEnd() const
152     {
153       NO_REPOSITORY_RETURN( make_filter_iterator( detail::ByRepository( *this ),
154                             sat::detail::SolvableIterator(),
155                             sat::detail::SolvableIterator() ) );
156       return make_filter_iterator(detail::ByRepository( *this ),
157                                   sat::detail::SolvableIterator(_repo->end),
158                                   sat::detail::SolvableIterator(_repo->end) );
159     }
160
161     Repository::ProductInfoIterator Repository::compatibleWithProductBegin() const
162     {
163       NO_REPOSITORY_RETURN( ProductInfoIterator() );
164       return ProductInfoIterator( sat::SolvAttr::repositoryDistros, *this );
165     }
166
167     Repository::ProductInfoIterator Repository::compatibleWithProductEnd() const
168     {
169       return ProductInfoIterator();
170     }
171
172     Repository::ProductInfoIterator Repository::updatesProductBegin() const
173     {
174       NO_REPOSITORY_RETURN( ProductInfoIterator() );
175       return ProductInfoIterator( sat::SolvAttr::repositoryUpdates, *this );
176     }
177
178     Repository::ProductInfoIterator Repository::updatesProductEnd() const
179     {
180       return ProductInfoIterator();
181     }
182
183     RepoInfo Repository::info() const
184     {
185       NO_REPOSITORY_RETURN( RepoInfo() );
186       return myPool().repoInfo( _repo );
187     }
188
189     void Repository::setInfo( const RepoInfo & info_r )
190     {
191         NO_REPOSITORY_THROW( Exception( "Can't set RepoInfo for norepo." ) );
192         if ( info_r.alias() != alias() )
193         {
194             ZYPP_THROW( Exception( str::form( "RepoInfo alias (%s) does not match repository alias (%s)",
195                                               info_r.alias().c_str(), alias().c_str() ) ) );
196         }
197         myPool().setRepoInfo( _repo, info_r );
198
199         // satsolver priority is based on '<', while yum's repoinfo
200         // uses 1(highest)->99(lowest). Thus we use -info_r.priority.
201         _repo->priority = -info_r.priority();
202         // subpriority could be used to e.g. prefer http over dvd iff both have same priority.
203         // _repo->subpriority = 0;
204     }
205
206     void Repository::clearInfo()
207     {
208         NO_REPOSITORY_RETURN();
209         myPool().setRepoInfo( _repo, RepoInfo() );
210     }
211
212     void Repository::eraseFromPool()
213     {
214         NO_REPOSITORY_RETURN();
215         MIL << *this << " removed from pool" << endl;
216         myPool()._deleteRepo( _repo );
217         _id = sat::detail::noRepoId;
218     }
219
220     Repository Repository::nextInPool() const
221     {
222       NO_REPOSITORY_RETURN( noRepository );
223       for_( it, sat::Pool::instance().reposBegin(), sat::Pool::instance().reposEnd() )
224       {
225         if ( *it == *this )
226         {
227           if ( ++it != _for_end )
228             return *it;
229           break;
230         }
231       }
232       return noRepository;
233     }
234
235     void Repository::addSolv( const Pathname & file_r )
236     {
237       NO_REPOSITORY_THROW( Exception( "Can't add solvables to norepo." ) );
238
239       AutoDispose<FILE*> file( ::fopen( file_r.c_str(), "r" ), ::fclose );
240       if ( file == NULL )
241       {
242         file.resetDispose();
243         ZYPP_THROW( Exception( "Can't open solv-file: "+file_r.asString() ) );
244       }
245
246       if ( myPool()._addSolv( _repo, file ) != 0 )
247       {
248         ZYPP_THROW( Exception( "Error reading solv-file: "+file_r.asString() ) );
249       }
250
251       MIL << *this << " after adding " << file_r << endl;
252     }
253
254     void Repository::addHelix( const Pathname & file_r )
255     {
256       NO_REPOSITORY_THROW( Exception( "Can't add solvables to norepo." ) );
257
258       std::string command( file_r.extension() == ".gz" ? "zcat " : "cat " );
259       command += file_r.asString();
260
261       AutoDispose<FILE*> file( ::popen( command.c_str(), "r" ), ::pclose );
262       if ( file == NULL )
263       {
264         file.resetDispose();
265         ZYPP_THROW( Exception( "Can't open helix-file: "+file_r.asString() ) );
266       }
267
268       if ( myPool()._addHelix( _repo, file ) != 0 )
269       {
270         ZYPP_THROW( Exception( "Error reading helix-file: "+file_r.asString() ) );
271       }
272
273       MIL << *this << " after adding " << file_r << endl;
274     }
275
276     sat::detail::SolvableIdType Repository::addSolvables( unsigned count_r )
277     {
278         NO_REPOSITORY_THROW( Exception( "Can't add solvables to norepo.") );
279         return myPool()._addSolvables( _repo, count_r );
280     }
281
282     /******************************************************************
283      **
284      ** FUNCTION NAME : operator<<
285      ** FUNCTION TYPE : std::ostream &
286      */
287     std::ostream & operator<<( std::ostream & str, const Repository & obj )
288     {
289         if ( ! obj )
290             return str << "noRepository";
291
292         return str << "sat::repo(" << obj.alias() << ")"
293                    << "{"
294                    << "prio " << obj.get()->priority
295                    << ", size " << obj.solvablesSize()
296                    << "}";
297     }
298
299     ///////////////////////////////////////////////////////////////////
300     //
301     // Repository::ProductInfoIterator
302     //
303     ///////////////////////////////////////////////////////////////////
304
305     Repository::ProductInfoIterator::ProductInfoIterator( sat::SolvAttr attr_r, Repository repo_r )
306     { base_reference() = sat::LookupRepoAttr( attr_r, repo_r ).begin(); }
307
308     std::string Repository::ProductInfoIterator::label() const
309     { return base_reference().subFind( sat::SolvAttr::repositoryProductLabel ).asString(); }
310
311     std::string Repository::ProductInfoIterator::cpeId() const
312     { return base_reference().subFind( sat::SolvAttr::repositoryProductCpeid ).asString(); }
313
314     /////////////////////////////////////////////////////////////////
315 } // namespace zypp
316 ///////////////////////////////////////////////////////////////////