def qimporthook(orig, ui, repo, *files, **opts): q = repo.mq # checks for an unused patch name. prompts if the patch already exists and # returns the corrected name. def checkpatchname(patch, current_filename=None): name = patch.name # For the first patch imported, the patch has already been temporarily saved # to disk by the time we reach here, with a filename that we cannot control # (eg 973703 for bz://973703). The patch is then renamed by us to the name of # the attachment in Bugzilla (unless patch_format has been overridden). # Unfortunately it's common for people to use the bug number as the filename of # the attachment, which would cause a name collision with this temporary file. # Patches other than the first will not have a current_filename. if name == current_filename: # Add a suffix to the patch filename to avoid a collision. This is preferable # to just skipping the check to see if the file exists, since if we leave the # filename as-is, subsequent qimports of the same bug will abort with an mq # "patch already exists" when it is unable to write its temporary file. ui.status("Changing patch filename to avoid conflict with temporary file.\n") name = "%s_" % name while os.path.exists(q.join(name)): msg = ("A file named '%s' already exists in your patch directory.\n" "Rename %s '%s' (%d) (r)/overwrite (o)?" % (name, 'patch' if isinstance(patch, bz.Patch) else 'attachment', patch.desc, int(patch.id))) if name in q.series and q.isapplied(name): ui.write("A patch file named '%s' is already applied.\n") choice = 'r' else: choice = ui.prompt(msg, default="r") if choice == 'r': name = ui.prompt("Enter the new patch name (old one was '%s'):" % name, default=name) else: # overwrite break if name in q.series and q.isapplied(name): ui.fatal("Patch with that name is already applied.") return name # hook for url.open which lets the user edit the returned patch name def previewopen(orig, ui, path): fp = orig(ui, path) class PreviewReader(object): def read(self): return ui.edit(fp.read(), ui.username()) return PreviewReader() # Install the preview hook if necessary. This will preview non-bz:// bugs # and that's OK. if opts['preview']: extensions.wrapfunction(url, "open", previewopen) # mercurial's url.search_re includes the // and that doesn't match what we # want which is bz:dddddd(/ddddd)? files = map(fixuppath, files) # Do the import as normal. The first patch of any bug is actually imported # and the rest are stored in the global delayed_imports. The imported # patches have dumb filenames because there's no way to tell mq to pick the # patch name *after* download. ret = orig(ui, repo, *files, **opts) if ret or bzhandler.last_imported_patch() is None: return ret # If the user passed a name, then mq used that so we don't need to rename if not opts['name']: # cache the lookup of the name. findcmd is not fast. qrename = cmdutil.findcmd("qrename", commands.table)[1][0] # Rename the already imported patch. If there are multiple patches, the # rest will be in bzhandler.delayed_imports, which we'll name correctly # in the first place. oldpatchname = q.fullseries[q.fullseriesend()] newpatchname = checkpatchname(bzhandler.last_imported_patch(), current_filename=oldpatchname) if newpatchname != oldpatchname: if newpatchname in q.series: q.delete(repo, [newpatchname], {}) qrename(ui, repo, oldpatchname, newpatchname) # mq always reports the original name, which is confusing so we'll # report the rename. But if ui.verbose is on, qrename will have already # reported it. if not ui.verbose: ui.status("renamed %s -> %s\n" % (oldpatchname, newpatchname)) # now process the delayed imports # these opts are invariant for all patches newopts = {} newopts.update(opts) newopts['force'] = True # loop through the Patches and import them by calculating their url. The # bz:// handler will have cached the lookup so we don't hit the network # here. Each one of these pushes an unapplied patch onto the beginning of # the queue, and unapplied patches are ignored when importing them, so do # these in reverse order. for patch in reversed(list(bzhandler.delayed_imports)): newopts['name'] = checkpatchname(patch) path = makebzurl(patch.bug.num, patch.id) ret = orig(ui, repo, path, **newopts) if ret: return ret
def qimporthook(orig, ui, repo, *files, **opts): q = repo.mq # checks for an unused patch name. prompts if the patch already exists and # returns the corrected name. def checkpatchname(patch): name = patch.name # Hg v1.4+: "ui.prompt is now a simple prompt and does not accept a list of choices. Use ui.promptchoice instead.". hasPromptchoice = hasattr(ui, 'promptchoice') while os.path.exists(q.join(name)): prompt = "A patch file named '%s' already exists in your patch directory. Rename %s '%s' (%d) (r)/overwrite (o)?" % \ (name, 'patch' if isinstance(patch, bz.Patch) else 'attachment', patch.desc, int(patch.id)) if hasPromptchoice: choice = ui.promptchoice(prompt, ("&readonly", "&overwrite"), 0) choice = ["r", "o"][choice] else: choice = ui.prompt(prompt, ("&readonly", "&overwrite"), "r") if choice == 'r': name = ui.prompt("Enter the new patch name (old one was '%s'):" % name) else: # overwrite break; if name in q.series and q.isapplied(name): ui.warn("Patch was already applied. Changes will not take effect until the patch is reapplied.") return name # hook for url.open which lets the user edit the returned def previewopen(orig, ui, path): fp = orig(ui, path) class PreviewReader(object): def read(self): return ui.edit(fp.read(), ui.username()) return PreviewReader() # Install the preview hook if necessary. This will preview non-bz:// bugs # and that's OK. if opts['preview']: extensions.wrapfunction(url, "open", previewopen) # mercurial's url.search_re includes the // and that doesn't match what we # want which is bz:dddddd(/ddddd)? files = map(fixuppath, files) # Do the import as normal. The first patch of any bug is actually imported # and the rest are stored in the global delayed_imports. The imported # patches have dumb filenames because there's no way to tell mq to pick the # patch name *after* download. ret = orig(ui, repo, *files, **opts) if ret or bzhandler.last_imported_patch() is None: return ret # If the user passed a name, then mq used that so we don't need to rename if not opts['name']: # cache the lookup of the name. findcmd is not fast. qrename = cmdutil.findcmd("qrename", commands.table)[1][0] # Rename the already imported patch. If there are multiple patches, the # rest will be in bzhandler.delayed_imports, which we'll name correctly # in the first place. try: # hg 1.9+ oldpatchname = q.fullseries[q.fullseriesend()] except: oldpatchname = q.full_series[q.full_series_end()] newpatchname = checkpatchname(bzhandler.last_imported_patch()) if newpatchname != oldpatchname: qrename(ui, repo, oldpatchname, newpatchname) # mq always reports the original name, which is confusing so we'll # report the rename. But if ui.verbose is on, qrename will have already # reported it. if not ui.verbose: ui.write("renamed %s -> %s\n" % (oldpatchname, newpatchname)) # now process the delayed imports # these opts are invariant for all patches newopts = {} newopts.update(opts) newopts['force'] = True # loop through the Patches and import them by calculating their url. The # bz:// handler will have cached the lookup so we don't hit the network # here. Each one of these pushes an unapplied patch onto the beginning of # the queue, and unapplied patches are ignored when importing them, so do # these in reverse order. for patch in reversed(list(bzhandler.delayed_imports)): newopts['name'] = checkpatchname(patch) path = makebzurl(patch.bug.num, patch.id) ret = orig(ui, repo, path, **newopts) if ret: return ret
def qimporthook(orig, ui, repo, *files, **opts): q = repo.mq # checks for an unused patch name. prompts if the patch already exists and # returns the corrected name. def checkpatchname(patch, current_filename=None): name = patch.name # For the first patch imported, the patch has already been temporarily saved # to disk by the time we reach here, with a filename that we cannot control # (eg 973703 for bz://973703). The patch is then renamed by us to the name of # the attachment in Bugzilla (unless patch_format has been overridden). # Unfortunately it's common for people to use the bug number as the filename of # the attachment, which would cause a name collision with this temporary file. # Patches other than the first will not have a current_filename. if name == current_filename: # Add a suffix to the patch filename to avoid a collision. This is preferable # to just skipping the check to see if the file exists, since if we leave the # filename as-is, subsequent qimports of the same bug will abort with an mq # "patch already exists" when it is unable to write its temporary file. ui.status("Changing patch filename to avoid conflict with temporary file.\n") name = "%s_" % name while os.path.exists(q.join(name)): msg = ( "A file named '%s' already exists in your patch directory.\n" "Rename %s '%s' (%d) (r)/overwrite (o)?" % (name, "patch" if isinstance(patch, bz.Patch) else "attachment", patch.desc, int(patch.id)) ) if name in q.series and q.isapplied(name): ui.write("A patch file named '%s' is already applied.\n") choice = "r" else: choice = ui.prompt(msg, default="r") if choice == "r": name = ui.prompt("Enter the new patch name (old one was '%s'):" % name, default=name) else: # overwrite break if name in q.series and q.isapplied(name): ui.fatal("Patch with that name is already applied.") return name # hook for url.open which lets the user edit the returned patch name def previewopen(orig, ui, path): fp = orig(ui, path) class PreviewReader(object): def read(self): return ui.edit(fp.read(), ui.username()) return PreviewReader() # Install the preview hook if necessary. This will preview non-bz:// bugs # and that's OK. if opts["preview"]: extensions.wrapfunction(url, "open", previewopen) # mercurial's url.search_re includes the // and that doesn't match what we # want which is bz:dddddd(/ddddd)? files = map(fixuppath, files) # Do the import as normal. The first patch of any bug is actually imported # and the rest are stored in the global delayed_imports. The imported # patches have dumb filenames because there's no way to tell mq to pick the # patch name *after* download. ret = orig(ui, repo, *files, **opts) if ret or bzhandler.last_imported_patch() is None: return ret # If the user passed a name, then mq used that so we don't need to rename if not opts["name"]: # cache the lookup of the name. findcmd is not fast. qrename = cmdutil.findcmd("qrename", commands.table)[1][0] # Rename the already imported patch. If there are multiple patches, the # rest will be in bzhandler.delayed_imports, which we'll name correctly # in the first place. oldpatchname = q.fullseries[q.fullseriesend()] newpatchname = checkpatchname(bzhandler.last_imported_patch(), current_filename=oldpatchname) if newpatchname != oldpatchname: if newpatchname in q.series: q.delete(repo, [newpatchname], {}) qrename(ui, repo, oldpatchname, newpatchname) # mq always reports the original name, which is confusing so we'll # report the rename. But if ui.verbose is on, qrename will have already # reported it. if not ui.verbose: ui.status("renamed %s -> %s\n" % (oldpatchname, newpatchname)) # now process the delayed imports # these opts are invariant for all patches newopts = {} newopts.update(opts) newopts["force"] = True # loop through the Patches and import them by calculating their url. The # bz:// handler will have cached the lookup so we don't hit the network # here. Each one of these pushes an unapplied patch onto the beginning of # the queue, and unapplied patches are ignored when importing them, so do # these in reverse order. for patch in reversed(list(bzhandler.delayed_imports)): newopts["name"] = checkpatchname(patch) path = makebzurl(patch.bug.num, patch.id) ret = orig(ui, repo, path, **newopts) if ret: return ret