libzypp  13.10.6
RepoManager.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
13 #include <cstdlib>
14 #include <iostream>
15 #include <fstream>
16 #include <sstream>
17 #include <list>
18 #include <map>
19 #include <algorithm>
20 
21 #include "zypp/base/InputStream.h"
22 #include "zypp/base/LogTools.h"
23 #include "zypp/base/Gettext.h"
24 #include "zypp/base/Function.h"
25 #include "zypp/base/Regex.h"
26 #include "zypp/PathInfo.h"
27 #include "zypp/TmpPath.h"
28 
29 #include "zypp/ServiceInfo.h"
31 #include "zypp/RepoManager.h"
32 
35 #include "zypp/MediaSetAccess.h"
36 #include "zypp/ExternalProgram.h"
37 #include "zypp/ManagedFile.h"
38 
41 #include "zypp/repo/ServiceRepos.h"
46 
47 #include "zypp/Target.h" // for Target::targetDistribution() for repo index services
48 #include "zypp/ZYppFactory.h" // to get the Target from ZYpp instance
49 #include "zypp/HistoryLog.h" // to write history :O)
50 
51 #include "zypp/ZYppCallbacks.h"
52 
53 #include "sat/Pool.h"
54 
55 using std::endl;
56 using std::string;
57 using namespace zypp::repo;
58 
59 #define OPT_PROGRESS const ProgressData::ReceiverFnc & = ProgressData::ReceiverFnc()
60 
62 namespace zypp
63 {
65  namespace
66  {
70  class MediaMounter
71  {
72  public:
74  MediaMounter( const Url & url_r )
75  {
76  media::MediaManager mediamanager;
77  _mid = mediamanager.open( url_r );
78  mediamanager.attach( _mid );
79  }
80 
82  ~MediaMounter()
83  {
84  media::MediaManager mediamanager;
85  mediamanager.release( _mid );
86  mediamanager.close( _mid );
87  }
88 
93  Pathname getPathName( const Pathname & path_r = Pathname() ) const
94  {
95  media::MediaManager mediamanager;
96  return mediamanager.localPath( _mid, path_r );
97  }
98 
99  private:
101  };
103 
105  template <class Iterator>
106  inline bool foundAliasIn( const std::string & alias_r, Iterator begin_r, Iterator end_r )
107  {
108  for_( it, begin_r, end_r )
109  if ( it->alias() == alias_r )
110  return true;
111  return false;
112  }
114  template <class Container>
115  inline bool foundAliasIn( const std::string & alias_r, const Container & cont_r )
116  { return foundAliasIn( alias_r, cont_r.begin(), cont_r.end() ); }
117 
119  template <class Iterator>
120  inline Iterator findAlias( const std::string & alias_r, Iterator begin_r, Iterator end_r )
121  {
122  for_( it, begin_r, end_r )
123  if ( it->alias() == alias_r )
124  return it;
125  return end_r;
126  }
128  template <class Container>
129  inline typename Container::iterator findAlias( const std::string & alias_r, Container & cont_r )
130  { return findAlias( alias_r, cont_r.begin(), cont_r.end() ); }
132  template <class Container>
133  inline typename Container::const_iterator findAlias( const std::string & alias_r, const Container & cont_r )
134  { return findAlias( alias_r, cont_r.begin(), cont_r.end() ); }
135 
136 
138  inline std::string filenameFromAlias( const std::string & alias_r, const std::string & stem_r )
139  {
140  std::string filename( alias_r );
141  // replace slashes with underscores
142  str::replaceAll( filename, "/", "_" );
143 
144  filename = Pathname(filename).extend("."+stem_r).asString();
145  MIL << "generating filename for " << stem_r << " [" << alias_r << "] : '" << filename << "'" << endl;
146  return filename;
147  }
148 
164  struct RepoCollector : private base::NonCopyable
165  {
166  RepoCollector()
167  {}
168 
169  RepoCollector(const std::string & targetDistro_)
170  : targetDistro(targetDistro_)
171  {}
172 
173  bool collect( const RepoInfo &repo )
174  {
175  // skip repositories meant for other distros than specified
176  if (!targetDistro.empty()
177  && !repo.targetDistribution().empty()
178  && repo.targetDistribution() != targetDistro)
179  {
180  MIL
181  << "Skipping repository meant for '" << targetDistro
182  << "' distribution (current distro is '"
183  << repo.targetDistribution() << "')." << endl;
184 
185  return true;
186  }
187 
188  repos.push_back(repo);
189  return true;
190  }
191 
192  RepoInfoList repos;
193  std::string targetDistro;
194  };
196 
202  std::list<RepoInfo> repositories_in_file( const Pathname & file )
203  {
204  MIL << "repo file: " << file << endl;
205  RepoCollector collector;
206  parser::RepoFileReader parser( file, bind( &RepoCollector::collect, &collector, _1 ) );
207  return collector.repos;
208  }
209 
211 
220  std::list<RepoInfo> repositories_in_dir( const Pathname &dir )
221  {
222  MIL << "directory " << dir << endl;
223  std::list<RepoInfo> repos;
224  std::list<Pathname> entries;
225  if ( filesystem::readdir( entries, dir, false ) != 0 )
226  {
227  // TranslatorExplanation '%s' is a pathname
228  ZYPP_THROW(Exception(str::form(_("Failed to read directory '%s'"), dir.c_str())));
229  }
230 
231  str::regex allowedRepoExt("^\\.repo(_[0-9]+)?$");
232  for ( std::list<Pathname>::const_iterator it = entries.begin(); it != entries.end(); ++it )
233  {
234  if (str::regex_match(it->extension(), allowedRepoExt))
235  {
236  std::list<RepoInfo> tmp = repositories_in_file( *it );
237  repos.insert( repos.end(), tmp.begin(), tmp.end() );
238 
239  //std::copy( collector.repos.begin(), collector.repos.end(), std::back_inserter(repos));
240  //MIL << "ok" << endl;
241  }
242  }
243  return repos;
244  }
245 
247 
248  inline void assert_alias( const RepoInfo & info )
249  {
250  if ( info.alias().empty() )
252  // bnc #473834. Maybe we can match the alias against a regex to define
253  // and check for valid aliases
254  if ( info.alias()[0] == '.')
256  info, _("Repository alias cannot start with dot.")));
257  }
258 
259  inline void assert_alias( const ServiceInfo & info )
260  {
261  if ( info.alias().empty() )
263  // bnc #473834. Maybe we can match the alias against a regex to define
264  // and check for valid aliases
265  if ( info.alias()[0] == '.')
267  info, _("Service alias cannot start with dot.")));
268  }
269 
271 
272  inline void assert_urls( const RepoInfo & info )
273  {
274  if ( info.baseUrlsEmpty() )
275  ZYPP_THROW( RepoNoUrlException( info ) );
276  }
277 
278  inline void assert_url( const ServiceInfo & info )
279  {
280  if ( ! info.url().isValid() )
282  }
283 
285 
290  inline Pathname rawcache_path_for_repoinfo( const RepoManagerOptions &opt, const RepoInfo &info )
291  {
292  assert_alias(info);
293  return opt.repoRawCachePath / info.escaped_alias();
294  }
295 
304  inline Pathname rawproductdata_path_for_repoinfo( const RepoManagerOptions &opt, const RepoInfo &info )
305  {
306  assert_alias(info);
307  return opt.repoRawCachePath / info.escaped_alias() / info.path();
308  }
309 
313  inline Pathname packagescache_path_for_repoinfo( const RepoManagerOptions &opt, const RepoInfo &info )
314  {
315  assert_alias(info);
316  return opt.repoPackagesCachePath / info.escaped_alias();
317  }
318 
322  inline Pathname solv_path_for_repoinfo( const RepoManagerOptions &opt, const RepoInfo &info)
323  {
324  assert_alias(info);
325  return opt.repoSolvCachePath / info.escaped_alias();
326  }
327 
329 
331  class ServiceCollector
332  {
333  public:
334  typedef std::set<ServiceInfo> ServiceSet;
335 
336  ServiceCollector( ServiceSet & services_r )
337  : _services( services_r )
338  {}
339 
340  bool operator()( const ServiceInfo & service_r ) const
341  {
342  _services.insert( service_r );
343  return true;
344  }
345 
346  private:
347  ServiceSet & _services;
348  };
350 
351  } // namespace
353 
354  std::list<RepoInfo> readRepoFile( const Url & repo_file )
355  {
356  // no interface to download a specific file, using workaround:
358  Url url(repo_file);
359  Pathname path(url.getPathName());
360  url.setPathName ("/");
361  MediaSetAccess access(url);
362  Pathname local = access.provideFile(path);
363 
364  DBG << "reading repo file " << repo_file << ", local path: " << local << endl;
365 
366  return repositories_in_file(local);
367  }
368 
370  //
371  // class RepoManagerOptions
372  //
374 
375  RepoManagerOptions::RepoManagerOptions( const Pathname & root_r )
376  {
377  repoCachePath = Pathname::assertprefix( root_r, ZConfig::instance().repoCachePath() );
378  repoRawCachePath = Pathname::assertprefix( root_r, ZConfig::instance().repoMetadataPath() );
379  repoSolvCachePath = Pathname::assertprefix( root_r, ZConfig::instance().repoSolvfilesPath() );
380  repoPackagesCachePath = Pathname::assertprefix( root_r, ZConfig::instance().repoPackagesPath() );
381  knownReposPath = Pathname::assertprefix( root_r, ZConfig::instance().knownReposPath() );
382  knownServicesPath = Pathname::assertprefix( root_r, ZConfig::instance().knownServicesPath() );
383  pluginsPath = Pathname::assertprefix( root_r, ZConfig::instance().pluginsPath() );
384  probe = ZConfig::instance().repo_add_probe();
385 
386  rootDir = root_r;
387  }
388 
390  {
391  RepoManagerOptions ret;
392  ret.repoCachePath = root_r;
393  ret.repoRawCachePath = root_r/"raw";
394  ret.repoSolvCachePath = root_r/"solv";
395  ret.repoPackagesCachePath = root_r/"packages";
396  ret.knownReposPath = root_r/"repos.d";
397  ret.knownServicesPath = root_r/"services.d";
398  ret.pluginsPath = root_r/"plugins";
399  ret.rootDir = root_r;
400  return ret;
401  }
402 
403  std:: ostream & operator<<( std::ostream & str, const RepoManagerOptions & obj )
404  {
405 #define OUTS(X) str << " " #X "\t" << obj.X << endl
406  str << "RepoManagerOptions (" << obj.rootDir << ") {" << endl;
407  OUTS( repoRawCachePath );
408  OUTS( repoSolvCachePath );
409  OUTS( repoPackagesCachePath );
410  OUTS( knownReposPath );
411  OUTS( knownServicesPath );
412  OUTS( pluginsPath );
413  str << "}" << endl;
414 #undef OUTS
415  return str;
416  }
417 
424  {
425  public:
426  Impl( const RepoManagerOptions &opt )
427  : _options(opt)
428  {
429  init_knownServices();
430  init_knownRepositories();
431  }
432 
433  public:
434  bool repoEmpty() const { return _repos.empty(); }
435  RepoSizeType repoSize() const { return _repos.size(); }
436  RepoConstIterator repoBegin() const { return _repos.begin(); }
437  RepoConstIterator repoEnd() const { return _repos.end(); }
438 
439  bool hasRepo( const std::string & alias ) const
440  { return foundAliasIn( alias, _repos ); }
441 
442  RepoInfo getRepo( const std::string & alias ) const
443  {
444  RepoConstIterator it( findAlias( alias, _repos ) );
445  return it == _repos.end() ? RepoInfo::noRepo : *it;
446  }
447 
448  public:
449  Pathname metadataPath( const RepoInfo & info ) const
450  { return rawcache_path_for_repoinfo( _options, info ); }
451 
452  Pathname packagesPath( const RepoInfo & info ) const
453  { return packagescache_path_for_repoinfo( _options, info ); }
454 
455  RepoStatus metadataStatus( const RepoInfo & info ) const;
456 
457  RefreshCheckStatus checkIfToRefreshMetadata( const RepoInfo & info, const Url & url, RawMetadataRefreshPolicy policy );
458 
459  void refreshMetadata( const RepoInfo & info, RawMetadataRefreshPolicy policy, OPT_PROGRESS );
460 
461  void cleanMetadata( const RepoInfo & info, OPT_PROGRESS );
462 
463  void cleanPackages( const RepoInfo & info, OPT_PROGRESS );
464 
465  void buildCache( const RepoInfo & info, CacheBuildPolicy policy, OPT_PROGRESS );
466 
467  repo::RepoType probe( const Url & url, const Pathname & path = Pathname() ) const;
468 
469  void cleanCacheDirGarbage( OPT_PROGRESS );
470 
471  void cleanCache( const RepoInfo & info, OPT_PROGRESS );
472 
473  bool isCached( const RepoInfo & info ) const
474  { return PathInfo(solv_path_for_repoinfo( _options, info ) / "solv").isExist(); }
475 
476  RepoStatus cacheStatus( const RepoInfo & info ) const
477  { return RepoStatus::fromCookieFile(solv_path_for_repoinfo(_options, info) / "cookie"); }
478 
479  void loadFromCache( const RepoInfo & info, OPT_PROGRESS );
480 
481  void addRepository( const RepoInfo & info, OPT_PROGRESS );
482 
483  void addRepositories( const Url & url, OPT_PROGRESS );
484 
485  void removeRepository( const RepoInfo & info, OPT_PROGRESS );
486 
487  void modifyRepository( const std::string & alias, const RepoInfo & newinfo_r, OPT_PROGRESS );
488 
489  RepoInfo getRepositoryInfo( const std::string & alias, OPT_PROGRESS );
490  RepoInfo getRepositoryInfo( const Url & url, const url::ViewOption & urlview, OPT_PROGRESS );
491 
492  public:
493  bool serviceEmpty() const { return _services.empty(); }
494  ServiceSizeType serviceSize() const { return _services.size(); }
495  ServiceConstIterator serviceBegin() const { return _services.begin(); }
496  ServiceConstIterator serviceEnd() const { return _services.end(); }
497 
498  bool hasService( const std::string & alias ) const
499  { return foundAliasIn( alias, _services ); }
500 
501  ServiceInfo getService( const std::string & alias ) const
502  {
503  ServiceConstIterator it( findAlias( alias, _services ) );
504  return it == _services.end() ? ServiceInfo::noService : *it;
505  }
506 
507  public:
508  void addService( const ServiceInfo & service );
509  void addService( const std::string & alias, const Url & url )
510  { addService( ServiceInfo( alias, url ) ); }
511 
512  void removeService( const std::string & alias );
513  void removeService( const ServiceInfo & service )
514  { removeService( service.alias() ); }
515 
516  void refreshServices();
517 
518  void refreshService( const std::string & alias );
519  void refreshService( const ServiceInfo & service )
520  { refreshService( service.alias() ); }
521 
522  void modifyService( const std::string & oldAlias, const ServiceInfo & newService );
523 
524  repo::ServiceType probeService( const Url & url ) const;
525 
526  private:
527  void saveService( ServiceInfo & service ) const;
528 
529  Pathname generateNonExistingName( const Pathname & dir, const std::string & basefilename ) const;
530 
531  std::string generateFilename( const RepoInfo & info ) const
532  { return filenameFromAlias( info.alias(), "repo" ); }
533 
534  std::string generateFilename( const ServiceInfo & info ) const
535  { return filenameFromAlias( info.alias(), "service" ); }
536 
537  void setCacheStatus( const RepoInfo & info, const RepoStatus & status )
538  {
539  Pathname base = solv_path_for_repoinfo( _options, info );
541  status.saveToCookieFile( base / "cookie" );
542  }
543 
544  void touchIndexFile( const RepoInfo & info );
545 
546  template<typename OutputIterator>
547  void getRepositoriesInService( const std::string & alias, OutputIterator out ) const
548  {
549  MatchServiceAlias filter( alias );
550  std::copy( boost::make_filter_iterator( filter, _repos.begin(), _repos.end() ),
551  boost::make_filter_iterator( filter, _repos.end(), _repos.end() ),
552  out);
553  }
554 
555  private:
556  void init_knownServices();
557  void init_knownRepositories();
558 
559  private:
563 
564  private:
565  friend Impl * rwcowClone<Impl>( const Impl * rhs );
567  Impl * clone() const
568  { return new Impl( *this ); }
569  };
571 
573  inline std::ostream & operator<<( std::ostream & str, const RepoManager::Impl & obj )
574  { return str << "RepoManager::Impl"; }
575 
577 
579  {
580  filesystem::assert_dir( _options.knownServicesPath );
581  Pathname servfile = generateNonExistingName( _options.knownServicesPath,
582  generateFilename( service ) );
583  service.setFilepath( servfile );
584 
585  MIL << "saving service in " << servfile << endl;
586 
587  std::ofstream file( servfile.c_str() );
588  if ( !file )
589  {
590  // TranslatorExplanation '%s' is a filename
591  ZYPP_THROW( Exception(str::form( _("Can't open file '%s' for writing."), servfile.c_str() )));
592  }
593  service.dumpAsIniOn( file );
594  MIL << "done" << endl;
595  }
596 
612  Pathname RepoManager::Impl::generateNonExistingName( const Pathname & dir,
613  const std::string & basefilename ) const
614  {
615  std::string final_filename = basefilename;
616  int counter = 1;
617  while ( PathInfo(dir + final_filename).isExist() )
618  {
619  final_filename = basefilename + "_" + str::numstring(counter);
620  ++counter;
621  }
622  return dir + Pathname(final_filename);
623  }
624 
626 
628  {
629  Pathname dir = _options.knownServicesPath;
630  std::list<Pathname> entries;
631  if (PathInfo(dir).isExist())
632  {
633  if ( filesystem::readdir( entries, dir, false ) != 0 )
634  {
635  // TranslatorExplanation '%s' is a pathname
636  ZYPP_THROW(Exception(str::form(_("Failed to read directory '%s'"), dir.c_str())));
637  }
638 
639  //str::regex allowedServiceExt("^\\.service(_[0-9]+)?$");
640  for_(it, entries.begin(), entries.end() )
641  {
642  parser::ServiceFileReader(*it, ServiceCollector(_services));
643  }
644  }
645 
646  repo::PluginServices(_options.pluginsPath/"services", ServiceCollector(_services));
647  }
648 
650  namespace {
656  inline void cleanupNonRepoMetadtaFolders( const Pathname & cachePath_r,
657  const Pathname & defaultCachePath_r,
658  const std::list<std::string> & repoEscAliases_r )
659  {
660  if ( cachePath_r != defaultCachePath_r )
661  return;
662 
663  std::list<std::string> entries;
664  if ( filesystem::readdir( entries, cachePath_r, false ) == 0 )
665  {
666  entries.sort();
667  std::set<std::string> oldfiles;
668  set_difference( entries.begin(), entries.end(), repoEscAliases_r.begin(), repoEscAliases_r.end(),
669  std::inserter( oldfiles, oldfiles.end() ) );
670  for ( const std::string & old : oldfiles )
671  {
672  if ( old == Repository::systemRepoAlias() ) // don't remove the @System solv file
673  continue;
674  filesystem::recursive_rmdir( cachePath_r / old );
675  }
676  }
677  }
678  } // namespace
681  {
682  MIL << "start construct known repos" << endl;
683 
684  if ( PathInfo(_options.knownReposPath).isExist() )
685  {
686  std::list<std::string> repoEscAliases;
687  for ( RepoInfo & repoInfo : repositories_in_dir(_options.knownReposPath) )
688  {
689  // set the metadata path for the repo
690  repoInfo.setMetadataPath( rawcache_path_for_repoinfo(_options, repoInfo) );
691  // set the downloaded packages path for the repo
692  repoInfo.setPackagesPath( packagescache_path_for_repoinfo(_options, repoInfo) );
693 
694  _repos.insert( repoInfo );
695  repoEscAliases.push_back(repoInfo.escaped_alias());
696  }
697  repoEscAliases.sort();
698 
699  // delete metadata folders without corresponding repo (e.g. old tmp directories)
700  //
701  // bnc#891515: Auto-cleanup only zypp.conf default locations. Otherwise
702  // we'd need somemagic file to identify zypp cache directories. Without this
703  // we may easily remove user data (zypper --pkg-cache-dir . download ...)
704  RepoManagerOptions defaultCache( _options.rootDir );
705  cleanupNonRepoMetadtaFolders( _options.repoRawCachePath, defaultCache.repoRawCachePath, repoEscAliases );
706  cleanupNonRepoMetadtaFolders( _options.repoSolvCachePath, defaultCache.repoSolvCachePath, repoEscAliases );
707  cleanupNonRepoMetadtaFolders( _options.repoPackagesCachePath, defaultCache.repoPackagesCachePath, repoEscAliases );
708  }
709  MIL << "end construct known repos" << endl;
710  }
711 
713 
715  {
716  Pathname mediarootpath = rawcache_path_for_repoinfo( _options, info );
717  Pathname productdatapath = rawproductdata_path_for_repoinfo( _options, info );
718  RepoType repokind = info.type();
719  RepoStatus status;
720 
721  switch ( repokind.toEnum() )
722  {
723  case RepoType::NONE_e:
724  // unknown, probe the local metadata
725  repokind = probe( productdatapath.asUrl() );
726  break;
727  default:
728  break;
729  }
730 
731  switch ( repokind.toEnum() )
732  {
733  case RepoType::RPMMD_e :
734  {
735  status = RepoStatus( productdatapath + "/repodata/repomd.xml");
736  }
737  break;
738 
739  case RepoType::YAST2_e :
740  {
741  status = RepoStatus( productdatapath + "/content") && (RepoStatus( mediarootpath + "/media.1/media"));
742  }
743  break;
744 
746  {
747  if ( PathInfo(Pathname(productdatapath + "/cookie")).isExist() )
748  status = RepoStatus( productdatapath + "/cookie");
749  }
750  break;
751 
752  case RepoType::NONE_e :
753  // Return default RepoStatus in case of RepoType::NONE
754  // indicating it should be created?
755  // ZYPP_THROW(RepoUnknownTypeException());
756  break;
757  }
758  return status;
759  }
760 
761 
763  {
764  Pathname productdatapath = rawproductdata_path_for_repoinfo( _options, info );
765 
766  RepoType repokind = info.type();
767  if ( repokind.toEnum() == RepoType::NONE_e )
768  // unknown, probe the local metadata
769  repokind = probe( productdatapath.asUrl() );
770  // if still unknown, just return
771  if (repokind == RepoType::NONE_e)
772  return;
773 
774  Pathname p;
775  switch ( repokind.toEnum() )
776  {
777  case RepoType::RPMMD_e :
778  p = Pathname(productdatapath + "/repodata/repomd.xml");
779  break;
780 
781  case RepoType::YAST2_e :
782  p = Pathname(productdatapath + "/content");
783  break;
784 
786  p = Pathname(productdatapath + "/cookie");
787  break;
788 
789  case RepoType::NONE_e :
790  default:
791  break;
792  }
793 
794  // touch the file, ignore error (they are logged anyway)
796  }
797 
798 
800  {
801  assert_alias(info);
802 
803  RepoStatus oldstatus;
804  RepoStatus newstatus;
805 
806  try
807  {
808  MIL << "Going to try to check whether refresh is needed for " << url << endl;
809 
810  // first check old (cached) metadata
811  Pathname mediarootpath = rawcache_path_for_repoinfo( _options, info );
812  filesystem::assert_dir(mediarootpath);
813  oldstatus = metadataStatus(info);
814 
815  if ( oldstatus.empty() )
816  {
817  MIL << "No cached metadata, going to refresh" << endl;
818  return REFRESH_NEEDED;
819  }
820 
821  {
822  std::string scheme( url.getScheme() );
823  if ( scheme == "cd" || scheme == "dvd" )
824  {
825  MIL << "never refresh CD/DVD" << endl;
826  return REPO_UP_TO_DATE;
827  }
828  }
829 
830  // now we've got the old (cached) status, we can decide repo.refresh.delay
831  if (policy != RefreshForced && policy != RefreshIfNeededIgnoreDelay)
832  {
833  // difference in seconds
834  double diff = difftime(
836  (Date::ValueType)oldstatus.timestamp()) / 60;
837 
838  DBG << "oldstatus: " << (Date::ValueType)oldstatus.timestamp() << endl;
839  DBG << "current time: " << (Date::ValueType)Date::now() << endl;
840  DBG << "last refresh = " << diff << " minutes ago" << endl;
841 
842  if ( diff < ZConfig::instance().repo_refresh_delay() )
843  {
844  if ( diff < 0 )
845  {
846  WAR << "Repository '" << info.alias() << "' was refreshed in the future!" << endl;
847  }
848  else
849  {
850  MIL << "Repository '" << info.alias()
851  << "' has been refreshed less than repo.refresh.delay ("
853  << ") minutes ago. Advising to skip refresh" << endl;
854  return REPO_CHECK_DELAYED;
855  }
856  }
857  }
858 
859  // To test the new matadta create temp dir as sibling of mediarootpath
860  filesystem::TmpDir tmpdir( filesystem::TmpDir::makeSibling( mediarootpath ) );
861 
862  repo::RepoType repokind = info.type();
863  // if the type is unknown, try probing.
864  switch ( repokind.toEnum() )
865  {
866  case RepoType::NONE_e:
867  // unknown, probe it \todo respect productdir
868  repokind = probe( url, info.path() );
869  break;
870  default:
871  break;
872  }
873 
874  if ( ( repokind.toEnum() == RepoType::RPMMD_e ) ||
875  ( repokind.toEnum() == RepoType::YAST2_e ) )
876  {
877  MediaSetAccess media(url);
878  shared_ptr<repo::Downloader> downloader_ptr;
879 
880  if ( repokind.toEnum() == RepoType::RPMMD_e )
881  downloader_ptr.reset(new yum::Downloader(info, mediarootpath));
882  else
883  downloader_ptr.reset( new susetags::Downloader(info, mediarootpath));
884 
885  RepoStatus newstatus = downloader_ptr->status(media);
886  bool refresh = false;
887  if ( oldstatus.checksum() == newstatus.checksum() )
888  {
889  MIL << "repo has not changed" << endl;
890  if ( policy == RefreshForced )
891  {
892  MIL << "refresh set to forced" << endl;
893  refresh = true;
894  }
895  }
896  else
897  {
898  MIL << "repo has changed, going to refresh" << endl;
899  refresh = true;
900  }
901 
902  if (!refresh)
903  touchIndexFile(info);
904 
905  return refresh ? REFRESH_NEEDED : REPO_UP_TO_DATE;
906  }
907  else if ( repokind.toEnum() == RepoType::RPMPLAINDIR_e )
908  {
909  MediaMounter media( url );
910  RepoStatus newstatus = parser::plaindir::dirStatus( media.getPathName( info.path() ) );
911  bool refresh = false;
912  if ( oldstatus.checksum() == newstatus.checksum() )
913  {
914  MIL << "repo has not changed" << endl;
915  if ( policy == RefreshForced )
916  {
917  MIL << "refresh set to forced" << endl;
918  refresh = true;
919  }
920  }
921  else
922  {
923  MIL << "repo has changed, going to refresh" << endl;
924  refresh = true;
925  }
926 
927  if (!refresh)
928  touchIndexFile(info);
929 
930  return refresh ? REFRESH_NEEDED : REPO_UP_TO_DATE;
931  }
932  else
933  {
935  }
936  }
937  catch ( const Exception &e )
938  {
939  ZYPP_CAUGHT(e);
940  ERR << "refresh check failed for " << url << endl;
941  ZYPP_RETHROW(e);
942  }
943 
944  return REFRESH_NEEDED; // default
945  }
946 
947 
949  {
950  assert_alias(info);
951  assert_urls(info);
952 
953  // we will throw this later if no URL checks out fine
954  RepoException rexception(_PL("Valid metadata not found at specified URL",
955  "Valid metadata not found at specified URLs",
956  info.baseUrlsSize() ) );
957 
958  // try urls one by one
959  for ( RepoInfo::urls_const_iterator it = info.baseUrlsBegin(); it != info.baseUrlsEnd(); ++it )
960  {
961  try
962  {
963  Url url(*it);
964 
965  // check whether to refresh metadata
966  // if the check fails for this url, it throws, so another url will be checked
967  if (checkIfToRefreshMetadata(info, url, policy)!=REFRESH_NEEDED)
968  return;
969 
970  MIL << "Going to refresh metadata from " << url << endl;
971 
972  repo::RepoType repokind = info.type();
973 
974  // if the type is unknown, try probing.
975  switch ( repokind.toEnum() )
976  {
977  case RepoType::NONE_e:
978  // unknown, probe it
979  repokind = probe( *it, info.path() );
980 
981  if (repokind.toEnum() != RepoType::NONE_e)
982  {
983  // Adjust the probed type in RepoInfo
984  info.setProbedType( repokind ); // lazy init!
985  //save probed type only for repos in system
986  for_( it, repoBegin(), repoEnd() )
987  {
988  if ( info.alias() == (*it).alias() )
989  {
990  RepoInfo modifiedrepo = info;
991  modifiedrepo.setType( repokind );
992  modifyRepository( info.alias(), modifiedrepo );
993  break;
994  }
995  }
996  }
997  break;
998  default:
999  break;
1000  }
1001 
1002  Pathname mediarootpath = rawcache_path_for_repoinfo( _options, info );
1003  if( filesystem::assert_dir(mediarootpath) )
1004  {
1005  Exception ex(str::form( _("Can't create %s"), mediarootpath.c_str()) );
1006  ZYPP_THROW(ex);
1007  }
1008 
1009  // create temp dir as sibling of mediarootpath
1010  filesystem::TmpDir tmpdir( filesystem::TmpDir::makeSibling( mediarootpath ) );
1011  if( tmpdir.path().empty() )
1012  {
1013  Exception ex(_("Can't create metadata cache directory."));
1014  ZYPP_THROW(ex);
1015  }
1016 
1017  if ( ( repokind.toEnum() == RepoType::RPMMD_e ) ||
1018  ( repokind.toEnum() == RepoType::YAST2_e ) )
1019  {
1020  MediaSetAccess media(url);
1021  shared_ptr<repo::Downloader> downloader_ptr;
1022 
1023  MIL << "Creating downloader for [ " << info.alias() << " ]" << endl;
1024 
1025  if ( repokind.toEnum() == RepoType::RPMMD_e )
1026  downloader_ptr.reset(new yum::Downloader(info, mediarootpath));
1027  else
1028  downloader_ptr.reset( new susetags::Downloader(info, mediarootpath) );
1029 
1036  for_( it, repoBegin(), repoEnd() )
1037  {
1038  Pathname cachepath(rawcache_path_for_repoinfo( _options, *it ));
1039  if ( PathInfo(cachepath).isExist() )
1040  downloader_ptr->addCachePath(cachepath);
1041  }
1042 
1043  downloader_ptr->download( media, tmpdir.path() );
1044  }
1045  else if ( repokind.toEnum() == RepoType::RPMPLAINDIR_e )
1046  {
1047  MediaMounter media( url );
1048  RepoStatus newstatus = parser::plaindir::dirStatus( media.getPathName( info.path() ) );
1049 
1050  Pathname productpath( tmpdir.path() / info.path() );
1051  filesystem::assert_dir( productpath );
1052  std::ofstream file( (productpath/"cookie").c_str() );
1053  if ( !file )
1054  {
1055  // TranslatorExplanation '%s' is a filename
1056  ZYPP_THROW( Exception(str::form( _("Can't open file '%s' for writing."), (productpath/"cookie").c_str() )));
1057  }
1058  file << url;
1059  if ( ! info.path().empty() && info.path() != "/" )
1060  file << " (" << info.path() << ")";
1061  file << endl;
1062  file << newstatus.checksum() << endl;
1063 
1064  file.close();
1065  }
1066  else
1067  {
1069  }
1070 
1071  // ok we have the metadata, now exchange
1072  // the contents
1073  filesystem::exchange( tmpdir.path(), mediarootpath );
1074 
1075  // we are done.
1076  return;
1077  }
1078  catch ( const Exception &e )
1079  {
1080  ZYPP_CAUGHT(e);
1081  ERR << "Trying another url..." << endl;
1082 
1083  // remember the exception caught for the *first URL*
1084  // if all other URLs fail, the rexception will be thrown with the
1085  // cause of the problem of the first URL remembered
1086  if (it == info.baseUrlsBegin())
1087  rexception.remember(e);
1088  }
1089  } // for every url
1090  ERR << "No more urls..." << endl;
1091  ZYPP_THROW(rexception);
1092  }
1093 
1095 
1096  void RepoManager::Impl::cleanMetadata( const RepoInfo & info, const ProgressData::ReceiverFnc & progressfnc )
1097  {
1098  ProgressData progress(100);
1099  progress.sendTo(progressfnc);
1100 
1101  filesystem::recursive_rmdir(rawcache_path_for_repoinfo(_options, info));
1102  progress.toMax();
1103  }
1104 
1105 
1106  void RepoManager::Impl::cleanPackages( const RepoInfo & info, const ProgressData::ReceiverFnc & progressfnc )
1107  {
1108  ProgressData progress(100);
1109  progress.sendTo(progressfnc);
1110 
1111  filesystem::recursive_rmdir(packagescache_path_for_repoinfo(_options, info));
1112  progress.toMax();
1113  }
1114 
1115 
1116  void RepoManager::Impl::buildCache( const RepoInfo & info, CacheBuildPolicy policy, const ProgressData::ReceiverFnc & progressrcv )
1117  {
1118  assert_alias(info);
1119  Pathname mediarootpath = rawcache_path_for_repoinfo( _options, info );
1120  Pathname productdatapath = rawproductdata_path_for_repoinfo( _options, info );
1121 
1122  if( filesystem::assert_dir(_options.repoCachePath) )
1123  {
1124  Exception ex(str::form( _("Can't create %s"), _options.repoCachePath.c_str()) );
1125  ZYPP_THROW(ex);
1126  }
1127  RepoStatus raw_metadata_status = metadataStatus(info);
1128  if ( raw_metadata_status.empty() )
1129  {
1130  /* if there is no cache at this point, we refresh the raw
1131  in case this is the first time - if it's !autorefresh,
1132  we may still refresh */
1133  refreshMetadata(info, RefreshIfNeeded, progressrcv );
1134  raw_metadata_status = metadataStatus(info);
1135  }
1136 
1137  bool needs_cleaning = false;
1138  if ( isCached( info ) )
1139  {
1140  MIL << info.alias() << " is already cached." << endl;
1141  RepoStatus cache_status = cacheStatus(info);
1142 
1143  if ( cache_status.checksum() == raw_metadata_status.checksum() )
1144  {
1145  MIL << info.alias() << " cache is up to date with metadata." << endl;
1146  if ( policy == BuildIfNeeded ) {
1147  return;
1148  }
1149  else {
1150  MIL << info.alias() << " cache rebuild is forced" << endl;
1151  }
1152  }
1153 
1154  needs_cleaning = true;
1155  }
1156 
1157  ProgressData progress(100);
1159  progress.sendTo( ProgressReportAdaptor( progressrcv, report ) );
1160  progress.name(str::form(_("Building repository '%s' cache"), info.label().c_str()));
1161  progress.toMin();
1162 
1163  if (needs_cleaning)
1164  {
1165  cleanCache(info);
1166  }
1167 
1168  MIL << info.alias() << " building cache..." << info.type() << endl;
1169 
1170  Pathname base = solv_path_for_repoinfo( _options, info);
1171 
1172  if( filesystem::assert_dir(base) )
1173  {
1174  Exception ex(str::form( _("Can't create %s"), base.c_str()) );
1175  ZYPP_THROW(ex);
1176  }
1177 
1178  if( ! PathInfo(base).userMayW() )
1179  {
1180  Exception ex(str::form( _("Can't create cache at %s - no writing permissions."), base.c_str()) );
1181  ZYPP_THROW(ex);
1182  }
1183  Pathname solvfile = base / "solv";
1184 
1185  // do we have type?
1186  repo::RepoType repokind = info.type();
1187 
1188  // if the type is unknown, try probing.
1189  switch ( repokind.toEnum() )
1190  {
1191  case RepoType::NONE_e:
1192  // unknown, probe the local metadata
1193  repokind = probe( productdatapath.asUrl() );
1194  break;
1195  default:
1196  break;
1197  }
1198 
1199  MIL << "repo type is " << repokind << endl;
1200 
1201  switch ( repokind.toEnum() )
1202  {
1203  case RepoType::RPMMD_e :
1204  case RepoType::YAST2_e :
1206  {
1207  // Take care we unlink the solvfile on exception
1208  ManagedFile guard( solvfile, filesystem::unlink );
1209  scoped_ptr<MediaMounter> forPlainDirs;
1210 
1212  cmd.push_back( "repo2solv.sh" );
1213 
1214  // repo2solv expects -o as 1st arg!
1215  cmd.push_back( "-o" );
1216  cmd.push_back( solvfile.asString() );
1217 
1218  if ( repokind == RepoType::RPMPLAINDIR )
1219  {
1220  forPlainDirs.reset( new MediaMounter( *info.baseUrlsBegin() ) );
1221  // recusive for plaindir as 2nd arg!
1222  cmd.push_back( "-R" );
1223  // FIXME this does only work form dir: URLs
1224  cmd.push_back( forPlainDirs->getPathName( info.path() ).c_str() );
1225  }
1226  else
1227  cmd.push_back( productdatapath.asString() );
1228 
1230  std::string errdetail;
1231 
1232  for ( std::string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() ) {
1233  WAR << " " << output;
1234  if ( errdetail.empty() ) {
1235  errdetail = prog.command();
1236  errdetail += '\n';
1237  }
1238  errdetail += output;
1239  }
1240 
1241  int ret = prog.close();
1242  if ( ret != 0 )
1243  {
1244  RepoException ex(str::form( _("Failed to cache repo (%d)."), ret ));
1245  ex.remember( errdetail );
1246  ZYPP_THROW(ex);
1247  }
1248 
1249  // We keep it.
1250  guard.resetDispose();
1251  }
1252  break;
1253  default:
1254  ZYPP_THROW(RepoUnknownTypeException( _("Unhandled repository type") ));
1255  break;
1256  }
1257  // update timestamp and checksum
1258  setCacheStatus(info, raw_metadata_status);
1259  MIL << "Commit cache.." << endl;
1260  progress.toMax();
1261  }
1262 
1264 
1265  repo::RepoType RepoManager::Impl::probe( const Url & url, const Pathname & path ) const
1266  {
1267  MIL << "going to probe the repo type at " << url << " (" << path << ")" << endl;
1268 
1269  if ( url.getScheme() == "dir" && ! PathInfo( url.getPathName()/path ).isDir() )
1270  {
1271  // Handle non existing local directory in advance, as
1272  // MediaSetAccess does not support it.
1273  MIL << "Probed type NONE (not exists) at " << url << " (" << path << ")" << endl;
1274  return repo::RepoType::NONE;
1275  }
1276 
1277  // prepare exception to be thrown if the type could not be determined
1278  // due to a media exception. We can't throw right away, because of some
1279  // problems with proxy servers returning an incorrect error
1280  // on ftp file-not-found(bnc #335906). Instead we'll check another types
1281  // before throwing.
1282 
1283  // TranslatorExplanation '%s' is an URL
1284  RepoException enew(str::form( _("Error trying to read from '%s'"), url.asString().c_str() ));
1285  bool gotMediaException = false;
1286  try
1287  {
1288  MediaSetAccess access(url);
1289  try
1290  {
1291  if ( access.doesFileExist(path/"/repodata/repomd.xml") )
1292  {
1293  MIL << "Probed type RPMMD at " << url << " (" << path << ")" << endl;
1294  return repo::RepoType::RPMMD;
1295  }
1296  }
1297  catch ( const media::MediaException &e )
1298  {
1299  ZYPP_CAUGHT(e);
1300  DBG << "problem checking for repodata/repomd.xml file" << endl;
1301  enew.remember(e);
1302  gotMediaException = true;
1303  }
1304 
1305  try
1306  {
1307  if ( access.doesFileExist(path/"/content") )
1308  {
1309  MIL << "Probed type YAST2 at " << url << " (" << path << ")" << endl;
1310  return repo::RepoType::YAST2;
1311  }
1312  }
1313  catch ( const media::MediaException &e )
1314  {
1315  ZYPP_CAUGHT(e);
1316  DBG << "problem checking for content file" << endl;
1317  enew.remember(e);
1318  gotMediaException = true;
1319  }
1320 
1321  // if it is a non-downloading URL denoting a directory
1322  if ( ! url.schemeIsDownloading() )
1323  {
1324  MediaMounter media( url );
1325  if ( PathInfo(media.getPathName()/path).isDir() )
1326  {
1327  // allow empty dirs for now
1328  MIL << "Probed type RPMPLAINDIR at " << url << " (" << path << ")" << endl;
1330  }
1331  }
1332  }
1333  catch ( const Exception &e )
1334  {
1335  ZYPP_CAUGHT(e);
1336  // TranslatorExplanation '%s' is an URL
1337  Exception enew(str::form( _("Unknown error reading from '%s'"), url.asString().c_str() ));
1338  enew.remember(e);
1339  ZYPP_THROW(enew);
1340  }
1341 
1342  if (gotMediaException)
1343  ZYPP_THROW(enew);
1344 
1345  MIL << "Probed type NONE at " << url << " (" << path << ")" << endl;
1346  return repo::RepoType::NONE;
1347  }
1348 
1350 
1352  {
1353  MIL << "Going to clean up garbage in cache dirs" << endl;
1354 
1355  ProgressData progress(300);
1356  progress.sendTo(progressrcv);
1357  progress.toMin();
1358 
1359  std::list<Pathname> cachedirs;
1360  cachedirs.push_back(_options.repoRawCachePath);
1361  cachedirs.push_back(_options.repoPackagesCachePath);
1362  cachedirs.push_back(_options.repoSolvCachePath);
1363 
1364  for_( dir, cachedirs.begin(), cachedirs.end() )
1365  {
1366  if ( PathInfo(*dir).isExist() )
1367  {
1368  std::list<Pathname> entries;
1369  if ( filesystem::readdir( entries, *dir, false ) != 0 )
1370  // TranslatorExplanation '%s' is a pathname
1371  ZYPP_THROW(Exception(str::form(_("Failed to read directory '%s'"), dir->c_str())));
1372 
1373  unsigned sdircount = entries.size();
1374  unsigned sdircurrent = 1;
1375  for_( subdir, entries.begin(), entries.end() )
1376  {
1377  // if it does not belong known repo, make it disappear
1378  bool found = false;
1379  for_( r, repoBegin(), repoEnd() )
1380  if ( subdir->basename() == r->escaped_alias() )
1381  { found = true; break; }
1382 
1383  if ( ! found )
1384  filesystem::recursive_rmdir( *subdir );
1385 
1386  progress.set( progress.val() + sdircurrent * 100 / sdircount );
1387  ++sdircurrent;
1388  }
1389  }
1390  else
1391  progress.set( progress.val() + 100 );
1392  }
1393  progress.toMax();
1394  }
1395 
1397 
1398  void RepoManager::Impl::cleanCache( const RepoInfo & info, const ProgressData::ReceiverFnc & progressrcv )
1399  {
1400  ProgressData progress(100);
1401  progress.sendTo(progressrcv);
1402  progress.toMin();
1403 
1404  MIL << "Removing raw metadata cache for " << info.alias() << endl;
1405  filesystem::recursive_rmdir(solv_path_for_repoinfo(_options, info));
1406 
1407  progress.toMax();
1408  }
1409 
1411 
1412  void RepoManager::Impl::loadFromCache( const RepoInfo & info, const ProgressData::ReceiverFnc & progressrcv )
1413  {
1414  assert_alias(info);
1415  Pathname solvfile = solv_path_for_repoinfo(_options, info) / "solv";
1416 
1417  if ( ! PathInfo(solvfile).isExist() )
1419 
1420  sat::Pool::instance().reposErase( info.alias() );
1421  try
1422  {
1423  Repository repo = sat::Pool::instance().addRepoSolv( solvfile, info );
1424  // test toolversion in order to rebuild solv file in case
1425  // it was written by an old libsolv-tool parser.
1426  //
1427  // Known version strings used:
1428  // - <no string>
1429  // - "1.0"
1430  //
1432  if ( toolversion.begin().asString().empty() )
1433  {
1434  repo.eraseFromPool();
1435  ZYPP_THROW(Exception("Solv-file was created by old parser."));
1436  }
1437  // else: up-to-date (or even newer).
1438  }
1439  catch ( const Exception & exp )
1440  {
1441  ZYPP_CAUGHT( exp );
1442  MIL << "Try to handle exception by rebuilding the solv-file" << endl;
1443  cleanCache( info, progressrcv );
1444  buildCache( info, BuildIfNeeded, progressrcv );
1445 
1446  sat::Pool::instance().addRepoSolv( solvfile, info );
1447  }
1448  }
1449 
1451 
1452  void RepoManager::Impl::addRepository( const RepoInfo & info, const ProgressData::ReceiverFnc & progressrcv )
1453  {
1454  assert_alias(info);
1455 
1456  ProgressData progress(100);
1458  progress.sendTo( ProgressReportAdaptor( progressrcv, report ) );
1459  progress.name(str::form(_("Adding repository '%s'"), info.label().c_str()));
1460  progress.toMin();
1461 
1462  MIL << "Try adding repo " << info << endl;
1463 
1464  RepoInfo tosave = info;
1465  if ( _repos.find(tosave) != _repos.end() )
1467 
1468  // check the first url for now
1469  if ( _options.probe )
1470  {
1471  DBG << "unknown repository type, probing" << endl;
1472 
1473  RepoType probedtype;
1474  probedtype = probe( *tosave.baseUrlsBegin(), info.path() );
1475  if ( tosave.baseUrlsSize() > 0 )
1476  {
1477  if ( probedtype == RepoType::NONE )
1479  else
1480  tosave.setType(probedtype);
1481  }
1482  }
1483 
1484  progress.set(50);
1485 
1486  // assert the directory exists
1487  filesystem::assert_dir(_options.knownReposPath);
1488 
1489  Pathname repofile = generateNonExistingName(
1490  _options.knownReposPath, generateFilename(tosave));
1491  // now we have a filename that does not exists
1492  MIL << "Saving repo in " << repofile << endl;
1493 
1494  std::ofstream file(repofile.c_str());
1495  if (!file)
1496  {
1497  // TranslatorExplanation '%s' is a filename
1498  ZYPP_THROW( Exception(str::form( _("Can't open file '%s' for writing."), repofile.c_str() )));
1499  }
1500 
1501  tosave.dumpAsIniOn(file);
1502  tosave.setFilepath(repofile);
1503  tosave.setMetadataPath( metadataPath( tosave ) );
1504  tosave.setPackagesPath( packagesPath( tosave ) );
1505  {
1506  // We chould fix the API as we must injet those paths
1507  // into the repoinfo in order to keep it usable.
1508  RepoInfo & oinfo( const_cast<RepoInfo &>(info) );
1509  oinfo.setMetadataPath( metadataPath( tosave ) );
1510  oinfo.setPackagesPath( packagesPath( tosave ) );
1511  }
1512  _repos.insert(tosave);
1513 
1514  progress.set(90);
1515 
1516  // check for credentials in Urls
1517  bool havePasswords = false;
1518  for_( urlit, tosave.baseUrlsBegin(), tosave.baseUrlsEnd() )
1519  if ( urlit->hasCredentialsInAuthority() )
1520  {
1521  havePasswords = true;
1522  break;
1523  }
1524  // save the credentials
1525  if ( havePasswords )
1526  {
1528  media::CredManagerOptions(_options.rootDir) );
1529 
1530  for_(urlit, tosave.baseUrlsBegin(), tosave.baseUrlsEnd())
1531  if (urlit->hasCredentialsInAuthority())
1533  cm.saveInUser(media::AuthData(*urlit));
1534  }
1535 
1536  HistoryLog().addRepository(tosave);
1537 
1538  progress.toMax();
1539  MIL << "done" << endl;
1540  }
1541 
1542 
1544  {
1545  std::list<RepoInfo> repos = readRepoFile(url);
1546  for ( std::list<RepoInfo>::const_iterator it = repos.begin();
1547  it != repos.end();
1548  ++it )
1549  {
1550  // look if the alias is in the known repos.
1551  for_ ( kit, repoBegin(), repoEnd() )
1552  {
1553  if ( (*it).alias() == (*kit).alias() )
1554  {
1555  ERR << "To be added repo " << (*it).alias() << " conflicts with existing repo " << (*kit).alias() << endl;
1557  }
1558  }
1559  }
1560 
1561  std::string filename = Pathname(url.getPathName()).basename();
1562 
1563  if ( filename == Pathname() )
1564  {
1565  // TranslatorExplanation '%s' is an URL
1566  ZYPP_THROW(RepoException(str::form( _("Invalid repo file name at '%s'"), url.asString().c_str() )));
1567  }
1568 
1569  // assert the directory exists
1570  filesystem::assert_dir(_options.knownReposPath);
1571 
1572  Pathname repofile = generateNonExistingName(_options.knownReposPath, filename);
1573  // now we have a filename that does not exists
1574  MIL << "Saving " << repos.size() << " repo" << ( repos.size() ? "s" : "" ) << " in " << repofile << endl;
1575 
1576  std::ofstream file(repofile.c_str());
1577  if (!file)
1578  {
1579  // TranslatorExplanation '%s' is a filename
1580  ZYPP_THROW( Exception(str::form( _("Can't open file '%s' for writing."), repofile.c_str() )));
1581  }
1582 
1583  for ( std::list<RepoInfo>::iterator it = repos.begin();
1584  it != repos.end();
1585  ++it )
1586  {
1587  MIL << "Saving " << (*it).alias() << endl;
1588  it->setFilepath(repofile.asString());
1589  it->dumpAsIniOn(file);
1590  _repos.insert(*it);
1591 
1592  HistoryLog(_options.rootDir).addRepository(*it);
1593  }
1594 
1595  MIL << "done" << endl;
1596  }
1597 
1599 
1601  {
1602  ProgressData progress;
1604  progress.sendTo( ProgressReportAdaptor( progressrcv, report ) );
1605  progress.name(str::form(_("Removing repository '%s'"), info.label().c_str()));
1606 
1607  MIL << "Going to delete repo " << info.alias() << endl;
1608 
1609  for_( it, repoBegin(), repoEnd() )
1610  {
1611  // they can be the same only if the provided is empty, that means
1612  // the provided repo has no alias
1613  // then skip
1614  if ( (!info.alias().empty()) && ( info.alias() != (*it).alias() ) )
1615  continue;
1616 
1617  // TODO match by url
1618 
1619  // we have a matcing repository, now we need to know
1620  // where it does come from.
1621  RepoInfo todelete = *it;
1622  if (todelete.filepath().empty())
1623  {
1624  ZYPP_THROW(RepoException( _("Can't figure out where the repo is stored.") ));
1625  }
1626  else
1627  {
1628  // figure how many repos are there in the file:
1629  std::list<RepoInfo> filerepos = repositories_in_file(todelete.filepath());
1630  if ( (filerepos.size() == 1) && ( filerepos.front().alias() == todelete.alias() ) )
1631  {
1632  // easy, only this one, just delete the file
1633  if ( filesystem::unlink(todelete.filepath()) != 0 )
1634  {
1635  // TranslatorExplanation '%s' is a filename
1636  ZYPP_THROW(RepoException(str::form( _("Can't delete '%s'"), todelete.filepath().c_str() )));
1637  }
1638  MIL << todelete.alias() << " sucessfully deleted." << endl;
1639  }
1640  else
1641  {
1642  // there are more repos in the same file
1643  // write them back except the deleted one.
1644  //TmpFile tmp;
1645  //std::ofstream file(tmp.path().c_str());
1646 
1647  // assert the directory exists
1648  filesystem::assert_dir(todelete.filepath().dirname());
1649 
1650  std::ofstream file(todelete.filepath().c_str());
1651  if (!file)
1652  {
1653  // TranslatorExplanation '%s' is a filename
1654  ZYPP_THROW( Exception(str::form( _("Can't open file '%s' for writing."), todelete.filepath().c_str() )));
1655  }
1656  for ( std::list<RepoInfo>::const_iterator fit = filerepos.begin();
1657  fit != filerepos.end();
1658  ++fit )
1659  {
1660  if ( (*fit).alias() != todelete.alias() )
1661  (*fit).dumpAsIniOn(file);
1662  }
1663  }
1664 
1665  CombinedProgressData cSubprogrcv(progress, 20);
1666  CombinedProgressData mSubprogrcv(progress, 40);
1667  CombinedProgressData pSubprogrcv(progress, 40);
1668  // now delete it from cache
1669  if ( isCached(todelete) )
1670  cleanCache( todelete, cSubprogrcv);
1671  // now delete metadata (#301037)
1672  cleanMetadata( todelete, mSubprogrcv );
1673  cleanPackages( todelete, pSubprogrcv );
1674  _repos.erase(todelete);
1675  MIL << todelete.alias() << " sucessfully deleted." << endl;
1676  HistoryLog(_options.rootDir).removeRepository(todelete);
1677  return;
1678  } // else filepath is empty
1679 
1680  }
1681  // should not be reached on a sucess workflow
1683  }
1684 
1686 
1687  void RepoManager::Impl::modifyRepository( const std::string & alias, const RepoInfo & newinfo_r, const ProgressData::ReceiverFnc & progressrcv )
1688  {
1689  RepoInfo toedit = getRepositoryInfo(alias);
1690  RepoInfo newinfo( newinfo_r ); // need writable copy to upadte housekeeping data
1691 
1692  // check if the new alias already exists when renaming the repo
1693  if ( alias != newinfo.alias() && hasRepo( newinfo.alias() ) )
1694  {
1696  }
1697 
1698  if (toedit.filepath().empty())
1699  {
1700  ZYPP_THROW(RepoException( _("Can't figure out where the repo is stored.") ));
1701  }
1702  else
1703  {
1704  // figure how many repos are there in the file:
1705  std::list<RepoInfo> filerepos = repositories_in_file(toedit.filepath());
1706 
1707  // there are more repos in the same file
1708  // write them back except the deleted one.
1709  //TmpFile tmp;
1710  //std::ofstream file(tmp.path().c_str());
1711 
1712  // assert the directory exists
1713  filesystem::assert_dir(toedit.filepath().dirname());
1714 
1715  std::ofstream file(toedit.filepath().c_str());
1716  if (!file)
1717  {
1718  // TranslatorExplanation '%s' is a filename
1719  ZYPP_THROW( Exception(str::form( _("Can't open file '%s' for writing."), toedit.filepath().c_str() )));
1720  }
1721  for ( std::list<RepoInfo>::const_iterator fit = filerepos.begin();
1722  fit != filerepos.end();
1723  ++fit )
1724  {
1725  // if the alias is different, dump the original
1726  // if it is the same, dump the provided one
1727  if ( (*fit).alias() != toedit.alias() )
1728  (*fit).dumpAsIniOn(file);
1729  else
1730  newinfo.dumpAsIniOn(file);
1731  }
1732 
1733  newinfo.setFilepath(toedit.filepath());
1734  _repos.erase(toedit);
1735  _repos.insert(newinfo);
1736  HistoryLog(_options.rootDir).modifyRepository(toedit, newinfo);
1737  MIL << "repo " << alias << " modified" << endl;
1738  }
1739  }
1740 
1742 
1743  RepoInfo RepoManager::Impl::getRepositoryInfo( const std::string & alias, const ProgressData::ReceiverFnc & progressrcv )
1744  {
1745  RepoConstIterator it( findAlias( alias, _repos ) );
1746  if ( it != _repos.end() )
1747  return *it;
1748  RepoInfo info;
1749  info.setAlias( alias );
1751  }
1752 
1753 
1754  RepoInfo RepoManager::Impl::getRepositoryInfo( const Url & url, const url::ViewOption & urlview, const ProgressData::ReceiverFnc & progressrcv )
1755  {
1756  for_( it, repoBegin(), repoEnd() )
1757  {
1758  for_( urlit, (*it).baseUrlsBegin(), (*it).baseUrlsEnd() )
1759  {
1760  if ( (*urlit).asString(urlview) == url.asString(urlview) )
1761  return *it;
1762  }
1763  }
1764  RepoInfo info;
1765  info.setBaseUrl( url );
1767  }
1768 
1770  //
1771  // Services
1772  //
1774 
1776  {
1777  assert_alias( service );
1778 
1779  // check if service already exists
1780  if ( hasService( service.alias() ) )
1782 
1783  // Writable ServiceInfo is needed to save the location
1784  // of the .service file. Finaly insert into the service list.
1785  ServiceInfo toSave( service );
1786  saveService( toSave );
1787  _services.insert( toSave );
1788 
1789  // check for credentials in Url (username:password, not ?credentials param)
1790  if ( toSave.url().hasCredentialsInAuthority() )
1791  {
1793  media::CredManagerOptions(_options.rootDir) );
1794 
1796  cm.saveInUser(media::AuthData(toSave.url()));
1797  }
1798 
1799  MIL << "added service " << toSave.alias() << endl;
1800  }
1801 
1803 
1804  void RepoManager::Impl::removeService( const std::string & alias )
1805  {
1806  MIL << "Going to delete repo " << alias << endl;
1807 
1808  const ServiceInfo & service = getService( alias );
1809 
1810  Pathname location = service.filepath();
1811  if( location.empty() )
1812  {
1813  ZYPP_THROW(RepoException( _("Can't figure out where the service is stored.") ));
1814  }
1815 
1816  ServiceSet tmpSet;
1817  parser::ServiceFileReader( location, ServiceCollector(tmpSet) );
1818 
1819  // only one service definition in the file
1820  if ( tmpSet.size() == 1 )
1821  {
1822  if ( filesystem::unlink(location) != 0 )
1823  {
1824  // TranslatorExplanation '%s' is a filename
1825  ZYPP_THROW(RepoException(str::form( _("Can't delete '%s'"), location.c_str() )));
1826  }
1827  MIL << alias << " sucessfully deleted." << endl;
1828  }
1829  else
1830  {
1831  filesystem::assert_dir(location.dirname());
1832 
1833  std::ofstream file(location.c_str());
1834  if( !file )
1835  {
1836  // TranslatorExplanation '%s' is a filename
1837  ZYPP_THROW( Exception(str::form( _("Can't open file '%s' for writing."), location.c_str() )));
1838  }
1839 
1840  for_(it, tmpSet.begin(), tmpSet.end())
1841  {
1842  if( it->alias() != alias )
1843  it->dumpAsIniOn(file);
1844  }
1845 
1846  MIL << alias << " sucessfully deleted from file " << location << endl;
1847  }
1848 
1849  // now remove all repositories added by this service
1850  RepoCollector rcollector;
1851  getRepositoriesInService( alias,
1852  boost::make_function_output_iterator( bind( &RepoCollector::collect, &rcollector, _1 ) ) );
1853  // cannot do this directly in getRepositoriesInService - would invalidate iterators
1854  for_(rit, rcollector.repos.begin(), rcollector.repos.end())
1855  removeRepository(*rit);
1856  }
1857 
1859 
1861  {
1862  // copy the set of services since refreshService
1863  // can eventually invalidate the iterator
1864  ServiceSet services( serviceBegin(), serviceEnd() );
1865  for_( it, services.begin(), services.end() )
1866  {
1867  if ( !it->enabled() )
1868  continue;
1869 
1870  try {
1871  refreshService(*it);
1872  }
1873  catch ( const repo::ServicePluginInformalException & e )
1874  { ;/* ignore ServicePluginInformalException */ }
1875  }
1876  }
1877 
1878  void RepoManager::Impl::refreshService( const std::string & alias )
1879  {
1880  ServiceInfo service( getService( alias ) );
1881  assert_alias( service );
1882  assert_url( service );
1883  // NOTE: It might be necessary to modify and rewrite the service info.
1884  // Either when probing the type, or when adjusting the repositories
1885  // enable/disable state.:
1886  bool serviceModified = false;
1887  MIL << "Going to refresh service '" << service.alias() << "', url: "<< service.url() << endl;
1888 
1890 
1891  // if the type is unknown, try probing.
1892  if ( service.type() == repo::ServiceType::NONE )
1893  {
1894  repo::ServiceType type = probeService( service.url() );
1895  if ( type != ServiceType::NONE )
1896  {
1897  service.setProbedType( type ); // lazy init!
1898  serviceModified = true;
1899  }
1900  }
1901 
1902  // get target distro identifier
1903  std::string servicesTargetDistro = _options.servicesTargetDistro;
1904  if ( servicesTargetDistro.empty() )
1905  {
1906  servicesTargetDistro = Target::targetDistribution( Pathname() );
1907  }
1908  DBG << "ServicesTargetDistro: " << servicesTargetDistro << endl;
1909 
1910  // parse it
1911  RepoCollector collector(servicesTargetDistro);
1912  // FIXME Ugly hack: ServiceRepos may throw ServicePluginInformalException
1913  // which is actually a notification. Using an exception for this
1914  // instead of signal/callback is bad. Needs to be fixed here, in refreshServices()
1915  // and in zypper.
1916  std::pair<DefaultIntegral<bool,false>, repo::ServicePluginInformalException> uglyHack;
1917  try {
1918  ServiceRepos repos(service, bind( &RepoCollector::collect, &collector, _1 ));
1919  }
1920  catch ( const repo::ServicePluginInformalException & e )
1921  {
1922  /* ignore ServicePluginInformalException and throw later */
1923  uglyHack.first = true;
1924  uglyHack.second = e;
1925  }
1926 
1927  // set service alias and base url for all collected repositories
1928  for_( it, collector.repos.begin(), collector.repos.end() )
1929  {
1930  // if the repo url was not set by the repoindex parser, set service's url
1931  Url url;
1932 
1933  if ( it->baseUrlsEmpty() )
1934  url = service.url();
1935  else
1936  {
1937  // service repo can contain only one URL now, so no need to iterate.
1938  url = *it->baseUrlsBegin();
1939  }
1940 
1941  // libzypp currently has problem with separate url + path handling
1942  // so just append the path to the baseurl
1943  if ( !it->path().empty() )
1944  {
1945  Pathname path(url.getPathName());
1946  path /= it->path();
1947  url.setPathName( path.asString() );
1948  it->setPath("");
1949  }
1950 
1951  // Prepend service alias:
1952  it->setAlias( str::form( "%s:%s", service.alias().c_str(), it->alias().c_str() ) );
1953 
1954  // save the url
1955  it->setBaseUrl( url );
1956  // set refrence to the parent service
1957  it->setService( service.alias() );
1958  }
1959 
1961  // Now compare collected repos with the ones in the system...
1962  //
1963  RepoInfoList oldRepos;
1964  getRepositoriesInService( service.alias(), std::back_inserter( oldRepos ) );
1965 
1966  // find old repositories to remove...
1967  for_( it, oldRepos.begin(), oldRepos.end() )
1968  {
1969  if ( ! foundAliasIn( it->alias(), collector.repos ) )
1970  {
1971  if ( it->enabled() && ! service.repoToDisableFind( it->alias() ) )
1972  {
1973  DBG << "Service removes enabled repo " << it->alias() << endl;
1974  service.addRepoToEnable( it->alias() );
1975  serviceModified = true;
1976  }
1977  else
1978  {
1979  DBG << "Service removes disabled repo " << it->alias() << endl;
1980  }
1981  removeRepository( *it );
1982  }
1983  }
1984 
1986  // create missing repositories and modify exising ones if needed...
1987  for_( it, collector.repos.begin(), collector.repos.end() )
1988  {
1989  // Service explicitly requests the repo being enabled?
1990  // Service explicitly requests the repo being disabled?
1991  // And hopefully not both ;) If so, enable wins.
1992  bool beEnabled = service.repoToEnableFind( it->alias() );
1993  bool beDisabled = service.repoToDisableFind( it->alias() );
1994 
1995  // Make sure the service repo is created with the
1996  // appropriate enable
1997  if ( beEnabled ) it->setEnabled(true);
1998  if ( beDisabled ) it->setEnabled(false);
1999 
2000  if ( beEnabled )
2001  {
2002  // Remove from enable request list.
2003  // NOTE: repoToDisable is handled differently.
2004  // It gets cleared on each refresh.
2005  service.delRepoToEnable( it->alias() );
2006  serviceModified = true;
2007  }
2008 
2009  RepoInfoList::iterator oldRepo( findAlias( it->alias(), oldRepos ) );
2010  if ( oldRepo == oldRepos.end() )
2011  {
2012  // Not found in oldRepos ==> a new repo to add
2013 
2014  // At that point check whether a repo with the same alias
2015  // exists outside this service. Maybe forcefully re-alias
2016  // the existing repo?
2017  DBG << "Service adds repo " << it->alias() << " " << (it->enabled()?"enabled":"disabled") << endl;
2018  addRepository( *it );
2019 
2020  // save repo credentials
2021  // ma@: task for modifyRepository?
2022  }
2023  else
2024  {
2025  // ==> an exising repo to check
2026  bool oldRepoModified = false;
2027 
2028  // changed enable?
2029  if ( beEnabled )
2030  {
2031  if ( ! oldRepo->enabled() )
2032  {
2033  DBG << "Service repo " << it->alias() << " gets enabled" << endl;
2034  oldRepo->setEnabled( true );
2035  oldRepoModified = true;
2036  }
2037  else
2038  {
2039  DBG << "Service repo " << it->alias() << " stays enabled" << endl;
2040  }
2041  }
2042  else if ( beDisabled )
2043  {
2044  if ( oldRepo->enabled() )
2045  {
2046  DBG << "Service repo " << it->alias() << " gets disabled" << endl;
2047  oldRepo->setEnabled( false );
2048  oldRepoModified = true;
2049  }
2050  else
2051  {
2052  DBG << "Service repo " << it->alias() << " stays disabled" << endl;
2053  }
2054  }
2055  else
2056  {
2057  DBG << "Service repo " << it->alias() << " stays " << (oldRepo->enabled()?"enabled":"disabled") << endl;
2058  }
2059 
2060  // changed url?
2061  // service repo can contain only one URL now, so no need to iterate.
2062  if ( oldRepo->url() != it->url() )
2063  {
2064  DBG << "Service repo " << it->alias() << " gets new URL " << it->url() << endl;
2065  oldRepo->setBaseUrl( it->url() );
2066  oldRepoModified = true;
2067  }
2068 
2069  // save if modified:
2070  if ( oldRepoModified )
2071  {
2072  modifyRepository( oldRepo->alias(), *oldRepo );
2073  }
2074  }
2075  }
2076 
2077  // Unlike reposToEnable, reposToDisable is always cleared after refresh.
2078  if ( ! service.reposToDisableEmpty() )
2079  {
2080  service.clearReposToDisable();
2081  serviceModified = true;
2082  }
2083 
2085  // save service if modified:
2086  if ( serviceModified )
2087  {
2088  // write out modified service file.
2089  modifyService( service.alias(), service );
2090  }
2091 
2092  if ( uglyHack.first )
2093  {
2094  throw( uglyHack.second ); // intentionally not ZYPP_THROW
2095  }
2096  }
2097 
2099 
2100  void RepoManager::Impl::modifyService( const std::string & oldAlias, const ServiceInfo & newService )
2101  {
2102  MIL << "Going to modify service " << oldAlias << endl;
2103 
2104  // we need a writable copy to link it to the file where
2105  // it is saved if we modify it
2106  ServiceInfo service(newService);
2107 
2108  if ( service.type() == ServiceType::PLUGIN )
2109  {
2110  MIL << "Not modifying plugin service '" << oldAlias << "'" << endl;
2111  return;
2112  }
2113 
2114  const ServiceInfo & oldService = getService(oldAlias);
2115 
2116  Pathname location = oldService.filepath();
2117  if( location.empty() )
2118  {
2119  ZYPP_THROW(RepoException( _("Can't figure out where the service is stored.") ));
2120  }
2121 
2122  // remember: there may multiple services being defined in one file:
2123  ServiceSet tmpSet;
2124  parser::ServiceFileReader( location, ServiceCollector(tmpSet) );
2125 
2126  filesystem::assert_dir(location.dirname());
2127  std::ofstream file(location.c_str());
2128  for_(it, tmpSet.begin(), tmpSet.end())
2129  {
2130  if( *it != oldAlias )
2131  it->dumpAsIniOn(file);
2132  }
2133  service.dumpAsIniOn(file);
2134  file.close();
2135  service.setFilepath(location);
2136 
2137  _services.erase(oldAlias);
2138  _services.insert(service);
2139 
2140  // changed properties affecting also repositories
2141  if( oldAlias != service.alias() // changed alias
2142  || oldService.enabled() != service.enabled() // changed enabled status
2143  )
2144  {
2145  std::vector<RepoInfo> toModify;
2146  getRepositoriesInService(oldAlias, std::back_inserter(toModify));
2147  for_( it, toModify.begin(), toModify.end() )
2148  {
2149  if (oldService.enabled() && !service.enabled())
2150  it->setEnabled(false);
2151  else if (!oldService.enabled() && service.enabled())
2152  {
2155  }
2156  else
2157  it->setService(service.alias());
2158  modifyRepository(it->alias(), *it);
2159  }
2160  }
2161 
2163  }
2164 
2166 
2168  {
2169  try
2170  {
2171  MediaSetAccess access(url);
2172  if ( access.doesFileExist("/repo/repoindex.xml") )
2173  return repo::ServiceType::RIS;
2174  }
2175  catch ( const media::MediaException &e )
2176  {
2177  ZYPP_CAUGHT(e);
2178  // TranslatorExplanation '%s' is an URL
2179  RepoException enew(str::form( _("Error trying to read from '%s'"), url.asString().c_str() ));
2180  enew.remember(e);
2181  ZYPP_THROW(enew);
2182  }
2183  catch ( const Exception &e )
2184  {
2185  ZYPP_CAUGHT(e);
2186  // TranslatorExplanation '%s' is an URL
2187  Exception enew(str::form( _("Unknown error reading from '%s'"), url.asString().c_str() ));
2188  enew.remember(e);
2189  ZYPP_THROW(enew);
2190  }
2191 
2192  return repo::ServiceType::NONE;
2193  }
2194 
2196  //
2197  // CLASS NAME : RepoManager
2198  //
2200 
2202  : _pimpl( new Impl(opt) )
2203  {}
2204 
2206  {}
2207 
2209  { return _pimpl->repoEmpty(); }
2210 
2212  { return _pimpl->repoSize(); }
2213 
2215  { return _pimpl->repoBegin(); }
2216 
2218  { return _pimpl->repoEnd(); }
2219 
2220  RepoInfo RepoManager::getRepo( const std::string & alias ) const
2221  { return _pimpl->getRepo( alias ); }
2222 
2223  bool RepoManager::hasRepo( const std::string & alias ) const
2224  { return _pimpl->hasRepo( alias ); }
2225 
2226  std::string RepoManager::makeStupidAlias( const Url & url_r )
2227  {
2228  std::string ret( url_r.getScheme() );
2229  if ( ret.empty() )
2230  ret = "repo-";
2231  else
2232  ret += "-";
2233 
2234  std::string host( url_r.getHost() );
2235  if ( ! host.empty() )
2236  {
2237  ret += host;
2238  ret += "-";
2239  }
2240 
2241  static Date::ValueType serial = Date::now();
2242  ret += Digest::digest( Digest::sha1(), str::hexstring( ++serial ) +url_r.asCompleteString() ).substr(0,8);
2243  return ret;
2244  }
2245 
2247  { return _pimpl->metadataStatus( info ); }
2248 
2250  { return _pimpl->checkIfToRefreshMetadata( info, url, policy ); }
2251 
2252  Pathname RepoManager::metadataPath( const RepoInfo &info ) const
2253  { return _pimpl->metadataPath( info ); }
2254 
2255  Pathname RepoManager::packagesPath( const RepoInfo &info ) const
2256  { return _pimpl->packagesPath( info ); }
2257 
2259  { return _pimpl->refreshMetadata( info, policy, progressrcv ); }
2260 
2261  void RepoManager::cleanMetadata( const RepoInfo &info, const ProgressData::ReceiverFnc & progressrcv )
2262  { return _pimpl->cleanMetadata( info, progressrcv ); }
2263 
2264  void RepoManager::cleanPackages( const RepoInfo &info, const ProgressData::ReceiverFnc & progressrcv )
2265  { return _pimpl->cleanPackages( info, progressrcv ); }
2266 
2268  { return _pimpl->cacheStatus( info ); }
2269 
2270  void RepoManager::buildCache( const RepoInfo &info, CacheBuildPolicy policy, const ProgressData::ReceiverFnc & progressrcv )
2271  { return _pimpl->buildCache( info, policy, progressrcv ); }
2272 
2273  void RepoManager::cleanCache( const RepoInfo &info, const ProgressData::ReceiverFnc & progressrcv )
2274  { return _pimpl->cleanCache( info, progressrcv ); }
2275 
2276  bool RepoManager::isCached( const RepoInfo &info ) const
2277  { return _pimpl->isCached( info ); }
2278 
2279  void RepoManager::loadFromCache( const RepoInfo &info, const ProgressData::ReceiverFnc & progressrcv )
2280  { return _pimpl->loadFromCache( info, progressrcv ); }
2281 
2283  { return _pimpl->cleanCacheDirGarbage( progressrcv ); }
2284 
2285  repo::RepoType RepoManager::probe( const Url & url, const Pathname & path ) const
2286  { return _pimpl->probe( url, path ); }
2287 
2289  { return _pimpl->probe( url ); }
2290 
2291  void RepoManager::addRepository( const RepoInfo &info, const ProgressData::ReceiverFnc & progressrcv )
2292  { return _pimpl->addRepository( info, progressrcv ); }
2293 
2294  void RepoManager::addRepositories( const Url &url, const ProgressData::ReceiverFnc & progressrcv )
2295  { return _pimpl->addRepositories( url, progressrcv ); }
2296 
2297  void RepoManager::removeRepository( const RepoInfo & info, const ProgressData::ReceiverFnc & progressrcv )
2298  { return _pimpl->removeRepository( info, progressrcv ); }
2299 
2300  void RepoManager::modifyRepository( const std::string &alias, const RepoInfo & newinfo, const ProgressData::ReceiverFnc & progressrcv )
2301  { return _pimpl->modifyRepository( alias, newinfo, progressrcv ); }
2302 
2303  RepoInfo RepoManager::getRepositoryInfo( const std::string &alias, const ProgressData::ReceiverFnc & progressrcv )
2304  { return _pimpl->getRepositoryInfo( alias, progressrcv ); }
2305 
2306  RepoInfo RepoManager::getRepositoryInfo( const Url & url, const url::ViewOption & urlview, const ProgressData::ReceiverFnc & progressrcv )
2307  { return _pimpl->getRepositoryInfo( url, urlview, progressrcv ); }
2308 
2310  { return _pimpl->serviceEmpty(); }
2311 
2313  { return _pimpl->serviceSize(); }
2314 
2316  { return _pimpl->serviceBegin(); }
2317 
2319  { return _pimpl->serviceEnd(); }
2320 
2321  ServiceInfo RepoManager::getService( const std::string & alias ) const
2322  { return _pimpl->getService( alias ); }
2323 
2324  bool RepoManager::hasService( const std::string & alias ) const
2325  { return _pimpl->hasService( alias ); }
2326 
2328  { return _pimpl->probeService( url ); }
2329 
2330  void RepoManager::addService( const std::string & alias, const Url& url )
2331  { return _pimpl->addService( alias, url ); }
2332 
2333  void RepoManager::addService( const ServiceInfo & service )
2334  { return _pimpl->addService( service ); }
2335 
2336  void RepoManager::removeService( const std::string & alias )
2337  { return _pimpl->removeService( alias ); }
2338 
2339  void RepoManager::removeService( const ServiceInfo & service )
2340  { return _pimpl->removeService( service ); }
2341 
2343  { return _pimpl->refreshServices(); }
2344 
2345  void RepoManager::refreshService( const std::string & alias )
2346  { return _pimpl->refreshService( alias ); }
2347 
2349  { return _pimpl->refreshService( service ); }
2350 
2351  void RepoManager::modifyService( const std::string & oldAlias, const ServiceInfo & service )
2352  { return _pimpl->modifyService( oldAlias, service ); }
2353 
2355 
2356  std::ostream & operator<<( std::ostream & str, const RepoManager & obj )
2357  { return str << *obj._pimpl; }
2358 
2360 } // namespace zypp
Pathname packagesPath(const RepoInfo &info) const
Definition: RepoManager.cc:452
RepoManager(const RepoManagerOptions &options=RepoManagerOptions())
int assert_dir(const Pathname &path, unsigned mode)
Like &#39;mkdir -p&#39;.
Definition: PathInfo.cc:324
void removeService(const std::string &alias)
Removes service specified by its name.
thrown when it was impossible to match a repository
Thrown when the repo alias is found to be invalid.
Interface to gettext.
RepoManagerOptions(const Pathname &root_r=Pathname())
Default ctor following ZConfig global settings.
Definition: RepoManager.cc:375
#define MIL
Definition: Logger.h:47
bool hasService(const std::string &alias) const
Definition: RepoManager.cc:498
std::string alias() const
unique identifier for this source.
static const std::string & sha1()
sha1
Definition: Digest.cc:46
int exchange(const Pathname &lpath, const Pathname &rpath)
Exchanges two files or directories.
Definition: PathInfo.cc:688
void setCacheStatus(const RepoInfo &info, const RepoStatus &status)
Definition: RepoManager.cc:537
std::string generateFilename(const ServiceInfo &info) const
Definition: RepoManager.cc:534
thrown when it was impossible to determine this repo type.
std::string digest()
get hex string representation of the digest
Definition: Digest.cc:174
Retrieval of repository list for a service.
Definition: ServiceRepos.h:26
virtual std::ostream & dumpAsIniOn(std::ostream &str) const
Write this RepoInfo object into str in a .repo file format.
Definition: RepoInfo.cc:426
void refreshServices()
Refreshes all enabled services.
bool serviceEmpty() const
Gets true if no service is in RepoManager (so no one in specified location)
void modifyService(const std::string &oldAlias, const ServiceInfo &service)
Modifies service file (rewrites it with new values) and underlying repositories if needed...
Read service data from a .service file.
void sendTo(const ReceiverFnc &fnc_r)
Set ReceiverFnc.
Definition: ProgressData.h:231
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:320
Date timestamp() const
timestamp of the repository.
Definition: RepoStatus.cc:144
ServiceConstIterator serviceBegin() const
Definition: RepoManager.cc:495
std::string checksum() const
Checksum of the repository.
Definition: RepoStatus.cc:141
static ZConfig & instance()
Singleton ctor.
Definition: ZConfig.cc:655
Pathname path() const
Definition: TmpPath.cc:146
static TmpDir makeSibling(const Pathname &sibling_r)
Provide a new empty temporary directory as sibling.
Definition: TmpPath.cc:287
#define OPT_PROGRESS
Definition: RepoManager.cc:59
RWCOW_pointer< Impl > _pimpl
Pointer to implementation.
Definition: RepoManager.h:690
void cleanCacheDirGarbage(const ProgressData::ReceiverFnc &progressrcv=ProgressData::ReceiverFnc())
Remove any subdirectories of cache directories which no longer belong to any of known repositories...
RepoConstIterator repoBegin() const
Definition: RepoManager.cc:436
Pathname filepath() const
File where this repo was read from.
void resetDispose()
Set no dispose function.
Definition: AutoDispose.h:162
bool isCached(const RepoInfo &info) const
Definition: RepoManager.cc:473
RepoStatus metadataStatus(const RepoInfo &info) const
Status of local metadata.
std::string getPathName(EEncoding eflag=zypp::url::E_DECODED) const
Returns the path name from the URL.
Definition: Url.cc:598
#define _PL(MSG1, MSG2, N)
Return translated text (plural form).
Definition: Gettext.h:24
bool empty() const
Test for an empty path.
Definition: Pathname.h:113
std::string getHost(EEncoding eflag=zypp::url::E_DECODED) const
Returns the hostname or IP from the URL authority.
Definition: Url.cc:582
RefreshCheckStatus
Possibly return state of checkIfRefreshMEtadata function.
Definition: RepoManager.h:191
Pathname metadataPath(const RepoInfo &info) const
Path where the metadata is downloaded and kept.
const std::string & command() const
The command we&#39;re executing.
urls_const_iterator baseUrlsBegin() const
iterator that points at begin of repository urls
Definition: RepoInfo.cc:252
RepoSet::size_type RepoSizeType
Definition: RepoManager.h:124
bool empty() const
Is the status empty?
Definition: RepoStatus.cc:124
void loadFromCache(const RepoInfo &info, const ProgressData::ReceiverFnc &progressrcv=ProgressData::ReceiverFnc())
Load resolvables into the pool.
ServiceConstIterator serviceEnd() const
Iterator to place behind last service in internal storage.
repo::RepoType probe(const Url &url, const Pathname &path) const
Probe repo metadata type.
std::string generateFilename(const RepoInfo &info) const
Definition: RepoManager.cc:531
RepoConstIterator repoBegin() const
void refreshMetadata(const RepoInfo &info, RawMetadataRefreshPolicy policy=RefreshIfNeeded, const ProgressData::ReceiverFnc &progressrcv=ProgressData::ReceiverFnc())
Refresh local raw cache.
Pathname packagesPath(const RepoInfo &info) const
Path where the rpm packages are downloaded and kept.
void addService(const std::string &alias, const Url &url)
Definition: RepoManager.cc:509
void touchIndexFile(const RepoInfo &info)
Definition: RepoManager.cc:762
void setAlias(const std::string &alias)
set the repository alias
Definition: RepoInfoBase.cc:99
void addRepoToEnable(const std::string &alias_r)
Add alias_r to the set of ReposToEnable.
Definition: ServiceInfo.cc:127
void removeRepository(const RepoInfo &info, OPT_PROGRESS)
void modifyService(const std::string &oldAlias, const ServiceInfo &newService)
bool toMax()
Set counter value to current max value (unless no range).
Definition: ProgressData.h:270
void setProbedType(const repo::RepoType &t) const
This allows to adjust the RepoType lazy, from NONE to some probed value, even for const objects...
Definition: RepoInfo.cc:191
bool doesFileExist(const Pathname &file, unsigned media_nr=1)
Checks if a file exists on the specified media, with user callbacks.
void setFilepath(const Pathname &filename)
set the path to the .repo file
void refreshService(const ServiceInfo &service)
Definition: RepoManager.cc:519
What is known about a repository.
Definition: RepoInfo.h:66
Service plugin has trouble providing the metadata but this should not be treated as error...
void removeRepository(const RepoInfo &info, const ProgressData::ReceiverFnc &progressrcv=ProgressData::ReceiverFnc())
Remove the best matching repository from known repos list.
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition: Easy.h:27
void setBaseUrl(const Url &url)
Clears current base URL list and adds url.
Definition: RepoInfo.cc:179
bool enabled() const
If enabled is false, then this repository must be ignored as if does not exists, except when checking...
std::string targetDistro
Definition: RepoManager.cc:193
void reposErase(const std::string &alias_r)
Remove a Repository named alias_r.
Definition: Pool.h:98
Service already exists and some unique attribute can&#39;t be duplicated.
bool repo_add_probe() const
Whether repository urls should be probed.
Definition: ZConfig.cc:821
urls_const_iterator baseUrlsEnd() const
iterator that points at end of repository urls
Definition: RepoInfo.cc:259
std::string targetDistribution() const
This is register.target attribute of the installed base product.
Definition: Target.cc:114
static RepoStatus fromCookieFile(const Pathname &path)
reads the status from a file which contains the checksum and timestamp in each line.
Definition: RepoStatus.cc:97
Service without alias was used in an operation.
RepoStatus metadataStatus(const RepoInfo &info) const
Definition: RepoManager.cc:714
RepoSet::const_iterator RepoConstIterator
Definition: RepoManager.h:123
function< bool(const ProgressData &)> ReceiverFnc
Most simple version of progress reporting The percentage in most cases.
Definition: ProgressData.h:144
RepoStatus dirStatus(const Pathname &dir)
Gives a cookie for a dir.
Definition: RepoParser.cc:48
Url::asString() view options.
Definition: UrlBase.h:39
void cleanMetadata(const RepoInfo &info, OPT_PROGRESS)
#define ERR
Definition: Logger.h:49
unsigned int MediaAccessId
Media manager access Id type.
Definition: MediaSource.h:29
void modifyRepository(const std::string &alias, const RepoInfo &newinfo, const ProgressData::ReceiverFnc &progressrcv=ProgressData::ReceiverFnc())
Modify repository attributes.
std::vector< std::string > Arguments
RepoManagerOptions _options
Definition: RepoManager.cc:560
std::string asString() const
Returns a default string representation of the Url object.
Definition: Url.cc:491
ServiceInfo getService(const std::string &alias) const
Definition: RepoManager.cc:501
void refreshService(const std::string &alias)
Refresh specific service.
RepoSizeType repoSize() const
Repo manager settings.
Definition: RepoManager.h:52
void remember(const Exception &old_r)
Store an other Exception as history.
Definition: Exception.cc:89
std::string & replaceAll(std::string &str_r, const std::string &from_r, const std::string &to_r)
Replace all occurrences of from_r with to_r in str_r (inplace).
Definition: String.cc:304
void removeService(const ServiceInfo &service)
Definition: RepoManager.cc:513
transform_iterator< repo::RepoVariablesUrlReplacer, url_set::const_iterator > urls_const_iterator
Definition: RepoInfo.h:96
Progress callback from another progress.
Definition: ProgressData.h:387
std::string label() const
Label for use in messages for the user interface.
void addRepository(const RepoInfo &info, OPT_PROGRESS)
static const ServiceType RIS
Repository Index Service (RIS) (formerly known as &#39;Novell Update&#39; (NU) service)
Definition: ServiceType.h:32
RepoManager implementation.
Definition: RepoManager.cc:423
#define ZYPP_RETHROW(EXCPT)
Drops a logline and rethrows, updating the CodeLocation.
Definition: Exception.h:328
void setPathName(const std::string &path, EEncoding eflag=zypp::url::E_DECODED)
Set the path name.
Definition: Url.cc:758
std::set< RepoInfo > RepoSet
RepoInfo typedefs.
Definition: RepoManager.h:122
bool toMin()
Set counter value to current min value.
Definition: ProgressData.h:266
RepoInfo getRepositoryInfo(const std::string &alias, OPT_PROGRESS)
Downloader for SUSETags (YaST2) repositories Encapsulates all the knowledge of which files have to be...
Definition: Downloader.h:34
boost::noncopyable NonCopyable
Ensure derived classes cannot be copied.
Definition: NonCopyable.h:26
static Pool instance()
Singleton ctor.
Definition: Pool.h:51
bool serviceEmpty() const
Definition: RepoManager.cc:493
static RepoManagerOptions makeTestSetup(const Pathname &root_r)
Test setup adjusting all paths to be located below one root_r directory.
Definition: RepoManager.cc:389
Pathname rootDir
remembers root_r value for later use
Definition: RepoManager.h:99
void removeRepository(const RepoInfo &repo)
Log recently removed repository.
Definition: HistoryLog.cc:257
Provide a new empty temporary directory and recursively delete it when no longer needed.
Definition: TmpPath.h:170
void clearReposToDisable()
Clear the set of ReposToDisable.
Definition: ServiceInfo.cc:164
Lightweight repository attribute value lookup.
Definition: LookupAttr.h:260
std::string asCompleteString() const
Returns a complete string representation of the Url object.
Definition: Url.cc:499
std::ostream & operator<<(std::ostream &str, const Exception &obj)
Definition: Exception.cc:120
RepoConstIterator repoEnd() const
Execute a program and give access to its io An object of this class encapsulates the execution of an ...
void cleanCacheDirGarbage(OPT_PROGRESS)
int unlink(const Pathname &path)
Like &#39;unlink&#39;.
Definition: PathInfo.cc:660
thrown when it was impossible to determine one url for this repo.
Definition: RepoException.h:78
Just inherits Exception to separate media exceptions.
static const ServiceType NONE
No service set.
Definition: ServiceType.h:34
static const SolvAttr repositoryToolVersion
Definition: SolvAttr.h:169
Service type enumeration.
Definition: ServiceType.h:26
void modifyRepository(const std::string &alias, const RepoInfo &newinfo_r, OPT_PROGRESS)
ServiceSet::const_iterator ServiceConstIterator
Definition: RepoManager.h:118
std::ostream & operator<<(std::ostream &str, const DeltaCandidates &obj)
repo::ServiceType probeService(const Url &url) const
Probe the type or the service.
int recursive_rmdir(const Pathname &path)
Like &#39;rm -r DIR&#39;.
Definition: PathInfo.cc:417
#define WAR
Definition: Logger.h:48
#define OUTS(X)
void setMetadataPath(const Pathname &path)
set the path where the local metadata is stored
Definition: RepoInfo.cc:195
void setType(const repo::RepoType &t)
set the repository type
Definition: RepoInfo.cc:188
Maintain [min,max] and counter (value) for progress counting.
Definition: ProgressData.h:135
RepoInfoList repos
Definition: RepoManager.cc:192
RepoStatus cacheStatus(const RepoInfo &info) const
Definition: RepoManager.cc:476
Pathname generateNonExistingName(const Pathname &dir, const std::string &basefilename) const
Generate a non existing filename in a directory, using a base name.
Definition: RepoManager.cc:612
void addRepository(const RepoInfo &repo)
Log a newly added repository.
Definition: HistoryLog.cc:245
zypp::Url url
Definition: MediaCurl.cc:193
RepoInfo getRepo(const std::string &alias) const
Definition: RepoManager.cc:442
Writing the zypp history fileReference counted signleton for writhing the zypp history file...
Definition: HistoryLog.h:55
void addRepository(const RepoInfo &info, const ProgressData::ReceiverFnc &progressrcv=ProgressData::ReceiverFnc())
Adds a repository to the list of known repositories.
RepoInfo getRepositoryInfo(const std::string &alias, const ProgressData::ReceiverFnc &progressrcv=ProgressData::ReceiverFnc())
Find a matching repository info.
#define _(MSG)
Return translated text.
Definition: Gettext.h:21
static const ServiceType PLUGIN
Plugin services are scripts installed on your system that provide the package manager with repositori...
Definition: ServiceType.h:43
std::string receiveLine()
Read one line from the input stream.
void delRepoToEnable(const std::string &alias_r)
Remove alias_r from the set of ReposToEnable.
Definition: ServiceInfo.cc:133
static std::string makeStupidAlias(const Url &url_r=Url())
Some stupid string but suitable as alias for your url if nothing better is available.
RefreshCheckStatus checkIfToRefreshMetadata(const RepoInfo &info, const Url &url, RawMetadataRefreshPolicy policy=RefreshIfNeeded)
Checks whether to refresh metadata for specified repository and url.
void cleanCache(const RepoInfo &info, const ProgressData::ReceiverFnc &progressrcv=ProgressData::ReceiverFnc())
clean local cache
void cleanCache(const RepoInfo &info, OPT_PROGRESS)
std::string numstring(char n, int w=0)
Definition: String.h:219
ServiceSet::size_type ServiceSizeType
Definition: RepoManager.h:119
Class for handling media authentication data.
Definition: MediaUserAuth.h:30
bool reposToDisableEmpty() const
Definition: ServiceInfo.cc:140
static const RepoType NONE
Definition: RepoType.h:32
int touch(const Pathname &path)
Change file&#39;s modification and access times.
Definition: PathInfo.cc:1133
void saveToCookieFile(const Pathname &path) const
save the status information to a cookie file
Definition: RepoStatus.cc:114
ServiceInfo getService(const std::string &alias) const
Finds ServiceInfo by alias or return ServiceInfo::noService.
void getRepositoriesInService(const std::string &alias, OutputIterator out) const
Definition: RepoManager.cc:547
void setPackagesPath(const Pathname &path)
set the path where the local packages are stored
Definition: RepoInfo.cc:198
bool repoEmpty() const
Definition: RepoManager.cc:434
std::ostream & copy(std::istream &from_r, std::ostream &to_r)
Copy istream to ostream.
Definition: IOStream.h:50
int close()
Wait for the progamm to complete.
bool hasRepo(const std::string &alias) const
Return whether there is a known repository for alias.
static const RepoType RPMMD
Definition: RepoType.h:29
creates and provides information about known sources.
Definition: RepoManager.h:108
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition: Exception.h:324
std::string form(const char *format,...)
Printf style construction of std::string.
Definition: String.cc:34
RepoStatus cacheStatus(const RepoInfo &info) const
Status of metadata cache.
repo::RepoType type() const
Type of repository,.
Definition: RepoInfo.cc:222
int readdir(std::list< std::string > &retlist_r, const Pathname &path_r, bool dots_r)
Return content of directory via retlist.
Definition: PathInfo.cc:599
RepoSizeType repoSize() const
Definition: RepoManager.cc:435
void addService(const ServiceInfo &service)
std::list< RepoInfo > readRepoFile(const Url &repo_file)
Parses repo_file and returns a list of RepoInfo objects corresponding to repositories found within th...
Definition: RepoManager.cc:354
RepoInfo getRepo(const std::string &alias) const
Find RepoInfo by alias or return RepoInfo::noRepo.
static const RepoType YAST2
Definition: RepoType.h:30
ServiceSet & _services
Definition: RepoManager.cc:347
thrown when it was impossible to determine an alias for this repo.
Definition: RepoException.h:91
void buildCache(const RepoInfo &info, CacheBuildPolicy policy=BuildIfNeeded, const ProgressData::ReceiverFnc &progressrcv=ProgressData::ReceiverFnc())
Refresh local cache.
Base class for Exception.
Definition: Exception.h:143
void addRepositories(const Url &url, const ProgressData::ReceiverFnc &progressrcv=ProgressData::ReceiverFnc())
Adds repositores from a repo file to the list of known repositories.
std::set< ServiceInfo > ServiceSet
ServiceInfo typedefs.
Definition: RepoManager.h:114
Type toEnum() const
Definition: RepoType.h:48
Exception for repository handling.
Definition: RepoException.h:37
void saveService(ServiceInfo &service) const
Definition: RepoManager.cc:578
Impl(const RepoManagerOptions &opt)
Definition: RepoManager.cc:426
media::MediaAccessId _mid
Definition: RepoManager.cc:100
static Date now()
Return the current time.
Definition: Date.h:76
repo::RepoType probe(const Url &url, const Pathname &path=Pathname()) const
callback::SendReport< DownloadProgressReport > * report
Definition: MediaCurl.cc:178
value_type val() const
Definition: ProgressData.h:292
ServiceConstIterator serviceEnd() const
Definition: RepoManager.cc:496
Functor thats filter RepoInfo by service which it belongs to.
Definition: RepoManager.h:633
bool isCached(const RepoInfo &info) const
Whether a repository exists in cache.
bool hasRepo(const std::string &alias) const
Definition: RepoManager.cc:439
Reference counted access to a _Tp object calling a custom Dispose function when the last AutoDispose ...
Definition: AutoDispose.h:92
The repository cache is not built yet so you can&#39;t create the repostories from the cache...
Definition: RepoException.h:65
time_t ValueType
Definition: Date.h:37
void eraseFromPool()
Remove this Repository from it&#39;s Pool.
Definition: Repository.cc:225
Pathname repoPackagesCachePath
Definition: RepoManager.h:81
static const ServiceInfo noService
Represents an empty service.
Definition: ServiceInfo.h:58
RepoConstIterator repoEnd() const
Definition: RepoManager.cc:437
bool hasService(const std::string &alias) const
Return whether there is a known service for alias.
void removeService(const std::string &alias)
void buildCache(const RepoInfo &info, CacheBuildPolicy policy, OPT_PROGRESS)
bool repoToDisableFind(const std::string &alias_r) const
Whether alias_r is mentioned in ReposToDisable.
Definition: ServiceInfo.cc:152
static const RepoInfo noRepo
Represents no Repository (one with an empty alias).
Definition: RepoInfo.h:75
bool regex_match(const std::string &s, smatch &matches, const regex &regex)
regex ZYPP_STR_REGEX regex ZYPP_STR_REGEX
Definition: Regex.h:70
Thrown when the repo alias is found to be invalid.
ServiceSizeType serviceSize() const
Gets count of service in RepoManager (in specified location)
static const RepoType RPMPLAINDIR
Definition: RepoType.h:31
static const std::string & systemRepoAlias()
Reserved system repository alias .
Definition: Repository.cc:35
bool repoToEnableFind(const std::string &alias_r) const
Whether alias_r is mentioned in ReposToEnable.
Definition: ServiceInfo.cc:124
ServiceSizeType serviceSize() const
Definition: RepoManager.cc:494
Local facts about a repository This class represents the status of a repository on the system...
Definition: RepoStatus.h:37
void cleanPackages(const RepoInfo &info, const ProgressData::ReceiverFnc &progressrcv=ProgressData::ReceiverFnc())
Clean local package cache.
unsigned repo_refresh_delay() const
Amount of time in minutes that must pass before another refresh.
Definition: ZConfig.cc:824
Repository already exists and some unique attribute can&#39;t be duplicated.
ServiceConstIterator serviceBegin() const
Iterator to first service in internal storage.
bool set(value_type val_r)
Set new counter value.
Definition: ProgressData.h:251
std::string getScheme() const
Returns the scheme name of the URL.
Definition: Url.cc:527
Url url() const
Gets url to service.
Definition: ServiceInfo.cc:101
static bool schemeIsDownloading(const std::string &scheme_r)
http https ftp sftp tftp
Definition: Url.cc:474
void modifyRepository(const RepoInfo &oldrepo, const RepoInfo &newrepo)
Log certain modifications to a repository.
Definition: HistoryLog.cc:268
std::ostream & operator<<(std::ostream &str, const RepoManager::Impl &obj)
Definition: RepoManager.cc:573
Impl * clone() const
clone for RWCOW_pointer
Definition: RepoManager.cc:567
urls_size_type baseUrlsSize() const
number of repository urls
Definition: RepoInfo.cc:266
Repository addRepoSolv(const Pathname &file_r, const std::string &name_r)
Load Solvables from a solv-file into a Repository named name_r.
Definition: Pool.cc:145
std::string asString() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: LookupAttr.cc:613
void name(const std::string &name_r)
Set counter name.
Definition: ProgressData.h:227
Downloader for YUM (rpm-nmd) repositories Encapsulates all the knowledge of which files have to be do...
Definition: Downloader.h:41
Pathname metadataPath(const RepoInfo &info) const
Definition: RepoManager.cc:449
void setProbedType(const repo::ServiceType &t) const
Definition: ServiceInfo.cc:109
void cleanPackages(const RepoInfo &info, OPT_PROGRESS)
Pathname provideFile(const OnMediaLocation &resource, ProvideFileOptions options=PROVIDE_DEFAULT, const Pathname &deltafile=Pathname())
Provides a file from a media location.
bool repoEmpty() const
void loadFromCache(const RepoInfo &info, OPT_PROGRESS)
std::string hexstring(char n, int w=4)
Definition: String.h:254
void addService(const std::string &alias, const Url &url)
Adds new service by it&#39;s alias and url.
void refreshMetadata(const RepoInfo &info, RawMetadataRefreshPolicy policy, OPT_PROGRESS)
Definition: RepoManager.cc:948
Service has no or invalid url defined.
Url manipulation class.
Definition: Url.h:87
void addRepositories(const Url &url, OPT_PROGRESS)
Media access layer responsible for handling files distributed on a set of media with media change and...
void cleanMetadata(const RepoInfo &info, const ProgressData::ReceiverFnc &progressrcv=ProgressData::ReceiverFnc())
Clean local metadata.
void saveInUser(const AuthData &cred)
Saves given cred to user&#39;s credentials file.
Pathname path() const
Repository path.
Definition: RepoInfo.cc:243
#define DBG
Definition: Logger.h:46
bool hasCredentialsInAuthority() const
Returns true if username and password are encoded in the authority component.
Definition: Url.h:371
virtual std::ostream & dumpAsIniOn(std::ostream &str) const
Writes ServiceInfo to stream in &quot;.service&quot; format.
Definition: ServiceInfo.cc:168
repo::ServiceType type() const
Definition: ServiceInfo.cc:104
void refreshService(const std::string &alias)
iterator begin() const
Iterator to the begin of query results.
Definition: LookupAttr.cc:236
Repository type enumeration.
Definition: RepoType.h:27
RefreshCheckStatus checkIfToRefreshMetadata(const RepoInfo &info, const Url &url, RawMetadataRefreshPolicy policy)
Definition: RepoManager.cc:799
repo::ServiceType probeService(const Url &url) const