~thopiekar/zypper/libzypp-manual-import

« back to all changes in this revision

Viewing changes to zypp/target/TargetImpl.commitFindFileConflicts.cc

  • Committer: Thomas-Karl Pietrowski
  • Date: 2014-01-29 22:44:28 UTC
  • Revision ID: thopiekar@googlemail.com-20140129224428-gpcqnsdakby362n8
firstĀ import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*---------------------------------------------------------------------\
 
2
|                          ____ _   __ __ ___                          |
 
3
|                         |__  / \ / / . \ . \                         |
 
4
|                           / / \ V /|  _/  _/                         |
 
5
|                          / /__ | | | | | |                           |
 
6
|                         /_____||_| |_| |_|                           |
 
7
|                                                                      |
 
8
\---------------------------------------------------------------------*/
 
9
/** \file zypp/target/TargetImpl.commitFindFileConflicts.cc
 
10
 */
 
11
extern "C"
 
12
{
 
13
#include <solv/pool.h>
 
14
#include <solv/repo.h>
 
15
#include <solv/solvable.h>
 
16
#include <solv/poolarch.h>
 
17
#include <solv/repo_solv.h>
 
18
#include <solv/repo_rpmdb.h>
 
19
#include <solv/pool_fileconflicts.h>
 
20
}
 
21
#include <iostream>
 
22
#include <unordered_set>
 
23
#include <string>
 
24
 
 
25
#include "zypp/base/LogTools.h"
 
26
#include "zypp/base/Gettext.h"
 
27
#include "zypp/base/Exception.h"
 
28
#include "zypp/base/UserRequestException.h"
 
29
 
 
30
#include "zypp/sat/Queue.h"
 
31
#include "zypp/sat/FileConflicts.h"
 
32
#include "zypp/sat/Pool.h"
 
33
 
 
34
#include "zypp/target/TargetImpl.h"
 
35
#include "zypp/target/CommitPackageCache.h"
 
36
 
 
37
#include "zypp/ZYppCallbacks.h"
 
38
 
 
39
using std::endl;
 
40
 
 
41
///////////////////////////////////////////////////////////////////
 
42
namespace zypp
 
