From e422eea9999a02262d3bad996879378ce1824541 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 9 Jul 2011 14:10:50 -0400 Subject: apply: add interactive option Rather than asking whether or not to apply each patch individually, list all of the patches at once and allow the user to either apply all of them, apply none of them, or interactively choose which ones to apply (a la interactive rebasing). In addition to choosing which patches to apply, the interactive option also allows reordering the patches before applying, and choosing to apply committed or rejected patches. https://bugzilla.gnome.org/show_bug.cgi?id=657558 --- git-bz | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++------ git-bz.txt | 11 +++++++---- 2 files changed, 58 insertions(+), 10 deletions(-) diff --git a/git-bz b/git-bz index cfda958..150598c 100755 --- a/git-bz +++ b/git-bz @@ -835,6 +835,16 @@ def prompt(message): elif line == 'n' or line == 'N': return False +def prompt_multi(message, options): + while True: + # Using print here could result in Python adding a stray space + # before the next print + sys.stdout.write(message + " ") + line = sys.stdin.readline() + opt = line[0].lower() + if opt in options: + return opt + def die(message): print >>sys.stderr, message sys.exit(1) @@ -1531,21 +1541,56 @@ def do_add_url(bug_reference, commit_or_revision_range): def do_apply(bug_reference): bug = Bug.load(BugHandle.parse_or_die(bug_reference), attachmentdata=True) + if len(bug.patches) == 0: + die("No patches on bug %d" % bug.id) + + patches = [] + patches_by_id = {} print "Bug %d - %s" % (bug.id, bug.short_desc) print for patch in bug.patches: if patch.status == 'committed' or patch.status == 'rejected': - print "Skipping, %s: %s" % (patch.status, patch.description) - continue + print "%d (skipping, %s) - %s" % (patch.attach_id, patch.status, patch.description) + else: + patches.append(patch) - print patch.description - if not prompt("Apply?"): - continue + for patch in patches: + print "%d - %s" % (patch.attach_id, patch.description) + print + opt = prompt_multi("Apply? [(y)es, (n)o, (i)nteractive]", ["y", "n", "i"]) - print + if opt == "n": + return + elif opt == "i": + template = StringIO() + template.write("# Bug %d - %s\n\n" % (bug.id, bug.short_desc)) + for patch in bug.patches: + patches_by_id[patch.attach_id] = patch + if patch.status == 'committed' or patch.status == 'rejected': + template.write("#%d - %s (%s)\n" % (patch.attach_id, patch.description, patch.status)) + else: + template.write("%d - %s\n" % (patch.attach_id, patch.description)) + template.write("\n") + template.write("""# Uncommented patches will be applied in the order they appear. +# Lines starting with '#' will be ignored. Delete everything to abort. +""") + + lines = edit_template(template.getvalue()) + patches = [] + for line in lines: + match = re.match('^(\d+)', line) + if match: + pid = int(match.group(1)) + if not patches_by_id.has_key(pid): + die("Unknown attachment id " + pid) + patches.append(patches_by_id[pid]) + + if len(patches) == 0: + die("No patches to apply, aborting") + for patch in patches: handle, filename = tempfile.mkstemp(".patch", make_filename(patch.description) + "-") f = os.fdopen(handle, "w") f.write(patch.data) diff --git a/git-bz.txt b/git-bz.txt index 18bce74..0dcf7f7 100644 --- a/git-bz.txt +++ b/git-bz.txt @@ -134,10 +134,13 @@ apply 'git bz apply' [-n | --no-add-url] -For each patch attachment (except for obsolete patches) of the specified -bug, prompts whether to apply. If prompt is agreed to runs 'git am' on -the patch to apply it to the current branch. Aborts if 'git am' fails to -allow cleaning up conflicts. +Lists all "pending" patches on the specified bug (ie, the patches that +are not obsolete, committed, or rejected), and then prompts whether to +apply them. In addition to simply accepting or rejecting the list of +patches, you can also type "i" to interactively choose which patches +to apply, and in what order, as with 'git rebase -i'. If any patches +are selected, it runs 'git am' on each one to apply it to the current +branch. Aborts if 'git am' fails, to allow cleaning up conflicts. Examples: -- cgit v1.2.3