nutools/lib/pyulib/src/uapps/plver.py

166 lines
5.2 KiB
Python
Raw Normal View History

2013-08-27 15:14:44 +04:00
#!/usr/bin/env python
# -*- coding: utf-8 -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
u"""%(scriptname)s: Afficher la dernière version d'un ensemble de fichiers
USAGE
%(scriptname)s [/path/to/]basename
OPTIONS
-r Inverser le rôle de cet utilitaire: afficher toutes les versions des
fichiers plutôt que la dernière
-s suffix
Ajouter suffix à la liste des suffixes qui doivent être enlevés au nom
de fichier avant de trouver la version.
-n Ne pas utiliser une liste de suffixes par défaut qui convient pour les
fichiers d'archives et d'export:
(war, jar, ear, zip, tar[.gz|.bz2], t[gz|bz2], sql, ldif)
-f INPUT-FILE
Au lieu de lister les fichiers, prendre la liste dans INPUT-FILE. -f -
signifie lire sur stdin."""
import os, sys, re
from os import path
from glob import glob
from ulib.all import *
SUFFIXES = (".war", ".jar", ".ear", ".zip", ".gz", ".bz2", ".tar", ".tgz", ".tbz2",
".sql", ".ldif",
)
def strip_suffixes(p, suffixes=SUFFIXES):
suffix_striped = True
while suffix_striped:
suffix_striped = False
for suffix in suffixes:
if p.endswith(suffix):
p = p[:len(p) - len(suffix)]
suffix_striped = True
return p
RE_ARCHIVE = re.compile(r'(?i)\.(war|jar|ear|zip|tar|tar\.gz|tgz|tar\.bz2|tbz2)$')
def is_archive(p):
return RE_ARCHIVE.search(p) is not None
def strip_archive_ext(p):
mo = RE_ARCHIVE.search(p)
if mo is not None:
p = p[:mo.start(0)]
return p
RE_PATH_VERSION = re.compile(r'(?i)(?:-|_|\.)' # préfixe: - ou .
r'(\d+(?:(-|_|\.)\d+(?:\2\d+)*)?)' # version
r'(?:(a|alpha|b|beta|rc)(\d*))?' # type
r'$' #
)
RE_NUMBERS = re.compile(r'\d+')
TYPE_MAPPINGS = {'a': 'alpha', 'b': 'beta'}
TYPES = ['alpha', 'beta', None, 'rc']
def has_version(p):
return RE_PATH_VERSION.search(p) is not None
def get_version(p):
mo = RE_PATH_VERSION.search(p)
if mo is None: return None, None, None
else:
vns = map(int, RE_NUMBERS.findall(mo.group(1)))
type = mo.group(3)
if type is not None: type = type.lower()
type = TYPE_MAPPINGS.get(type, type)
n = mo.group(4)
if n is not None: n = int(n)
return vns, type, n
def strip_version(p):
mo = RE_PATH_VERSION.search(p)
if mo is not None:
p = p[:mo.start(0)]
return p
class PathVersion:
def __init__(self, suffixes=SUFFIXES):
self.suffixes = suffixes
def cmp(self, p0, p1):
p0 = strip_suffixes(p0, self.suffixes)
p1 = strip_suffixes(p1, self.suffixes)
2015-08-20 07:58:17 +04:00
2013-08-27 15:14:44 +04:00
vns0, type0, n0 = get_version(p0)
vns1, type1, n1 = get_version(p1)
c = cmp(vns0, vns1)
if c == 0: c = cmp(TYPES.index(type0), TYPES.index(type1))
if c == 0: c = cmp(n0, n1)
return c
2015-08-20 07:58:17 +04:00
2013-08-27 15:14:44 +04:00
def display_help():
uprint(__doc__ % globals())
def run_plver():
all = False
reverse = False
suffixes = list(SUFFIXES)
inf = None
opts, argv = get_args(None, 'arns:f:',
['help', 'all', 'reverse', 'no-suffixes', 'suffix=', 'file='])
for opt, value in opts:
if opt in ('--help', ):
display_help()
sys.exit(0)
elif opt in ('-a', '--all'):
all = True
elif opt in ('-r', '--reverse'):
reverse = True
elif opt in ('-n', '--no-suffixes'):
suffixes = []
elif opt in ('-s', '--suffix'):
suffixes.append(value)
elif opt in ('-f', '--file'):
inf = value
if inf == '-': inf = sys.stdin
basenames = {}
if inf is None:
# Generer une liste de fichiers en ne gardant que les fichiers archive qui
# ont un numero de version. Classer ces fichiers par noms de base
if not argv: argv = ['*']
for arg in argv:
if path.isdir(arg): arg += '/'
if not arg.endswith('*'): arg += '*'
for p in glob(arg):
n = strip_suffixes(p, suffixes)
s = p[len(n):]
if has_version(n):
b = strip_version(n) + s
if b not in basenames:
basenames[b] = []
basenames[b].append(p)
else:
lines = Lines()
for p in lines.readlines(inf):
n = strip_suffixes(p, suffixes)
s = p[len(n):]
if has_version(n):
b = strip_version(n) + s
if b not in basenames:
basenames[b] = []
basenames[b].append(p)
# Pour chacun des noms de base, classer la liste et retourner la(les)
# version(s) demandée(s)
pv = PathVersion(suffixes)
for basename, paths in basenames.items():
if all:
paths.sort(pv.cmp, reverse=reverse)
for p in paths:
print p
else:
paths.sort(pv.cmp, reverse=True)
if reverse:
for p in paths[1:]:
print p
else:
print paths[0]
if __name__ == '__main__':
run_plver()