701 lines
24 KiB
Python
Executable File
701 lines
24 KiB
Python
Executable File
#!/usr/bin/env python
|
|
"""\
|
|
@file install.py
|
|
@author Phoenix
|
|
@date 2008-01-27
|
|
@brief Install files into an indra checkout.
|
|
|
|
Install files as specified by:
|
|
https://wiki.lindenlab.com/wiki/User:Phoenix/Library_Installation
|
|
|
|
|
|
$LicenseInfo:firstyear=2007&license=mit$
|
|
|
|
Copyright (c) 2007, Linden Research, Inc.
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
in the Software without restriction, including without limitation the rights
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
THE SOFTWARE.
|
|
$/LicenseInfo$
|
|
"""
|
|
|
|
import copy
|
|
import errno
|
|
import md5
|
|
import optparse
|
|
import os
|
|
import pprint
|
|
import sys
|
|
import tarfile
|
|
import urllib
|
|
import urlparse
|
|
|
|
from sets import Set as set, ImmutableSet as frozenset
|
|
|
|
# Locate -our- python library relative to our install location.
|
|
from os.path import realpath, dirname, join
|
|
|
|
# Walk back to checkout base directory
|
|
base_dir = dirname(dirname(realpath(__file__)))
|
|
# Walk in to libraries directory
|
|
lib_dir = join(join(join(base_dir, 'indra'), 'lib'), 'python')
|
|
|
|
if lib_dir not in sys.path:
|
|
sys.path.insert(0, lib_dir)
|
|
|
|
from indra.base import llsd
|
|
from indra.util import helpformatter
|
|
|
|
class InstallFile(object):
|
|
"This is just a handy way to throw around details on a file in memory."
|
|
def __init__(self, pkgname, url, md5sum, cache_dir, platform_path):
|
|
self.pkgname = pkgname
|
|
self.url = url
|
|
self.md5sum = md5sum
|
|
filename = urlparse.urlparse(url)[2].split('/')[-1]
|
|
self.filename = os.path.join(cache_dir, filename)
|
|
self.platform_path = platform_path
|
|
|
|
def __str__(self):
|
|
return "ifile{%s:%s}" % (self.pkgname, self.url)
|
|
|
|
def _is_md5_match(self):
|
|
hasher = md5.new(file(self.filename).read())
|
|
if hasher.hexdigest() == self.md5sum:
|
|
return True
|
|
return False
|
|
|
|
def is_match(self, platform):
|
|
"""@brief Test to see if this ifile is part of platform
|
|
@param platform The target platform. Eg, win32 or linux/i686/gcc/3.3
|
|
@return Returns True if the ifile is in the platform.
|
|
"""
|
|
if self.platform_path == 'common':
|
|
return True
|
|
req_platform_path = platform.split('/')
|
|
#print "platform:",req_platform_path
|
|
#print "path:",self.platform_path
|
|
# to match, every path part much match
|
|
match_count = min(len(req_platform_path), len(self.platform_path))
|
|
for ii in range(0, match_count):
|
|
if req_platform_path[ii] != self.platform_path[ii]:
|
|
return False
|
|
#print "match!"
|
|
return True
|
|
|
|
|
|
def fetch_local(self):
|
|
print "Looking for:",self.filename
|
|
if not os.path.exists(self.filename):
|
|
print "not there -- fetching"
|
|
elif self.md5sum and not self._is_md5_match():
|
|
print "Found, but md5 does not match."
|
|
os.remove(self.filename)
|
|
else:
|
|
print "Found matching package"
|
|
return
|
|
print "Downloading",self.url,"to local file",self.filename
|
|
urllib.urlretrieve(self.url, self.filename)
|
|
if self.md5sum and not self._is_md5_match():
|
|
raise RuntimeError("Error matching md5 for %s" % self.url)
|
|
|
|
class LicenseDefinition(object):
|
|
def __init__(self, definition):
|
|
#probably looks like:
|
|
# { text : ...,
|
|
# url : ...
|
|
# blessed : ...
|
|
# }
|
|
self._definition = definition
|
|
|
|
|
|
class BinaryDefinition(object):
|
|
def __init__(self, definition):
|
|
#probably looks like:
|
|
# { packages : {platform...},
|
|
# copyright : ...
|
|
# license : ...
|
|
# description: ...
|
|
# }
|
|
self._definition = definition
|
|
|
|
def _ifiles_from(self, tree, pkgname, cache_dir):
|
|
return self._ifiles_from_path(tree, pkgname, cache_dir, [])
|
|
|
|
def _ifiles_from_path(self, tree, pkgname, cache_dir, path):
|
|
ifiles = []
|
|
if tree.has_key('url'):
|
|
ifiles.append(InstallFile(
|
|
pkgname,
|
|
tree['url'],
|
|
tree.get('md5sum', None),
|
|
cache_dir,
|
|
path))
|
|
else:
|
|
for key in tree:
|
|
platform_path = copy.copy(path)
|
|
platform_path.append(key)
|
|
ifiles.extend(
|
|
self._ifiles_from_path(
|
|
tree[key],
|
|
pkgname,
|
|
cache_dir,
|
|
platform_path))
|
|
return ifiles
|
|
|
|
def ifiles(self, pkgname, platform, cache_dir):
|
|
"""@brief return a list of appropriate InstallFile instances to install
|
|
@param pkgname The name of the package to be installed, eg 'tut'
|
|
@param platform The target platform. Eg, win32 or linux/i686/gcc/3.3
|
|
@param cache_dir The directory to cache downloads.
|
|
@return Returns a list of InstallFiles which are part of this install
|
|
"""
|
|
if 'packages' not in self._definition:
|
|
return []
|
|
all_ifiles = self._ifiles_from(
|
|
self._definition['packages'],
|
|
pkgname,
|
|
cache_dir)
|
|
if platform == 'all':
|
|
return all_ifiles
|
|
return [ifile for ifile in all_ifiles if ifile.is_match(platform)]
|
|
|
|
class InstalledPackage(object):
|
|
def __init__(self, definition):
|
|
# looks like:
|
|
# { url1 : [file1,file2,...],
|
|
# url2 : [file1,file2,...],...
|
|
# }
|
|
self._installed = {}
|
|
for url in definition:
|
|
self._installed[url] = definition[url]
|
|
|
|
def urls(self):
|
|
return self._installed.keys()
|
|
|
|
def files_in(self, url):
|
|
return self._installed[url]
|
|
|
|
def remove(self, url):
|
|
self._installed.pop(url)
|
|
|
|
def add_files(self, url, files):
|
|
self._installed[url] = files
|
|
|
|
class Installer(object):
|
|
def __init__(self, install_filename, installed_filename, dryrun):
|
|
self._install_filename = install_filename
|
|
self._install_changed = False
|
|
self._installed_filename = installed_filename
|
|
self._installed_changed = False
|
|
self._dryrun = dryrun
|
|
self._binaries = {}
|
|
self._licenses = {}
|
|
self._installed = {}
|
|
self.load()
|
|
|
|
def load(self):
|
|
if os.path.exists(self._install_filename):
|
|
install = llsd.parse(file(self._install_filename).read())
|
|
try:
|
|
for name in install['binaries']:
|
|
self._binaries[name] = BinaryDefinition(
|
|
install['binaries'][name])
|
|
except KeyError:
|
|
pass
|
|
try:
|
|
for name in install['licenses']:
|
|
self._licenses[name] = LicenseDefinition(install['licenses'][name])
|
|
except KeyError:
|
|
pass
|
|
if os.path.exists(self._installed_filename):
|
|
installed = llsd.parse(file(self._installed_filename).read())
|
|
try:
|
|
bins = installed['binaries']
|
|
for name in bins:
|
|
self._installed[name] = InstalledPackage(bins[name])
|
|
except KeyError:
|
|
pass
|
|
|
|
def _write(self, filename, state):
|
|
print "Writing state to",filename
|
|
if not self._dryrun:
|
|
file(filename, 'w').write(llsd.format_xml(state))
|
|
|
|
def save(self):
|
|
if self._install_changed:
|
|
state = {}
|
|
state['licenses'] = {}
|
|
for name in self._licenses:
|
|
state['licenses'][name] = self._licenses[name]._definition
|
|
#print "self._binaries:",self._binaries
|
|
state['binaries'] = {}
|
|
for name in self._binaries:
|
|
state['binaries'][name] = self._binaries[name]._definition
|
|
self._write(self._install_filename, state)
|
|
if self._installed_changed:
|
|
state = {}
|
|
state['binaries'] = {}
|
|
bin = state['binaries']
|
|
for name in self._installed:
|
|
#print "installed:",name,self._installed[name]._installed
|
|
bin[name] = self._installed[name]._installed
|
|
self._write(self._installed_filename, state)
|
|
|
|
def is_license_info_valid(self):
|
|
valid = True
|
|
for bin in self._binaries:
|
|
binary = self._binaries[bin]._definition
|
|
if not binary.has_key('license'):
|
|
valid = False
|
|
print >>sys.stderr, "No license info for binary", bin + '.'
|
|
continue
|
|
if binary['license'] not in self._licenses:
|
|
valid = False
|
|
lic = binary['license']
|
|
print >>sys.stderr, "Missing license info for '" + lic + "'",
|
|
print >>sys.stderr, 'in binary', bin + '.'
|
|
return valid
|
|
|
|
def detail_binary(self, name):
|
|
"Return a binary definition detail"
|
|
try:
|
|
detail = self._binaries[name]._definition
|
|
return detail
|
|
except KeyError:
|
|
return None
|
|
|
|
def _update_field(self, binary, field):
|
|
"""Given a block and a field name, add or update it.
|
|
@param binary[in,out] a dict containing all the details about a binary.
|
|
@param field the name of the field to update.
|
|
"""
|
|
if binary.has_key(field):
|
|
print "Update value for '" + field + "'"
|
|
print "(Leave blank to keep current value)"
|
|
print "Current Value: '" + binary[field] + "'"
|
|
else:
|
|
print "Specify value for '" + field + "'"
|
|
value = raw_input("Enter New Value: ")
|
|
if binary.has_key(field) and not value:
|
|
pass
|
|
elif value:
|
|
binary[field] = value
|
|
|
|
def _add_package(self, binary):
|
|
"""Add an url for a platform path to the binary.
|
|
@param binary[in,out] a dict containing all the details about a binary."""
|
|
print """\
|
|
Please enter a new package location and url. Some examples:
|
|
common -- specify a package for all platforms
|
|
linux -- specify a package for all arch and compilers on linux
|
|
darwin/universal -- specify a mac os x universal
|
|
win32/i686/vs/2003 -- specify a windows visual studio 2003 package"""
|
|
target = raw_input("Package path: ")
|
|
url = raw_input("Package URL: ")
|
|
md5sum = raw_input("Package md5: ")
|
|
path = target.split('/')
|
|
if not binary.has_key('packages'):
|
|
binary['packages'] = {}
|
|
update = binary['packages']
|
|
for child in path:
|
|
if not update.has_key(child):
|
|
update[child] = {}
|
|
parent = update
|
|
update = update[child]
|
|
parent[child]['url'] = llsd.uri(url)
|
|
parent[child]['md5sum'] = md5sum
|
|
|
|
def adopt_binary(self, name):
|
|
"Interactively pull a new binary into the install"
|
|
if not self._binaries.has_key(name):
|
|
print "Adding binary '" + name + "'."
|
|
self._binaries[name] = BinaryDefinition({})
|
|
else:
|
|
print "Updating binary '" + name + "'."
|
|
binary = self._binaries[name]._definition
|
|
for field in ('copyright', 'license', 'description'):
|
|
self._update_field(binary, field)
|
|
self._add_package(binary)
|
|
print "Adopted binary '" + name + "':"
|
|
pprint.pprint(self._binaries[name])
|
|
self._install_changed = True
|
|
return True
|
|
|
|
def orphan_binary(self, name):
|
|
self._binaries.pop(name)
|
|
self._install_changed = True
|
|
|
|
def add_license(self, name, text, url):
|
|
if self._licenses.has_key(name):
|
|
print "License '" + name + "' being overwritten."
|
|
definition = {}
|
|
if url:
|
|
definition['url'] = url
|
|
if not url and text is None:
|
|
print "Please enter license text. End input with EOF (^D)."
|
|
text = sys.stdin.read()
|
|
definition['text'] = text
|
|
self._licenses[name] = LicenseDefinition(definition)
|
|
self._install_changed = True
|
|
return True
|
|
|
|
def remove_license(self, name):
|
|
self._licenses.pop(name)
|
|
self._install_changed = True
|
|
|
|
def _determine_install_set(self, ifiles):
|
|
"""@brief determine what to install
|
|
@param ifiles A list of InstallFile instances which are necessary for this install
|
|
@return Returns the tuple (ifiles to install, ifiles to remove)"""
|
|
installed_list = []
|
|
for package in self._installed:
|
|
installed_list.extend(self._installed[package].urls())
|
|
installed_set = set(installed_list)
|
|
#print "installed_set:",installed_set
|
|
install_list = [ifile.url for ifile in ifiles]
|
|
install_set = set(install_list)
|
|
#print "install_set:",install_set
|
|
remove_set = installed_set.difference(install_set)
|
|
to_remove = [ifile for ifile in ifiles if ifile.url in remove_set]
|
|
#print "to_remove:",to_remove
|
|
install_set = install_set.difference(installed_set)
|
|
to_install = [ifile for ifile in ifiles if ifile.url in install_set]
|
|
#print "to_install:",to_install
|
|
return to_install, to_remove
|
|
|
|
def _build_ifiles(self, platform, cache_dir):
|
|
"""@brief determine what files to install and remove
|
|
@param platform The target platform. Eg, win32 or linux/i686/gcc/3.3
|
|
@param cache_dir The directory to cache downloads.
|
|
@return Returns the tuple (ifiles to install, ifiles to remove)"""
|
|
ifiles = []
|
|
for bin in self._binaries:
|
|
ifiles.extend(self._binaries[bin].ifiles(bin, platform, cache_dir))
|
|
return self._determine_install_set(ifiles)
|
|
|
|
def _remove(self, to_remove):
|
|
remove_file_list = []
|
|
for ifile in to_remove:
|
|
remove_file_list.extend(
|
|
self._installed[ifile.pkgname].files_in(ifile.url))
|
|
self._installed[ifile.pkgname].remove(ifile.url)
|
|
self._installed_changed = True
|
|
for filename in remove_file_list:
|
|
print "rm",filename
|
|
if not self._dryrun:
|
|
os.remove(filename)
|
|
|
|
def _install(self, to_install, install_dir):
|
|
for ifile in to_install:
|
|
tar = tarfile.open(ifile.filename, 'r')
|
|
print "Extracting",ifile.filename,"to destination",install_dir
|
|
if not self._dryrun:
|
|
# *NOTE: try to call extractall, which first appears
|
|
# in python 2.5. Phoenix 2008-01-28
|
|
try:
|
|
tar.extractall(path=install_dir)
|
|
except AttributeError:
|
|
_extractall(tar, path=install_dir)
|
|
if self._installed.has_key(ifile.pkgname):
|
|
self._installed[ifile.pkgname].add_files(ifile.url, tar.getnames())
|
|
else:
|
|
# *HACK: this understands the installed package syntax.
|
|
definition = { ifile.url : tar.getnames() }
|
|
self._installed[ifile.pkgname] = InstalledPackage(definition)
|
|
self._installed_changed = True
|
|
|
|
def do_install(self, platform, install_dir, cache_dir):
|
|
"""@brief Do the installation for for the platform.
|
|
@param platform The target platform. Eg, win32 or linux/i686/gcc/3.3
|
|
@param install_dir The root directory to install into. Created if missing.
|
|
@param cache_dir The directory to cache downloads. Created if missing."""
|
|
if not self._binaries:
|
|
raise RuntimeError("No binaries to install. Please add them.")
|
|
_mkdir(install_dir)
|
|
_mkdir(cache_dir)
|
|
to_install, to_remove = self._build_ifiles(platform, cache_dir)
|
|
|
|
# we do this in multiple steps reduce the likelyhood to have a
|
|
# bad install.
|
|
for ifile in to_install:
|
|
ifile.fetch_local()
|
|
self._remove(to_remove)
|
|
self._install(to_install, install_dir)
|
|
|
|
|
|
#
|
|
# *NOTE: PULLED FROM PYTHON 2.5 tarfile.py Phoenix 2008-01-28
|
|
#
|
|
def _extractall(tar, path=".", members=None):
|
|
"""Extract all members from the archive to the current working
|
|
directory and set owner, modification time and permissions on
|
|
directories afterwards. `path' specifies a different directory
|
|
to extract to. `members' is optional and must be a subset of the
|
|
list returned by getmembers().
|
|
"""
|
|
directories = []
|
|
|
|
if members is None:
|
|
members = tar
|
|
|
|
for tarinfo in members:
|
|
if tarinfo.isdir():
|
|
# Extract directory with a safe mode, so that
|
|
# all files below can be extracted as well.
|
|
try:
|
|
os.makedirs(os.path.join(path, tarinfo.name), 0777)
|
|
except EnvironmentError:
|
|
pass
|
|
directories.append(tarinfo)
|
|
else:
|
|
tar.extract(tarinfo, path)
|
|
|
|
# Reverse sort directories.
|
|
directories.sort(lambda a, b: cmp(a.name, b.name))
|
|
directories.reverse()
|
|
|
|
# Set correct owner, mtime and filemode on directories.
|
|
for tarinfo in directories:
|
|
path = os.path.join(path, tarinfo.name)
|
|
try:
|
|
tar.chown(tarinfo, path)
|
|
tar.utime(tarinfo, path)
|
|
tar.chmod(tarinfo, path)
|
|
except tarfile.ExtractError, e:
|
|
if tar.errorlevel > 1:
|
|
raise
|
|
else:
|
|
tar._dbg(1, "tarfile: %s" % e)
|
|
|
|
|
|
def _mkdir(directory):
|
|
"Safe, repeatable way to make a directory."
|
|
try:
|
|
os.makedirs(directory)
|
|
except OSError, e:
|
|
if e[0] != errno.EEXIST:
|
|
raise
|
|
|
|
def _get_platform():
|
|
"Return appropriate platform packages for the environment."
|
|
platform_map = {
|
|
'darwin': 'darwin',
|
|
'linux2': 'linux',
|
|
'win32' : 'win32',
|
|
'cygwin' : 'win32',
|
|
'solaris' : 'solaris'
|
|
}
|
|
return platform_map[sys.platform]
|
|
|
|
def main():
|
|
parser = optparse.OptionParser(
|
|
usage="usage: %prog [options]",
|
|
formatter = helpformatter.Formatter(),
|
|
description="""This script fetches and installs binary packages.
|
|
|
|
The process is to open and read an install manifest file which specifies
|
|
what files should be installed. For each file in the manifest:
|
|
* make sure it has a license
|
|
* check the installed version
|
|
** if not installed and needs to be, download and install
|
|
** if installed version differs, download & install
|
|
|
|
When specifying a platform, you can specify 'all' to install all
|
|
packages, or any platform of the form:
|
|
|
|
OS[/arch[/compiler[/compiler_version]]]
|
|
|
|
Where the supported values for each are:
|
|
OS: darwin, linux, win32, solaris
|
|
arch: i686, x86_64, ppc, universal
|
|
compiler: vs, gcc
|
|
compiler_version: 2003, 2005, 2008, 3.3, 3.4, 4.0, etc.
|
|
|
|
No checks are made to ensure a valid combination of platform
|
|
parts. Some exmples of valid platforms:
|
|
|
|
win32
|
|
win32/i686/vs/2005
|
|
linux/x86_64/gcc/3.3
|
|
linux/x86_64/gcc/4.0
|
|
darwin/universal/gcc/4.0
|
|
""")
|
|
parser.add_option(
|
|
'--dry-run',
|
|
action='store_true',
|
|
default=False,
|
|
dest='dryrun',
|
|
help='Do not actually install files. Downloads will still happen.')
|
|
parser.add_option(
|
|
'--install-manifest',
|
|
type='string',
|
|
default=join(base_dir, 'install.xml'),
|
|
dest='install_filename',
|
|
help='The file used to describe what should be installed.')
|
|
parser.add_option(
|
|
'--installed-manifest',
|
|
type='string',
|
|
default=join(base_dir, 'installed.xml'),
|
|
dest='installed_filename',
|
|
help='The file used to record what is installed.')
|
|
parser.add_option(
|
|
'-p', '--platform',
|
|
type='string',
|
|
default=_get_platform(),
|
|
dest='platform',
|
|
help="""Override the automatically determined platform. \
|
|
You can specify 'all' to do a complete installation of all binaries.""")
|
|
parser.add_option(
|
|
'--cache-dir',
|
|
type='string',
|
|
default=join(base_dir, '.install.cache'),
|
|
dest='cache_dir',
|
|
help='Where to download files.')
|
|
parser.add_option(
|
|
'--install-dir',
|
|
type='string',
|
|
default=base_dir,
|
|
dest='install_dir',
|
|
help='Where to unpack the installed files.')
|
|
parser.add_option(
|
|
'--skip-license-check',
|
|
action='store_false',
|
|
default=True,
|
|
dest='check_license',
|
|
help="Do not perform the license check.")
|
|
parser.add_option(
|
|
'--add-license',
|
|
type='string',
|
|
default=None,
|
|
dest='new_license',
|
|
help="""Add a license to the install file. Argument is the name of \
|
|
license. Specify --license-url if the license is remote or specify \
|
|
--license-text, otherwse the license text will be read from standard \
|
|
input.""")
|
|
parser.add_option(
|
|
'--remove-license',
|
|
type='string',
|
|
default=None,
|
|
dest='remove_license',
|
|
help="Remove a named license.")
|
|
parser.add_option(
|
|
'--license-url',
|
|
type='string',
|
|
default=None,
|
|
dest='license_url',
|
|
help="""Put the specified url into an added license. \
|
|
Ignored if --add-license is not specified.""")
|
|
parser.add_option(
|
|
'--license-text',
|
|
type='string',
|
|
default=None,
|
|
dest='license_text',
|
|
help="""Put the text into an added license. \
|
|
Ignored if --add-license is not specified.""")
|
|
parser.add_option(
|
|
'--orphan',
|
|
type='string',
|
|
default=None,
|
|
dest='orphan',
|
|
help="Remove a binary from the install file.")
|
|
parser.add_option(
|
|
'--adopt',
|
|
type='string',
|
|
default=None,
|
|
dest='adopt',
|
|
help="""Add a binary into the install file. Argument is the name of \
|
|
the binary to add.""")
|
|
parser.add_option(
|
|
'--list',
|
|
action='store_true',
|
|
default=False,
|
|
dest='list_binaries',
|
|
help="List the binaries in the install manifest")
|
|
parser.add_option(
|
|
'--details',
|
|
type='string',
|
|
default=None,
|
|
dest='detail_binary',
|
|
help="Get detailed information on specified binary.")
|
|
options, args = parser.parse_args()
|
|
|
|
|
|
installer = Installer(
|
|
options.install_filename,
|
|
options.installed_filename,
|
|
options.dryrun)
|
|
|
|
#
|
|
# Handle the queries for information
|
|
#
|
|
if options.list_binaries:
|
|
print "binary list:",installer._binaries.keys()
|
|
return 0
|
|
if options.detail_binary:
|
|
detail = installer.detail_binary(options.detail_binary)
|
|
if detail:
|
|
print "Detail on binary",options.detail_binary+":"
|
|
pprint.pprint(detail)
|
|
else:
|
|
print "Bianry '"+options.detail_binary+"' not found in",
|
|
print "install file."
|
|
return 0
|
|
|
|
#
|
|
# Handle updates -- can only do one of these
|
|
# *TODO: should this change the command line syntax?
|
|
#
|
|
if options.new_license:
|
|
if not installer.add_license(
|
|
options.new_license,
|
|
options.license_text,
|
|
options.license_url):
|
|
return 1
|
|
elif options.remove_license:
|
|
installer.remove_license(options.remove_license)
|
|
elif options.orphan:
|
|
installer.orphan_binary(options.orphan)
|
|
elif options.adopt:
|
|
if not installer.adopt_binary(options.adopt):
|
|
return 1
|
|
else:
|
|
if options.check_license:
|
|
if not installer.is_license_info_valid():
|
|
print >>sys.stderr, 'Please add or correct the license',
|
|
print >>sys.stderr, 'information in',
|
|
print >>sys.stderr, options.install_filename + '.'
|
|
print >>sys.stderr, "You can also use the --add-license",
|
|
print >>sys.stderr, "option. See", sys.argv[0], "--help"
|
|
return 1
|
|
|
|
# *TODO: check against a list of 'known good' licenses.
|
|
# *TODO: check for urls which conflict -- will lead to
|
|
# problems.
|
|
|
|
installer.do_install(
|
|
options.platform,
|
|
options.install_dir,
|
|
options.cache_dir)
|
|
|
|
# save out any changes
|
|
installer.save()
|
|
return 0
|
|
|
|
if __name__ == '__main__':
|
|
sys.exit(main())
|