From 7839be1f1998626e820c24d2c3600babc3253e41 Mon Sep 17 00:00:00 2001 From: Jeremie Dimino Date: Mon, 17 Dec 2007 07:30:29 +0100 Subject: [PATCH] Changement de la fonction pour detecter les nouveaux patches. darcs-hash:20071217063029-af139-f98ea94095b6675734b9acfcd9316f90cbb81109.gz --- gestion/darcs_send_changes.py | 155 +++++++++++++++++++++++++++------- 1 file changed, 126 insertions(+), 29 deletions(-) diff --git a/gestion/darcs_send_changes.py b/gestion/darcs_send_changes.py index 410bb6de..fc0e17c8 100755 --- a/gestion/darcs_send_changes.py +++ b/gestion/darcs_send_changes.py @@ -27,6 +27,7 @@ Envoie un mail détaillant le dernier patch appliqué à un dépot. """ import commands, os, sys, email +from interactive import * try: from lxml import etree @@ -44,7 +45,7 @@ from email.Utils import formatdate from email import Encoders CONF_PATH = "_darcs/third-party/darcs-send-changes" -LAST_SEEN_FILE = CONF_PATH + "/last-seen" +SEEN_FILE = CONF_PATH + "/seen" ID_FILE = CONF_PATH + "/id" def to_utf8(str): @@ -65,7 +66,11 @@ def to_utf8(str): def darcs(args): """ Invoque darcs et renvoie sa sortie. """ - return to_utf8(commands.getoutput("env DARCS_DONT_ESCAPE_8BIT=1 darcs " + args)) + return to_utf8(commands.getstatusoutput("env DARCS_DONT_ESCAPE_8BIT=1 darcs " + args)) + +def darcs_raw(args): + """ Invoque darcs et renvoie sa sortie. """ + return commands.getstatusoutput("env DARCS_DONT_ESCAPE_8BIT=0 darcs " + args) def get_patch_properties(hash): """ Récupère les informations a propos d'un certain patch. """ @@ -73,14 +78,20 @@ def get_patch_properties(hash): match_cmd = "--match='hash %s'" % hash else: match_cmd = "--last 1" - prop = etree.XML(darcs("changes %s --xml-output" % match_cmd))[0] - diff = darcs("diff %s --unified" % match_cmd) + (status, changelog) = darcs("changes %s --xml-output" % match_cmd) + if status != 0 or changelog == "": + return None + prop = etree.XML(changelog) + if len(prop) == 0: + return None + prop = prop[0] + diff = darcs("diff %s --unified" % match_cmd)[1] diff = diff[diff.find('\ndiff ')+1:] cwd = os.getcwd() hostname = commands.getoutput('hostname -s') shortrepo = os.path.basename(cwd) if os.path.exists(ID_FILE): - id = file(ID_FILE).readlines()[0].strip() + id = file(ID_FILE).read().strip() else: id = shortrepo return { 'author': prop.attrib['author'], @@ -176,20 +187,85 @@ Les options disponibles sont: -s, --smtp spécifie le serveur smtp à utiliser -r, --repo spécifie l'emplacement du dépôt -f, --from hash du premier patch de la série a envoyer + -i, --interactive sélectionne les patches en mode interactif Si aucun destinataire n'est donné, roots@crans.org est utilisé. """ % { 'name': os.path.basename(sys.argv[0]) }) sys.exit(0) +def getnew(): + '''Renvoie les possibles nouveaux patches''' + if os.access(SEEN_FILE, os.R_OK): + seen=set(map(lambda x: x[0:-1], file(SEEN_FILE).readlines())) + else: + seen=set([]) + return set(filter(lambda x: x.endswith(".gz"), os.listdir("_darcs/patches"))) - seen + +def addseen(patches): + '''Ajoute des patches aux patches déjà vus''' + if not os.path.exists(CONF_PATH): + p = "." + for comp in CONF_PATH.split('/'): + p = "%s/%s" % (p, comp) + if not os.path.exists(p): + os.mkdir(p) + open(SEEN_FILE, "a+").writelines([patch + "\n" for patch in patches]) + +def select(patches): + '''Sélection interactive de patches''' + decided = [] + ignore = [] + while patches: + (status, changelog) = darcs("changes --match='hash %s'" % patches[-1]) + if status == 0: + print + print changelog + c = ask("Envoyer ce patch ? (%d/%d)" % (len(decided)+1, len(patches) + len(decided)), + [("YO", "envoyer ce patch"), + ("n", "ne pas envoyer ce patch"), + ("p", "revenir au patch précédent"), + ("e", "envoyer tout les patches suivant"), + ("i", "n'envoyer aucun des patches suivant"), + ("v", "voir le patch"), + Exit]) + if c == "y": + decided.append((True, patches.pop())) + elif c == "n": + decided.append((False, patches.pop())) + elif c == "p": + if decided: + patches.append(decided.pop()[1]) + else: + cprint("Déjà au début de la liste!", "rouge") + elif c == "e": + while patches: + decided.append((True, patches.pop())) + elif c == "i": + while patches: + decided.append((False, patches.pop())) + else: + ignore.append(patches.pop()) + + ask("%d patches à envoyer, accepter ?" % [x[0] for x in decided].count(True), + [("YO", "oui"), + ("nq", "non", None, lambda: sys.exit(0))]) + for d in decided: + if d[0]: + patches.append(d[1]) + else: + ignore.append(d[1]) + return patches, ignore + if __name__ == "__main__": import smtplib, getopt smtp = 'localhost' repo = None from_hash = None + interactive = False try: - options, arg = getopt.getopt(sys.argv[1:], 'hs:r:f:', [ 'help', 'smtp=', 'repo=', 'from=']) + options, arg = getopt.getopt(sys.argv[1:], 'hs:r:f:i', [ 'help', 'smtp=', 'repo=', 'from=', 'interactive']) except getopt.error, msg: __usage(unicode(msg)) for opt, val in options: @@ -201,6 +277,8 @@ if __name__ == "__main__": repo = val elif opt in [ '-f', '--from' ]: from_hash = val + elif opt in [ '-i', '--interactive' ]: + interactive = True else: __usage("option inconnue « %s »'" % opt) recipient = arg @@ -212,31 +290,50 @@ if __name__ == "__main__": else: while not os.path.exists('_darcs') and os.getcwd() != '/': os.chdir('..') - if not os.path.exists('_darcs') and os.getcwd() == '/': - cprint("Pas de dépôt darcs trouvé") - sys.exit(1) + if not os.path.exists('_darcs'): + cprint("Pas de dépôt darcs trouvé") + sys.exit(1) - if not from_hash: - if os.path.exists(LAST_SEEN_FILE): - f = open(LAST_SEEN_FILE) - from_hash = f.readlines()[0].strip() - f.close() - else: - from_hash = None + if not os.path.exists(SEEN_FILE): + # Sélection du patch façon darcs + cprint(u"C'est la première fois que vous lancez %s dans ce dépôt." % os.path.basename(sys.argv[0])) + c = ask("Que voulez-vous faire ?", + [("S", "sélectionner les patchs à envoyer/ignorer en mode interactif", "select"), + ("e", "tout envoyer", "all"), + ("i", "tout ignorer", "none"), + Exit]) + if c == "none": + addseen(getnew()) + sys.exit(0) + elif c == "all": + patches = getnew() + elif c == "select": + # On récupère la liste des patches triés + patches = [x.attrib['hash'] for x in etree.XML(darcs_raw("changes --xml-output")[1])] + patches, ignore = select(patches) + addseen(ignore) + else: + patches = [] + ignore = [] + # Tri des patches + for patch in getnew(): + (status, changelog) = darcs_raw("changes --xml-output --match='hash %s'" % patch) + try: + prop = etree.XML(changelog)[0] + patches.append((int(prop.attrib['date']), prop.attrib['hash'])) + except: + ignore.append(patch) + addseen(ignore) + patches.sort() + patches = [x[1] for x in patches] + if interactive: + patches, _ = select(patches) - patches = get_patches_properties(from_hash) if len(patches) == 0: sys.exit(0) for patch in patches: - cprint("Envoi du patch %s a %s." % (patch['hash'], ", ".join(recipient))) - send_changes(smtplib.SMTP(smtp), recipient, patch) - if not os.path.exists(CONF_PATH): - p = "" - for comp in CONF_PATH.split('/'): - p = "%s/%s" % (p, comp) - if not os.path.exits(p): - os.mkdir(p) - f = open(LAST_SEEN_FILE, "w") - f.write(patches[-1]['hash']) - f.close() - + props = get_patch_properties(patch) + if props: + cprint("Envoi du patch %s a %s." % (props['hash'], ", ".join(recipient))) + send_changes(smtplib.SMTP(smtp), recipient, props) + addseen([patch])