Intégration de la branche release-7.3.0

This commit is contained in:
Jephté Clain 2017-10-19 12:12:34 +04:00
commit ab69916d2b
17 changed files with 220 additions and 33 deletions

View File

@ -1,3 +1,19 @@
## Version 7.3.0 du 19/10/2017-12:12
* `72d7d15` maj version ulib
* `9fb19b4` ulib/multiconf: améliorer conf_install()
* `6c3ae24` openurl: supprimer la sortie erreur pour cacher les warnings GTK
* `528a281` em: supprimer la sortie d'erreur par défaut. rendre configurable la géométrie
* `489b31d` moiso: améliorer l'ergonomie pour le démontage
* `7bd0a95` ufile: support des pattern regex
* `6130c2f` chrono.py: 0 est équivalent à la chaine vide
* `9c5b46b` pyulib: ajouter ShConfig
* `f31f5f7` corriger un problème de compilation sur OL6
* `ab8ede8` awk: support du format dd/mm/yy
* `312c7dc` ajouter des fonctions pour simplifier le check de la version de l'os et l'installation de paquets
* `5bf55e5` bug
* `b6ff411` maj doc uscrontab
## Version 7.2.0 du 26/09/2017-17:01 ## Version 7.2.0 du 26/09/2017-17:01
* `1e576da` multiconf: rajouter conf_upgrade() dans conf_auto() * `1e576da` multiconf: rajouter conf_upgrade() dans conf_auto()

View File

@ -1 +1 @@
7.2.0 7.3.0

View File

@ -32,6 +32,12 @@ def playSound(name=None):
def isnum(i): def isnum(i):
return type(i) in (IntType, LongType) return type(i) in (IntType, LongType)
RE_NUM = re.compile(r'\d+$')
def numof(s):
if isnum(s): return s
elif s is None: return None
elif RE_NUM.match(str(s)) is not None: return int(str(s))
else: return s
DEFAULT_TIMEOUT = '5' DEFAULT_TIMEOUT = '5'
@ -99,11 +105,13 @@ class Chrono:
return Timedelta(seconds=timeout) return Timedelta(seconds=timeout)
def set_timeout(self, timeout=None): def set_timeout(self, timeout=None):
if timeout == '': timeout = None
if timeout is not None and not isnum(timeout): if timeout is not None and not isnum(timeout):
tmp = parse_desthour(str(timeout)) tmp = parse_desthour(str(timeout))
if tmp is None: tmp = parse_timeout(timeout) if tmp is None: tmp = parse_timeout(timeout)
if tmp is None: tmp = int(timeout) * 60 if tmp is None: tmp = int(timeout) * 60
timeout = tmp timeout = tmp
if timeout == 0: timeout = None
self.timeout = timeout self.timeout = timeout
if timeout is None: self.initial = '00:00' if timeout is None: self.initial = '00:00'
else: self.initial = self.__format(self.__delta(timeout)) else: self.initial = self.__format(self.__delta(timeout))
@ -334,7 +342,6 @@ d'arrivée, et que la durée est calculée automatiquement""")
timeout = o.timeout timeout = o.timeout
if timeout is None: timeout = DEFAULT_TIMEOUT if timeout is None: timeout = DEFAULT_TIMEOUT
elif timeout == '': timeout = None
o.timeout = timeout o.timeout = timeout
run_chronometre(o.timeout, o.autostart) run_chronometre(o.timeout, o.autostart)

10
em
View File

@ -1,13 +1,19 @@
#!/bin/bash #!/bin/bash
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
EMACS_GEOMETRY=150x50+0+67 : "${EM_GEOMETRY:=150x50+0+67}" "${EM_STDERR:=}"
# Essayer avec emacs # Essayer avec emacs
emacs="$(which emacs 2>/dev/null)" emacs="$(which emacs 2>/dev/null)"
if [ -x "$emacs" ]; then if [ -x "$emacs" ]; then
if [ -n "$DISPLAY" ]; then if [ -n "$DISPLAY" ]; then
exec "$emacs" -g "$EMACS_GEOMETRY" "$@" & if [ -n "$EM_STDERR" ]; then
# ne pas supprimer la sortie erreur
exec "$emacs" -g "$EM_GEOMETRY" "$@" &
else
# supprimer la sortie d'erreur. les warnings de GTK sont horripilants
exec "$emacs" -g "$EM_GEOMETRY" "$@" 2>/dev/null &
fi
exit 0 exit 0
else else
exec "$emacs" -nw "$@" exec "$emacs" -nw "$@"

View File

@ -11,14 +11,18 @@ value peut être placé entre double quotes ou simple quotes. Elle peut s'étend
plusieurs lignes si elle est mise entre quotes, ou si elle se termine par \ plusieurs lignes si elle est mise entre quotes, ou si elle se termine par \
""" """
__all__ = ('ConfigFile', 'ShConfigFile', 'PListFile') __all__ = (
'ConfigFile', 'ShConfigFile', 'PListFile',
'ShConfig',
)
import os, string, re, types import os, string, re, types, shlex
from os import path from os import path
from base import make_prop, isseq, seqof, firstof from base import odict, make_prop, isseq, seqof, firstof
from uio import _s, _u from uio import _s, _u
from files import TextFile from files import TextFile
from ulib.formats import unicodeF
#################### ####################
# gestion des commentaires # gestion des commentaires
@ -806,6 +810,68 @@ class PListFile(TextFile):
_print_debug("XXX string=%s" % string) _print_debug("XXX string=%s" % string)
return string return string
################################################################################
# classes utilisant shlex et l'interface odict
class ShConfig(odict):
_formats = None
def __init__(self, config, formats=None):
super(ShConfig, self).__init__()
if formats is None: formats = {}
else: formats = dict(formats)
self.__dict__['_formats'] = formats
for name in self._formats.keys():
self[name] = None
inf = open(config, 'rb')
try: s = inf.read()
finally: inf.close()
parts = shlex.split(s, True)
self.parse(parts)
def get_format(self, name):
format = None
if format is None: format = self._formats.get(name, None)
if format is None: format = self._formats.get(None, None)
if format is None: format = unicodeF
return format
RE_ARRAY = re.compile(r'([^=]+)=\((.*)')
RE_ARRAY_LAST = re.compile(r'(.*)\)$')
RE_SCALAR = re.compile(r'([^=]+)=(.*)')
def parse(self, parts):
i = 0
while i < len(parts):
part = parts[i]
i += 1
amo = self.RE_ARRAY.match(part)
smo = self.RE_SCALAR.match(part)
if amo is not None:
array = []
name, value = amo.groups()
format = self.get_format(name)
if value != '': array.append(format.parse(value))
while i < len(parts):
value = parts[i]
i += 1
mo = self.RE_ARRAY_LAST.match(value)
if mo is not None:
value = mo.group(1)
if value != '': array.append(format.parse(value))
break
else:
array.append(format.parse(value))
self[name] = array
elif smo is not None:
name, value = smo.groups()
format = self.get_format(name)
self[name] = format.parse(value)
else:
continue # ignorer l'erreur pour le moment
raise ValueError("%s: not a variable" % part)
################################################################################
if __name__ == '__main__': if __name__ == '__main__':
import doctest import doctest
doctest.testmod() doctest.testmod()

View File

@ -19,9 +19,9 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#include <unistd.h>
#include <sys/ptrace.h> #include <sys/ptrace.h>
#include <sys/user.h> #include <sys/user.h>
#include <unistd.h>
enum child_state { enum child_state {
ptrace_detached = 0, ptrace_detached = 0,

View File

@ -1 +1 @@
015000000 015001000

View File

@ -1883,6 +1883,12 @@ function __parse_date_fr(date, parts, y, m, d) {
m = int(parts[2]) m = int(parts[2])
d = int(parts[1]) d = int(parts[1])
return mktime(sprintf("%04i %02i %02i 00 00 00 +0400", y, m, d)) return mktime(sprintf("%04i %02i %02i 00 00 00 +0400", y, m, d))
} else if (match(date, /([0-9][0-9]?)\/([0-9][0-9]?)\/([0-9][0-9])/, parts)) {
basey = int(strftime("%Y")); basey = basey - basey % 100
y = basey + int(parts[3])
m = int(parts[2])
d = int(parts[1])
return mktime(sprintf("%04i %02i %02i 00 00 00 +0400", y, m, d))
} }
return -1 return -1
} }

