Mercurial > hg
changeset 2646:ddf404954092
merge with tonfa-experimental
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Wed, 19 Jul 2006 14:22:08 -0500 |
parents | 02b6fa7bbfbf (diff) 9bd3d44c32f6 (current diff) |
children | e57df017640d |
files | mercurial/commands.py |
diffstat | 26 files changed, 593 insertions(+), 65 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/contrib/sample.hgrc Wed Jul 19 14:22:08 2006 -0500 @@ -0,0 +1,123 @@ +### --- User interface + +[ui] + +### show changed files and be a bit more verbose if True + +# verbose = True + +### username data to appear in comits +### it usually takes the form: Joe User <joe.user@host.com> + +# username = Joe User <j.user@example.com> + +### --- Extensions + +[extensions] + +### each extension has its own 'extension_name=path' line +### the default python library path is used when path is left blank +### the hgext dir is used when 'hgext.extension_name=' is written + +### acl - Access control lists +### hg help acl + +# hgext.acl = + +### bisect - binary search changesets to detect bugs +### hg help bisect + +# hgext.hbisect = + +### bugzilla - update bugzilla bugs when changesets mention them +### hg help bugzilla + +# hgext.bugzilla = + +### extdiff - Use external diff application instead of builtin one + +# hgext.extdiff = + +### gpg - GPG checks and signing +### hg help gpg + +# hgext.gpg = + +### hgk - GUI repository browser +### hg help view + +# hgk = /home/user/hg/hg/contrib/hgk.py + +### mq - Mercurial patch queues +### hg help mq + +# hgext.mq = + +### notify - Template driven e-mail notifications +### hg help notify + +# hgext.notify = + +### patchbomb - send changesets as a series of patch emails +### hg help email + +# hgext.patchbomb = + +### win32text - line ending conversion filters for the Windows platform + +# hgext.win32text = + +### --- hgk additional configuration + +[hgk] + +### set executable path + +# path = /home/user/hg/hg/contrib/hgk + +### --- Hook to Mercurial actions - See hgrc man page for avaliable hooks + +[hooks] + +### Example notify hooks (load hgext.notify extension before use) + +# incoming.notify = python:hgext.notify.hook +# changegroup.notify = python:hgext.notify.hook + +### Email configuration for the notify and patchbomb extensions + +[email] + +### Your email address + +# from = user@example.com + +### Method to send email - smtp or /usr/sbin/sendmail or other program name + +# method = smtp + +### smtp server to send email to + +[smtp] + +# host = mail +# port = 25 +# tls = false +# username = user +# password = blivet +# local_hostname = myhost + +### --- Email notification hook for server + +[notify] +### multiple sources can be specified as a whitespace or comma separated list + +# sources = serve push pull bundle + +### set this to False when you're ready for mail to start sending + +# test = True + +### path to config file with names of subscribers + +# config = /path/to/subscription/file
--- a/contrib/vim/hgcommand.vim Mon Jul 17 02:09:35 2006 +0200 +++ b/contrib/vim/hgcommand.vim Wed Jul 19 14:22:08 2006 -0500 @@ -171,7 +171,7 @@ endif let hgCommand = s:HGGetOption("HGCommandHGExec", "hg") . " " . a:cmd - echomsg "DBG :".hgCommand + "echomsg "DBG :".hgCommand let hgOut = system(hgCommand) " HACK: diff command does not return proper error codes if v:shell_error && a:cmdName != 'hgdiff' @@ -315,18 +315,27 @@ function! s:HGGetStatusVars(revisionVar, branchVar, repositoryVar) let hgBufferCheck=s:HGCurrentBufferCheck() + "echomsg "DBG : in HGGetStatusVars" if hgBufferCheck == -1 return "" endif let fileName=bufname(hgBufferCheck) - let realFileName = fnamemodify(s:HGResolveLink(fileName), ':t') - let oldCwd=s:HGChangeToCurrentFileDir(fileName) + let fileNameWithoutLink=s:HGResolveLink(fileName) + let realFileName = fnamemodify(fileNameWithoutLink, ':t') + let oldCwd=s:HGChangeToCurrentFileDir(realFileName) try - ""TODO - "if !filereadable('HG/Root') - "return "" - "endif - let hgCommand = s:HGGetOption("HGCommandHGExec", "hg") . " status -mardui " . fileName + let hgCommand = s:HGGetOption("HGCommandHGExec", "hg") . " root " + let roottext=system(hgCommand) + " Suppress ending null char ! Does it work in window ? + let roottext=substitute(roottext,'^.*/\([^/\n\r]*\)\n\_.*$','\1','') + if match(getcwd()."/".fileNameWithoutLink, roottext) == -1 + return "" + endif + let returnExpression = "" + if a:repositoryVar != "" + let returnExpression=returnExpression . " | let " . a:repositoryVar . "='" . roottext . "'" + endif + let hgCommand = s:HGGetOption("HGCommandHGExec", "hg") . " status -mardui " . realFileName let statustext=system(hgCommand) if(v:shell_error) return "" @@ -339,32 +348,23 @@ let revision="DELETED" elseif match(statustext, '^[A]') >= 0 let revision="ADDED" - endif + else + " The file is tracked, we can try to get is revision number + let hgCommand = s:HGGetOption("HGCommandHGExec", "hg") . " parents -b " + let statustext=system(hgCommand) + if(v:shell_error) + return "" + endif + let revision=substitute(statustext, '^changeset:\s*\(\d\+\):.*\_$\_.*$', '\1', "") - let hgCommand = s:HGGetOption("HGCommandHGExec", "hg") . " parents -b " - let statustext=system(hgCommand) - if(v:shell_error) - return "" - endif - if exists('revision') - let returnExpression = "let " . a:revisionVar . "='" . revision . "'" - else - let revision=substitute(statustext, '^changeset:\s*\(\d\+\):.*\_$\_.*$', '\1', "") - let returnExpression = "let " . a:revisionVar . "='" . revision . "'" + if a:branchVar != "" && match(statustext, '^\_.*\_^branch:') >= 0 + let branch=substitute(statustext, '^\_.*\_^branch:\s*\(\S\+\)\n\_.*$', '\1', "") + let returnExpression=returnExpression . " | let " . a:branchVar . "='" . branch . "'" + endif endif - - if a:branchVar != "" && match(statustext, '^\_.*\_^branch:') >= 0 - let branch=substitute(statustext, '^\_.*\_^branch:\s*\(\S\+\)\n\_.*$', '\1', "") - let returnExpression=returnExpression . " | let " . a:branchVar . "='" . branch . "'" + if (exists('revision')) + let returnExpression = "let " . a:revisionVar . "='" . revision . "' " . returnExpression endif - if a:repositoryVar != "" - let hgCommand = s:HGGetOption("HGCommandHGExec", "hg") . " root " - let roottext=system(hgCommand) - let repository=substitute(roottext,'^.*/\([^/\n\r]*\)\n\_.*$','\1','') - let returnExpression=returnExpression . " | let " . a:repositoryVar . "='" . repository . "'" - endif - - return returnExpression finally @@ -432,6 +432,11 @@ if origBuffer != a:hgBuffer call setbufvar(origBuffer, "HGBufferSetup", 0) endif + else + "We are presumably in the original buffer + let b:HGBufferSetup = 0 + "We do the setup now as now event will be triggered allowing it later. + call s:HGSetupBuffer() endif return a:hgBuffer endfunction @@ -608,6 +613,7 @@ augroup HGCommandPlugin au! au BufEnter * call s:HGSetupBuffer() + au BufWritePost * call s:HGSetupBuffer() " Force resetting up buffer on external file change (HG update) au FileChangedShell * call s:HGSetupBuffer(1) augroup END @@ -686,7 +692,7 @@ endif let resultBuffer=s:HGDoCommand('annotate -ndu -r ' . revision, 'hgannotate', revision) - echomsg "DBG: ".resultBuffer + "echomsg "DBG: ".resultBuffer if resultBuffer != -1 set filetype=HGAnnotate endif @@ -754,8 +760,7 @@ \ ':call <SID>HGFinishCommit("' . messageFileName . '",' . \ '"' . newCwd . '",' . \ '"' . realFileName . '",' . - \ hgBufferCheck . ')<CR>'. - \ ':call <SID>HGBufferSetup(1)<CR>' + \ hgBufferCheck . ')<CR>' silent 0put ='HG: ----------------------------------------------------------------------' silent put =\"HG: Enter Log. Lines beginning with `HG:' are removed automatically\" @@ -840,7 +845,7 @@ if strlen(a:targetDir) > 0 execute 'cd' escape(a:targetDir, ' ') endif - let resultBuffer=s:HGCreateCommandBuffer('commit -F "' . a:messageFile . '" "'. a:targetFile . '"', 'hgcommit', '', a:origBuffNR) + let resultBuffer=s:HGCreateCommandBuffer('commit -l "' . a:messageFile . '" "'. a:targetFile . '"', 'hgcommit', '', a:origBuffNR) execute 'cd' escape(oldCwd, ' ') execute 'bw' escape(a:messageFile, ' *?\') silent execute 'call delete("' . a:messageFile . '")' @@ -908,7 +913,6 @@ " Function: s:HGUpdate() {{{2 function! s:HGUpdate() return s:HGMarkOrigBufferForSetup(s:HGDoCommand('update', 'update', '')) - call s:HGSetupBuffer(1) endfunction " Function: s:HGVimDiff(...) {{{2 @@ -1673,6 +1677,11 @@ may still be bugs in here, depending on many configuration details. ============================================================================== + +9. TODO *hgcommand-todo* + + Integrate symlink tracking once HG will support them. +============================================================================== === END_DOC """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " v im:tw=78:ts=8:ft=help:norl:
--- a/doc/hgrc.5.txt Mon Jul 17 02:09:35 2006 +0200 +++ b/doc/hgrc.5.txt Wed Jul 19 14:22:08 2006 -0500 @@ -317,7 +317,7 @@ Assigns symbolic names to repositories. The left side is the symbolic name, and the right gives the directory or URL that is the location of the repository. Default paths can be declared by - setting the following entries. + setting the following entries. default;; Directory or URL to use when pulling if no source is specified. Default is set to repository from which the current repository @@ -326,6 +326,18 @@ Optional. Directory or URL to use when pushing if no destination is specified. +server:: + Controls generic server settings. + uncompressed;; + Whether to allow clients to clone a repo using the uncompressed + streaming protocol. This transfers about 40% more data than a + regular clone, but uses less memory and CPU on both server and + client. Over a LAN (100Mbps or better) or a very fast WAN, an + uncompressed streaming clone is a lot faster (~10x) than a regular + clone. Over most WAN connections (anything slower than about + 6Mbps), uncompressed streaming is slower, because of the extra + data transfer overhead. Default is False. + ui:: User interface controls. debug;;
--- a/mercurial/commands.py Mon Jul 17 02:09:35 2006 +0200 +++ b/mercurial/commands.py Wed Jul 19 14:22:08 2006 -0500 @@ -869,11 +869,22 @@ if op2 != nullid: raise util.Abort(_('outstanding uncommitted merge')) node = repo.lookup(rev) - parent, p2 = repo.changelog.parents(node) - if parent == nullid: + p1, p2 = repo.changelog.parents(node) + if p1 == nullid: raise util.Abort(_('cannot back out a change with no parents')) if p2 != nullid: - raise util.Abort(_('cannot back out a merge')) + if not opts['parent']: + raise util.Abort(_('cannot back out a merge changeset without ' + '--parent')) + p = repo.lookup(opts['parent']) + if p not in (p1, p2): + raise util.Abort(_('%s is not a parent of %s' % + (short(p), short(node)))) + parent = p + else: + if opts['parent']: + raise util.Abort(_('cannot use --parent on non-merge changeset')) + parent = p1 repo.update(node, force=True, show_stats=False) revert_opts = opts.copy() revert_opts['rev'] = hex(parent) @@ -963,6 +974,7 @@ ui.setconfig_remoteopts(**opts) hg.clone(ui, ui.expandpath(source), dest, pull=opts['pull'], + stream=opts['uncompressed'], rev=opts['rev'], update=not opts['noupdate']) @@ -2612,6 +2624,7 @@ ! = deleted, but still tracked ? = not tracked I = ignored (not shown by default) + = the previous added file was copied from here """ show_ignored = opts['ignored'] and True or False @@ -2640,6 +2653,9 @@ for f in changes: ui.write(format % f) + if (opts.get('copies') and not opts.get('no_status') + and opt == 'added' and repo.dirstate.copies.has_key(f)): + ui.write(' %s%s' % (repo.dirstate.copies[f], end)) def tag(ui, repo, name, rev_=None, **opts): """add a tag for the current tip or a given revision @@ -2847,6 +2863,7 @@ ('m', 'message', '', _('use <text> as commit message')), ('l', 'logfile', '', _('read commit message from <file>')), ('d', 'date', '', _('record datecode as commit date')), + ('', 'parent', '', _('parent to choose when backing out merge')), ('u', 'user', '', _('record user as committer')), ('I', 'include', [], _('include names matching the given patterns')), ('X', 'exclude', [], _('exclude names matching the given patterns'))], @@ -2869,6 +2886,8 @@ ('r', 'rev', [], _('a changeset you would like to have after cloning')), ('', 'pull', None, _('use pull protocol to copy metadata')), + ('', 'uncompressed', None, + _('use uncompressed transfer (fast over LAN)')), ('e', 'ssh', '', _('specify ssh command to use')), ('', 'remotecmd', '', _('specify hg command to run on the remote side'))], @@ -3127,6 +3146,7 @@ ('u', 'unknown', None, _('show only unknown (not tracked) files')), ('i', 'ignored', None, _('show ignored files')), ('n', 'no-status', None, _('hide status prefix')), + ('C', 'copies', None, _('show source of copied files')), ('0', 'print0', None, _('end filenames with NUL, for use with xargs')), ('I', 'include', [], _('include names matching the given patterns')),
--- a/mercurial/hg.py Mon Jul 17 02:09:35 2006 +0200 +++ b/mercurial/hg.py Wed Jul 19 14:22:08 2006 -0500 @@ -74,7 +74,8 @@ scheme) return ctor(ui, path) -def clone(ui, source, dest=None, pull=False, rev=None, update=True): +def clone(ui, source, dest=None, pull=False, rev=None, update=True, + stream=False): """Make a copy of an existing repository. Create a copy of an existing repository in a new directory. The @@ -96,6 +97,9 @@ pull: always pull from source repository, even in local case + stream: stream raw data uncompressed from repository (fast over + LAN, slow over WAN) + rev: revision to clone up to (implies pull=True) update: update working directory after clone completes, if @@ -153,9 +157,9 @@ # we lock here to avoid premature writing to the target dest_lock = lock.lock(os.path.join(dest_path, ".hg", "lock")) - # we need to remove the (empty) data dir in dest so copyfiles - # can do its work - os.rmdir(os.path.join(dest_path, ".hg", "data")) + # we need to remove the (empty) data dir in dest so copyfiles + # can do its work + os.rmdir(os.path.join(dest_path, ".hg", "data")) files = "data 00manifest.d 00manifest.i 00changelog.d 00changelog.i" for f in files.split(): src = os.path.join(source, ".hg", f) @@ -166,8 +170,8 @@ if inst.errno != errno.ENOENT: raise - # we need to re-init the repo after manually copying the data - # into it + # we need to re-init the repo after manually copying the data + # into it dest_repo = repository(ui, dest) else: @@ -179,7 +183,7 @@ revs = [src_repo.lookup(r) for r in rev] if dest_repo.local(): - dest_repo.pull(src_repo, heads=revs) + dest_repo.clone(src_repo, heads=revs, stream=stream) elif src_repo.local(): src_repo.push(dest_repo, revs=revs) else:
--- a/mercurial/hgweb/hgweb_mod.py Mon Jul 17 02:09:35 2006 +0200 +++ b/mercurial/hgweb/hgweb_mod.py Wed Jul 19 14:22:08 2006 -0500 @@ -11,7 +11,8 @@ import mimetypes from mercurial.demandload import demandload demandload(globals(), "re zlib ConfigParser mimetools cStringIO sys tempfile") -demandload(globals(), "mercurial:mdiff,ui,hg,util,archival,templater") +demandload(globals(), "mercurial:mdiff,ui,hg,util,archival,streamclone") +demandload(globals(), "mercurial:templater") demandload(globals(), "mercurial.hgweb.common:get_mtime,staticfile") from mercurial.node import * from mercurial.i18n import gettext as _ @@ -859,7 +860,10 @@ or self.t("error", error="%r not found" % fname)) def do_capabilities(self, req): - resp = 'unbundle' + caps = ['unbundle'] + if self.repo.ui.configbool('server', 'uncompressed'): + caps.append('stream=%d' % self.repo.revlogversion) + resp = ' '.join(caps) req.httphdr("application/mercurial-0.1", length=len(resp)) req.write(resp) @@ -950,3 +954,7 @@ finally: fp.close() os.unlink(tempname) + + def do_stream_out(self, req): + req.httphdr("application/mercurial-0.1") + streamclone.stream_out(self.repo, req)
--- a/mercurial/httprepo.py Mon Jul 17 02:09:35 2006 +0200 +++ b/mercurial/httprepo.py Wed Jul 19 14:22:08 2006 -0500 @@ -326,6 +326,9 @@ fp.close() os.unlink(tempname) + def stream_out(self): + return self.do_cmd('stream_out') + class httpsrepository(httprepository): def __init__(self, ui, path): if not has_https:
--- a/mercurial/localrepo.py Mon Jul 17 02:09:35 2006 +0200 +++ b/mercurial/localrepo.py Wed Jul 19 14:22:08 2006 -0500 @@ -8,17 +8,19 @@ from node import * from i18n import gettext as _ from demandload import * +import repo demandload(globals(), "appendfile changegroup") -demandload(globals(), "changelog dirstate filelog manifest repo context") +demandload(globals(), "changelog dirstate filelog manifest context") demandload(globals(), "re lock transaction tempfile stat mdiff errno ui") -demandload(globals(), "os revlog util") +demandload(globals(), "os revlog time util") -class localrepository(object): +class localrepository(repo.repository): capabilities = () def __del__(self): self.transhandle = None def __init__(self, parentui, path=None, create=0): + repo.repository.__init__(self) if not path: p = os.getcwd() while not os.path.isdir(os.path.join(p, ".hg")): @@ -1183,7 +1185,7 @@ # unbundle assumes local user cannot lock remote repo (new ssh # servers, http servers). - if 'unbundle' in remote.capabilities: + if remote.capable('unbundle'): return self.push_unbundle(remote, force, revs) return self.push_addchangegroup(remote, force, revs) @@ -2201,6 +2203,50 @@ self.ui.warn(_("%d integrity errors encountered!\n") % errors[0]) return 1 + def stream_in(self, remote): + fp = remote.stream_out() + resp = int(fp.readline()) + if resp != 0: + raise util.Abort(_('operation forbidden by server')) + self.ui.status(_('streaming all changes\n')) + total_files, total_bytes = map(int, fp.readline().split(' ', 1)) + self.ui.status(_('%d files to transfer, %s of data\n') % + (total_files, util.bytecount(total_bytes))) + start = time.time() + for i in xrange(total_files): + name, size = fp.readline().split('\0', 1) + size = int(size) + self.ui.debug('adding %s (%s)\n' % (name, util.bytecount(size))) + ofp = self.opener(name, 'w') + for chunk in util.filechunkiter(fp, limit=size): + ofp.write(chunk) + ofp.close() + elapsed = time.time() - start + self.ui.status(_('transferred %s in %.1f seconds (%s/sec)\n') % + (util.bytecount(total_bytes), elapsed, + util.bytecount(total_bytes / elapsed))) + self.reload() + return len(self.heads()) + 1 + + def clone(self, remote, heads=[], stream=False): + '''clone remote repository. + + keyword arguments: + heads: list of revs to clone (forces use of pull) + stream: use streaming clone if possible''' + + # now, all clients that can request uncompressed clones can + # read repo formats supported by all servers that can serve + # them. + + # if revlog format changes, client will have to check version + # and format flags on "stream" capability, and use + # uncompressed only if compatible. + + if stream and not heads and remote.capable('stream'): + return self.stream_in(remote) + return self.pull(remote, heads) + # used to avoid circular references so destructors work def aftertrans(base): p = base
--- a/mercurial/remoterepo.py Mon Jul 17 02:09:35 2006 +0200 +++ b/mercurial/remoterepo.py Wed Jul 19 14:22:08 2006 -0500 @@ -5,7 +5,9 @@ # This software may be used and distributed according to the terms # of the GNU General Public License, incorporated herein by reference. -class remoterepository(object): +import repo + +class remoterepository(repo.repository): def dev(self): return -1
--- a/mercurial/repo.py Mon Jul 17 02:09:35 2006 +0200 +++ b/mercurial/repo.py Wed Jul 19 14:22:08 2006 -0500 @@ -5,4 +5,19 @@ # This software may be used and distributed according to the terms # of the GNU General Public License, incorporated herein by reference. -class RepoError(Exception): pass +class RepoError(Exception): + pass + +class repository(object): + def capable(self, name): + '''tell whether repo supports named capability. + return False if not supported. + if boolean capability, return True. + if string capability, return string.''' + name_eq = name + '=' + for cap in self.capabilities: + if name == cap: + return True + if cap.startswith(name_eq): + return cap[len(name_eq):] + return False
--- a/mercurial/sshrepo.py Mon Jul 17 02:09:35 2006 +0200 +++ b/mercurial/sshrepo.py Wed Jul 19 14:22:08 2006 -0500 @@ -198,3 +198,6 @@ if not r: return 1 return int(r) + + def stream_out(self): + return self.do_cmd('stream_out')
--- a/mercurial/sshserver.py Mon Jul 17 02:09:35 2006 +0200 +++ b/mercurial/sshserver.py Wed Jul 19 14:22:08 2006 -0500 @@ -8,7 +8,7 @@ from demandload import demandload from i18n import gettext as _ from node import * -demandload(globals(), "os sys tempfile util") +demandload(globals(), "os streamclone sys tempfile util") class sshserver(object): def __init__(self, ui, repo): @@ -60,8 +60,10 @@ capabilities: space separated list of tokens ''' - r = "capabilities: unbundle\n" - self.respond(r) + caps = ['unbundle'] + if self.ui.configbool('server', 'uncompressed'): + caps.append('stream=%d' % self.repo.revlogversion) + self.respond("capabilities: %s\n" % (' '.join(caps),)) def do_lock(self): '''DEPRECATED - allowing remote client to lock repo is not safe''' @@ -167,3 +169,5 @@ fp.close() os.unlink(tempname) + def do_stream_out(self): + streamclone.stream_out(self.repo, self.fout)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial/streamclone.py Wed Jul 19 14:22:08 2006 -0500 @@ -0,0 +1,90 @@ +# streamclone.py - streaming clone server support for mercurial +# +# Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com> +# +# This software may be used and distributed according to the terms +# of the GNU General Public License, incorporated herein by reference. + +from demandload import demandload +from i18n import gettext as _ +demandload(globals(), "os stat util") + +# if server supports streaming clone, it advertises "stream" +# capability with value that is version+flags of repo it is serving. +# client only streams if it can read that repo format. + +def walkrepo(root): + '''iterate over metadata files in repository. + walk in natural (sorted) order. + yields 2-tuples: name of .d or .i file, size of file.''' + + strip_count = len(root) + len(os.sep) + def walk(path, recurse): + ents = os.listdir(path) + ents.sort() + for e in ents: + pe = os.path.join(path, e) + st = os.lstat(pe) + if stat.S_ISDIR(st.st_mode): + if recurse: + for x in walk(pe, True): + yield x + else: + if not stat.S_ISREG(st.st_mode) or len(e) < 2: + continue + sfx = e[-2:] + if sfx in ('.d', '.i'): + yield pe[strip_count:], st.st_size + # write file data first + for x in walk(os.path.join(root, 'data'), True): + yield x + # write manifest before changelog + meta = list(walk(root, False)) + meta.sort() + meta.reverse() + for x in meta: + yield x + +# stream file format is simple. +# +# server writes out line that says how many files, how many total +# bytes. separator is ascii space, byte counts are strings. +# +# then for each file: +# +# server writes out line that says file name, how many bytes in +# file. separator is ascii nul, byte count is string. +# +# server writes out raw file data. + +def stream_out(repo, fileobj): + '''stream out all metadata files in repository. + writes to file-like object, must support write() and optional flush().''' + + if not repo.ui.configbool('server', 'uncompressed'): + fileobj.write('1\n') + return + + fileobj.write('0\n') + + # get consistent snapshot of repo. lock during scan so lock not + # needed while we stream, and commits can happen. + lock = repo.lock() + repo.ui.debug('scanning\n') + entries = [] + total_bytes = 0 + for name, size in walkrepo(repo.path): + entries.append((name, size)) + total_bytes += size + lock.release() + + repo.ui.debug('%d files, %d bytes to transfer\n' % + (len(entries), total_bytes)) + fileobj.write('%d %d\n' % (len(entries), total_bytes)) + for name, size in entries: + repo.ui.debug('sending %s (%d bytes)\n' % (name, size)) + fileobj.write('%s\0%d\n' % (name, size)) + for chunk in util.filechunkiter(repo.opener(name), limit=size): + fileobj.write(chunk) + flush = getattr(fileobj, 'flush', None) + if flush: flush()
--- a/mercurial/util.py Mon Jul 17 02:09:35 2006 +0200 +++ b/mercurial/util.py Wed Jul 19 14:22:08 2006 -0500 @@ -961,3 +961,24 @@ else: _rcpath = os_rcpath() return _rcpath + +def bytecount(nbytes): + '''return byte count formatted as readable string, with units''' + + units = ( + (100, 1<<30, _('%.0f GB')), + (10, 1<<30, _('%.1f GB')), + (1, 1<<30, _('%.2f GB')), + (100, 1<<20, _('%.0f MB')), + (10, 1<<20, _('%.1f MB')), + (1, 1<<20, _('%.2f MB')), + (100, 1<<10, _('%.0f KB')), + (10, 1<<10, _('%.1f KB')), + (1, 1<<10, _('%.2f KB')), + (1, 1, _('%.0f bytes')), + ) + + for multiplier, divisor, format in units: + if nbytes >= divisor * multiplier: + return format % (nbytes / float(divisor)) + return units[-1][2] % nbytes
--- a/tests/test-backout Mon Jul 17 02:09:35 2006 +0200 +++ b/tests/test-backout Wed Jul 19 14:22:08 2006 -0500 @@ -60,4 +60,40 @@ hg backout -d '3 0' 1 hg locate b +cd .. +hg init m +cd m +echo a > a +hg commit -d '0 0' -A -m a +echo b > b +hg commit -d '1 0' -A -m b +echo c > c +hg commit -d '2 0' -A -m b +hg update 1 +echo d > d +hg commit -d '3 0' -A -m c +hg merge 2 +hg commit -d '4 0' -A -m d + +echo '# backout of merge should fail' + +hg backout 4 + +echo '# backout of merge with bad parent should fail' + +hg backout --parent 0 4 + +echo '# backout of non-merge with parent should fail' + +hg backout --parent 0 3 + +echo '# backout with valid parent should be ok' + +hg backout -d '5 0' --parent 2 4 + +hg rollback +hg update -C + +hg backout -d '6 0' --parent 3 4 + exit 0
--- a/tests/test-backout.out Mon Jul 17 02:09:35 2006 +0200 +++ b/tests/test-backout.out Wed Jul 19 14:22:08 2006 -0500 @@ -29,3 +29,23 @@ the backout changeset is a new head - do not forget to merge (use "backout -m" if you want to auto-merge) b: No such file or directory +adding a +adding b +adding c +0 files updated, 0 files merged, 1 files removed, 0 files unresolved +adding d +1 files updated, 0 files merged, 0 files removed, 0 files unresolved +(branch merge, don't forget to commit) +# backout of merge should fail +abort: cannot back out a merge changeset without --parent +# backout of merge with bad parent should fail +abort: cb9a9f314b8b is not a parent of b2f3bb92043e +# backout of non-merge with parent should fail +abort: cannot use --parent on non-merge changeset +# backout with valid parent should be ok +removing d +changeset 5:11fbd9be634c backs out changeset 4:b2f3bb92043e +rolling back last transaction +1 files updated, 0 files merged, 0 files removed, 0 files unresolved +removing c +changeset 5:1a5f1a63bf2c backs out changeset 4:b2f3bb92043e
--- a/tests/test-help.out Mon Jul 17 02:09:35 2006 +0200 +++ b/tests/test-help.out Wed Jul 19 14:22:08 2006 -0500 @@ -195,6 +195,7 @@ ! = deleted, but still tracked ? = not tracked I = ignored (not shown by default) + = the previous added file was copied from here aliases: st @@ -207,6 +208,7 @@ -u --unknown show only unknown (not tracked) files -i --ignored show ignored files -n --no-status hide status prefix + -C --copies show source of copied files -0 --print0 end filenames with NUL, for use with xargs -I --include include names matching the given patterns -X --exclude exclude names matching the given patterns
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-http Wed Jul 19 14:22:08 2006 -0500 @@ -0,0 +1,25 @@ +#!/bin/sh + +hg init test +cd test +echo foo>foo +hg commit -A -d '0 0' -m 1 +hg --config server.uncompressed=True serve -p 20059 -d --pid-file=hg1.pid +cat hg1.pid >> $DAEMON_PIDS +hg serve -p 20060 -d --pid-file=hg2.pid +cat hg2.pid >> $DAEMON_PIDS +cd .. + +echo % clone via stream +http_proxy= hg clone --uncompressed http://localhost:20059/ copy 2>&1 | \ + sed -e 's/[0-9][0-9.]*/XXX/g' +cd copy +hg verify + +echo % try to clone via stream, should use pull instead +http_proxy= hg clone --uncompressed http://localhost:20060/ copy2 + +echo % clone via pull +http_proxy= hg clone http://localhost:20059/ copy-pull +cd copy-pull +hg verify
--- a/tests/test-http-proxy Mon Jul 17 02:09:35 2006 +0200 +++ b/tests/test-http-proxy Wed Jul 19 14:22:08 2006 -0500 @@ -4,7 +4,7 @@ cd a echo a > a hg ci -Ama -d '1123456789 0' -hg serve -p 20059 -d --pid-file=hg.pid +hg --config server.uncompressed=True serve -p 20059 -d --pid-file=hg.pid cat hg.pid >> $DAEMON_PIDS cd .. @@ -13,8 +13,18 @@ cat proxy.pid >> $DAEMON_PIDS sleep 2 -echo %% url for proxy -http_proxy=http://localhost:20060/ hg --config http_proxy.always=True clone http://localhost:20059/ b +echo %% url for proxy, stream +http_proxy=http://localhost:20060/ hg --config http_proxy.always=True clone --uncompressed http://localhost:20059/ b | \ + sed -e 's/[0-9][0-9.]*/XXX/g' +cd b +hg verify +cd .. + +echo %% url for proxy, pull +http_proxy=http://localhost:20060/ hg --config http_proxy.always=True clone http://localhost:20059/ b-pull +cd b-pull +hg verify +cd .. echo %% host:port for proxy http_proxy=localhost:20060 hg clone --config http_proxy.always=True http://localhost:20059/ c
--- a/tests/test-http-proxy.out Mon Jul 17 02:09:35 2006 +0200 +++ b/tests/test-http-proxy.out Wed Jul 19 14:22:08 2006 -0500 @@ -1,11 +1,26 @@ adding a -%% url for proxy +%% url for proxy, stream +streaming all changes +XXX files to transfer, XXX bytes of data +transferred XXX bytes in XXX seconds (XXX KB/sec) +XXX files updated, XXX files merged, XXX files removed, XXX files unresolved +checking changesets +checking manifests +crosschecking files in changesets and manifests +checking files +1 files, 1 changesets, 1 total revisions +%% url for proxy, pull requesting all changes adding changesets adding manifests adding file changes added 1 changesets with 1 changes to 1 files 1 files updated, 0 files merged, 0 files removed, 0 files unresolved +checking changesets +checking manifests +crosschecking files in changesets and manifests +checking files +1 files, 1 changesets, 1 total revisions %% host:port for proxy requesting all changes adding changesets
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-http.out Wed Jul 19 14:22:08 2006 -0500 @@ -0,0 +1,30 @@ +adding foo +% clone via stream +streaming all changes +XXX files to transfer, XXX bytes of data +transferred XXX bytes in XXX seconds (XXX KB/sec) +XXX files updated, XXX files merged, XXX files removed, XXX files unresolved +checking changesets +checking manifests +crosschecking files in changesets and manifests +checking files +1 files, 1 changesets, 1 total revisions +% try to clone via stream, should use pull instead +requesting all changes +adding changesets +adding manifests +adding file changes +added 1 changesets with 1 changes to 1 files +1 files updated, 0 files merged, 0 files removed, 0 files unresolved +% clone via pull +requesting all changes +adding changesets +adding manifests +adding file changes +added 1 changesets with 1 changes to 1 files +1 files updated, 0 files merged, 0 files removed, 0 files unresolved +checking changesets +checking manifests +crosschecking files in changesets and manifests +checking files +1 files, 1 changesets, 1 total revisions
--- a/tests/test-pull Mon Jul 17 02:09:35 2006 +0200 +++ b/tests/test-pull Wed Jul 19 14:22:08 2006 -0500 @@ -11,7 +11,7 @@ cat hg.pid >> $DAEMON_PIDS cd .. -http_proxy= hg clone http://localhost:20059/ copy +http_proxy= hg clone --pull http://localhost:20059/ copy cd copy hg verify hg co
--- a/tests/test-ssh Mon Jul 17 02:09:35 2006 +0200 +++ b/tests/test-ssh Wed Jul 19 14:22:08 2006 -0500 @@ -27,10 +27,19 @@ cd remote echo this > foo hg ci -A -m "init" -d "1000000 0" foo +echo '[server]' > .hg/hgrc +echo 'uncompressed = True' >> .hg/hgrc cd .. -echo "# clone remote" +echo "# clone remote via stream" +hg clone -e ./dummyssh --uncompressed ssh://user@dummy/remote local-stream 2>&1 | \ + sed -e 's/[0-9][0-9.]*/XXX/g' +cd local-stream +hg verify +cd .. + +echo "# clone remote via pull" hg clone -e ./dummyssh ssh://user@dummy/remote local echo "# verify"
--- a/tests/test-ssh.out Mon Jul 17 02:09:35 2006 +0200 +++ b/tests/test-ssh.out Wed Jul 19 14:22:08 2006 -0500 @@ -1,5 +1,15 @@ # creating 'remote' -# clone remote +# clone remote via stream +streaming all changes +XXX files to transfer, XXX bytes of data +transferred XXX bytes in XXX seconds (XXX KB/sec) +XXX files updated, XXX files merged, XXX files removed, XXX files unresolved +checking changesets +checking manifests +crosschecking files in changesets and manifests +checking files +1 files, 1 changesets, 1 total revisions +# clone remote via pull requesting all changes adding changesets adding manifests @@ -70,6 +80,7 @@ Got arguments 1:user@dummy 2:hg -R remote serve --stdio 3: 4: 5: Got arguments 1:user@dummy 2:hg -R remote serve --stdio 3: 4: 5: Got arguments 1:user@dummy 2:hg -R remote serve --stdio 3: 4: 5: +Got arguments 1:user@dummy 2:hg -R remote serve --stdio 3: 4: 5: Got arguments 1:user@dummy 2:hg -R local serve --stdio 3: 4: 5: Got arguments 1:user@dummy 2:hg -R remote serve --stdio 3: 4: 5: Got arguments 1:user@dummy 2:hg -R remote serve --stdio 3: 4: 5:
--- a/tests/test-status Mon Jul 17 02:09:35 2006 +0200 +++ b/tests/test-status Wed Jul 19 14:22:08 2006 -0500 @@ -32,3 +32,6 @@ hg status echo "hg status modified added removed deleted unknown never-existed ignored:" hg status modified added removed deleted unknown never-existed ignored +hg copy modified copied +echo "hg status -C:" +hg status -C