#!/usr/bin/python
# -*- coding: utf-8 -*- 

import sys
import os
import os.path
import fnmatch
import shutil
import zipfile 
import stat
import getopt
from os.path import dirname
import shutil
from os import system
import ConfigParser
import StringIO
import re
import urllib2

DEBUG = False
VERBOSE = False

def message(msg):
    if VERBOSE:
        print msg

def msgerror(msg):
    print "ERROR: ", msg

def msgwarn(msg):
    print "WARNING: ", msg

def debug(msg):
    if DEBUG:
        print "DEBUG: ", msg

def acquire_file(name):
  files = list()
  folder = os.getcwd()
  while folder not in ( None, "", "/"):
    pathname = os.path.join(folder,name)
    if os.path.exists(pathname):
      files.append(pathname)
    folder = os.path.dirname(folder)
  return files

def get_gvspkg_bin_folder(): 
    files = list()
    files.append(os.path.join(os.environ['HOME'],".gvspkg.bin"))
    files.extend( acquire_file(".gvspkg.bin") )
    files.extend( acquire_file("gvspkg.bin") )
    debug( "gvspkg.bin = %s" % files[-1])
    return files[-1]

RWALL = stat.S_IWOTH | stat.S_IROTH | stat.S_IWUSR | stat.S_IRUSR | stat.S_IWGRP | stat.S_IRGRP 

VERSION = os.path.basename(os.getcwd())
GVSPKG_ROOT = get_gvspkg_bin_folder()

def getVersion():
    return VERSION

def getPackagesRoot():
    return GVSPKG_ROOT

def getPool():
    return getPackagesRoot() + "/pool"

def getWeb():
    return getPackagesRoot() + "/web"

def getDist():
    return getPackagesRoot() + "/dists/" +getVersion()

def findfiles(root,filename):
    result=list()
    for wroot, dirs, files in os.walk(root):
        for f in files :
            if fnmatch.fnmatch(f,filename):
                result.append(wroot+"/"+f)
    result.sort()
    return result

def mychmod(filename, perms):
    try:
        os.chmod(filename,perms)
    except Exception, ex:
        msgwarn("Can't change permissions of file '%s', error %s" % (filename, str(ex)))

class Command:

    def __init__(self, args):
        self.args = args
        self.defaultoptions = None

    def load_options(self,filename):
        debug("loading option from %s" % filename)
        if not os.path.isfile(filename):
            debug("filename %s not found" % filename)
            return
        f=file(filename,"r")
        for line in f.readlines():
            line = line.strip()
            if line=="" or line.startswith("#"):
                continue
            if line[-1] == "\n":
                line = line[:-1]
            n = line.find("=")
            if n<0 :
                continue
            cmd = line[:n]
            args = line[n+1:].strip()

            if args != "":
              self.defaultoptions[cmd] = self.defaultoptions.get(cmd,[]) +  args.split(" ")
            debug("add options: %s=%r" % (cmd, args.split(" ")))

        f.close()

    def load_default_options(self):
        if self.defaultoptions != None:
            return
        self.defaultoptions = dict()
        options = list();
        rootoptions = os.path.join(GVSPKG_ROOT,"options")
        if os.path.isfile(rootoptions):
            options.append(rootoptions)
        else:
            options.append("~/.gvspkg.bin/options")
        options.extend(acquire_file(".gvspkg.options"))
        options.extend(acquire_file("gvspkg.options"))
        for optionfile in options:
          self.load_options(optionfile)

    def getArgs(self,name):
        self.load_default_options()
        l = list()
        cmd = self.defaultoptions.get(name,None)
        if cmd != None:
          l.extend(cmd)
        l.extend(self.args[1:])
        return l

