# HG changeset patch # User mpm@selenic.com # Date 1118716600 28800 # Node ID 27d08c0c2a7e5fe1ad956202cdf88617f561ccfe # Parent dac675ef618949ced82e437d797083c7190faee5# Parent 67c19ad374a9862aa32f4c22d5510d449c59de3e Merge with TAH -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Merge with TAH fixup history messages to not interfere with GPG signing manifest hash: aea3a92e4699dfe0cbd98e6e2c8c6971218a59b8 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.0 (GNU/Linux) iD8DBQFCrkK4ywK+sNU5EO8RAqxHAKCNyjTE5F/7EvM+ipjhgzIUk1aWZACgm7zz eBcKlHcOA8ceUcn4IEBLQpM= =YfHT -----END PGP SIGNATURE----- diff --git a/README b/README --- a/README +++ b/README @@ -59,7 +59,7 @@ Branching and merging: $ cd .. $ mkdir linux-work $ cd linux-work - $ hg branch ../linux # create a new branch + $ hg init ../linux # create a new branch $ hg update # populate the working directory $ $ hg commit @@ -100,6 +100,9 @@ Network support: # export your current repo via HTTP with browsable interface foo$ hg serve -n "My repo" -p 80 + # pushing changes to a remote repo with SSH + foo$ hg push ssh://user@example.com/~/hg/ + # merge changes from a remote machine bar$ hg pull http://foo/ bar$ hg co # merge changes into your working directory @@ -110,10 +113,10 @@ Network support: Symbolic repository names: - Mercurial uses an optional file called ~/.hgpaths to track repo - locations symbolically. Simply add a line with the name, a space, and - a URL: + Mercurial uses an options file called ~/.hgrc. To track locations + symbolically, add a section to it like this: - foo$ echo "main http://selenic.com/hg/" >> ~/.hgpaths - foo$ hg merge main - foo$ hg co + [paths] + main = http://selenic.com/hg + hgweb = http://edge2.net/hg/hgweb/ + hgdoc = http://edge2.net/hg/man/ diff --git a/doc/hg.1.txt b/doc/hg.1.txt --- a/doc/hg.1.txt +++ b/doc/hg.1.txt @@ -188,6 +188,22 @@ FILES (which could be a local path or a remote URI), the format is with each mapping on a seperate line +NON_TRANSPARENT PROXY SUPPORT +----- + + To access a mercurial repository through a proxy, + create a file $HOME/.hgrc in the following format: + +[http_proxy] +host=myproxy:8080 +user= +passwd= +no=,,,... + + "user","passwd" fields are used for authenticating proxies, + "no" is a comma-separated list of local host names + for which proxy must be bypassed. + BUGS ---- Probably lots, please post them to the mailing list (See Resources below) diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -118,8 +118,12 @@ def show_changeset(ui, repo, rev=0, chan time.localtime(float(changes[2].split(' ')[0])))) ui.note("files: %s\n" % " ".join(changes[3])) if description: - ui.status("description: %s\n" % description[0]) - ui.note(''.join(["| %s\n" % line.rstrip() for line in description[1:]])) + if ui.verbose: + ui.status("description:\n") + ui.status(changes[4].strip()) + ui.status("\n") + else: + ui.status("summary: %s\n" % description[0]) ui.status("\n") def help(ui, cmd=None): diff --git a/mercurial/hg.py b/mercurial/hg.py --- a/mercurial/hg.py +++ b/mercurial/hg.py @@ -723,38 +723,50 @@ class localrepository: if not unknown: self.ui.status("nothing to do!\n") return None - + + rep = {} + reqcnt = 0 + unknown = remote.branches(unknown) while unknown: - n = unknown.pop(0) - seen[n[0]] = 1 - - self.ui.debug("examining %s:%s\n" % (short(n[0]), short(n[1]))) - if n == nullid: break - if n in seenbranch: - self.ui.debug("branch already found\n") - continue - if n[1] and n[1] in m: # do we know the base? - self.ui.debug("found incomplete branch %s:%s\n" - % (short(n[0]), short(n[1]))) - search.append(n) # schedule branch range for scanning - seenbranch[n] = 1 - else: - if n[2] in m and n[3] in m: - if n[1] not in fetch: - self.ui.debug("found new changeset %s\n" % - short(n[1])) - fetch.append(n[1]) # earliest unknown - continue + r = [] + while unknown: + n = unknown.pop(0) + if n[0] in seen: + continue - r = [] - for a in n[2:4]: - if a not in seen: r.append(a) - - if r: - self.ui.debug("requesting %s\n" % - " ".join(map(short, r))) - for b in remote.branches(r): + self.ui.debug("examining %s:%s\n" % (short(n[0]), short(n[1]))) + if n[0] == nullid: + break + if n in seenbranch: + self.ui.debug("branch already found\n") + continue + if n[1] and n[1] in m: # do we know the base? + self.ui.debug("found incomplete branch %s:%s\n" + % (short(n[0]), short(n[1]))) + search.append(n) # schedule branch range for scanning + seenbranch[n] = 1 + else: + if n[1] not in seen and n[1] not in fetch: + if n[2] in m and n[3] in m: + self.ui.debug("found new changeset %s\n" % + short(n[1])) + fetch.append(n[1]) # earliest unknown + continue + + for a in n[2:4]: + if a not in rep: + r.append(a) + rep[a] = 1 + + seen[n[0]] = 1 + + if r: + reqcnt += 1 + self.ui.debug("request %d: %s\n" % + (reqcnt, " ".join(map(short, r)))) + for p in range(0, len(r), 10): + for b in remote.branches(r[p:p+10]): self.ui.debug("received %s:%s\n" % (short(b[0]), short(b[1]))) if b[0] not in m and b[0] not in seen: @@ -762,10 +774,13 @@ class localrepository: while search: n = search.pop(0) + reqcnt += 1 l = remote.between([(n[0], n[1])])[0] + l.append(n[1]) p = n[0] f = 1 - for i in l + [n[1]]: + for i in l: + self.ui.debug("narrowing %d:%d %s\n" % (f, len(l), short(i))) if i in m: if f <= 2: self.ui.debug("found new branch changeset %s\n" % @@ -785,6 +800,8 @@ class localrepository: self.ui.note("adding new changesets starting at " + " ".join([short(f) for f in fetch]) + "\n") + self.ui.debug("%d total queries\n" % reqcnt) + return remote.changegroup(fetch) def changegroup(self, basenodes): @@ -1228,6 +1245,36 @@ class remoterepository: def __init__(self, ui, path): self.url = path self.ui = ui + no_list = [ "localhost", "127.0.0.1" ] + host = ui.config("http_proxy", "host") + user = ui.config("http_proxy", "user") + passwd = ui.config("http_proxy", "passwd") + no = ui.config("http_proxy", "no") + if no: + no_list = no_list + no.split(",") + + no_proxy = 0 + for h in no_list: + if (path.startswith("http://" + h + "/") or + path.startswith("http://" + h + ":") or + path == "http://" + h): + no_proxy = 1 + + # Note: urllib2 takes proxy values from the environment and those will + # take precedence + + proxy_handler = urllib2.BaseHandler() + if host and not no_proxy: + proxy_handler = urllib2.ProxyHandler({"http" : "http://" + host}) + + authinfo = None + if user and passwd: + passmgr = urllib2.HTTPPasswordMgrWithDefaultRealm() + passmgr.add_password(None, host, user, passwd) + authinfo = urllib2.ProxyBasicAuthHandler(passmgr) + + opener = urllib2.build_opener(proxy_handler, authinfo) + urllib2.install_opener(opener) def do_cmd(self, cmd, **args): self.ui.debug("sending %s command\n" % cmd) @@ -1235,7 +1282,7 @@ class remoterepository: q.update(args) qs = urllib.urlencode(q) cu = "%s?%s" % (self.url, qs) - return urllib.urlopen(cu) + return urllib2.urlopen(cu) def heads(self): d = self.do_cmd("heads").read() diff --git a/mercurial/hgweb.py b/mercurial/hgweb.py --- a/mercurial/hgweb.py +++ b/mercurial/hgweb.py @@ -135,6 +135,7 @@ class hgweb: def refresh(self): s = os.stat(os.path.join(self.path, ".hg", "00changelog.i")) if s.st_mtime != self.mtime: + self.mtime = s.st_mtime self.repo = repository(ui(), self.path) def date(self, cs): diff --git a/mercurial/mdiff.py b/mercurial/mdiff.py --- a/mercurial/mdiff.py +++ b/mercurial/mdiff.py @@ -43,28 +43,41 @@ def textdiff(a, b): def sortdiff(a, b): la = lb = 0 - + lena = len(a) + lenb = len(b) + while 1: - if la >= len(a) or lb >= len(b): break - if b[lb] < a[la]: - si = lb - while lb < len(b) and b[lb] < a[la] : lb += 1 - yield "insert", la, la, si, lb - elif a[la] < b[lb]: - si = la - while la < len(a) and a[la] < b[lb]: la += 1 - yield "delete", si, la, lb, lb - else: + am, bm, = la, lb + + # walk over matching lines + while lb < lenb and la < lena and a[la] == b[lb] : la += 1 lb += 1 - if lb < len(b): - yield "insert", la, la, lb, len(b) + if la > am: + yield (am, bm, la - am) # return a match + + # skip mismatched lines from b + while lb < lenb and b[lb] < a[la]: + lb += 1 - if la < len(a): - yield "delete", la, len(a), lb, lb + if lb >= lenb: + break + + # skip mismatched lines from a + while la < lena and b[lb] > a[la]: + la += 1 + + if la >= lena: + break + + yield (lena, lenb, 0) def diff(a, b, sorted=0): + if not a: + s = "".join(b) + return s and (struct.pack(">lll", 0, 0, len(s)) + s) + bin = [] p = [0] for i in a: p.append(p[-1] + len(i)) @@ -76,13 +89,16 @@ def diff(a, b, sorted=0): print a, b raise else: - d = difflib.SequenceMatcher(None, a, b).get_opcodes() - - for o, m, n, s, t in d: - if o == 'equal': continue - s = "".join(b[s:t]) - bin.append(struct.pack(">lll", p[m], p[n], len(s)) + s) - + d = difflib.SequenceMatcher(None, a, b).get_matching_blocks() + la = 0 + lb = 0 + for am, bm, size in d: + s = "".join(b[lb:bm]) + if am > la or s: + bin.append(struct.pack(">lll", p[la], p[am], len(s)) + s) + la = am + size + lb = bm + size + return "".join(bin) def patchtext(bin): diff --git a/mercurial/revlog.py b/mercurial/revlog.py --- a/mercurial/revlog.py +++ b/mercurial/revlog.py @@ -43,17 +43,28 @@ nullid = "\0" * 20 indexformat = ">4l20s20s20s" class lazyparser: - def __init__(self, data): + def __init__(self, data, revlog): self.data = data self.s = struct.calcsize(indexformat) self.l = len(data)/self.s self.index = [None] * self.l self.map = {nullid: -1} + self.all = 0 + self.revlog = revlog - def load(self, pos): - block = pos / 1000 - i = block * 1000 - end = min(self.l, i + 1000) + def load(self, pos=None): + if self.all: return + if pos is not None: + block = pos / 1000 + i = block * 1000 + end = min(self.l, i + 1000) + else: + self.all = 1 + i = 0 + end = self.l + self.revlog.index = self.index + self.revlog.nodemap = self.map + while i < end: d = self.data[i * self.s: (i + 1) * self.s] e = struct.unpack(indexformat, d) @@ -78,16 +89,14 @@ class lazymap: def __init__(self, parser): self.p = parser def load(self, key): + if self.p.all: return n = self.p.data.find(key) if n < 0: raise KeyError("node " + hex(key)) pos = n / self.p.s self.p.load(pos) def __contains__(self, key): - try: - self[key] - return True - except KeyError: - return False + self.p.load() + return key in self.p.map def __iter__(self): for i in xrange(self.p.l): try: @@ -121,7 +130,7 @@ class revlog: if len(i) > 10000: # big index, let's parse it on demand - parser = lazyparser(i) + parser = lazyparser(i, self) self.index = lazyindex(parser) self.nodemap = lazymap(parser) else: