#!/usr/bin/env python2.6 -t

"""
gets all depended catalog names
usage: get_dependencies <md5_sum>

search rest: r'/rest/catalogs/([^/]+)/(sparc|i386)/(SunOS[^/]+)/catalognames/([^/]+)/', 'Srv4ByCatAndCatalogname',
pkgdepend genertate creates entries like:
depend fmri=__TBD 
 pkg.debug.depend.file=libpcre.so.1 
 pkg.debug.depend.path=lib 
 pkg.debug.depend.path=opt/csw/lib 
 pkg.debug.depend.path=opt/csw/lib 
 pkg.debug.depend.path=opt/csw/lib/amd64 
 pkg.debug.depend.path=opt/csw/lib/i386 
 pkg.debug.depend.path=usr/lib 
 pkg.debug.depend.reason=opt/csw/bin/swig 
 pkg.debug.depend.type=elf 
 type=require
"""

from __future__ import print_function

import optparse
import rest
import common_constants
import pprint
import gdbm
import logging
import sys
import os
import cjson
from lib.python.shell import ShellCommand
import makeStdLibDb
import platform
import re
from lib.python import configuration
from lib.python import representations

from Cheetah.Template import Template

fn_stdlibs = 'work/stdlibs.json'
fn_pkgstats = 'work/pkgstats'
LDD_CMD = '/usr/bin/ldd'

FileRE = '.*pkg.debug.depend.file=([^\s]*)\s.*'
PathRE = 'pkg.debug.depend.path=([^\s]*)'
ReasonRE = '.*pkg.debug.depend.reason=([^\s]*)\s.*'

# strict
# depend_tmpl = 'depend fmri=pkg://opencsw/$catalogname@$version,$rel-$revision type=require'
# lazzy
depend_tmpl = 'depend fmri=pkg:/opencsw/$catalogname@$version type=require'
manifest_tmpl = '''
set name=pkg.fmri value=pkg:/opencsw/$category/$catalogname@$version,$osrel-$revision:$pstamp
set name=pkg.summary value="$summary"
set name=pkg.human-version value=$version
set name=publisher value=$email
'''

catrel = 'unstable'
arch = platform.processor()
osrel = platform.system()+platform.release()
pkgroot = '../pkgroot'

def char2dotvers(version):
     newversion = ''
     converted = False
     for c in version:
        try: 
	    n = int(c)
            if converted: newversion +='.'; converted = False
            newversion += c
	except ValueError:
            if c == '.':
                newversion += c
            else:
                newversion += ".%d" % (ord(c.upper())-0x40)
                converted = True
     return newversion

class GetPackage(object):
    def __init__(self):
        self.cached_catalogs_bins = {}
        self.cached_catalogs_links = {}
        self.cached_catalogs_needed_bins = {}
        config = configuration.GetConfig()
        username, password = rest.GetUsernameAndPassword()
        self.rest_client = rest.RestClient(
          pkgdb_url=config.get('rest', 'pkgdb'),
          releases_url=config.get('rest', 'releases'),
          username=username,
          password=password)
        self.cp = rest.CachedPkgstats(fn_pkgstats, self.rest_client)
        

    def resolveDeps(self, p5m):
        def getResolvedPath(bin, lib):
            ret_code, cstdout, cstderr = ShellCommand([LDD_CMD,os.path.join(pkgroot,bin)])
            for line in cstdout.split('\n'):
                if lib in line:
                    return os.path.dirname(line.split('=>')[1]).strip()
        with open( p5m ) as pf:
            for line in pf.readlines():
                line = line.strip()
                if line.startswith('depend fmri=__TBD') and'pkg.debug.depend.type=elf' in line:
                    basename = re.match(FileRE, line).group(1)
                    reason = re.match(ReasonRE, line).group(1)
                    # these path are useless because its sorted alphabetically
                    paths = re.findall(PathRE, line)
                    # thats why we get the used path
                    deppath = getResolvedPath(reason, basename)
                    logging.debug("getPathsAndCatnames:  %s %s %s %s" % (catrel,arch,osrel,basename))
                    pkg = self.rest_client.GetPathsAndCatnamesByBasename(catrel, arch, osrel, basename)
                    if deppath:
                    	if not deppath in pkg.keys():
                    		if os.path.islink(deppath):
                    			deppath = os.path.realpath(deppath)
                        catalogname = pkg[deppath][0][0]
                        # import pdb; pdb.set_trace()
                        version = pkg[deppath][0][1].split(',')[0]
                        if not version.startswith('fakeversion'):
                            version = char2dotvers(version)
                            print (Template(depend_tmpl,searchList=[
                                        {'catalogname': catalogname,'version': version }]))
                    else:
                        print (line)
                else:
                    print (line)
                        
def main():
    global pkgroot, catrel, arch, osrel

    parser = optparse.OptionParser()
    parser.add_option("--debug", dest="debug", action="store_true")
    parser.add_option("-r", "--os-release", dest="osrel",
                    default='system',
                    help="E.g. SunOS5.10")
    parser.add_option("-a", "--arch", dest="arch", default='system',
                    help="'i386' or 'sparc'")
    parser.add_option("-c", "--catalog-release", dest="catrel",
                    default="unstable",
                    help="E.g. unstable, dublin")    
    parser.add_option("-R", "--pkg-root", dest="pkgroot",
                    default="../pkgroot",
                    help="E.g. unstable, dublin")    
    options, args = parser.parse_args()
    if not args:
        logging.error("need argument: package_prototype after pkgdepend generate")
        sys.exit(1)
    if options.debug:
        logging.basicConfig(level=logging.DEBUG)
    if options.osrel:
        osrel = options.osrel
    if options.arch:
        arch = options.arch
    if options.catrel:
        catrel = options.catrel
    if options.pkgroot:
        pkgroot = options.pkgroot
    logging.debug("use options: %s %s %s %s" % (catrel, arch, osrel, pkgroot))
    logging.debug("use arg:  %s" % args)
    if not os.path.exists(fn_stdlibs):
        print ("needed file %s not found, will create this" % fn_stdlibs, file=sys.stderr)
        makeStdLibDb.buildStdlibList()
    
    Pkg = GetPackage()
    for p5m in args:
        Pkg.resolveDeps(p5m)
    print ("")


if __name__ == '__main__':
  main()
