diff options
author | Ondřej Surý <ondrej@sury.org> | 2011-04-26 09:55:32 +0200 |
---|---|---|
committer | Ondřej Surý <ondrej@sury.org> | 2011-04-26 09:55:32 +0200 |
commit | 7b15ed9ef455b6b66c6b376898a88aef5d6a9970 (patch) | |
tree | 3ef530baa80cdf29436ba981f5783be6b4d2202b /lib | |
parent | 50104cc32a498f7517a51c8dc93106c51c7a54b4 (diff) | |
download | golang-7b15ed9ef455b6b66c6b376898a88aef5d6a9970.tar.gz |
Imported Upstream version 2011.04.13upstream/2011.04.13
Diffstat (limited to 'lib')
-rw-r--r-- | lib/codereview/codereview.py | 141 | ||||
-rw-r--r-- | lib/godoc/search.txt | 4 |
2 files changed, 118 insertions, 27 deletions
diff --git a/lib/codereview/codereview.py b/lib/codereview/codereview.py index fa703c711..766e827fc 100644 --- a/lib/codereview/codereview.py +++ b/lib/codereview/codereview.py @@ -779,7 +779,7 @@ def Incoming(ui, repo, opts): _, incoming, _ = findcommonincoming(repo, getremote(ui, repo, opts)) return incoming -desc_re = '^(.+: |tag release\.|release\.|fix build)' +desc_re = '^(.+: |(tag )?(release|weekly)\.|fix build)' desc_msg = '''Your CL description appears not to use the standard form. @@ -1135,12 +1135,27 @@ def clpatch(ui, repo, clname, **opts): if missing_codereview: return missing_codereview - cl, patch, err = DownloadCL(ui, repo, clname) + cl, vers, patch, err = DownloadCL(ui, repo, clname) if err != "": return err if patch == emptydiff: return "codereview issue %s has no diff" % clname + if not repo[vers]: + return "codereview issue %s is newer than the current repository; hg sync" % clname + + # find current hg version (hg identify) + ctx = repo[None] + parents = ctx.parents() + id = '+'.join([short(p.node()) for p in parents]) + + # if version does not match the patch version, + # try to update the patch line numbers. + if id != vers: + patch, err = portPatch(repo, patch, vers, id) + if err != "": + return "codereview issue %s is out of date: %s" % (clname, err) + argv = ["hgpatch"] if opts["no_incoming"]: argv += ["--checksync=false"] @@ -1163,6 +1178,67 @@ def clpatch(ui, repo, clname, **opts): cl.Flush(ui, repo) ui.write(cl.PendingText() + "\n") +# portPatch rewrites patch from being a patch against +# oldver to being a patch against newver. +def portPatch(repo, patch, oldver, newver): + lines = patch.splitlines(True) # True = keep \n + delta = None + for i in range(len(lines)): + line = lines[i] + if line.startswith('--- a/'): + file = line[6:-1] + delta = fileDeltas(repo, file, oldver, newver) + if not delta or not line.startswith('@@ '): + continue + # @@ -x,y +z,w @@ means the patch chunk replaces + # the original file's line numbers x up to x+y with the + # line numbers z up to z+w in the new file. + # Find the delta from x in the original to the same + # line in the current version and add that delta to both + # x and z. + m = re.match('@@ -([0-9]+),([0-9]+) \+([0-9]+),([0-9]+) @@', line) + if not m: + return None, "error parsing patch line numbers" + n1, len1, n2, len2 = int(m.group(1)), int(m.group(2)), int(m.group(3)), int(m.group(4)) + d, err = lineDelta(delta, n1, len1) + if err != "": + return "", err + n1 += d + n2 += d + lines[i] = "@@ -%d,%d +%d,%d @@\n" % (n1, len1, n2, len2) + + newpatch = ''.join(lines) + return newpatch, "" + +# fileDelta returns the line number deltas for the given file's +# changes from oldver to newver. +# The deltas are a list of (n, len, newdelta) triples that say +# lines [n, n+len) were modified, and after that range the +# line numbers are +newdelta from what they were before. +def fileDeltas(repo, file, oldver, newver): + cmd = ["hg", "diff", "--git", "-r", oldver + ":" + newver, "path:" + file] + data = RunShell(cmd, silent_ok=True) + deltas = [] + for line in data.splitlines(): + m = re.match('@@ -([0-9]+),([0-9]+) \+([0-9]+),([0-9]+) @@', line) + if not m: + continue + n1, len1, n2, len2 = int(m.group(1)), int(m.group(2)), int(m.group(3)), int(m.group(4)) + deltas.append((n1, len1, n2+len2-(n1+len1))) + return deltas + +# lineDelta finds the appropriate line number delta to apply to the lines [n, n+len). +# It returns an error if those lines were rewritten by the patch. +def lineDelta(deltas, n, len): + d = 0 + for (old, oldlen, newdelta) in deltas: + if old >= n+len: + break + if old+len > n: + return 0, "patch and recent changes conflict" + d = newdelta + return d, "" + def download(ui, repo, clname, **opts): """download a change from the code review server @@ -1172,7 +1248,7 @@ def download(ui, repo, clname, **opts): if missing_codereview: return missing_codereview - cl, patch, err = DownloadCL(ui, repo, clname) + cl, vers, patch, err = DownloadCL(ui, repo, clname) if err != "": return err ui.write(cl.EditorText() + "\n") @@ -1333,16 +1409,16 @@ def reposetup(ui, repo): def CheckContributor(ui, repo, user=None): set_status("checking CONTRIBUTORS file") - if not user: - user = ui.config("ui", "username") - if not user: - raise util.Abort("[ui] username is not configured in .hgrc") _, userline = FindContributor(ui, repo, user, warn=False) if not userline: raise util.Abort("cannot find %s in CONTRIBUTORS" % (user,)) return userline -def FindContributor(ui, repo, user, warn=True): +def FindContributor(ui, repo, user=None, warn=True): + if not user: + user = ui.config("ui", "username") + if not user: + raise util.Abort("[ui] username is not configured in .hgrc") user = user.lower() m = re.match(r".*<(.*)>", user) if m: @@ -1463,7 +1539,7 @@ def submit(ui, repo, *pats, **opts): # we're committed. upload final patch, close review, add commit message changeURL = short(node) url = other.url() - m = re.match("^https?://([^@/]+@)?([^.]+)\.googlecode\.com/hg/", url) + m = re.match("^https?://([^@/]+@)?([^.]+)\.googlecode\.com/hg/?", url) if m: changeURL = "http://code.google.com/p/%s/source/detail?r=%s" % (m.group(2), changeURL) else: @@ -1558,7 +1634,10 @@ def sync_changes(ui, repo): cl.files = Sub(cl.files, extra) cl.Flush(ui, repo) if not cl.files: - ui.warn("CL %s has no files; suggest hg change -d %s\n" % (cl.name, cl.name)) + if not cl.copied_from: + ui.warn("CL %s has no files; delete with hg change -d %s\n" % (cl.name, cl.name)) + else: + ui.warn("CL %s has no files; delete locally with hg change -D %s\n" % (cl.name, cl.name)) return def upload(ui, repo, name, **opts): @@ -1738,25 +1817,35 @@ def DownloadCL(ui, repo, clname): set_status("downloading CL " + clname) cl, err = LoadCL(ui, repo, clname) if err != "": - return None, None, "error loading CL %s: %s" % (clname, ExceptionDetail()) + return None, None, None, "error loading CL %s: %s" % (clname, err) # Grab RSS feed to learn about CL feed = XMLGet(ui, "/rss/issue/" + clname) if feed is None: - return None, None, "cannot download CL" + return None, None, None, "cannot download CL" # Find most recent diff diff = None prefix = 'http://' + server + '/' - for link in feed.findall("{http://www.w3.org/2005/Atom}entry/{http://www.w3.org/2005/Atom}link"): - if link.get('rel') != 'alternate': - continue - text = link.get('href') - if not text.startswith(prefix) or not text.endswith('.diff'): + vers = "" + for entry in feed.findall("{http://www.w3.org/2005/Atom}entry"): + thisVers = "" + for title in entry.findall("{http://www.w3.org/2005/Atom}title"): + m = re.search('diff -r ([0-9a-f]+) ', title.text) + if m: + thisVers = m.group(1) + if thisVers == "": continue - diff = text[len(prefix)-1:] + for link in entry.findall("{http://www.w3.org/2005/Atom}link"): + if link.get('rel') != 'alternate': + continue + text = link.get('href') + if not text.startswith(prefix) or not text.endswith('.diff'): + continue + diff = text[len(prefix)-1:] + vers = thisVers if diff is None: - return None, None, "CL has no diff" + return None, None, None, "CL has no diff" diffdata = MySend(diff, force_auth=False) # Find author - first entry will be author who created CL. @@ -1765,7 +1854,7 @@ def DownloadCL(ui, repo, clname): nick = author.text.strip() break if not nick: - return None, None, "CL has no author" + return None, None, None, "CL has no author" # The author is just a nickname: get the real email address. try: @@ -1775,7 +1864,7 @@ def DownloadCL(ui, repo, clname): except: ui.warn("error looking up %s: %s\n" % (nick, ExceptionDetail())) cl.copied_from = nick+"@needtofix" - return cl, diffdata, "" + return cl, vers, diffdata, "" match = re.match(r"<b>(.*) \((.*)\)</b>", data) if not match: return None, None, "error looking up %s: cannot parse result %s" % (nick, repr(data)) @@ -1784,10 +1873,12 @@ def DownloadCL(ui, repo, clname): email = match.group(1) # Print warning if email is not in CONTRIBUTORS file. - FindContributor(ui, repo, email) - cl.copied_from = email + him = FindContributor(ui, repo, email) + me = FindContributor(ui, repo, None) + if him != me: + cl.copied_from = email - return cl, diffdata, "" + return cl, vers, diffdata, "" def MySend(request_path, payload=None, content_type="application/octet-stream", @@ -1797,7 +1888,7 @@ def MySend(request_path, payload=None, try: return MySend1(request_path, payload, content_type, timeout, force_auth, **kwargs) except Exception, e: - if type(e) == urllib2.HTTPError and e.code == 403: # forbidden, it happens + if type(e) != urllib2.HTTPError or e.code != 500: # only retry on HTTP 500 error raise print >>sys.stderr, "Loading "+request_path+": "+ExceptionDetail()+"; trying again in 2 seconds." time.sleep(2) diff --git a/lib/godoc/search.txt b/lib/godoc/search.txt index eff4d36fc..967c1ac01 100644 --- a/lib/godoc/search.txt +++ b/lib/godoc/search.txt @@ -46,9 +46,9 @@ package {Pak.Name} {.end} {.section Textual} {.section Complete} -{Found} TEXTUAL OCCURENCES +{Found} TEXTUAL OCCURRENCES {.or} -MORE THAN {Found} TEXTUAL OCCURENCES +MORE THAN {Found} TEXTUAL OCCURRENCES {.end} {.repeated section @} |