class PackageInfo(str):
    def __init__(self, filename):
        self._ini = None
        self.filename = filename[:-7]
        self.type = filename[-6:]
        s = os.path.basename(self.filename)
        s = s.split("-")
        #print "## PackageInfo ", repr(s)
        self.gvsig = s[0] + "-" + s[1]
        self.gvsig_version = s[2]
        self.code = s[3]
        try:
            if s[5] == 'SNAPSHOT':
                self.version = s[4] + "-" + s[5]
                self.build = s[6]
                self.status = s[7]
                self.os = s[8]
                self.arch = s[9]
            else:
                self.version = s[4]
                self.build = s[5]
                self.status = s[6]
                self.os = s[7]
                self.arch = s[8]
        except Exception:
            self.build = "0"
            self.status = "unknow"
            self.os = "all"
            self.arch = "all"
	try:
	    self.build = int(self.build)
	except:
	    pass

    def getCode(self):
        return self.code

    def getKey(self):
        return self.code+"-"+self.os+"-"+self.arch

    def getFullName(self):
        return os.path.basename(self.filename)

    def getFullVersion(self):
        return "%s-%06d" %(self.version,self.build)

    def getFilename(self):
        return self.filename + "." + self.type

    def hasPki(self):
        return os.path.isfile( self.getPkiFilename() )

    def getPkiFilename(self):
        return self.filename + ".gvspki"

    def hasPkg(self):
        return os.path.isfile( self.getPkgFilename() )

    def getPkgFilename(self):
        return self.filename + ".gvspkg"

    def getIniOption(self, name, default=None):
      section = "general"
      ini = self.getIni()
      if ini.has_option(section, name):
        x = ini.get(section, name)
	x = x.replace("\\:", ":")
        return x 
      return default 
    
    def getDescription(self):
      return self.getIniOption("description")

    def getName(self):
      return self.getIniOption("name")

    def getOwner(self):
      ini = self.getIni()
      if ini.has_option("general","owner"):
        return ini.get("general","owner")
      return None

    def getUrl(self):
      ini = self.getIni()
      if ini.has_option("general","download-url"):
        return ini.get("general","download-url")
      return None

    def getSourceUrl(self):
      ini = self.getIni()
      if ini.has_option("general","source-url"):
        return ini.get("general","source-url")
      return None

    def getDependencies(self):
      ini = self.getIni()
      if ini.has_option("general","dependencies"):
        return ini.get("general","dependencies")
      return None

    def getType(self):
      ini = self.getIni()
      if ini.has_option("general","type"):
        return ini.get("general","type")
      return None

    def getOfficial(self):
      ini = self.getIni()
      if ini.has_option("general","official"):
        return ini.get("general","official")
      return None

    def getIni(self):
        if self._ini != None:
          return self._ini
        index_path = self.getPkiFilename()
        outputfolder="/tmp/gvspkg.%s" % os.getpid()
        os.mkdir(outputfolder)
        os.system('unzip -q %s -d %s' % (index_path,outputfolder))

        files = findfiles(outputfolder, "package.info")
        if len(files) != 1:
            msgerror("Can't locate package.info in pool '%s'." % (index_name))
            return None

        package_info = files[0]
        self._ini = ConfigParser.ConfigParser()
        f = file(package_info,"r")
        ss = f.read()
        self._ini.readfp(StringIO.StringIO("[general]\n"+ss))
        f.close()
        shutil.rmtree(outputfolder)
        return self._ini

    def __str__(self):
        return self.filename

    def __repr__(self):
        return "filename=%r:gvsig=%r:gvsig_version=%r:code=%r:version=%r:build=%r:status=%r" % (
                self.filename, self.gvsig, self.gvsig_version, self.code, self.version, self.build, self.status )

class IndexList(list):

    def load(self, fname):
        message( "Loading index list from '%s'." % fname)
        f=file(fname,"r")
        lines=f.readlines()
        f.close()
        for line in lines:
          if line[-1] == "\n":
            line = line[:-1]
          
          info = PackageInfo(line)
          self.append(info)

    def save(self,fname):
        message( "Saving index list from '%s'." % fname)
        f=file(fname,"w")
        for index in self:
          f.write("%s\n" % index.getFilename())
        f.close()
        mychmod(fname,RWALL)

    def build(self, pool, version):
        message( "Creating index list for version '%s' from '%s'" % (version, pool) )
        packages=dict()
        for root, dirs, files in os.walk(pool):
            for f in files :
                fullpath = root+"/"+f
                info = PackageInfo(fullpath)
                if info.gvsig == "gvSIG-desktop" and info.gvsig_version == version :
                    if packages.get(info.getKey()) == None:
                        debug( "build: add    " + repr(info))
                        packages[info.getKey()]=info
                    else:
                        oldinfo = packages[info.getKey()]
                        debug("build: %s %s %s" % ( info.getKey(), oldinfo.getFullVersion(),info.getFullVersion()))
                        if oldinfo.getFullVersion()<info.getFullVersion()  :
                            debug( "build: update "+ repr(oldinfo))
                            packages[info.getKey()]=info
                else:
                    debug( "build: skip   "+ repr(info))
        self.extend(packages.values())
        self.sort()

def lsi(args):
    cmd = Command(args)
    try:
        opts, args = getopt.getopt(cmd.getArgs("lsi"), "l", ["long-format"])
    except getopt.GetoptError, err:
        # print help information and exit:
        print str(err) # will print something like "option -a not recognized"
        help(args)
        sys.exit(2)

    long_format=False
    for opt, arg in opts:
        if opt in ("-l", "--long-format"):
            long_format = True
        else:
            assert False, "unhandled option"

    indexes = IndexList()
    indexes.build(getPool(), getVersion())

    for info in indexes:
        if info.hasPki():
            if long_format:
                print "["+os.path.basename(info.getPkiFilename())+"]"
                print "# ", info.getPkiFilename()
                show(["show", os.path.basename(info.getPkiFilename())])
            else:
                print info.getPkiFilename()

def installkit_add(cmd,arg1,arg2):

    folder = "%s/gvspkg.bin" % os.path.dirname(sys.argv[0])

    cmd = "%s/installkit %s/main.tcl %s %s %s" % (
        folder,
        folder,
        cmd,
        arg1,
        arg2
    )
    system(cmd)

def mkinstall(args):
    cmd = Command(args)
    try:
        opts, args = getopt.getopt(cmd.getArgs("mkinstall"), "N:lL:wW:", ["addjrewin", "addjrelin", "jrelin=", "jrewin=", "distribution-name="])
    except getopt.GetoptError, err:
        # print help information and exit:
        print str(err) # will print something like "option -a not recognized"
        help(args)
        sys.exit(2)

    #print "opts = ",opts
    #print "args = ",args
    addjrelin=False
    addjrewin=False
    jrelin=None
    jrewin=None
    distribution_name = "custom"
    for opt, arg in opts:
        if opt in ("-L", "--jrelin"):
            jrelin = arg
        elif opt in ("-W", "--jrewin"):
            jrewin = arg
        elif opt in ("-l", "--addjrelin"):
            addjrelin = True
        elif opt in ("-w", "--addjrewin"):
            addjrewin = True
        elif opt in ("-N", "--distrinution-name"):
            distribution_name = arg
        else:
            assert False, "unhandled option"
    

    if len(args) != 2 :
        help(args)
        sys.exit(4)

    bin_name = args[0]
    gvspks_name = args[1]
    custom_name = bin_name.replace("online", distribution_name)

    if not "online" in bin_name :
        print "gvspkg mkinstall: binary file name must contain 'online'"
        sys.exit(3)

    if addjrelin and addjrewin :
        print "gvspkg mkinstall: only one of addjrelin or addjrewin is allowed."
        sys.exit(4)

    message("Creando %s..." % custom_name)
    shutil.copyfile(bin_name, custom_name)
    mychmod(custom_name,RWALL)
    message("Añadiendo %s..." % gvspks_name)
    installkit_add("addpks", custom_name, gvspks_name)

    if addjrelin:
        withjre_name = bin_name.replace("online", "standard-withjre")
        message("Creando %s..." % withjre_name)
        shutil.copyfile(custom_name, withjre_name)
        mychmod(withjre_name,RWALL)
        message("Añadiendo %s..." % jrelin)
        installkit_add("addjrelin", withjre_name, jrelin)


    if addjrewin:
        withjre_name = bin_name.replace("online", "standard-withjre")
        message("Creando %s..." % withjre_name)
        shutil.copyfile(custom_name, withjre_name)
        mychmod(withjre_name,RWALL)
        message("Añadiendo %s..." % jrewin)
        installkit_add("addjrewin", withjre_name, jrewin)


def mks(args):
    cmd = Command(args)
    message(cmd.getArgs("mks")) 
    try:
        opts, args = getopt.getopt(cmd.getArgs("mks"), "ixscI:", ["index-only","include-default-selection", "clear-list", "exclude=", "excludepki=", "excludepkg=", "include="])
    except getopt.GetoptError, err:
        # print help information and exit:
        print str(err) # will print something like "option -a not recognized"
        help(args)
        sys.exit(2)

    default_selection = None
    index_only = False
    clear_list=False
    includes=list()
    excludes_pki=list()
    excludes_pkg=list()
    for opt, arg in opts:
        if opt in ("-c", "--clear-list"):
            clear_list = True
        elif opt in ("-s", "--include-default-selection"):
            default_selection = "defaultPackages"
        elif opt in ("-x", "--exclude"):
            excludes_pki.append(arg)
            excludes_pkg.append(arg)
        elif opt in ( "--excludepki"):
            excludes_pki.append(arg)
        elif opt in ( "--excludepkg"):
            excludes_pkg.append(arg)
        elif opt in ( "--include", "-I"):
            includes.append(PackageInfo(arg))
        elif opt in ("-i", "--index-only"):
            index_only = True
        else:
            assert False, "unhandled option %r" % opt

    if default_selection!=None and  not os.path.isfile(default_selection) :
        msgwarn("No se ha encontrado el fichero %r. la opcion -s/--include-default-selection sera ignorada." % default_selection)
        default_selection = None

    indexes = IndexList()

    packages_txt = getDist() +"/packages.txt"
    packages_gvspki = getDist() +"/packages.gvspki"
    packages_gvspks = getDist() +"/packages.gvspks"

    message( "Creating 'packages.gvspki' for version '%s'" % getVersion() )
    if not os.path.exists(getDist()):
        msgerror("Can't locate version folder '%s'." % getDist())
        sys.exit(3)
   
    if os.path.exists(packages_txt) and not clear_list:
        indexes.load(packages_txt)
    else:
        indexes.build(getPool(), getVersion())
        indexes.save(packages_txt)

    for pkg in includes:
      indexes.append(pkg)

    message( "Writing 'packages.gvspki' to '%s'" % packages_gvspki )
    set = zipfile.ZipFile(packages_gvspki,"w",zipfile.ZIP_STORED)
    for info in indexes:
        if not ( info.code in excludes_pki or info.getFullName() in excludes_pki ):
            try:
                if info.hasPki() :
                    set.write(info.getPkiFilename(), os.path.basename(info.getPkiFilename()))
            except Exception, ex:
                msgerror("Can't add index '%s', error %s" % (info, str(ex)))
    if default_selection != None :
        set.write(default_selection,default_selection)
    set.close()
    mychmod(packages_gvspki,RWALL)

    if not index_only :
        message( "Writing 'packages.gvspks' to '%s'" % packages_gvspks )
        set = zipfile.ZipFile(packages_gvspks,"w",zipfile.ZIP_STORED)
        for info in indexes:
            if not ( info.code in excludes_pkg or info.getFullName() in excludes_pkg ):
                try:
                    if info.hasPkg():
                      set.write(info.getPkgFilename(), os.path.basename(info.getPkgFilename()))
                except Exception, ex:
                    msgerror("Can't add package '%s', error %s" % (index, str(ex)))
        if default_selection != None :
            set.write(default_selection,default_selection)
        set.close()
        mychmod(packages_gvspks,RWALL)

    message( "Created")


def mkhtml(args):
    def getCode(info):
      return info.code


    cmd = Command(args)
    try:
        opts, args = getopt.getopt(cmd.getArgs("mks"), "xsc", ["clear-list", "exclude=", "excludepki=", "excludepkg=", "include="])
    except getopt.GetoptError, err:
        # print help information and exit:
        print str(err) # will print something like "option -a not recognized"
        help(args)
        sys.exit(2)

    index_only = False
    clear_list=False
    includes=list()
    excludes_pki=list()
    excludes_pkg=list()
    for opt, arg in opts:
        if opt in ("-c", "--clear-list"):
            clear_list = True
        elif opt in ("-x", "--exclude"):
            excludes_pki.append(arg)
            excludes_pkg.append(arg)
        elif opt in ( "--excludepki"):
            excludes_pki.append(arg)
        elif opt in ( "--excludepkg"):
            excludes_pkg.append(arg)
        elif opt in ( "--include", "-I"):
            includes.append(PackageInfo(arg))
        else:
            assert False, "unhandled option %r" % opt

    indexes = IndexList()

    packages_txt = getDist() +"/packages.txt"
   
    if os.path.exists(packages_txt) and not clear_list:
        indexes.load(packages_txt)
    else:
        indexes.build(getPool(), getVersion())
        indexes.save(packages_txt)

    for pkg in includes:
      indexes.append(pkg)

    allpackages = list()
    basepath = getWeb()
    for info in indexes:
        if not ( info.code in excludes_pki or info.getFullName() in excludes_pki ):
            try:
                if info.hasPki() :
                    mkpkihtml(basepath, info)
                    allpackages.append(info)
            except Exception, ex:
                msgerror("Can't create html '%s', error %s" % (info, str(ex)))

    html = '''
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="Content-Type" content= "text/html; charset=us-ascii" />
      <title>"%s" package list</title>'''% getVersion() # Title

    html += '''  
<!-- estilos para las tablas -->
  <style type="text/css" title="currentStyle">
    @import "css/demo_table.css";
    @import "css/thickbox.css";
    #pkglist{
        width:100%;
        clear:both;
        font-family:Arial,Helvetica,sans-serif;
    }
    #pkgdetails{
        width:600px !important;
        clear:both;
    }
    #pkgdetails table th{
        text-algin:right;
    }
  </style>
</head>''' 

    html += '''
<body>
  <h1>%s package list</h1>
  <table id="pkglist" summary="%s package list" width="100%%" >
    <thead>
    <tr>
      <td>Package name</td>
      <td>Version</td>
      <td>O.S.</td>
      <td>Official</td>
      <td>Type</td>
      <td>Owner</td>
    </tr>
    </thead>
    <tbody>'''%(getVersion(),getVersion())

    # sort allpackages
    for item in sorted(allpackages, key=getCode):
      html += '''\n    <tr>
      <td><a class="thickbox" href="%s">%s</a></td>
      <td>%s</td>
      <td>%s</td>
      <td>%s</td>
      <td>%s</td>
      <td>%s</td>
    </tr>\n'''%(
	"../../../web/" + item.getFullName() + ".html?height=400&width=600",
        item.getName(),
	item.version,
	item.os,
	item.getOfficial(),
	item.getType(),
	item.getOwner()
      )
    html += """ </tbody>\n </table>
<!--javascript para la visualización de la tabla y carga dinámica del contenido del enlace -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js" type="text/javascript"></script>
<script src="http://datatables.net/release-datatables/media/js/jquery.dataTables.js" type="text/javascript"></script>
<script type="text/javascript" src="js/thickbox-compressed.js"></script>

<!-- inicialización de la tabla con cosas chachis -->
<script type="text/javascript">
  $(document).ready(function() {
      $('#pkglist').dataTable( {
      "bPaginate": false,
      "bLengthChange": true,
      "bFilter": true,
      "bSort": true,
      "bInfo": true,
      "bAutoWidth": true
    });
 } );
</script>
</body>
</html>"""

    # generate index.html
    try:
      f=file(getDist()+"/web/index.html","w")
      f.write(html)
      f.close()
    except Exception, ex:
      raise ex


