Classes | |
class | LogFile |
Functions | |
def | main |
def | walk |
def | filename_match |
def | expand_source_dir |
def | remove |
def | getCommonPath |
def | getRelativePath |
def | update |
def | install |
def | uninstall |
Variables | |
string | _version = "$Id: install.py,v 1.15 2008/10/28 17:24:39 marcocle Exp $" |
usage | |
help |
def fragments::install::main | ( | ) |
Definition at line 22 of file install.py.
00022 : 00023 try: 00024 # optparse is available only since Python 2.3 00025 from optparse import OptionParser 00026 parser = OptionParser() 00027 parser.add_option("-x","--exclude",action="append", 00028 metavar="PATTERN", default = [], 00029 dest="exclusions", help="which files/directories to avoid to install") 00030 parser.add_option("-l","--log",action="store", 00031 dest="logfile", default="install.log", 00032 help="where to store the informations about installed files [default: %default]") 00033 parser.add_option("-d","--destname",action="store", 00034 dest="destname", default=None, 00035 help="name to use when installing the source into the destination directory [default: source name]") 00036 parser.add_option("-u","--uninstall",action="store_true", 00037 dest="uninstall", default=False, 00038 help="do uninstall") 00039 parser.add_option("-s","--symlink",action="store_true", 00040 dest="symlink", default=False, 00041 help="create symlinks instead of copy") 00042 #parser.add_option("-p","--permission",action="store", 00043 # metavar="PERM", 00044 # dest="permission", 00045 # help="modify the permission of the destination file (see 'man chown'). Unix only.") 00046 (opts,args) = parser.parse_args() 00047 except ImportError: 00048 # Old style option parsing 00049 # It must be removed when the support for Python 2.2 is dropped 00050 from getopt import getopt, GetoptError 00051 from sys import argv,exit 00052 class _DummyParserClass: 00053 def __init__(self): 00054 self.usage = "usage: install.py [options]" 00055 self.help = """options: 00056 -h, --help show this help message and exit 00057 -x PATTERN, --exclude=PATTERN 00058 which files/directories to avoid to install 00059 -l LOGFILE, --log=LOGFILE 00060 where to store the informations about installed files 00061 [default: install.log] 00062 -d DESTNAME, --destname=DESTNAME 00063 name to use when installing the source into the 00064 destination directory [default: source name] 00065 -u, --uninstall do uninstall 00066 -s, --symlink create symlinks instead of copy""" 00067 def error(self,msg=None): 00068 print self.usage + "\n" 00069 if not msg: 00070 msg = self.help 00071 print msg 00072 exit(1) 00073 parser = _DummyParserClass() 00074 try: 00075 optlist, args = getopt(argv[1:],"hx:l:d:us", 00076 ["help","exclude","log","destname","uninstall","symlink"]) 00077 except GetoptError: 00078 # print help information and exit: 00079 parser.error() 00080 # Dummy option class 00081 class _DummyOptionsClass: 00082 def __init__(self): 00083 # defaults 00084 self.exclusions = [] 00085 self.uninstall = False 00086 self.logfile = "install.log" 00087 self.destname = None 00088 self.symlink = False 00089 opts = _DummyOptionsClass() 00090 for opt,val in optlist: 00091 if opt in [ "-h", "--help" ]: 00092 parser.error() 00093 elif opt in [ "-x", "--exclude" ]: 00094 opts.exclusions.append(val) 00095 elif opt in [ "-l", "--log" ]: 00096 opts.logfile = val 00097 elif opt in [ "-d", "--destname" ]: 00098 opts.destname = val 00099 elif opt in [ "-u", "--uninstall" ]: 00100 opts.uninstall = True 00101 elif opt in [ "-s", "--symlink" ]: 00102 opts.symlink = True 00103 # options consistency check 00104 from pickle import dump,load 00105 from os.path import realpath 00106 if opts.uninstall: 00107 if opts.exclusions: 00108 parser.error("Exclusion list does not make sense for uninstall") 00109 opts.destination = args 00110 try: 00111 log = load(open(opts.logfile,"rb")) 00112 except: 00113 log = LogFile() 00114 uninstall(log,opts.destination,realpath(dirname(opts.logfile))) 00115 if log: 00116 dump(log,open(opts.logfile,"wb")) 00117 else: 00118 from os import remove 00119 try: 00120 remove(opts.logfile) 00121 except OSError, x: 00122 if x.errno != 2 : raise 00123 else : # install mode 00124 if len(args) < 2: 00125 parser.error("Specify at least one source and (only) one destination") 00126 opts.destination = args[-1] 00127 opts.sources = args[:-1] 00128 try: 00129 log = load(open(opts.logfile,"rb")) 00130 except: 00131 log = LogFile() 00132 if opts.symlink : 00133 if len(opts.sources) != 1: 00134 parser.error("no more that 2 args with --symlink") 00135 opts.destination, opts.destname = split(opts.destination) 00136 install(opts.sources,opts.destination, 00137 log,opts.exclusions,opts.destname, 00138 opts.symlink, realpath(dirname(opts.logfile))) 00139 dump(log,open(opts.logfile,"wb")) 00140 from os import makedirs, listdir, rmdir
def fragments::install::walk | ( | top, | ||
topdown = True , |
||||
onerror = None | ||||
) |
Copied from Python 2.3 os.py (see original file for copyright) This function has been introduced in Python 2.3, and this copy should be removed once the support for Python 2.2 is dropped.
Definition at line 147 of file install.py.
00147 : 00148 """Copied from Python 2.3 os.py (see original file for copyright) 00149 This function has been introduced in Python 2.3, and this copy should 00150 be removed once the support for Python 2.2 is dropped. 00151 """ 00152 00153 from os.path import join, isdir, islink 00154 00155 # We may not have read permission for top, in which case we can't 00156 # get a list of the files the directory contains. os.path.walk 00157 # always suppressed the exception then, rather than blow up for a 00158 # minor reason when (say) a thousand readable directories are still 00159 # left to visit. That logic is copied here. 00160 try: 00161 # Note that listdir and error are globals in this module due 00162 # to earlier import-*. 00163 names = listdir(top) 00164 except error, err: 00165 if onerror is not None: 00166 onerror(err) 00167 return 00168 00169 dirs, nondirs = [], [] 00170 for name in names: 00171 if isdir(join(top, name)): 00172 dirs.append(name) 00173 else: 00174 nondirs.append(name) 00175 00176 if topdown: 00177 yield top, dirs, nondirs 00178 for name in dirs: 00179 path = join(top, name) 00180 if not islink(path): 00181 for x in walk(path, topdown, onerror): 00182 yield x 00183 if not topdown: 00184 yield top, dirs, nondirs 00185 class LogFile:
def fragments::install::filename_match | ( | name, | ||
patterns, | ||||
default = False | ||||
) |
Check if the name is matched by any of the patterns in exclusions.
Definition at line 214 of file install.py.
00214 : 00215 """ 00216 Check if the name is matched by any of the patterns in exclusions. 00217 """ 00218 from fnmatch import fnmatch 00219 for x in patterns: 00220 if fnmatch(name,x): 00221 return True 00222 return default 00223 def expand_source_dir(source, destination, exclusions = [],
def fragments::install::expand_source_dir | ( | source, | ||
destination, | ||||
exclusions = [] , |
||||
destname = None , |
||||
logdir = realpath(".") | ||||
) |
Generate the list of copies.
Definition at line 224 of file install.py.
00225 : 00226 """ 00227 Generate the list of copies. 00228 """ 00229 expansion = {} 00230 src_path,src_name = split(source) 00231 if destname: 00232 to_replace = source 00233 replacement = join(destination,destname) 00234 else: 00235 to_replace = src_path 00236 replacement = destination 00237 00238 for dirname, dirs, files in walk(source): 00239 if to_replace: 00240 dest_path=dirname.replace(to_replace,replacement) 00241 else: 00242 dest_path=join(destination,dirname) 00243 # remove excluded dirs from the list 00244 dirs[:] = [ d for d in dirs if not filename_match(d,exclusions) ] 00245 # loop over files 00246 for f in files: 00247 if filename_match(f,exclusions): continue 00248 key = getRelativePath(dest_path, join(dirname,f)) 00249 value = getRelativePath(logdir, join(dest_path,f)) 00250 expansion[key] = value 00251 return expansion 00252 def remove(file, logdir):
def fragments::install::remove | ( | file, | ||
logdir | ||||
) |
Definition at line 253 of file install.py.
00253 : 00254 from os import remove 00255 from os.path import normpath, splitext, exists 00256 file = normpath(join(logdir, file)) 00257 try: 00258 print "Remove '%s'"%file 00259 remove(file) 00260 # For python files, remove the compiled versions too 00261 if splitext(file)[-1] == ".py": 00262 for c in ['c', 'o']: 00263 if exists(file + c): 00264 print "Remove '%s'" % (file+c) 00265 remove(file+c) 00266 file_path = split(file)[0] 00267 while file_path and (len(listdir(file_path)) == 0): 00268 print "Remove empty dir '%s'"%file_path 00269 rmdir(file_path) 00270 file_path = split(file_path)[0] 00271 except OSError, x: # ignore file-not-found errors 00272 if x.errno in [2, 13] : 00273 print "Previous removal ignored" 00274 else: 00275 raise 00276 00277 def getCommonPath(dirname, filename):
def fragments::install::getCommonPath | ( | dirname, | ||
filename | ||||
) |
Definition at line 278 of file install.py.
00278 : 00279 from os import sep 00280 from itertools import izip 00281 from os.path import splitdrive 00282 # if the 2 components are on different drives (windows) 00283 if splitdrive(dirname)[0] != splitdrive(filename)[0]: 00284 return None 00285 dirl = dirname.split(sep) 00286 filel = filename.split(sep) 00287 commpth = [] 00288 for d, f in izip(dirl, filel): 00289 if d == f : 00290 commpth.append(d) 00291 else : 00292 break 00293 commpth = sep.join(commpth) 00294 if not commpth: 00295 commpth = sep 00296 elif commpth[-1] != sep: 00297 commpth += sep 00298 return commpth 00299 def getRelativePath(dirname, filename):
def fragments::install::getRelativePath | ( | dirname, | ||
filename | ||||
) |
calculate the relative path of filename with regards to dirname
Definition at line 300 of file install.py.
00300 : 00301 """ calculate the relative path of filename with regards to dirname """ 00302 import os.path 00303 # Translate the filename to the realpath of the parent directory + basename 00304 filepath,basename = os.path.split(filename) 00305 filename = os.path.join(os.path.realpath(filepath),basename) 00306 # Get the absolute pathof the destination directory 00307 dirname = os.path.realpath(dirname) 00308 commonpath = getCommonPath(dirname, filename) 00309 # for windows if the 2 components are on different drives 00310 if not commonpath: 00311 return filename 00312 relname = filename[len(commonpath):] 00313 reldir = dirname[len(commonpath):] 00314 if reldir: 00315 relname = (os.path.pardir+os.path.sep)*len(reldir.split(os.path.sep)) \ 00316 + relname 00317 return relname 00318 def update(src,dest,old_dest = None, syml = False, logdir = realpath(".")):
def fragments::install::update | ( | src, | ||
dest, | ||||
old_dest = None , |
||||
syml = False , |
||||
logdir = realpath(".") | ||||
) |
Definition at line 319 of file install.py.
00319 : 00320 from shutil import copy2 00321 from sys import platform 00322 from os.path import normpath 00323 if platform != "win32": 00324 from os import symlink 00325 realdest = normpath(join(logdir, dest)) 00326 dest_path = split(realdest)[0] 00327 realsrc = normpath(join(dest_path,src)) 00328 if (not exists(realdest)) or (getmtime(realsrc) > getmtime(realdest)): 00329 if not isdir(dest_path): 00330 print "Create dir '%s'"%(dest_path) 00331 makedirs(dest_path) 00332 # the destination file is missing or older than the source 00333 if syml and platform != "win32" : 00334 if exists(realdest): 00335 remove(realdest,logdir) 00336 print "Create Link to '%s' in '%s'"%(src,dest_path) 00337 symlink(src,realdest) 00338 else: 00339 print "Copy '%s' -> '%s'"%(src,realdest) 00340 copy2(realsrc,realdest) # do the copy (cp -p src dest) 00341 #if old_dest != dest: # the file was installed somewhere else 00342 # # remove the old destination 00343 # if old_dest is not None: 00344 # remove(old_dest,logdir) 00345 def install(sources, destination, logfile, exclusions = [],
def fragments::install::install | ( | sources, | ||
destination, | ||||
logfile, | ||||
exclusions = [] , |
||||
destname = None , |
||||
syml = False , |
||||
logdir = realpath(".") | ||||
) |
Copy sources to destination keeping track of what has been done in logfile. The destination must be a directory and sources are copied into it. If exclusions is not empty, the files matching one of its elements are not copied.
Definition at line 346 of file install.py.
00347 : 00348 """ 00349 Copy sources to destination keeping track of what has been done in logfile. 00350 The destination must be a directory and sources are copied into it. 00351 If exclusions is not empty, the files matching one of its elements are not 00352 copied. 00353 """ 00354 for s in sources: 00355 src_path, src_name = split(s) 00356 if not exists(s): 00357 continue # silently ignore missing sources 00358 elif not isdir(s): # copy the file, without logging (?) 00359 if destname is None: 00360 dest = join(destination,src_name) 00361 else: 00362 dest = join(destination,destname) 00363 src = getRelativePath(destination,s) 00364 dest = getRelativePath(logdir,dest) 00365 old_dest = logfile.get_dest(src) 00366 update(src,dest,old_dest,syml,logdir) 00367 logfile.set_dest(src,dest) # update log 00368 else: # for directories 00369 # expand the content of the directory as a dictionary 00370 # mapping sources to destinations 00371 to_do = expand_source_dir(s,destination,exclusions,destname, logdir) 00372 src = getRelativePath(destination,s) 00373 last_done = logfile.get_dest(src) 00374 if last_done is None: last_done = {} 00375 for k in to_do: 00376 try: 00377 old_dest = last_done[k] 00378 del last_done[k] 00379 except KeyError: 00380 old_dest = None 00381 update(k,to_do[k],old_dest,syml,logdir) 00382 # remove files that were copied but are not anymore in the list 00383 for old_dest in last_done.values(): 00384 remove(old_dest,logdir) 00385 logfile.set_dest(src,to_do) # update log 00386 def uninstall(logfile, destinations = [], logdir=realpath(".")):
def fragments::install::uninstall | ( | logfile, | ||
destinations = [] , |
||||
logdir = realpath(".") | ||||
) |
Remove copied files using logfile to know what to remove. If destinations is not empty, only the files/directories specified are removed.
Definition at line 387 of file install.py.
00387 : 00388 """ 00389 Remove copied files using logfile to know what to remove. 00390 If destinations is not empty, only the files/directories specified are 00391 removed. 00392 """ 00393 for s in logfile.get_sources(): 00394 dest = logfile.get_dest(s) 00395 if type(dest) is str: 00396 if filename_match(dest,destinations,default=True): 00397 remove(dest, logdir) 00398 logfile.remove(s) 00399 else: 00400 for subs in dest.keys(): 00401 subdest = dest[subs] 00402 if filename_match(subdest,destinations,default=True): 00403 remove(subdest,logdir) 00404 del dest[subs] 00405 if not dest: 00406 logfile.remove(s) 00407 if __name__ == "__main__":
string fragments::install::_version = "$Id: install.py,v 1.15 2008/10/28 17:24:39 marcocle Exp $" [static] |
Definition at line 20 of file install.py.
Definition at line 54 of file install.py.
Definition at line 55 of file install.py.