# HG changeset patch # User Alexis S. L. Carvalho # Date 1174016718 10800 # Node ID 0d51eb296fb93ca3a4035de62cd06c3da940c248 # Parent 2a8b6d78d7ee0a7b1a7a625b9cb03f4810d186ad# Parent 83153299aab5648c7fc8e8f99c6ad2e2739e2cad Merge with crew-stable diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py --- a/mercurial/cmdutil.py +++ b/mercurial/cmdutil.py @@ -138,7 +138,7 @@ def walk(repo, pats=[], opts={}, node=No exact = dict.fromkeys(files) for src, fn in repo.walk(node=node, files=files, match=matchfn, badmatch=badmatch): - yield src, fn, util.pathto(repo.getcwd(), fn), fn in exact + yield src, fn, util.pathto(repo.root, repo.getcwd(), fn), fn in exact def findrenames(repo, added=None, removed=None, threshold=0.5): '''find renamed files -- yields (before, after, score) tuples''' diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -493,7 +493,7 @@ def docopy(ui, repo, pats, opts, wlock): # target: ossep def copy(origsrc, abssrc, relsrc, target, exact): abstarget = util.canonpath(repo.root, cwd, target) - reltarget = util.pathto(cwd, abstarget) + reltarget = util.pathto(repo.root, cwd, abstarget) prevsrc = targets.get(abstarget) if prevsrc is not None: ui.warn(_('%s: not overwriting - %s collides with %s\n') % @@ -2172,9 +2172,19 @@ def revert(ui, repo, *pats, **opts): # walk target manifest. + def badmatch(path): + if path in names: + return True + path_ = path + '/' + for f in names: + if f.startswith(path_): + return True + return False + for src, abs, rel, exact in cmdutil.walk(repo, pats, opts, node=node, - badmatch=names.has_key): - if abs in names: continue + badmatch=badmatch): + if abs in names or src == 'b': + continue names[abs] = (rel, exact) target_only[abs] = True @@ -2414,11 +2424,12 @@ def status(ui, repo, *pats, **opts): format = "%s %%s%s" % (char, end) for f in changes: - ui.write(format % util.pathto(cwd, f)) + ui.write(format % util.pathto(repo.root, cwd, f)) if ((all or opts.get('copies')) and not opts.get('no_status')): copied = repo.dirstate.copied(f) if copied: - ui.write(' %s%s' % (util.pathto(cwd, copied), end)) + ui.write(' %s%s' % (util.pathto(repo.root, cwd, copied), + end)) def tag(ui, repo, name, rev_=None, **opts): """add a tag for the current or given revision diff --git a/mercurial/dirstate.py b/mercurial/dirstate.py --- a/mercurial/dirstate.py +++ b/mercurial/dirstate.py @@ -33,10 +33,14 @@ class dirstate(object): cwd = os.getcwd() if cwd == self.root: return '' # self.root ends with a path separator if self.root is '/' or 'C:\' - common_prefix_len = len(self.root) - if not self.root.endswith(os.sep): - common_prefix_len += 1 - return cwd[common_prefix_len:] + rootsep = self.root + if not rootsep.endswith(os.sep): + rootsep += os.sep + if cwd.startswith(rootsep): + return cwd[len(rootsep):] + else: + # we're outside the repo. return an absolute path. + return cwd def hgignore(self): '''return the contents of .hgignore files as a list of patterns. @@ -361,7 +365,7 @@ class dirstate(object): elif stat.S_ISSOCK(st.st_mode): kind = _('socket') elif stat.S_ISDIR(st.st_mode): kind = _('directory') self.ui.warn(_('%s: unsupported file type (type is %s)\n') % ( - util.pathto(self.getcwd(), f), + util.pathto(self.root, self.getcwd(), f), kind)) return False @@ -471,7 +475,7 @@ class dirstate(object): if not found: if inst.errno != errno.ENOENT or not badmatch: self.ui.warn('%s: %s\n' % ( - util.pathto(self.getcwd(), ff), + util.pathto(self.root, self.getcwd(), ff), inst.strerror)) elif badmatch and badmatch(ff) and imatch(nf): yield 'b', ff, None diff --git a/mercurial/hgweb/hgweb_mod.py b/mercurial/hgweb/hgweb_mod.py --- a/mercurial/hgweb/hgweb_mod.py +++ b/mercurial/hgweb/hgweb_mod.py @@ -1066,8 +1066,6 @@ class hgweb(object): headers={'status': '401 Unauthorized'}) return - req.httphdr("application/mercurial-0.1") - their_heads = req.form['heads'][0].split(' ') def check_heads(): @@ -1079,6 +1077,8 @@ class hgweb(object): bail(_('unsynced changes\n')) return + req.httphdr("application/mercurial-0.1") + # do not lock repo until all changegroup data is # streamed. save to temporary file. @@ -1089,67 +1089,78 @@ class hgweb(object): for s in util.filechunkiter(req, limit=length): fp.write(s) - lock = self.repo.lock() try: - if not check_heads(): - req.write('0\n') - req.write(_('unsynced changes\n')) - return + lock = self.repo.lock() + try: + if not check_heads(): + req.write('0\n') + req.write(_('unsynced changes\n')) + return - fp.seek(0) - header = fp.read(6) - if not header.startswith("HG"): - # old client with uncompressed bundle - def generator(f): - yield header - for chunk in f: - yield chunk - elif not header.startswith("HG10"): - req.write("0\n") - req.write(_("unknown bundle version\n")) - return - elif header == "HG10GZ": - def generator(f): - zd = zlib.decompressobj() - for chunk in f: - yield zd.decompress(chunk) - elif header == "HG10BZ": - def generator(f): - zd = bz2.BZ2Decompressor() - zd.decompress("BZ") - for chunk in f: - yield zd.decompress(chunk) - elif header == "HG10UN": - def generator(f): - for chunk in f: - yield chunk + fp.seek(0) + header = fp.read(6) + if not header.startswith("HG"): + # old client with uncompressed bundle + def generator(f): + yield header + for chunk in f: + yield chunk + elif not header.startswith("HG10"): + req.write("0\n") + req.write(_("unknown bundle version\n")) + return + elif header == "HG10GZ": + def generator(f): + zd = zlib.decompressobj() + for chunk in f: + yield zd.decompress(chunk) + elif header == "HG10BZ": + def generator(f): + zd = bz2.BZ2Decompressor() + zd.decompress("BZ") + for chunk in f: + yield zd.decompress(chunk) + elif header == "HG10UN": + def generator(f): + for chunk in f: + yield chunk + else: + req.write("0\n") + req.write(_("unknown bundle compression type\n")) + return + gen = generator(util.filechunkiter(fp, 4096)) + + # send addchangegroup output to client + + old_stdout = sys.stdout + sys.stdout = cStringIO.StringIO() + + try: + url = 'remote:%s:%s' % (proto, + req.env.get('REMOTE_HOST', '')) + try: + ret = self.repo.addchangegroup( + util.chunkbuffer(gen), 'serve', url) + except util.Abort, inst: + sys.stdout.write("abort: %s\n" % inst) + ret = 0 + finally: + val = sys.stdout.getvalue() + sys.stdout = old_stdout + req.write('%d\n' % ret) + req.write(val) + finally: + lock.release() + except (OSError, IOError), inst: + req.write('0\n') + filename = getattr(inst, 'filename', '') + # Don't send our filesystem layout to the client + if filename.startswith(self.repo.root): + filename = filename[len(self.repo.root)+1:] else: - req.write("0\n") - req.write(_("unknown bundle compression type\n")) - return - gen = generator(util.filechunkiter(fp, 4096)) - - # send addchangegroup output to client - - old_stdout = sys.stdout - sys.stdout = cStringIO.StringIO() - - try: - url = 'remote:%s:%s' % (proto, - req.env.get('REMOTE_HOST', '')) - try: - ret = self.repo.addchangegroup(util.chunkbuffer(gen), - 'serve', url) - except util.Abort, inst: - sys.stdout.write("abort: %s\n" % inst) - ret = 0 - finally: - val = sys.stdout.getvalue() - sys.stdout = old_stdout - req.write('%d\n' % ret) - req.write(val) - finally: - lock.release() + filename = '' + error = getattr(inst, 'strerror', 'Unknown error') + req.write('%s: %s\n' % (error, filename)) finally: fp.close() os.unlink(tempname) diff --git a/mercurial/httprepo.py b/mercurial/httprepo.py --- a/mercurial/httprepo.py +++ b/mercurial/httprepo.py @@ -75,6 +75,14 @@ def netlocunsplit(host, port, user=None, return userpass + '@' + hostport return hostport +# work around a bug in Python < 2.4.2 +# (it leaves a "\n" at the end of Proxy-authorization headers) +class request(urllib2.Request): + def add_header(self, key, val): + if key.lower() == 'proxy-authorization': + val = val.strip() + return urllib2.Request.add_header(self, key, val) + class httpsendfile(file): def __len__(self): return os.fstat(self.fileno()).st_size @@ -238,7 +246,7 @@ class httprepository(remoterepository): if data: self.ui.debug(_("sending %s bytes\n") % headers.get('content-length', 'X')) - resp = urllib2.urlopen(urllib2.Request(cu, data, headers)) + resp = urllib2.urlopen(request(cu, data, headers)) except urllib2.HTTPError, inst: if inst.code == 401: raise util.Abort(_('authorization failed')) diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -902,7 +902,7 @@ class localrepository(repo.repository): yield 'b', fn else: self.ui.warn(_('%s: No such file in rev %s\n') % ( - util.pathto(self.getcwd(), fn), short(node))) + util.pathto(self.root, self.getcwd(), fn), short(node))) else: for src, fn in self.dirstate.walk(files, match, badmatch=badmatch): yield src, fn diff --git a/mercurial/merge.py b/mercurial/merge.py --- a/mercurial/merge.py +++ b/mercurial/merge.py @@ -450,7 +450,10 @@ def update(repo, node, branchmerge, forc wc = repo.workingctx() if node is None: # tip of current branch - node = repo.branchtags()[wc.branch()] + try: + node = repo.branchtags()[wc.branch()] + except KeyError: + raise util.Abort(_("branch %s not found") % wc.branch()) overwrite = force and not branchmerge forcemerge = force and branchmerge pl = wc.parents() diff --git a/mercurial/patch.py b/mercurial/patch.py --- a/mercurial/patch.py +++ b/mercurial/patch.py @@ -359,7 +359,7 @@ def updatedir(ui, repo, patches, wlock=N cfiles = patches.keys() cwd = repo.getcwd() if cwd: - cfiles = [util.pathto(cwd, f) for f in patches.keys()] + cfiles = [util.pathto(repo.root, cwd, f) for f in patches.keys()] for f in patches: ctype, gp = patches[f] if ctype == 'RENAME': diff --git a/mercurial/util.py b/mercurial/util.py --- a/mercurial/util.py +++ b/mercurial/util.py @@ -325,13 +325,22 @@ def globre(pat, head='^', tail='$'): _globchars = {'[': 1, '{': 1, '*': 1, '?': 1} -def pathto(n1, n2): +def pathto(root, n1, n2): '''return the relative path from one place to another. + root should use os.sep to separate directories n1 should use os.sep to separate directories n2 should use "/" to separate directories returns an os.sep-separated path. + + If n1 is a relative path, it's assumed it's + relative to root. + n2 should always be relative to root. ''' if not n1: return localpath(n2) + if os.path.isabs(n1): + if os.path.splitdrive(root)[0] != os.path.splitdrive(n1)[0]: + return os.path.join(root, localpath(n2)) + n2 = '/'.join((pconvert(root), n2)) a, b = n1.split(os.sep), n2.split('/') a.reverse() b.reverse() diff --git a/tests/test-import b/tests/test-import --- a/tests/test-import +++ b/tests/test-import @@ -32,6 +32,17 @@ hg --cwd a diff -r0:1 > tip.patch hg --cwd b import -mpatch ../tip.patch rm -r b +echo % hg -R repo import +# put the clone in a subdir - having a directory named "a" +# used to hide a bug. +mkdir dir +hg clone -r0 a dir/b +hg --cwd a export tip > dir/tip.patch +cd dir +hg -R b import tip.patch +cd .. +rm -r dir + echo % import from stdin hg clone -r0 a b hg --cwd a export tip | hg --cwd b import - diff --git a/tests/test-import.out b/tests/test-import.out --- a/tests/test-import.out +++ b/tests/test-import.out @@ -30,6 +30,14 @@ adding file changes added 1 changesets with 2 changes to 2 files 2 files updated, 0 files merged, 0 files removed, 0 files unresolved applying ../tip.patch +% hg -R repo import +requesting all changes +adding changesets +adding manifests +adding file changes +added 1 changesets with 2 changes to 2 files +2 files updated, 0 files merged, 0 files removed, 0 files unresolved +applying tip.patch % import from stdin requesting all changes adding changesets diff --git a/tests/test-mq.out b/tests/test-mq.out --- a/tests/test-mq.out +++ b/tests/test-mq.out @@ -68,8 +68,8 @@ guards series: abort: repository already exists! % qinit; ; qinit -c -adding A -adding B +adding .hg/patches/A +adding .hg/patches/B A .hgignore A A A B diff --git a/tests/test-newbranch b/tests/test-newbranch --- a/tests/test-newbranch +++ b/tests/test-newbranch @@ -48,3 +48,7 @@ hg id hg up -q 1 hg up -q hg id +hg branch foobar +hg up + +exit 0 diff --git a/tests/test-newbranch.out b/tests/test-newbranch.out --- a/tests/test-newbranch.out +++ b/tests/test-newbranch.out @@ -83,3 +83,4 @@ 67ec16bde7f1575d523313b9bca000f6a6f12dca % update with no arguments: tipmost revision of the current branch bf1bc2f45e83 4909a3732169 (foo) tip +abort: branch foobar not found diff --git a/tests/test-revert b/tests/test-revert --- a/tests/test-revert +++ b/tests/test-revert @@ -88,5 +88,8 @@ hg revert --all -rtip echo %% issue332 hg ci -A -m b -d '1000001 0' echo foobar > b/b -hg revert b +mkdir newdir +echo foo > newdir/newfile +hg add newdir/newfile +hg revert b newdir true diff --git a/tests/test-revert.out b/tests/test-revert.out --- a/tests/test-revert.out +++ b/tests/test-revert.out @@ -61,3 +61,4 @@ reverting a %% issue332 adding b/b reverting b/b +forgetting newdir/newfile diff --git a/tests/test-walk b/tests/test-walk --- a/tests/test-walk +++ b/tests/test-walk @@ -90,3 +90,9 @@ hg rm fenugreek debugwalk fenugreek touch new debugwalk new +chdir .. +debugwalk -R t t/mammals/skunk +mkdir t2 +chdir t2 +debugwalk -R ../t ../t/mammals/skunk +debugwalk --cwd ../t mammals/skunk diff --git a/tests/test-walk.out b/tests/test-walk.out --- a/tests/test-walk.out +++ b/tests/test-walk.out @@ -276,3 +276,16 @@ m fenugreek fenugreek exact hg debugwalk new f new new exact +cd .. + +hg debugwalk -R t t/mammals/skunk +f mammals/skunk t/mammals/skunk exact + +cd t2 + +hg debugwalk -R ../t ../t/mammals/skunk +f mammals/skunk ../t/mammals/skunk exact + +hg debugwalk --cwd ../t mammals/skunk +f mammals/skunk mammals/skunk exact +