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>
24 ///////////////////////////////////////////////////////////////////
26 { /////////////////////////////////////////////////////////////////
27 ///////////////////////////////////////////////////////////////////
29 { /////////////////////////////////////////////////////////////////
31 ///////////////////////////////////////////////////////////////////
34 ///////////////////////////////////////////////////////////////////
35 /// \class RepoMirrorListTempProvider
36 /// \brief Provide access to downloaded mirror list (in temp space)
39 /// Tempspace (and mirror list) are deleted when provider goes out
41 struct RepoMirrorListTempProvider
43 RepoMirrorListTempProvider()
45 RepoMirrorListTempProvider( const Pathname & localfile_r )
46 : _localfile( localfile_r )
48 RepoMirrorListTempProvider( const Url & url_r )
51 abs_url.setPathName( "/" );
52 abs_url.setQueryParam( "mediahandler", "curl" );
53 _access.reset( new MediaSetAccess( abs_url ) );
54 _localfile = _access->provideFile( url_r.getPathName() );
57 const Pathname & localfile() const
58 { return _localfile; }
61 shared_ptr<MediaSetAccess> _access;
64 ///////////////////////////////////////////////////////////////////
66 inline std::vector<Url> RepoMirrorListParseXML( const Pathname &tmpfile )
68 InputStream tmpfstream (tmpfile);
69 media::MetaLinkParser metalink;
70 metalink.parse(tmpfstream);
71 return metalink.getUrls();
74 inline std::vector<Url> RepoMirrorListParseTXT( const Pathname &tmpfile )
76 InputStream tmpfstream (tmpfile);
77 std::vector<Url> my_urls;
79 while (getline(tmpfstream.stream(), tmpurl))
81 if ( tmpurl[0] == '#' )
84 my_urls.push_back(Url(tmpurl));
87 {;} // ignore malformed urls
92 /** Parse a local mirrorlist \a listfile_r and return usable URLs */
93 inline std::vector<Url> RepoMirrorListParse( const Url & url_r, const Pathname & listfile_r, bool mirrorListForceMetalink_r )
95 USR << url_r << " " << listfile_r << endl;
97 std::vector<Url> mirrorurls;
98 if ( mirrorListForceMetalink_r || url_r.asString().find( "/metalink" ) != std::string::npos )
99 mirrorurls = RepoMirrorListParseXML( listfile_r );
101 mirrorurls = RepoMirrorListParseTXT( listfile_r );
104 std::vector<Url> ret;
105 for ( auto & murl : mirrorurls )
107 if ( murl.getScheme() != "rsync" )
109 size_t delpos = murl.getPathName().find("repodata/repomd.xml");
110 if( delpos != std::string::npos )
112 murl.setPathName( murl.getPathName().erase(delpos) );
114 ret.push_back( murl );
116 if ( ret.size() >= 4 ) // why 4?
124 ///////////////////////////////////////////////////////////////////
126 RepoMirrorList::RepoMirrorList( const Url & url_r, const Pathname & metadatapath_r, bool mirrorListForceMetalink_r )
128 if ( url_r.getScheme() == "file" )
130 // never cache for local mirrorlist
131 _urls = RepoMirrorListParse( url_r, url_r.getPathName(), mirrorListForceMetalink_r );
133 else if ( ! PathInfo( metadatapath_r).isDir() )
136 RepoMirrorListTempProvider provider( url_r ); // RAII: lifetime of any downloaded files
137 _urls = RepoMirrorListParse( url_r, provider.localfile(), mirrorListForceMetalink_r );
142 Pathname cachefile( metadatapath_r );
143 if ( mirrorListForceMetalink_r || url_r.asString().find( "/metalink" ) != std::string::npos )
144 cachefile /= "mirrorlist.xml";
146 cachefile /= "mirrorlist.txt";
148 zypp::filesystem::PathInfo cacheinfo( cachefile );
149 if ( !cacheinfo.isFile() || cacheinfo.mtime() < time(NULL) - (long) ZConfig::instance().repo_refresh_delay() * 60 )
151 DBG << "Getting MirrorList from URL: " << url_r << endl;
152 RepoMirrorListTempProvider provider( url_r ); // RAII: lifetime of downloaded file
154 // Create directory, if not existing
155 DBG << "Copy MirrorList file to " << cachefile << endl;
156 zypp::filesystem::assert_dir( metadatapath_r );
157 zypp::filesystem::hardlinkCopy( provider.localfile(), cachefile );
160 _urls = RepoMirrorListParse( url_r, cachefile, mirrorListForceMetalink_r );
163 DBG << "Removing Cachefile as it contains no URLs" << endl;
164 zypp::filesystem::unlink( cachefile );
169 /////////////////////////////////////////////////////////////////
171 ///////////////////////////////////////////////////////////////////
172 /////////////////////////////////////////////////////////////////
174 ///////////////////////////////////////////////////////////////////