- fixed missplaced Logger.h includes
[platform/upstream/libzypp.git] / zypp / zypp_detail / ZYppImpl.cc
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/zypp_detail/ZYppImpl.cc
10  *
11 */
12
13 #include <sys/utsname.h>
14 #include <iostream>
15 #include <fstream>
16 #include "zypp/base/Logger.h"
17
18 #include "zypp/zypp_detail/ZYppImpl.h"
19 #include "zypp/detail/ResImplTraits.h"
20 #include "zypp/solver/detail/Helper.h"
21 #include "zypp/target/TargetImpl.h"
22 #include "zypp/ZYpp.h"
23 #include "zypp/NVRAD.h"
24 #include "zypp/Language.h"
25 #include "zypp/DiskUsageCounter.h"
26 #include "zypp/NameKindProxy.h"
27
28 using std::endl;
29
30 ///////////////////////////////////////////////////////////////////
31 namespace zypp
32 { /////////////////////////////////////////////////////////////////
33   ///////////////////////////////////////////////////////////////////
34   namespace zypp_detail
35   { /////////////////////////////////////////////////////////////////
36
37     inline Locale defaultTextLocale()
38     {
39       Locale ret( "en" );
40       char * envlist[] = { "LC_ALL", "LC_CTYPE", "LANG", NULL };
41       for ( char ** envvar = envlist; *envvar; ++envvar )
42         {
43           char * envlang = getenv( *envvar );
44           if ( envlang )
45             {
46               std::string envstr( envlang );
47               if ( envstr != "POSIX" && envstr != "C" )
48                 {
49                   Locale lang( envlang );
50                   if ( lang != Locale::noCode )
51                     {
52                       ret = lang;
53                       break;
54                     }
55                 }
56             }
57         }
58       return ret;
59     }
60
61     ///////////////////////////////////////////////////////////////////
62     //
63     //  METHOD NAME : ZYppImpl::ZYppImpl
64     //  METHOD TYPE : Constructor
65     //
66     ZYppImpl::ZYppImpl()
67     : _textLocale( defaultTextLocale() )
68     , _pool()
69     , _sourceFeed( _pool )
70     , _target(0)
71     , _resolver( new Resolver(_pool.accessor()) )
72     , _disk_usage()
73     {
74       MIL << "defaultTextLocale: '" << _textLocale << "'" << endl;
75
76       MIL << "initializing keyring..." << std::endl;
77       //_keyring = new KeyRing(homePath() + Pathname("/keyring/all"), homePath() + Pathname("/keyring/trusted"));
78       _keyring = new KeyRing();
79
80       struct utsname buf;
81       if (uname (&buf) < 0) {
82         ERR << "Can't determine system architecture" << endl;
83       }
84       else {
85         _architecture = Arch( buf.machine );
86
87         MIL << "uname architecture is '" << buf.machine << "'" << endl;
88
89         // some CPUs report i686 but dont implement cx8 and cmov
90         // check for both flags in /proc/cpuinfo and downgrade
91         // to i586 if either is missing (cf bug #18885)
92
93         if (_architecture == Arch_i686)
94         {
95             std::ifstream cpuinfo ("/proc/cpuinfo");
96             if (!cpuinfo)
97             {
98                 ERR << "Cant open /proc/cpuinfo" << endl;
99             }
100             else
101             {
102                 char infoline[1024];
103                 while (cpuinfo.good())
104                 {
105                     if (!cpuinfo.getline (infoline, 1024, '\n'))
106                     {
107                         if (cpuinfo.eof())
108                             break;
109                     }
110                     if (strncmp (infoline, "flags", 5) == 0)
111                     {
112                         std::string flagsline (infoline);
113                         if ((flagsline.find( "cx8" ) == std::string::npos)
114                             || (flagsline.find( "cmov" ) == std::string::npos))
115                         {
116                             _architecture = Arch_i586;
117                         }
118                         break;
119                     } // flags found
120                 } // read proc/cpuinfo
121             } // proc/cpuinfo opened
122         } // i686 extra flags check
123
124         MIL << "System architecture is '" << _architecture << "'" << endl;
125       }
126
127     }
128
129     ///////////////////////////////////////////////////////////////////
130     //
131     //  METHOD NAME : ZYppImpl::~ZYppImpl
132     //  METHOD TYPE : Destructor
133     //
134     ZYppImpl::~ZYppImpl()
135     {}
136
137     //------------------------------------------------------------------------
138     // add/remove resolvables
139
140     void ZYppImpl::addResolvables (const ResStore& store, bool installed)
141     {
142         _pool.insert(store.begin(), store.end(), installed);
143     }
144
145     void ZYppImpl::removeResolvables (const ResStore& store)
146     {
147         for (ResStore::iterator it = store.begin(); it != store.end(); ++it)
148         {
149             _pool.erase(*it);
150         }
151     }
152
153     void ZYppImpl::removeInstalledResolvables ()
154     {
155         for (ResPool::const_iterator it = pool().begin(); it != pool().end();)
156         {
157             ResPool::const_iterator next = it; ++next;
158             if (it->status().isInstalled())
159                 _pool.erase( *it );
160             it = next;
161         }
162     }
163
164     DiskUsageCounter::MountPointSet ZYppImpl::diskUsage()
165     { return _disk_usage.disk_usage(pool()); }
166
167     void ZYppImpl::setPartitions(const DiskUsageCounter::MountPointSet &mp)
168     { _disk_usage.setMountPoints(mp); }
169
170     //------------------------------------------------------------------------
171     // target
172
173     Target_Ptr ZYppImpl::target() const
174     {
175       if (! _target)
176         ZYPP_THROW(Exception("Target not initialized."));
177       return _target;
178      }
179
180     void ZYppImpl::initTarget(const Pathname & root, bool commit_only)
181     {
182       MIL << "initTarget( " << root << ", " << commit_only << ")" << endl;
183       if (_target) {
184         if (_target->root() == root) {
185             MIL << "Repeated call to initTarget()" << endl;
186             return;
187         }
188         removeInstalledResolvables( );
189       }
190       _target = new Target( root );
191       if (!commit_only)
192       {
193         _target->enableStorage( root );
194         addResolvables( _target->resolvables(), true );
195       }
196     }
197
198     void ZYppImpl::finishTarget()
199     {
200       if (_target)
201         removeInstalledResolvables();
202       _target = 0;
203     }
204
205     //------------------------------------------------------------------------
206     // commit
207
208     /** \todo Remove workflow from target, lot's of it could be done here,
209      * and target used for transact. */
210     ZYppCommitResult ZYppImpl::commit( const ZYppCommitPolicy & policy_r )
211     {
212       MIL << "Attempt to commit (" << policy_r << ")" << endl;
213       if (! _target)
214         ZYPP_THROW( Exception("Target not initialized.") );
215
216       ZYppCommitResult res = _target->_pimpl->commit( pool(), policy_r );
217
218       if (! policy_r.dryRun() ) {
219         // reload new status from target
220         removeInstalledResolvables();
221         addResolvables( _target->resolvables(), true );
222       }
223
224       MIL << "Commit (" << policy_r << ") returned: "
225           << res << endl;
226       return res;
227     }
228
229
230     //------------------------------------------------------------------------
231     // locales
232
233     /** */
234     void ZYppImpl::setRequestedLocales( const LocaleSet & locales_r )
235     {
236       ResPool mpool( pool() );
237       // assert all requested are available
238       for ( LocaleSet::const_iterator it = locales_r.begin();
239             it != locales_r.end(); ++it )
240         {
241           NameKindProxy select( nameKindProxy<Language>( mpool, it->code() ) );
242           if ( select.installedEmpty() && select.availableEmpty() )
243             _pool.insert( Language::availableInstance( *it ) );
244         }
245
246       // now adjust status
247       for ( ResPool::byKind_iterator it = mpool.byKindBegin<Language>();
248             it != mpool.byKindEnd<Language>(); ++it )
249         {
250           NameKindProxy select( nameKindProxy<Language>( mpool, (*it)->name() ) );
251           if ( locales_r.find( Locale( (*it)->name() ) ) != locales_r.end() )
252             {
253               // Language is requested
254               if ( select.installedEmpty() )
255                 {
256                   if ( select.availableEmpty() )
257                     {
258                       // no item ==> provide available to install
259                       _pool.insert( Language::availableInstance( Locale((*it)->name()) ) );
260                       select = nameKindProxy<Language>( mpool, (*it)->name() );
261                     }
262                   // available only ==> to install
263                   select.availableBegin()->status().setTransactValue( ResStatus::TRANSACT, ResStatus::USER );
264                 }
265               else
266                 {
267                   // installed ==> keep it
268                   select.installedBegin()->status().setTransactValue( ResStatus::KEEP_STATE, ResStatus::USER );
269                   if ( ! select.availableEmpty() )
270                     {
271                       // both items ==> keep
272                       select.availableBegin()->status().setTransactValue( ResStatus::KEEP_STATE, ResStatus::USER );
273                     }
274                 }
275             }
276           else
277             {
278               // Language is NOT requested
279               if ( ! select.installedEmpty() )
280                 select.installedBegin()->status().setTransactValue( ResStatus::TRANSACT, ResStatus::USER );
281               if ( ! select.availableEmpty() )
282                 select.availableBegin()->status().setTransactValue( ResStatus::KEEP_STATE, ResStatus::USER );
283             }
284         }
285     }
286
287     /** */
288     ZYppImpl::LocaleSet ZYppImpl::getAvailableLocales() const
289     {
290       ZYpp::LocaleSet ret;
291       ResPool mpool( pool() );
292       for ( ResPool::byKind_iterator it = mpool.byKindBegin<Language>();
293             it != mpool.byKindEnd<Language>(); ++it )
294         {
295           if ( (*it).status().isUninstalled() ) // available!
296             ret.insert( Locale( (*it)->name() ) );
297         }
298       return ret;
299     }
300
301     /** */
302     ZYppImpl::LocaleSet ZYppImpl::getRequestedLocales() const
303     {
304       ZYpp::LocaleSet ret;
305       ResPool mpool( pool() );
306       for ( ResPool::byKind_iterator it = mpool.byKindBegin<Language>();
307             it != mpool.byKindEnd<Language>(); ++it )
308         {
309           NameKindProxy select( nameKindProxy<Language>( mpool, (*it)->name() ) );
310           if ( ! select.installedEmpty()
311                && select.installedBegin()->status().getTransactValue() != ResStatus::TRANSACT )
312             ret.insert( Locale( (*it)->name() ) );
313           else if ( ! select.availableEmpty()
314                     && select.availableBegin()->status().getTransactValue() == ResStatus::TRANSACT )
315             ret.insert( Locale( (*it)->name() ) );
316         }
317       return ret;
318     }
319
320     void ZYppImpl::availableLocale( const Locale & locale_r )
321     {
322       _pool.insert( Language::availableInstance( locale_r ) );
323     }
324
325     //------------------------------------------------------------------------
326     // architecture
327
328     void ZYppImpl::setArchitecture( const Arch & arch )
329     {
330         _architecture = arch;
331         if (_resolver) _resolver->setArchitecture( arch );
332     }
333
334     //------------------------------------------------------------------------
335     // target store path
336
337     Pathname ZYppImpl::homePath() const
338     { return _home_path.empty() ? Pathname("/var/lib/zypp") : _home_path; }
339
340     void ZYppImpl::setHomePath( const Pathname & path )
341     { _home_path = path; }
342
343     /******************************************************************
344      **
345      ** FUNCTION NAME : operator<<
346      ** FUNCTION TYPE : std::ostream &
347     */
348     std::ostream & operator<<( std::ostream & str, const ZYppImpl & obj )
349     {
350       return str << "ZYppImpl";
351     }
352
353     /////////////////////////////////////////////////////////////////
354   } // namespace zypp_detail
355   ///////////////////////////////////////////////////////////////////
356   /////////////////////////////////////////////////////////////////
357 } // namespace zypp
358 ///////////////////////////////////////////////////////////////////