Changement de la fonction pour detecter les nouveaux patches.

darcs-hash:20071217063029-af139-f98ea94095b6675734b9acfcd9316f90cbb81109.gz
This commit is contained in:
Jeremie Dimino 2007-12-17 07:30:29 +01:00
parent f1d1f2a477
commit 7839be1f19

View file

@ -27,6 +27,7 @@ Envoie un mail détaillant le dernier patch appliqué à un dépot.
""" """
import commands, os, sys, email import commands, os, sys, email
from interactive import *
try: try:
from lxml import etree from lxml import etree
@ -44,7 +45,7 @@ from email.Utils import formatdate
from email import Encoders from email import Encoders
CONF_PATH = "_darcs/third-party/darcs-send-changes" 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" ID_FILE = CONF_PATH + "/id"
def to_utf8(str): def to_utf8(str):
@ -65,7 +66,11 @@ def to_utf8(str):
def darcs(args): def darcs(args):
""" Invoque darcs et renvoie sa sortie. """ """ 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): def get_patch_properties(hash):
""" Récupère les informations a propos d'un certain patch. """ """ 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 match_cmd = "--match='hash %s'" % hash
else: else:
match_cmd = "--last 1" match_cmd = "--last 1"
prop = etree.XML(darcs("changes %s --xml-output" % match_cmd))[0] (status, changelog) = darcs("changes %s --xml-output" % match_cmd)
diff = darcs("diff %s --unified" % 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:] diff = diff[diff.find('\ndiff ')+1:]
cwd = os.getcwd() cwd = os.getcwd()
hostname = commands.getoutput('hostname -s') hostname = commands.getoutput('hostname -s')
shortrepo = os.path.basename(cwd) shortrepo = os.path.basename(cwd)
if os.path.exists(ID_FILE): if os.path.exists(ID_FILE):
id = file(ID_FILE).readlines()[0].strip() id = file(ID_FILE).read().strip()
else: else:
id = shortrepo id = shortrepo
return { 'author': prop.attrib['author'], return { 'author': prop.attrib['author'],
@ -176,20 +187,85 @@ Les options disponibles sont:
-s, --smtp <serveur> spécifie le serveur smtp à utiliser -s, --smtp <serveur> spécifie le serveur smtp à utiliser
-r, --repo <chemin> spécifie l'emplacement du dépôt -r, --repo <chemin> spécifie l'emplacement du dépôt
-f, --from <hash> hash du premier patch de la série a envoyer -f, --from <hash> 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é. Si aucun destinataire n'est donné, roots@crans.org est utilisé.
""" % { 'name': os.path.basename(sys.argv[0]) }) """ % { 'name': os.path.basename(sys.argv[0]) })
sys.exit(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__": if __name__ == "__main__":
import smtplib, getopt import smtplib, getopt
smtp = 'localhost' smtp = 'localhost'
repo = None repo = None
from_hash = None from_hash = None
interactive = False
try: 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: except getopt.error, msg:
__usage(unicode(msg)) __usage(unicode(msg))
for opt, val in options: for opt, val in options:
@ -201,6 +277,8 @@ if __name__ == "__main__":
repo = val repo = val
elif opt in [ '-f', '--from' ]: elif opt in [ '-f', '--from' ]:
from_hash = val from_hash = val
elif opt in [ '-i', '--interactive' ]:
interactive = True
else: else:
__usage("option inconnue « %s »'" % opt) __usage("option inconnue « %s »'" % opt)
recipient = arg recipient = arg
@ -212,31 +290,50 @@ if __name__ == "__main__":
else: else:
while not os.path.exists('_darcs') and os.getcwd() != '/': while not os.path.exists('_darcs') and os.getcwd() != '/':
os.chdir('..') os.chdir('..')
if not os.path.exists('_darcs') and os.getcwd() == '/': if not os.path.exists('_darcs'):
cprint("Pas de dépôt darcs trouvé") cprint("Pas de dépôt darcs trouvé")
sys.exit(1) sys.exit(1)
if not from_hash: if not os.path.exists(SEEN_FILE):
if os.path.exists(LAST_SEEN_FILE): # Sélection du patch façon darcs
f = open(LAST_SEEN_FILE) cprint(u"C'est la première fois que vous lancez %s dans ce dépôt." % os.path.basename(sys.argv[0]))
from_hash = f.readlines()[0].strip() c = ask("Que voulez-vous faire ?",
f.close() [("S", "sélectionner les patchs à envoyer/ignorer en mode interactif", "select"),
else: ("e", "tout envoyer", "all"),
from_hash = None ("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: if len(patches) == 0:
sys.exit(0) sys.exit(0)
for patch in patches: for patch in patches:
cprint("Envoi du patch %s a %s." % (patch['hash'], ", ".join(recipient))) props = get_patch_properties(patch)
send_changes(smtplib.SMTP(smtp), recipient, patch) if props:
if not os.path.exists(CONF_PATH): cprint("Envoi du patch %s a %s." % (props['hash'], ", ".join(recipient)))
p = "" send_changes(smtplib.SMTP(smtp), recipient, props)
for comp in CONF_PATH.split('/'): addseen([patch])
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()