View File

@ -60,6 +60,17 @@ function pkg_check_install() {
pkg_installm "$@" pkg_installm "$@"
} }
function require_pkgs() {
# installer les packages spécifiés silencieusement et sans confirmation.
# si les packages n'existent pas ou ne peuvent pas être installé, c'est une
# erreur fatale.
if ! pkg_check "$@"; then
# essayer d'installer les packages
enote "Installation de packages $*"
pkg_install "$@" || die
fi
}
################################################################################ ################################################################################
# Gestion des services # Gestion des services

View File

@ -24,8 +24,8 @@ function conf_auto() {
# conf_auto NAME # conf_auto NAME
# est équivalent à: # est équivalent à:
# conf_init VARS... # conf_init VARS...
# conf_find_files __CONF_FILES ~/etc/default/NAME.conf ~/etc/NAME.d/*.conf # conf_find_files __CONF_FILES ~/etc/default/NAME ~/etc/NAME.d/*.conf
# conf_upgrade ~/etc/default/NAME.conf # conf_upgrade ~/etc/default/NAME
# conf_load_files "${__CONF_FILES[@]}" # conf_load_files "${__CONF_FILES[@]}"
# Pour supporter les scénarii où les fichiers de configuration sont ailleurs # Pour supporter les scénarii où les fichiers de configuration sont ailleurs
# que dans ~/etc/default, l'argument NAME peut être un chemin: # que dans ~/etc/default, l'argument NAME peut être un chemin:
@ -43,8 +43,8 @@ function conf_auto() {
conf_find_files __CONFS_FILES "$__name.conf" "$__name.d/*.conf" conf_find_files __CONFS_FILES "$__name.conf" "$__name.d/*.conf"
[ $# -gt 0 ] && conf_upgrade "$__name.conf" [ $# -gt 0 ] && conf_upgrade "$__name.conf"
else else
conf_find_files __CONFS_FILES "$HOME/etc/default/$__name.conf" "$HOME/etc/$__name.d/*.conf" conf_find_files __CONFS_FILES "$HOME/etc/default/$__name" "$HOME/etc/$__name.d/*.conf"
[ $# -gt 0 ] && conf_upgrade "$HOME/etc/default/$__name.conf" [ $# -gt 0 ] && conf_upgrade "$HOME/etc/default/$__name"
fi fi
conf_load_files "${__CONFS_FILES[@]}" conf_load_files "${__CONFS_FILES[@]}"
} }
@ -240,8 +240,9 @@ function conf_load_files() {
} }
function conf_install() { function conf_install() {
# USAGE: conf_install DEST SRCS... # USAGE: conf_install DEST PREFIX SRCS...
# installer les fichiers de SRCS dans le répertoire standardisé DEST # installer les fichiers de SRCS dans le répertoire standardisé DEST avec le
# préfixe PREFIX
# ## destination # ## destination
# - si DEST est un nom sans chemin, e.g NAME, alors la destination est # - si DEST est un nom sans chemin, e.g NAME, alors la destination est
# ~/etc/NAME.d # ~/etc/NAME.d
@ -253,24 +254,43 @@ function conf_install() {
# - si SRC est un fichier, le prendre tel quel # - si SRC est un fichier, le prendre tel quel
# - si SRC est un répertoire, prendre tous les fichiers SRC/*.conf # - si SRC est un répertoire, prendre tous les fichiers SRC/*.conf
# - si SRC est un pattern, prendre tous les fichiers correspondant # - si SRC est un pattern, prendre tous les fichiers correspondant
local -a srcs # s'il n'y a qu'une seule source, la destination sera DEST/PREFIX.conf
# sinon, la destination sera DEST/PREFIX-SRCNAME où SRCNAME est le nom du
# fichier source
# si PREFIX est vide, alors les fichiers sont copiés avec leur nom sans
# modification.
local -a tmpsrcs srcs
local src dir wc local src dir wc
local dest="$1"; shift local dest="$1"; shift
local prefix="$1"; shift
[[ "$dest" == */* ]] || dest="$HOME/etc/$dest.d" [[ "$dest" == */* ]] || dest="$HOME/etc/$dest.d"
mkdir -p "$dest" || return 1 mkdir -p "$dest" || return 1
for src in "$@"; do for src in "$@"; do
if [ -f "$src" ]; then if [ -f "$src" ]; then
srcs=("$src") array_add srcs "$src"
elif [ -d "$src" ]; then elif [ -d "$src" ]; then
array_lsfiles srcs "$src" "*.conf" array_lsfiles tmpsrcs "$src" "*.conf"
array_extend srcs tmpsrcs
else else
splitwcs "$src" dir wc splitwcs "$src" dir wc
array_lsfiles srcs "$dir" "$wc" array_lsfiles tmpsrcs "$dir" "$wc"
array_extend srcs tmpsrcs
fi fi
done
[ ${#srcs[*]} -gt 0 ] || return 0
if [ -n "$prefix" ]; then
if [ ${#srcs[*]} -eq 1 ]; then
copy_update_ask -y "$src" "$dest/$prefix.conf"
else
for src in "${srcs[@]}"; do
copy_update_ask -y "$src" "$dest/$prefix-$(basename -- "$srcname")"
done
fi
else
for src in "${srcs[@]}"; do for src in "${srcs[@]}"; do
copy_update_ask -y "$src" "$dest" copy_update_ask -y "$src" "$dest"
done done
done fi
} }
function conf_upgrade() { function conf_upgrade() {

View File

@ -611,3 +611,28 @@ function on_default() {
#XXX ici, on peut ajouter le code de support pour d'autres systèmes #XXX ici, on peut ajouter le code de support pour d'autres systèmes
return 1 return 1
} }
################################################################################
# Support uinst
function require_debian() {
set -- -d debian "$@"
if check_sysinfos "$@"; then
urequire debian
return 0
fi
local -a infos; local info
for info in "$@"; do
if ! [[ "$info" == -* ]]; then
infos=("${infos[@]}" "$info")
fi
done
local msg="Ce script n'est pas supporté sur $(get_sysinfos_desc)"
[ -n "$*" ] && msg="$msg
Il faut au moins l'un des systèmes suivants: ${infos[*]}"
[ -n "$UINST" -a -n "$ABORT" ] && touch "$ABORT"
die "$msg"
}
function require_stretch() {
require_debian -v stretch+
}

1
moiso
View File

@ -29,6 +29,7 @@ parse_opts "${PRETTYOPTS[@]}" \
image="$1" image="$1"
[ -n "$image" ] || die "Vous devez spécifier l'image iso à monter" [ -n "$image" ] || die "Vous devez spécifier l'image iso à monter"
[ -d "$image" -a -f "$image.iso" ] && image="$image.iso"
[ -f "$image" ] || die "$image: fichier introuvable" [ -f "$image" ] || die "$image: fichier introuvable"
image="$(abspath "$image")" image="$(abspath "$image")"

24
openurl
View File

@ -3,6 +3,9 @@
source "$(dirname "$0")/lib/ulib/ulib" || exit 1 source "$(dirname "$0")/lib/ulib/ulib" || exit 1
urequire DEFAULTS urequire DEFAULTS
# faut-il supprimer la sortie erreur? les warnings de GTK sont horripilants.
: "${OPENURL_STDERR:=}"
function display_help() { function display_help() {
uecho "$scriptname: Ouvrir une URL dans un navigateur uecho "$scriptname: Ouvrir une URL dans un navigateur
@ -22,15 +25,20 @@ esac
setx url="$scriptdir/caturl" "$1" || die setx url="$scriptdir/caturl" "$1" || die
if progexists xdg-open; then if progexists xdg-open; then
exec xdg-open "$url" if [ -n "$OPENURL_STDERR" ]; then
elif progexists gnome-open; then exec xdg-open "$url"
exec gnome-open "$url" else
else exec xdg-open "$url" 2>/dev/null
# si on est sur un MacOSX, essayer utiliser open
urequire sysinfos
if check_sysinfos -s macosx; then
exec open "$url"
fi fi
elif progexists gnome-open; then
if [ -n "$OPENURL_STDERR" ]; then
exec gnome-open "$url"
else
exec gnome-open "$url" 2>/dev/null
fi
elif check_sysinfos -s macosx; then
# si on est sur un MacOSX, utiliser open
exec open "$url"
fi fi
die "Impossible de trouver une méthode pour ouvrir l'url $url" die "Impossible de trouver une méthode pour ouvrir l'url $url"

View File

@ -28,9 +28,9 @@ compilerArgs=-O2 -D_GNU_SOURCE -o $cacheDir/$executableFilename $cacheDir/$sourc
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#include <unistd.h>
#include <sys/ptrace.h> #include <sys/ptrace.h>
#include <sys/user.h> #include <sys/user.h>
#include <unistd.h>
enum child_state { enum child_state {
ptrace_detached = 0, ptrace_detached = 0,

14
ufile
View File

@ -12,7 +12,11 @@ Dans ce fichier, le tableau RULES contient des règles qui sont chacune de la
forme pattern:destdir[:renamef] forme pattern:destdir[:renamef]
- pattern est au format glob et identifie les fichiers auxquels s'applique la - pattern est au format glob et identifie les fichiers auxquels s'applique la
règle règle, sauf si la chaine commence par / auquel cas il s'agit d'une expression
régulière reconnue par awk. Par exemple, les deux patterns suivants sont
équivalents:
[ab]cd*.pdf
/[ab]cd.*\\\\.pdf\$
- destdir est le répertoire de destination dans lequel classer le fichier - destdir est le répertoire de destination dans lequel classer le fichier
- renamef est une fonction qui permet de supporter le renommage d'un fichier - renamef est une fonction qui permet de supporter le renommage d'un fichier
lors de son classement. Sa signature est 'renamef filename pf destdir' où lors de son classement. Sa signature est 'renamef filename pf destdir' où
@ -107,7 +111,7 @@ function __set_dest() {
setx dest=abspath "$dest" setx dest=abspath "$dest"
else else
__check_destdir "$destdir" "$rule" || return 1 __check_destdir "$destdir" "$rule" || return 1
setx dest=joinp "$destdir" "$filename" setx dest=joinp "$destdir" "$dest"
fi fi
upvar dest "$dest" upvar dest "$dest"
return 0 return 0
@ -223,7 +227,11 @@ for file in "${files[@]}"; do
odestdir="$HOME" odestdir="$HOME"
fi fi
eval "[[ \"\$filename\" == $(qwc "$pattern") ]]" || continue if [ "${pattern#/}" != "$pattern" ]; then
awk -v filename="$filename" -v pattern="${pattern#/}" 'BEGIN { exit(filename ~ pattern? 0: 1) }' || continue
else
eval "[[ \"\$filename\" == $(qwc "$pattern") ]]" || continue
fi
unset dest unset dest
interaction=--DEFAULT-- interaction=--DEFAULT--

View File

@ -197,6 +197,19 @@ Les lignes commençant par # sont des commentaires et sont ignorées
La fonction elogto() permet de spécifier un fichier vers lequel toutes les La fonction elogto() permet de spécifier un fichier vers lequel toutes les
sorties sont redirigées. sorties sont redirigées.
La fonction osvar() permet d'utiliser une variable de type oneshot définie
via l'option --osvar. Dans l'exemple suivant:
0 1 * * *
osvar FIRST=default SECOND
echo \"first is $FIRST and second is $SECOND\"
En temps normal, FIRST vaut la valeur par défaut 'default' et SECOND vaut la
chaine vide ''. Si on appelle '$scriptname -v FIRST=1 -v SECOND=2' alors ces
variables auront la valeur spécifiée *une seule fois* à la prochaine
invocation avant de retrouver leur valeur par défaut à l'invocation
suivante.
OPTIONS OPTIONS
-A, --install -A, --install
Installer une planification toutes les minutes du script dans la crontab Installer une planification toutes les minutes du script dans la crontab

2
uwatch
View File

@ -81,7 +81,7 @@ rcount)
duration="${1:-$DEFAULT_DURATION}" duration="${1:-$DEFAULT_DURATION}"
[ -n "$offset" ] && duration=$(($duration - $offset)) [ -n "$offset" ] && duration=$(($duration - $offset))
end=$(($start + $duration)) end=$(($start + $duration))
TZ= setx until=date -d "@$end" +%H:%M:%S setx until=date -d "@$end" +%H:%M:%S
;; ;;
esac esac