- merge repomd branch
[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);
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    F.MD5Hash = Handler->MD5Sum();
103    F.Size = Handler->FileSize();
104    F.Path = flCombine(Handler->Directory(), Handler->FileName());
105    F.Type = "srpm";
106
107    List.push_back(F);
108    
109    return true;
110 }
111                                                                         /*}}}*/
112
113 bool rpmSrcRecordParser::Restart()
114 {
115    Handler->Rewind();
116    return true;
117 }
118
119 bool rpmSrcRecordParser::Step() 
120 {
121    return Handler->Skip();
122 }
123
124 bool rpmSrcRecordParser::Jump(unsigned long Off)
125 {
126    return Handler->Jump(Off);
127 }
128
129 string rpmSrcRecordParser::Package() const
130 {
131    return Handler->Name();
132 }
133
134 string rpmSrcRecordParser::Version() const
135 {
136    string e, v, r, verstr;
137    e = Handler->Epoch();
138    v = Handler->Version();
139    r = Handler->Release();
140
141    if (e.empty() == false)
142       verstr = e + ":" + v + "-" + r;
143    else
144       verstr = v + "-" + r;
145    return verstr;
146 }
147     
148
149 // RecordParser::Maintainer - Return the maintainer email               /*{{{*/
150 // ---------------------------------------------------------------------
151 /* */
152 string rpmSrcRecordParser::Maintainer() const
153 {
154    return Handler->Packager();
155 }
156
157 string rpmSrcRecordParser::Section() const
158 {
159    return Handler->Group();
160 }
161
162 unsigned long rpmSrcRecordParser::Offset() 
163 {
164     return Handler->Offset();
165 }
166
167 void rpmSrcRecordParser::BufCat(const char *text)
168 {
169    if (text != NULL)
170       BufCat(text, text+strlen(text));
171 }
172
173 void rpmSrcRecordParser::BufCat(const char *begin, const char *end)
174 {
175    unsigned len = end - begin;
176     
177    if (BufUsed+len+1 >= BufSize)
178    {
179       BufSize += 512;
180       char *tmp = (char*)realloc(Buffer, BufSize);
181       if (tmp == NULL)
182       {
183          _error->Errno("realloc", _("Could not allocate buffer for record text"));
184          return;
185       }
186       Buffer = tmp;
187    }
188
189    strncpy(Buffer+BufUsed, begin, len);
190    BufUsed += len;
191 }
192
193 void rpmSrcRecordParser::BufCatTag(const char *tag, const char *value)
194 {
195    BufCat(tag);
196    BufCat(value);
197 }
198
199 void rpmSrcRecordParser::BufCatDep(Dependency *Dep)
200 {
201    string buf;
202
203    BufCat(Dep->Name.c_str());
204    if (Dep->Version.empty() == false) 
205    {
206       BufCat(" ");
207       switch (Dep->Op) {
208          case pkgCache::Dep::Less:
209             buf += "<";
210             break;
211          case pkgCache::Dep::LessEq:
212             buf += "<=";
213             break;
214          case pkgCache::Dep::Equals: 
215             buf += "=";
216             break;
217          case pkgCache::Dep::Greater:
218             buf += ">";
219             break;
220          case pkgCache::Dep::GreaterEq:
221             buf += ">=";
222             break;
223       }
224
225       BufCat(buf.c_str());
226       BufCat(" ");
227       BufCat(Dep->Version.c_str());
228    }
229 }
230
231 void rpmSrcRecordParser::BufCatDescr(const char *descr)
232 {
233    const char *begin = descr;
234
235    while (*descr) 
236    {
237       if (*descr=='\n') 
238       {
239          BufCat(" ");
240          BufCat(begin, descr+1);
241          begin = descr+1;
242       }
243       descr++;
244    }
245    BufCat(" ");
246    BufCat(begin, descr);
247    BufCat("\n");
248 }
249
250 // SrcRecordParser::AsStr - The record in raw text
251 // -----------------------------------------------
252 string rpmSrcRecordParser::AsStr() 
253 {
254    int type, type2, type3, count;
255    char *str;
256    char **strv;
257    char **strv2;
258    int_32 *numv;
259    char buf[32];
260
261    BufUsed = 0;
262
263    BufCatTag("Package: ", Handler->Name().c_str());
264
265    BufCatTag("\nSection: ", Handler->Group().c_str());
266
267    snprintf(buf, sizeof(buf), "%d", Handler->InstalledSize());
268    BufCatTag("\nInstalled Size: ", buf);
269
270    BufCatTag("\nPackager: ", Handler->Packager().c_str());
271    //BufCatTag("\nVendor: ", Handler->Vendor().c_str());
272
273    BufCat("\nVersion: ");
274    // XXX FIXME: handle the epoch madness somewhere central instead of
275    // figuring it out on every damn occasion separately
276
277    string e, v, r, verstr;
278    e = Handler->Epoch();
279    v = Handler->Version();
280    r = Handler->Release();
281
282    if (e.empty() == false)
283       verstr = e + ":" + v + "-" + r;
284    else
285       verstr = v + "-" + r;
286
287    BufCat(verstr.c_str());
288
289    vector<Dependency*> Deps, Conflicts;
290    vector<Dependency*>::iterator I;
291    bool start = true;
292
293    Handler->Depends(pkgCache::Dep::Depends, Deps);
294    for (I = Deps.begin(); I != Deps.end(); I++) {
295       if ((*I)->Type != pkgCache::Dep::Depends)
296          continue;
297       if (start) {
298          BufCat("\nBuild-Depends: ");
299          start = false;
300       } else {
301          BufCat(", ");
302       }
303       BufCatDep(*I);
304    }
305
306    // Doesn't do anything yet, build conflicts aren't recorded yet...
307    Handler->Depends(pkgCache::Dep::Conflicts, Conflicts);
308    start = true;
309    for (I = Conflicts.begin(); I != Conflicts.end(); I++) {
310       if (start) {
311          BufCat("\nBuild-Conflicts: ");
312          start = false;
313       } else {
314          BufCat(", ");
315       }
316       BufCatDep(*I);
317    }
318
319    BufCatTag("\nArchitecture: ", Handler->Arch().c_str());
320
321    snprintf(buf, sizeof(buf), "%d", Handler->FileSize());
322    BufCatTag("\nSize: ", buf);
323
324    BufCatTag("\nMD5Sum: ", Handler->MD5Sum().c_str());
325
326    BufCatTag("\nFilename: ", Handler->FileName().c_str());
327
328    BufCatTag("\nSummary: ", Handler->Summary().c_str());
329    BufCat("\nDescription: ");
330    BufCat("\n");
331    BufCatDescr(Handler->Description().c_str());
332    BufCat("\n");
333
334    return string(Buffer, BufUsed);
335 }
336
337
338 // SrcRecordParser::BuildDepends - Return the Build-Depends information /*{{{*/
339 // ---------------------------------------------------------------------
340 bool rpmSrcRecordParser::BuildDepends(vector<pkgSrcRecords::Parser::BuildDepRec> &BuildDeps,
341                                       bool ArchOnly)
342 {
343    BuildDepRec rec;
344    BuildDeps.clear();
345
346    vector<Dependency*> Deps, Conflicts;
347    Handler->Depends(pkgCache::Dep::Depends, Deps);
348
349    for (vector<Dependency*>::iterator I = Deps.begin(); I != Deps.end(); I++) {
350       rec.Package = (*I)->Name;
351       rec.Version = (*I)->Version;
352       rec.Op = (*I)->Op;
353       rec.Type = pkgSrcRecords::Parser::BuildDepend;
354       BuildDeps.push_back(rec);
355    }
356       
357    Handler->Depends(pkgCache::Dep::Conflicts, Conflicts);
358
359    for (vector<Dependency*>::iterator I = Conflicts.begin(); I != Conflicts.end(); I++) {
360       rec.Package = (*I)->Name;
361       rec.Version = (*I)->Version;
362       rec.Op = (*I)->Op;
363       rec.Type = pkgSrcRecords::Parser::BuildConflict;
364       BuildDeps.push_back(rec);
365    }
366    return true;
367 }
368                                                                         /*}}}*/
369 #endif /* HAVE_RPM */
370
371 // vim:sts=3:sw=3