#!/usr/bin/python

import re
import os

def chomp(line):
    """Similar to perl chomp"""
    try:
	    if line[-1]=='\n':
		return line[:-1]
	    else:
    		return line
    except IndexError:    
	return ''



class synthesis_parser:
    """class to parse a synthesis hdlist"""
    _list={}
    _path={}
    _operation_re=None
    _requires_re=None
    def __init__(self):
	self._requires_re=re.compile('^([^[]*)(?:\[\*\])*(\[.*])?')
	self._operation_re=re.compile('\[([<>=]*) *(.*)\]')


    def split_requires(self,req_array):
        """split the requires in a dictionary"""
        res={}
        for i in req_array:
            require=self._requires_re.match(i)
            if require:
                name=require.groups()[0]
                res[name]={}
                condition=require.groups()[1]
                if condition:
                    op=''
                    version=''
                    o=self._operation_re.match(condition)
                    if o:
                        (op,version)=o.groups()[0:2]
                        res[name]['version']=version
                        res[name]['operation']=op
        return res
    def get_list(self):
        """ return the list of rpm parsed from the synthesis """
        return self._list

    def get_path(self,rpm):
        """ return the path of the rpm"""
        r=self._list[rpm]
        res= os.path.dirname(self._path[r['source']]['path'])+'/'
        res=res + self._path[r['source']]['rpm']+'/'
        return res+'/'+'%s-%s-%s.%s.rpm' % (rpm,r['version'],r['release'],r['arch'])
    
    def open_listing(self,f):
	""" open a synthetis, by taking the url as argument. support ftp:// and http://, and simple file."""	
	# TODO and https ?
	if f.startswith('http://'):
	        r=self.open_from_http(f)
	elif f.startswith('ftp://'):
	        r=self.open_from_ftp(f)
	else:
	        r=self.open_from_disk(f)
	return r

    def open_from_ftp(self,f):
        return self.open_from_http(f)
        
    #TODO used native python library, once urllib will be usable with gzip
    # use file detection
    def uncompress(self,f,cmd_line):
        """ open a compressed file """
        return cmd_line + ' | zcat '



    def open_from_http(self,f):
       	""" read a file from http """
	# let's the fun begin, with popen
	cmd_line='wget -q -O - %s' % f;
	return os.popen(self.uncompress(f,cmd_line))
		        
    def open_from_disk(self,f):
        cmd_line=' cat %s ' % f
	return os.popen(self.uncompress(f,cmd_line))


    def add_hdlist(self,name_source,path,path_to_rpm='.'):
        """ add the synthesis.hdlist to the list """
        self._path[name_source]={}
        self._path[name_source]['path']=path
        self._path[name_source]['rpm']=path_to_rpm
        f=self.open_listing(path)
        tmp={}
        line=f.readline()
        while line:
            line=chomp(line)
            l=line.split('@')[1:]
            if l[0] == 'summary':
                tmp['summary']=l[1]
            for i in ('requires','provides','conflict','obsoletes'):
                if l[0] == i:
                        tmp[i]=self.split_requires(l[1:])
            if l[0] == 'info':
                rpm=l[1].split('-')
                version=rpm[-2:-1][0]
                name='-'.join(rpm[0:-2])
                tmp['version']=version
                tmp['epoch']=l[2]
                tmp['size']=l[3]
                tmp['group']=l[4]
                tmp['source']=name_source
                tmp['release']='.'.join(rpm[-1].split('.')[0:-1])
                tmp['arch']=rpm[-1].split('.')[-1]
                self._list[name]=tmp
                tmp={}
            line=f.readline()

if __name__=='__main__':
	si=synthesis_parser()
	si.add_hdlist('main','/mnt/BIG/dis/cooker/i586/Mandrake/base/synthesis.hdlist.cz','../RPMS/')
	si.add_hdlist('contrib','ftp://ftp.free.fr/pub/Distributions_Linux/Mandrakelinux/devel/cooker/cooker/Mandrake//base/synthesis.hdlist2.cz','../RPMS2/')
	print si._list['apache']
	req=si._list['apache']['requires']
	for j in req.keys():
	    if req[j].has_key('version'):
	        print j,req[j]['operation'],req[j]['version']
	    else:
        	print j



