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