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