Imported Upstream version 17.0.0
[platform/upstream/libzypp.git] / zypp / RepoManager.cc
index d34a792..50ddf46 100644 (file)
@@ -63,6 +63,19 @@ using namespace zypp::repo;
 ///////////////////////////////////////////////////////////////////
 namespace zypp
 {
+
+  ///////////////////////////////////////////////////////////////////
+  namespace env
+  {
+    /** To trigger appdata refresh unconditionally */
+    inline bool ZYPP_PLUGIN_APPDATA_FORCE_COLLECT()
+    {
+      const char * env = getenv("ZYPP_PLUGIN_APPDATA_FORCE_COLLECT");
+      return( env && str::strToBool( env, true ) );
+    }
+  } // namespace env
+  ///////////////////////////////////////////////////////////////////
+
   ///////////////////////////////////////////////////////////////////
   namespace
   {
@@ -367,6 +380,15 @@ namespace zypp
 
     ////////////////////////////////////////////////////////////////////////////
 
+    ///////////////////////////////////////////////////////////////////
+    namespace
+    {
+      /** Whether repo is not under RM control and provides it's own methadata paths. */
+      inline bool isTmpRepo( const RepoInfo & info_r )
+      { return( info_r.filepath().empty() && info_r.usesAutoMethadataPaths() ); }
+    } // namespace
+    ///////////////////////////////////////////////////////////////////
+
     /**
      * \short Calculates the raw cache path for a repository, this is usually
      * /var/cache/zypp/alias
@@ -374,7 +396,7 @@ namespace zypp
     inline Pathname rawcache_path_for_repoinfo( const RepoManagerOptions &opt, const RepoInfo &info )
     {
       assert_alias(info);
-      return opt.repoRawCachePath / info.escaped_alias();
+      return isTmpRepo( info ) ? info.metadataPath() : opt.repoRawCachePath / info.escaped_alias();
     }
 
     /**
@@ -386,10 +408,7 @@ namespace zypp
      * for example /var/cache/zypp/alias/addondir
      */
     inline Pathname rawproductdata_path_for_repoinfo( const RepoManagerOptions &opt, const RepoInfo &info )
-    {
-      assert_alias(info);
-      return opt.repoRawCachePath / info.escaped_alias() / info.path();
-    }
+    { return rawcache_path_for_repoinfo( opt, info ) / info.path(); }
 
     /**
      * \short Calculates the packages cache path for a repository
@@ -397,16 +416,16 @@ namespace zypp
     inline Pathname packagescache_path_for_repoinfo( const RepoManagerOptions &opt, const RepoInfo &info )
     {
       assert_alias(info);
-      return opt.repoPackagesCachePath / info.escaped_alias();
+      return isTmpRepo( info ) ? info.packagesPath() : opt.repoPackagesCachePath / info.escaped_alias();
     }
 
     /**
      * \short Calculates the solv cache path for a repository
      */
-    inline Pathname solv_path_for_repoinfo( const RepoManagerOptions &opt, const RepoInfo &info)
+    inline Pathname solv_path_for_repoinfo( const RepoManagerOptions &opt, const RepoInfo &info )
     {
       assert_alias(info);
-      return opt.repoSolvCachePath / info.escaped_alias();
+      return isTmpRepo( info ) ? info.metadataPath().dirname() / "%SLV%" : opt.repoSolvCachePath / info.escaped_alias();
     }
 
     ////////////////////////////////////////////////////////////////////////////
@@ -517,7 +536,8 @@ namespace zypp
     ~Impl()
     {
       // trigger appdata refresh if some repos change
-      if ( _reposDirty && geteuid() == 0 && ( _options.rootDir.empty() || _options.rootDir == "/" ) )
+      if ( ( _reposDirty || env::ZYPP_PLUGIN_APPDATA_FORCE_COLLECT() )
+       && geteuid() == 0 && ( _options.rootDir.empty() || _options.rootDir == "/" ) )
       {
        try {
          std::list<Pathname> entries;
@@ -891,7 +911,7 @@ namespace zypp
     switch ( repokind.toEnum() )
     {
       case RepoType::RPMMD_e :
-        status = RepoStatus( productdatapath/"repodata/repomd.xml");
+        status = RepoStatus( productdatapath/"repodata/repomd.xml") && RepoStatus( mediarootpath/"media.1/media" );
        break;
 
       case RepoType::YAST2_e :
@@ -954,33 +974,37 @@ namespace zypp
     assert_alias(info);
     try
     {
-      MIL << "Going to try to check whether refresh is needed for " << url << endl;
+      MIL << "Going to try to check whether refresh is needed for " << url << " (" << info.type() << ")" << endl;
 
       // first check old (cached) metadata
       Pathname mediarootpath = rawcache_path_for_repoinfo( _options, info );
       filesystem::assert_dir( mediarootpath );
       RepoStatus oldstatus = metadataStatus( info );
-
       if ( oldstatus.empty() )
       {
         MIL << "No cached metadata, going to refresh" << endl;
         return REFRESH_NEEDED;
       }
 
+      if ( url.schemeIsVolatile() )
       {
-        if ( url.schemeIsVolatile() )
-       {
-         MIL << "never refresh CD/DVD" << endl;
-          return REPO_UP_TO_DATE;
-       }
-       if ( url.schemeIsLocal() )
-       {
-         policy = RefreshIfNeededIgnoreDelay;
-       }
+       MIL << "Never refresh CD/DVD" << endl;
+       return REPO_UP_TO_DATE;
+      }
+
+      if ( policy == RefreshForced )
+      {
+       MIL << "Forced refresh!" << endl;
+       return REFRESH_NEEDED;
+      }
+
+      if ( url.schemeIsLocal() )
+      {
+       policy = RefreshIfNeededIgnoreDelay;
       }
 
       // now we've got the old (cached) status, we can decide repo.refresh.delay
-      if (policy != RefreshForced && policy != RefreshIfNeededIgnoreDelay)
+      if ( policy != RefreshIfNeededIgnoreDelay )
       {
         // difference in seconds
         double diff = difftime(
@@ -1042,27 +1066,17 @@ namespace zypp
       }
 
       // check status
-      bool refresh = false;
       if ( oldstatus == newstatus )
       {
        MIL << "repo has not changed" << endl;
-       if ( policy == RefreshForced )
-       {
-         MIL << "refresh set to forced" << endl;
-         refresh = true;
-       }
+       touchIndexFile( info );
+       return REPO_UP_TO_DATE;
       }
-      else
+      else // includes newstatus.empty() if e.g. repo format changed
       {
        MIL << "repo has changed, going to refresh" << endl;
-       refresh = true;
+       return REFRESH_NEEDED;
       }
-
-      if (!refresh)
-       touchIndexFile(info);
-
-      return refresh ? REFRESH_NEEDED : REPO_UP_TO_DATE;
-
     }
     catch ( const Exception &e )
     {
@@ -1087,7 +1101,6 @@ namespace zypp
 
     // Suppress (interactive) media::MediaChangeReport if we in have multiple basurls (>1)
     media::ScopedDisableMediaChangeReport guard( info.baseUrlsSize() > 1 );
-
     // try urls one by one
     for ( RepoInfo::urls_const_iterator it = info.baseUrlsBegin(); it != info.baseUrlsEnd(); ++it )
     {
@@ -1102,16 +1115,15 @@ namespace zypp
 
         MIL << "Going to refresh metadata from " << url << endl;
 
+       // bsc#1048315: Always re-probe in case of repo format change.
+       // TODO: Would be sufficient to verify the type and re-probe
+       // if verification failed (or type is RepoType::NONE)
         repo::RepoType repokind = info.type();
-
-        // if the type is unknown, try probing.
-       if ( repokind == RepoType::NONE )
        {
-         // unknown, probe it
-         repokind = probe( *it, info.path() );
-
-         if (repokind.toEnum() != RepoType::NONE_e)
+         repo::RepoType probed = probe( *it, info.path() );
+         if ( repokind != probed )
          {
+           repokind = probed;
            // Adjust the probed type in RepoInfo
            info.setProbedType( repokind ); // lazy init!
            //save probed type only for repos in system
@@ -1188,7 +1200,8 @@ namespace zypp
         // ok we have the metadata, now exchange
         // the contents
        filesystem::exchange( tmpdir.path(), mediarootpath );
-       reposManip();   // remember to trigger appdata refresh
+       if ( ! isTmpRepo( info ) )
+         reposManip(); // remember to trigger appdata refresh
 
         // we are done.
         return;
@@ -1344,7 +1357,7 @@ namespace zypp
 
         if ( repokind == RepoType::RPMPLAINDIR )
         {
-          forPlainDirs.reset( new MediaMounter( *info.baseUrlsBegin() ) );
+          forPlainDirs.reset( new MediaMounter( info.url() ) );
           // recusive for plaindir as 2nd arg!
           cmd.push_back( "-R" );
           // FIXME this does only work form dir: URLs
@@ -1620,16 +1633,13 @@ namespace zypp
     if ( _options.probe )
     {
       DBG << "unknown repository type, probing" << endl;
+      assert_urls(tosave);
 
-      RepoType probedtype;
-      probedtype = probe( *tosave.baseUrlsBegin(), info.path() );
-      if ( tosave.baseUrlsSize() > 0 )
-      {
-        if ( probedtype == RepoType::NONE )
-          ZYPP_THROW(RepoUnknownTypeException(info));
-        else
-          tosave.setType(probedtype);
-      }
+      RepoType probedtype( probe( tosave.url(), info.path() ) );
+      if ( probedtype == RepoType::NONE )
+       ZYPP_THROW(RepoUnknownTypeException(info));
+      else
+       tosave.setType(probedtype);
     }
 
     progress.set(50);
@@ -1651,14 +1661,15 @@ namespace zypp
 
     tosave.dumpAsIniOn(file);
     tosave.setFilepath(repofile);
-    tosave.setMetadataPath( metadataPath( tosave ) );
-    tosave.setPackagesPath( packagesPath( tosave ) );
+    tosave.setMetadataPath( rawcache_path_for_repoinfo( _options, tosave ) );
+    tosave.setPackagesPath( packagescache_path_for_repoinfo( _options, tosave ) );
     {
-      // We chould fix the API as we must injet those paths
+      // We should fix the API as we must inject those paths
       // into the repoinfo in order to keep it usable.
       RepoInfo & oinfo( const_cast<RepoInfo &>(info) );
-      oinfo.setMetadataPath( metadataPath( tosave ) );
-      oinfo.setPackagesPath( packagesPath( tosave ) );
+      oinfo.setFilepath(repofile);
+      oinfo.setMetadataPath( rawcache_path_for_repoinfo( _options, tosave ) );
+      oinfo.setPackagesPath( packagescache_path_for_repoinfo( _options, tosave ) );
     }
     reposManip().insert(tosave);
 
@@ -1719,8 +1730,10 @@ namespace zypp
           ++it )
     {
       MIL << "Saving " << (*it).alias() << endl;
-      it->setFilepath(repofile.asString());
       it->dumpAsIniOn(file);
+      it->setFilepath(repofile);
+      it->setMetadataPath( rawcache_path_for_repoinfo( _options, *it ) );
+      it->setPackagesPath( packagescache_path_for_repoinfo( _options, *it ) );
       reposManip().insert(*it);
 
       HistoryLog(_options.rootDir).addRepository(*it);
@@ -1875,6 +1888,16 @@ namespace zypp
       }
 
       newinfo.setFilepath(toedit.filepath());
+      newinfo.setMetadataPath( rawcache_path_for_repoinfo( _options, newinfo ) );
+      newinfo.setPackagesPath( packagescache_path_for_repoinfo( _options, newinfo ) );
+      {
+       // We should fix the API as we must inject those paths
+       // into the repoinfo in order to keep it usable.
+       RepoInfo & oinfo( const_cast<RepoInfo &>(newinfo_r) );
+       oinfo.setFilepath(toedit.filepath());
+       oinfo.setMetadataPath( rawcache_path_for_repoinfo( _options, newinfo ) );
+       oinfo.setPackagesPath( packagescache_path_for_repoinfo( _options, newinfo ) );
+      }
       reposManip().erase(toedit);
       reposManip().insert(newinfo);
       // check for credentials in Urls