# HG changeset patch # User Brendan Cully # Date 1161722541 25200 # Node ID bd8339976504f6b593a6c4486970a437bc435328 # Parent e0db0b7934f2d21b396b236ada6ebd9de70d560d# Parent ceaa3fefc10c5d4a6684d4720b6c9e776b817f1f Merge with mpm diff --git a/contrib/zsh_completion b/contrib/zsh_completion --- a/contrib/zsh_completion +++ b/contrib/zsh_completion @@ -14,29 +14,50 @@ local curcontext="$curcontext" state line typeset -A opt_args -local subcmds repos tags newFiles addedFiles includeExclude commitMessage +local repos newFiles addedFiles includeExclude commitMessage +local ridx _hgroot + +# FIXME: why isn't opt_args available? +[[ -d .hg ]] && _hgroot="$PWD" +ridx=$words[(i)-R] +(( $ridx < $#words )) && _hgroot="${words[$ridx+1]}" -_mq_state () { +# hg dispatch (borrowed from _cvs) +(( $+functions[_hg_cmd] )) || +_hg_cmd () { + _call_program hg hg -R "$_hgroot" "$@" +} + +(( $+functions[_hg_state] )) || +_hg_state () { case "$state" in + (tags) + compadd $(_hg_cmd tags 2> /dev/null | + sed -e 's/[0-9]*:[a-f0-9]*$//; s/ *$//') + ;; (qapplied) - compadd $(hg qapplied) + compadd $(_hg_cmd qapplied) ;; (qunapplied) - compadd $(hg qunapplied) + compadd $(_hg_cmd qunapplied) ;; esac } -tags=($(hg tags 2> /dev/null | sed -e 's/[0-9]*:[a-f0-9]\{40\}$//; s/ *$//')) -subcmds=($(hg -v help | sed -e '1,/^list of commands:/d' \ +(( $+_hg_commands )) || +_hg_commands=($(hg -v help | sed -e '1,/^list of commands:/d' \ -e '/^global options:/,$d' -e '/^ [^ ]/!d; s/[,:].*//g;')) # A lot of commands have these arguments includeExclude=( - '*-I-[include names matching the given patterns]:dir:_files -W $(hg root) -/' - '*--include-[include names matching the given patterns]:dir:_files -W $(hg root) -/' - '*-X-[exclude names matching the given patterns]:dir:_files -W $(hg root) -/' - '*--exclude-[exclude names matching the given patterns]:dir:_files -W $(hg root) -/') + '*-I-[include names matching the given patterns]:dir:_files -W $(_hg_cmd root) -/' + '*--include-[include names matching the given patterns]:dir:_files -W $(_hg_cmd root) -/' + '*-X-[exclude names matching the given patterns]:dir:_files -W $(_hg_cmd root) -/' + '*--exclude-[exclude names matching the given patterns]:dir:_files -W $(_hg_cmd root) -/') + +styleOpts=( + '--style[display using template map file]:' + '--template[display with template]:') commitMessage=( '(-m --message -l --logfile --edit)-e[edit commit message]' @@ -68,7 +89,7 @@ if [[ $service == "hg" ]]; then '*::command:->subcmd' && return 0 if (( CURRENT == 1 )); then - _wanted commands expl 'hg command' compadd -a subcmds + _wanted commands expl 'hg command' compadd -a _hg_commands return fi service="$words[1]" @@ -77,7 +98,7 @@ fi case $service in (add) - newFiles=(${(ps:\0:)"$(hg status -0un .)"}) + newFiles=(${(ps:\0:)"$(_hg_cmd status -0un .)"}) _arguments $includeExclude \ '*:file:->unknown' _wanted files expl 'unknown files' compadd -a newFiles @@ -89,7 +110,7 @@ case $service in ;; (forget) - addedFiles=(${(ps:\0:)"$(hg status -0an .)"}) + addedFiles=(${(ps:\0:)"$(_hg_cmd status -0an .)"}) _arguments $includeExclude \ '*:file:->added' _wanted files expl 'newly added files' compadd -a addedFiles @@ -128,8 +149,8 @@ case $service in (diff) _arguments $includeExclude \ - '*-r[revision]:revision:($tags)' \ - '*--rev[revision]:revision:($tags)' \ + '*-r[revision]:revision:->tags' \ + '*--rev[revision]:revision:->tags' \ '(--text)-a[treat all files as text]' \ '(-a)--text[treat all files as text]' \ '*:file:_files' @@ -153,10 +174,10 @@ case $service in ;; (revert) - addedFiles=(${(ps:\0:)"$(hg status -0amrn .)"}) + addedFiles=(${(ps:\0:)"$(_hg_cmd status -0amrn .)"}) _arguments \ - '(--rev)-r[revision to revert to]:revision:($tags)' \ - '(-r)--rev[revision to revert to]:revision:($tags)' \ + '(--rev)-r[revision to revert to]:revision:->tags' \ + '(-r)--rev[revision to revert to]:revision:->tags' \ '(--nonrecursive)-n[do not recurse into subdirectories]' \ '(-n)--nonrecursive[do not recurse into subdirectories]' \ '*:file:->modified' @@ -164,7 +185,7 @@ case $service in ;; (commit|ci) - addedFiles=(${(ps:\0:)"$(hg status -0amrn .)"}) + addedFiles=(${(ps:\0:)"$(_hg_cmd status -0amrn .)"}) _arguments $includeExclude \ '(--addremove)-A[run addremove during commit]' \ '(-A)--addremove[run addremove during commit]' \ @@ -184,15 +205,15 @@ case $service in _arguments $includeExclude \ '(--output)-o[print output to file with formatted name]:filespec:' \ '(-o)--output[print output to file with formatted name]:filespec:' \ - '(--rev)-r[revision]:revision:($tags)' \ - '(-r)--rev[revision]:revision:($tags)' \ + '(--rev)-r[revision]:revision:->tags' \ + '(-r)--rev[revision]:revision:->tags' \ '*:file:_files' ;; (annotate) _arguments $includeExclude \ - '(--rev)-r[annotate the specified revision]:revision:($tags)' \ - '(-r)--rev[annotate the specified revision]:revision:($tags)' \ + '(--rev)-r[annotate the specified revision]:revision:->tags' \ + '(-r)--rev[annotate the specified revision]:revision:->tags' \ '(--text)-a[treat all files as text]' \ '(-a)--text[treat all files as text]' \ '(--user)-u[list the author]' \ @@ -206,8 +227,8 @@ case $service in (grep) _arguments $includeExclude \ - '*-r[search in given revision range]:revision:($tags)' \ - '*--rev[search in given revision range]:revision:($tags)' \ + '*-r[search in given revision range]:revision:->tags' \ + '*--rev[search in given revision range]:revision:->tags' \ '--all[print all revisions with matches]' \ '(-print0)-0[end filenames with NUL, for use with xargs]' \ '(-0)--print0[end filenames with NUL, for use with xargs]' \ @@ -224,8 +245,8 @@ case $service in (locate) _arguments $includeExclude \ - '(--rev)-r[search repository as it stood at revision]:revision:($tags)' \ - '(-r)--rev[search repository as it stood at revision]:revision:($tags)' \ + '(--rev)-r[search repository as it stood at revision]:revision:->tags' \ + '(-r)--rev[search repository as it stood at revision]:revision:->tags' \ '(--print0)-0[end filenames with NUL, for use with xargs]' \ '(-0)--print0[end filenames with NUL, for use with xargs]' \ '(--fullpath)-f[print complete paths]' \ @@ -234,9 +255,9 @@ case $service in ;; (log|history) - _arguments $includeExclude \ - '*-r[show the specified revision or range]:revision:($tags)' \ - '*--rev[show the specified revision or range]:revision:($tags)' \ + _arguments $includeExclude $styleOpts \ + '*-r[show the specified revision or range]:revision:->tags' \ + '*--rev[show the specified revision or range]:revision:->tags' \ '(--no-merges -M --only-merges)-m[show only merge revisions]' \ '(--no-merges -M -m)--only-merges[show only merge revisions]' \ '(--only-merges -m --no-merges)-M[do not show merge revisions]' \ @@ -258,7 +279,7 @@ case $service in '(-C --clean -m)--merge[allow merging of branches]' \ '(-m --merge --clean)-C[overwrite locally modified files]' \ '(-m --merge -C)--clean[overwrite locally modified files]' \ - '*:revision or tag:($tags)' + '*:revision or tag:->tags' ;; (tag) @@ -271,12 +292,12 @@ case $service in '(-d)--date[record datecode as commit date]:date code:' \ '(--user)-u[record user as commiter]:user:' \ '(-u)--user[record user as commiter]:user:' \ - '*:name, then revision:($tags)' + '*:name, then revision:->tags' ;; (clone) if (( CURRENT == 2 )); then - repos=( $(hg paths | sed -e 's/^.*= //') ) + repos=( $(_hg_cmd paths | sed -e 's/^.*= //') ) _arguments \ '(--no-update)-U[do not update the new working directory]' \ '(-U)--no-update[do not update the new working directory]' \ @@ -293,8 +314,8 @@ case $service in (rawcommit) _arguments \ - '(--parent)-p[parent revision]:revision:($tags)' \ - '(-p)--parent[parent revision]:revision:($tags)' \ + '(--parent)-p[parent revision]:revision:->tags' \ + '(-p)--parent[parent revision]:revision:->tags' \ '(--date)-d[record datecode as commit date]:date code:' \ '(-d)--date[record datecode as commit date]:date code:' \ '(--user)-u[record user as commiter]:user:' \ @@ -321,7 +342,7 @@ case $service in ;; (incoming) - _arguments \ + _arguments $styleOpts \ '(--patch)-p[show patch]' \ '(-p)--patch[show patch]' \ '(--no-merges)-M[do not show merge revisions]' \ @@ -337,13 +358,13 @@ case $service in '(-p)--strip[directory strip option for patch (default: 1)]:count:' \ '(--force)-f[skip check for outstanding uncommitted changes]' \ '(-f)--force[skip check for outstanding uncommitted changes]' \ - '(--base)-b[base directory to read patches from]:file:_files -W $(hg root) -/' \ - '(-b)--base[base directory to read patches from]:file:_files -W $(hg root) -/' \ + '(--base)-b[base directory to read patches from]:file:_files -W $(_hg_cmd root) -/' \ + '(-b)--base[base directory to read patches from]:file:_files -W $(_hg_cmd root) -/' \ '*:patch file:_files' ;; (pull) - repos=( $(hg paths | sed -e 's/^.*= //') ) + repos=( $(_hg_cmd paths | sed -e 's/^.*= //') ) _arguments \ '(--update)-u[update working directory to tip after pull]' \ '(-u)--update[update working directory to tip after pull]' \ @@ -355,7 +376,7 @@ case $service in ;; (outgoing) - _arguments \ + _arguments $styleOpts \ '(--patch)-p[show patch]' \ '(-p)--patch[show patch]' \ '(--no-merges)-M[do not show merge revisions]' \ @@ -377,7 +398,7 @@ case $service in ;; (push) - repos=( $(hg paths | sed -e 's/^.*= //') ) + repos=( $(_hg_cmd paths | sed -e 's/^.*= //') ) _arguments \ '(--force)-f[force push]' \ '(-f)--force[force push]' \ @@ -409,11 +430,11 @@ case $service in ;; (help) - _wanted commands expl 'hg command' compadd -a subcmds + _wanted commands expl 'hg command' compadd -a _hg_commands ;; (heads) - _arguments \ + _arguments $styleOpts \ '(--branches)-b[find branch info]' \ '(-b)--branches[find branch info]' ;; @@ -427,15 +448,26 @@ case $service in ;; (manifest) - _arguments '*:revision:($tags)' + _arguments '*:revision:->tags' + ;; + + (par*) + _arguments $styleOpts \ + '(--rev 1)-r[show parents of the specified rev]:revision:->tags' \ + '(-r 1)--rev[show parents of the specified rev]:revision:->tags' \ + '::revision:->tags' ;; - (parents) - _arguments '*:revision:($tags)' + (identify|recover|root|undo|verify|version|ct|tags) + # no arguments for these commands ;; - (identify|recover|root|undo|view|verify|version|ct|tags) - # no arguments for these commands + # HGK + (vi*) + _arguments \ + '(--limit)-l[limit number of changes displayed]:' \ + '(-l)--limit[limit number of changes displayed]:' \ + '::revision range:->tags' ;; # MQ commands @@ -444,7 +476,6 @@ case $service in {-k,--keep}'[keep patch file]' \ {-r,--rev}'[revision]:applied patch:->qapplied' \ '*:unapplied patches:->qunapplied' - _mq_state ;; (qnew) @@ -454,12 +485,10 @@ case $service in ;; (qpo*) - applied=( $(hg qapplied) ) _arguments \ (1){-a,--all}'[pop all patches]' \ {-f,--force}'[forget any local changes]' \ ':applied patch:->qapplied' - _mq_state ;; (qpu*) @@ -467,7 +496,6 @@ case $service in (1){-a,--all}'[apply all patches]' \ {-f,--force}'[apply if the patch has rejects]' \ ':unapplied patch:->qunapplied' - _mq_state ;; (qref*) _arguments $commitMessage $includeExclude \ @@ -479,3 +507,5 @@ case $service in _message "unknown hg command completion: $service" ;; esac + +_hg_state diff --git a/hgext/mq.py b/hgext/mq.py --- a/hgext/mq.py +++ b/hgext/mq.py @@ -2003,6 +2003,35 @@ def reposetup(ui, repo): return tagscache + def branchtags(self): + if self.branchcache != None: + return self.branchcache + + q = self.mq + if not q.applied: + return super(mqrepo, self).branchtags() + + self.branchcache = {} # avoid recursion in changectx + cl = self.changelog + partial, last, lrev = self._readbranchcache() + + qbase = cl.rev(revlog.bin(q.applied[0].rev)) + start = lrev + 1 + if start < qbase: + # update the cache (excluding the patches) and save it + self._updatebranchcache(partial, lrev+1, qbase) + self._writebranchcache(partial, cl.node(qbase-1), qbase-1) + start = qbase + # if start = qbase, the cache is as updated as it should be. + # if start > qbase, the cache includes (part of) the patches. + # we might as well use it, but we won't save it. + + # update the cache up to the tip + self._updatebranchcache(partial, start, cl.count()) + + self.branchcache = partial + return self.branchcache + if repo.local(): repo.__class__ = mqrepo repo.mq = queue(ui, repo.join("")) 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 @@ -527,6 +527,23 @@ class hgweb(object): date = t) parity += 1 + def heads(**map): + parity = 0 + count = 0 + + for node in self.repo.heads(): + count += 1 + if count > 10: + break; + + ctx = self.repo.changectx(node) + + yield {'parity': self.stripes(parity), + 'branch': ctx.branch(), + 'node': hex(node), + 'date': ctx.date()} + parity += 1 + def changelist(**map): parity = 0 cl = self.repo.changelog @@ -560,6 +577,7 @@ class hgweb(object): self.repo.ui.config("web", "author", "unknown")), # also lastchange = cl.read(cl.tip())[2], tags = tagentries, + heads = heads, shortlog = changelist, node = hex(cl.tip()), archives=self.archivelist("tip")) diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -295,6 +295,18 @@ class localrepository(repo.repository): self.branchcache = {} # avoid recursion in changectx + partial, last, lrev = self._readbranchcache() + + tiprev = self.changelog.count() - 1 + if lrev != tiprev: + self._updatebranchcache(partial, lrev+1, tiprev+1) + self._writebranchcache(partial, self.changelog.tip(), tiprev) + + self.branchcache = partial + return self.branchcache + + def _readbranchcache(self): + partial = {} try: f = self.opener("branches.cache") last, lrev = f.readline().rstrip().split(" ", 1) @@ -303,34 +315,30 @@ class localrepository(repo.repository): self.changelog.node(lrev) == last): # sanity check for l in f: node, label = l.rstrip().split(" ", 1) - self.branchcache[label] = bin(node) + partial[label] = bin(node) else: # invalidate the cache last, lrev = nullid, -1 f.close() except IOError: last, lrev = nullid, -1 + return partial, last, lrev - tip = self.changelog.count() - 1 - if lrev != tip: - for r in xrange(lrev + 1, tip + 1): - c = self.changectx(r) - b = c.branch() - if b: - self.branchcache[b] = c.node() - self._writebranchcache() - - return self.branchcache - - def _writebranchcache(self): + def _writebranchcache(self, branches, tip, tiprev): try: f = self.opener("branches.cache", "w") - t = self.changelog.tip() - f.write("%s %s\n" % (hex(t), self.changelog.count() - 1)) - for label, node in self.branchcache.iteritems(): + f.write("%s %s\n" % (hex(tip), tiprev)) + for label, node in branches.iteritems(): f.write("%s %s\n" % (hex(node), label)) except IOError: pass + def _updatebranchcache(self, partial, start, end): + for r in xrange(start, end): + c = self.changectx(r) + b = c.branch() + if b: + partial[b] = c.node() + def lookup(self, key): if key == '.': key = self.dirstate.parents()[0] diff --git a/templates/gitweb/map b/templates/gitweb/map --- a/templates/gitweb/map +++ b/templates/gitweb/map @@ -39,6 +39,7 @@ filerevchild = ' fileannotatechild = 'child {rev}:{node|short}' tags = tags.tmpl tagentry = '#date|age# ago#tag|escape#changeset | changelog | manifest' +headentry = '{date|age} ago{node|short}{branch|escape}changeset | changelog | manifest' diffblock = '
#lines#
' changelogtag = 'tag:#tag|escape#' changesettag = 'tag#tag|escape#' diff --git a/templates/gitweb/summary.tmpl b/templates/gitweb/summary.tmpl --- a/templates/gitweb/summary.tmpl +++ b/templates/gitweb/summary.tmpl @@ -36,4 +36,12 @@ summary | ... +
heads
+ +{heads%headentry} + + + +
...
#footer# diff --git a/tests/test-mq-caches b/tests/test-mq-caches new file mode 100755 --- /dev/null +++ b/tests/test-mq-caches @@ -0,0 +1,76 @@ +#!/bin/sh + +echo '[extensions]' >> $HGRCPATH +echo 'hgext.mq=' >> $HGRCPATH + +show_branch_cache() +{ + branches=.hg/branches.cache + hg log -r tip --template 'tip: #rev#\n' + if [ -f $branches ]; then + sort $branches + else + echo No $branches + fi + if [ "$1" = 1 ]; then + for b in foo bar; do + hg log -r $b --template "branch $b: "'#rev#\n' + done + fi +} + +hg init a +cd a +hg qinit -c + +echo '# mq patch on an empty repo' +hg qnew p1 +show_branch_cache + +echo > pfile +hg add pfile +hg qrefresh -m 'patch 1' +show_branch_cache + +echo +echo '# some regular revisions' +hg qpop +echo foo > foo +hg add foo +echo foo > .hg/branch +hg ci -m 'branch foo' -d '1000000 0' + +echo bar > bar +hg add bar +echo bar > .hg/branch +hg ci -m 'branch bar' -d '1000000 0' +show_branch_cache + +echo +echo '# add some mq patches' +hg qpush +show_branch_cache + +hg qnew p2 +echo foo > .hg/branch +echo foo2 >> foo +hg qrefresh -m 'patch 2' +show_branch_cache 1 + +echo +echo '# removing the cache' +rm -f .hg/branches.cache +show_branch_cache 1 + +echo +echo '# importing rev 1 (the cache now ends in one of the patches)' +hg qimport -r 1 -n p0 +show_branch_cache 1 +hg log -r qbase --template 'qbase: #rev#\n' + +echo +echo '# detect an invalid cache' +hg qpop -a +hg qpush -a +show_branch_cache + diff --git a/tests/test-mq-caches.out b/tests/test-mq-caches.out new file mode 100644 --- /dev/null +++ b/tests/test-mq-caches.out @@ -0,0 +1,53 @@ +# mq patch on an empty repo +tip: 0 +No .hg/branches.cache +tip: 0 +No .hg/branches.cache + +# some regular revisions +Patch queue now empty +tip: 1 +3f910abad313ff802d3a23a7529433872df9b3ae 1 +3f910abad313ff802d3a23a7529433872df9b3ae bar +9539f35bdc80732cc9a3f84e46508f1ed1ec8cff foo + +# add some mq patches +applying p1 +Now at: p1 +tip: 2 +3f910abad313ff802d3a23a7529433872df9b3ae 1 +3f910abad313ff802d3a23a7529433872df9b3ae bar +9539f35bdc80732cc9a3f84e46508f1ed1ec8cff foo +tip: 3 +3f910abad313ff802d3a23a7529433872df9b3ae 1 +3f910abad313ff802d3a23a7529433872df9b3ae bar +9539f35bdc80732cc9a3f84e46508f1ed1ec8cff foo +branch foo: 3 +branch bar: 2 + +# removing the cache +tip: 3 +3f910abad313ff802d3a23a7529433872df9b3ae 1 +3f910abad313ff802d3a23a7529433872df9b3ae bar +9539f35bdc80732cc9a3f84e46508f1ed1ec8cff foo +branch foo: 3 +branch bar: 2 + +# importing rev 1 (the cache now ends in one of the patches) +tip: 3 +3f910abad313ff802d3a23a7529433872df9b3ae 1 +3f910abad313ff802d3a23a7529433872df9b3ae bar +9539f35bdc80732cc9a3f84e46508f1ed1ec8cff foo +branch foo: 3 +branch bar: 2 +qbase: 1 + +# detect an invalid cache +Patch queue now empty +applying p0 +applying p1 +applying p2 +Now at: p2 +tip: 3 +9539f35bdc80732cc9a3f84e46508f1ed1ec8cff 0 +9539f35bdc80732cc9a3f84e46508f1ed1ec8cff foo