def guess_components(ui, repo, patchfile=None, **opts): bugs = set() minBugs = 20 for change in patch_changes(ui, repo, patchfile, **opts): m = BUG_RE.search(change.description()) if m: bugs.add(m.group(2)) if len(bugs) >= minBugs: break if len(bugs) == 0: ui.write("No bugs found\n") return components = Counter() url = ui.config('bugzilla', 'jsonrpc-url') if url is None: url = ui.config('bugzilla', 'url') if url is None: url = bugzilla_jsonrpc_url else: url = "%s/jsonrpc.cgi" % url for b in fetch_bugs(url, ui, bugs): comp = "%s :: %s" % (b['product'], b['component']) ui.debug("bug %s: %s\n" % (b['id'], comp)) components.update([comp]) return components
def bzbugs(ui, repo, patchfile=None, **opts): '''List the bugs that have modified the files in a patch Scan through the last LIMIT commits to find bugs that touch the same files. The patch may be given as a file or a URL. If no patch is specified, the changes in the working directory will be used. If there are no changes, the topmost applied patch in your mq repository will be used. Alternatively, the -f option may be used to pass in one or more files that will be used instead. ''' bugs = set() minBugs = 20 for change in patch_changes(ui, repo, patchfile, **opts): m = BUG_RE.search(change.description()) if m: bugs.add(m.group(2)) if len(bugs) >= minBugs: break if bugs: for bug in bugs: ui.write("bug %s\n" % bug) else: ui.write("No bugs found\n")
def extract_bug_num_and_desc(desc): # Given a commit description, attempt to return a bug number (if found), # and the description with that bug number string removed. bug = None m = BUG_RE.search(desc) if m: bug = m.group(2) desc = desc[:m.start()] + desc[m.end():] return (bug, desc.strip())
def bzcomponents(ui, repo, patchfile=None, **opts): '''Suggest a bugzilla product and component for a patch Scan through the last LIMIT commits to find bug product/components that touch the same files. The patch may be given as a file or a URL. If no patch is specified, the changes in the working directory will be used. If there are no changes, the topmost applied patch in your mq repository will be used. Alternatively, the -f option may be used to pass in one or more files that will be used to infer the component instead. ''' bugs = set() for change in patch_changes(ui, repo, patchfile, **opts): m = BUG_RE.search(change.description()) if m: bugs.add(m.group(2)) if len(bugs) == 0: ui.write("No bugs found\n") return components = Counter() url = ui.config('bugzilla', 'jsonrpc-url', None) if url is None: url = ui.config('bugzilla', 'url', None) if url is None: url = bugzilla_jsonrpc_url else: url = "%s/jsonrpc.cgi" % url for b in fetch_bugs(url, ui, bugs): comp = "%s :: %s" % (b['product'], b['component']) ui.debug("bug %s: %s\n" % (b['id'], comp)) components.update([comp]) if opts.get('brief'): if len(components) == 0: ui.write("no components found\n") else: r = [ "%s x %d" % (comp, count) for comp, count in components.most_common(3) ] ui.write(", ".join(r) + "\n") return ui.write("Potential components:\n") if len(components) == 0: ui.write(" none found in range (try higher --limit?)\n") else: for (comp, count) in components.most_common(5): ui.write(" %s: %d\n" % (comp, count))
def update_patch(ui, repo, rev, bug, update_patch, rename_patch, interactive): q = repo.mq try: rev = q.lookup(rev) except util.error.Abort: # If the patch is not coming from mq, don't complain that the name is not found update_patch = False rename_patch = False todo = [] if rename_patch: todo.append("name") if update_patch: todo.append("description") if todo: if interactive and ui.prompt("Update patch " + " and ".join(todo) + " (y/n)?") != 'y': ui.write(_("Exiting without updating patch\n")) return if rename_patch: newname = str("bug-%s-%s" % (bug, re.sub(r'^bug-\d+-', '', rev))) if newname != rev: try: mq.rename(ui, repo, rev, newname) except: # mq.rename has a tendency to leave things in an inconsistent # state. Fix things up. q.invalidate() if os.path.exists( q.join(newname)) and newname not in q.fullseries: os.rename(q.join(newname), q.join(rev)) raise rev = newname if update_patch: # Add "Bug nnnn - " to the beginning of the description ph = mq.patchheader(q.join(rev), q.plainmode) msg = [s.decode('utf-8') for s in ph.message] if not msg: msg = ["Bug %s patch" % bug] elif not BUG_RE.search(msg[0]): msg[0] = "Bug %s - %s" % (bug, msg[0]) opts = { 'git': True, 'message': '\n'.join(msg).encode('utf-8'), 'include': ["re:."] } mq.refresh(ui, repo, **opts) return rev
def update_patch(ui, repo, rev, bug, update_patch, rename_patch, interactive): q = repo.mq try: rev = q.lookup(rev) except util.error.Abort: # If the patch is not coming from mq, don't complain that the name is not found update_patch = False rename_patch = False todo = [] if rename_patch: todo.append("name") if update_patch: todo.append("description") if todo: if interactive and ui.prompt("Update patch " + " and ".join(todo) + " (y/n)?") != 'y': ui.write(_("Exiting without updating patch\n")) return if rename_patch: newname = str("bug-%s-%s" % (bug, re.sub(r'^bug-\d+-', '', rev))) if newname != rev: try: mq.rename(ui, repo, rev, newname) except: # mq.rename has a tendency to leave things in an inconsistent # state. Fix things up. q.invalidate() if os.path.exists(q.join(newname)) and newname not in q.fullseries: os.rename(q.join(newname), q.join(rev)) raise rev = newname if update_patch: # Add "Bug nnnn - " to the beginning of the description ph = mq.patchheader(q.join(rev), q.plainmode) msg = [s.decode('utf-8') for s in ph.message] if not msg: msg = ["Bug %s patch" % bug] elif not BUG_RE.search(msg[0]): msg[0] = "Bug %s - %s" % (bug, msg[0]) opts = {'git': True, 'message': '\n'.join(msg).encode('utf-8'), 'include': ["re:."]} mq.refresh(ui, repo, **opts) return rev
def bzbugs(ui, repo, patchfile=None, **opts): '''List the bugs that have modified the files in a patch Scan through the last LIMIT commits to find bugs that touch the same files. The patch may be given as a file or a URL. If no patch is specified, the changes in the working directory will be used. If there are no changes, the topmost applied patch in your mq repository will be used. Alternatively, the -f option may be used to pass in one or more files that will be used instead. ''' bugs = set() for change in patch_changes(ui, repo, patchfile, **opts): m = BUG_RE.search(change.description()) if m: bugs.add(m.group(2)) if bugs: for bug in bugs: ui.write("bug %s\n" % bug) else: ui.write("No bugs found\n")
def buglink(x): return BUG_RE.sub(BUGZILLA_LINK, x)
def parse_bugs(msg): bugs = set() m = BUG_RE.search(msg) if m: bugs.add(m.group(2)) return bugs