def mkpkihtml(basepath, info):
  html='''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
  <title>%s</title>
  <!-- estilos para las tablas -->
  <style type="text/css" title="currentStyle">
    @import "../dists/%s/web/css/demo_table.css";
    #pkgdetails{
      width:600px;
      clear:both;
    }
    #pkgdetails table th{
        text-algin:right;
    }
  </style>
</head>
<body>\n'''%(info.getIniOption("name"), getVersion())
  html += '  <table id="pkgdetails" summary=%s >\n'%info.getIniOption("name")
  html += '    <thead>\n  <tr>\n  <th>%s </th>\n  <td>%s</td>\n  </tr>\n  </thead>\n'%("Name", info.getIniOption("name"))
  html += '    <tbody><tr><th>%s </th><td>%s</td></tr>\n'%("Code", info.code)
  html += '    <tr><th valing="top">%s </th><td>%s</td></tr>\n'%("Version", info.version)
  html += '    <tr><th valing="top">%s </th><td>%s</td></tr>\n'%("State", info.getIniOption("state"))
  html += '    <tr><th valing="top">%s </th><td>%s</td></tr>\n'%("Build", info.build)
  html += '    <tr><th valing="top">%s </th><td>%s</td></tr>\n'%("Owner", info.getOwner())

  #url = info.getUrl()
  url = info.getIniOption("download-url")
  if url != None:
    html += '    <tr><th valing="top">Downloads</th><td><a href ="%s">Binaries</a></td></tr>\n'%(url)
  else:
    html += '    <tr><th valing="top">Downloads</th><td>Binaries</td></tr>\n'

  sourceUrl = info.getSourceUrl()

  if sourceUrl != None:
    html += '    <tr><td></td><td><a href ="%s">Sources</a></td></tr>\n'%(sourceUrl)
  else:
    html += "    <tr><td></td><td>Sources</td></tr>\n"

  html += '    <tr><th valing="top">%s </th><td>%s</td></tr>\n'%("Dependencies", info.getDependencies().replace("\:",":"))
  html += '    <tr><th valing="top">%s </th><td>%s</td></tr>\n'%("Type", info.getType())
  html += '    <tr><th valing="top">%s </th><td>%s</td></tr>\n'%("Official", info.getOfficial())
  description = info.getDescription().replace("\\n", "<br>")
  description = description.replace("\:",":")
  html += '    <tr valing="top"><th valing="top">%s </th><td>%s</td></tr>\n'%("Description", description) 
  html += """  </tbody>\n</table>\n"""
  html += """ 
  <!-- javascript para la visualización de la tabla -->
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js" type="text/javascript"></script>
  <script src="http://datatables.net/release-datatables/media/js/jquery.dataTables.js" type="text/javascript"></script>
  <!-- inicialización de la tabla con cosas chachis -->
  <script type="text/javascript">
    $(document).ready(function() {
      $('#pkgdetails').dataTable( {
        "bPaginate": false,
        "bLengthChange": true,
        "bFilter": false,
        "bSort": false,
        "bInfo": false,
        "bAutoWidth": true
      });
    });
  </script>
  </body>\n</html>"""


  try:
    f = file(getWeb() + "/" + info.getFullName() + ".html","w")
    f.write(html)
    f.close()
  except Exception, ex:
    raise ex

def show(args):
    cmd = Command(args)
    try:
        opts, args = getopt.getopt(cmd.getArgs("show"), "S", [ "verify"])
    except getopt.GetoptError, err:
        # print help information and exit:
        print str(err) # will print something like "option -a not recognized"
        help(args)
        sys.exit(2)

    verify = False
    for opt, arg in opts:
        if opt in ("-V", "--verify"):
            verify = True
        else:
            assert False, "unhandled option %r" % opt

    index_name=args[0]
    message( "Show package.info from '%s'" % index_name)
    files = findfiles(getPool(), index_name)
    if len(files) != 1:
        msgerror("Can't locate package '%s' in pool '%s'." % (index_name, getPool()))
        return
    index_path = files[0]
    outputfolder="/tmp/gvspkg.%s" % os.getpid()
    os.mkdir(outputfolder)
    os.system('unzip -q %s -d %s' % (index_path,outputfolder))

    files = findfiles(outputfolder, "package.info")
    if len(files) != 1:
        msgerror("Can't locate package.info in pool '%s'." % (index_name))
        return

    package_info = files[0]
    f = file(package_info,"r")
    s = f.read()
    f.close()
    print s
    if verify:
      verify_sign(package_info)
    shutil.rmtree(outputfolder)

def editall(args):
    cmd = Command(args)
    try:  
        opts, args = getopt.getopt(cmd.getArgs("editall"), "Scx:I:r:", ["clear-list", "exclude=", "excludepki=", "excludepkg=", "include=", "replace=", "sign"])
    except getopt.GetoptError, err:
        # print help information and exit:
        print str(err) # will print something like "option -a not recognized"
        help(args)
        sys.exit(2)

    index_only = False
    clear_list=False
    includes=list()
    excludes_pki=list()
    replaces = list()
    excludes_pkg=list()
    sign = False
    interactive = True
    for opt, arg in opts:
        if opt in ("-c", "--clear-list"):
            clear_list = True
        elif opt in ("-x", "--exclude"):
            excludes_pki.append(arg)
            excludes_pkg.append(arg)
        elif opt in ( "--excludepki"):
            excludes_pki.append(arg)
        elif opt in ( "--excludepkg"):
            excludes_pkg.append(arg)
        elif opt in ( "--include", "-I"):
            includes.append(PackageInfo(arg))
        elif opt in ("-r", "--replace"):
            interactive = False
            replaces.append(arg)
        elif opt in ("-S", "--sign"):
            sign = True
        else:
            assert False, "unhandled option %r" % opt

    indexes = IndexList()

    packages_txt = getDist() +"/packages.txt"
    if os.path.exists(packages_txt) and not clear_list:
        indexes.load(packages_txt)
    else:
        indexes.build(getPool(), getVersion())
        indexes.save(packages_txt)

    for pkg in includes:
      indexes.append(pkg)

    allpackages = list()
    for info in indexes:
        if not ( info.code in excludes_pki or info.getFullName() in excludes_pki ):
            try:
                if info.hasPki() :
                  print info.getPkiFilename() 
                  if interactive :
                    edit_pkginfo_of_package(info.getPkiFilename(), edit_ui)
                  elif len(replaces) < 1:
                    edit_pkginfo_of_package(info.getPkiFilename(), edit_replace, replaces)

                  if sign:
                    edit_pkginfo_of_package(info.getPkiFilename(), edit_sign)

            except Exception, ex:
                msgerror("Can't add index '%s', error %s" % (info, str(ex)))

def edit(args):
    cmd = Command(args)
    try:
        opts, args = getopt.getopt(cmd.getArgs("edit"), "Sr:", [ "replace=", "onlysign", "sign" ])
    except getopt.GetoptError, err:
        # print help information and exit:
        print str(err) # will print something like "option -a not recognized"
        help(args)
        sys.exit(2)

    replaces = list()
    interactive = True
    sign = False
    for opt, arg in opts:
        if opt in ("-r", "--replace"):
            interactive = False
            replaces.append(arg)
        elif opt in ("--onlysign"):
            interactive = False
            sign = True
        elif opt in ("-S", "--sign"):
            sign = True
        else:
            assert False, "unhandled option %r" % opt

    index_name=args[0]
    message( "Show package.info from '%s'" % index_name)
    files = findfiles(getPool(), index_name)
    if len(files) != 1:
        msgerror("Can't locate package '%s' in pool '%s'." % (index_name, getPool()))
        return
    index_path = files[0]
    if interactive:
      edit_pkginfo_of_package(index_path, edit_ui)
    elif len(replaces) < 1:
      edit_pkginfo_of_package(index_path, edit_replace, replaces)

    if sign:
      edit_pkginfo_of_package(index_path, edit_sign)

def edit_ui(filename, args):
      os.system('vi "%s"' % filename)

def edit_replace(filename, args):
      replaces = args[0]
      f = open(filename)
      s = f.read()
      f.close()
      for replace in replaces:
        x = replace.split(replace[0])
        if len(x)==4:
          s=re.sub(x[1],x[2],s)
      f = open(filename,"w")
      f.write(s)
      f.close()

def edit_sign(filename, args):
      os.system('java -cp "%s/commons-codec-1.6.jar:%s/org.gvsig.installer.lib.impl-1.0.1-SNAPSHOT.jar" org.gvsig.installer.lib.impl.utils.SignUtil sign %s' %  (
        get_gvspkg_bin_folder(),
        get_gvspkg_bin_folder(),
        filename)
      )

def verify_sign(filename):
      os.system('java -cp "%s/commons-codec-1.6.jar:%s/org.gvsig.installer.lib.impl-1.0.1-SNAPSHOT.jar" org.gvsig.installer.lib.impl.utils.SignUtil verify %s' % (
        get_gvspkg_bin_folder(),
        get_gvspkg_bin_folder(),
        filename)
      )

