1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/repo/RepoMirrorList.cc
16 #include "zypp/repo/RepoMirrorList.h"
17 #include "zypp/media/MetaLinkParser.h"
18 #include "zypp/MediaSetAccess.h"
19 #include "zypp/base/LogTools.h"
20 #include "zypp/ZConfig.h"
21 #include "zypp/PathInfo.h"
25 ///////////////////////////////////////////////////////////////////
27 { /////////////////////////////////////////////////////////////////
28 ///////////////////////////////////////////////////////////////////
30 { /////////////////////////////////////////////////////////////////
32 ///////////////////////////////////////////////////////////////////
35 ///////////////////////////////////////////////////////////////////
36 /// \class RepoMirrorListTempProvider
37 /// \brief Provide access to downloaded mirror list (in temp space)
40 /// Tempspace (and mirror list) are deleted when provider goes out
42 struct RepoMirrorListTempProvider
44 RepoMirrorListTempProvider()
46 RepoMirrorListTempProvider( const Pathname & localfile_r )
47 : _localfile( localfile_r )
49 RepoMirrorListTempProvider( const Url & url_r )
52 abs_url.setPathName( "/" );
53 abs_url.setQueryParam( "mediahandler", "curl" );
54 _access.reset( new MediaSetAccess( abs_url ) );
55 _localfile = _access->provideFile( url_r.getPathName() );
58 const Pathname & localfile() const
59 { return _localfile; }
62 shared_ptr<MediaSetAccess> _access;
65 ///////////////////////////////////////////////////////////////////
67 inline std::vector<Url> RepoMirrorListParseXML( const Pathname &tmpfile )
69 InputStream tmpfstream (tmpfile);
70 media::MetaLinkParser metalink;
71 metalink.parse(tmpfstream);
72 return metalink.getUrls();
75 inline std::vector<Url> RepoMirrorListParseTXT( const Pathname &tmpfile )
77 InputStream tmpfstream (tmpfile);
78 std::vector<Url> my_urls;
80 while (getline(tmpfstream.stream(), tmpurl))
82 my_urls.push_back(Url(tmpurl));
87 /** Parse a local mirrorlist \a listfile_r and return usable URLs */
88 inline std::vector<Url> RepoMirrorListParse( const Url & url_r, const Pathname & listfile_r )
90 USR << url_r << " " << listfile_r << endl;
92 std::vector<Url> mirrorurls;
93 if ( url_r.asString().find( "/metalink" ) != string::npos )
94 mirrorurls = RepoMirrorListParseXML( listfile_r );
96 mirrorurls = RepoMirrorListParseTXT( listfile_r );
100 for ( auto & murl : mirrorurls )
102 if ( murl.getScheme() != "rsync" )
104 size_t delpos = murl.getPathName().find("repodata/repomd.xml");
105 if( delpos != string::npos )
107 murl.setPathName( murl.getPathName().erase(delpos) );
109 ret.push_back( murl );
111 if ( ret.size() >= 4 ) // why 4?
119 ///////////////////////////////////////////////////////////////////
122 RepoMirrorList::RepoMirrorList( const Url & url_r, const Pathname & metadatapath_r )
124 if ( url_r.getScheme() == "file" )
126 // never cache for local mirrorlist
127 _urls = RepoMirrorListParse( url_r, url_r.getPathName() );
129 else if ( ! PathInfo( metadatapath_r).isDir() )
132 RepoMirrorListTempProvider provider( url_r ); // RAII: lifetime of any downloaded files
133 _urls = RepoMirrorListParse( url_r, provider.localfile() );
138 Pathname cachefile( metadatapath_r );
139 if ( url_r.asString().find( "/metalink" ) != string::npos )
140 cachefile /= "mirrorlist.xml";
142 cachefile /= "mirrorlist.txt";
144 zypp::filesystem::PathInfo cacheinfo( cachefile );
145 if ( !cacheinfo.isFile() || cacheinfo.mtime() < time(NULL) - (long) ZConfig::instance().repo_refresh_delay() * 60 )
147 DBG << "Getting MirrorList from URL: " << url_r << endl;
148 RepoMirrorListTempProvider provider( url_r ); // RAII: lifetime of downloaded file
150 // Create directory, if not existing
151 DBG << "Copy MirrorList file to " << cachefile << endl;
152 zypp::filesystem::assert_dir( metadatapath_r );
153 zypp::filesystem::hardlinkCopy( provider.localfile(), cachefile );
156 _urls = RepoMirrorListParse( url_r, cachefile );
159 DBG << "Removing Cachefile as it contains no URLs" << endl;
160 zypp::filesystem::unlink( cachefile );
165 /////////////////////////////////////////////////////////////////
167 ///////////////////////////////////////////////////////////////////
168 /////////////////////////////////////////////////////////////////
170 ///////////////////////////////////////////////////////////////////