add ZYPP_TESTSUITE_FAKE_ARCH to overrride detected architecture.
[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       // detect the true architecture
81       struct utsname buf;
82       if (uname (&buf) < 0) {
83         ERR << "Can't determine system architecture" << endl;
84       }
85       else {
86         _architecture = Arch( buf.machine );
87
88         MIL << "uname architecture is '" << buf.machine << "'" << endl;
89
90         // some CPUs report i686 but dont implement cx8 and cmov
91         // check for both flags in /proc/cpuinfo and downgrade
92         // to i586 if either is missing (cf bug #18885)
93
94         if (_architecture == Arch_i686)
95         {
96             std::ifstream cpuinfo ("/proc/cpuinfo");
97             if (!cpuinfo)
98             {
99                 ERR << "Cant open /proc/cpuinfo" << endl;
100             }
101             else
102             {
103                 char infoline[1024];
104                 while (cpuinfo.good())
105                 {
106                     if (!cpuinfo.getline (infoline, 1024, '\n'))
107                     {
108                         if (cpuinfo.eof())
109                             break;
110                     }
111                     if (strncmp (infoline, "flags", 5) == 0)
112                     {
113                         std::string flagsline (infoline);
114                         if ((flagsline.find( "cx8" ) == std::string::npos)
115                             || (flagsline.find( "cmov" ) == std::string::npos))
116                         {
117                             _architecture = Arch_i586;
118                         }
119                         break;
120                     } // flags found
121                 } // read proc/cpuinfo
122             } // proc/cpuinfo opened
123         } // i686 extra flags check
124
125         MIL << "System architecture is '" << _architecture << "'" << endl;
126       }
127     
128
129       std::string fakearch(getenv("ZYPP_TESTSUITE_FAKE_ARCH"));
130       if ( fakearch.size() > 0 ) 
131       {
132         _architecture = Arch( fakearch );
133         MIL << "ZYPP_TESTSUITE_FAKE_ARCH: Setting fake system architecture for test purpuses (warning! commit will be disabled!) to: '" << _architecture << "'" << endl;
134       }
135     }
136
137     ///////////////////////////////////////////////////////////////////
138     //
139     //  METHOD NAME : ZYppImpl::~ZYppImpl
140     //  METHOD TYPE : Destructor
141     //
142     ZYppImpl::~ZYppImpl()
143     {}
144
145     //------------------------------------------------------------------------
146     // add/remove resolvables
147
148     void ZYppImpl::addResolvables (const ResStore& store, bool installed)
149     {
150         _pool.insert(store.begin(), store.end(), installed);
151     }
152
153     void ZYppImpl::removeResolvables (const ResStore& store)
154     {
155         for (ResStore::iterator it = store.begin(); it != store.end(); ++it)
156         {
157             _pool.erase(*it);
158         }
159     }
160
161     void ZYppImpl::removeInstalledResolvables ()
162     {
163         for (ResPool::const_iterator it = pool().begin(); it != pool().end();)
164         {
165             ResPool::const_iterator next = it; ++next;
166             if (it->status().isInstalled())
167                 _pool.erase( *it );
168             it = next;
169         }
170     }
171
172     DiskUsageCounter::MountPointSet ZYppImpl::diskUsage()
173     { return _disk_usage.disk_usage(pool()); }
174
175     void ZYppImpl::setPartitions(const DiskUsageCounter::MountPointSet &mp)
176     { _disk_usage.setMountPoints(mp); }
177
178     //------------------------------------------------------------------------
179     // target
180
181     Target_Ptr ZYppImpl::target() const
182     {
183       if (! _target)
184         ZYPP_THROW(Exception("Target not initialized."));
185       return _target;
186      }
187
188     void ZYppImpl::initTarget(const Pathname & root, bool commit_only)
189     {
190       MIL << "initTarget( " << root << ", " << commit_only << ")" << endl;
191       if (_target) {
192         if (_target->root() == root) {
193             MIL << "Repeated call to initTarget()" << endl;
194             return;
195         }
196         removeInstalledResolvables( );
197       }
198       _target = new Target( root );
199       if (!commit_only)
200       {
201         _target->enableStorage( root );
202         addResolvables( _target->resolvables(), true );
203       }
204     }
205
206     void ZYppImpl::finishTarget()
207     {
208       if (_target)
209         removeInstalledResolvables();
210       _target = 0;
211     }
212
213     //------------------------------------------------------------------------
214     // commit
215
216     /** \todo Remove workflow from target, lot's of it could be done here,
217      * and target used for transact. */
218     ZYppCommitResult ZYppImpl::commit( const ZYppCommitPolicy & policy_r )
219     {
220       if ( getenv("ZYPP_TESTSUITE_FAKE_ARCH") )
221       {
222         ZYPP_THROW( Exception("ZYPP_TESTSUITE_FAKE_ARCH set. Commit not allowed and disabled.") );
223       }
224         
225       MIL << "Attempt to commit (" << policy_r << ")" << endl;
226       if (! _target)
227         ZYPP_THROW( Exception("Target not initialized.") );
228
229       ZYppCommitResult res = _target->_pimpl->commit( pool(), policy_r );
230
231       if (! policy_r.dryRun() ) {
232         // reload new status from target
233         removeInstalledResolvables();
234         addResolvables( _target->resolvables(), true );
235       }
236
237       MIL << "Commit (" << policy_r << ") returned: "
238           << res << endl;
239       return res;
240     }
241
242
243     //------------------------------------------------------------------------
244     // locales
245
246     /** */
247     void ZYppImpl::setRequestedLocales( const LocaleSet & locales_r )
248     {
249       ResPool mpool( pool() );
250       // assert all requested are available
251       for ( LocaleSet::const_iterator it = locales_r.begin();
252             it != locales_r.end(); ++it )
253         {
254           NameKindProxy select( nameKindProxy<Language>( mpool, it->code() ) );
255           if ( select.installedEmpty() && select.availableEmpty() )
256             _pool.insert( Language::availableInstance( *it ) );
257         }
258
259       // now adjust status
260       for ( ResPool::byKind_iterator it = mpool.byKindBegin<Language>();
261             it != mpool.byKindEnd<Language>(); ++it )
262         {
263           NameKindProxy select( nameKindProxy<Language>( mpool, (*it)->name() ) );
264           if ( locales_r.find( Locale( (*it)->name() ) ) != locales_r.end() )
265             {
266               // Language is requested
267               if ( select.installedEmpty() )
268                 {
269                   if ( select.availableEmpty() )
270                     {
271                       // no item ==> provide available to install
272                       _pool.insert( Language::availableInstance( Locale((*it)->name()) ) );
273                       select = nameKindProxy<Language>( mpool, (*it)->name() );
274                     }
275                   // available only ==> to install
276                   select.availableBegin()->status().setTransactValue( ResStatus::TRANSACT, ResStatus::USER );
277                 }
278               else
279                 {
280                   // installed ==> keep it
281                   select.installedBegin()->status().setTransactValue( ResStatus::KEEP_STATE, ResStatus::USER );
282                   if ( ! select.availableEmpty() )
283                     {
284                       // both items ==> keep
285                       select.availableBegin()->status().resetTransact( ResStatus::USER );
286                     }
287                 }
288             }
289           else
290             {
291               // Language is NOT requested
292               if ( ! select.installedEmpty() )
293                 select.installedBegin()->status().setTransactValue( ResStatus::TRANSACT, ResStatus::USER );
294               if ( ! select.availableEmpty() )
295                 select.availableBegin()->status().resetTransact( ResStatus::USER );
296             }
297         }
298     }
299
300     /** */
301     ZYppImpl::LocaleSet ZYppImpl::getAvailableLocales() const
302     {
303       ZYpp::LocaleSet ret;
304       ResPool mpool( pool() );
305       for ( ResPool::byKind_iterator it = mpool.byKindBegin<Language>();
306             it != mpool.byKindEnd<Language>(); ++it )
307         {
308           if ( (*it).status().isUninstalled() ) // available!
309             ret.insert( Locale( (*it)->name() ) );
310         }
311       return ret;
312     }
313
314     /** */
315     ZYppImpl::LocaleSet ZYppImpl::getRequestedLocales() const
316     {
317       ZYpp::LocaleSet ret;
318       ResPool mpool( pool() );
319       for ( ResPool::byKind_iterator it = mpool.byKindBegin<Language>();
320             it != mpool.byKindEnd<Language>(); ++it )
321         {
322           NameKindProxy select( nameKindProxy<Language>( mpool, (*it)->name() ) );
323           if ( ! select.installedEmpty()
324                && select.installedBegin()->status().getTransactValue() != ResStatus::TRANSACT )
325             ret.insert( Locale( (*it)->name() ) );
326           else if ( ! select.availableEmpty()
327                     && select.availableBegin()->status().getTransactValue() == ResStatus::TRANSACT )
328             ret.insert( Locale( (*it)->name() ) );
329         }
330       return ret;
331     }
332
333     void ZYppImpl::availableLocale( const Locale & locale_r )
334     {
335       _pool.insert( Language::availableInstance( locale_r ) );
336     }
337
338     //------------------------------------------------------------------------
339     // architecture
340
341     void ZYppImpl::setArchitecture( const Arch & arch )
342     {
343         _architecture = arch;
344         if (_resolver) _resolver->setArchitecture( arch );
345     }
346
347     //------------------------------------------------------------------------
348     // target store path
349
350     Pathname ZYppImpl::homePath() const
351     { return _home_path.empty() ? Pathname("/var/lib/zypp") : _home_path; }
352
353     void ZYppImpl::setHomePath( const Pathname & path )
354     { _home_path = path; }
355
356     /******************************************************************
357      **
358      ** FUNCTION NAME : operator<<
359      ** FUNCTION TYPE : std::ostream &
360     */
361     std::ostream & operator<<( std::ostream & str, const ZYppImpl & obj )
362     {
363       return str << "ZYppImpl";
364     }
365
366     /////////////////////////////////////////////////////////////////
367   } // namespace zypp_detail
368   ///////////////////////////////////////////////////////////////////
369   /////////////////////////////////////////////////////////////////
370 } // namespace zypp
371 ///////////////////////////////////////////////////////////////////