def edit_pkginfo_of_package(pkg_path, operation, *args):
    outputfolder="/tmp/gvspkg.%s" % os.getpid()
    os.mkdir(outputfolder)
    os.system('unzip -q %s -d %s' % (pkg_path,outputfolder))

    files = findfiles(outputfolder, "package.info")
    if len(files) != 1:
        msgerror("Can't locate package.info in pool '%s'." % (pkg_path))
        return

    package_info = files[0]
    code = package_info.split("/")[-2]
    operation(package_info, args)

    # zip -Dr kk.zip org.gvsig.wfs
    temp_index_name = "/tmp/packages.gvspki.%s" % os.getpid()
    temp_index = zipfile.ZipFile(temp_index_name,"w",zipfile.ZIP_STORED)
    temp_index.write(package_info, "%s/package.info" % (code))
    temp_index.close()
    shutil.rmtree(outputfolder)
    os.remove(pkg_path)
    shutil.move(temp_index_name,pkg_path)

def install(args):
    cmd = Command(args)
    try:
        opts, args = getopt.getopt(cmd.getArgs("install"), "f", [ "force" ])
    except getopt.GetoptError, err:
        # print help information and exit:
        print str(err) # will print something like "option -a not recognized"
        help(args)
        sys.exit(2)

    force = False
    for opt, arg in opts:
        if opt in ("-f", "--force"):
            force = True
        else:
            assert False, "unhandled option %r" % opt

    url_pki = args[0]
    message( "Download package index '%s'" % url_pki)
    temppath_pki= os.path.join("/tmp",os.path.basename(url_pki))
    downloadFile(url_pki,temppath_pki)
    pkg = PackageInfo(temppath_pki)
    url_pkg = pkg.getUrl().replace("\\","")
    message( "Download package '%s'" % url_pkg)
    temppath_pkg= os.path.join("/tmp",os.path.basename(url_pkg))
    downloadFile(url_pkg,temppath_pkg)
    folder = os.path.join(getPool(),pkg.getCode())
    if not os.path.isdir(folder) :
        os.makedirs(folder)
    pathname_pki = os.path.join(folder,os.path.basename(url_pki))
    if not force and os.path.isfile(pathname_pki) :
        msgerror("Ya existe en el pool el fichero gvspki indicado.")
        return 1
    pathname_pkg = os.path.join(folder,os.path.basename(url_pkg))
    if  not force and os.path.isfile(pathname_pki) :
        msgerror("Ya existe en el pool el fichero gvspkg indicado.")
        return 1
    message( "installing package '%s'" % os.path.basename(pathname_pki))
    shutil.copyfile(temppath_pki, pathname_pki)
    message( "installing package '%s'" % os.path.basename(pathname_pkg))
    shutil.copyfile(temppath_pkg, pathname_pkg)



def downloadFile(url,path):
  fsrc = urllib2.urlopen(url)
  fdst = file(path,"wb")
  shutil.copyfileobj(fsrc,fdst)
  fdst.close()
  fsrc.close()


