summaryrefslogtreecommitdiff
path: root/src/package.cpp
blob: 8b3779a14a2874c231872c01e86bcb23a0c3853d (plain)
    1 ////////////////////////////////////////////////////////////////////////
    2 // FILE:        package.cpp
    3 // AUTHOR:      Johannes Winkelmann, jw@tks6.net
    4 // COPYRIGHT:   (c) 2002 by Johannes Winkelmann
    5 // ---------------------------------------------------------------------
    6 //  This program is free software; you can redistribute it and/or modify
    7 //  it under the terms of the GNU General Public License as published by
    8 //  the Free Software Foundation; either version 2 of the License, or
    9 //  (at your option) any later version.
   10 ////////////////////////////////////////////////////////////////////////
   11 
   12 
   13 #include <iostream>
   14 #include <cstdio>
   15 #include <sys/stat.h>
   16 #include <sys/utsname.h>
   17 using namespace std;
   18 
   19 #include "package.h"
   20 #include "stringhelper.h"
   21 using namespace StringHelper;
   22 
   23 
   24 
   25 /*!
   26   Create a package, which is not yet fully initialized, This is interesting
   27   in combination with the lazy initialization
   28 */
   29 Package::Package( const string& name,
   30                   const string& path )
   31     : m_loaded( false )
   32 {
   33     m_data = new PackageData( name, path );
   34 }
   35 
   36 /*!
   37   Create a fully initialized package. Most interesting when created from a
   38   cache file
   39 */
   40 Package::Package( const string& name,
   41                   const string& path,
   42                   const string& version,
   43                   const string& release,
   44                   const string& description,
   45                   const string& dependencies,
   46                   const string& url,
   47                   const string& packager,
   48                   const string& maintainer,
   49                   const string& hasReadme,
   50                   const string& hasPreInstall,
   51                   const string& hasPostInstall)
   52     : m_loaded( true )
   53 {
   54     m_data = new PackageData( name, path, version, release,
   55                               description, dependencies, url,
   56                               packager, maintainer, hasReadme,
   57                               hasPreInstall, hasPostInstall );
   58 
   59 }
   60 
   61 Package::~Package()
   62 {
   63     delete m_data;
   64 }
   65 
   66 /*! \return the name of this package */
   67 const string& Package::name() const
   68 {
   69     return m_data->name;
   70 }
   71 
   72 /*! \return the path to this package */
   73 const string& Package::path() const
   74 {
   75     return m_data->path;
   76 }
   77 
   78 /*! \return the version of this package */
   79 const string& Package::version() const
   80 {
   81     load();
   82     return m_data->version;
   83 }
   84 
   85 /*! \return the release number of this package */
   86 const string& Package::release() const
   87 {
   88     load();
   89     return m_data->release;
   90 }
   91 
   92 /*! \return the description field of this package */
   93 const string& Package::description() const
   94 {
   95     load();
   96     return m_data->description;
   97 }
   98 
   99 /*! \return the dependency line of this package */
  100 const string& Package::dependencies() const
  101 {
  102     load();
  103     return m_data->depends;
  104 }
  105 
  106 /*! \return the url of this package */
  107 const string& Package::url() const
  108 {
  109     load();
  110     return m_data->url;
  111 }
  112 
  113 /*! \return the packager of this package */
  114 const string& Package::packager() const
  115 {
  116     load();
  117     return m_data->packager;
  118 }
  119 /*! \return the maintainer of this package */
  120 const string& Package::maintainer() const
  121 {
  122     load();
  123     return m_data->maintainer;
  124 }
  125 
  126 /*! \return whether or not this package has a readme file */
  127 const bool Package::hasReadme() const
  128 {
  129     load();
  130     return m_data->hasReadme;
  131 }
  132 
  133 /*! \return a typically formatted version-release string */
  134 string Package::versionReleaseString() const
  135 {
  136     load();
  137     return m_data->versionReleaseString;
  138 }
  139 
  140 const bool Package::hasPreInstall() const
  141 {
  142     return m_data->hasPreInstall;
  143 }
  144 
  145 const bool Package::hasPostInstall() const
  146 {
  147     return m_data->hasPostInstall;
  148 }
  149 
  150 /*!
  151   load from Pkgfile
  152 */
  153 void Package::load() const
  154 {
  155     if ( m_loaded ) {
  156         return;
  157     }
  158     m_loaded = true;
  159 
  160     string fileName = m_data->path + "/" + m_data->name + "/Pkgfile";
  161 
  162     // c IO is about four times faster then fstream :-(
  163     FILE* fp = fopen( fileName.c_str(), "r" );
  164     if ( fp == NULL ) {
  165         return;
  166     }
  167 
  168 
  169     const int length = BUFSIZ;
  170     char input[length];
  171     string line;
  172 
  173     time_t timeNow;
  174     time(&timeNow);
  175 
  176     struct utsname unameBuf;
  177     if (uname(&unameBuf) != 0) {
  178         unameBuf.release[0] = '\0';
  179     }
  180 
  181 
  182 
  183     while ( fgets( input, length, fp ) ) {
  184 
  185         line = stripWhiteSpace( input );
  186 
  187         if ( line.substr( 0, 8 ) == "version=" ) {
  188             m_data->version = getValueBefore( getValue( line, '=' ), '#' );
  189             m_data->version = stripWhiteSpace( m_data->version );
  190 
  191             expandShellCommands(m_data->version, timeNow, unameBuf);
  192         } else if ( line.substr( 0, 8 ) == "release=" ) {
  193             m_data->release = getValueBefore( getValue( line, '=' ), '#' );
  194             m_data->release = stripWhiteSpace( m_data->release );
  195         } else if ( line[0] == '#' ) {
  196             while ( !line.empty() &&
  197                     ( line[0] == '#' || line[0] == ' ' || line[0] == '\t' ) ) {
  198                 line = line.substr( 1 );
  199             }
  200             string::size_type pos = line.find( ':' );
  201             if ( pos != string::npos ) {
  202                 if ( startsWithNoCase( line, "desc" ) ) {
  203                     m_data->description =
  204                         stripWhiteSpace( getValue( line, ':' ) );
  205 
  206                 } else if ( startsWithNoCase( line, "pack" ) ) {
  207                     m_data->packager =
  208                         stripWhiteSpace( getValue( line, ':' ) );
  209                 } else if ( startsWithNoCase( line, "maint" ) ) {
  210                     m_data->maintainer =
  211                         stripWhiteSpace( getValue( line, ':' ) );
  212                 } else if ( startsWithNoCase( line, "url" ) ) {
  213                     m_data->url = stripWhiteSpace( getValue( line, ':' ) );
  214                 } else if ( startsWithNoCase( line, "dep" ) ) {
  215                     string depends = stripWhiteSpace( getValue( line, ':' ) );
  216 
  217                     StringHelper::replaceAll( depends, " ", "," );
  218                     StringHelper::replaceAll( depends, ",,", "," );
  219 
  220                     // TODO: decide which one to use
  221 #if 0
  222                     // remove commented out packages
  223                     list<string> deps = StringHelper::split( depends, ',' );
  224                     list<string>::iterator it = deps.begin();
  225                     for ( ; it != deps.end(); ++it ) {
  226                         if ( (*it)[0] == '#' ) {
  227                             cerr << "Commented dep: " << *it << endl;
  228                         } else {
  229                             if ( it != deps.begin() ) {
  230                                 m_data->depends += ",";
  231                             }
  232                             m_data->depends += *it;
  233                         }
  234                     }
  235 #else
  236                     m_data->depends = depends;
  237 #endif
  238 
  239                 }
  240             }
  241         }
  242     }
  243     fclose( fp );
  244 
  245     m_data->generateVersionReleaseString();
  246 
  247     string file = m_data->path + "/" + m_data->name + "/README";
  248     struct stat buf;
  249     if ( stat( file.c_str(), &buf ) != -1) {
  250         m_data->hasReadme = true;
  251     }
  252     file = m_data->path + "/" + m_data->name + "/pre-install";
  253     if ( stat( file.c_str(), &buf ) != -1) {
  254         m_data->hasPreInstall = true;
  255     }
  256     file = m_data->path + "/" + m_data->name + "/post-install";
  257     if ( stat( file.c_str(), &buf ) != -1) {
  258         m_data->hasPostInstall = true;
  259     }
  260 
  261 }
  262 
  263 void Package::setDependencies( const std::string& dependencies )
  264 {
  265     m_data->depends = dependencies;
  266 }
  267 
  268 
  269 
  270 PackageData::PackageData( const string& name_,
  271                           const string& path_,
  272                           const string& version_,
  273                           const string& release_,
  274                           const string& description_,
  275                           const string& dependencies_,
  276                           const string& url_,
  277                           const string& packager_,
  278                           const string& maintainer_,
  279                           const string& hasReadme_,
  280                           const string& hasPreInstall_,
  281                           const string& hasPostInstall_ )
  282     : name( name_ ),
  283       path( path_ ),
  284       version( version_ ),
  285       release( release_ ),
  286       description( description_ ),
  287       depends( dependencies_ ),
  288       url( url_ ),
  289       packager( packager_ ),
  290       maintainer( maintainer_ )
  291 
  292 {
  293     generateVersionReleaseString();
  294 
  295     hasReadme = ( stripWhiteSpace( hasReadme_ ) == "yes" );
  296     hasPreInstall = ( stripWhiteSpace( hasPreInstall_ ) == "yes" );
  297     hasPostInstall = ( stripWhiteSpace( hasPostInstall_ ) == "yes" );
  298 }
  299 
  300 void PackageData::generateVersionReleaseString()
  301 {
  302     versionReleaseString = version + "-" + release;
  303 }
  304 
  305 
  306 void Package::expandShellCommands(std::string& input,
  307                                   const time_t& timeNow,
  308                                   const struct utsname unameBuf)
  309 {
  310     // TODO: consider dropping either of the tagsets, depending on feedback
  311 
  312     static const int TAG_COUNT = 2;
  313     string startTag[TAG_COUNT] = { "`", "$(" };
  314     string endTag[TAG_COUNT] = { "`", ")" };
  315 
  316     for (int i = 0; i < TAG_COUNT; ++i) {
  317         string::size_type pos, dpos = 0;
  318         
  319         int len;
  320         pos = 0;
  321         while ((pos = input.find(startTag[i], pos)) != string::npos) {
  322             len = input.length();
  323             
  324             if (unameBuf.release) {
  325                 input = replaceAll(input,
  326                                    startTag[i] + "uname -r" + endTag[i],
  327                                    unameBuf.release);
  328             }
  329 
  330             dpos = input.find(startTag[i] + "date");
  331             if (dpos != string::npos) {
  332                 // NOTE: currently only works for one date pattern
  333                 string::size_type startpos, endpos;
  334                 endpos = input.find(endTag[i], dpos+1);
  335                 startpos = input.find('+', dpos+1);
  336 
  337                 string format = input.substr(startpos+1, endpos-startpos-1);
  338 
  339                 // support date '+...' and date "+..."
  340                 int len = format.length();
  341                 if (format[len-1] == '\'' || format[len-1] == '"') {
  342                     format = format.substr(0, len-1);
  343                 }
  344                 char timeBuf[32];
  345                 strftime(timeBuf, 32, format.c_str(), localtime(&timeNow));
  346 
  347                 input = input.substr(0, dpos) + timeBuf +
  348                     input.substr(endpos+1);
  349             }
  350             
  351             ++pos;
  352         }
  353     }
  354 }

Generated by cgit