Mercurial > hg
changeset 1469:0847c45ffee6
Merge bundle -r work from Eric Hopper
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Thu, 27 Oct 2005 12:26:16 -0700 |
parents | 214f42f23a3b (diff) dc1bbc456b96 (current diff) |
children | fb9b84c91222 |
files | mercurial/commands.py mercurial/localrepo.py mercurial/revlog.py |
diffstat | 52 files changed, 1990 insertions(+), 1028 deletions(-) [+] |
line wrap: on
line diff
--- a/CONTRIBUTORS Sun Oct 16 16:24:40 2005 -0700 +++ b/CONTRIBUTORS Thu Oct 27 12:26:16 2005 -0700 @@ -3,6 +3,7 @@ Goffredo Baroncelli <kreijack at libero.it> Muli Ben-Yehuda <mulix at mulix.org> Mikael Berthe <mikael at lilotux.net> +Benoit Boissinot <bboissin at gmail.com> Vincent Danjean <vdanjean.ml at free.fr> Jake Edge <jake at edge2.net> Michael Fetterman <michael.fetterman at intel.com>
--- a/Makefile Sun Oct 16 16:24:40 2005 -0700 +++ b/Makefile Thu Oct 27 12:26:16 2005 -0700 @@ -10,7 +10,7 @@ clean: -$(PYTHON) setup.py clean --all # ignore errors of this command find . -name '*.py[co]' -exec rm -f '{}' ';' - make -C doc clean + $(MAKE) -C doc clean dist: tests doc TAR_OPTIONS="--owner=root --group=root --mode=u+w,go-w,a+rX-s" $(PYTHON) setup.py sdist --force-manifest @@ -18,8 +18,11 @@ tests: cd tests && ./run-tests +test-%: + cd tests && ./run-tests $@ + doc: - make -C doc + $(MAKE) -C doc .PHONY: all clean dist tests doc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/contrib/hg-menu.vim Thu Oct 27 12:26:16 2005 -0700 @@ -0,0 +1,93 @@ +" vim600: set foldmethod=marker: +" ============================================================================= +" Name Of File: hg-menu.vim +" Description: Interface to Mercurial Version Control. +" Author: Steve Borho (modified Jeff Lanzarotta's RCS script) +" Date: Wednesday, October 5, 2005 +" Version: 0.1.0 +" Copyright: None. +" Usage: These command and gui menu displays useful hg functions +" Configuration: Your hg executable must be in your path. +" ============================================================================= + +" Section: Init {{{1 +if exists("loaded_hg_menu") + finish +endif +let loaded_hg_menu = 1 + +" Section: Menu Options {{{1 +if has("gui") +" amenu H&G.Commit\ File<Tab>,ci :!hg commit %<CR>:e!<CR> +" amenu H&G.Commit\ All<Tab>,call :!hg commit<CR>:e!<CR> +" amenu H&G.-SEP1- <nul> + amenu H&G.Add<Tab>\\add :!hg add %<CR><CR> + amenu H&G.Forget\ Add<Tab>\\fgt :!hg forget %<CR><CR> + amenu H&G.Show\ Differences<Tab>\\diff :call ShowResults("FileDiff", "hg\ diff")<CR><CR> + amenu H&G.Revert\ to\ Last\ Version<Tab>\\revert :!hg revert %<CR>:e!<CR> + amenu H&G.Show\ History<Tab>\\log :call ShowResults("FileLog", "hg\ log")<CR><CR> + amenu H&G.Annotate<Tab>\\an :call ShowResults("annotate", "hg\ annotate")<CR><CR> + amenu H&G.-SEP1- <nul> + amenu H&G.Repo\ Status<Tab>\\stat :call ShowResults("RepoStatus", "hg\ status")<CR><CR> + amenu H&G.Pull<Tab>\\pull :!hg pull<CR>:e!<CR> + amenu H&G.Update<Tab>\\upd :!hg update<CR>:e!<CR> +endif + +" Section: Mappings {{{1 +if(v:version >= 600) + " The default Leader is \ 'backslash' + map <Leader>add :!hg add %<CR><CR> + map <Leader>fgt :!hg forget %<CR><CR> + map <Leader>diff :call ShowResults("FileDiff", "hg\ diff")<CR><CR> + map <Leader>revert :!hg revert %<CR>:e!<CR> + map <Leader>log :call ShowResults("FileLog", "hg\ log")<CR><CR> + map <Leader>an :call ShowResults("annotate", "hg\ annotate")<CR><CR> + map <Leader>stat :call ShowResults("RepoStatus", "hg\ status")<CR><CR> + map <Leader>upd :!hg update<CR>:e!<CR> + map <Leader>pull :!hg pull<CR>:e!<CR> +else + " pre 6.0, the default Leader was a comma + map ,add :!hg add %<CR><CR> + map ,fgt :!hg forget %<CR><CR> + map ,diff :call ShowResults("FileDiff", "hg\ diff")<CR><CR> + map ,revert :!hg revert<CR>:e!<CR> + map ,log :call ShowResults("FileLog", "hg\ log")<CR><CR> + map ,an :call ShowResults("annotate", "hg\ annotate")<CR><CR> + map ,stat :call ShowResults("RepoStatus", "hg\ status")<CR><CR> + map ,upd :!hg update<CR>:e!<CR> + map ,pull :!hg pull<CR>:e!<CR> +endif + +" Section: Functions {{{1 +" Show the log results of the current file with a revision control system. +function! ShowResults(bufferName, cmdName) + " Modify the shortmess option: + " A don't give the "ATTENTION" message when an existing swap file is + " found. + set shortmess+=A + + " Get the name of the current buffer. + let currentBuffer = bufname("%") + + " If a buffer with the name rlog exists, delete it. + if bufexists(a:bufferName) + execute 'bd! ' a:bufferName + endif + + " Create a new buffer. + execute 'new ' a:bufferName + + " Execute the command. + execute 'r!' a:cmdName ' ' currentBuffer + + " Make is so that the file can't be edited. + setlocal nomodified + setlocal nomodifiable + setlocal readonly + + " Go to the beginning of the buffer. + execute "normal 1G" + + " Restore the shortmess option. + set shortmess-=A +endfunction
--- a/contrib/hgk Sun Oct 16 16:24:40 2005 -0700 +++ b/contrib/hgk Thu Oct 27 12:26:16 2005 -0700 @@ -403,9 +403,12 @@ set ctext .ctop.cdet.left.ctext text $ctext -bg white -state disabled -font $textfont \ -width $geometry(ctextw) -height $geometry(ctexth) \ - -yscrollcommand ".ctop.cdet.left.sb set" -wrap none + -yscrollcommand ".ctop.cdet.left.sb set" \ + -xscrollcommand ".ctop.cdet.left.hb set" -wrap none scrollbar .ctop.cdet.left.sb -command "$ctext yview" + scrollbar .ctop.cdet.left.hb -orient horizontal -command "$ctext xview" pack .ctop.cdet.left.sb -side right -fill y + pack .ctop.cdet.left.hb -side bottom -fill x pack $ctext -side left -fill both -expand 1 .ctop.cdet add .ctop.cdet.left @@ -465,6 +468,7 @@ bindkey ? findprev bindkey f nextfile bind . <Control-q> doquit + bind . <Control-w> doquit bind . <Control-f> dofind bind . <Control-g> {findnext 0} bind . <Control-r> findprev
--- a/contrib/zsh_completion Sun Oct 16 16:24:40 2005 -0700 +++ b/contrib/zsh_completion Thu Oct 27 12:26:16 2005 -0700 @@ -14,23 +14,38 @@ local curcontext="$curcontext" state line typeset -A opt_args -local subcmds repos tags newFiles addedFiles +local subcmds repos tags newFiles addedFiles includeExclude 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' \ - -e '/^global options:/,$d' -e '/^ [^ ]/!d; s/[,:]//g;')) + -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) -/') if [[ $service == "hg" ]]; then _arguments -C -A "-*" \ - '-R+[repository root directory]' \ - '-y[non-interactive]' \ - '-v[verbose]' \ - '-q[quiet]' \ + '(--repository)-R[repository root directory]:root:_files -/' \ + '(-R)--repository[repository root directory]:root:_files -/' \ + '--cwd[change working directory]:new working directory:_files -/' \ + '(--noninteractive)-y[do not prompt, assume yes for any required answers]' \ + '(-y)--noninteractive[do not prompt, assume yes for any required answers]' \ + '(--verbose)-v[enable additional output]' \ + '(-v)--verbose[enable additional output]' \ + '(--quiet)-q[suppress output]' \ + '(-q)--quiet[suppress output]' \ + '(--help)-h[display help and exit]' \ + '(-h)--help[display help and exit]' \ + '--debug[debug mode]' \ + '--debugger[start debugger]' \ + '--traceback[print traceback on exception]' \ '--time[time how long the command takes]' \ '--profile[profile]' \ - '-h-[display help and exit]' \ - '--version-[output version information and exit]' \ - '--cwd[change working directory]:new working directory:_files -/' \ + '--version[output version information and exit]' \ '*::command:->subcmd' && return 0 if (( CURRENT == 1 )); then @@ -42,88 +57,344 @@ fi case $service in + (add) + newFiles=( $(hg status -un) ) + _arguments $includeExclude \ + '*:file:->unknown' + _wanted files expl 'unknown files' compadd -a newFiles + ;; + (addremove) - _arguments \ - '-I[include path in search]:dir:_files -W $(hg root) -/' \ - '-X[exclude path in search]:dir:_files -W $(hg root) -/' \ + _arguments $includeExclude \ '*:directories:_files -/' # assume they want to add/remove a dir ;; - (add) - newFiles=( $(hg status -un) ) - _arguments \ - '-I[include path in search]:dir:_files -W $(hg root) -/' \ - '-X[exclude path in search]:dir:_files -W $(hg root) -/' - _wanted files expl 'unknown files' compadd -a newFiles + (forget) + addedFiles=( $(hg status -an) ) + _arguments $includeExclude \ + '*:file:->added' + _wanted files expl 'newly added files' compadd -a addedFiles ;; (remove|rm) + _arguments $includeExclude \ + '*:file:_files' + ;; + + (copy|cp) + _arguments $includeExclude \ + '(--after)-A[record a copy that has already occurred]' \ + '(-A)--after[record a copy that has already occurred]' \ + '(--force)-f[forcibly copy over an existing managed file]' \ + '(-f)--force[forcibly copy over an existing managed file]' \ + '(--parents)-p[append source path to dest]' \ + '(-p)--parents[append source path to dest]' \ + '*:files:_files' + ;; + + (rename|mv) + if (( CURRENT == 2 )); then + _arguments $includeExclude \ + '(--after)-A[record a rename that has already occurred]' \ + '(-A)--after[record a rename that has already occurred]' \ + '(--force)-f[replace destination if it exists]' \ + '(-F)--force[replace destination if it exists]' \ + '(--parents)-p[append source path to dest]' \ + '(-p)--parents[append source path to dest]' \ + '*:files:_files' + else + _arguments '*:destination:_files' + fi + ;; + + (diff) + _arguments $includeExclude \ + '*-r[revision]:revision:($tags)' \ + '*--rev[revision]:revision:($tags)' \ + '(--text)-a[treat all files as text]' \ + '(-a)--text[treat all files as text]' \ + '*:file:_files' + ;; + + (status) + _arguments $includeExclude \ + '(--no-status)-n[hide status prefix]' \ + '(-n)--no-status[hide status prefix]' \ + '(--print0)-0[end filenames with NUL, for use with xargs]' \ + '(-0)--print0[end filenames with NUL, for use with xargs]' \ + '(--modified)-m[show only modified files]' \ + '(-m)--modified[show only modified files]' \ + '(--added)-a[show only added files]' \ + '(-a)--added[show only added files]' \ + '(--removed)-r[show only removed files]' \ + '(-r)--removed[show only removed files]' \ + '(--unknown)-u[show only unknown files]' \ + '(-u)--unknown[show only unknown files]' \ + '*:search pattern, then files:_files' + ;; + + (revert) + addedFiles=( $(hg status -mrn) ) # modified, removed _arguments \ - '-I[include path in search]:dir:_files -W $(hg root) -/' \ - '-X[exclude path in search]:dir:_files -W $(hg root) -/' \ - '*:file:_files' + '(--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' + _wanted files expl 'mofified files' compadd -a addedFiles + ;; + + (commit|ci) + addedFiles=( $(hg status -amrn) ) # added, modified, removed + _arguments $includeExclude \ + '(--addremove)-A[run addremove during commit]' \ + '(-A)--addremove[run addremove during commit]' \ + '(--message)-m[use <txt> as commit message]:string:' \ + '(-m)--message[use <txt> as commit message]:string:' \ + '(--logfile)-l[read commit message from <file>]:.log file:_file -g \*.txt' \ + '(-l)--logfile[read commit message from <file>]:.log file:_file -g \*.txt' \ + '(--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:' \ + '(-u)--user[record user as commiter]:user:' \ + '*:file:->modified' + _wanted files expl 'mofified files' compadd -a addedFiles ;; (cat) - _arguments \ - '-I[include path in search]:dir:_files -W $(hg root) -/' \ - '-X[exclude path in search]:dir:_files -W $(hg root) -/' \ - '-o[output to file]:file:' \ - '-r[revision]:revision:($tags)' \ + _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)' \ + '*:file:_files' + ;; + + (annotate) + _arguments $includeExclude \ + '(--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]' \ + '(-u)--user[list the author]' \ + '(--changeset)-c[list the changeset]' \ + '(-c)--changeset[list the changeset]' \ + '(--number)-n[list the revision number (default)]' \ + '(-n)--number[list the revision number (default)]' \ + '*:files:_files' + ;; + + (grep) + _arguments $includeExclude \ + '*-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]' \ + '(--ignore-case)-i[ignore case when matching]' \ + '(-i)--ignore-case[ignore case when matching]' \ + '(--files-with-matches)-l[print names of files and revs that match]' \ + '(-l)--files-with-matches[print names of files and revs that match]' \ + '(--line-number)-n[print matching line numbers]' \ + '(-n)--line-number[print matching line numbers]' \ + '(--user)-u[print user who committed change]' \ + '(-u)--user[print user who committed change]' \ + '*:search pattern:' + ;; + + (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)' \ + '(--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]' \ + '(-f)--fullpath[print complete paths]' \ + '*:search pattern:' + ;; + + (log|history) + _arguments $includeExclude \ + '*-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]' \ + '(--only-merges -m -M)--no-merges[do not show merge revisions]' \ + '(--keyword)-k[search for a keyword]:keyword:' \ + '(-k)--keyword[search for a keyword]:keyword:' \ + '(--branch)-b[show branches]' \ + '(-b)--branch[show branches]' \ + '(--patch)-p[show patch]' \ + '(-p)--patch[show patch]' \ '*:file:_files' ;; - (checkout|update|up|co) + (update|checkout|co) + _arguments \ + '(--branch)-b[checkout the head of a specific branch]' \ + '(-b)--branch[checkout the head of a specific branch]' \ + '(-C --clean --merge)-m[allow merging of branches]' \ + '(-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)' + ;; + + (tag) + _arguments \ + '(--local)-l[make the tag local]' \ + '(-l)--local[make the tag local]' \ + '(--message)-m[message for tag commit log entry]:string:' \ + '(-m)--message[message for tag commit log entry]:string:' \ + '(--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:' \ + '(-u)--user[record user as commiter]:user:' \ + '*:name, then revision:($tags)' + ;; + + (clone) + if (( CURRENT == 2 )); then + _arguments \ + '(--no-update)-U[do not update the new working directory]' \ + '(-U)--no-update[do not update the new working directory]' \ + '(--ssh)-e[specify ssh command to use]:string:' \ + '(-e)--ssh[specify ssh command to use]:string:' \ + '--pull[use pull protocol to copy metadata]' \ + '--remotecmd[specify hg command to run on the remote side]:remote hg:' \ + '*:local repo:_files -/' + elif (( CURRENT == 3 )); then + _arguments '*:dest repo:_files -/' + fi + ;; + + (rawcommit) _arguments \ - '-b[checkout the head of a specific branch]:tag:' \ - '-m[allow merging of conflicts]' \ - '-C[overwrite locally modified files]' \ + '(--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:' \ + '(-u)--user[record user as commiter]:user:' \ + '(--message)-m[use <txt> as commit message]:string:' \ + '(-m)--message[use <txt> as commit message]:string:' \ + '(--logfile)-l[read commit message from <file>]:.log file:_file -g \*.txt' \ + '(-l)--logfile[read commit message from <file>]:.log file:_file -g \*.txt' \ + '(--files)-F[file list]:file list:_files' \ + '(-F)--files[file list]:file list:_files' \ + '*:files to commit:_files' + ;; + + (bundle) + if (( CURRENT == 2 )); then + _arguments '*:changegroup file:_files -g \*.hg' + elif (( CURRENT == 3 )); then + _arguments '*:other repo:_files -/' + fi + ;; + + (unbundle) + _arguments '*:changegroup .hg file:_files -g \*.hg' + ;; + + (incoming) + _arguments \ + '(--patch)-p[show patch]' \ + '(-p)--patch[show patch]' \ + '(--no-merges)-M[do not show merge revisions]' \ + '(-M)--no-merges[do not show merge revisions]' \ + '(--newest-first)-n[show newest record first]' \ + '(-n)--newest-first[show newest record first]' \ + '*:mercurial repository:_files -/' + ;; + + (import|patch) + _arguments \ + '(--strip)-p[directory strip option for patch (default: 1)]:count:' \ + '(-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) -/' \ + '*:patch file:_files' + ;; + + (pull) + repos=( $(hg paths | sed -e 's/^.*= //') ) + _arguments \ + '(--update)-u[update working directory to tip after pull]' \ + '(-u)--update[update working directory to tip after pull]' \ + '(--ssh)-e[specify ssh command to use]:ssh command:' \ + '(-e)--ssh[specify ssh command to use]:ssh command:' \ + '--remotecmd[specify hg command to run on the remote side]:remote hg:' \ + '*:local repo:_files -/' + _wanted source expl 'source repository' compadd -a repos + ;; + + (outgoing) + _arguments \ + '(--patch)-p[show patch]' \ + '(-p)--patch[show patch]' \ + '(--no-merges)-M[do not show merge revisions]' \ + '(-M)--no-merges[do not show merge revisions]' \ + '(--newest-first)-n[show newest record first]' \ + '(-n)--newest-first[show newest record first]' \ + '*:local repo:_files -/' + _wanted source expl 'source repository' compadd -a repos + ;; + + (export) + _arguments \ + '(--outout)-o[print output to file with formatted name]:filespec:' \ + '(-o)--output[print output to file with formatted name]:filespec:' \ + '(--text)-a[treat all files as text]' \ + '(-a)--text[treat all files as text]' \ '*:revision:->revs' _wanted revs expl 'revision or tag' compadd -a tags ;; - (commit|ci) + (push) + repos=( $(hg paths | sed -e 's/^.*= //') ) _arguments \ - '-I[include path in search]:dir:_files -W $(hg root) -/' \ - '-X[exclude path in search]:dir:_files -W $(hg root) -/' \ - '-A[run addremove during commit]' \ - '-m[commit message]:string:' \ - '-d[date code]:string:' \ - '-u[user]:string:' \ - '*:file:_files' + '(--force)-f[force push]' \ + '(-f)--force[force push]' \ + '(--ssh)-e[specify ssh command to use]:ssh command:' \ + '(-e)--ssh[specify ssh command to use]:ssh command:' \ + '--remotecmd[specify hg command to run on the remote side]:remote hg:' \ + '*:local repo:_files -/' + _wanted source expl 'source repository' compadd -a repos ;; - (tag) + (serve) _arguments \ - '-l[make the tag local]:' \ - '-m[commit message]:string:' \ - '-d[date code]:string:' \ - '-u[user]:string:' \ - '*:name and revision:' + '(--accesslog)-A[name of access log file]:log file:_files' \ + '(-A)--accesslog[name of access log file]:log file:_files' \ + '(--errorlog)-E[name of error log file]:log file:_files' \ + '(-E)--errorlog[name of error log file]:log file:_files' \ + '(--port)-p[listen port]:listen port:' \ + '(-p)--port[listen port]:listen port:' \ + '(--address)-a[interface address]:interface address:' \ + '(-a)--address[interface address]:interface address:' \ + '(--name)-n[name to show in web pages]:repository name:' \ + '(-n)--name[name to show in web pages]:repository name:' \ + '(--templates)-t[web template directory]:template dir:_files -/' \ + '(-t)--templates[web template directory]:template dir:_files -/' \ + '--style[web template style]:style' \ + '--stdio[for remote clients]' \ + '(--ipv6)-6[use IPv6 in addition to IPv4]' \ + '(-6)--ipv6[use IPv6 in addition to IPv4]' ;; - (clone) - _arguments \ - '-U[skip update after cloning]' \ - '-e[ssh command]:string:' \ - '--pull[use pull protocol to copy metadata]' \ - '--remotecmd[remote hg command]:command:->subcmd' - ;; - - (export) - _arguments \ - '-o[output to a file]:file:' \ - '-a-[tread all files as text]' \ - '*:revision:->revs' - _wanted revs expl 'revision or tag' compadd -a tags + (help) + _wanted commands expl 'hg command' compadd -a subcmds ;; (heads) - _arguments '-b[find branch info]' - ;; - - (outgoing|out) - _arguments '-p[show patch]' + _arguments \ + '(--branches)-b[find branch info]' \ + '(-b)--branches[find branch info]' ;; (paths) @@ -134,175 +405,15 @@ _arguments '*:new repo directory:_files -/' ;; - (unbundle) - _arguments '*:changegroup file:_files' - ;; - (manifest) - _arguments \ - '*:revision:->revs' - _wanted revs expl 'revision or tag' compadd -a tags + _arguments '*:revision:($tags)' ;; (parents) - _arguments \ - '*:revision:->revs' - _wanted revs expl 'revision or tag' compadd -a tags - ;; - - (serve) - _arguments \ - '-A[access log file]:log file:_files' \ - '-E[error log file]:log file:_files' \ - '-p[listen port]:listen port:' \ - '-a[interface address]:interface address:' \ - '-n[repository name]:repository name:' \ - '--stdio[for remote clients]' \ - '-t[template directory]:template dir:_files -/' \ - '--style[template style]:style' \ - '-6[use IPv6 in addition to IPv4]' - ;; - - (pull) - repos=( $(hg paths | sed -e 's/^.*= //') ) - _arguments \ - '-u[update working directory]' \ - '-e[ssh command]:remote commands:' \ - '--remotecmd[remote hg command]:command:->subcmd' \ - '*:pull source:->repo' - _wanted source expl 'source repository' compadd -a repos - ;; - - (push) - repos=( $(hg paths | sed -e 's/^.*= //') ) - _arguments \ - '-f[force push]' \ - '-e[ssh command]:remote commands:' \ - '--remotecmd[remote hg command]:command:->subcmd' \ - '*:pull source:->repo' - _wanted source expl 'source repository' compadd -a repos - ;; - - (id|identify) - ;; - - (recover) - ;; - - (rawcommit) - _arguments \ - '-p[parent]:revision:($tags)' \ - '-d[date]:date:' \ - '-u[user]:user:' \ - '-F[file list]:file list:_files' \ - '-m[commit message]:string:' \ - '-l[commit message file]:message file:_files -g *.txt' \ - '*:files to commit:_files' - ;; - - (copy|cp) - _arguments \ - '-I[include path in search]:dir:_files -W $(hg root) -/' \ - '-X[exclude path in search]:dir:_files -W $(hg root) -/' \ - '-A-[record a copy after it has happened]' \ - '-f[replace destination if it exists]' \ - '-p[append source path to dest]' \ - '*:destination:' - ;; - - (rename|mv) - _arguments \ - '-I[include path in search]:dir:_files -W $(hg root) -/' \ - '-X[exclude path in search]:dir:_files -W $(hg root) -/' \ - '-A-[record a copy after it has happened]' \ - '-f[replace destination if it exists]' \ - '-p[append source path to dest]' \ - '*:destination:' + _arguments '*:revision:($tags)' ;; - (forget) - addedFiles=( $(hg status -an) ) - _arguments \ - '-I[include path in search]:dir:_files -W $(hg root) -/' \ - '-X[exclude path in search]:dir:_files -W $(hg root) -/' - _wanted files expl 'newly added files' compadd -a addedFiles - ;; - - (import|patch) - _arguments \ - '-p[path strip (default: 1)]:count:' \ - '-f[skip check for outstanding changes]' \ - '-b[base path]:file:_files -W $(hg root)' \ - '*:patch file:_files' - ;; - - (incoming|in) - _arguments \ - '-p[show patch]' \ - '*:mercurial repository:_files' - ;; - - (diff) - _arguments \ - '-I[include path in search]:dir:_files -W $(hg root) -/' \ - '-X[exclude path in search]:dir:_files -W $(hg root) -/' \ - '-r[revision]:revision:($tags)' \ - '-a-[tread all files as text]' \ - '*:file:_files' - ;; - - (log|history) - _arguments \ - '-I[include path in search]:dir:_files -W $(hg root) -/' \ - '-X[exclude path in search]:dir:_files -W $(hg root) -/' \ - '-r[revision]:revision:($tags)' \ - '-b[show branches]' \ - '-p[show patch]' \ - '*:file:_files' - ;; - - (grep) - _arguments \ - '-I[include path in search]:dir:_files -W $(hg root) -/' \ - '-X[exclude path in search]:dir:_files -W $(hg root) -/' \ - '-0[end fields with NUL]' \ - '--all[print all revisions with matches]' \ - '-i[ignore case]' \ - '-l[print names of files and revs with matches]' \ - '-n[print line numbers]' \ - '-r[search in revision rev]:revision:($tags)' \ - '-u[print user who made change]' \ - '*:search pattern, then files:_files' - ;; - - (status) - _arguments \ - '-I[include path in search]:dir:_files -W $(hg root) -/' \ - '-X[exclude path in search]:dir:_files -W $(hg root) -/' \ - '-0[end filenames with NUL]' \ - '-m[show only modified files]' \ - '-a[show only added files]' \ - '-r[show only removed files]' \ - '-u[show only unknown files]' \ - '-n[hide status prefix]' \ - '*:search pattern, then files:_files' - ;; - - (locate) - _arguments \ - '-r[search in revision rev]:revision:($tags)' \ - '-0[end fields with NUL]' \ - '-f[print complete paths]' \ - '-I[include path in search]:dir:_files -W $(hg root) -/' \ - '-X[exclude path in search]:dir:_files -W $(hg root) -/' \ - '*:search pattern:' - ;; - - (help) - _wanted commands expl 'hg command' compadd -a subcmds - ;; - - (root|undo|view|verify|version) + (identify|recover|root|undo|view|verify|version|ct|tags) # no arguments for these commands ;;
--- a/doc/Makefile Sun Oct 16 16:24:40 2005 -0700 +++ b/doc/Makefile Thu Oct 27 12:26:16 2005 -0700 @@ -15,7 +15,7 @@ asciidoc -d manpage -b docbook $*.txt %.html: %.txt - asciidoc -b html $*.txt + asciidoc -b html4 $*.txt clean: $(RM) $(MAN) $(MAN:%=%.xml) $(MAN:%=%.html)
--- a/doc/hg.1.txt Sun Oct 16 16:24:40 2005 -0700 +++ b/doc/hg.1.txt Thu Oct 27 12:26:16 2005 -0700 @@ -201,7 +201,6 @@ -I, --include <pat> include names matching the given patterns -X, --exclude <pat> exclude names matching the given patterns -f, --force forcibly copy over an existing managed file - -p, --parents append source path to dest aliases: cp @@ -493,7 +492,6 @@ Options: -A, --after record a rename that has already occurred -f, --force forcibly copy over an existing managed file - -p, --parents append source path to dest aliases: mv
--- a/hgmerge Sun Oct 16 16:24:40 2005 -0700 +++ b/hgmerge Thu Oct 27 12:26:16 2005 -0700 @@ -15,6 +15,17 @@ EDITOR="vi" fi +# find decent versions of our utilities, insisting on the GNU versions where we +# need to +DIFF3=gdiff3 +DIFF=gdiff +PATCH=gpatch + +type $DIFF3 >/dev/null 2>&1 || DIFF3=diff3 +type $DIFF >/dev/null 2>&1 || DIFF=diff +type $PATCH >/dev/null 2>&1 || PATCH=patch +$DIFF3 --version >/dev/null 2>&1 || DIFF3= + # Back up our file cp "$LOCAL" "$LOCAL.orig" @@ -22,8 +33,14 @@ if type merge > /dev/null 2>&1; then merge "$LOCAL" "$BASE" "$OTHER" 2> /dev/null && exit 0 cp "$LOCAL.orig" "$LOCAL" -elif type diff3 > /dev/null 2>&1; then - diff3 -m "$LOCAL.orig" "$BASE" "$OTHER" > "$LOCAL" && exit 0 +elif [ -n "$DIFF3" ]; then + echo $DIFF3 -m "$LOCAL.orig" "$BASE" "$OTHER" + $DIFF3 -m "$LOCAL.orig" "$BASE" "$OTHER" > "$LOCAL" && exit 0 + if [ $? -eq 2 ]; then + echo "$DIFF3 failed! Exiting." 1>&2 + cp "$LOCAL.orig" "$LOCAL" + exit 1 + fi cp "$LOCAL.orig" "$LOCAL" fi @@ -48,10 +65,18 @@ exit 0 fi -if type diff3 > /dev/null 2>&1; then +if [ -n "$DIFF3" ]; then echo "conflicts detected in $LOCAL" - diff3 -m "$LOCAL.orig" "$BASE" "$OTHER" > "$LOCAL" || $EDITOR "$LOCAL" - exit 0 + $DIFF3 -m "$LOCAL.orig" "$BASE" "$OTHER" > "$LOCAL" || { + case $? in + 1) + $EDITOR "$LOCAL" ;; + 2) echo "$DIFF3 failed! Exiting." 1>&2 + cp "$LOCAL.orig" "$LOCAL" + exit 1 ;; + esac + exit 0 + } fi HGTMP="" @@ -60,7 +85,7 @@ } # attempt to manually merge with diff and patch -if type diff > /dev/null 2>&1 && type patch > /dev/null 2>&1; then +if [ -n "$DIFF" -a -n "$PATCH" ]; then # Remove temporary files even if we get interrupted trap "cleanup_exit" 0 # normal exit trap "exit 1" 1 2 3 6 15 # HUP INT QUIT ABRT TERM @@ -71,8 +96,8 @@ exit 1 } - diff -u "$BASE" "$OTHER" > "$HGTMP/diff" - if patch "$LOCAL" < "$HGTMP/diff"; then + $DIFF -u "$BASE" "$OTHER" > "$HGTMP/diff" || : + if $PATCH "$LOCAL" < "$HGTMP/diff"; then exit 0 else # If rejects are empty after using the editor, merge was ok
--- a/mercurial/bdiff.c Sun Oct 16 16:24:40 2005 -0700 +++ b/mercurial/bdiff.c Thu Oct 27 12:26:16 2005 -0700 @@ -53,7 +53,7 @@ struct hunk *base, *head; }; -static __inline uint32_t rol32(uint32_t word, unsigned int shift) +static inline uint32_t rol32(uint32_t word, unsigned int shift) { return (word << shift) | (word >> (32 - shift)); }
--- a/mercurial/changelog.py Sun Oct 16 16:24:40 2005 -0700 +++ b/mercurial/changelog.py Thu Oct 27 12:26:16 2005 -0700 @@ -6,6 +6,7 @@ # of the GNU General Public License, incorporated herein by reference. from revlog import * +from i18n import gettext as _ from demandload import demandload demandload(globals(), "os time util") @@ -43,11 +44,11 @@ try: when, offset = map(int, date.split(' ')) except ValueError: - raise ValueError('invalid date: %r' % date) + raise ValueError(_('invalid date: %r') % date) if abs(when) > 0x7fffffff: - raise ValueError('date exceeds 32 bits: %d' % when) + raise ValueError(_('date exceeds 32 bits: %d') % when) if abs(offset) >= 43200: - raise ValueError('impossible time zone offset: %d' % offset) + raise ValueError(_('impossible time zone offset: %d') % offset) else: date = "%d %d" % util.makedate() list.sort()
--- a/mercurial/commands.py Sun Oct 16 16:24:40 2005 -0700 +++ b/mercurial/commands.py Thu Oct 27 12:26:16 2005 -0700 @@ -7,6 +7,7 @@ from demandload import demandload from node import * +from i18n import gettext as _ demandload(globals(), "os re sys signal shutil imp urllib pdb") demandload(globals(), "fancyopts ui hg util lock revlog") demandload(globals(), "fnmatch hgweb mdiff random signal time traceback") @@ -31,7 +32,7 @@ return args def matchpats(repo, cwd, pats=[], opts={}, head=''): - return util.matcher(repo.root, cwd, pats or ['.'], opts.get('include'), + return util.cmdmatcher(repo.root, cwd, pats or ['.'], opts.get('include'), opts.get('exclude'), head) def makewalk(repo, pats, opts, head=''): @@ -178,7 +179,7 @@ try: num = revlog.rev(revlog.lookup(val)) except KeyError: - raise util.Abort('invalid revision identifier %s', val) + raise util.Abort(_('invalid revision identifier %s'), val) return num seen = {} for spec in revs: @@ -238,7 +239,7 @@ i += 1 return ''.join(newname) except KeyError, inst: - raise util.Abort("invalid format spec '%%%s' in output file name", + raise util.Abort(_("invalid format spec '%%%s' in output file name"), inst.args[0]) def make_file(repo, r, pat, node=None, @@ -332,52 +333,52 @@ parents = [] if ui.verbose: - ui.write("changeset: %d:%s\n" % (rev, hex(changenode))) + ui.write(_("changeset: %d:%s\n") % (rev, hex(changenode))) else: - ui.write("changeset: %d:%s\n" % (rev, short(changenode))) + ui.write(_("changeset: %d:%s\n") % (rev, short(changenode))) for tag in repo.nodetags(changenode): - ui.status("tag: %s\n" % tag) + ui.status(_("tag: %s\n") % tag) for parent in parents: - ui.write("parent: %d:%s\n" % parent) + ui.write(_("parent: %d:%s\n") % parent) if brinfo and changenode in brinfo: br = brinfo[changenode] - ui.write("branch: %s\n" % " ".join(br)) + ui.write(_("branch: %s\n") % " ".join(br)) - ui.debug("manifest: %d:%s\n" % (repo.manifest.rev(changes[0]), + ui.debug(_("manifest: %d:%s\n") % (repo.manifest.rev(changes[0]), hex(changes[0]))) - ui.status("user: %s\n" % changes[1]) - ui.status("date: %s\n" % date) + ui.status(_("user: %s\n") % changes[1]) + ui.status(_("date: %s\n") % date) if ui.debugflag: files = repo.changes(log.parents(changenode)[0], changenode) - for key, value in zip(["files:", "files+:", "files-:"], files): + for key, value in zip([_("files:"), _("files+:"), _("files-:")], files): if value: ui.note("%-12s %s\n" % (key, " ".join(value))) else: - ui.note("files: %s\n" % " ".join(changes[3])) + ui.note(_("files: %s\n") % " ".join(changes[3])) description = changes[4].strip() if description: if ui.verbose: - ui.status("description:\n") + ui.status(_("description:\n")) ui.status(description) ui.status("\n\n") else: - ui.status("summary: %s\n" % description.splitlines()[0]) + ui.status(_("summary: %s\n") % description.splitlines()[0]) ui.status("\n") def show_version(ui): """output version and copyright information""" - ui.write("Mercurial Distributed SCM (version %s)\n" + ui.write(_("Mercurial Distributed SCM (version %s)\n") % version.get_version()) - ui.status( + ui.status(_( "\nCopyright (C) 2005 Matt Mackall <mpm@selenic.com>\n" "This is free software; see the source for copying conditions. " "There is NO\nwarranty; " "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n" - ) + )) def help_(ui, cmd=None, with_version=False): """show help for a given command or all commands""" @@ -400,7 +401,7 @@ # aliases aliases = ', '.join(key.split('|')[1:]) if aliases: - ui.write("\naliases: %s\n" % aliases) + ui.write(_("\naliases: %s\n") % aliases) # options if i[1]: @@ -411,18 +412,18 @@ if ui.verbose or with_version: show_version(ui) else: - ui.status("Mercurial Distributed SCM\n") + ui.status(_("Mercurial Distributed SCM\n")) ui.status('\n') # list of commands if cmd == "shortlist": - ui.status('basic commands (use "hg help" ' - 'for the full list or option "-v" for details):\n\n') + ui.status(_('basic commands (use "hg help" ' + 'for the full list or option "-v" for details):\n\n')) elif ui.verbose: - ui.status('list of commands:\n\n') + ui.status(_('list of commands:\n\n')) else: - ui.status('list of commands (use "hg help -v" ' - 'to show aliases and global options):\n\n') + ui.status(_('list of commands (use "hg help -v" ' + 'to show aliases and global options):\n\n')) h = {} cmds = {} @@ -461,7 +462,7 @@ opt_output.append(("%2s%s" % (shortopt and "-%s" % shortopt, longopt and " --%s" % longopt), "%s%s" % (desc, - default and " (default: %s)" % default + default and _(" (default: %s)") % default or ""))) if opt_output: @@ -475,34 +476,59 @@ # Commands start here, listed alphabetically def add(ui, repo, *pats, **opts): - '''add the specified files on the next commit''' + """add the specified files on the next commit + + Schedule files to be version controlled and added to the repository. + + The files will be added to the repository at the next commit. + + If no names are given, add all files in the current directory and + its subdirectories. + """ + names = [] for src, abs, rel, exact in walk(repo, pats, opts): if exact: - if ui.verbose: ui.status('adding %s\n' % rel) + if ui.verbose: ui.status(_('adding %s\n') % rel) names.append(abs) elif repo.dirstate.state(abs) == '?': - ui.status('adding %s\n' % rel) + ui.status(_('adding %s\n') % rel) names.append(abs) repo.add(names) def addremove(ui, repo, *pats, **opts): - """add all new files, delete all missing files""" + """add all new files, delete all missing files + + Add all new files and remove all missing files from the repository. + + New files are ignored if they match any of the patterns in .hgignore. As + with add, these changes take effect at the next commit. + """ add, remove = [], [] for src, abs, rel, exact in walk(repo, pats, opts): if src == 'f' and repo.dirstate.state(abs) == '?': add.append(abs) if ui.verbose or not exact: - ui.status('adding ', rel, '\n') + ui.status(_('adding %s\n') % rel) if repo.dirstate.state(abs) != 'r' and not os.path.exists(rel): remove.append(abs) if ui.verbose or not exact: - ui.status('removing ', rel, '\n') + ui.status(_('removing %s\n') % rel) repo.add(add) repo.remove(remove) def annotate(ui, repo, *pats, **opts): - """show changeset information per file line""" + """show changeset information per file line + + List changes in files, showing the revision id responsible for each line + + This command is useful to discover who did a change or when a change took + place. + + Without the -a option, annotate will avoid processing files it + detects as binary. With -a, annotate will generate an annotation + anyway, probably with undesirable results. + """ def getnode(rev): return short(repo.changelog.node(rev)) @@ -512,7 +538,7 @@ return trimuser(ui, cl[1], rev, ucache) if not pats: - raise util.Abort('at least one file name or pattern required') + raise util.Abort(_('at least one file name or pattern required')) opmap = [['user', getname], ['number', str], ['changeset', getnode]] if not opts['user'] and not opts['changeset']: @@ -527,12 +553,12 @@ for src, abs, rel, exact in walk(repo, pats, opts): if abs not in mmap: - ui.warn("warning: %s is not in the repository!\n" % rel) + ui.warn(_("warning: %s is not in the repository!\n") % rel) continue f = repo.file(abs) if not opts['text'] and util.binary(f.read(mmap[abs])): - ui.write("%s: binary file\n" % rel) + ui.write(_("%s: binary file\n") % rel) continue lines = f.annotate(mmap[abs]) @@ -550,9 +576,22 @@ ui.write("%s: %s" % (" ".join(p), l[1])) def bundle(ui, repo, fname, dest="default-push", **opts): - """create a changegroup file""" + """create a changegroup file + + Generate a compressed changegroup file collecting all changesets + not found in the other repository. + + This file can then be transferred using conventional means and + applied to another repository with the unbundle command. This is + useful when native push and pull are not available or when + exporting an entire repository is undesirable. The standard file + extension is ".hg". + + Unlike import/export, this exactly preserves all changeset + contents including permissions, rename data, and revision history. + """ f = open(fname, "wb") - dest = ui.expandpath(dest) + dest = ui.expandpath(dest, repo.root) other = hg.repository(ui, dest) o = repo.findoutgoing(other) cg = repo.changegroup(o) @@ -571,7 +610,19 @@ raise def cat(ui, repo, file1, *pats, **opts): - """output the latest or given revisions of files""" + """output the latest or given revisions of files + + Print the specified files as they were at the given revision. + If no revision is given then the tip is used. + + Output may be to a file, in which case the name of the file is + given using a format string. The formatting rules are the same as + for the export command, with the following additions: + + %s basename of file being printed + %d dirname of file being printed, or '.' if in repo root + %p root-relative path name of file being printed + """ mf = {} if opts['rev']: change = repo.changelog.read(repo.lookup(opts['rev'])) @@ -585,19 +636,34 @@ try: n = r.lookup(rev) except KeyError, inst: - raise util.Abort('cannot find file %s in rev %s', rel, rev) + raise util.Abort(_('cannot find file %s in rev %s'), rel, rev) else: n = r.tip() fp = make_file(repo, r, opts['output'], node=n, pathname=abs) fp.write(r.read(n)) def clone(ui, source, dest=None, **opts): - """make a copy of an existing repository""" + """make a copy of an existing repository + + Create a copy of an existing repository in a new directory. + + If no destination directory name is specified, it defaults to the + basename of the source. + + The location of the source is added to the new repository's + .hg/hgrc file, as the default to be used for future pulls. + + For efficiency, hardlinks are used for cloning whenever the source + and destination are on the same filesystem. Some filesystems, + such as AFS, implement hardlinking incorrectly, but do not report + errors. In these cases, use the --pull option to avoid + hardlinking. + """ if dest is None: dest = os.path.basename(os.path.normpath(source)) if os.path.exists(dest): - raise util.Abort("destination '%s' already exists", dest) + raise util.Abort(_("destination '%s' already exists"), dest) dest = os.path.realpath(dest) @@ -649,7 +715,10 @@ for f in files.split(): src = os.path.join(source, ".hg", f) dst = os.path.join(dest, ".hg", f) - util.copyfiles(src, dst) + try: + util.copyfiles(src, dst) + except OSError, inst: + if inst.errno != errno.ENOENT: raise repo = hg.repository(ui, dest) @@ -673,16 +742,22 @@ d.close() def commit(ui, repo, *pats, **opts): - """commit the specified files or all outstanding changes""" - if opts['text']: - ui.warn("Warning: -t and --text is deprecated," - " please use -m or --message instead.\n") - message = opts['message'] or opts['text'] + """commit the specified files or all outstanding changes + + Commit changes to the given files into the repository. + + If a list of files is omitted, all changes reported by "hg status" + from the root of the repository will be commited. + + The HGEDITOR or EDITOR environment variables are used to start an + editor to add a commit comment. + """ + message = opts['message'] logfile = opts['logfile'] if message and logfile: - raise util.Abort('options --message and --logfile are mutually ' - 'exclusive') + raise util.Abort(_('options --message and --logfile are mutually ' + 'exclusive')) if not message and logfile: try: if logfile == '-': @@ -690,7 +765,7 @@ else: message = open(logfile).read() except IOError, inst: - raise util.Abort("can't read commit message '%s': %s" % + raise util.Abort(_("can't read commit message '%s': %s") % (logfile, inst.strerror)) if opts['addremove']: @@ -713,19 +788,20 @@ def docopy(ui, repo, pats, opts): if not pats: - raise util.Abort('no source or destination specified') + raise util.Abort(_('no source or destination specified')) elif len(pats) == 1: - raise util.Abort('no destination specified') + raise util.Abort(_('no destination specified')) pats = list(pats) dest = pats.pop() sources = [] + dir2dir = len(pats) == 1 and os.path.isdir(pats[0]) def okaytocopy(abs, rel, exact): - reasons = {'?': 'is not managed', - 'a': 'has been marked for add'} + reasons = {'?': _('is not managed'), + 'a': _('has been marked for add')} reason = reasons.get(repo.dirstate.state(abs)) if reason: - if exact: ui.warn('%s: not copying - file %s\n' % (rel, reason)) + if exact: ui.warn(_('%s: not copying - file %s\n') % (rel, reason)) else: return True @@ -733,7 +809,7 @@ if okaytocopy(abs, rel, exact): sources.append((abs, rel, exact)) if not sources: - raise util.Abort('no files to copy') + raise util.Abort(_('no files to copy')) cwd = repo.getcwd() absdest = util.canonpath(repo.root, cwd, dest) @@ -741,36 +817,44 @@ if os.path.exists(reldest): destisfile = not os.path.isdir(reldest) else: - destisfile = len(sources) == 1 or repo.dirstate.state(absdest) != '?' + destisfile = not dir2dir and (len(sources) == 1 + or repo.dirstate.state(absdest) != '?') + + if destisfile and len(sources) > 1: + raise util.Abort(_('with multiple sources, destination must be a ' + 'directory')) - if destisfile: - if opts['parents']: - raise util.Abort('with --parents, destination must be a directory') - elif len(sources) > 1: - raise util.Abort('with multiple sources, destination must be a ' - 'directory') + srcpfxlen = 0 + if dir2dir: + srcpfx = util.pathto(cwd, util.canonpath(repo.root, cwd, pats[0])) + if os.path.exists(reldest): + srcpfx = os.path.split(srcpfx)[0] + if srcpfx: + srcpfx += os.sep + srcpfxlen = len(srcpfx) + errs, copied = 0, [] for abs, rel, exact in sources: - if opts['parents']: - mydest = os.path.join(dest, rel) - elif destisfile: + if destisfile: mydest = reldest + elif dir2dir: + mydest = os.path.join(dest, rel[srcpfxlen:]) else: mydest = os.path.join(dest, os.path.basename(rel)) myabsdest = util.canonpath(repo.root, cwd, mydest) myreldest = util.pathto(cwd, myabsdest) if not opts['force'] and repo.dirstate.state(myabsdest) not in 'a?': - ui.warn('%s: not overwriting - file already managed\n' % myreldest) + ui.warn(_('%s: not overwriting - file already managed\n') % myreldest) continue mydestdir = os.path.dirname(myreldest) or '.' if not opts['after']: try: - if opts['parents']: os.makedirs(mydestdir) + if dir2dir: os.makedirs(mydestdir) elif not destisfile: os.mkdir(mydestdir) except OSError, inst: if inst.errno != errno.EEXIST: raise if ui.verbose or not exact: - ui.status('copying %s to %s\n' % (rel, myreldest)) + ui.status(_('copying %s to %s\n') % (rel, myreldest)) if not opts['after']: try: shutil.copyfile(rel, myreldest) @@ -779,19 +863,34 @@ raise util.Abort(str(inst)) except IOError, inst: if inst.errno == errno.ENOENT: - ui.warn('%s: deleted in working copy\n' % rel) + ui.warn(_('%s: deleted in working copy\n') % rel) else: - ui.warn('%s: cannot copy - %s\n' % (rel, inst.strerror)) + ui.warn(_('%s: cannot copy - %s\n') % (rel, inst.strerror)) errs += 1 continue repo.copy(abs, myabsdest) copied.append((abs, rel, exact)) if errs: - ui.warn('(consider using --after)\n') + ui.warn(_('(consider using --after)\n')) return errs, copied def copy(ui, repo, *pats, **opts): - """mark files as copied for the next commit""" + """mark files as copied for the next commit + + Mark dest as having copies of source files. If dest is a + directory, copies are put in that directory. If dest is a file, + there can only be one source. + + By default, this command copies the contents of files as they + stand in the working directory. If invoked with --after, the + operation is recorded, but no copying is performed. + + This command takes effect in the next commit. + + NOTE: This command should be treated as experimental. While it + should properly record copied files, this information is not yet + fully used by merge, nor fully reported by log. + """ errs, copied = docopy(ui, repo, pats, opts) return errs @@ -816,22 +915,22 @@ for f in dc: state = repo.dirstate.state(f) if state in "nr" and f not in m1: - ui.warn("%s in state %s, but not in manifest1\n" % (f, state)) + ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state)) errors += 1 if state in "a" and f in m1: - ui.warn("%s in state %s, but also in manifest1\n" % (f, state)) + ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state)) errors += 1 if state in "m" and f not in m1 and f not in m2: - ui.warn("%s in state %s, but not in either manifest\n" % + ui.warn(_("%s in state %s, but not in either manifest\n") % (f, state)) errors += 1 for f in m1: state = repo.dirstate.state(f) if state not in "nrm": - ui.warn("%s in manifest1, but listed as state %s" % (f, state)) + ui.warn(_("%s in manifest1, but listed as state %s") % (f, state)) errors += 1 if errors: - raise util.Abort(".hg/dirstate inconsistent with current parent's manifest") + raise util.Abort(_(".hg/dirstate inconsistent with current parent's manifest")) def debugconfig(ui): """show combined config settings from all hgrc files""" @@ -842,6 +941,19 @@ for section, name, value in ui.walkconfig(): ui.write('%s.%s=%s\n' % (section, name, value)) +def debugsetparents(ui, repo, rev1, rev2=None): + """ + manually set the parents of the current working directory + + This is useful for writing repository conversion tools, but should + be used with care. + """ + + if not rev2: + rev2 = hex(nullid) + + repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2)) + def debugstate(ui, repo): """show the contents of the current dirstate""" repo.dirstate.read() @@ -854,7 +966,7 @@ time.strftime("%x %X", time.localtime(dc[file_][3])), file_)) for f in repo.dirstate.copies: - ui.write("copy: %s -> %s\n" % (repo.dirstate.copies[f], f)) + ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copies[f], f)) def debugdata(ui, file_, rev): """dump the contents of an data file revision""" @@ -862,7 +974,7 @@ try: ui.write(r.revision(r.lookup(rev))) except KeyError: - raise util.Abort('invalid revision identifier %s', rev) + raise util.Abort(_('invalid revision identifier %s'), rev) def debugindex(ui, file_): """dump the contents of an index file""" @@ -902,9 +1014,9 @@ n = r.tip() m = r.renamed(n) if m: - ui.write("renamed from %s:%s\n" % (m[0], hex(m[1]))) + ui.write(_("renamed from %s:%s\n") % (m[0], hex(m[1]))) else: - ui.write("not renamed\n") + ui.write(_("not renamed\n")) def debugwalk(ui, repo, *pats, **opts): """show how files match on given patterns""" @@ -919,7 +1031,22 @@ ui.write("%s\n" % line.rstrip()) def diff(ui, repo, *pats, **opts): - """diff working directory (or selected files)""" + """diff working directory (or selected files) + + Show differences between revisions for the specified files. + + Differences between files are shown using the unified diff format. + + When two revision arguments are given, then changes are shown + between those revisions. If only one revision is specified then + that revision is compared to the working directory, and, when no + revisions are specified, the working directory files are compared + to its parent. + + Without the -a option, diff will avoid generating diffs of files + it detects as binary. With -a, diff will generate a diff anyway, + probably with undesirable results. + """ node1, node2 = None, None revs = [repo.lookup(x) for x in opts['rev']] @@ -928,7 +1055,7 @@ if len(revs) > 1: node2 = revs[1] if len(revs) > 2: - raise util.Abort("too many revisions to diff") + raise util.Abort(_("too many revisions to diff")) fns, matchfn, anypats = matchpats(repo, repo.getcwd(), pats, opts) @@ -960,30 +1087,69 @@ fp.close() def export(ui, repo, *changesets, **opts): - """dump the header and diffs for one or more changesets""" + """dump the header and diffs for one or more changesets + + Print the changeset header and diffs for one or more revisions. + + The information shown in the changeset header is: author, + changeset hash, parent and commit comment. + + Output may be to a file, in which case the name of the file is + given using a format string. The formatting rules are as follows: + + %% literal "%" character + %H changeset hash (40 bytes of hexadecimal) + %N number of patches being generated + %R changeset revision number + %b basename of the exporting repository + %h short-form changeset hash (12 bytes of hexadecimal) + %n zero-padded sequence number, starting at 1 + %r zero-padded changeset revision number + + Without the -a option, export will avoid generating diffs of files + it detects as binary. With -a, export will generate a diff anyway, + probably with undesirable results. + """ if not changesets: - raise util.Abort("export requires at least one changeset") + raise util.Abort(_("export requires at least one changeset")) seqno = 0 revs = list(revrange(ui, repo, changesets)) total = len(revs) revwidth = max(map(len, revs)) - ui.note(len(revs) > 1 and "Exporting patches:\n" or "Exporting patch:\n") + ui.note(len(revs) > 1 and _("Exporting patches:\n") or _("Exporting patch:\n")) for cset in revs: seqno += 1 doexport(ui, repo, cset, seqno, total, revwidth, opts) def forget(ui, repo, *pats, **opts): - """don't add the specified files on the next commit""" + """don't add the specified files on the next commit + + Undo an 'hg add' scheduled for the next commit. + """ forget = [] for src, abs, rel, exact in walk(repo, pats, opts): if repo.dirstate.state(abs) == 'a': forget.append(abs) if ui.verbose or not exact: - ui.status('forgetting ', rel, '\n') + ui.status(_('forgetting %s\n') % rel) repo.forget(forget) def grep(ui, repo, pattern, *pats, **opts): - """search for a pattern in specified files and revisions""" + """search for a pattern in specified files and revisions + + Search revisions of files for a regular expression. + + This command behaves differently than Unix grep. It only accepts + Python/Perl regexps. It searches repository history, not the + working directory. It always prints the revision number in which + a match appears. + + By default, grep only prints output for the first revision of a + file in which it finds a match. To get it to print every revision + that contains a change in match status ("-" for a match that + becomes a non-match, or "+" for a non-match that becomes a match), + use the --all flag. + """ reflags = 0 if opts['ignore_case']: reflags |= re.I @@ -1102,7 +1268,14 @@ return (count == 0 and 1) or 0 def heads(ui, repo, **opts): - """show current repository heads""" + """show current repository heads + + Show all repository head changesets. + + Repository "heads" are changesets that don't have children + changesets. They are where development generally takes place and + are the usual targets for update and merge operations. + """ heads = repo.changelog.heads() br = None if opts['branches']: @@ -1111,10 +1284,16 @@ show_changeset(ui, repo, changenode=n, brinfo=br) def identify(ui, repo): - """print information about the working copy""" + """print information about the working copy + Print a short summary of the current state of the repo. + + This summary identifies the repository state using one or two parent + hash identifiers, followed by a "+" if there are uncommitted changes + in the working directory, followed by a list of tags for this revision. + """ parents = [p for p in repo.dirstate.parents() if p != nullid] if not parents: - ui.write("unknown\n") + ui.write(_("unknown\n")) return hexfunc = ui.verbose and hex or short @@ -1133,22 +1312,39 @@ ui.write("%s\n" % ' '.join(output)) def import_(ui, repo, patch1, *patches, **opts): - """import an ordered set of patches""" + """import an ordered set of patches + + Import a list of patches and commit them individually. + + If there are outstanding changes in the working directory, import + will abort unless given the -f flag. + + If a patch looks like a mail message (its first line starts with + "From " or looks like an RFC822 header), it will not be applied + unless the -f option is used. The importer neither parses nor + discards mail headers, so use -f only to override the "mailness" + safety check, not to import a real mail message. + """ patches = (patch1,) + patches if not opts['force']: (c, a, d, u) = repo.changes() if c or a or d: - raise util.Abort("outstanding uncommitted changes") + raise util.Abort(_("outstanding uncommitted changes")) d = opts["base"] strip = opts["strip"] mailre = re.compile(r'(?:From |[\w-]+:)') - diffre = re.compile(r'(?:diff -|--- .*\s+\w+ \w+ +\d+ \d+:\d+:\d+ \d+)') + + # attempt to detect the start of a patch + # (this heuristic is borrowed from quilt) + diffre = re.compile(r'(?:Index:[ \t]|diff[ \t]|RCS file: |' + + 'retrieving revision [0-9]+(\.[0-9]+)*$|' + + '(---|\*\*\*)[ \t])') for patch in patches: - ui.status("applying %s\n" % patch) + ui.status(_("applying %s\n") % patch) pf = os.path.join(d, patch) message = [] @@ -1159,15 +1355,15 @@ if (not message and not hgpatch and mailre.match(line) and not opts['force']): if len(line) > 35: line = line[:32] + '...' - raise util.Abort('first line looks like a ' - 'mail header: ' + line) + raise util.Abort(_('first line looks like a ' + 'mail header: ') + line) if diffre.match(line): break elif hgpatch: # parse values when importing the result of an hg export if line.startswith("# User "): user = line[7:] - ui.debug('User: %s\n' % user) + ui.debug(_('User: %s\n') % user) elif not line.startswith("# ") and line: message.append(line) hgpatch = False @@ -1179,10 +1375,10 @@ # make sure message isn't empty if not message: - message = "imported patch %s\n" % patch + message = _("imported patch %s\n") % patch else: message = "%s\n" % '\n'.join(message) - ui.debug('message:\n%s\n' % message) + ui.debug(_('message:\n%s\n') % message) files = util.patch(strip, pf, ui) @@ -1191,30 +1387,64 @@ repo.commit(files, message, user) def incoming(ui, repo, source="default", **opts): - """show new changesets found in source""" - source = ui.expandpath(source) + """show new changesets found in source + + Show new changesets found in the specified repo or the default + pull repo. These are the changesets that would be pulled if a pull + was requested. + + Currently only local repositories are supported. + """ + source = ui.expandpath(source, repo.root) other = hg.repository(ui, source) if not other.local(): - raise util.Abort("incoming doesn't work for remote repositories yet") + raise util.Abort(_("incoming doesn't work for remote repositories yet")) o = repo.findincoming(other) if not o: return o = other.changelog.nodesbetween(o)[0] + if opts['newest_first']: + o.reverse() for n in o: + parents = [p for p in other.changelog.parents(n) if p != nullid] + if opts['no_merges'] and len(parents) == 2: + continue show_changeset(ui, other, changenode=n) if opts['patch']: - prev = other.changelog.parents(n)[0] + prev = (parents and parents[0]) or nullid dodiff(ui, ui, other, prev, n) ui.write("\n") def init(ui, dest="."): - """create a new repository in the given directory""" + """create a new repository in the given directory + + Initialize a new repository in the given directory. If the given + directory does not exist, it is created. + + If no directory is given, the current directory is used. + """ if not os.path.exists(dest): os.mkdir(dest) hg.repository(ui, dest, create=1) def locate(ui, repo, *pats, **opts): - """locate files matching specific patterns""" + """locate files matching specific patterns + + Print all files under Mercurial control whose names match the + given patterns. + + This command searches the current directory and its + subdirectories. To search an entire repository, move to the root + of the repository. + + If no patterns are given to match, this command prints all file + names. + + If you want to feed the output of this command into the "xargs" + command, use the "-0" option to both this command and "xargs". + This will avoid the problem of "xargs" treating single filenames + that contain white space as multiple filenames. + """ end = opts['print0'] and '\0' or '\n' for src, abs, rel, exact in walk(repo, pats, opts, '(?:.*/|)'): @@ -1226,7 +1456,15 @@ ui.write(rel, end) def log(ui, repo, *pats, **opts): - """show revision history of entire repository or files""" + """show revision history of entire repository or files + + Print the revision history of the specified files or the entire project. + + By default this command outputs: changeset id and hash, tags, + parents, user, date and time, and a summary for each commit. The + -v switch adds some more detail, such as changed files, manifest + hashes or message signatures. + """ class dui: # Implement and delegate some ui protocol. Save hunks of # output for later display in the desired order. @@ -1260,14 +1498,19 @@ du = dui(ui) elif st == 'add': du.bump(rev) + changenode = repo.changelog.node(rev) + parents = [p for p in repo.changelog.parents(changenode) + if p != nullid] + if opts['no_merges'] and len(parents) == 2: + continue + if opts['only_merges'] and len(parents) != 2: + continue + br = None - if opts['branch']: - br = repo.branchlookup([repo.changelog.node(rev)]) - if opts['keyword']: changes = repo.changelog.read(repo.changelog.node(rev)) miss = 0 - for k in opts['keyword']: + for k in [kw.lower() for kw in opts['keyword']]: if not (k in changes[1].lower() or k in changes[4].lower() or k in " ".join(changes[3][:20]).lower()): @@ -1276,10 +1519,12 @@ if miss: continue + if opts['branch']: + br = repo.branchlookup([repo.changelog.node(rev)]) + show_changeset(du, repo, rev, brinfo=br) if opts['patch']: - changenode = repo.changelog.node(rev) - prev, other = repo.changelog.parents(changenode) + prev = (parents and parents[0]) or nullid dodiff(du, du, repo, prev, changenode, fns) du.write("\n\n") elif st == 'iter': @@ -1287,7 +1532,13 @@ ui.write(*args) def manifest(ui, repo, rev=None): - """output the latest or given revision of the project manifest""" + """output the latest or given revision of the project manifest + + Print a list of version controlled files for the given revision. + + The manifest is the list of files being version controlled. If no revision + is given then the tip is used. + """ if rev: try: # assume all revision numbers are for changesets @@ -1307,20 +1558,33 @@ ui.write("%40s %3s %s\n" % (hex(m[f]), mf[f] and "755" or "644", f)) def outgoing(ui, repo, dest="default-push", **opts): - """show changesets not found in destination""" - dest = ui.expandpath(dest) + """show changesets not found in destination + + Show changesets not found in the specified destination repo or the + default push repo. These are the changesets that would be pushed + if a push was requested. + """ + dest = ui.expandpath(dest, repo.root) other = hg.repository(ui, dest) o = repo.findoutgoing(other) o = repo.changelog.nodesbetween(o)[0] + if opts['newest_first']: + o.reverse() for n in o: + parents = [p for p in repo.changelog.parents(n) if p != nullid] + if opts['no_merges'] and len(parents) == 2: + continue show_changeset(ui, repo, changenode=n) if opts['patch']: - prev = repo.changelog.parents(n)[0] + prev = (parents and parents[0]) or nullid dodiff(ui, ui, repo, prev, n) ui.write("\n") def parents(ui, repo, rev=None): - """show the parents of the working dir or revision""" + """show the parents of the working dir or revision + + Print the working directory's parent revisions. + """ if rev: p = repo.changelog.parents(repo.lookup(rev)) else: @@ -1331,7 +1595,14 @@ show_changeset(ui, repo, changenode=n) def paths(ui, search=None): - """show definition of symbolic path names""" + """show definition of symbolic path names + + Show definition of symbolic path name NAME. If no name is given, show + definition of available names. + + Path names are defined in the [paths] section of /etc/mercurial/hgrc + and $HOME/.hgrc. If run inside a repository, .hg/hgrc is used, too. + """ try: repo = hg.repository(ui=ui) except hg.RepoError: @@ -1342,16 +1613,35 @@ if name == search: ui.write("%s\n" % path) return - ui.warn("not found!\n") + ui.warn(_("not found!\n")) return 1 else: for name, path in ui.configitems("paths"): ui.write("%s = %s\n" % (name, path)) def pull(ui, repo, source="default", **opts): - """pull changes from the specified source""" - source = ui.expandpath(source) - ui.status('pulling from %s\n' % (source)) + """pull changes from the specified source + + Pull changes from a remote repository to a local one. + + This finds all changes from the repository at the specified path + or URL and adds them to the local repository. By default, this + does not update the copy of the project in the working directory. + + Valid URLs are of the form: + + local/filesystem/path + http://[user@]host[:port][/path] + https://[user@]host[:port][/path] + ssh://[user@]host[:port][/path] + + SSH requires an accessible shell account on the destination machine + and a copy of hg in the remote path. With SSH, paths are relative + to the remote user's home directory by default; use two slashes at + the start of a path to specify it as relative to the filesystem root. + """ + source = ui.expandpath(source, repo.root) + ui.status(_('pulling from %s\n') % (source)) if opts['ssh']: ui.setconfig("ui", "ssh", opts['ssh']) @@ -1369,13 +1659,33 @@ if opts['update']: return update(ui, repo) else: - ui.status("(run 'hg update' to get a working copy)\n") + ui.status(_("(run 'hg update' to get a working copy)\n")) return r def push(ui, repo, dest="default-push", force=False, ssh=None, remotecmd=None): - """push changes to the specified destination""" - dest = ui.expandpath(dest) + """push changes to the specified destination + + Push changes from the local repository to the given destination. + + This is the symmetrical operation for pull. It helps to move + changes from the current repository to a different one. If the + destination is local this is identical to a pull in that directory + from the current one. + + By default, push will refuse to run if it detects the result would + increase the number of remote heads. This generally indicates the + the client has forgotten to sync and merge before pushing. + + Valid URLs are of the form: + + local/filesystem/path + ssh://[user@]host[:port][/path] + + SSH requires an accessible shell account on the destination + machine and a copy of hg in the remote path. + """ + dest = ui.expandpath(dest, repo.root) ui.status('pushing to %s\n' % (dest)) if ssh: @@ -1388,10 +1698,16 @@ return r def rawcommit(ui, repo, *flist, **rc): - "raw commit interface" + """raw commit interface + + Lowlevel commit, for use in helper scripts. + + This command is not intended to be used by normal users, as it is + primarily useful for importing from other SCMs. + """ if rc['text']: - ui.warn("Warning: -t and --text is deprecated," - " please use -m or --message instead.\n") + ui.warn(_("Warning: -t and --text is deprecated," + " please use -m or --message instead.\n")) message = rc['message'] or rc['text'] if not message and rc['logfile']: try: @@ -1399,7 +1715,7 @@ except IOError: pass if not message and not rc['logfile']: - raise util.Abort("missing commit message") + raise util.Abort(_("missing commit message")) files = relpath(repo, list(flist)) if rc['files']: @@ -1413,49 +1729,83 @@ raise util.Abort(str(inst)) def recover(ui, repo): - """roll back an interrupted transaction""" + """roll back an interrupted transaction + + Recover from an interrupted commit or pull. + + This command tries to fix the repository status after an interrupted + operation. It should only be necessary when Mercurial suggests it. + """ repo.recover() def remove(ui, repo, pat, *pats, **opts): - """remove the specified files on the next commit""" + """remove the specified files on the next commit + + Schedule the indicated files for removal from the repository. + + This command schedules the files to be removed at the next commit. + This only removes files from the current branch, not from the + entire project history. If the files still exist in the working + directory, they will be deleted from it. + """ names = [] def okaytoremove(abs, rel, exact): c, a, d, u = repo.changes(files = [abs]) reason = None - if c: reason = 'is modified' - elif a: reason = 'has been marked for add' - elif u: reason = 'is not managed' + if c: reason = _('is modified') + elif a: reason = _('has been marked for add') + elif u: reason = _('is not managed') if reason: - if exact: ui.warn('not removing %s: file %s\n' % (rel, reason)) + if exact: ui.warn(_('not removing %s: file %s\n') % (rel, reason)) else: return True for src, abs, rel, exact in walk(repo, (pat,) + pats, opts): if okaytoremove(abs, rel, exact): - if ui.verbose or not exact: ui.status('removing %s\n' % rel) + if ui.verbose or not exact: ui.status(_('removing %s\n') % rel) names.append(abs) - for name in names: - try: - os.unlink(name) - except OSError, inst: - if inst.errno != errno.ENOENT: raise - repo.remove(names) + repo.remove(names, unlink=True) def rename(ui, repo, *pats, **opts): - """rename files; equivalent of copy + remove""" + """rename files; equivalent of copy + remove + + Mark dest as copies of sources; mark sources for deletion. If + dest is a directory, copies are put in that directory. If dest is + a file, there can only be one source. + + By default, this command copies the contents of files as they + stand in the working directory. If invoked with --after, the + operation is recorded, but no copying is performed. + + This command takes effect in the next commit. + + NOTE: This command should be treated as experimental. While it + should properly record rename files, this information is not yet + fully used by merge, nor fully reported by log. + """ errs, copied = docopy(ui, repo, pats, opts) names = [] for abs, rel, exact in copied: - if ui.verbose or not exact: ui.status('removing %s\n' % rel) - try: - os.unlink(rel) - except OSError, inst: - if inst.errno != errno.ENOENT: raise + if ui.verbose or not exact: ui.status(_('removing %s\n') % rel) names.append(abs) - repo.remove(names) + repo.remove(names, unlink=True) return errs def revert(ui, repo, *names, **opts): - """revert modified files or dirs back to their unmodified states""" + """revert modified files or dirs back to their unmodified states + + Revert any uncommitted modifications made to the named files or + directories. This restores the contents of the affected files to + an unmodified state. + + If a file has been deleted, it is recreated. If the executable + mode of a file was changed, it is reset. + + If a directory is given, all files in that directory and its + subdirectories are reverted. + + If no arguments are given, all files in the current directory and + its subdirectories are reverted. + """ node = opts['rev'] and repo.lookup(opts['rev']) or \ repo.dirstate.parents()[0] root = os.path.realpath(repo.root) @@ -1494,25 +1844,42 @@ chosen[relname] = 1 return ret + (c, a, d, u) = repo.changes() + repo.forget(filter(choose, a)) + repo.undelete(filter(choose, d)) + r = repo.update(node, False, True, choose, False) for n in relnames: if n not in chosen: - ui.warn('error: no matches for %s\n' % n) + ui.warn(_('error: no matches for %s\n') % n) r = 1 sys.stdout.flush() return r def root(ui, repo): - """print the root (top) of the current working dir""" + """print the root (top) of the current working dir + + Print the root directory of the current repository. + """ ui.write(repo.root + "\n") def serve(ui, repo, **opts): - """export the repository via HTTP""" + """export the repository via HTTP + + Start a local HTTP repository browser and pull server. + + By default, the server logs accesses to stdout and errors to + stderr. Use the "-A" and "-E" options to log to files. + """ if opts["stdio"]: fin, fout = sys.stdin, sys.stdout sys.stdout = sys.stderr + # Prevent insertion/deletion of CRs + util.set_binary(fin) + util.set_binary(fout) + def getarg(): argline = fin.readline()[:-1] arg, l = argline.split() @@ -1597,29 +1964,34 @@ except socket.error: pass if port != 80: - ui.status('listening at http://%s:%d/\n' % (addr, port)) + ui.status(_('listening at http://%s:%d/\n') % (addr, port)) else: - ui.status('listening at http://%s/\n' % addr) + ui.status(_('listening at http://%s/\n') % addr) httpd.serve_forever() def status(ui, repo, *pats, **opts): - '''show changed files in the working directory + """show changed files in the working directory + Show changed files in the working directory. If no names are + given, all files are shown. Otherwise, only files matching the + given names are shown. + + The codes used to show the status of files are: M = modified A = added R = removed ? = not tracked - ''' + """ cwd = repo.getcwd() files, matchfn, anypats = matchpats(repo, cwd, pats, opts) (c, a, d, u) = [[util.pathto(cwd, x) for x in n] for n in repo.changes(files=files, match=matchfn)] - changetypes = [('modified', 'M', c), - ('added', 'A', a), - ('removed', 'R', d), - ('unknown', '?', u)] + changetypes = [(_('modified'), 'M', c), + (_('added'), 'A', a), + (_('removed'), 'R', d), + (_('unknown'), '?', u)] end = opts['print0'] and '\0' or '\n' @@ -1634,19 +2006,33 @@ ui.write(format % f) def tag(ui, repo, name, rev=None, **opts): - """add a tag for the current tip or a given revision""" + """add a tag for the current tip or a given revision + + Name a particular revision using <name>. + + Tags are used to name particular revisions of the repository and are + very useful to compare different revision, to go back to significant + earlier versions or to mark branch points as releases, etc. + + If no revision is given, the tip is used. + + To facilitate version control, distribution, and merging of tags, + they are stored as a file named ".hgtags" which is managed + similarly to other project files and can be hand-edited if + necessary. + """ if opts['text']: - ui.warn("Warning: -t and --text is deprecated," - " please use -m or --message instead.\n") + ui.warn(_("Warning: -t and --text is deprecated," + " please use -m or --message instead.\n")) if name == "tip": - raise util.Abort("the name 'tip' is reserved") + raise util.Abort(_("the name 'tip' is reserved")) if rev: r = hex(repo.lookup(rev)) else: r = hex(repo.changelog.tip()) if name.find(revrangesep) >= 0: - raise util.Abort("'%s' cannot be used in a tag name" % revrangesep) + raise util.Abort(_("'%s' cannot be used in a tag name") % revrangesep) if opts['local']: repo.opener("localtags", "a").write("%s %s\n" % (r, name)) @@ -1655,22 +2041,27 @@ (c, a, d, u) = repo.changes() for x in (c, a, d, u): if ".hgtags" in x: - raise util.Abort("working copy of .hgtags is changed " - "(please commit .hgtags manually)") + raise util.Abort(_("working copy of .hgtags is changed " + "(please commit .hgtags manually)")) repo.wfile(".hgtags", "ab").write("%s %s\n" % (r, name)) if repo.dirstate.state(".hgtags") == '?': repo.add([".hgtags"]) message = (opts['message'] or opts['text'] or - "Added tag %s for changeset %s" % (name, r)) + _("Added tag %s for changeset %s") % (name, r)) try: repo.commit([".hgtags"], message, opts['user'], opts['date']) except ValueError, inst: raise util.Abort(str(inst)) def tags(ui, repo): - """list repository tags""" + """list repository tags + + List the repository tags. + + This lists both regular and local tags. + """ l = repo.tagslist() l.reverse() @@ -1682,22 +2073,28 @@ ui.write("%-30s %s\n" % (t, r)) def tip(ui, repo): - """show the tip revision""" + """show the tip revision + + Show the tip revision. + """ n = repo.changelog.tip() show_changeset(ui, repo, changenode=n) def unbundle(ui, repo, fname): - """apply a changegroup file""" + """apply a changegroup file + + Apply a compressed changegroup file generated by the bundle + command. + """ f = urllib.urlopen(fname) if f.read(4) != "HG10": - raise util.Abort("%s: not a Mercurial bundle file" % fname) + raise util.Abort(_("%s: not a Mercurial bundle file") % fname) def bzgenerator(f): zd = bz2.BZ2Decompressor() for chunk in f: yield zd.decompress(chunk) - yield zd.flush() bzgen = bzgenerator(util.filechunkiter(f, 4096)) repo.addchangegroup(util.chunkbuffer(bzgen)) @@ -1718,7 +2115,9 @@ repo.undo() def update(ui, repo, node=None, merge=False, clean=False, branch=None): - '''update or merge working directory + """update or merge working directory + + Update the working directory to the specified revision. If there are no outstanding changes in the working directory and there is a linear relationship between the current version and the @@ -1729,7 +2128,10 @@ changed between either parent are marked as changed for the next commit and a commit must be performed before any further updates are allowed. - ''' + + By default, update will refuse to run if doing so would require + merging or discarding local changes. + """ if branch: br = repo.branchlookup(branch=branch) found = [] @@ -1737,22 +2139,30 @@ if branch in br[x]: found.append(x) if len(found) > 1: - ui.warn("Found multiple heads for %s\n" % branch) + ui.warn(_("Found multiple heads for %s\n") % branch) for x in found: show_changeset(ui, repo, changenode=x, brinfo=br) return 1 if len(found) == 1: node = found[0] - ui.warn("Using head %s for branch %s\n" % (short(node), branch)) + ui.warn(_("Using head %s for branch %s\n") % (short(node), branch)) else: - ui.warn("branch %s not found\n" % (branch)) + ui.warn(_("branch %s not found\n") % (branch)) return 1 else: node = node and repo.lookup(node) or repo.changelog.tip() return repo.update(node, allow=merge, force=clean) def verify(ui, repo): - """verify the integrity of the repository""" + """verify the integrity of the repository + + Verify the integrity of the current repository. + + This will perform an extensive check of the repository's + integrity, validating the hashes and checksums of each entry in + the changelog, manifest, and tracked files, as well as the + integrity of their crosslinks and indices. + """ return repo.verify() # Command options and aliases are listed here, alphabetically @@ -1760,244 +2170,249 @@ table = { "^add": (add, - [('I', 'include', [], 'include path in search'), - ('X', 'exclude', [], 'exclude path from search')], + [('I', 'include', [], _('include names matching the given patterns')), + ('X', 'exclude', [], _('exclude names matching the given patterns'))], "hg add [OPTION]... [FILE]..."), "addremove": (addremove, - [('I', 'include', [], 'include path in search'), - ('X', 'exclude', [], 'exclude path from search')], + [('I', 'include', [], _('include names matching the given patterns')), + ('X', 'exclude', [], _('exclude names matching the given patterns'))], "hg addremove [OPTION]... [FILE]..."), "^annotate": (annotate, - [('r', 'rev', '', 'revision'), - ('a', 'text', None, 'treat all files as text'), - ('u', 'user', None, 'show user'), - ('n', 'number', None, 'show revision number'), - ('c', 'changeset', None, 'show changeset'), - ('I', 'include', [], 'include path in search'), - ('X', 'exclude', [], 'exclude path from search')], - 'hg annotate [OPTION]... FILE...'), + [('r', 'rev', '', _('annotate the specified revision')), + ('a', 'text', None, _('treat all files as text')), + ('u', 'user', None, _('list the author')), + ('n', 'number', None, _('list the revision number (default)')), + ('c', 'changeset', None, _('list the changeset')), + ('I', 'include', [], _('include names matching the given patterns')), + ('X', 'exclude', [], _('exclude names matching the given patterns'))], + _('hg annotate [OPTION]... FILE...')), "bundle": (bundle, [], - 'hg bundle FILE DEST'), + _('hg bundle FILE DEST')), "cat": (cat, - [('I', 'include', [], 'include path in search'), - ('X', 'exclude', [], 'exclude path from search'), - ('o', 'output', "", 'output to file'), - ('r', 'rev', '', 'revision')], - 'hg cat [OPTION]... FILE...'), + [('I', 'include', [], _('include names matching the given patterns')), + ('X', 'exclude', [], _('exclude names matching the given patterns')), + ('o', 'output', "", _('print output to file with formatted name')), + ('r', 'rev', '', _('print the given revision'))], + _('hg cat [OPTION]... FILE...')), "^clone": (clone, - [('U', 'noupdate', None, 'skip update after cloning'), - ('e', 'ssh', "", 'ssh command'), - ('r', 'rev', [], 'a changeset you would like to have after cloning'), - ('', 'pull', None, 'use pull protocol to copy metadata'), - ('', 'remotecmd', "", 'remote hg command')], - 'hg clone [OPTION]... SOURCE [DEST]'), + [('U', 'noupdate', None, _('do not update the new working directory')), + ('e', 'ssh', "", _('specify ssh command to use')), + ('', 'pull', None, _('use pull protocol to copy metadata')), + ('r', 'rev', [], _('a changeset you would like to have after cloning')), + ('', 'remotecmd', "", _('specify hg command to run on the remote side'))], + _('hg clone [OPTION]... SOURCE [DEST]')), "^commit|ci": (commit, - [('A', 'addremove', None, 'run add/remove during commit'), - ('I', 'include', [], 'include path in search'), - ('X', 'exclude', [], 'exclude path from search'), - ('m', 'message', "", 'commit message'), - ('t', 'text', "", 'commit message (deprecated: use -m)'), - ('l', 'logfile', "", 'commit message file'), - ('d', 'date', "", 'date code'), - ('u', 'user', "", 'user')], - 'hg commit [OPTION]... [FILE]...'), + [('A', 'addremove', None, _('run addremove during commit')), + ('I', 'include', [], _('include names matching the given patterns')), + ('X', 'exclude', [], _('exclude names matching the given patterns')), + ('m', 'message', "", _('use <text> as commit message')), + ('l', 'logfile', "", _('read the commit message from <file>')), + ('d', 'date', "", _('record datecode as commit date')), + ('u', 'user', "", _('record user as commiter'))], + _('hg commit [OPTION]... [FILE]...')), "copy|cp": (copy, - [('I', 'include', [], 'include path in search'), - ('X', 'exclude', [], 'exclude path from search'), - ('A', 'after', None, 'record a copy after it has happened'), - ('f', 'force', None, 'replace destination if it exists'), - ('p', 'parents', None, 'append source path to dest')], - 'hg copy [OPTION]... [SOURCE]... DEST'), - "debugancestor": (debugancestor, [], 'debugancestor INDEX REV1 REV2'), - "debugcheckstate": (debugcheckstate, [], 'debugcheckstate'), - "debugconfig": (debugconfig, [], 'debugconfig'), - "debugstate": (debugstate, [], 'debugstate'), - "debugdata": (debugdata, [], 'debugdata FILE REV'), - "debugindex": (debugindex, [], 'debugindex FILE'), - "debugindexdot": (debugindexdot, [], 'debugindexdot FILE'), - "debugrename": (debugrename, [], 'debugrename FILE [REV]'), + [('I', 'include', [], _('include names matching the given patterns')), + ('X', 'exclude', [], _('exclude names matching the given patterns')), + ('A', 'after', None, _('record a copy that has already occurred')), + ('f', 'force', None, _('forcibly copy over an existing managed file'))], + _('hg copy [OPTION]... [SOURCE]... DEST')), + "debugancestor": (debugancestor, [], _('debugancestor INDEX REV1 REV2')), + "debugcheckstate": (debugcheckstate, [], _('debugcheckstate')), + "debugconfig": (debugconfig, [], _('debugconfig')), + "debugsetparents": (debugsetparents, [], _('debugsetparents REV1 [REV2]')), + "debugstate": (debugstate, [], _('debugstate')), + "debugdata": (debugdata, [], _('debugdata FILE REV')), + "debugindex": (debugindex, [], _('debugindex FILE')), + "debugindexdot": (debugindexdot, [], _('debugindexdot FILE')), + "debugrename": (debugrename, [], _('debugrename FILE [REV]')), "debugwalk": (debugwalk, - [('I', 'include', [], 'include path in search'), - ('X', 'exclude', [], 'exclude path from search')], - 'debugwalk [OPTION]... [FILE]...'), + [('I', 'include', [], _('include names matching the given patterns')), + ('X', 'exclude', [], _('exclude names matching the given patterns'))], + _('debugwalk [OPTION]... [FILE]...')), "^diff": (diff, - [('r', 'rev', [], 'revision'), - ('a', 'text', None, 'treat all files as text'), - ('I', 'include', [], 'include path in search'), - ('X', 'exclude', [], 'exclude path from search')], - 'hg diff [-a] [-I] [-X] [-r REV1 [-r REV2]] [FILE]...'), + [('r', 'rev', [], _('revision')), + ('a', 'text', None, _('treat all files as text')), + ('I', 'include', [], _('include names matching the given patterns')), + ('X', 'exclude', [], _('exclude names matching the given patterns'))], + _('hg diff [-a] [-I] [-X] [-r REV1 [-r REV2]] [FILE]...')), "^export": (export, - [('o', 'output', "", 'output to file'), - ('a', 'text', None, 'treat all files as text')], + [('o', 'output', "", _('print output to file with formatted name')), + ('a', 'text', None, _('treat all files as text'))], "hg export [-a] [-o OUTFILE] REV..."), "forget": (forget, - [('I', 'include', [], 'include path in search'), - ('X', 'exclude', [], 'exclude path from search')], + [('I', 'include', [], _('include names matching the given patterns')), + ('X', 'exclude', [], _('exclude names matching the given patterns'))], "hg forget [OPTION]... FILE..."), "grep": (grep, - [('0', 'print0', None, 'end fields with NUL'), - ('I', 'include', [], 'include path in search'), - ('X', 'exclude', [], 'include path in search'), - ('', 'all', None, 'print all revisions with matches'), - ('i', 'ignore-case', None, 'ignore case when matching'), - ('l', 'files-with-matches', None, 'print names of files and revs with matches'), - ('n', 'line-number', None, 'print line numbers'), - ('r', 'rev', [], 'search in revision rev'), - ('u', 'user', None, 'print user who made change')], + [('0', 'print0', None, _('end fields with NUL')), + ('I', 'include', [], _('include names matching the given patterns')), + ('X', 'exclude', [], _('include names matching the given patterns')), + ('', 'all', None, _('print all revisions that match')), + ('i', 'ignore-case', None, _('ignore case when matching')), + ('l', 'files-with-matches', None, _('print only filenames and revs that match')), + ('n', 'line-number', None, _('print matching line numbers')), + ('r', 'rev', [], _('search in given revision range')), + ('u', 'user', None, _('print user who committed change'))], "hg grep [OPTION]... PATTERN [FILE]..."), "heads": (heads, - [('b', 'branches', None, 'find branch info')], - 'hg heads [-b]'), - "help": (help_, [], 'hg help [COMMAND]'), - "identify|id": (identify, [], 'hg identify'), + [('b', 'branches', None, _('find branch info'))], + _('hg heads [-b]')), + "help": (help_, [], _('hg help [COMMAND]')), + "identify|id": (identify, [], _('hg identify')), "import|patch": (import_, - [('p', 'strip', 1, 'path strip'), - ('f', 'force', None, 'skip check for outstanding changes'), - ('b', 'base', "", 'base path')], + [('p', 'strip', 1, _('directory strip option for patch. This has the same\n') + + _('meaning as the corresponding patch option')), + ('f', 'force', None, _('skip check for outstanding uncommitted changes')), + ('b', 'base', "", _('base path'))], "hg import [-f] [-p NUM] [-b BASE] PATCH..."), "incoming|in": (incoming, - [('p', 'patch', None, 'show patch')], - 'hg incoming [-p] [SOURCE]'), - "^init": (init, [], 'hg init [DEST]'), + [('M', 'no-merges', None, _("do not show merges")), + ('p', 'patch', None, _('show patch')), + ('n', 'newest-first', None, _('show newest record first'))], + _('hg incoming [-p] [-n] [-M] [SOURCE]')), + "^init": (init, [], _('hg init [DEST]')), "locate": (locate, - [('r', 'rev', '', 'revision'), - ('0', 'print0', None, 'end filenames with NUL'), - ('f', 'fullpath', None, 'print complete paths'), - ('I', 'include', [], 'include path in search'), - ('X', 'exclude', [], 'exclude path from search')], - 'hg locate [OPTION]... [PATTERN]...'), + [('r', 'rev', '', _('search the repository as it stood at rev')), + ('0', 'print0', None, _('end filenames with NUL, for use with xargs')), + ('f', 'fullpath', None, _('print complete paths from the filesystem root')), + ('I', 'include', [], _('include names matching the given patterns')), + ('X', 'exclude', [], _('exclude names matching the given patterns'))], + _('hg locate [OPTION]... [PATTERN]...')), "^log|history": (log, - [('I', 'include', [], 'include path in search'), - ('X', 'exclude', [], 'exclude path from search'), - ('b', 'branch', None, 'show branches'), - ('k', 'keyword', [], 'search for a keyword'), - ('r', 'rev', [], 'revision'), - ('p', 'patch', None, 'show patch')], - 'hg log [-I] [-X] [-r REV]... [-p] [FILE]'), - "manifest": (manifest, [], 'hg manifest [REV]'), + [('I', 'include', [], _('include names matching the given patterns')), + ('X', 'exclude', [], _('exclude names matching the given patterns')), + ('b', 'branch', None, _('show branches')), + ('k', 'keyword', [], _('search for a keyword')), + ('r', 'rev', [], _('show the specified revision or range')), + ('M', 'no-merges', None, _("do not show merges")), + ('m', 'only-merges', None, _("show only merges")), + ('p', 'patch', None, _('show patch'))], + _('hg log [-I] [-X] [-r REV]... [-p] [FILE]')), + "manifest": (manifest, [], _('hg manifest [REV]')), "outgoing|out": (outgoing, - [('p', 'patch', None, 'show patch')], - 'hg outgoing [-p] [DEST]'), - "parents": (parents, [], 'hg parents [REV]'), - "paths": (paths, [], 'hg paths [NAME]'), + [('M', 'no-merges', None, _("do not show merges")), + ('p', 'patch', None, _('show patch')), + ('n', 'newest-first', None, _('show newest record first'))], + _('hg outgoing [-p] [-n] [-M] [DEST]')), + "parents": (parents, [], _('hg parents [REV]')), + "paths": (paths, [], _('hg paths [NAME]')), "^pull": (pull, - [('u', 'update', None, 'update working directory'), - ('e', 'ssh', "", 'ssh command'), - ('', 'remotecmd', "", 'remote hg command'), - ('r', 'rev', [], 'a specific revision you would like to pull')], - 'hg pull [-u] [-e FILE] [--remotecmd FILE] [-r rev]... [SOURCE]'), + [('u', 'update', None, _('update the working directory to tip after pull')), + ('e', 'ssh', "", _('specify ssh command to use')), + ('r', 'rev', [], _('a specific revision you would like to pull')), + ('', 'remotecmd', "", _('specify hg command to run on the remote side'))], + _('hg pull [-u] [-e FILE] [-r rev] [--remotecmd FILE] [SOURCE]')), "^push": (push, - [('f', 'force', None, 'force push'), - ('e', 'ssh', "", 'ssh command'), - ('', 'remotecmd', "", 'remote hg command')], - 'hg push [-f] [-e FILE] [--remotecmd FILE] [DEST]'), + [('f', 'force', None, _('force push')), + ('e', 'ssh', "", _('specify ssh command to use')), + ('', 'remotecmd', "", _('specify hg command to run on the remote side'))], + _('hg push [-f] [-e FILE] [--remotecmd FILE] [DEST]')), "rawcommit": (rawcommit, - [('p', 'parent', [], 'parent'), - ('d', 'date', "", 'date code'), - ('u', 'user', "", 'user'), - ('F', 'files', "", 'file list'), - ('m', 'message', "", 'commit message'), - ('t', 'text', "", 'commit message (deprecated: use -m)'), - ('l', 'logfile', "", 'commit message file')], - 'hg rawcommit [OPTION]... [FILE]...'), - "recover": (recover, [], "hg recover"), + [('p', 'parent', [], _('parent')), + ('d', 'date', "", _('date code')), + ('u', 'user', "", _('user')), + ('F', 'files', "", _('file list')), + ('m', 'message', "", _('commit message')), + ('t', 'text', "", _('commit message (deprecated: use -m)')), + ('l', 'logfile', "", _('commit message file'))], + _('hg rawcommit [OPTION]... [FILE]...')), + "recover": (recover, [], _("hg recover")), "^remove|rm": (remove, - [('I', 'include', [], 'include path in search'), - ('X', 'exclude', [], 'exclude path from search')], - "hg remove [OPTION]... FILE..."), + [('I', 'include', [], _('include names matching the given patterns')), + ('X', 'exclude', [], _('exclude names matching the given patterns'))], + _("hg remove [OPTION]... FILE...")), "rename|mv": (rename, - [('I', 'include', [], 'include path in search'), - ('X', 'exclude', [], 'exclude path from search'), - ('A', 'after', None, 'record a copy after it has happened'), - ('f', 'force', None, 'replace destination if it exists'), - ('p', 'parents', None, 'append source path to dest')], - 'hg rename [OPTION]... [SOURCE]... DEST'), + [('I', 'include', [], _('include names matching the given patterns')), + ('X', 'exclude', [], _('exclude names matching the given patterns')), + ('A', 'after', None, _('record a rename that has already occurred')), + ('f', 'force', None, _('forcibly copy over an existing managed file'))], + _('hg rename [OPTION]... [SOURCE]... DEST')), "^revert": (revert, - [("n", "nonrecursive", None, "don't recurse into subdirs"), - ("r", "rev", "", "revision")], - "hg revert [-n] [-r REV] [NAME]..."), - "root": (root, [], "hg root"), + [("n", "nonrecursive", None, _("do not recurse into subdirectories")), + ("r", "rev", "", _("revision to revert to"))], + _("hg revert [-n] [-r REV] [NAME]...")), + "root": (root, [], _("hg root")), "^serve": (serve, - [('A', 'accesslog', '', 'access log file'), - ('E', 'errorlog', '', 'error log file'), - ('p', 'port', 0, 'listen port'), - ('a', 'address', '', 'interface address'), - ('n', 'name', "", 'repository name'), - ('', 'stdio', None, 'for remote clients'), - ('t', 'templates', "", 'template directory'), - ('', 'style', "", 'template style'), - ('6', 'ipv6', None, 'use IPv6 in addition to IPv4')], - "hg serve [OPTION]..."), + [('A', 'accesslog', '', _('name of access log file to write to')), + ('E', 'errorlog', '', _('name of error log file to write to')), + ('p', 'port', 0, _('port to use (default: 8000)')), + ('a', 'address', '', _('address to use')), + ('n', 'name', "", _('name to show in web pages (default: working dir)')), + ('', 'stdio', None, _('for remote clients')), + ('t', 'templates', "", _('web templates to use')), + ('', 'style', "", _('template style to use')), + ('6', 'ipv6', None, _('use IPv6 in addition to IPv4'))], + _("hg serve [OPTION]...")), "^status": (status, - [('m', 'modified', None, 'show only modified files'), - ('a', 'added', None, 'show only added files'), - ('r', 'removed', None, 'show only removed files'), - ('u', 'unknown', None, 'show only unknown (not tracked) files'), - ('n', 'no-status', None, 'hide status prefix'), - ('0', 'print0', None, 'end filenames with NUL'), - ('I', 'include', [], 'include path in search'), - ('X', 'exclude', [], 'exclude path from search')], - "hg status [OPTION]... [FILE]..."), + [('m', 'modified', None, _('show only modified files')), + ('a', 'added', None, _('show only added files')), + ('r', 'removed', None, _('show only removed files')), + ('u', 'unknown', None, _('show only unknown (not tracked) files')), + ('n', 'no-status', None, _('hide status prefix')), + ('0', 'print0', None, _('end filenames with NUL, for use with xargs')), + ('I', 'include', [], _('include names matching the given patterns')), + ('X', 'exclude', [], _('exclude names matching the given patterns'))], + _("hg status [OPTION]... [FILE]...")), "tag": (tag, - [('l', 'local', None, 'make the tag local'), - ('m', 'message', "", 'commit message'), - ('t', 'text', "", 'commit message (deprecated: use -m)'), - ('d', 'date', "", 'date code'), - ('u', 'user', "", 'user')], - 'hg tag [OPTION]... NAME [REV]'), - "tags": (tags, [], 'hg tags'), - "tip": (tip, [], 'hg tip'), + [('l', 'local', None, _('make the tag local')), + ('m', 'message', "", _('message for tag commit log entry')), + ('t', 'text', "", _('commit message (deprecated: use -m)')), + ('d', 'date', "", _('record datecode as commit date')), + ('u', 'user', "", _('record user as commiter'))], + _('hg tag [OPTION]... NAME [REV]')), + "tags": (tags, [], _('hg tags')), + "tip": (tip, [], _('hg tip')), "unbundle": (unbundle, [], - 'hg unbundle FILE'), - "undo": (undo, [], 'hg undo'), + _('hg unbundle FILE')), + "undo": (undo, [], _('hg undo')), "^update|up|checkout|co": (update, - [('b', 'branch', "", 'checkout the head of a specific branch'), - ('m', 'merge', None, 'allow merging of conflicts'), - ('C', 'clean', None, 'overwrite locally modified files')], - 'hg update [-b TAG] [-m] [-C] [REV]'), - "verify": (verify, [], 'hg verify'), - "version": (show_version, [], 'hg version'), + [('b', 'branch', "", _('checkout the head of a specific branch')), + ('m', 'merge', None, _('allow merging of branches')), + ('C', 'clean', None, _('overwrite locally modified files'))], + _('hg update [-b TAG] [-m] [-C] [REV]')), + "verify": (verify, [], _('hg verify')), + "version": (show_version, [], _('hg version')), } globalopts = [ - ('R', 'repository', "", 'repository root directory'), - ('', 'cwd', '', 'change working directory'), - ('y', 'noninteractive', None, 'run non-interactively'), - ('q', 'quiet', None, 'quiet mode'), - ('v', 'verbose', None, 'verbose mode'), - ('', 'debug', None, 'debug mode'), - ('', 'debugger', None, 'start debugger'), - ('', 'traceback', None, 'print traceback on exception'), - ('', 'time', None, 'time how long the command takes'), - ('', 'profile', None, 'profile'), - ('', 'version', None, 'output version information and exit'), - ('h', 'help', None, 'display help and exit'), + ('R', 'repository', "", _("repository root directory")), + ('', 'cwd', '', _("change working directory")), + ('y', 'noninteractive', None, _("do not prompt, assume 'yes' for any required answers")), + ('q', 'quiet', None, _("suppress output")), + ('v', 'verbose', None, _("enable additional output")), + ('', 'debug', None, _("enable debugging output")), + ('', 'debugger', None, _("start debugger")), + ('', 'traceback', None, _("print traceback on exception")), + ('', 'time', None, _("time how long the command takes")), + ('', 'profile', None, _("print command execution profile")), + ('', 'version', None, _("output version information and exit")), + ('h', 'help', None, _("display help and exit")), ] norepo = ("clone init version help debugancestor debugconfig debugdata" @@ -2022,7 +2437,7 @@ class ParseError(Exception): """Exception raised on errors in parsing the command line.""" -def parse(args): +def parse(ui, args): options = {} cmdoptions = {} @@ -2033,6 +2448,17 @@ if args: cmd, args = args[0], args[1:] + defaults = ui.config("defaults", cmd) + if defaults: + # reparse with command defaults added + args = [cmd] + defaults.split() + args + try: + args = fancyopts.fancyopts(args, globalopts, options) + except fancyopts.getopt.GetoptError, inst: + raise ParseError(None, inst) + + cmd, args = args[0], args[1:] + i = find(cmd)[1] c = list(i[1]) else: @@ -2066,11 +2492,16 @@ u = ui.ui() external = [] for x in u.extensions(): + def on_exception(Exception, inst): + u.warn(_("*** failed to import extension %s\n") % x[1]) + u.warn("%s\n" % inst) + if "--traceback" in sys.argv[1:]: + traceback.print_exc() if x[1]: try: mod = imp.load_source(x[0], x[1]) - except: - u.warn("*** failed to import extension %s\n" % x[1]) + except Exception, inst: + on_exception(Exception, inst) continue else: def importh(name): @@ -2081,8 +2512,8 @@ return mod try: mod = importh(x[0]) - except: - u.warn("failed to import extension %s\n" % x[0]) + except Exception, inst: + on_exception(Exception, inst) continue external.append(mod) @@ -2090,21 +2521,21 @@ cmdtable = getattr(x, 'cmdtable', {}) for t in cmdtable: if t in table: - u.warn("module %s overrides %s\n" % (x.__name__, t)) + u.warn(_("module %s overrides %s\n") % (x.__name__, t)) table.update(cmdtable) try: - cmd, func, args, options, cmdoptions = parse(args) + cmd, func, args, options, cmdoptions = parse(u, args) except ParseError, inst: if inst.args[0]: - u.warn("hg %s: %s\n" % (inst.args[0], inst.args[1])) + u.warn(_("hg %s: %s\n") % (inst.args[0], inst.args[1])) help_(u, inst.args[0]) else: - u.warn("hg: %s\n" % inst.args[1]) + u.warn(_("hg: %s\n") % inst.args[1]) help_(u, 'shortlist') sys.exit(-1) except UnknownCommand, inst: - u.warn("hg: unknown command '%s'\n" % inst.args[0]) + u.warn(_("hg: unknown command '%s'\n") % inst.args[0]) help_(u, 'shortlist') sys.exit(1) @@ -2117,7 +2548,7 @@ s = get_times() def print_time(): t = get_times() - u.warn("Time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n" % + u.warn(_("Time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n") % (t[4]-s[4], t[0]-s[0], t[2]-s[2], t[1]-s[1], t[3]-s[3])) atexit.register(print_time) @@ -2176,42 +2607,42 @@ traceback.print_exc() raise except hg.RepoError, inst: - u.warn("abort: ", inst, "!\n") + u.warn(_("abort: "), inst, "!\n") except revlog.RevlogError, inst: - u.warn("abort: ", inst, "!\n") + u.warn(_("abort: "), inst, "!\n") except SignalInterrupt: - u.warn("killed!\n") + u.warn(_("killed!\n")) except KeyboardInterrupt: try: - u.warn("interrupted!\n") + u.warn(_("interrupted!\n")) except IOError, inst: if inst.errno == errno.EPIPE: if u.debugflag: - u.warn("\nbroken pipe\n") + u.warn(_("\nbroken pipe\n")) else: raise except IOError, inst: if hasattr(inst, "code"): - u.warn("abort: %s\n" % inst) + u.warn(_("abort: %s\n") % inst) elif hasattr(inst, "reason"): - u.warn("abort: error: %s\n" % inst.reason[1]) + u.warn(_("abort: error: %s\n") % inst.reason[1]) elif hasattr(inst, "args") and inst[0] == errno.EPIPE: if u.debugflag: - u.warn("broken pipe\n") + u.warn(_("broken pipe\n")) elif getattr(inst, "strerror", None): if getattr(inst, "filename", None): - u.warn("abort: %s - %s\n" % (inst.strerror, inst.filename)) + u.warn(_("abort: %s - %s\n") % (inst.strerror, inst.filename)) else: - u.warn("abort: %s\n" % inst.strerror) + u.warn(_("abort: %s\n") % inst.strerror) else: raise except OSError, inst: if hasattr(inst, "filename"): - u.warn("abort: %s: %s\n" % (inst.strerror, inst.filename)) + u.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename)) else: - u.warn("abort: %s\n" % inst.strerror) + u.warn(_("abort: %s\n") % inst.strerror) except util.Abort, inst: - u.warn('abort: ', inst.args[0] % inst.args[1:], '\n') + u.warn(_('abort: '), inst.args[0] % inst.args[1:], '\n') sys.exit(1) except TypeError, inst: # was this an argument error? @@ -2219,17 +2650,17 @@ if len(tb) > 2: # no raise u.debug(inst, "\n") - u.warn("%s: invalid arguments\n" % cmd) + u.warn(_("%s: invalid arguments\n") % cmd) help_(u, cmd) except UnknownCommand, inst: - u.warn("hg: unknown command '%s'\n" % inst.args[0]) + u.warn(_("hg: unknown command '%s'\n") % inst.args[0]) help_(u, 'shortlist') except SystemExit: # don't catch this in the catch-all below raise except: - u.warn("** unknown exception encountered, details follow\n") - u.warn("** report bug details to mercurial@selenic.com\n") + u.warn(_("** unknown exception encountered, details follow\n")) + u.warn(_("** report bug details to mercurial@selenic.com\n")) raise sys.exit(-1)
--- a/mercurial/dirstate.py Sun Oct 16 16:24:40 2005 -0700 +++ b/mercurial/dirstate.py Thu Oct 27 12:26:16 2005 -0700 @@ -9,6 +9,7 @@ import struct, os from node import * +from i18n import gettext as _ from demandload import * demandload(globals(), "time bisect stat util re") @@ -67,7 +68,7 @@ try: syntax = syntaxes[s] except KeyError: - self.ui.warn("ignoring invalid syntax '%s'\n" % s) + self.ui.warn(_("ignoring invalid syntax '%s'\n") % s) continue pat = syntax + line for s in syntaxes.values(): @@ -117,6 +118,8 @@ self.dirty = 1 def setparents(self, p1, p2=nullid): + if not self.pl: + self.read() self.markdirty() self.pl = p1, p2 @@ -187,7 +190,7 @@ try: del self.map[f] except KeyError: - self.ui.warn("not in dirstate: %s!\n" % f) + self.ui.warn(_("not in dirstate: %s!\n") % f) pass def clear(self): @@ -268,6 +271,22 @@ # directly by this function, but might be modified by your statmatch call. # def walkhelper(self, files, statmatch, dc): + def supported_type(f, st): + if stat.S_ISREG(st.st_mode): + return True + else: + kind = 'unknown' + if stat.S_ISCHR(st.st_mode): kind = _('character device') + elif stat.S_ISBLK(st.st_mode): kind = _('block device') + elif stat.S_ISFIFO(st.st_mode): kind = _('fifo') + elif stat.S_ISLNK(st.st_mode): kind = _('symbolic link') + 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), + kind)) + return False + # recursion free walker, faster than os.walk. def findfiles(s): retfiles = [] @@ -290,9 +309,9 @@ ds = os.path.join(nd, f +'/') if statmatch(ds, st): work.append(p) - else: - if statmatch(np, st): - yield util.pconvert(np) + elif statmatch(np, st) and supported_type(np, st): + yield util.pconvert(np) + known = {'.hg': 1} def seen(fn): @@ -315,27 +334,17 @@ sorted.sort() for fl in sorted: yield 'f', fl - elif stat.S_ISREG(st.st_mode): + else: ff = util.normpath(ff) if seen(ff): continue found = False self.blockignore = True - if statmatch(ff, st): + if statmatch(ff, st) and supported_type(ff, st): found = True self.blockignore = False if found: yield 'f', ff - else: - kind = 'unknown' - if stat.S_ISCHR(st.st_mode): kind = 'character device' - elif stat.S_ISBLK(st.st_mode): kind = 'block device' - elif stat.S_ISFIFO(st.st_mode): kind = 'fifo' - elif stat.S_ISLNK(st.st_mode): kind = 'symbolic link' - elif stat.S_ISSOCK(st.st_mode): kind = 'socket' - self.ui.warn('%s: unsupported file type (type is %s)\n' % ( - util.pathto(self.getcwd(), ff), - kind)) # step two run through anything left in the dc hash and yield # if we haven't already seen it @@ -368,8 +377,6 @@ if self.ignore(fn): return False return match(fn) - if not stat.S_ISREG(s.st_mode): - return False c = dc.pop(fn, None) if c: type, mode, size, time = c
--- a/mercurial/hgweb.py Sun Oct 16 16:24:40 2005 -0700 +++ b/mercurial/hgweb.py Thu Oct 27 12:26:16 2005 -0700 @@ -10,7 +10,9 @@ from demandload import demandload demandload(globals(), "mdiff time re socket zlib errno ui hg ConfigParser") demandload(globals(), "zipfile tempfile StringIO tarfile BaseHTTPServer util") +demandload(globals(), "mimetypes") from node import * +from i18n import gettext as _ def templatepath(): for f in "templates", "../templates": @@ -61,12 +63,20 @@ return "/" return up + "/" +def get_mtime(repo_path): + hg_path = os.path.join(repo_path, ".hg") + cl_path = os.path.join(hg_path, "00changelog.i") + if os.path.exists(os.path.join(cl_path)): + return os.stat(cl_path).st_mtime + else: + return os.stat(hg_path).st_mtime + class hgrequest: def __init__(self, inp=None, out=None, env=None): self.inp = inp or sys.stdin self.out = out or sys.stdout self.env = env or os.environ - self.form = cgi.parse(self.inp, self.env) + self.form = cgi.parse(self.inp, self.env, keep_blank_values=1) def write(self, *things): for thing in things: @@ -111,7 +121,7 @@ if m: self.map[m.group(1)] = os.path.join(self.base, m.group(2)) else: - raise LookupError("unknown map entry '%s'" % l) + raise LookupError(_("unknown map entry '%s'") % l) def __call__(self, t, **map): m = self.defaults.copy() @@ -154,6 +164,8 @@ common_filters = { "escape": cgi.escape, + "strip": lambda x: x.strip(), + "rstrip": lambda x: x.rstrip(), "age": age, "date": lambda x: util.datestr(x), "addbreaks": nl2br, @@ -176,9 +188,9 @@ self.archives = 'zip', 'gz', 'bz2' def refresh(self): - s = os.stat(os.path.join(self.repo.root, ".hg", "00changelog.i")) - if s.st_mtime != self.mtime: - self.mtime = s.st_mtime + mtime = get_mtime(self.repo.root) + if mtime != self.mtime: + self.mtime = mtime self.repo = hg.repository(self.repo.ui, self.repo.root) self.maxchanges = int(self.repo.ui.config("web", "maxchanges", 10)) self.maxfiles = int(self.repo.ui.config("web", "maxfiles", 10)) @@ -196,12 +208,14 @@ if len(files) > self.maxfiles: yield self.t("fileellipses") - def parents(self, t1, nodes=[], rev=None,**args): + def parents(self, node, parents=[], rev=None, hide=False, **args): if not rev: rev = lambda x: "" - for node in nodes: - if node != nullid: - yield self.t(t1, node=hex(node), rev=rev(node), **args) + parents = [p for p in parents if p != nullid] + if hide and len(parents) == 1 and rev(parents[0]) == rev(node) - 1: + return + for p in parents: + yield dict(node=hex(p), rev=rev(p), **args) def showtag(self, t1, node=nullid, **args): for t in self.repo.nodetags(node): @@ -290,7 +304,7 @@ for label, rev in l: yield {"label": label, "rev": rev} - yield {"label": "tip", "rev": ""} + yield {"label": "tip", "rev": "tip"} def changelist(**map): parity = (start - end) & 1 @@ -303,8 +317,8 @@ l.insert(0, {"parity": parity, "author": changes[1], - "parent": self.parents("changelogparent", - cl.parents(n), cl.rev), + "parent": self.parents(n, cl.parents(n), cl.rev, + hide=True), "changelogtag": self.showtag("changelogtag",n), "manifest": hex(changes[0]), "desc": changes[4], @@ -364,8 +378,7 @@ yield self.t('searchentry', parity=count & 1, author=changes[1], - parent=self.parents("changelogparent", - cl.parents(n), cl.rev), + parent=self.parents(n, cl.parents(n), cl.rev), changelogtag=self.showtag("changelogtag",n), manifest=hex(changes[0]), desc=changes[4], @@ -410,8 +423,7 @@ diff=diff, rev=cl.rev(n), node=nodeid, - parent=self.parents("changesetparent", - cl.parents(n), cl.rev), + parent=self.parents(n, cl.parents(n), cl.rev), changesettag=self.showtag("changesettag",n), manifest=hex(changes[0]), author=changes[1], @@ -443,8 +455,7 @@ "node": hex(cn), "author": cs[1], "date": cs[2], - "parent": self.parents("filelogparent", - fl.parents(n), + "parent": self.parents(n, fl.parents(n), fl.rev, file=f), "desc": cs[4]}) parity = 1 - parity @@ -465,6 +476,11 @@ cs = cl.read(cn) mfn = cs[0] + mt = mimetypes.guess_type(f)[0] + rawtext = text + if util.binary(text): + text = "(binary:%s)" % mt + def lines(): for l, t in enumerate(text.splitlines(1)): yield {"line": t, @@ -476,13 +492,14 @@ filenode=node, path=up(f), text=lines(), + raw=rawtext, + mimetype=mt, rev=changerev, node=hex(cn), manifest=hex(mfn), author=cs[1], date=cs[2], - parent=self.parents("filerevparent", - fl.parents(n), fl.rev, file=f), + parent=self.parents(n, fl.parents(n), fl.rev, file=f), permissions=self.repo.manifest.readflags(mfn)[f]) def fileannotate(self, f, node): @@ -534,8 +551,7 @@ manifest=hex(mfn), author=cs[1], date=cs[2], - parent=self.parents("fileannotateparent", - fl.parents(n), fl.rev, file=f), + parent=self.parents(n, fl.parents(n), fl.rev, file=f), permissions=self.repo.manifest.readflags(mfn)[f]) def manifest(self, mnode, path): @@ -639,8 +655,7 @@ filenode=hex(mf.get(file, nullid)), node=changeset, rev=self.repo.changelog.rev(n), - parent=self.parents("filediffparent", - cl.parents(n), cl.rev), + parent=self.parents(n, cl.parents(n), cl.rev), diff=diff) def archive(self, req, cnode, type): @@ -704,8 +719,32 @@ def footer(**map): yield self.t("footer", **map) + def expand_form(form): + shortcuts = { + 'cl': [('cmd', ['changelog']), ('rev', None)], + 'cs': [('cmd', ['changeset']), ('node', None)], + 'f': [('cmd', ['file']), ('filenode', None)], + 'fl': [('cmd', ['filelog']), ('filenode', None)], + 'fd': [('cmd', ['filediff']), ('node', None)], + 'fa': [('cmd', ['annotate']), ('filenode', None)], + 'mf': [('cmd', ['manifest']), ('manifest', None)], + 'ca': [('cmd', ['archive']), ('node', None)], + 'tags': [('cmd', ['tags'])], + 'tip': [('cmd', ['changeset']), ('node', ['tip'])], + } + + for k in shortcuts.iterkeys(): + if form.has_key(k): + for name, value in shortcuts[k]: + if value is None: + value = form[k] + form[name] = value + del form[k] + self.refresh() + expand_form(req.form) + t = self.repo.ui.config("web", "templates", templatepath()) m = os.path.join(t, "map") style = self.repo.ui.config("web", "style", "") @@ -843,7 +882,7 @@ def __init__(self, *args, **kwargs): if self.address_family is None: - raise hg.RepoError('IPv6 not available on this system') + raise hg.RepoError(_('IPv6 not available on this system')) BaseHTTPServer.HTTPServer.__init__(self, *args, **kwargs) class hgwebhandler(BaseHTTPServer.BaseHTTPRequestHandler): @@ -960,9 +999,7 @@ .replace("//", "/")) # update time with local timezone - d = (os.stat(os.path.join(path, - ".hg", "00changelog.d")).st_mtime, - util.makedate()[1]) + d = (get_mtime(path), util.makedate()[1]) yield dict(contact=(get("ui", "username") or # preferred get("web", "contact") or # deprecated
--- a/mercurial/httprepo.py Sun Oct 16 16:24:40 2005 -0700 +++ b/mercurial/httprepo.py Thu Oct 27 12:26:16 2005 -0700 @@ -7,6 +7,7 @@ from node import * from remoterepo import * +from i18n import gettext as _ from demandload import * demandload(globals(), "hg os urllib urllib2 urlparse zlib util") @@ -67,7 +68,7 @@ return -1 def do_cmd(self, cmd, **args): - self.ui.debug("sending %s command\n" % cmd) + self.ui.debug(_("sending %s command\n") % cmd) q = {"cmd": cmd} q.update(args) qs = urllib.urlencode(q) @@ -79,13 +80,13 @@ if not proto.startswith('application/mercurial') and \ not proto.startswith('text/plain') and \ not proto.startswith('application/hg-changegroup'): - raise hg.RepoError("'%s' does not appear to be an hg repository" % + raise hg.RepoError(_("'%s' does not appear to be an hg repository") % self.url) if proto.startswith('application/mercurial'): version = proto[22:] if float(version) > 0.1: - raise hg.RepoError("'%s' uses newer protocol %s" % + raise hg.RepoError(_("'%s' uses newer protocol %s") % (self.url, version)) return resp @@ -95,7 +96,7 @@ try: return map(bin, d[:-1].split(" ")) except: - self.ui.warn("unexpected response:\n" + d[:400] + "\n...\n") + self.ui.warn(_("unexpected response:\n") + d[:400] + "\n...\n") raise def branches(self, nodes): @@ -105,7 +106,7 @@ br = [ tuple(map(bin, b.split(" "))) for b in d.splitlines() ] return br except: - self.ui.warn("unexpected response:\n" + d[:400] + "\n...\n") + self.ui.warn(_("unexpected response:\n") + d[:400] + "\n...\n") raise def between(self, pairs): @@ -115,7 +116,7 @@ p = [ l and map(bin, l.split(" ")) or [] for l in d.splitlines() ] return p except: - self.ui.warn("unexpected response:\n" + d[:400] + "\n...\n") + self.ui.warn(_("unexpected response:\n") + d[:400] + "\n...\n") raise def changegroup(self, nodes):
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial/i18n.py Thu Oct 27 12:26:16 2005 -0700 @@ -0,0 +1,15 @@ +""" +i18n.py - internationalization support for mercurial + +Copyright 2005 Matt Mackall <mpm@selenic.com> + +This software may be used and distributed according to the terms +of the GNU General Public License, incorporated herein by reference. +""" + +# the import from gettext is _really_ slow +# for now we use a dummy function +gettext = lambda x: x +#import gettext +#t = gettext.translation('hg', '/usr/share/locale', fallback=1) +#gettext = t.gettext
--- a/mercurial/localrepo.py Sun Oct 16 16:24:40 2005 -0700 +++ b/mercurial/localrepo.py Thu Oct 27 12:26:16 2005 -0700 @@ -8,6 +8,7 @@ import struct, os, util import filelog, manifest, changelog, dirstate, repo from node import * +from i18n import gettext as _ from demandload import * demandload(globals(), "re lock transaction tempfile stat mdiff errno") @@ -18,12 +19,12 @@ while not os.path.isdir(os.path.join(p, ".hg")): oldp = p p = os.path.dirname(p) - if p == oldp: raise repo.RepoError("no repo found") + if p == oldp: raise repo.RepoError(_("no repo found")) path = p self.path = os.path.join(path, ".hg") if not create and not os.path.isdir(self.path): - raise repo.RepoError("repository %s not found" % self.path) + raise repo.RepoError(_("repository %s not found") % self.path) self.root = os.path.abspath(path) self.ui = ui @@ -48,7 +49,7 @@ def hook(self, name, **args): s = self.ui.config("hooks", name) if s: - self.ui.note("running hook %s: %s\n" % (name, s)) + self.ui.note(_("running hook %s: %s\n") % (name, s)) old = {} for k, v in args.items(): k = k.upper() @@ -68,7 +69,7 @@ del os.environ[k] if r: - self.ui.warn("abort: %s hook failed with status %d!\n" % + self.ui.warn(_("abort: %s hook failed with status %d!\n") % (name, r)) return False return True @@ -138,7 +139,7 @@ try: return self.changelog.lookup(key) except: - raise repo.RepoError("unknown revision '%s'" % key) + raise repo.RepoError(_("unknown revision '%s'") % key) def dev(self): return os.stat(self.path).st_dev @@ -174,7 +175,7 @@ for mf, cmd in self.encodepats: if mf(filename): - self.ui.debug("filtering %s through %s\n" % (filename, cmd)) + self.ui.debug(_("filtering %s through %s\n") % (filename, cmd)) data = util.filter(data, cmd) break @@ -190,7 +191,7 @@ for mf, cmd in self.decodepats: if mf(filename): - self.ui.debug("filtering %s through %s\n" % (filename, cmd)) + self.ui.debug(_("filtering %s through %s\n") % (filename, cmd)) data = util.filter(data, cmd) break @@ -217,28 +218,28 @@ def recover(self): lock = self.lock() if os.path.exists(self.join("journal")): - self.ui.status("rolling back interrupted transaction\n") + self.ui.status(_("rolling back interrupted transaction\n")) return transaction.rollback(self.opener, self.join("journal")) else: - self.ui.warn("no interrupted transaction available\n") + self.ui.warn(_("no interrupted transaction available\n")) def undo(self): lock = self.lock() if os.path.exists(self.join("undo")): - self.ui.status("rolling back last transaction\n") + self.ui.status(_("rolling back last transaction\n")) transaction.rollback(self.opener, self.join("undo")) self.dirstate = None util.rename(self.join("undo.dirstate"), self.join("dirstate")) self.dirstate = dirstate.dirstate(self.opener, self.ui, self.root) else: - self.ui.warn("no undo information available\n") + self.ui.warn(_("no undo information available\n")) def lock(self, wait=1): try: return lock.lock(self.join("lock"), 0) except lock.LockHeld, inst: if wait: - self.ui.warn("waiting for lock held by %s\n" % inst.args[0]) + self.ui.warn(_("waiting for lock held by %s\n") % inst.args[0]) return lock.lock(self.join("lock"), wait) raise inst @@ -326,7 +327,7 @@ elif s == 'r': remove.append(f) else: - self.ui.warn("%s not tracked!\n" % f) + self.ui.warn(_("%s not tracked!\n") % f) else: (c, a, d, u) = self.changes(match=match) commit = c + a @@ -340,7 +341,7 @@ m2 = self.manifest.read(c2[0]) if not commit and not remove and not force and p2 == nullid: - self.ui.status("nothing changed\n") + self.ui.status(_("nothing changed\n")) return None if not self.hook("precommit"): @@ -359,7 +360,7 @@ mf1[f] = util.is_exec(self.wjoin(f), mf1.get(f, False)) t = self.wread(f) except IOError: - self.ui.warn("trouble committing %s!\n" % f) + self.ui.warn(_("trouble committing %s!\n") % f) raise r = self.file(f) @@ -369,7 +370,7 @@ if cp: meta["copy"] = cp meta["copyrev"] = hex(m1.get(cp, m2.get(cp, nullid))) - self.ui.debug(" %s: copy %s:%s\n" % (f, cp, meta["copyrev"])) + self.ui.debug(_(" %s: copy %s:%s\n") % (f, cp, meta["copyrev"])) fp1, fp2 = nullid, nullid else: fp1 = m1.get(f, nullid) @@ -520,40 +521,66 @@ for f in list: p = self.wjoin(f) if not os.path.exists(p): - self.ui.warn("%s does not exist!\n" % f) + self.ui.warn(_("%s does not exist!\n") % f) elif not os.path.isfile(p): - self.ui.warn("%s not added: only files supported currently\n" % f) + self.ui.warn(_("%s not added: only files supported currently\n") % f) elif self.dirstate.state(f) in 'an': - self.ui.warn("%s already tracked!\n" % f) + self.ui.warn(_("%s already tracked!\n") % f) else: self.dirstate.update([f], "a") def forget(self, list): for f in list: if self.dirstate.state(f) not in 'ai': - self.ui.warn("%s not added!\n" % f) + self.ui.warn(_("%s not added!\n") % f) else: self.dirstate.forget([f]) - def remove(self, list): + def remove(self, list, unlink=False): + if unlink: + for f in list: + try: + util.unlink(self.wjoin(f)) + except OSError, inst: + if inst.errno != errno.ENOENT: raise for f in list: p = self.wjoin(f) if os.path.exists(p): - self.ui.warn("%s still exists!\n" % f) + self.ui.warn(_("%s still exists!\n") % f) elif self.dirstate.state(f) == 'a': - self.ui.warn("%s never committed!\n" % f) + self.ui.warn(_("%s never committed!\n") % f) self.dirstate.forget([f]) elif f not in self.dirstate: - self.ui.warn("%s not tracked!\n" % f) + self.ui.warn(_("%s not tracked!\n") % f) else: self.dirstate.update([f], "r") + def undelete(self, list): + p = self.dirstate.parents()[0] + mn = self.changelog.read(p)[0] + mf = self.manifest.readflags(mn) + m = self.manifest.read(mn) + for f in list: + if self.dirstate.state(f) not in "r": + self.ui.warn("%s not removed!\n" % f) + else: + t = self.file(f).read(m[f]) + try: + self.wwrite(f, t) + except IOError, e: + if e.errno != errno.ENOENT: + raise + os.makedirs(os.path.dirname(self.wjoin(f))) + self.wwrite(f, t) + util.set_exec(self.wjoin(f), mf[f]) + self.dirstate.update([f], "n") + def copy(self, source, dest): p = self.wjoin(dest) if not os.path.exists(p): - self.ui.warn("%s does not exist!\n" % dest) + self.ui.warn(_("%s does not exist!\n") % dest) elif not os.path.isfile(p): - self.ui.warn("copy failed: %s is not a file\n" % dest) + self.ui.warn(_("copy failed: %s is not a file\n") % dest) else: if self.dirstate.state(dest) == '?': self.dirstate.update([dest], "a") @@ -711,7 +738,7 @@ # assume we're closer to the tip than the root # and start by examining the heads - self.ui.status("searching for changes\n") + self.ui.status(_("searching for changes\n")) if not heads: heads = remote.heads() @@ -741,21 +768,21 @@ if n[0] in seen: continue - self.ui.debug("examining %s:%s\n" % (short(n[0]), short(n[1]))) + 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") + 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" + 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" % + self.ui.debug(_("found new changeset %s\n") % short(n[1])) fetch[n[1]] = 1 # earliest unknown base[n[2]] = 1 # latest known @@ -770,14 +797,14 @@ if r: reqcnt += 1 - self.ui.debug("request %d: %s\n" % + 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" % + self.ui.debug(_("received %s:%s\n") % (short(b[0]), short(b[1]))) if b[0] in m: - self.ui.debug("found base node %s\n" % short(b[0])) + self.ui.debug(_("found base node %s\n") % short(b[0])) base[b[0]] = 1 elif b[0] not in seen: unknown.append(b) @@ -791,15 +818,15 @@ p = n[0] f = 1 for i in l: - self.ui.debug("narrowing %d:%d %s\n" % (f, len(l), short(i))) + 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" % + self.ui.debug(_("found new branch changeset %s\n") % short(p)) fetch[p] = 1 base[i] = 1 else: - self.ui.debug("narrowed branch search to %s:%s\n" + self.ui.debug(_("narrowed branch search to %s:%s\n") % (short(p), short(i))) search.append((p, i)) break @@ -808,15 +835,15 @@ # sanity check our fetch list for f in fetch.keys(): if f in m: - raise repo.RepoError("already have changeset " + short(f[:4])) + raise repo.RepoError(_("already have changeset ") + short(f[:4])) if base.keys() == [nullid]: - self.ui.warn("warning: pulling from an unrelated repository!\n") + self.ui.warn(_("warning: pulling from an unrelated repository!\n")) - self.ui.note("found new changesets starting at " + + self.ui.note(_("found new changesets starting at ") + " ".join([short(f) for f in fetch]) + "\n") - self.ui.debug("%d total queries\n" % reqcnt) + self.ui.debug(_("%d total queries\n") % reqcnt) return fetch.keys() @@ -825,7 +852,7 @@ base = {} self.findincoming(remote, base, heads) - self.ui.debug("common changesets up to " + self.ui.debug(_("common changesets up to ") + " ".join(map(short, base.keys())) + "\n") remain = dict.fromkeys(self.changelog.nodemap) @@ -855,13 +882,13 @@ # if we have an empty repo, fetch everything if self.changelog.tip() == nullid: - self.ui.status("requesting all changes\n") + self.ui.status(_("requesting all changes\n")) fetch = [nullid] else: fetch = self.findincoming(remote) if not fetch: - self.ui.status("no changes found\n") + self.ui.status(_("no changes found\n")) return 1 if heads is None: @@ -877,19 +904,19 @@ heads = remote.heads() inc = self.findincoming(remote, base, heads) if not force and inc: - self.ui.warn("abort: unsynced remote changes!\n") - self.ui.status("(did you forget to sync? use push -f to force)\n") + self.ui.warn(_("abort: unsynced remote changes!\n")) + self.ui.status(_("(did you forget to sync? use push -f to force)\n")) return 1 update = self.findoutgoing(remote, base) if not update: - self.ui.status("no changes found\n") + self.ui.status(_("no changes found\n")) return 1 elif not force: if len(heads) < len(self.changelog.heads()): - self.ui.warn("abort: push creates new remote branches!\n") - self.ui.status("(did you forget to merge?" + - " use push -f to force)\n") + self.ui.warn(_("abort: push creates new remote branches!\n")) + self.ui.status(_("(did you forget to merge?" + " use push -f to force)\n")) return 1 cg = self.changegroup(update) @@ -1226,8 +1253,8 @@ if l <= 4: return "" d = source.read(l - 4) if len(d) < l - 4: - raise repo.RepoError("premature EOF reading chunk" + - " (got %d bytes, expected %d)" + raise repo.RepoError(_("premature EOF reading chunk" + " (got %d bytes, expected %d)") % (len(d), l - 4)) return d @@ -1238,7 +1265,7 @@ yield c def csmap(x): - self.ui.debug("add changeset %s\n" % short(x)) + self.ui.debug(_("add changeset %s\n") % short(x)) return self.changelog.count() def revmap(x): @@ -1252,7 +1279,7 @@ oldheads = len(self.changelog.heads()) # pull off the changeset group - self.ui.status("adding changesets\n") + self.ui.status(_("adding changesets\n")) co = self.changelog.tip() cn = self.changelog.addgroup(getgroup(), csmap, tr, 1) # unique cnr, cor = map(self.changelog.rev, (cn, co)) @@ -1261,16 +1288,16 @@ changesets = cnr - cor # pull off the manifest group - self.ui.status("adding manifests\n") + self.ui.status(_("adding manifests\n")) mm = self.manifest.tip() mo = self.manifest.addgroup(getgroup(), revmap, tr) # process the files - self.ui.status("adding file changes\n") + self.ui.status(_("adding file changes\n")) while 1: f = getchunk() if not f: break - self.ui.debug("adding %s revisions\n" % f) + self.ui.debug(_("adding %s revisions\n") % f) fl = self.file(f) o = fl.count() n = fl.addgroup(getgroup(), revmap, tr) @@ -1280,18 +1307,18 @@ newheads = len(self.changelog.heads()) heads = "" if oldheads and newheads > oldheads: - heads = " (+%d heads)" % (newheads - oldheads) + heads = _(" (+%d heads)") % (newheads - oldheads) - self.ui.status(("added %d changesets" + - " with %d changes to %d files%s\n") - % (changesets, revisions, files, heads)) + self.ui.status(_("added %d changesets" + " with %d changes to %d files%s\n") + % (changesets, revisions, files, heads)) tr.close() if changesets > 0: if not self.hook("changegroup", node=hex(self.changelog.node(cor+1))): - self.ui.warn("abort: changegroup hook returned failure!\n") + self.ui.warn(_("abort: changegroup hook returned failure!\n")) return 1 for i in range(cor + 1, cnr + 1): @@ -1303,7 +1330,7 @@ moddirstate=True): pl = self.dirstate.parents() if not force and pl[1] != nullid: - self.ui.warn("aborting: outstanding uncommitted merges\n") + self.ui.warn(_("aborting: outstanding uncommitted merges\n")) return 1 p1, p2 = pl[0], node @@ -1326,10 +1353,10 @@ # resolve the manifest to determine which files # we care about merging - self.ui.note("resolving manifests\n") - self.ui.debug(" force %s allow %s moddirstate %s linear %s\n" % + self.ui.note(_("resolving manifests\n")) + self.ui.debug(_(" force %s allow %s moddirstate %s linear %s\n") % (force, allow, moddirstate, linear_path)) - self.ui.debug(" ancestor %s local %s remote %s\n" % + self.ui.debug(_(" ancestor %s local %s remote %s\n") % (short(man), short(m1n), short(m2n))) merge = {} @@ -1375,7 +1402,7 @@ a = ma.get(f, nullid) # are both different from the ancestor? if n != a and m2[f] != a: - self.ui.debug(" %s versions differ, resolve\n" % f) + self.ui.debug(_(" %s versions differ, resolve\n") % f) # merge executable bits # "if we changed or they changed, change in merge" a, b, c = mfa.get(f, 0), mfw[f], mf2[f] @@ -1386,7 +1413,7 @@ # is remote's version newer? # or are we going back in time? elif force or m2[f] != a or (p2 == pa and mw[f] == m1[f]): - self.ui.debug(" remote %s is newer, get\n" % f) + self.ui.debug(_(" remote %s is newer, get\n") % f) get[f] = m2[f] s = 1 elif f in umap: @@ -1395,60 +1422,60 @@ if not s and mfw[f] != mf2[f]: if force: - self.ui.debug(" updating permissions for %s\n" % f) + self.ui.debug(_(" updating permissions for %s\n") % f) util.set_exec(self.wjoin(f), mf2[f]) else: a, b, c = mfa.get(f, 0), mfw[f], mf2[f] mode = ((a^b) | (a^c)) ^ a if mode != b: - self.ui.debug(" updating permissions for %s\n" % f) + self.ui.debug(_(" updating permissions for %s\n") % f) util.set_exec(self.wjoin(f), mode) del m2[f] elif f in ma: if n != ma[f]: - r = "d" + r = _("d") if not force and (linear_path or allow): r = self.ui.prompt( - (" local changed %s which remote deleted\n" % f) + - "(k)eep or (d)elete?", "[kd]", "k") - if r == "d": + (_(" local changed %s which remote deleted\n") % f) + + _("(k)eep or (d)elete?"), _("[kd]"), _("k")) + if r == _("d"): remove.append(f) else: - self.ui.debug("other deleted %s\n" % f) + self.ui.debug(_("other deleted %s\n") % f) remove.append(f) # other deleted it else: # file is created on branch or in working directory if force and f not in umap: - self.ui.debug("remote deleted %s, clobbering\n" % f) + self.ui.debug(_("remote deleted %s, clobbering\n") % f) remove.append(f) elif n == m1.get(f, nullid): # same as parent if p2 == pa: # going backwards? - self.ui.debug("remote deleted %s\n" % f) + self.ui.debug(_("remote deleted %s\n") % f) remove.append(f) else: - self.ui.debug("local modified %s, keeping\n" % f) + self.ui.debug(_("local modified %s, keeping\n") % f) else: - self.ui.debug("working dir created %s, keeping\n" % f) + self.ui.debug(_("working dir created %s, keeping\n") % f) for f, n in m2.iteritems(): if choose and not choose(f): continue if f[0] == "/": continue if f in ma and n != ma[f]: - r = "k" + r = _("k") if not force and (linear_path or allow): r = self.ui.prompt( - ("remote changed %s which local deleted\n" % f) + - "(k)eep or (d)elete?", "[kd]", "k") - if r == "k": get[f] = n + (_("remote changed %s which local deleted\n") % f) + + _("(k)eep or (d)elete?"), _("[kd]"), _("k")) + if r == _("k"): get[f] = n elif f not in ma: - self.ui.debug("remote created %s\n" % f) + self.ui.debug(_("remote created %s\n") % f) get[f] = n else: if force or p2 == pa: # going backwards? - self.ui.debug("local deleted %s, recreating\n" % f) + self.ui.debug(_("local deleted %s, recreating\n") % f) get[f] = n else: - self.ui.debug("local deleted %s\n" % f) + self.ui.debug(_("local deleted %s\n") % f) del mw, m1, m2, ma @@ -1463,17 +1490,17 @@ p1, p2 = p2, nullid else: if not allow: - self.ui.status("this update spans a branch" + - " affecting the following files:\n") + self.ui.status(_("this update spans a branch" + " affecting the following files:\n")) fl = merge.keys() + get.keys() fl.sort() for f in fl: cf = "" - if f in merge: cf = " (resolve)" + if f in merge: cf = _(" (resolve)") self.ui.status(" %s%s\n" % (f, cf)) - self.ui.warn("aborting update spanning branches!\n") - self.ui.status("(use update -m to merge across branches" + - " or -C to lose changes)\n") + self.ui.warn(_("aborting update spanning branches!\n")) + self.ui.status(_("(use update -m to merge across branches" + " or -C to lose changes)\n")) return 1 branch_merge = True @@ -1485,7 +1512,7 @@ files.sort() for f in files: if f[0] == "/": continue - self.ui.note("getting %s\n" % f) + self.ui.note(_("getting %s\n") % f) t = self.file(f).read(get[f]) try: self.wwrite(f, t) @@ -1505,7 +1532,7 @@ files = merge.keys() files.sort() for f in files: - self.ui.status("merging %s\n" % f) + self.ui.status(_("merging %s\n") % f) my, other, flag = merge[f] self.merge3(f, my, other) util.set_exec(self.wjoin(f), flag) @@ -1525,14 +1552,13 @@ remove.sort() for f in remove: - self.ui.note("removing %s\n" % f) + self.ui.note(_("removing %s\n") % f) try: - os.unlink(self.wjoin(f)) + util.unlink(self.wjoin(f)) except OSError, inst: - self.ui.warn("update failed to remove %s: %s!\n" % (f, inst)) - # try removing directories that might now be empty - try: os.removedirs(os.path.dirname(self.wjoin(f))) - except: pass + if inst.errno != errno.ENOENT: + self.ui.warn(_("update failed to remove %s: %s!\n") % + (f, inst.strerror)) if moddirstate: if branch_merge: self.dirstate.update(remove, 'r') @@ -1556,15 +1582,15 @@ b = temp("base", base) c = temp("other", other) - self.ui.note("resolving %s\n" % fn) - self.ui.debug("file %s: my %s other %s ancestor %s\n" % + self.ui.note(_("resolving %s\n") % fn) + self.ui.debug(_("file %s: my %s other %s ancestor %s\n") % (fn, short(my), short(other), short(base))) cmd = (os.environ.get("HGMERGE") or self.ui.config("ui", "merge") or "hgmerge") - r = os.system("%s %s %s %s" % (cmd, a, b, c)) + r = os.system('%s "%s" "%s" "%s"' % (cmd, a, b, c)) if r: - self.ui.warn("merging %s failed!\n" % fn) + self.ui.warn(_("merging %s failed!\n") % fn) os.unlink(b) os.unlink(c) @@ -1581,25 +1607,25 @@ errors[0] += 1 seen = {} - self.ui.status("checking changesets\n") + self.ui.status(_("checking changesets\n")) for i in range(self.changelog.count()): changesets += 1 n = self.changelog.node(i) l = self.changelog.linkrev(n) if l != i: - err("incorrect link (%d) for changeset revision %d" % (l, i)) + err(_("incorrect link (%d) for changeset revision %d") %(l, i)) if n in seen: - err("duplicate changeset at revision %d" % i) + err(_("duplicate changeset at revision %d") % i) seen[n] = 1 for p in self.changelog.parents(n): if p not in self.changelog.nodemap: - err("changeset %s has unknown parent %s" % + err(_("changeset %s has unknown parent %s") % (short(n), short(p))) try: changes = self.changelog.read(n) except Exception, inst: - err("unpacking changeset %s: %s" % (short(n), inst)) + err(_("unpacking changeset %s: %s") % (short(n), inst)) neededmanifests[changes[0]] = n @@ -1607,55 +1633,55 @@ filelinkrevs.setdefault(f, []).append(i) seen = {} - self.ui.status("checking manifests\n") + self.ui.status(_("checking manifests\n")) for i in range(self.manifest.count()): n = self.manifest.node(i) l = self.manifest.linkrev(n) if l < 0 or l >= self.changelog.count(): - err("bad manifest link (%d) at revision %d" % (l, i)) + err(_("bad manifest link (%d) at revision %d") % (l, i)) if n in neededmanifests: del neededmanifests[n] if n in seen: - err("duplicate manifest at revision %d" % i) + err(_("duplicate manifest at revision %d") % i) seen[n] = 1 for p in self.manifest.parents(n): if p not in self.manifest.nodemap: - err("manifest %s has unknown parent %s" % + err(_("manifest %s has unknown parent %s") % (short(n), short(p))) try: delta = mdiff.patchtext(self.manifest.delta(n)) except KeyboardInterrupt: - self.ui.warn("interrupted") + self.ui.warn(_("interrupted")) raise except Exception, inst: - err("unpacking manifest %s: %s" % (short(n), inst)) + err(_("unpacking manifest %s: %s") % (short(n), inst)) ff = [ l.split('\0') for l in delta.splitlines() ] for f, fn in ff: filenodes.setdefault(f, {})[bin(fn[:40])] = 1 - self.ui.status("crosschecking files in changesets and manifests\n") + self.ui.status(_("crosschecking files in changesets and manifests\n")) for m,c in neededmanifests.items(): - err("Changeset %s refers to unknown manifest %s" % + err(_("Changeset %s refers to unknown manifest %s") % (short(m), short(c))) del neededmanifests for f in filenodes: if f not in filelinkrevs: - err("file %s in manifest but not in changesets" % f) + err(_("file %s in manifest but not in changesets") % f) for f in filelinkrevs: if f not in filenodes: - err("file %s in changeset but not in manifest" % f) + err(_("file %s in changeset but not in manifest") % f) - self.ui.status("checking files\n") + self.ui.status(_("checking files\n")) ff = filenodes.keys() ff.sort() for f in ff: @@ -1669,15 +1695,15 @@ n = fl.node(i) if n in seen: - err("%s: duplicate revision %d" % (f, i)) + err(_("%s: duplicate revision %d") % (f, i)) if n not in filenodes[f]: - err("%s: %d:%s not in manifests" % (f, i, short(n))) + err(_("%s: %d:%s not in manifests") % (f, i, short(n))) else: del filenodes[f][n] flr = fl.linkrev(n) if flr not in filelinkrevs[f]: - err("%s:%s points to unexpected changeset %d" + err(_("%s:%s points to unexpected changeset %d") % (f, short(n), flr)) else: filelinkrevs[f].remove(flr) @@ -1686,25 +1712,25 @@ try: t = fl.read(n) except Exception, inst: - err("unpacking file %s %s: %s" % (f, short(n), inst)) + err(_("unpacking file %s %s: %s") % (f, short(n), inst)) # verify parents (p1, p2) = fl.parents(n) if p1 not in nodes: - err("file %s:%s unknown parent 1 %s" % + err(_("file %s:%s unknown parent 1 %s") % (f, short(n), short(p1))) if p2 not in nodes: - err("file %s:%s unknown parent 2 %s" % + err(_("file %s:%s unknown parent 2 %s") % (f, short(n), short(p1))) nodes[n] = 1 # cross-check for node in filenodes[f]: - err("node %s in manifests not in %s" % (hex(node), f)) + err(_("node %s in manifests not in %s") % (hex(node), f)) - self.ui.status("%d files, %d changesets, %d total revisions\n" % + self.ui.status(_("%d files, %d changesets, %d total revisions\n") % (files, changesets, revisions)) if errors[0]: - self.ui.warn("%d integrity errors encountered!\n" % errors[0]) + self.ui.warn(_("%d integrity errors encountered!\n") % errors[0]) return 1
--- a/mercurial/manifest.py Sun Oct 16 16:24:40 2005 -0700 +++ b/mercurial/manifest.py Thu Oct 27 12:26:16 2005 -0700 @@ -7,6 +7,7 @@ import sys, struct from revlog import * +from i18n import gettext as _ from demandload import * demandload(globals(), "bisect") @@ -38,16 +39,6 @@ self.read(node) return self.mapcache[2] - def diff(self, a, b): - # this is sneaky, as we're not actually using a and b - if self.listcache and self.addlist and self.listcache[0] == a: - d = mdiff.diff(self.listcache[1], self.addlist, 1) - if mdiff.patch(a, d) != b: - raise AssertionError("sortdiff failed!") - return d - else: - return mdiff.textdiff(a, b) - def add(self, map, flags, transaction, link, p1=None, p2=None, changed=None): # directly generate the mdiff delta from the data collected during @@ -144,7 +135,7 @@ end = bs if w[1] == 1: raise AssertionError( - "failed to remove %s from manifest\n" % f) + _("failed to remove %s from manifest\n") % f) else: # item is found, replace/delete the existing line end = bs + 1 @@ -158,7 +149,7 @@ text = "".join(self.addlist) if cachedelta and mdiff.patch(self.listcache[0], cachedelta) != text: - raise AssertionError("manifest delta failure\n") + raise AssertionError(_("manifest delta failure\n")) n = self.addrevision(text, transaction, link, p1, p2, cachedelta) self.mapcache = (n, map, flags) self.listcache = (text, self.addlist)
--- a/mercurial/mdiff.py Sun Oct 16 16:24:40 2005 -0700 +++ b/mercurial/mdiff.py Thu Oct 27 12:26:16 2005 -0700 @@ -45,65 +45,6 @@ return "".join(l) -def sortdiff(a, b): - la = lb = 0 - lena = len(a) - lenb = len(b) - - while 1: - am, bm, = la, lb - - # walk over matching lines - while lb < lenb and la < lena and a[la] == b[lb] : - la += 1 - lb += 1 - - if la > am: - yield (am, bm, la - am) # return a match - - # skip mismatched lines from b - while la < lena and lb < lenb and b[lb] < a[la]: - lb += 1 - - if lb >= lenb: - break - - # skip mismatched lines from a - while la < lena and lb < lenb 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)) - - if sorted: - try: - d = sortdiff(a, b) - except: - raise - else: - 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): pos = 0 t = [] @@ -119,5 +60,3 @@ patches = mpatch.patches textdiff = bdiff.bdiff - -
--- a/mercurial/revlog.py Sun Oct 16 16:24:40 2005 -0700 +++ b/mercurial/revlog.py Thu Oct 27 12:26:16 2005 -0700 @@ -11,6 +11,7 @@ """ from node import * +from i18n import gettext as _ from demandload import demandload demandload(globals(), "binascii errno heapq mdiff sha struct zlib") @@ -47,7 +48,7 @@ if t == '\0': return bin if t == 'x': return zlib.decompress(bin) if t == 'u': return bin[1:] - raise RevlogError("unknown compression type %s" % t) + raise RevlogError(_("unknown compression type %s") % t) indexformat = ">4l20s20s20s" @@ -97,6 +98,8 @@ def __len__(self): return len(self.p.index) def load(self, pos): + if pos < 0: + pos += len(self.p.index) self.p.load(pos) return self.p.index[pos] def __getitem__(self, pos): @@ -213,7 +216,7 @@ try: return self.nodemap[node] except KeyError: - raise RevlogError('%s: no node %s' % (self.indexfile, hex(node))) + raise RevlogError(_('%s: no node %s') % (self.indexfile, hex(node))) def linkrev(self, node): return self.index[self.rev(node)][3] def parents(self, node): if node == nullid: return (nullid, nullid) @@ -444,8 +447,8 @@ for n in self.nodemap: if hex(n).startswith(id): c.append(n) - if len(c) > 1: raise KeyError("Ambiguous identifier") - if len(c) < 1: raise KeyError("No match found") + if len(c) > 1: raise RevlogError(_("Ambiguous identifier")) + if len(c) < 1: raise RevlogError(_("No match found")) return c[0] return None @@ -507,7 +510,7 @@ text = mdiff.patches(text, bins) if node != hash(text, p1, p2): - raise RevlogError("integrity check failed on %s:%d" + raise RevlogError(_("integrity check failed on %s:%d") % (self.datafile, rev)) self.cache = (node, rev, text) @@ -776,7 +779,7 @@ if node in self.nodemap: # this can happen if two branches make the same change # if unique: - # raise RevlogError("already have %s" % hex(node[:4])) + # raise RevlogError(_("already have %s") % hex(node[:4])) chain = node continue delta = chunk[80:] @@ -785,7 +788,7 @@ # retrieve the parent revision of the delta chain chain = p1 if not chain in self.nodemap: - raise RevlogError("unknown base %s" % short(chain[:4])) + raise RevlogError(_("unknown base %s") % short(chain[:4])) # full versions are inserted when the needed deltas become # comparable to the uncompressed text or when the previous @@ -804,7 +807,7 @@ text = self.patches(text, [delta]) chk = self.addrevision(text, transaction, link, p1, p2) if chk != node: - raise RevlogError("consistency error adding group") + raise RevlogError(_("consistency error adding group")) measure = len(text) else: e = (end, len(cdelta), self.base(t), link, p1, p2, node)
--- a/mercurial/sshrepo.py Sun Oct 16 16:24:40 2005 -0700 +++ b/mercurial/sshrepo.py Thu Oct 27 12:26:16 2005 -0700 @@ -7,6 +7,7 @@ from node import * from remoterepo import * +from i18n import gettext as _ from demandload import * demandload(globals(), "hg os re stat") @@ -17,7 +18,7 @@ m = re.match(r'ssh://(([^@]+)@)?([^:/]+)(:(\d+))?(/(.*))?', path) if not m: - raise hg.RepoError("couldn't parse destination %s" % path) + raise hg.RepoError(_("couldn't parse destination %s") % path) self.user = m.group(2) self.host = m.group(3) @@ -41,7 +42,7 @@ if size == 0: break l = self.pipee.readline() if not l: break - self.ui.status("remote: ", l) + self.ui.status(_("remote: "), l) def __del__(self): try: @@ -49,7 +50,7 @@ self.pipei.close() # read the error descriptor until EOF for l in self.pipee: - self.ui.status("remote: ", l) + self.ui.status(_("remote: "), l) self.pipee.close() except: pass @@ -58,7 +59,7 @@ return -1 def do_cmd(self, cmd, **args): - self.ui.debug("sending %s command\n" % cmd) + self.ui.debug(_("sending %s command\n") % cmd) self.pipeo.write("%s\n" % cmd) for k, v in args.items(): self.pipeo.write("%s %d\n" % (k, len(v))) @@ -74,7 +75,7 @@ try: l = int(l) except: - raise hg.RepoError("unexpected response '%s'" % l) + raise hg.RepoError(_("unexpected response '%s'") % l) return r.read(l) def lock(self): @@ -89,7 +90,7 @@ try: return map(bin, d[:-1].split(" ")) except: - raise hg.RepoError("unexpected response '%s'" % (d[:400] + "...")) + raise hg.RepoError(_("unexpected response '%s'") % (d[:400] + "...")) def branches(self, nodes): n = " ".join(map(hex, nodes)) @@ -98,7 +99,7 @@ br = [ tuple(map(bin, b.split(" "))) for b in d.splitlines() ] return br except: - raise hg.RepoError("unexpected response '%s'" % (d[:400] + "...")) + raise hg.RepoError(_("unexpected response '%s'") % (d[:400] + "...")) def between(self, pairs): n = "\n".join(["-".join(map(hex, p)) for p in pairs]) @@ -107,7 +108,7 @@ p = [ l and map(bin, l.split(" ")) or [] for l in d.splitlines() ] return p except: - raise hg.RepoError("unexpected response '%s'" % (d[:400] + "...")) + raise hg.RepoError(_("unexpected response '%s'") % (d[:400] + "...")) def changegroup(self, nodes): n = " ".join(map(hex, nodes)) @@ -117,7 +118,7 @@ def addchangegroup(self, cg): d = self.call("addchangegroup") if d: - raise hg.RepoError("push refused: %s", d) + raise hg.RepoError(_("push refused: %s"), d) while 1: d = cg.read(4096)
--- a/mercurial/transaction.py Sun Oct 16 16:24:40 2005 -0700 +++ b/mercurial/transaction.py Thu Oct 27 12:26:16 2005 -0700 @@ -13,6 +13,7 @@ import os import util +from i18n import gettext as _ class transaction: def __init__(self, report, opener, journal, after=None): @@ -20,7 +21,7 @@ # abort here if the journal already exists if os.path.exists(journal): - raise AssertionError("journal already exists - run hg recover") + raise AssertionError(_("journal already exists - run hg recover")) self.report = report self.opener = opener @@ -58,17 +59,17 @@ def abort(self): if not self.entries: return - self.report("transaction abort!\n") + self.report(_("transaction abort!\n")) for f, o in self.entries: try: self.opener(f, "a").truncate(o) except: - self.report("failed to truncate %s\n" % f) + self.report(_("failed to truncate %s\n") % f) self.entries = [] - self.report("rollback completed\n") + self.report(_("rollback completed\n")) def rollback(opener, file): for l in open(file).readlines():
--- a/mercurial/ui.py Sun Oct 16 16:24:40 2005 -0700 +++ b/mercurial/ui.py Thu Oct 27 12:26:16 2005 -0700 @@ -6,6 +6,7 @@ # of the GNU General Public License, incorporated herein by reference. import os, ConfigParser +from i18n import gettext as _ from demandload import * demandload(globals(), "re socket sys util") @@ -88,9 +89,12 @@ user = user[f+1:] return user - def expandpath(self, loc): + def expandpath(self, loc, root=""): paths = {} for name, path in self.configitems("paths"): + m = path.find("://") + if m == -1: + path = os.path.join(root, path) paths[name] = path return paths.get(loc, loc) @@ -114,7 +118,7 @@ if re.match(pat, r): return r else: - self.write("unrecognized response\n") + self.write(_("unrecognized response\n")) def status(self, *msg): if not self.quiet: self.write(*msg) def warn(self, *msg): @@ -135,7 +139,7 @@ os.environ.get("EDITOR", "vi")) os.environ["HGUSER"] = self.username() - util.system("%s %s" % (editor, name), errprefix="edit failed") + util.system("%s %s" % (editor, name), errprefix=_("edit failed")) t = open(name).read() t = re.sub("(?m)^HG:.*\n", "", t)
--- a/mercurial/util.py Sun Oct 16 16:24:40 2005 -0700 +++ b/mercurial/util.py Thu Oct 27 12:26:16 2005 -0700 @@ -11,6 +11,7 @@ """ import os, errno +from i18n import gettext as _ from demandload import * demandload(globals(), "re cStringIO shutil popen2 tempfile threading time") @@ -46,7 +47,7 @@ cmd = cmd.replace('INFILE', inname) cmd = cmd.replace('OUTFILE', outname) code = os.system(cmd) - if code: raise Abort("command '%s' failed: %s" % + if code: raise Abort(_("command '%s' failed: %s") % (cmd, explain_exit(code))) return open(outname, 'rb').read() finally: @@ -82,7 +83,7 @@ files.setdefault(pf, 1) code = fp.close() if code: - raise Abort("patch command failed: %s" % explain_exit(code)) + raise Abort(_("patch command failed: %s") % explain_exit(code)[0]) return files.keys() def binary(s): @@ -178,6 +179,16 @@ raise Abort('%s not under root' % myname) def matcher(canonroot, cwd='', names=['.'], inc=[], exc=[], head=''): + return _matcher(canonroot, cwd, names, inc, exc, head, 'glob') + +def cmdmatcher(canonroot, cwd='', names=['.'], inc=[], exc=[], head=''): + if os.name == 'nt': + dflt_pat = 'glob' + else: + dflt_pat = 'relpath' + return _matcher(canonroot, cwd, names, inc, exc, head, dflt_pat) + +def _matcher(canonroot, cwd, names, inc, exc, head, dflt_pat): """build a function to match a set of file patterns arguments: @@ -207,12 +218,15 @@ make head regex a rooted bool """ - def patkind(name): + def patkind(name, dflt_pat='glob'): for prefix in 're', 'glob', 'path', 'relglob', 'relpath', 'relre': if name.startswith(prefix + ':'): return name.split(':', 1) + return dflt_pat, name + + def contains_glob(name): for c in name: - if c in _globchars: return 'glob', name - return 'relpath', name + if c in _globchars: return True + return False def regex(kind, name, tail): '''convert a pattern into a regular expression''' @@ -232,22 +246,36 @@ def matchfn(pats, tail): """build a matching function from a set of patterns""" - if pats: - pat = '(?:%s)' % '|'.join([regex(k, p, tail) for (k, p) in pats]) - return re.compile(pat).match + if not pats: + return + matches = [] + for k, p in pats: + try: + pat = '(?:%s)' % regex(k, p, tail) + matches.append(re.compile(pat).match) + except re.error, inst: + raise Abort("invalid pattern: %s:%s" % (k, p)) + + def buildfn(text): + for m in matches: + r = m(text) + if r: + return r + + return buildfn def globprefix(pat): '''return the non-glob prefix of a path, e.g. foo/* -> foo''' root = [] for p in pat.split(os.sep): - if patkind(p)[0] == 'glob': break + if contains_glob(p): break root.append(p) return '/'.join(root) pats = [] files = [] roots = [] - for kind, name in map(patkind, names): + for kind, name in [patkind(p, dflt_pat) for p in names]: if kind in ('glob', 'relpath'): name = canonpath(canonroot, cwd, name) if name == '': @@ -296,6 +324,13 @@ os.unlink(dst) os.rename(src, dst) +def unlink(f): + """unlink and remove the directory if it is empty""" + os.unlink(f) + # try removing directories that might now be empty + try: os.removedirs(os.path.dirname(f)) + except: pass + def copyfiles(src, dst, hardlink=None): """Copy a directory tree using hardlinks if possible""" @@ -365,13 +400,23 @@ os_link = os.link else: def os_link(src, dst): - raise OSError(0, "Hardlinks not supported") + raise OSError(0, _("Hardlinks not supported")) # Platform specific variants if os.name == 'nt': + demandload(globals(), "msvcrt") nulldev = 'NUL:' + + try: + import win32api, win32process + filename = win32process.GetModuleFileNameEx(win32api.GetCurrentProcess(), 0) + systemrc = os.path.join(os.path.dirname(filename), 'mercurial.ini') + + except ImportError: + systemrc = r'c:\mercurial\mercurial.ini' + pass - rcpath = (r'c:\mercurial\mercurial.ini', + rcpath = (systemrc, os.path.join(os.path.expanduser('~'), 'mercurial.ini')) def parse_patch_output(output_line): @@ -408,6 +453,9 @@ def set_exec(f, mode): pass + def set_binary(fd): + msvcrt.setmode(fd.fileno(), os.O_BINARY) + def pconvert(path): return path.replace("\\", "/") @@ -421,7 +469,7 @@ readlock = _readlock_file def explain_exit(code): - return "exited with status %d" % code, code + return _("exited with status %d") % code, code else: nulldev = '/dev/null' @@ -454,6 +502,9 @@ else: os.chmod(f, s & 0666) + def set_binary(fd): + pass + def pconvert(path): return path @@ -484,14 +535,14 @@ """return a 2-tuple (desc, code) describing a process's status""" if os.WIFEXITED(code): val = os.WEXITSTATUS(code) - return "exited with status %d" % val, val + return _("exited with status %d") % val, val elif os.WIFSIGNALED(code): val = os.WTERMSIG(code) - return "killed by signal %d" % val, val + return _("killed by signal %d") % val, val elif os.WIFSTOPPED(code): val = os.WSTOPSIG(code) - return "stopped by signal %d" % val, val - raise ValueError("invalid exit code") + return _("stopped by signal %d") % val, val + raise ValueError(_("invalid exit code")) class chunkbuffer(object): """Allow arbitrary sized chunks of data to be efficiently read from an @@ -504,7 +555,7 @@ self.buf = '' self.targetsize = int(targetsize) if self.targetsize <= 0: - raise ValueError("targetsize must be greater than 0, was %d" % + raise ValueError(_("targetsize must be greater than 0, was %d") % targetsize) self.iterempty = False
--- a/setup.py Sun Oct 16 16:24:40 2005 -0700 +++ b/setup.py Thu Oct 27 12:26:16 2005 -0700 @@ -6,6 +6,7 @@ # './setup.py --help' for more options import glob +import sys from distutils.core import setup, Extension from distutils.command.install_data import install_data @@ -15,6 +16,20 @@ try: import py2exe + # Help py2exe to find win32com.shell + try: + import modulefinder + import win32com + for p in win32com.__path__[1:]: # Take the path to win32comext + modulefinder.AddPackagePath("win32com", p) + pn = "win32com.shell" + __import__(pn) + m = sys.modules[pn] + for p in m.__path__[1:]: + modulefinder.AddPackagePath(pn, p) + except ImportError: + pass + # Due to the use of demandload py2exe is not finding the modules. # packagescan.getmodules creates a list of modules included in # the mercurial package plus depdent modules. @@ -34,6 +49,8 @@ # Sets the 'includes' option with the list of needed modules if not self.includes: self.includes = [] + else: + self.includes = self.includes.split(',') self.includes += mercurial.packagescan.getmodules(self.build_lib, 'mercurial') self.includes += mercurial.packagescan.getmodules(self.build_lib,
--- a/templates/changelog.tmpl Sun Oct 16 16:24:40 2005 -0700 +++ b/templates/changelog.tmpl Thu Oct 27 12:26:16 2005 -0700 @@ -7,8 +7,8 @@ <div class="buttons"> <a href="?cmd=tags">tags</a> -<a href="?cmd=manifest;manifest=#manifest#;path=/">manifest</a> -<a type="application/rss+xml" href="?cmd=changelog;style=rss">rss</a> +<a href="?mf=#manifest|short#;path=/">manifest</a> +<a type="application/rss+xml" href="?style=rss">rss</a> </div> <h2>changelog for #repo|escape#</h2> @@ -18,7 +18,7 @@ <label for="search1">search:</label> <input type="hidden" name="cmd" value="changelog"> <input name="rev" id="search1" type="text" size="30"> -navigate: <small>#changenav%naventry#</small> +navigate: <small class="navigate">#changenav%naventry#</small> </p> </form> @@ -29,7 +29,7 @@ <label for="search2">search:</label> <input type="hidden" name="cmd" value="changelog"> <input name="rev" id="search2" type="text" size="30"> -navigate: <small>#changenav%naventry#</small> +navigate: <small class="navigate">#changenav%naventry#</small> </p> </form>
--- a/templates/changelogentry-rss.tmpl Sun Oct 16 16:24:40 2005 -0700 +++ b/templates/changelogentry-rss.tmpl Thu Oct 27 12:26:16 2005 -0700 @@ -1,7 +1,7 @@ <item> - <title>#desc|firstline|escape#</title> - <link>#url#?cmd=changeset;node=#node#</link> - <description><![CDATA[#desc|escape|addbreaks#]]></description> + <title>#desc|strip|firstline|rstrip|escape#</title> + <link>#url#?cs=#node|short#</link> + <description><![CDATA[#desc|strip|escape|addbreaks#]]></description> <author>#author|obfuscate#</author> <pubDate>#date|rfc822date#</pubDate> </item>
--- a/templates/changelogentry.tmpl Sun Oct 16 16:24:40 2005 -0700 +++ b/templates/changelogentry.tmpl Thu Oct 27 12:26:16 2005 -0700 @@ -1,13 +1,13 @@ <table class="changelogEntry parity#parity#"> <tr> <th class="age" width="15%">#date|age# ago:</th> - <th class="firstline">#desc|firstline|escape#</th> + <th class="firstline">#desc|strip|firstline|escape#</th> </tr> <tr> <th class="changesetRev">changeset #rev#:</th> - <td class="changesetNode"><a href="?cmd=changeset;node=#node#">#node|short#</a></td> + <td class="changesetNode"><a href="?cs=#node|short#">#node|short#</a></td> </tr> - #parent# + #parent%changelogparent# #changelogtag# <tr> <th class="author">author:</th> @@ -18,7 +18,7 @@ <td class="date">#date|date#</td> </tr> <tr> - <th class="files"><a href="?cmd=manifest;manifest=#manifest#;path=/">files</a>:</th> + <th class="files"><a href="?mf=#manifest|short#;path=/">files</a>:</th> <td class="files">#files#</td> </tr> </table>
--- a/templates/changeset-raw.tmpl Sun Oct 16 16:24:40 2005 -0700 +++ b/templates/changeset-raw.tmpl Thu Oct 27 12:26:16 2005 -0700 @@ -3,7 +3,7 @@ # User #author# # Date #date|date# # Node ID #node# -#parent# +#parent%changesetparent# #desc# #diff#
--- a/templates/changeset.tmpl Sun Oct 16 16:24:40 2005 -0700 +++ b/templates/changeset.tmpl Thu Oct 27 12:26:16 2005 -0700 @@ -4,21 +4,21 @@ <body> <div class="buttons"> -<a href="?cmd=changelog;rev=#rev#">changelog</a> +<a href="?cl=#rev#">changelog</a> <a href="?cmd=tags">tags</a> -<a href="?cmd=manifest;manifest=#manifest#;path=/">manifest</a> -<a href="?cmd=changeset;node=#node#;style=raw">raw</a> +<a href="?mf=#manifest|short#;path=/">manifest</a> +<a href="?cs=#node|short#;style=raw">raw</a> #archives%archiveentry# </div> -<h2>changeset: #desc|escape|firstline#</h2> +<h2>changeset: #desc|strip|escape|firstline#</h2> <table id="changesetEntry"> <tr> <th class="changeset">changeset #rev#:</th> - <td class="changeset"><a href="?cmd=changeset;node=#node#">#node|short#</a></td> + <td class="changeset"><a href="?cs=#node|short#">#node|short#</a></td> </tr> -#parent# +#parent%changesetparent# #changesettag# <tr> <th class="author">author:</th> @@ -32,7 +32,7 @@ <td class="files">#files#</td></tr> <tr> <th class="description">description:</th> - <td class="description">#desc|escape|addbreaks#</td> + <td class="description">#desc|strip|escape|addbreaks#</td> </tr> </table> @@ -40,7 +40,6 @@ #diff# </div> -</body> -</html> +#footer#
--- a/templates/fileannotate.tmpl Sun Oct 16 16:24:40 2005 -0700 +++ b/templates/fileannotate.tmpl Thu Oct 27 12:26:16 2005 -0700 @@ -4,12 +4,12 @@ <body> <div class="buttons"> -<a href="?cmd=changelog;rev=#rev#">changelog</a> -<a href="?cmd=tags">tags</a> -<a href="?cmd=changeset;node=#node#">changeset</a> -<a href="?cmd=manifest;manifest=#manifest#;path=#path#">manifest</a> -<a href="?cmd=file;file=#file#;filenode=#filenode#">file</a> -<a href="?cmd=filelog;file=#file#;filenode=#filenode#">revisions</a> +<a href="?cl=#rev#">changelog</a> +<a href="?tags=">tags</a> +<a href="?cs=#node|short#">changeset</a> +<a href="?mf=#manifest|short#;path=#path#">manifest</a> +<a href="?f=#filenode|short#;file=#file#">file</a> +<a href="?fl=#filenode|short#;file=#file#">revisions</a> </div> <h2>Annotate #file#</h2> @@ -17,8 +17,8 @@ <table> <tr> <td class="metatag">changeset #rev#:</td> - <td><a href="?cmd=changeset;node=#node#">#node|short#</a></td></tr> -#parent# + <td><a href="?cs=#node|short#">#node|short#</a></td></tr> +#parent%fileannotateparent# <tr> <td class="metatag">author:</td> <td>#author|obfuscate#</td></tr>
--- a/templates/filediff.tmpl Sun Oct 16 16:24:40 2005 -0700 +++ b/templates/filediff.tmpl Thu Oct 27 12:26:16 2005 -0700 @@ -4,13 +4,13 @@ <body> <div class="buttons"> -<a href="?cmd=changelog;rev=#rev#">changelog</a> -<a href="?cmd=tags">tags</a> -<a href="?cmd=changeset;node=#node#">changeset</a> -<a href="?cmd=file;file=#file#;filenode=#filenode#">file</a> -<a href="?cmd=filelog;file=#file#;filenode=#filenode#">revisions</a> -<a href="?cmd=annotate;file=#file#;filenode=#filenode#">annotate</a> -<a href="?cmd=filediff;file=#file#;node=#node#;style=raw">raw</a> +<a href="?cl=#rev#">changelog</a> +<a href="?tags=">tags</a> +<a href="?cs=#node|short#">changeset</a> +<a href="?f=#filenode|short#;file=#file#">file</a> +<a href="?fl=#filenode|short#;file=#file#">revisions</a> +<a href="?fa=#filenode|short#;file=#file#">annotate</a> +<a href="?fd=#node|short#;file=#file#;style=raw">raw</a> </div> <h2>#file#</h2> @@ -18,9 +18,9 @@ <table id="filediffEntry"> <tr> <th class="revision">revision #rev#:</th> - <td class="revision"><a href="?cmd=changeset;node=#node#">#node|short#</a></td> + <td class="revision"><a href="?cs=#node|short#">#node|short#</a></td> </tr> -#parent# +#parent%filediffparent# </table> <div id="fileDiff">
--- a/templates/filelog.tmpl Sun Oct 16 16:24:40 2005 -0700 +++ b/templates/filelog.tmpl Thu Oct 27 12:26:16 2005 -0700 @@ -1,17 +1,17 @@ #header# <title>#repo|escape#: #file# history</title> <link rel="alternate" type="application/rss+xml" - href="?cmd=filelog;file=#file#;filenode=0;style=rss" title="RSS feed for #repo|escape#:#file#"> + href="?fl=0;file=#file#;style=rss" title="RSS feed for #repo|escape#:#file#"> </head> </head> <body> <div class="buttons"> -<a href="?cmd=changelog">changelog</a> -<a href="?cmd=tags">tags</a> -<a href="?cmd=file;file=#file#;filenode=#filenode#">file</a> -<a href="?cmd=annotate;file=#file#;filenode=#filenode#">annotate</a> -<a type="application/rss+xml" href="?cmd=filelog;file=#file#;filenode=0;style=rss">rss</a> +<a href="?cl=tip">changelog</a> +<a href="?tags=">tags</a> +<a href="?f=#filenode|short#;file=#file#">file</a> +<a href="?fa=#filenode|short#;file=#file#">annotate</a> +<a type="application/rss+xml" href="?fl=0;file=#file#;style=rss">rss</a> </div> <h2>#file# revision history</h2>
--- a/templates/filelogentry-rss.tmpl Sun Oct 16 16:24:40 2005 -0700 +++ b/templates/filelogentry-rss.tmpl Thu Oct 27 12:26:16 2005 -0700 @@ -1,7 +1,7 @@ <item> - <title>#desc|firstline|escape#</title> - <link>#url#?cmd=file;file=#file#;filenode=#filenode#</link> - <description><![CDATA[#desc|escape|addbreaks#]]></description> + <title>#desc|strip|firstline|rstrip|escape#</title> + <link>#url#?f=#filenode|short#;file=#file#</link> + <description><![CDATA[#desc|strip|escape|addbreaks#]]></description> <author>#author|obfuscate#</author> <pubDate>#date|rfc822date#</pubDate>> </item>
--- a/templates/filelogentry.tmpl Sun Oct 16 16:24:40 2005 -0700 +++ b/templates/filelogentry.tmpl Thu Oct 27 12:26:16 2005 -0700 @@ -1,12 +1,12 @@ <table class="parity#parity#" width="100%" cellspacing="0" cellpadding="0"> <tr> <td align="right" width="15%"><b>#date|age# ago: </b></td> - <td><b><a href="?cmd=changeset;node=#node#">#desc|firstline|escape#</a></b></td></tr> + <td><b><a href="?cs=#node|short#">#desc|strip|firstline|escape#</a></b></td></tr> <tr> <td align="right">revision #filerev#: </td> - <td><a href="?cmd=file;file=#file#;filenode=#filenode#">#filenode|short#</a> -<a href="?cmd=filediff;file=#file#;node=#node#">(diff)</a> -<a href="?cmd=annotate;file=#file#;filenode=#filenode#">(annotate)</a> + <td><a href="?f=#filenode|short#;file=#file#">#filenode|short#</a> +<a href="?fd=#node|short#;file=#file#">(diff)</a> +<a href="?fa=#filenode|short#;file=#file#">(annotate)</a> </td></tr> <tr> <td align="right">author: </td>
--- a/templates/filerevision-raw.tmpl Sun Oct 16 16:24:40 2005 -0700 +++ b/templates/filerevision-raw.tmpl Thu Oct 27 12:26:16 2005 -0700 @@ -1,3 +1,4 @@ -#header# -#text%fileline# -#footer# +Context-type: #mimetype# +Content-disposition: filename=#file# + +#raw#
--- a/templates/filerevision.tmpl Sun Oct 16 16:24:40 2005 -0700 +++ b/templates/filerevision.tmpl Thu Oct 27 12:26:16 2005 -0700 @@ -4,13 +4,13 @@ <body> <div class="buttons"> -<a href="?cmd=changelog;rev=#rev#">changelog</a> -<a href="?cmd=tags">tags</a> -<a href="?cmd=changeset;node=#node#">changeset</a> -<a href="?cmd=manifest;manifest=#manifest#;path=#path#">manifest</a> -<a href="?cmd=filelog;file=#file#;filenode=#filenode#">revisions</a> -<a href="?cmd=annotate;file=#file#;filenode=#filenode#">annotate</a> -<a href="?cmd=file;file=#file#;filenode=#filenode#;style=raw">raw</a> +<a href="?cl=#rev#">changelog</a> +<a href="?tags=">tags</a> +<a href="?cs=#node|short#">changeset</a> +<a href="?mf=#manifest|short#;path=#path#">manifest</a> +<a href="?fl=#filenode|short#;file=#file#">revisions</a> +<a href="?fa=#filenode|short#;file=#file#">annotate</a> +<a href="?f=#filenode|short#;file=#file#;style=raw">raw</a> </div> <h2>#file#</h2> @@ -18,8 +18,8 @@ <table> <tr> <td class="metatag">changeset #rev#:</td> - <td><a href="?cmd=changeset;node=#node#">#node|short#</a></td></tr> -#parent# + <td><a href="?cs=#node|short#">#node|short#</a></td></tr> +#parent%filerevparent# <tr> <td class="metatag">author:</td> <td>#author|obfuscate#</td></tr>
--- a/templates/footer.tmpl Sun Oct 16 16:24:40 2005 -0700 +++ b/templates/footer.tmpl Thu Oct 27 12:26:16 2005 -0700 @@ -1,2 +1,7 @@ +<div class="logo"> +powered by<br/> +<a href="http://www.selenic.com/mercurial/">mercurial</a> +</div> + </body> </html>
--- a/templates/header.tmpl Sun Oct 16 16:24:40 2005 -0700 +++ b/templates/header.tmpl Thu Oct 27 12:26:16 2005 -0700 @@ -21,6 +21,13 @@ font-family: sans; font-weight: bold; } +.navigate a { + background-color: #ccc; + padding: 2pt; + font-family: sans; + color: black; +} + .metatag { background-color: #888888; color: white; @@ -30,6 +37,23 @@ /* Common */ pre { margin: 0; } +.logo { + background-color: #333; + padding: 4pt; + margin: 8pt 0 8pt 8pt; + font-family: sans; + font-size: 60%; + color: white; + float: right; + clear: right; + text-align: left; +} + +.logo a { + font-weight: bold; + font-size: 150%; + color: #999; +} /* Changelog entries */ .changelogEntry { width: 100%; }
--- a/templates/manifest.tmpl Sun Oct 16 16:24:40 2005 -0700 +++ b/templates/manifest.tmpl Thu Oct 27 12:26:16 2005 -0700 @@ -4,9 +4,9 @@ <body> <div class="buttons"> -<a href="?cmd=changelog;rev=#rev#">changelog</a> -<a href="?cmd=tags">tags</a> -<a href="?cmd=changeset;node=#node#">changeset</a> +<a href="?cl=#rev#">changelog</a> +<a href="?tags=">tags</a> +<a href="?cs=#node|short#">changeset</a> </div> <h2>manifest for changeset #node|short#: #path#</h2> @@ -14,7 +14,7 @@ <table cellpadding="0" cellspacing="0"> <tr class="parity1"> <td><tt>drwxr-xr-x</tt> - <td><a href="?cmd=manifest;manifest=#manifest#;path=#up#">[up]</a> + <td><a href="?mf=#manifest|short#;path=#up#">[up]</a> #dentries%manifestdirentry# #fentries%manifestfileentry# </table>
--- a/templates/map Sun Oct 16 16:24:40 2005 -0700 +++ b/templates/map Thu Oct 27 12:26:16 2005 -0700 @@ -3,39 +3,39 @@ footer = footer.tmpl search = search.tmpl changelog = changelog.tmpl -naventry = "<a href="?cmd=changelog;rev=#rev#">#label#</a> " -filedifflink = "<a href="?cmd=filediff;node=#node#;file=#file#">#file#</a> " -filenodelink = "<a href="?cmd=file;filenode=#filenode#;file=#file#">#file#</a> " +naventry = "<a href="?cl=#rev#">#label#</a> " +filedifflink = "<a href="?fd=#node|short#;file=#file#">#file#</a> " +filenodelink = "<a href="?f=#filenode|short#;file=#file#">#file#</a> " fileellipses = "..." changelogentry = changelogentry.tmpl searchentry = changelogentry.tmpl changeset = changeset.tmpl manifest = manifest.tmpl manifestdirentry = "<tr class="parity#parity#"><td><tt>drwxr-xr-x</tt> <td><a href="?cmd=manifest;manifest=#manifest#;path=#path#">#basename#/</a>" -manifestfileentry = "<tr class="parity#parity#"><td><tt>#permissions|permissions#</tt> <td><a href="?cmd=file;filenode=#filenode#;file=#file#">#basename#</a>" +manifestfileentry = "<tr class="parity#parity#"><td><tt>#permissions|permissions#</tt> <td><a href="?f=#filenode|short#;file=#file#">#basename#</a>" filerevision = filerevision.tmpl fileannotate = fileannotate.tmpl filediff = filediff.tmpl filelog = filelog.tmpl fileline = "<div class="parity#parity#"><span class="lineno">#linenumber#</span>#line|escape#</div>" filelogentry = filelogentry.tmpl -annotateline = "<tr class="parity#parity#"><td class="annotate"><a href="?cmd=changeset;node=#node#">#author|obfuscate#@#rev#</a></td><td><pre>#line|escape#</pre></td></tr>" +annotateline = "<tr class="parity#parity#"><td class="annotate"><a href="?cs=#node|short#">#author|obfuscate#@#rev#</a></td><td><pre>#line|escape#</pre></td></tr>" difflineplus = "<span class="plusline">#line|escape#</span>" difflineminus = "<span class="minusline">#line|escape#</span>" difflineat = "<span class="atline">#line|escape#</span>" diffline = "#line|escape#" -changelogparent = "<tr><th class="parent">parent #rev#:</th><td class="parent"><a href="?cmd=changeset;node=#node#">#node|short#</a></td></tr>" -changesetparent = "<tr><th class="parent">parent #rev#:</th><td class="parent"><a href="?cmd=changeset;node=#node#">#node|short#</a></td></tr>" -filerevparent = "<tr><td class="metatag">parent:</td><td><a href="?cmd=file;file=#file#;filenode=#node#">#node|short#</a></td></tr>" -fileannotateparent = "<tr><td class="metatag">parent:</td><td><a href="?cmd=annotate;file=#file#;filenode=#node#">#node|short#</a></td></tr>" +changelogparent = "<tr><th class="parent">parent #rev#:</th><td class="parent"><a href="?cs=#node|short#">#node|short#</a></td></tr>" +changesetparent = "<tr><th class="parent">parent #rev#:</th><td class="parent"><a href="?cs=#node|short#">#node|short#</a></td></tr>" +filerevparent = "<tr><td class="metatag">parent:</td><td><a href="?f=#node|short#;file=#file#">#node|short#</a></td></tr>" +fileannotateparent = "<tr><td class="metatag">parent:</td><td><a href="?fa=#filenode|short#;file=#file#">#node|short#</a></td></tr>" tags = tags.tmpl -tagentry = "<li class="tagEntry parity#parity#"><span class="node">#node#</span> <a href="?cmd=changeset;node=#node#">#tag#</a></li>" +tagentry = "<li class="tagEntry parity#parity#"><span class="node">#node#</span> <a href="?cs=#node|short#">#tag#</a></li>" diffblock = "<pre class="parity#parity#">#lines#</pre>" changelogtag = "<tr><th class="tag">tag:</th><td class="tag">#tag#</td></tr>" changesettag = "<tr><th class="tag">tag:</th><td class="tag">#tag#</td></tr>" -filediffparent = "<tr><th class="parent">parent #rev#:</th><td class="parent"><a href="?cmd=changeset;node=#node#">#node|short#</a></td></tr>" -filelogparent = "<tr><td align="right">parent #rev#: </td><td><a href="?cmd=file;file=#file#;filenode=#node#">#node|short#</a></td></tr>" -indexentry = "<tr class="parity#parity#"><td><a href="#url#">#name#</a></td><td>#shortdesc#</td><td>#contact|obfuscate#</td><td>#lastupdate|age# ago</td><td><a href="#url#?cmd=changelog;style=rss">RSS</a></td></tr>" +filediffparent = "<tr><th class="parent">parent #rev#:</th><td class="parent"><a href="?cs=#node|short#">#node|short#</a></td></tr>" +filelogparent = "<tr><td align="right">parent #rev#: </td><td><a href="?f=#node|short#;file=#file#">#node|short#</a></td></tr>" +indexentry = "<tr class="parity#parity#"><td><a href="#url#">#name#</a></td><td>#shortdesc#</td><td>#contact|obfuscate#</td><td>#lastupdate|age# ago</td><td><a href="#url#?cl=tip;style=rss">RSS</a></td></tr>" index = index.tmpl -archiveentry = "<a href="?cmd=archive;node=#node#;type=#type#">#type#</a> " +archiveentry = "<a href="?ca=#node|short#;type=#type#">#type#</a> " notfound = notfound.tmpl
--- a/templates/search.tmpl Sun Oct 16 16:24:40 2005 -0700 +++ b/templates/search.tmpl Thu Oct 27 12:26:16 2005 -0700 @@ -4,25 +4,29 @@ <body> <div class="buttons"> -<a href="?cmd=changelog;rev=#rev#">changelog</a> -<a href="?cmd=tags">tags</a> -<a href="?cmd=manifest;manifest=#manifest#;path=/">manifest</a> +<a href="?cl=tip">changelog</a> +<a href="?tags=">tags</a> +<a href="?mf=#manifest|short#;path=/">manifest</a> </div> <h2>searching for #query|escape#</h2> <form> +<p> search: <input type="hidden" name="cmd" value="changelog"> <input name="rev" type="text" width="30" value="#query|escape#"> +</p> </form> #entries# <form> +<p> search: <input type="hidden" name="cmd" value="changelog"> -<input name="rev" type="text" width="30"> +<input name="rev" type="text" width="30" value="#query|escape#"> +</p> </form> #footer#
--- a/templates/tags.tmpl Sun Oct 16 16:24:40 2005 -0700 +++ b/templates/tags.tmpl Thu Oct 27 12:26:16 2005 -0700 @@ -4,8 +4,8 @@ <body> <div class="buttons"> -<a href="?cmd=changelog;rev=#rev#">changelog</a> -<a href="?cmd=manifest;manifest=#manifest#;path=/">manifest</a> +<a href="?cl=tip">changelog</a> +<a href="?mf=#manifest|short#;path=/">manifest</a> </div> <h2>tags:</h2>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-confused-revert Thu Oct 27 12:26:16 2005 -0700 @@ -0,0 +1,52 @@ +#!/bin/sh + +hg init +echo foo > a +hg add a +hg commit -m "1" -d "0 0" + +echo bar > b +hg add b +hg remove a + +echo "%%% should show a removed and b added" +hg status + +echo "reverting..." +hg revert + +echo "%%% should show b unknown and a back to normal" +hg status + +rm b + +hg co -C 0 +echo foo-a > a +hg commit -m "2a" -d "0 0" + +hg co -C 0 +echo foo-b > a +hg commit -m "2b" -d "0 0" + +HGMERGE=true hg update -m 1 + +echo "%%% should show foo-b" +cat a + +echo bar > b +hg add b +rm a +hg remove a + +echo "%%% should show a removed and b added" +hg status + +echo "reverting..." +hg revert + +echo "%%% should show b unknown and a marked modified (merged)" +hg status + +echo "%%% should show foo-b" +cat a +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-confused-revert.out Thu Oct 27 12:26:16 2005 -0700 @@ -0,0 +1,17 @@ +%%% should show a removed and b added +A b +R a +reverting... +%%% should show b unknown and a back to normal +? b +merging a +%%% should show foo-b +foo-b +%%% should show a removed and b added +A b +R a +reverting... +%%% should show b unknown and a marked modified (merged) +? b +%%% should show foo-b +foo-b
--- a/tests/test-help.out Sun Oct 16 16:24:40 2005 -0700 +++ b/tests/test-help.out Thu Oct 27 12:26:16 2005 -0700 @@ -124,33 +124,66 @@ add the specified files on the next commit + Schedule files to be version controlled and added to the repository. + + The files will be added to the repository at the next commit. + + If no names are given, add all files in the current directory and + its subdirectories. + options: - -I --include include path in search - -X --exclude exclude path from search + -I --include include names matching the given patterns + -X --exclude exclude names matching the given patterns hg add: option --skjdfks not recognized hg add [OPTION]... [FILE]... add the specified files on the next commit + Schedule files to be version controlled and added to the repository. + + The files will be added to the repository at the next commit. + + If no names are given, add all files in the current directory and + its subdirectories. + options: - -I --include include path in search - -X --exclude exclude path from search + -I --include include names matching the given patterns + -X --exclude exclude names matching the given patterns hg diff [-a] [-I] [-X] [-r REV1 [-r REV2]] [FILE]... diff working directory (or selected files) + Show differences between revisions for the specified files. + + Differences between files are shown using the unified diff format. + + When two revision arguments are given, then changes are shown + between those revisions. If only one revision is specified then + that revision is compared to the working directory, and, when no + revisions are specified, the working directory files are compared + to its parent. + + Without the -a option, diff will avoid generating diffs of files + it detects as binary. With -a, diff will generate a diff anyway, + probably with undesirable results. + options: -r --rev revision -a --text treat all files as text - -I --include include path in search - -X --exclude exclude path from search + -I --include include names matching the given patterns + -X --exclude exclude names matching the given patterns hg status [OPTION]... [FILE]... show changed files in the working directory + Show changed files in the working directory. If no names are + given, all files are shown. Otherwise, only files matching the + given names are shown. + + The codes used to show the status of files are: M = modified A = added R = removed @@ -163,9 +196,9 @@ -r --removed show only removed files -u --unknown show only unknown (not tracked) files -n --no-status hide status prefix - -0 --print0 end filenames with NUL - -I --include include path in search - -X --exclude exclude path from search + -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 hg status [OPTION]... [FILE]... show changed files in the working directory
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-revert Thu Oct 27 12:26:16 2005 -0700 @@ -0,0 +1,24 @@ +#!/bin/sh + +hg init +echo 123 > a +echo 123 > c +hg add a c +hg commit -m "first" -d "0 0" a c +echo 123 > b +hg status +echo 12 > c +hg status +hg add b +hg status +hg rm a +hg status +hg revert a +hg status +hg revert b +hg status +hg revert c +hg status +ls + +true
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-revert.out Thu Oct 27 12:26:16 2005 -0700 @@ -0,0 +1,16 @@ +? b +M c +? b +M c +A b +M c +A b +R a +M c +A b +M c +? b +? b +a +b +c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-symlinks Thu Oct 27 12:26:16 2005 -0700 @@ -0,0 +1,24 @@ +#!/bin/sh +#Test bug regarding symlinks that showed up in hg 0.7 +#Author: Matthew Elder <sseses@gmail.com> + +#make and initialize repo +hg init test; cd test; + +#make a file and a symlink +touch foo; ln -s foo bar; + +#import with addremove -- symlink walking should _not_ screwup. +hg addremove + +#commit -- the symlink should _not_ appear added to dir state +hg commit -m 'initial' + +#add a new file so hg will let me commit again +touch bomb + +#again, symlink should _not_ show up on dir state +hg addremove + +#Assert screamed here before, should go by without consequence +hg commit -m 'is there a bug?'
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-symlinks.out Thu Oct 27 12:26:16 2005 -0700 @@ -0,0 +1,4 @@ +bar: unsupported file type (type is symbolic link) +adding foo +bar: unsupported file type (type is symbolic link) +adding bomb
--- a/tests/test-update-reverse Sun Oct 16 16:24:40 2005 -0700 +++ b/tests/test-update-reverse Thu Oct 27 12:26:16 2005 -0700 @@ -7,7 +7,7 @@ touch main hg add main -hg commit -t "Added main" -d "0 0" +hg commit -m "Added main" -d "0 0" hg checkout 0 echo Main should be gone
--- a/tests/test-update-reverse.out Sun Oct 16 16:24:40 2005 -0700 +++ b/tests/test-update-reverse.out Thu Oct 27 12:26:16 2005 -0700 @@ -1,4 +1,3 @@ -Warning: -t and --text is deprecated, please use -m or --message instead. Main should be gone a changeset: 3:91ebc10ed028
--- a/tests/test-walk Sun Oct 16 16:24:40 2005 -0700 +++ b/tests/test-walk Thu Oct 27 12:26:16 2005 -0700 @@ -30,7 +30,7 @@ hg debugwalk cd .. hg debugwalk -Ibeans -hg debugwalk 'mammals/../beans/b*' +hg debugwalk 'glob:mammals/../beans/b*' hg debugwalk '-X*/Procyonidae' mammals hg debugwalk path:mammals hg debugwalk .. @@ -42,8 +42,8 @@ hg debugwalk glob:\* hg debugwalk 're:.*[kb]$' hg debugwalk path:beans/black -hg debugwalk beans 'beans/*' -hg debugwalk 'j*' +hg debugwalk beans 'glob:beans/*' +hg debugwalk 'glob:j*' hg debugwalk NOEXIST mkfifo fifo hg debugwalk fifo