def help(args):
    print """
usage: gvspkg [OPTIONS] COMMANDS

OPTIONS:

-h|--help
    Muestra esta ayuda

-v|--verbose
    Activa el modo verbose

-d|--debug
    Activa el modo debug. Se muestran mensajes que pueden ser
    utilies de cara a depuracion.

--version version
    Fija la version con la que van a trabajar los comandos indicados.

-r|--package-root package-root
    Fija la carpeta en la que va a buscar el raiz del sistema de paquetes
    con el que trabajar
    
COMMANDS:

mkinstall [OPTIONS] install-file packages-file

    OPTIONS:

    -L | --jrelin=path

    -W | --jrewin=path

    -l | --addjrelin

    -w | --addjrewin
    
    -N | --distribution-name=name

      Nombre usado como sufijo del nuevo binario a generar. Por defecto si no se
      indica valdra "custom".


lsi [OPTIONS]
    Lista los indices disponibles de la version

    OPTIONS:

    -l | --long-format
        Muestra para cada paquete la informacion del package.info

mks [OPTIONS]
     Crea el fichero packages.gvspki con los indices de la
     version y packages.gvspkg con los paquetes.

     OPTIONS:

     -c | --clear-list
        Elimina la lista de paquetes a utilizar recreandola a partir
        de los paquetes del pool tomando el ultimo build de cada paquete.

     --excludepkg pkgcode
        No incluye el paquete indicado en el fichero gvspkg a generar

     --excludepki pkgcode
        No incluye el paquete indicado en el fichero gvspki a generar

     --exclude pkgcode
        No incluye el paquete indicado en los ficheros gvspkg y gvspki a generar

     -s | --include-default-selection
        Incluye el fichero "defaultPackages", que se debe encontrar en el
        directorio corriente, con los nombres de paquetes a seleccionar
        por defecto.

     -i | --index-only
        No crea el fichero gvspks, solo crea el gvspki

     -I full-path-to-package | --include full-path-to-package 
        Añade el paquete indicado a la lista de paquetes aunque no coincida para 
        la version de gvSIG con la que se esta trabajando.

mkhtml [OPTIONS]
     ????

     OPTIONS:

     -c | --clear-list
        Elimina la lista de paquetes a utilizar recreandola a partir
        de los paquetes del pool tomando el ultimo build de cada paquete.

     --excludepkg pkgcode
        No incluye el paquete indicado en el fichero gvspkg a generar

     --excludepki pkgcode
        No incluye el paquete indicado en el fichero gvspki a generar

     --exclude pkgcode
        No incluye el paquete indicado en los ficheros gvspkg y gvspki a generar

show OPTIONS package-index
    Muestra el package.info del indice indicado como parametro.

    OPTIONS

    --verify | -V
      Comprueba la forma del packete.

edit [OPTIONS] package-index
    Edita el package.info del indice indicado como parametro.

     OPTIONS:

     --replace=@search@replace@
       Reemplaza en el package.info de cada paquete la cadena "search" por "replace"
       todas las veces que aparezca. "@" puede ser cualquier caracter que no aparezca
       en "search" y "replace".
       Esta opcion puede indicarse tatas veces como reemplazos se deseen efectuar.

     --onlysign
       firma el package.info sin editarlo de forma interactiva (no invoca al editor antes 
       de firmarlo).

     --sign | -S
       Firma el package.info tras terminar la edicion (bach o interactiva)

editall [OPTIONS]
    Edita todos los package.info 

     OPTIONS:

     -c | --clear-list
        Elimina la lista de paquetes a utilizar recreandola a partir
        de los paquetes del pool tomando el ultimo build de cada paquete.

     --excludepkg pkgcode
        No incluye el paquete indicado en el fichero gvspkg a generar

     --excludepki pkgcode
        No incluye el paquete indicado en el fichero gvspki a generar

     --exclude pkgcode
        No incluye el paquete indicado en los ficheros gvspkg y gvspki a generar

     --replace=@search@replace@
       Reemplaza en el package.info de cada paquete la cadena "search" por "replace"
       todas las veces que aparezca. "@" puede ser cualquier caracter que no aparezca
       en "search" y "replace".
       Esta opcion puede indicarse tatas veces como reemplazos se deseen efectuar.

      --sign | -S
        Firma todos los paquetes que sean oficiales

install [OPTIONS] url-to-pki
    descarga de la url indicada un fichero gvspki e instala este junto con su correspondiente
    pkg en el pool local.

     OPTIONS:

     -f | --force
       fuerza la sobreescritura de los ficheros en caso de que estos ya existan.

Si en la carpeta corriente encuentra un fichero gvspkg.options cargara los
flags indicados ahi como flags por defecto para cada comando. El formato del 
fichero es:
  main=OPCION-POR-DEFECTO
  mks=OPCOPNES-POR-DEFECTO
Donde main indica las opciones por defecto generales, independientes del comando
a ejecutar. "mks" indica las opciones por defecto a usar en el comando "mks", y 
asi sucesivamente, indicando el nombre del comando seguido de un "=" y las opciones
por defecto para ese comando.

Por defecto la version la obtiene del nombre de la carpeta 
corriente (%s). Las opciones indicadas en el fichero gvspkg.options tienen prioridad
sobre este valor.

El directorio root de la estructura de packetes lo buscara en el
sitio indicado por la variable de entorno GVPKG_ROOT, y si esta no
esta establecida usara "%s". Las opciones indicadas en el fichero gvspkg.options 
tienen prioridad sobre este valor.

    """ % (VERSION, GVSPKG_ROOT)

def main():
    global VERSION
    global VERBOSE
    global GVSPKG_ROOT

    cmd = Command(sys.argv)
    try:
        opts, args = getopt.getopt(cmd.getArgs("main"), "dhvr:", ["debug", "verbose", "version=", "package-root=","help"])
    except getopt.GetoptError, err:
        # print help information and exit:
        print str(err) # will print something like "option -a not recognized"
        help(None)
        sys.exit(2)

    for opt, arg in opts:
        if opt in ("-h", "--help"):
            help(args)
            sys.exit()
        elif opt in ("-d", "--debug"):
            DEBUG = True
        elif opt in ("-v", "--verbose"):
            VERBOSE = True
        elif opt in ("--version"):
            VERSION = arg
        elif opt in ("-r", "--package-root"):
            GVSPKG_ROOT = arg
        else:
            assert False, "unhandled option"
    # 
    message("VERSION=%s" % VERSION)
    message("GVSPKG_ROOT=%s" % GVSPKG_ROOT)

    command = "help"
    if len(args)>0:
        command=args[0]

    if command=="lsi" :
        lsi(args)
    elif command == "mks":
        mks(args)
    elif command == "edit":
        edit(args)
    elif command == "editall":
        editall(args)
    elif command == "show":
        show(args)
    elif command == "mkhtml":
        mkhtml(args)
    elif command == "mkinstall":
        mkinstall(args)
    elif command == "install":
        install(args)
    else:
        help(args)


main()

