2005-11-09 16:43:05 -05:00
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
// FILE: package.cpp
|
|
|
|
// AUTHOR: Johannes Winkelmann, jw@tks6.net
|
|
|
|
// COPYRIGHT: (c) 2002 by Johannes Winkelmann
|
|
|
|
// ---------------------------------------------------------------------
|
|
|
|
// This program is free software; you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU General Public License as published by
|
|
|
|
// the Free Software Foundation; either version 2 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
#include <iostream>
|
|
|
|
#include <cstdio>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/utsname.h>
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
#include "package.h"
|
|
|
|
#include "stringhelper.h"
|
|
|
|
using namespace StringHelper;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Create a package, which is not yet fully initialized, This is interesting
|
|
|
|
in combination with the lazy initialization
|
|
|
|
*/
|
|
|
|
Package::Package( const string& name,
|
|
|
|
const string& path )
|
|
|
|
: m_loaded( false )
|
|
|
|
{
|
|
|
|
m_data = new PackageData( name, path );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Create a fully initialized package. Most interesting when created from a
|
|
|
|
cache file
|
|
|
|
*/
|
|
|
|
Package::Package( const string& name,
|
|
|
|
const string& path,
|
|
|
|
const string& version,
|
|
|
|
const string& release,
|
|
|
|
const string& description,
|
|
|
|
const string& dependencies,
|
|
|
|
const string& url,
|
2023-03-10 10:03:11 -05:00
|
|
|
const string& optionals,
|
2005-11-09 16:43:05 -05:00
|
|
|
const string& maintainer,
|
|
|
|
const string& hasReadme,
|
|
|
|
const string& hasPreInstall,
|
|
|
|
const string& hasPostInstall)
|
|
|
|
: m_loaded( true )
|
|
|
|
{
|
|
|
|
m_data = new PackageData( name, path, version, release,
|
|
|
|
description, dependencies, url,
|
2023-03-10 10:03:11 -05:00
|
|
|
optionals, maintainer, hasReadme,
|
2005-11-09 16:43:05 -05:00
|
|
|
hasPreInstall, hasPostInstall );
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Package::~Package()
|
|
|
|
{
|
|
|
|
delete m_data;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! \return the name of this package */
|
|
|
|
const string& Package::name() const
|
|
|
|
{
|
|
|
|
return m_data->name;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! \return the path to this package */
|
|
|
|
const string& Package::path() const
|
|
|
|
{
|
|
|
|
return m_data->path;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! \return the version of this package */
|
|
|
|
const string& Package::version() const
|
|
|
|
{
|
|
|
|
load();
|
|
|
|
return m_data->version;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! \return the release number of this package */
|
|
|
|
const string& Package::release() const
|
|
|
|
{
|
|
|
|
load();
|
|
|
|
return m_data->release;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! \return the description field of this package */
|
|
|
|
const string& Package::description() const
|
|
|
|
{
|
|
|
|
load();
|
|
|
|
return m_data->description;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! \return the dependency line of this package */
|
|
|
|
const string& Package::dependencies() const
|
|
|
|
{
|
|
|
|
load();
|
|
|
|
return m_data->depends;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! \return the url of this package */
|
|
|
|
const string& Package::url() const
|
|
|
|
{
|
|
|
|
load();
|
|
|
|
return m_data->url;
|
|
|
|
}
|
|
|
|
|
2023-03-10 10:03:11 -05:00
|
|
|
/*! \return the optional dependencies of this package */
|
|
|
|
const string& Package::optionals() const
|
2005-11-09 16:43:05 -05:00
|
|
|
{
|
|
|
|
load();
|
2023-03-10 10:03:11 -05:00
|
|
|
return m_data->optionals;
|
2005-11-09 16:43:05 -05:00
|
|
|
}
|
|
|
|
/*! \return the maintainer of this package */
|
|
|
|
const string& Package::maintainer() const
|
|
|
|
{
|
|
|
|
load();
|
|
|
|
return m_data->maintainer;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! \return whether or not this package has a readme file */
|
2023-06-19 14:44:03 -04:00
|
|
|
bool Package::hasReadme() const
|
2005-11-09 16:43:05 -05:00
|
|
|
{
|
|
|
|
load();
|
|
|
|
return m_data->hasReadme;
|
|
|
|
}
|
|
|
|
|
2006-09-03 12:12:55 -04:00
|
|
|
/*! \return a typically formatted version-release string */
|
|
|
|
string Package::versionReleaseString() const
|
|
|
|
{
|
|
|
|
load();
|
|
|
|
return m_data->versionReleaseString;
|
|
|
|
}
|
|
|
|
|
2023-06-19 14:44:03 -04:00
|
|
|
bool Package::hasPreInstall() const
|
2005-11-09 16:43:05 -05:00
|
|
|
{
|
|
|
|
return m_data->hasPreInstall;
|
|
|
|
}
|
|
|
|
|
2023-06-19 14:44:03 -04:00
|
|
|
bool Package::hasPostInstall() const
|
2005-11-09 16:43:05 -05:00
|
|
|
{
|
|
|
|
return m_data->hasPostInstall;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
load from Pkgfile
|
|
|
|
*/
|
|
|
|
void Package::load() const
|
|
|
|
{
|
|
|
|
if ( m_loaded ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
m_loaded = true;
|
|
|
|
|
|
|
|
string fileName = m_data->path + "/" + m_data->name + "/Pkgfile";
|
|
|
|
|
|
|
|
// c IO is about four times faster then fstream :-(
|
|
|
|
FILE* fp = fopen( fileName.c_str(), "r" );
|
|
|
|
if ( fp == NULL ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const int length = BUFSIZ;
|
|
|
|
char input[length];
|
|
|
|
string line;
|
2006-09-03 12:12:55 -04:00
|
|
|
|
2005-11-09 16:43:05 -05:00
|
|
|
time_t timeNow;
|
|
|
|
time(&timeNow);
|
2006-09-03 12:12:55 -04:00
|
|
|
|
2005-11-09 16:43:05 -05:00
|
|
|
struct utsname unameBuf;
|
|
|
|
if (uname(&unameBuf) != 0) {
|
|
|
|
unameBuf.release[0] = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while ( fgets( input, length, fp ) ) {
|
|
|
|
|
|
|
|
line = stripWhiteSpace( input );
|
|
|
|
|
|
|
|
if ( line.substr( 0, 8 ) == "version=" ) {
|
|
|
|
m_data->version = getValueBefore( getValue( line, '=' ), '#' );
|
|
|
|
m_data->version = stripWhiteSpace( m_data->version );
|
|
|
|
|
|
|
|
expandShellCommands(m_data->version, timeNow, unameBuf);
|
|
|
|
} else if ( line.substr( 0, 8 ) == "release=" ) {
|
|
|
|
m_data->release = getValueBefore( getValue( line, '=' ), '#' );
|
|
|
|
m_data->release = stripWhiteSpace( m_data->release );
|
|
|
|
} else if ( line[0] == '#' ) {
|
|
|
|
while ( !line.empty() &&
|
|
|
|
( line[0] == '#' || line[0] == ' ' || line[0] == '\t' ) ) {
|
|
|
|
line = line.substr( 1 );
|
|
|
|
}
|
|
|
|
string::size_type pos = line.find( ':' );
|
|
|
|
if ( pos != string::npos ) {
|
2006-09-27 11:41:25 -04:00
|
|
|
if ( startsWithNoCase( line, "desc" ) ) {
|
2005-11-09 16:43:05 -05:00
|
|
|
m_data->description =
|
|
|
|
stripWhiteSpace( getValue( line, ':' ) );
|
2006-09-27 11:41:25 -04:00
|
|
|
} else if ( startsWithNoCase( line, "maint" ) ) {
|
2005-11-09 16:43:05 -05:00
|
|
|
m_data->maintainer =
|
|
|
|
stripWhiteSpace( getValue( line, ':' ) );
|
2006-09-27 11:41:25 -04:00
|
|
|
} else if ( startsWithNoCase( line, "url" ) ) {
|
2005-11-09 16:43:05 -05:00
|
|
|
m_data->url = stripWhiteSpace( getValue( line, ':' ) );
|
2023-03-10 10:03:11 -05:00
|
|
|
} else if ( startsWithNoCase( line, "optional" ) or
|
|
|
|
startsWithNoCase( line, "nice to have" ) ) {
|
|
|
|
string softdeps = stripWhiteSpace( getValue( line, ':' ) );
|
|
|
|
|
|
|
|
StringHelper::replaceAll( softdeps, " ", "," );
|
|
|
|
StringHelper::replaceAll( softdeps, ",,", "," );
|
|
|
|
|
|
|
|
// TODO: decide which one to use
|
|
|
|
#if 0
|
|
|
|
// remove commented out packages
|
|
|
|
list<string> softDepList = StringHelper::split( softdeps, ',' );
|
|
|
|
list<string>::iterator it = deps.begin();
|
|
|
|
for ( ; it != softDepList.end(); ++it ) {
|
|
|
|
if ( (*it)[0] == '#' ) {
|
|
|
|
cerr << "Commented dep: " << *it << endl;
|
|
|
|
} else {
|
|
|
|
if ( it != softDepsList.begin() ) {
|
|
|
|
m_data->optionals += ",";
|
|
|
|
}
|
|
|
|
m_data->optionals += *it;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
m_data->optionals = softdeps;
|
|
|
|
#endif
|
2006-09-27 11:41:25 -04:00
|
|
|
} else if ( startsWithNoCase( line, "dep" ) ) {
|
2005-11-09 16:43:05 -05:00
|
|
|
string depends = stripWhiteSpace( getValue( line, ':' ) );
|
|
|
|
|
|
|
|
StringHelper::replaceAll( depends, " ", "," );
|
|
|
|
StringHelper::replaceAll( depends, ",,", "," );
|
|
|
|
|
|
|
|
// TODO: decide which one to use
|
|
|
|
#if 0
|
|
|
|
// remove commented out packages
|
|
|
|
list<string> deps = StringHelper::split( depends, ',' );
|
|
|
|
list<string>::iterator it = deps.begin();
|
|
|
|
for ( ; it != deps.end(); ++it ) {
|
|
|
|
if ( (*it)[0] == '#' ) {
|
|
|
|
cerr << "Commented dep: " << *it << endl;
|
|
|
|
} else {
|
|
|
|
if ( it != deps.begin() ) {
|
|
|
|
m_data->depends += ",";
|
|
|
|
}
|
|
|
|
m_data->depends += *it;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
m_data->depends = depends;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fclose( fp );
|
|
|
|
|
2006-09-03 12:12:55 -04:00
|
|
|
m_data->generateVersionReleaseString();
|
2005-11-09 16:43:05 -05:00
|
|
|
|
|
|
|
string file = m_data->path + "/" + m_data->name + "/README";
|
|
|
|
struct stat buf;
|
|
|
|
if ( stat( file.c_str(), &buf ) != -1) {
|
|
|
|
m_data->hasReadme = true;
|
|
|
|
}
|
|
|
|
file = m_data->path + "/" + m_data->name + "/pre-install";
|
|
|
|
if ( stat( file.c_str(), &buf ) != -1) {
|
|
|
|
m_data->hasPreInstall = true;
|
|
|
|
}
|
|
|
|
file = m_data->path + "/" + m_data->name + "/post-install";
|
|
|
|
if ( stat( file.c_str(), &buf ) != -1) {
|
|
|
|
m_data->hasPostInstall = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void Package::setDependencies( const std::string& dependencies )
|
|
|
|
{
|
|
|
|
m_data->depends = dependencies;
|
|
|
|
}
|
|
|
|
|
2023-03-10 10:03:11 -05:00
|
|
|
void Package::setOptionals( const std::string& optionals )
|
|
|
|
{
|
|
|
|
m_data->optionals = optionals;
|
|
|
|
}
|
|
|
|
|
2005-11-09 16:43:05 -05:00
|
|
|
|
|
|
|
|
|
|
|
PackageData::PackageData( const string& name_,
|
|
|
|
const string& path_,
|
|
|
|
const string& version_,
|
|
|
|
const string& release_,
|
|
|
|
const string& description_,
|
|
|
|
const string& dependencies_,
|
|
|
|
const string& url_,
|
2023-03-10 10:03:11 -05:00
|
|
|
const string& optionals_,
|
2005-11-09 16:43:05 -05:00
|
|
|
const string& maintainer_,
|
|
|
|
const string& hasReadme_,
|
|
|
|
const string& hasPreInstall_,
|
|
|
|
const string& hasPostInstall_ )
|
|
|
|
: name( name_ ),
|
|
|
|
path( path_ ),
|
|
|
|
version( version_ ),
|
|
|
|
release( release_ ),
|
|
|
|
description( description_ ),
|
|
|
|
depends( dependencies_ ),
|
|
|
|
url( url_ ),
|
2023-03-10 10:03:11 -05:00
|
|
|
optionals( optionals_ ),
|
2005-11-09 16:43:05 -05:00
|
|
|
maintainer( maintainer_ )
|
|
|
|
|
|
|
|
{
|
2006-09-03 12:12:55 -04:00
|
|
|
generateVersionReleaseString();
|
2006-09-27 11:41:25 -04:00
|
|
|
|
2005-11-09 16:43:05 -05:00
|
|
|
hasReadme = ( stripWhiteSpace( hasReadme_ ) == "yes" );
|
|
|
|
hasPreInstall = ( stripWhiteSpace( hasPreInstall_ ) == "yes" );
|
|
|
|
hasPostInstall = ( stripWhiteSpace( hasPostInstall_ ) == "yes" );
|
|
|
|
}
|
|
|
|
|
2006-09-03 12:12:55 -04:00
|
|
|
void PackageData::generateVersionReleaseString()
|
|
|
|
{
|
|
|
|
versionReleaseString = version + "-" + release;
|
|
|
|
}
|
|
|
|
|
2005-11-09 16:43:05 -05:00
|
|
|
|
2006-09-03 12:12:55 -04:00
|
|
|
void Package::expandShellCommands(std::string& input,
|
2005-11-09 16:43:05 -05:00
|
|
|
const time_t& timeNow,
|
|
|
|
const struct utsname unameBuf)
|
|
|
|
{
|
|
|
|
// TODO: consider dropping either of the tagsets, depending on feedback
|
2006-09-03 12:12:55 -04:00
|
|
|
|
2005-11-09 16:43:05 -05:00
|
|
|
static const int TAG_COUNT = 2;
|
|
|
|
string startTag[TAG_COUNT] = { "`", "$(" };
|
|
|
|
string endTag[TAG_COUNT] = { "`", ")" };
|
2006-09-03 12:12:55 -04:00
|
|
|
|
2005-11-09 16:43:05 -05:00
|
|
|
for (int i = 0; i < TAG_COUNT; ++i) {
|
2006-11-05 09:26:08 -05:00
|
|
|
string::size_type pos, dpos = 0;
|
|
|
|
|
|
|
|
pos = 0;
|
|
|
|
while ((pos = input.find(startTag[i], pos)) != string::npos) {
|
|
|
|
|
2023-06-19 14:44:03 -04:00
|
|
|
input = replaceAll(input,
|
|
|
|
startTag[i] + "uname -r" + endTag[i],
|
|
|
|
unameBuf.release);
|
2005-11-09 16:43:05 -05:00
|
|
|
|
2006-11-05 09:26:08 -05:00
|
|
|
dpos = input.find(startTag[i] + "date");
|
|
|
|
if (dpos != string::npos) {
|
2005-11-09 16:43:05 -05:00
|
|
|
// NOTE: currently only works for one date pattern
|
|
|
|
string::size_type startpos, endpos;
|
2006-11-05 09:26:08 -05:00
|
|
|
endpos = input.find(endTag[i], dpos+1);
|
|
|
|
startpos = input.find('+', dpos+1);
|
2006-09-03 12:12:55 -04:00
|
|
|
|
2005-11-09 16:43:05 -05:00
|
|
|
string format = input.substr(startpos+1, endpos-startpos-1);
|
2006-09-03 12:12:55 -04:00
|
|
|
|
2005-11-09 16:43:05 -05:00
|
|
|
// support date '+...' and date "+..."
|
|
|
|
int len = format.length();
|
|
|
|
if (format[len-1] == '\'' || format[len-1] == '"') {
|
|
|
|
format = format.substr(0, len-1);
|
|
|
|
}
|
|
|
|
char timeBuf[32];
|
|
|
|
strftime(timeBuf, 32, format.c_str(), localtime(&timeNow));
|
|
|
|
|
2006-11-05 09:26:08 -05:00
|
|
|
input = input.substr(0, dpos) + timeBuf +
|
2005-11-09 16:43:05 -05:00
|
|
|
input.substr(endpos+1);
|
|
|
|
}
|
2006-11-05 09:26:08 -05:00
|
|
|
|
|
|
|
++pos;
|
2005-11-09 16:43:05 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|