1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/RepoManager.cc
16 #include "zypp/base/InputStream.h"
17 #include "zypp/base/Logger.h"
18 #include "zypp/base/Function.h"
19 #include "zypp/PathInfo.h"
20 #include "zypp/TmpPath.h"
22 #include "zypp/repo/RepoException.h"
23 #include "zypp/RepoManager.h"
25 #include "zypp/cache/CacheStore.h"
26 #include "zypp/repo/cached/RepoImpl.h"
27 #include "zypp/MediaSetAccess.h"
29 #include "zypp/parser/RepoFileReader.h"
30 #include "zypp/source/yum/YUMDownloader.h"
31 #include "zypp/parser/yum/RepoParser.h"
33 #include "zypp/source/susetags/SUSETagsDownloader.h"
34 #include "zypp/parser/susetags/RepoParser.h"
38 using namespace zypp::repo;
39 using namespace zypp::filesystem;
41 using zypp::source::yum::YUMDownloader;
42 using zypp::source::susetags::SUSETagsDownloader;
44 ///////////////////////////////////////////////////////////////////
46 { /////////////////////////////////////////////////////////////////
48 ///////////////////////////////////////////////////////////////////
50 // CLASS NAME : RepoManagerOptions
52 ///////////////////////////////////////////////////////////////////
54 RepoManagerOptions::RepoManagerOptions()
57 repoCachePath = globalConfig.defaultRepoCachePath();
58 repoRawCachePath = globalConfig.defaultRepoRawCachePath();
59 knownReposPath = globalConfig.defaultKnownReposPath();
63 * \short Simple callback to collect the results
77 bool collect( const RepoInfo &repo )
79 //MIL << "here in collector: " << repo.alias() << endl;
80 repos.push_back(repo);
81 //MIL << "added: " << repo.alias() << endl;
88 ////////////////////////////////////////////////////////////////////////////
91 * \short List of RepoInfo's from a directory
93 * Goes trough every file in a directory and adds all
94 * RepoInfo's contained in that file.
96 * \param file pathname of the file to read.
98 static std::list<RepoInfo> repositories_in_path( const Pathname &dir )
100 MIL << " " << dir << endl;
101 RepoCollector collector;
102 std::list<RepoInfo> repos;
103 list<Pathname> entries;
104 if ( filesystem::readdir( entries, Pathname(dir), false ) != 0 )
105 ZYPP_THROW(Exception("failed to read directory"));
107 for ( list<Pathname>::const_iterator it = entries.begin(); it != entries.end(); ++it )
110 parser::RepoFileReader parser( file, bind( &RepoCollector::collect, &collector, _1 ) );
112 //std::copy( collector.repos.begin(), collector.repos.end(), std::back_inserter(repos));
113 //MIL << "ok" << endl;
115 return collector.repos;
118 ////////////////////////////////////////////////////////////////////////////
120 static void assert_alias( const RepoInfo &info )
122 if (info.alias().empty())
123 ZYPP_THROW(RepoNoAliasException());
126 ////////////////////////////////////////////////////////////////////////////
128 static void assert_urls( const RepoInfo &info )
130 if (info.urls().empty())
131 ZYPP_THROW(RepoNoUrlException());
134 ////////////////////////////////////////////////////////////////////////////
137 * \short Calculates the raw cache path for a repository
139 static Pathname rawcache_path_for_repoinfo( const RepoManagerOptions &opt, const RepoInfo &info )
142 return opt.repoRawCachePath + info.alias();
145 ///////////////////////////////////////////////////////////////////
147 // CLASS NAME : RepoManager::Impl
149 ///////////////////////////////////////////////////////////////////
152 * \short RepoManager implementation.
154 struct RepoManager::Impl
156 Impl( const RepoManagerOptions &opt )
167 RepoManagerOptions options;
170 /** Offer default Impl. */
171 static shared_ptr<Impl> nullimpl()
173 static shared_ptr<Impl> _nullimpl( new Impl );
178 friend Impl * rwcowClone<Impl>( const Impl * rhs );
179 /** clone for RWCOW_pointer */
181 { return new Impl( *this ); }
183 ///////////////////////////////////////////////////////////////////
185 /** \relates RepoManager::Impl Stream output */
186 inline std::ostream & operator<<( std::ostream & str, const RepoManager::Impl & obj )
188 return str << "RepoManager::Impl";
191 ///////////////////////////////////////////////////////////////////
193 // CLASS NAME : RepoManager
195 ///////////////////////////////////////////////////////////////////
197 RepoManager::RepoManager( const RepoManagerOptions &opt )
198 : _pimpl( new Impl(opt) )
201 ////////////////////////////////////////////////////////////////////////////
203 RepoManager::~RepoManager()
206 ////////////////////////////////////////////////////////////////////////////
208 std::list<RepoInfo> RepoManager::knownRepositories() const
211 return repositories_in_path("/etc/zypp/repos.d");
215 ////////////////////////////////////////////////////////////////////////////
217 void RepoManager::refreshMetadata( const RepoInfo &info )
222 // try urls one by one
223 for ( RepoInfo::urls_const_iterator it = info.urlsBegin(); it != info.urlsEnd(); ++it )
226 filesystem::TmpDir tmpdir;
228 repo::RepoType repokind = info.type();
230 // if the type is unknown, try probing.
231 switch ( repokind.toEnum() )
233 case RepoType::NONE_e:
235 repokind = probe(*it);
241 switch ( repokind.toEnum() )
243 case RepoType::RPMMD_e :
245 YUMDownloader downloader( url, "/" );
246 downloader.download(tmpdir.path());
250 case RepoType::YAST2_e :
252 SUSETagsDownloader downloader( url, "/" );
253 downloader.download(tmpdir.path());
258 ZYPP_THROW(RepoUnknownTypeException());
261 // ok we have the metadata, now exchange
263 Pathname rawpath = rawcache_path_for_repoinfo(_pimpl->options, info);
265 filesystem::assert_dir(rawpath);
266 filesystem::rename( rawpath, oldmetadata.path() );
267 // move the just downloaded there
268 filesystem::rename( tmpdir.path(), rawpath );
274 ////////////////////////////////////////////////////////////////////////////
276 void RepoManager::cleanMetadata( const RepoInfo &info )
278 filesystem::recursive_rmdir(rawcache_path_for_repoinfo(_pimpl->options, info));
281 ////////////////////////////////////////////////////////////////////////////
283 void RepoManager::buildCache( const RepoInfo &info )
286 Pathname rawpath = rawcache_path_for_repoinfo(_pimpl->options, info);
288 cache::CacheStore store(_pimpl->options.repoCachePath);
290 if ( store.isCached( info.alias() ) )
292 MIL << info.alias() << " is already cached, cleaning..." << endl;
293 data::RecordId id = store.lookupRepository(info.alias());
294 store.cleanRepository(id);
297 data::RecordId id = store.lookupOrAppendRepository(info.alias());
300 repo::RepoType repokind = info.type();
302 // if the type is unknown, try probing.
303 switch ( repokind.toEnum() )
305 case RepoType::NONE_e:
306 // unknown, probe the local metadata
307 repokind = probe(Url(rawpath.asString()));
313 switch ( repokind.toEnum() )
315 case RepoType::RPMMD_e :
317 parser::yum::RepoParser parser(id, store);
318 parser.parse(rawpath);
322 case RepoType::YAST2_e :
324 parser::susetags::RepoParser parser(id, store);
325 parser.parse(rawpath);
330 ZYPP_THROW(RepoUnknownTypeException());
333 MIL << "Commit cache.." << endl;
337 ////////////////////////////////////////////////////////////////////////////
339 repo::RepoType RepoManager::probe( const Url &url )
341 MediaSetAccess access(url);
342 if ( access.doesFileExist("/repodata/repomd.xml") )
343 return repo::RepoType::RPMMD;
344 if ( access.doesFileExist("/content") )
345 return repo::RepoType::YAST2;
347 return repo::RepoType("UNKNOWN");
350 ////////////////////////////////////////////////////////////////////////////
352 void RepoManager::cleanCache( const RepoInfo &info )
354 cache::CacheStore store(_pimpl->options.repoCachePath);
356 data::RecordId id = store.lookupRepository(info.alias());
357 store.cleanRepository(id);
361 ////////////////////////////////////////////////////////////////////////////
363 bool RepoManager::isCached( const RepoInfo &info ) const
365 cache::CacheStore store(_pimpl->options.repoCachePath);
366 return store.isCached(info.alias());
369 Repository RepoManager::createFromCache( const RepoInfo &info )
371 cache::CacheStore store(_pimpl->options.repoCachePath);
373 if ( ! store.isCached( info.alias() ) )
374 ZYPP_THROW(RepoNotCachedException());
376 MIL << "Repository " << info.alias() << " is cached" << endl;
378 data::RecordId id = store.lookupRepository(info.alias());
379 repo::cached::RepoImpl::Ptr repoimpl =
380 new repo::cached::RepoImpl( info, _pimpl->options.repoCachePath, id );
381 // read the resolvables from cache
382 repoimpl->createResolvables();
383 return Repository(repoimpl);
386 ////////////////////////////////////////////////////////////////////////////
388 void RepoManager::addRepository( const RepoInfo &info )
393 ////////////////////////////////////////////////////////////////////////////
395 std::ostream & operator<<( std::ostream & str, const RepoManager & obj )
397 return str << *obj._pimpl;
400 /////////////////////////////////////////////////////////////////
402 ///////////////////////////////////////////////////////////////////