00001
00002
00003
00004
00005
00006
00007
00008
00012 #include <iostream>
00013 #include <fstream>
00014 #include <sstream>
00015
00016 #include <boost/tokenizer.hpp>
00017 #include <boost/algorithm/string.hpp>
00018
00019 #include "zypp/base/Logger.h"
00020 #include "zypp/base/PtrTypes.h"
00021 #include "zypp/base/String.h"
00022 #include "zypp/CapFactory.h"
00023
00024 #include "zypp/source/susetags/PatternTagFileParser.h"
00025 #include "zypp/parser/tagfile/ParseException.h"
00026 #include <boost/regex.hpp>
00027
00028 #undef ZYPP_BASE_LOGGER_LOGGROUP
00029 #define ZYPP_BASE_LOGGER_LOGGROUP "PatternsTagFileParser"
00030
00031 using namespace std;
00032 using namespace boost;
00033 using namespace zypp::parser::tagfile;
00034
00036 namespace zypp
00037 {
00038
00039 namespace source
00040 {
00041
00042 namespace susetags
00043 {
00044
00045 struct PatternTagFileParser::Scrap
00046 {
00047 std::string _parser_version;
00048 std::string _name;
00049 std::string _version;
00050 std::string _release;
00051 std::string _arch;
00052 std::list<std::string> _suggests;
00053 std::list<std::string> _recommends;
00054 std::list<std::string> _requires;
00055 std::list<std::string> _conflicts;
00056 std::list<std::string> _provides;
00057 std::list<std::string> _obsoletes;
00058 std::list<std::string> _freshens;
00059 std::list<std::string> _supplements;
00060 std::list<std::string> _pkgsuggests;
00061 std::list<std::string> _pkgrecommends;
00062 std::list<std::string> _pkgrequires;
00063 std::list<std::string> _includes;
00064 std::list<std::string> _extends;
00065 };
00066
00067 Pattern::Ptr parsePattern( parser::ParserProgress::Ptr progress, Source_Ref source_r, const Pathname & file_r )
00068 {
00069 MIL << "Starting to parse pattern " << file_r << std::endl;
00070 PatternTagFileParser p(progress);
00071 try
00072 {
00073 p.parse( file_r );
00074 }
00075 catch (zypp::parser::tagfile::ParseException &e)
00076 {
00077 ZYPP_CAUGHT(e);
00078 ERR << "Pattern " << file_r << " is broken." << std::endl;
00079 return 0L;
00080 }
00081
00082 p.patImpl->_source = source_r;
00083 return p.result;
00084 }
00085
00086 PatternTagFileParser::PatternTagFileParser( parser::ParserProgress::Ptr progress )
00087 : parser::tagfile::TagFileParser(progress)
00088 {
00089 patImpl = new SuseTagsPatternImpl;
00090 _scrap.reset( new Scrap );
00091 }
00092
00093 void PatternTagFileParser::consume( const SingleTag &tag )
00094 {
00095 if ( tag.name == "Sum" )
00096 {
00097 patImpl->_summary.setText(tag.value, Locale(tag.modifier));
00098 }
00099 else if ( tag.name == "Ver" )
00100 {
00101 _scrap->_parser_version = tag.value;
00102 }
00103 else if ( tag.name == "Pat" )
00104 {
00105 std::string line = tag.value;
00106 std::vector<std::string> words;
00107
00108 if (str::split( line, std::back_inserter(words), " " ) != 4 )
00109 ZYPP_THROW( parser::tagfile::ParseException( "Expected [name version release arch] ], got [" + tag.value +"]") );
00110
00111 _scrap->_name = words[0];
00112 _scrap->_version = words[1];
00113 _scrap->_release = words[2];
00114 _scrap->_arch = words[3];
00115 }
00116 else if ( tag.name == "Vis" )
00117 {
00118 patImpl->_visible = (tag.value == "true") ? true : false;
00119 }
00120 else if ( tag.name == "Cat" )
00121 {
00122 patImpl->_category.setText(tag.value, Locale(tag.modifier));
00123 }
00124 else if ( tag.name == "Ico" )
00125 {
00126 patImpl->_icon = tag.value;
00127 }
00128 else if ( tag.name == "Ord" )
00129 {
00130 patImpl->_order = tag.value;
00131 }
00132 }
00133
00134 void PatternTagFileParser::consume( const MultiTag &tag )
00135 {
00136 if ( tag.name == "Des" )
00137 {
00138 std::string buffer;
00139 for (std::list<std::string>::const_iterator it = tag.values.begin(); it != tag.values.end(); ++it)
00140 {
00141 buffer += (*it + "\n");
00142 }
00143 patImpl->_description.setText(buffer, Locale(tag.modifier));
00144 }
00145 if ( tag.name == "Req" )
00146 {
00147 _scrap->_requires = tag.values;
00148 }
00149 else if ( tag.name == "Rec" )
00150 {
00151 _scrap->_recommends = tag.values;
00152 }
00153 else if ( tag.name == "Prv" )
00154 {
00155 _scrap->_provides = tag.values;
00156 }
00157 else if ( tag.name == "Obs" )
00158 {
00159 _scrap->_obsoletes = tag.values;
00160 }
00161 else if ( tag.name == "Con" )
00162 {
00163 _scrap->_conflicts = tag.values;
00164 }
00165 else if ( tag.name == "Sup" )
00166 {
00167 _scrap->_supplements = tag.values;
00168 }
00169 else if ( tag.name == "Sug" )
00170 {
00171 _scrap->_suggests = tag.values;
00172 }
00173 else if ( tag.name == "Fre" )
00174 {
00175 _scrap->_freshens = tag.values;
00176 }
00177 else if ( tag.name == "Prq" )
00178 {
00179 _scrap->_pkgrequires = tag.values;
00180 }
00181 else if ( tag.name == "Prc" )
00182 {
00183 _scrap->_pkgrecommends = tag.values;
00184 }
00185 else if ( tag.name == "Psg" )
00186 {
00187 _scrap->_pkgsuggests = tag.values;
00188 }
00189 else if ( tag.name == "Inc" )
00190 {
00191 _scrap->_includes = tag.values;
00192 }
00193 else if ( tag.name == "Ext" )
00194 {
00195 _scrap->_extends = tag.values;
00196 }
00197 }
00198
00199 void PatternTagFileParser::parseDeps( const std::list<std::string> & strdeps, CapSet & capset, const Resolvable::Kind & kind )
00200 {
00201 CapFactory f;
00202 for (std::list<std::string>::const_iterator it = strdeps.begin(); it != strdeps.end(); it++)
00203 {
00204 if ( (*it).empty() )
00205 {
00206 stringstream ss;
00207 WAR << "Emtpy capability on " << _file_r << " line " << _line_number << ". Ignoring." << endl;
00208 }
00209
00210 try
00211 {
00212 Capability cap = f.parse( kind, *it );
00213 capset.insert( cap );
00214 }
00215 catch ( const Exception &e )
00216 {
00217 stringstream ss;
00218 ss << "Broken capability [" << *it << "]" << _file_r << " line " << _line_number;
00219 ZYPP_THROW( ParseException( ss.str() ) );
00220 }
00221 }
00222 return;
00223 }
00224
00225 void PatternTagFileParser::endParse()
00226 {
00227 #warning FIXME how to insert the specific language packages
00228 Dependencies _deps;
00229
00230 parseDeps( _scrap->_recommends, _deps[Dep::RECOMMENDS] );
00231 parseDeps( _scrap->_requires, _deps[Dep::REQUIRES] );
00232 parseDeps( _scrap->_conflicts, _deps[Dep::CONFLICTS] );
00233 parseDeps( _scrap->_provides, _deps[Dep::PROVIDES] );
00234 parseDeps( _scrap->_obsoletes, _deps[Dep::OBSOLETES] );
00235 parseDeps( _scrap->_suggests, _deps[Dep::SUGGESTS] );
00236 parseDeps( _scrap->_supplements, _deps[Dep::SUPPLEMENTS] );
00237 parseDeps( _scrap->_freshens, _deps[Dep::FRESHENS] );
00238 parseDeps( _scrap->_pkgrecommends, _deps[Dep::RECOMMENDS], ResTraits<Package>::kind );
00239 parseDeps( _scrap->_pkgrequires, _deps[Dep::REQUIRES], ResTraits<Package>::kind );
00240 parseDeps( _scrap->_pkgsuggests, _deps[Dep::SUGGESTS], ResTraits<Package>::kind );
00241 parseDeps( _scrap->_includes, patImpl->_includes );
00242 parseDeps( _scrap->_extends, patImpl->_extends );
00243
00244 Arch arch;
00245 if (!_scrap->_arch.empty())
00246 arch = Arch(_scrap->_arch);
00247
00248 NVRAD nvrad = NVRAD( _scrap->_name, Edition( _scrap->_version, _scrap->_release, std::string() ), arch, _deps );
00249 result = detail::makeResolvableFromImpl( nvrad, patImpl );
00250 }
00252 }
00255 }
00258 }