- When stepping through source records skip binaries
[apt.git] / apt-pkg / rpm / rpmsrcrecords.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description                                                          /*{{{*/
3 // $Id: rpmsrcrecords.cc,v 1.9 2003/01/29 15:19:02 niemeyer Exp $
4 /* ######################################################################
5    
6    SRPM Records - Parser implementation for RPM style source indexes
7       
8    ##################################################################### 
9  */
10                                                                         /*}}}*/
11 // Include Files                                                        /*{{{*/
12 #ifdef __GNUG__
13 #pragma implementation "apt-pkg/rpmsrcrecords.h"
14 #endif 
15
16 #include <config.h>
17
18 #ifdef HAVE_RPM
19
20 #include <assert.h>
21
22 #include <apt-pkg/rpmsrcrecords.h>
23 #include <apt-pkg/error.h>
24 #include <apt-pkg/strutl.h>
25 #include <apt-pkg/rpmhandler.h>
26 #include <apt-pkg/pkgcache.h>
27
28 #include <apti18n.h>
29
30 #if RPM_VERSION >= 0x040100
31 #include <rpm/rpmds.h>
32 #endif
33
34 using namespace std;
35
36 // SrcRecordParser::rpmSrcRecordParser - Constructor                    /*{{{*/
37 // ---------------------------------------------------------------------
38 /* */
39 rpmSrcRecordParser::rpmSrcRecordParser(string File,pkgIndexFile const *Index)
40     : Parser(Index), Buffer(0), BufSize(0), BufUsed(0)
41 {
42    struct stat Buf;
43    if (stat(File.c_str(),&Buf) == 0 && S_ISDIR(Buf.st_mode))
44       Handler = new RPMDirHandler(File);
45    else if (flExtension(File) == "rpm")
46       Handler = new RPMSingleFileHandler(File);
47    else if (flExtension(File) == "xml")
48       Handler = new RPMRepomdHandler(File, false);
49    else
50       Handler = new RPMFileHandler(File);
51 }
52                                                                         /*}}}*/
53 // SrcRecordParser::~rpmSrcRecordParser - Destructor                    /*{{{*/
54 // ---------------------------------------------------------------------
55 /* */
56 rpmSrcRecordParser::~rpmSrcRecordParser()
57 {
58    delete Handler;
59    free(Buffer);
60 }
61                                                                         /*}}}*/
62 // SrcRecordParser::Binaries - Return the binaries field                /*{{{*/
63 // ---------------------------------------------------------------------
64 /* This member parses the binaries field into a pair of class arrays and
65    returns a list of strings representing all of the components of the
66    binaries field. The returned array need not be freed and will be
67    reused by the next Binaries function call. */
68 const char **rpmSrcRecordParser::Binaries()
69 {
70    return NULL;
71
72 // WTF is this ?!? If we're looking for sources why would be interested
73 // in binaries? Maybe there's an inner Zen to this all but
74 // apt-cache showsrc seems to work without just fine so disabled for now...
75 #if 0
76    int i = 0;
77    char **bins;
78    int type, count;
79    assert(HeaderP != NULL);
80    int rc = headerGetEntry(HeaderP, CRPMTAG_BINARY,
81                            &type, (void**)&bins, &count);
82    if (rc != 1)
83        return NULL;
84    for (i = 0; (unsigned)i < sizeof(StaticBinList)/sizeof(char*) && i < count;
85         i++)
86       StaticBinList[i] = bins[i];
87    StaticBinList[i] = 0;
88    return StaticBinList;
89 #endif
90 }
91                                                                         /*}}}*/
92 // SrcRecordParser::Files - Return a list of files for this source      /*{{{*/
93 // ---------------------------------------------------------------------
94 /* This parses the list of files and returns it, each file is required to have
95    a complete source package */
96 bool rpmSrcRecordParser::Files(vector<pkgSrcRecords::File> &List)
97 {
98    List.clear();
99    
100    pkgSrcRecords::File F;
101
102    // XXX FIXME: Ignoring the md5sum for source packages for now 
103    //F.MD5Hash = Handler->MD5Sum();
104    F.MD5Hash = "";
105    F.Size = Handler->FileSize();
106    F.Path = flCombine(Handler->Directory(), Handler->FileName());
107    F.Type = "srpm";
108
109    List.push_back(F);
110    
111    return true;
112 }
113                                                                         /*}}}*/
114
115 bool rpmSrcRecordParser::Restart()
116 {
117    Handler->Rewind();
118    return true;
119 }
120
121 bool rpmSrcRecordParser::Step() 
122 {
123    bool ret = Handler->Skip();
124    // Repomd can have both binaries and sources, step over any binaries
125    while (ret && ! Handler->IsSourceRpm()) {
126       ret = Handler->Skip();
127    }
128    return ret;
129 }
130
131 bool rpmSrcRecordParser::Jump(unsigned long Off)
132 {
133    return Handler->Jump(Off);
134 }
135
136 string rpmSrcRecordParser::Package() const
137 {
138    return Handler->Name();
139 }
140
141 string rpmSrcRecordParser::Version() const
142 {
143    return Handler->EVR();
144 }
145     
146
147 // RecordParser::Maintainer - Return the maintainer email               /*{{{*/
148 // ---------------------------------------------------------------------
149 /* */
150 string rpmSrcRecordParser::Maintainer() const
151 {
152    return Handler->Packager();
153 }
154
155 string rpmSrcRecordParser::Section() const
156 {
157    return Handler->Group();
158 }
159
160 unsigned long rpmSrcRecordParser::Offset() 
161 {
162     return Handler->Offset();
163 }
164
165 void rpmSrcRecordParser::BufCat(const char *text)
166 {
167    if (text != NULL)
168       BufCat(text, text+strlen(text));
169 }
170
171 void rpmSrcRecordParser::BufCat(const char *begin, const char *end)
172 {
173    unsigned len = end - begin;
174     
175    if (BufUsed+len+1 >= BufSize)
176    {
177       BufSize += 512;
178       char *tmp = (char*)realloc(Buffer, BufSize);
179       if (tmp == NULL)
180       {
181          _error->Errno("realloc", _("Could not allocate buffer for record text"));
182          return;
183       }
184       Buffer = tmp;
185    }
186
187    strncpy(Buffer+BufUsed, begin, len);
188    BufUsed += len;
189 }
190
191 void rpmSrcRecordParser::BufCatTag(const char *tag, const char *value)
192 {
193    BufCat(tag);
194    BufCat(value);
195 }
196
197 void rpmSrcRecordParser::BufCatDep(Dependency *Dep)
198 {
199    string buf;
200
201    BufCat(Dep->Name.c_str());
202    if (Dep->Version.empty() == false) 
203    {
204       BufCat(" ");
205       switch (Dep->Op) {
206          case pkgCache::Dep::Less:
207             buf += "<";
208             break;
209          case pkgCache::Dep::LessEq:
210             buf += "<=";
211             break;
212          case pkgCache::Dep::Equals: 
213             buf += "=";
214             break;
215          case pkgCache::Dep::Greater:
216             buf += ">";
217             break;
218          case pkgCache::Dep::GreaterEq:
219             buf += ">=";
220             break;
221       }
222
223       BufCat(buf.c_str());
224       BufCat(" ");
225       BufCat(Dep->Version.c_str());
226    }
227 }
228
229 void rpmSrcRecordParser::BufCatDescr(const char *descr)
230 {
231    const char *begin = descr;
232
233    while (*descr) 
234    {
235       if (*descr=='\n') 
236       {
237          BufCat(" ");
238          BufCat(begin, descr+1);
239          begin = descr+1;
240       }
241       descr++;
242    }
243    BufCat(" ");
244    BufCat(begin, descr);
245    BufCat("\n");
246 }
247
248 // SrcRecordParser::AsStr - The record in raw text
249 // -----------------------------------------------
250 string rpmSrcRecordParser::AsStr() 
251 {
252    char buf[32];
253
254    BufUsed = 0;
255
256    BufCatTag("Package: ", Handler->Name().c_str());
257
258    BufCatTag("\nSection: ", Handler->Group().c_str());
259
260    snprintf(buf, sizeof(buf), "%lu", Handler->InstalledSize());
261    BufCatTag("\nInstalled Size: ", buf);
262
263    BufCatTag("\nPackager: ", Handler->Packager().c_str());
264    //BufCatTag("\nVendor: ", Handler->Vendor().c_str());
265
266    BufCat("\nVersion: ");
267    BufCat(Handler->EVR().c_str());
268
269    vector<Dependency*> Deps, Conflicts;
270    vector<Dependency*>::iterator I;
271    bool start = true;
272
273    Handler->Depends(pkgCache::Dep::Depends, Deps);
274    for (I = Deps.begin(); I != Deps.end(); I++) {
275       if ((*I)->Type != pkgCache::Dep::Depends)
276          continue;
277       if (start) {
278          BufCat("\nBuild-Depends: ");
279          start = false;
280       } else {
281          BufCat(", ");
282       }
283       BufCatDep(*I);
284    }
285
286    // Doesn't do anything yet, build conflicts aren't recorded yet...
287    Handler->Depends(pkgCache::Dep::Conflicts, Conflicts);
288    start = true;
289    for (I = Conflicts.begin(); I != Conflicts.end(); I++) {
290       if (start) {
291          BufCat("\nBuild-Conflicts: ");
292          start = false;
293       } else {
294          BufCat(", ");
295       }
296       BufCatDep(*I);
297    }
298
299    BufCatTag("\nArchitecture: ", Handler->Arch().c_str());
300
301    snprintf(buf, sizeof(buf), "%lu", Handler->FileSize());
302    BufCatTag("\nSize: ", buf);
303
304    BufCatTag("\nMD5Sum: ", Handler->MD5Sum().c_str());
305
306    BufCatTag("\nFilename: ", Handler->FileName().c_str());
307
308    BufCatTag("\nSummary: ", Handler->Summary().c_str());
309    BufCat("\nDescription: ");
310    BufCat("\n");
311    BufCatDescr(Handler->Description().c_str());
312    BufCat("\n");
313
314    return string(Buffer, BufUsed);
315 }
316
317
318 // SrcRecordParser::BuildDepends - Return the Build-Depends information /*{{{*/
319 // ---------------------------------------------------------------------
320 bool rpmSrcRecordParser::BuildDepends(vector<pkgSrcRecords::Parser::BuildDepRec> &BuildDeps,
321                                       bool ArchOnly)
322 {
323    BuildDepRec rec;
324    BuildDeps.clear();
325
326    vector<Dependency*> Deps, Conflicts;
327    Handler->Depends(pkgCache::Dep::Depends, Deps);
328
329    for (vector<Dependency*>::iterator I = Deps.begin(); I != Deps.end(); I++) {
330       rec.Package = (*I)->Name;
331       rec.Version = (*I)->Version;
332       rec.Op = (*I)->Op;
333       rec.Type = pkgSrcRecords::Parser::BuildDepend;
334       BuildDeps.push_back(rec);
335    }
336       
337    Handler->Depends(pkgCache::Dep::Conflicts, Conflicts);
338
339    for (vector<Dependency*>::iterator I = Conflicts.begin(); I != Conflicts.end(); I++) {
340       rec.Package = (*I)->Name;
341       rec.Version = (*I)->Version;
342       rec.Op = (*I)->Op;
343       rec.Type = pkgSrcRecords::Parser::BuildConflict;
344       BuildDeps.push_back(rec);
345    }
346    return true;
347 }
348                                                                         /*}}}*/
349 #endif /* HAVE_RPM */
350
351 // vim:sts=3:sw=3