43
{
 
44
  ///////////////////////////////////////////////////////////////////
 
45
  namespace target
 
46
  {
 
47
    ///////////////////////////////////////////////////////////////////
 
48
    namespace
 
49
    {
 
50
      /** libsolv::pool_findfileconflicts callback providing package header. */
 
51
      struct FileConflictsCB
 
52
      {
 
53
        FileConflictsCB( ::_Pool * pool_r, ProgressData & progress_r )
 
54
        : _progress( progress_r )
 
55
        , _state( ::rpm_state_create( pool_r, ::pool_get_rootdir(pool_r) ), ::rpm_state_free )
 
56
        {}
 
57
 
 
58
        void * operator()( ::_Pool * pool_r, sat::detail::IdType id_r )
 
59
        {
 
60
          void * ret = lookup( id_r );
 
61
 
 
62
          // report progress on 1st visit only, ticks later
 
63
          // (there may be up to 3 visits)
 
64
          if ( _visited.find( id_r ) == _visited.end() )
 
65
          {
 
66
            //DBG << "FCCB: " << sat::Solvable( id_r ) << " " << ret << endl;
 
67
            _visited.insert( id_r );
 
68
            if ( ! ret )
 
69
              _noFilelist.push( id_r );
 
70
            _progress.incr();
 
71
          }
 
72
          else
 
73
          {
 
74
            _progress.tick();
 
75
          }
 
76
          return ret;
 
77
        }
 
78
 
 
79
        const sat::Queue & noFilelist() const
 
80
        { return _noFilelist; }
 
81
 
 
82
        static void * invoke( ::_Pool * pool_r, sat::detail::IdType id_r, void * cbdata_r )
 
83
        { return (*reinterpret_cast<FileConflictsCB*>(cbdata_r))( pool_r, id_r ); }
 
84
 
 
85
      private:
 
86
        void * lookup( sat::detail::IdType id_r )
 
87
        {
 
88
          sat::Solvable solv( id_r );
 
89
          if ( solv.isSystem() )
 
90
          {
 
91
            Solvable * s = solv.get();
 
92
            if ( ! s->repo->rpmdbid )
 
93
              return nullptr;
 
94
            sat::detail::IdType rpmdbid = s->repo->rpmdbid[id_r - s->repo->start];
 
95
            if ( ! rpmdbid )
 
96
              return nullptr;
 
97
            return ::rpm_byrpmdbid( _state, rpmdbid );
 
98
          }
 
99
          else
 
100
          {
 
101
            Package::Ptr pkg( make<Package>( solv ) );
 
102
            if ( ! pkg )
 
103
              return nullptr;
 
104
            Pathname localfile( pkg->cachedLocation() );
 
105
            if ( localfile.empty() )
 
106
              return nullptr;
 
107
            AutoDispose<FILE*> fp( ::fopen( localfile.c_str(), "re" ), ::fclose );
 
108
            return ::rpm_byfp( _state, fp, localfile.c_str() );
 
109
          }
 
110
        }
 
111
 
 
112
      private:
 
113
        ProgressData & _progress;
 
114
        AutoDispose<void*> _state;
 
115
        std::unordered_set<sat::detail::IdType> _visited;
 
116
        sat::Queue _noFilelist;
 
117
      };
 
118
 
 
119
    } // namespace
 
120
    ///////////////////////////////////////////////////////////////////
 
121
 
 
122
    void TargetImpl::commitFindFileConflicts( const ZYppCommitPolicy & policy_r, ZYppCommitResult & result_r )
 
123
    {
 
124
      sat::Queue todo;
 
125
      sat::FileConflicts conflicts;
 
126
      int newpkgs = result_r.transaction().installedResult( todo );
 
127
      MIL << "Checking for file conflicts in " << newpkgs << " new packages..." << endl;
 
128
      if ( ! newpkgs )
 
129
        return;
 
130
 
 
131
      try {
 
132
        callback::SendReport<FindFileConflictstReport> report;
 
133
        ProgressData progress( todo.size() );
 
134
        if ( ! report->start( progress ) )
 
135
          ZYPP_THROW( AbortRequestException() );
 
136
 
 
137
        FileConflictsCB cb( sat::Pool::instance().get(), progress );
 
138
        // lambda receives progress trigger and translates into report
 
139
        auto sendProgress = [&]( const ProgressData & progress_r )->bool {
 
140
          if ( ! report->progress( progress_r, cb.noFilelist() ) )
 
141
            ZYPP_THROW( AbortRequestException() );
 
142
          return true;
 
143
        };
 
144
        progress.sendTo( sendProgress );
 
145
 
 
146
        unsigned count =
 
147
          ::pool_findfileconflicts( sat::Pool::instance().get(),
 
148
                                    todo,
 
149
                                    newpkgs,
 
150
                                    conflicts,
 
151
                                    FINDFILECONFLICTS_USE_SOLVABLEFILELIST | FINDFILECONFLICTS_CHECK_DIRALIASING | FINDFILECONFLICTS_USE_ROOTDIR,
 
152
                                    &FileConflictsCB::invoke,
 
153
                                    &cb );
 
154
        progress.toMax();
 
155
        progress.noSend();
 
156
 
 
157
        (count?WAR:MIL) << "Found " << count << " file conflicts." << endl;
 
158
        if ( ! report->result( progress, cb.noFilelist(), conflicts ) )
 
159
          ZYPP_THROW( AbortRequestException() );
 
160
      }
 
161
      catch ( const AbortRequestException & e )
 
162
      {
 
163
        TargetAbortedException excpt( N_("Installation has been aborted as directed.") );
 
164
        excpt.remember( e );
 
165
        ZYPP_THROW( excpt );
 
166
      }
 
167
    }
 
168
 
 
169
  } // namespace target
 
170
  ///////////////////////////////////////////////////////////////////
 
171
} // namespace zypp
 
172
///////////////////////////////////////////////////////////////////