##// END OF EJS Templates
merge with mpm
Benoit Boissinot -
r9535:75d290db merge default
parent child Browse files
Show More
@@ -0,0 +1,218 b''
1 #!/usr/bin/env python
2
3 """\
4 Reorder a revlog (by default the the manifest file in the current
5 repository) to save space. Specifically, this topologically sorts the
6 revisions in the revlog so that revisions on the same branch are adjacent
7 as much as possible. This is a workaround for the fact that Mercurial
8 computes deltas relative to the previous revision rather than relative to a
9 parent revision. This is *not* safe to run on a changelog.
10 """
11
12 # Originally written by Benoit Boissinot <benoit.boissinot at ens-lyon.org>
13 # as a patch to rewrite-log. Cleaned up, refactored, documented, and
14 # renamed by Greg Ward <greg at gerg.ca>.
15
16 # XXX would be nice to have a way to verify the repository after shrinking,
17 # e.g. by comparing "before" and "after" states of random changesets
18 # (maybe: export before, shrink, export after, diff).
19
20 import sys, os, tempfile
21 import optparse
22 from mercurial import ui as ui_, hg, revlog, transaction, node, util
23
24 def toposort(rl):
25 write = sys.stdout.write
26
27 children = {}
28 root = []
29 # build children and roots
30 write('reading %d revs ' % len(rl))
31 try:
32 for i in rl:
33 children[i] = []
34 parents = [p for p in rl.parentrevs(i) if p != node.nullrev]
35 # in case of duplicate parents
36 if len(parents) == 2 and parents[0] == parents[1]:
37 del parents[1]
38 for p in parents:
39 assert p in children
40 children[p].append(i)
41
42 if len(parents) == 0:
43 root.append(i)
44
45 if i % 1000 == 0:
46 write('.')
47 finally:
48 write('\n')
49
50 # XXX this is a reimplementation of the 'branchsort' topo sort
51 # algorithm in hgext.convert.convcmd... would be nice not to duplicate
52 # the algorithm
53 write('sorting ...')
54 visit = root
55 ret = []
56 while visit:
57 i = visit.pop(0)
58 ret.append(i)
59 if i not in children:
60 # This only happens if some node's p1 == p2, which can
61 # happen in the manifest in certain circumstances.
62 continue
63 next = []
64 for c in children.pop(i):
65 parents_unseen = [p for p in rl.parentrevs(c)
66 if p != node.nullrev and p in children]
67 if len(parents_unseen) == 0:
68 next.append(c)
69 visit = next + visit
70 write('\n')
71 return ret
72
73 def writerevs(r1, r2, order, tr):
74 write = sys.stdout.write
75 write('writing %d revs ' % len(order))
76 try:
77 count = 0
78 for rev in order:
79 n = r1.node(rev)
80 p1, p2 = r1.parents(n)
81 l = r1.linkrev(rev)
82 t = r1.revision(n)
83 n2 = r2.addrevision(t, tr, l, p1, p2)
84
85 if count % 1000 == 0:
86 write('.')
87 count += 1
88 finally:
89 write('\n')
90
91 def report(olddatafn, newdatafn):
92 oldsize = float(os.stat(olddatafn).st_size)
93 newsize = float(os.stat(newdatafn).st_size)
94
95 # argh: have to pass an int to %d, because a float >= 2^32
96 # blows up under Python 2.5 or earlier
97 sys.stdout.write('old file size: %12d bytes (%6.1f MiB)\n'
98 % (int(oldsize), oldsize/1024/1024))
99 sys.stdout.write('new file size: %12d bytes (%6.1f MiB)\n'
100 % (int(newsize), newsize/1024/1024))
101
102 shrink_percent = (oldsize - newsize) / oldsize * 100
103 shrink_factor = oldsize / newsize
104 sys.stdout.write('shrinkage: %.1f%% (%.1fx)\n'
105 % (shrink_percent, shrink_factor))
106
107 def main():
108
109 # Unbuffer stdout for nice progress output.
110 sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
111 write = sys.stdout.write
112
113 parser = optparse.OptionParser(description=__doc__)
114 parser.add_option('-R', '--repository',
115 default=os.path.curdir,
116 metavar='REPO',
117 help='repository root directory [default: current dir]')
118 parser.add_option('--revlog',
119 metavar='FILE',
120 help='shrink FILE [default: REPO/hg/store/00manifest.i]')
121 (options, args) = parser.parse_args()
122 if args:
123 parser.error('too many arguments')
124
125 # Open the specified repository.
126 ui = ui_.ui()
127 repo = hg.repository(ui, options.repository)
128 if not repo.local():
129 parser.error('not a local repository: %s' % options.repository)
130
131 if options.revlog is None:
132 indexfn = repo.sjoin('00manifest.i')
133 else:
134 if not options.revlog.endswith('.i'):
135 parser.error('--revlog option must specify the revlog index file '
136 '(*.i), not %s' % options.revlog)
137
138 indexfn = os.path.realpath(options.revlog)
139 store = repo.sjoin('')
140 if not indexfn.startswith(store):
141 parser.error('--revlog option must specify a revlog in %s, not %s'
142 % (store, indexfn))
143
144 datafn = indexfn[:-2] + '.d'
145 if not os.path.exists(indexfn):
146 parser.error('no such file: %s' % indexfn)
147 if '00changelog' in indexfn:
148 parser.error('shrinking the changelog will corrupt your repository')
149 if not os.path.exists(datafn):
150 # This is just a lazy shortcut because I can't be bothered to
151 # handle all the special cases that entail from no .d file.
152 parser.error('%s does not exist: revlog not big enough '
153 'to be worth shrinking' % datafn)
154
155 oldindexfn = indexfn + '.old'
156 olddatafn = datafn + '.old'
157 if os.path.exists(oldindexfn) or os.path.exists(olddatafn):
158 parser.error('one or both of\n'
159 ' %s\n'
160 ' %s\n'
161 'exists from a previous run; please clean up before '
162 'running again'
163 % (oldindexfn, olddatafn))
164
165 write('shrinking %s\n' % indexfn)
166 prefix = os.path.basename(indexfn)[:-1]
167 (tmpfd, tmpindexfn) = tempfile.mkstemp(dir=os.path.dirname(indexfn),
168 prefix=prefix,
169 suffix='.i')
170 tmpdatafn = tmpindexfn[:-2] + '.d'
171 os.close(tmpfd)
172
173 r1 = revlog.revlog(util.opener(os.getcwd(), audit=False), indexfn)
174 r2 = revlog.revlog(util.opener(os.getcwd(), audit=False), tmpindexfn)
175
176 # Don't use repo.transaction(), because then things get hairy with
177 # paths: some need to be relative to .hg, and some need to be
178 # absolute. Doing it this way keeps things simple: everything is an
179 # absolute path.
180 lock = repo.lock(wait=False)
181 tr = transaction.transaction(sys.stderr.write,
182 open,
183 repo.sjoin('journal'))
184
185 try:
186 try:
187 order = toposort(r1)
188 writerevs(r1, r2, order, tr)
189 report(datafn, tmpdatafn)
190 tr.close()
191 except:
192 # Abort transaction first, so we truncate the files before
193 # deleting them.
194 tr.abort()
195 if os.path.exists(tmpindexfn):
196 os.unlink(tmpindexfn)
197 if os.path.exists(tmpdatafn):
198 os.unlink(tmpdatafn)
199 raise
200 finally:
201 lock.release()
202
203 os.link(indexfn, oldindexfn)
204 os.link(datafn, olddatafn)
205 os.rename(tmpindexfn, indexfn)
206 os.rename(tmpdatafn, datafn)
207 write('note: old revlog saved in:\n'
208 ' %s\n'
209 ' %s\n'
210 '(You can delete those files when you are satisfied that your\n'
211 'repository is still sane. '
212 'Running \'hg verify\' is strongly recommended.)\n'
213 % (oldindexfn, olddatafn))
214
215 try:
216 main()
217 except KeyboardInterrupt:
218 sys.exit("interrupted")
@@ -530,3 +530,20 b' complete -o bashdefault -o default -F _h'
530 return
530 return
531 }
531 }
532
532
533 # shelve
534 _hg_shelves()
535 {
536 local shelves="$("$hg" unshelve -l . 2>/dev/null)"
537 local IFS=$'\n'
538 COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$shelves' -- "$cur"))
539 }
540
541 _hg_cmd_shelve()
542 {
543 _hg_status "mard"
544 }
545
546 _hg_cmd_unshelve()
547 {
548 _hg_shelves
549 }
@@ -95,6 +95,6 b' COPYING'
95 -------
95 -------
96 Copyright \(C) 2005-2009 Matt Mackall.
96 Copyright \(C) 2005-2009 Matt Mackall.
97 Free use of this software is granted under the terms of the GNU General
97 Free use of this software is granted under the terms of the GNU General
98 Public License (GPL).
98 Public License version 2.
99
99
100 .. include:: common.txt
100 .. include:: common.txt
@@ -106,6 +106,6 b' COPYING'
106 This manual page is copyright 2006 Vadim Gelfer.
106 This manual page is copyright 2006 Vadim Gelfer.
107 Mercurial is copyright 2005-2009 Matt Mackall.
107 Mercurial is copyright 2005-2009 Matt Mackall.
108 Free use of this software is granted under the terms of the GNU General
108 Free use of this software is granted under the terms of the GNU General
109 Public License (GPL).
109 Public License version 2.
110
110
111 .. include:: common.txt
111 .. include:: common.txt
@@ -946,6 +946,6 b' COPYING'
946 This manual page is copyright 2005 Bryan O'Sullivan.
946 This manual page is copyright 2005 Bryan O'Sullivan.
947 Mercurial is copyright 2005-2009 Matt Mackall.
947 Mercurial is copyright 2005-2009 Matt Mackall.
948 Free use of this software is granted under the terms of the GNU General
948 Free use of this software is granted under the terms of the GNU General
949 Public License (GPL).
949 Public License version 2.
950
950
951 .. include:: common.txt
951 .. include:: common.txt
@@ -160,9 +160,8 b' def colorqseries(orig, ui, repo, *dummy,'
160 return retval
160 return retval
161
161
162 _patch_effects = { 'applied': ['blue', 'bold', 'underline'],
162 _patch_effects = { 'applied': ['blue', 'bold', 'underline'],
163 'missing': ['red', 'bold'],
163 'missing': ['red', 'bold'],
164 'unapplied': ['black', 'bold'], }
164 'unapplied': ['black', 'bold'], }
165
166 def colorwrap(orig, s):
165 def colorwrap(orig, s):
167 '''wrap ui.write for colored diff output'''
166 '''wrap ui.write for colored diff output'''
168 lines = s.split('\n')
167 lines = s.split('\n')
@@ -153,11 +153,13 b" protomap = {'http': httpcheck,"
153 def issvnurl(url):
153 def issvnurl(url):
154 try:
154 try:
155 proto, path = url.split('://', 1)
155 proto, path = url.split('://', 1)
156 path = urllib.url2pathname(path)
156 if proto == 'file':
157 path = urllib.url2pathname(path)
157 except ValueError:
158 except ValueError:
158 proto = 'file'
159 proto = 'file'
159 path = os.path.abspath(url)
160 path = os.path.abspath(url)
160 path = path.replace(os.sep, '/')
161 if proto == 'file':
162 path = path.replace(os.sep, '/')
161 check = protomap.get(proto, lambda p, p2: False)
163 check = protomap.get(proto, lambda p, p2: False)
162 while '/' in path:
164 while '/' in path:
163 if check(path, proto):
165 if check(path, proto):
@@ -42,9 +42,9 b' fast (at least faster than having to com'
42 '''
42 '''
43
43
44 from mercurial.i18n import _
44 from mercurial.i18n import _
45 from mercurial.node import short
45 from mercurial.node import short, nullid
46 from mercurial import cmdutil, util, commands
46 from mercurial import cmdutil, util, commands
47 import os, shlex, shutil, tempfile
47 import os, shlex, shutil, tempfile, re
48
48
49 def snapshot(ui, repo, files, node, tmproot):
49 def snapshot(ui, repo, files, node, tmproot):
50 '''snapshot files as of some revision
50 '''snapshot files as of some revision
@@ -69,7 +69,7 b' def snapshot(ui, repo, files, node, tmpr'
69 for fn in files:
69 for fn in files:
70 wfn = util.pconvert(fn)
70 wfn = util.pconvert(fn)
71 if not wfn in ctx:
71 if not wfn in ctx:
72 # skipping new file after a merge ?
72 # File doesn't exist; could be a bogus modify
73 continue
73 continue
74 ui.note(' %s\n' % wfn)
74 ui.note(' %s\n' % wfn)
75 dest = os.path.join(base, wfn)
75 dest = os.path.join(base, wfn)
@@ -96,52 +96,95 b' def dodiff(ui, repo, diffcmd, diffopts, '
96
96
97 revs = opts.get('rev')
97 revs = opts.get('rev')
98 change = opts.get('change')
98 change = opts.get('change')
99 args = ' '.join(diffopts)
100 do3way = '$parent2' in args
99
101
100 if revs and change:
102 if revs and change:
101 msg = _('cannot specify --rev and --change at the same time')
103 msg = _('cannot specify --rev and --change at the same time')
102 raise util.Abort(msg)
104 raise util.Abort(msg)
103 elif change:
105 elif change:
104 node2 = repo.lookup(change)
106 node2 = repo.lookup(change)
105 node1 = repo[node2].parents()[0].node()
107 node1a, node1b = repo.changelog.parents(node2)
106 else:
108 else:
107 node1, node2 = cmdutil.revpair(repo, revs)
109 node1a, node2 = cmdutil.revpair(repo, revs)
110 if not revs:
111 node1b = repo.dirstate.parents()[1]
112 else:
113 node1b = nullid
114
115 # Disable 3-way merge if there is only one parent
116 if do3way:
117 if node1b == nullid:
118 do3way = False
108
119
109 matcher = cmdutil.match(repo, pats, opts)
120 matcher = cmdutil.match(repo, pats, opts)
110 modified, added, removed = repo.status(node1, node2, matcher)[:3]
121 mod_a, add_a, rem_a = map(set, repo.status(node1a, node2, matcher)[:3])
111 if not (modified or added or removed):
122 if do3way:
112 return 0
123 mod_b, add_b, rem_b = map(set, repo.status(node1b, node2, matcher)[:3])
124 else:
125 mod_b, add_b, rem_b = set(), set(), set()
126 modadd = mod_a | add_a | mod_b | add_b
127 common = modadd | rem_a | rem_b
128 if not common:
129 return 0
113
130
114 tmproot = tempfile.mkdtemp(prefix='extdiff.')
131 tmproot = tempfile.mkdtemp(prefix='extdiff.')
115 dir2root = ''
116 try:
132 try:
117 # Always make a copy of node1
133 # Always make a copy of node1a (and node1b, if applicable)
118 dir1 = snapshot(ui, repo, modified + removed, node1, tmproot)[0]
134 dir1a_files = mod_a | rem_a | ((mod_b | add_b) - add_a)
119 changes = len(modified) + len(removed) + len(added)
135 dir1a = snapshot(ui, repo, dir1a_files, node1a, tmproot)[0]
136 if do3way:
137 dir1b_files = mod_b | rem_b | ((mod_a | add_a) - add_b)
138 dir1b = snapshot(ui, repo, dir1b_files, node1b, tmproot)[0]
139 else:
140 dir1b = None
141
142 fns_and_mtime = []
120
143
121 # If node2 in not the wc or there is >1 change, copy it
144 # If node2 in not the wc or there is >1 change, copy it
122 if node2 or changes > 1:
145 dir2root = ''
123 dir2, fns_and_mtime = snapshot(ui, repo, modified + added, node2, tmproot)
146 if node2:
147 dir2 = snapshot(ui, repo, modadd, node2, tmproot)[0]
148 elif len(common) > 1:
149 #we only actually need to get the files to copy back to the working
150 #dir in this case (because the other cases are: diffing 2 revisions
151 #or single file -- in which case the file is already directly passed
152 #to the diff tool).
153 dir2, fns_and_mtime = snapshot(ui, repo, modadd, None, tmproot)
124 else:
154 else:
125 # This lets the diff tool open the changed file directly
155 # This lets the diff tool open the changed file directly
126 dir2 = ''
156 dir2 = ''
127 dir2root = repo.root
157 dir2root = repo.root
128 fns_and_mtime = []
129
158
130 # If only one change, diff the files instead of the directories
159 # If only one change, diff the files instead of the directories
131 if changes == 1 :
160 # Handle bogus modifies correctly by checking if the files exist
132 if len(modified):
161 if len(common) == 1:
133 dir1 = os.path.join(dir1, util.localpath(modified[0]))
162 common_file = util.localpath(common.pop())
134 dir2 = os.path.join(dir2root, dir2, util.localpath(modified[0]))
163 dir1a = os.path.join(dir1a, common_file)
135 elif len(removed) :
164 if not os.path.isfile(os.path.join(tmproot, dir1a)):
136 dir1 = os.path.join(dir1, util.localpath(removed[0]))
165 dir1a = os.devnull
137 dir2 = os.devnull
166 if do3way:
138 else:
167 dir1b = os.path.join(dir1b, common_file)
139 dir1 = os.devnull
168 if not os.path.isfile(os.path.join(tmproot, dir1b)):
140 dir2 = os.path.join(dir2root, dir2, util.localpath(added[0]))
169 dir1b = os.devnull
170 dir2 = os.path.join(dir2root, dir2, common_file)
141
171
142 cmdline = ('%s %s %s %s' %
172 # Function to quote file/dir names in the argument string
143 (util.shellquote(diffcmd), ' '.join(diffopts),
173 # When not operating in 3-way mode, an empty string is returned for parent2
144 util.shellquote(dir1), util.shellquote(dir2)))
174 replace = dict(parent=dir1a, parent1=dir1a, parent2=dir1b, child=dir2)
175 def quote(match):
176 key = match.group()[1:]
177 if not do3way and key == 'parent2':
178 return ''
179 return util.shellquote(replace[key])
180
181 # Match parent2 first, so 'parent1?' will match both parent1 and parent
182 regex = '\$(parent2|parent1?|child)'
183 if not do3way and not re.search(regex, args):
184 args += ' $parent1 $child'
185 args = re.sub(regex, quote, args)
186 cmdline = util.shellquote(diffcmd) + ' ' + args
187
145 ui.debug('running %r in %s\n' % (cmdline, tmproot))
188 ui.debug('running %r in %s\n' % (cmdline, tmproot))
146 util.system(cmdline, cwd=tmproot)
189 util.system(cmdline, cwd=tmproot)
147
190
@@ -173,11 +216,11 b' def extdiff(ui, repo, *pats, **opts):'
173 that revision is compared to the working directory, and, when no
216 that revision is compared to the working directory, and, when no
174 revisions are specified, the working directory files are compared
217 revisions are specified, the working directory files are compared
175 to its parent.'''
218 to its parent.'''
176 program = opts['program'] or 'diff'
219 program = opts.get('program')
177 if opts['program']:
220 option = opts.get('option')
178 option = opts['option']
221 if not program:
179 else:
222 program = 'diff'
180 option = opts['option'] or ['-Npru']
223 option = option or ['-Npru']
181 return dodiff(ui, repo, program, option, pats, opts)
224 return dodiff(ui, repo, program, option, pats, opts)
182
225
183 cmdtable = {
226 cmdtable = {
@@ -17,28 +17,7 b' from client import client, QueryFailed'
17
17
18 def serve(ui, repo, **opts):
18 def serve(ui, repo, **opts):
19 '''start an inotify server for this repository'''
19 '''start an inotify server for this repository'''
20 timeout = opts.get('timeout')
20 server.start(ui, repo.dirstate, repo.root, opts)
21 if timeout:
22 timeout = float(timeout) * 1e3
23
24 class service(object):
25 def init(self):
26 try:
27 self.master = server.master(ui, repo.dirstate,
28 repo.root, timeout)
29 except server.AlreadyStartedException, inst:
30 raise util.Abort(str(inst))
31
32 def run(self):
33 try:
34 self.master.run()
35 finally:
36 self.master.shutdown()
37
38 service = service()
39 logfile = ui.config('inotify', 'log')
40 cmdutil.service(opts, initfn=service.init, runfn=service.run,
41 logfile=logfile)
42
21
43 def debuginotify(ui, repo, **opts):
22 def debuginotify(ui, repo, **opts):
44 '''debugging information for inotify extension
23 '''debugging information for inotify extension
@@ -34,7 +34,8 b' def start_server(function):'
34 self.ui.debug('(starting inotify server)\n')
34 self.ui.debug('(starting inotify server)\n')
35 try:
35 try:
36 try:
36 try:
37 server.start(self.ui, self.dirstate, self.root)
37 server.start(self.ui, self.dirstate, self.root,
38 dict(daemon=True, daemon_pipefds=''))
38 except server.AlreadyStartedException, inst:
39 except server.AlreadyStartedException, inst:
39 # another process may have started its own
40 # another process may have started its own
40 # inotify server while this one was starting.
41 # inotify server while this one was starting.
@@ -7,7 +7,7 b''
7 # GNU General Public License version 2, incorporated herein by reference.
7 # GNU General Public License version 2, incorporated herein by reference.
8
8
9 from mercurial.i18n import _
9 from mercurial.i18n import _
10 from mercurial import osutil, util
10 from mercurial import cmdutil, osutil, util
11 import common
11 import common
12 import errno, os, select, socket, stat, struct, sys, tempfile, time
12 import errno, os, select, socket, stat, struct, sys, tempfile, time
13
13
@@ -823,52 +823,29 b' class master(object):'
823 sys.exit(0)
823 sys.exit(0)
824 pollable.run()
824 pollable.run()
825
825
826 def start(ui, dirstate, root):
826 def start(ui, dirstate, root, opts):
827 def closefds(ignore):
827 timeout = opts.get('timeout')
828 # (from python bug #1177468)
828 if timeout:
829 # close all inherited file descriptors
829 timeout = float(timeout) * 1e3
830 # Python 2.4.1 and later use /dev/urandom to seed the random module's RNG
830
831 # a file descriptor is kept internally as os._urandomfd (created on demand
831 class service(object):
832 # the first time os.urandom() is called), and should not be closed
832 def init(self):
833 try:
834 os.urandom(4)
835 urandom_fd = getattr(os, '_urandomfd', None)
836 except AttributeError:
837 urandom_fd = None
838 ignore.append(urandom_fd)
839 for fd in range(3, 256):
840 if fd in ignore:
841 continue
842 try:
833 try:
843 os.close(fd)
834 self.master = master(ui, dirstate, root, timeout)
844 except OSError:
835 except AlreadyStartedException, inst:
845 pass
836 raise util.Abort(str(inst))
846
847 m = master(ui, dirstate, root)
848 sys.stdout.flush()
849 sys.stderr.flush()
850
837
851 pid = os.fork()
838 def run(self):
852 if pid:
839 try:
853 return pid
840 self.master.run()
854
841 finally:
855 closefds(pollable.instances.keys())
842 self.master.shutdown()
856 os.setsid()
857
858 fd = os.open('/dev/null', os.O_RDONLY)
859 os.dup2(fd, 0)
860 if fd > 0:
861 os.close(fd)
862
843
863 fd = os.open(ui.config('inotify', 'log', '/dev/null'),
844 runargs = None
864 os.O_RDWR | os.O_CREAT | os.O_TRUNC)
845 if 'inserve' not in sys.argv:
865 os.dup2(fd, 1)
846 runargs = [sys.argv[0], 'inserve', '-R', root]
866 os.dup2(fd, 2)
867 if fd > 2:
868 os.close(fd)
869
847
870 try:
848 service = service()
871 m.run()
849 logfile = ui.config('inotify', 'log')
872 finally:
850 cmdutil.service(opts, initfn=service.init, runfn=service.run,
873 m.shutdown()
851 logfile=logfile, runargs=runargs)
874 os._exit(0)
@@ -244,12 +244,14 b' class kwfilelog(filelog.filelog):'
244 return t2 != text
244 return t2 != text
245 return revlog.revlog.cmp(self, node, text)
245 return revlog.revlog.cmp(self, node, text)
246
246
247 def _status(ui, repo, kwt, unknown, *pats, **opts):
247 def _status(ui, repo, kwt, *pats, **opts):
248 '''Bails out if [keyword] configuration is not active.
248 '''Bails out if [keyword] configuration is not active.
249 Returns status of working directory.'''
249 Returns status of working directory.'''
250 if kwt:
250 if kwt:
251 match = cmdutil.match(repo, pats, opts)
251 unknown = (opts.get('unknown') or opts.get('all')
252 return repo.status(match=match, unknown=unknown, clean=True)
252 or opts.get('untracked'))
253 return repo.status(match=cmdutil.match(repo, pats, opts), clean=True,
254 unknown=unknown)
253 if ui.configitems('keyword'):
255 if ui.configitems('keyword'):
254 raise util.Abort(_('[keyword] patterns cannot match'))
256 raise util.Abort(_('[keyword] patterns cannot match'))
255 raise util.Abort(_('no [keyword] patterns configured'))
257 raise util.Abort(_('no [keyword] patterns configured'))
@@ -259,7 +261,7 b' def _kwfwrite(ui, repo, expand, *pats, *'
259 if repo.dirstate.parents()[1] != nullid:
261 if repo.dirstate.parents()[1] != nullid:
260 raise util.Abort(_('outstanding uncommitted merge'))
262 raise util.Abort(_('outstanding uncommitted merge'))
261 kwt = kwtools['templater']
263 kwt = kwtools['templater']
262 status = _status(ui, repo, kwt, False, *pats, **opts)
264 status = _status(ui, repo, kwt, *pats, **opts)
263 modified, added, removed, deleted = status[:4]
265 modified, added, removed, deleted = status[:4]
264 if modified or added or removed or deleted:
266 if modified or added or removed or deleted:
265 raise util.Abort(_('outstanding uncommitted changes'))
267 raise util.Abort(_('outstanding uncommitted changes'))
@@ -380,30 +382,32 b' def files(ui, repo, *pats, **opts):'
380 See "hg help keyword" on how to construct patterns both for
382 See "hg help keyword" on how to construct patterns both for
381 inclusion and exclusion of files.
383 inclusion and exclusion of files.
382
384
383 Use -u/--untracked to list untracked files as well.
385 With -A/--all and -v/--verbose the codes used to show the status
384
385 With -a/--all and -v/--verbose the codes used to show the status
386 of files are::
386 of files are::
387
387
388 K = keyword expansion candidate
388 K = keyword expansion candidate
389 k = keyword expansion candidate (untracked)
389 k = keyword expansion candidate (not tracked)
390 I = ignored
390 I = ignored
391 i = ignored (untracked)
391 i = ignored (not tracked)
392 '''
392 '''
393 kwt = kwtools['templater']
393 kwt = kwtools['templater']
394 status = _status(ui, repo, kwt, opts.get('untracked'), *pats, **opts)
394 status = _status(ui, repo, kwt, *pats, **opts)
395 cwd = pats and repo.getcwd() or ''
395 modified, added, removed, deleted, unknown, ignored, clean = status
396 modified, added, removed, deleted, unknown, ignored, clean = status
396 files = sorted(modified + added + clean)
397 files = []
398 if not (opts.get('unknown') or opts.get('untracked')) or opts.get('all'):
399 files = sorted(modified + added + clean)
397 wctx = repo[None]
400 wctx = repo[None]
398 kwfiles = [f for f in files if kwt.iskwfile(f, wctx.flags)]
401 kwfiles = [f for f in files if kwt.iskwfile(f, wctx.flags)]
399 kwuntracked = [f for f in unknown if kwt.iskwfile(f, wctx.flags)]
402 kwunknown = [f for f in unknown if kwt.iskwfile(f, wctx.flags)]
400 cwd = pats and repo.getcwd() or ''
403 if not opts.get('ignore') or opts.get('all'):
401 kwfstats = (not opts.get('ignore') and
404 showfiles = kwfiles, kwunknown
402 (('K', kwfiles), ('k', kwuntracked),) or ())
405 else:
406 showfiles = [], []
403 if opts.get('all') or opts.get('ignore'):
407 if opts.get('all') or opts.get('ignore'):
404 kwfstats += (('I', [f for f in files if f not in kwfiles]),
408 showfiles += ([f for f in files if f not in kwfiles],
405 ('i', [f for f in unknown if f not in kwuntracked]),)
409 [f for f in unknown if f not in kwunknown])
406 for char, filenames in kwfstats:
410 for char, filenames in zip('KkIi', showfiles):
407 fmt = (opts.get('all') or ui.verbose) and '%s %%s\n' % char or '%s\n'
411 fmt = (opts.get('all') or ui.verbose) and '%s %%s\n' % char or '%s\n'
408 for f in filenames:
412 for f in filenames:
409 ui.write(fmt % repo.pathto(f, cwd))
413 ui.write(fmt % repo.pathto(f, cwd))
@@ -545,9 +549,12 b' cmdtable = {'
545 _('hg kwexpand [OPTION]... [FILE]...')),
549 _('hg kwexpand [OPTION]... [FILE]...')),
546 'kwfiles':
550 'kwfiles':
547 (files,
551 (files,
548 [('a', 'all', None, _('show keyword status flags of all files')),
552 [('A', 'all', None, _('show keyword status flags of all files')),
549 ('i', 'ignore', None, _('show files excluded from expansion')),
553 ('i', 'ignore', None, _('show files excluded from expansion')),
550 ('u', 'untracked', None, _('additionally show untracked files')),
554 ('u', 'unknown', None, _('only show unknown (not tracked) files')),
555 ('a', 'all', None,
556 _('show keyword status flags of all files (DEPRECATED)')),
557 ('u', 'untracked', None, _('only show untracked files (DEPRECATED)')),
551 ] + commands.walkopts,
558 ] + commands.walkopts,
552 _('hg kwfiles [OPTION]... [FILE]...')),
559 _('hg kwfiles [OPTION]... [FILE]...')),
553 'kwshrink': (shrink, commands.walkopts,
560 'kwshrink': (shrink, commands.walkopts,
@@ -43,6 +43,7 b' Optional configuration items::'
43 diffstat = True # add a diffstat before the diff content
43 diffstat = True # add a diffstat before the diff content
44 sources = serve # notify if source of incoming changes in this list
44 sources = serve # notify if source of incoming changes in this list
45 # (serve == ssh or http, push, pull, bundle)
45 # (serve == ssh or http, push, pull, bundle)
46 merge = False # send notification for merges (default True)
46 [email]
47 [email]
47 from = user@host.com # email address to send as if none given
48 from = user@host.com # email address to send as if none given
48 [web]
49 [web]
@@ -111,6 +112,7 b' class notifier(object):'
111 self.test = self.ui.configbool('notify', 'test', True)
112 self.test = self.ui.configbool('notify', 'test', True)
112 self.charsets = mail._charsets(self.ui)
113 self.charsets = mail._charsets(self.ui)
113 self.subs = self.subscribers()
114 self.subs = self.subscribers()
115 self.merge = self.ui.configbool('notify', 'merge', True)
114
116
115 mapfile = self.ui.config('notify', 'style')
117 mapfile = self.ui.config('notify', 'style')
116 template = (self.ui.config('notify', hooktype) or
118 template = (self.ui.config('notify', hooktype) or
@@ -166,10 +168,13 b' class notifier(object):'
166 return self.ui.config('web', 'baseurl') + (path or self.root)
168 return self.ui.config('web', 'baseurl') + (path or self.root)
167
169
168 def node(self, ctx, **props):
170 def node(self, ctx, **props):
169 '''format one changeset.'''
171 '''format one changeset, unless it is a suppressed merge.'''
172 if not self.merge and len(ctx.parents()) > 1:
173 return False
170 self.t.show(ctx, changes=ctx.changeset(),
174 self.t.show(ctx, changes=ctx.changeset(),
171 baseurl=self.ui.config('web', 'baseurl'),
175 baseurl=self.ui.config('web', 'baseurl'),
172 root=self.repo.root, webroot=self.root, **props)
176 root=self.repo.root, webroot=self.root, **props)
177 return True
173
178
174 def skipsource(self, source):
179 def skipsource(self, source):
175 '''true if incoming changes from this source should be skipped.'''
180 '''true if incoming changes from this source should be skipped.'''
@@ -283,16 +288,29 b' def hook(ui, repo, hooktype, node=None, '
283 return
288 return
284
289
285 ui.pushbuffer()
290 ui.pushbuffer()
291 data = ''
292 count = 0
286 if hooktype == 'changegroup':
293 if hooktype == 'changegroup':
287 start, end = ctx.rev(), len(repo)
294 start, end = ctx.rev(), len(repo)
288 count = end - start
289 for rev in xrange(start, end):
295 for rev in xrange(start, end):
290 n.node(repo[rev])
296 if n.node(repo[rev]):
291 n.diff(ctx, repo['tip'])
297 count += 1
298 else:
299 data += ui.popbuffer()
300 ui.note(_('notify: suppressing notification for merge %d:%s\n') %
301 (rev, repo[rev].hex()[:12]))
302 ui.pushbuffer()
303 if count:
304 n.diff(ctx, repo['tip'])
292 else:
305 else:
293 count = 1
306 if not n.node(ctx):
294 n.node(ctx)
307 ui.popbuffer()
308 ui.note(_('notify: suppressing notification for merge %d:%s\n') %
309 (ctx.rev(), ctx.hex()[:12]))
310 return
311 count += 1
295 n.diff(ctx)
312 n.diff(ctx)
296
313
297 data = ui.popbuffer()
314 data += ui.popbuffer()
298 n.send(ctx, count, data)
315 if count:
316 n.send(ctx, count, data)
@@ -17,8 +17,8 b' msgid ""'
17 msgstr ""
17 msgstr ""
18 "Project-Id-Version: Mercurial\n"
18 "Project-Id-Version: Mercurial\n"
19 "Report-Msgid-Bugs-To: <mercurial-devel@selenic.com>\n"
19 "Report-Msgid-Bugs-To: <mercurial-devel@selenic.com>\n"
20 "POT-Creation-Date: 2009-07-20 23:05+0200\n"
20 "POT-Creation-Date: 2009-09-29 00:26+0200\n"
21 "PO-Revision-Date: 2009-07-21 00:18+0200\n"
21 "PO-Revision-Date: 2009-09-29 00:41+0200\n"
22 "Last-Translator: <mg@lazybytes.net>\n"
22 "Last-Translator: <mg@lazybytes.net>\n"
23 "Language-Team: Danish\n"
23 "Language-Team: Danish\n"
24 "MIME-Version: 1.0\n"
24 "MIME-Version: 1.0\n"
@@ -1007,7 +1007,8 b' msgstr "CVS pserver godkendelse fejlede"'
1007 #, python-format
1007 #, python-format
1008 msgid ""
1008 msgid ""
1009 "unexpected response from CVS server (expected \"Valid-requests\", but got %r)"
1009 "unexpected response from CVS server (expected \"Valid-requests\", but got %r)"
1010 msgstr "uventet svar fra CVS serveren (forventede \"Valid-requests\", men fik %r)"
1010 msgstr ""
1011 "uventet svar fra CVS serveren (forventede \"Valid-requests\", men fik %r)"
1011
1012
1012 #, python-format
1013 #, python-format
1013 msgid "%d bytes missing from remote file"
1014 msgid "%d bytes missing from remote file"
@@ -1086,6 +1087,10 b' msgstr ""'
1086 msgid "%d changeset entries\n"
1087 msgid "%d changeset entries\n"
1087 msgstr "%d ændringer\n"
1088 msgstr "%d ændringer\n"
1088
1089
1090 #, python-format
1091 msgid "darcs version 2.1 or newer needed (found %r)"
1092 msgstr ""
1093
1089 msgid "Python ElementTree module is not available"
1094 msgid "Python ElementTree module is not available"
1090 msgstr "Python ElementTree modulet er ikke tilstede"
1095 msgstr "Python ElementTree modulet er ikke tilstede"
1091
1096
@@ -1492,10 +1497,6 b' msgid "merging with %d:%s\\n"'
1492 msgstr "sammenføjer med %d:%s\n"
1497 msgstr "sammenføjer med %d:%s\n"
1493
1498
1494 #, python-format
1499 #, python-format
1495 msgid "Automated merge with %s"
1496 msgstr "Automatisk sammenføjning med %s"
1497
1498 #, python-format
1499 msgid "new changeset %d:%s merges remote changes with local\n"
1500 msgid "new changeset %d:%s merges remote changes with local\n"
1500 msgstr "ny ændring %d:%s fletter fjernændringer sammen med lokale\n"
1501 msgstr "ny ændring %d:%s fletter fjernændringer sammen med lokale\n"
1501
1502
@@ -1576,10 +1577,6 b' msgstr ""'
1576 "arbejdskopien af .hgsigs er ændret (deponer venligst .hgsigs manuelt eller "
1577 "arbejdskopien af .hgsigs er ændret (deponer venligst .hgsigs manuelt eller "
1577 "brug --force)"
1578 "brug --force)"
1578
1579
1579 #, python-format
1580 msgid "Added signature for changeset %s"
1581 msgstr "Tilføjede underskrift af ændring %s"
1582
1583 msgid "unknown signature version"
1580 msgid "unknown signature version"
1584 msgstr "ukendt underskrift-version"
1581 msgstr "ukendt underskrift-version"
1585
1582
@@ -2133,7 +2130,9 b' msgstr ""'
2133 msgid ""
2130 msgid ""
2134 "\n"
2131 "\n"
2135 "%s keywords written to %s:\n"
2132 "%s keywords written to %s:\n"
2136 msgstr "\n%s nøgleord skrevet til %s:\n"
2133 msgstr ""
2134 "\n"
2135 "%s nøgleord skrevet til %s:\n"
2137
2136
2138 msgid "unhooked all commit hooks\n"
2137 msgid "unhooked all commit hooks\n"
2139 msgstr ""
2138 msgstr ""
@@ -3789,22 +3788,22 b' msgid ""'
3789 msgstr ""
3788 msgstr ""
3790
3789
3791 msgid "cannot use both abort and continue"
3790 msgid "cannot use both abort and continue"
3792 msgstr ""
3791 msgstr "abort og continue kan ikke angives samtidig"
3793
3792
3794 msgid "cannot use collapse with continue or abort"
3793 msgid "cannot use collapse with continue or abort"
3795 msgstr ""
3794 msgstr "continue eller abort kan ikke angives samtidig med collapse"
3796
3795
3797 msgid "abort and continue do not allow specifying revisions"
3796 msgid "abort and continue do not allow specifying revisions"
3798 msgstr ""
3797 msgstr "abort og continue tillader ikke at der angives revisioner"
3799
3798
3800 msgid "cannot specify both a revision and a base"
3799 msgid "cannot specify both a revision and a base"
3801 msgstr ""
3800 msgstr "man kan ikke angive både en revision og en basis"
3802
3801
3803 msgid "nothing to rebase\n"
3802 msgid "nothing to rebase\n"
3804 msgstr ""
3803 msgstr ""
3805
3804
3806 msgid "cannot use both keepbranches and extrafn"
3805 msgid "cannot use both keepbranches and extrafn"
3807 msgstr ""
3806 msgstr "man kan ikke bruge både keepbranches og extrafn"
3808
3807
3809 msgid "rebase merging completed\n"
3808 msgid "rebase merging completed\n"
3810 msgstr ""
3809 msgstr ""
@@ -3817,7 +3816,7 b' msgstr ""'
3817
3816
3818 #, python-format
3817 #, python-format
3819 msgid "%d revisions have been skipped\n"
3818 msgid "%d revisions have been skipped\n"
3820 msgstr ""
3819 msgstr "sprang %d revisioner over\n"
3821
3820
3822 msgid " set parents\n"
3821 msgid " set parents\n"
3823 msgstr ""
3822 msgstr ""
@@ -4275,7 +4274,7 b' msgid ""'
4275 msgstr ""
4274 msgstr ""
4276
4275
4277 #, python-format
4276 #, python-format
4278 msgid "[win32mbcs] filename conversion fail with %s encoding\n"
4277 msgid "[win32mbcs] filename conversion failed with %s encoding\n"
4279 msgstr ""
4278 msgstr ""
4280
4279
4281 msgid "[win32mbcs] cannot activate on this platform.\n"
4280 msgid "[win32mbcs] cannot activate on this platform.\n"
@@ -4668,12 +4667,27 b' msgid ""'
4668 " be expensive.\n"
4667 " be expensive.\n"
4669 " "
4668 " "
4670 msgstr ""
4669 msgstr ""
4670 "tilføj alle nye filer, fjern alle manglende filer\n"
4671 "\n"
4672 " Tilføj alle nye filer og fjern alle manglende filer fra depotet.\n"
4673 "\n"
4674 " Nye filer bliver ignoreret hvis de matcher et af mønstrene i\n"
4675 " .hgignore. Som ved add, så træder disse ændringer først i kræft\n"
4676 " ved næste commit.\n"
4677 "\n"
4678 " Brug -s/--similarity tilvalget for at opdage omdøbte filer. Med en\n"
4679 " parameter større end 0 bliver hver fjernet fil sammenlignet med\n"
4680 " enhver tilføjet fil og filer der er tilstrækkelig ens bliver\n"
4681 " opført som omdøbte. Dette tilvalg tager et procenttal mellem 0\n"
4682 " (slået fra) og 100 (filer skal være identiske) som parameter. At\n"
4683 " opdage omdøbninger på denne måde kan være dyrt.\n"
4684 " "
4671
4685
4672 msgid "similarity must be a number"
4686 msgid "similarity must be a number"
4673 msgstr ""
4687 msgstr "lighedsgrad skal være et tal"
4674
4688
4675 msgid "similarity must be between 0 and 100"
4689 msgid "similarity must be between 0 and 100"
4676 msgstr ""
4690 msgstr "lighedsgrad skal være mellem 0 og 100"
4677
4691
4678 msgid ""
4692 msgid ""
4679 "show changeset information by line for each file\n"
4693 "show changeset information by line for each file\n"
@@ -4705,10 +4719,10 b' msgstr ""'
4705 " "
4719 " "
4706
4720
4707 msgid "at least one filename or pattern is required"
4721 msgid "at least one filename or pattern is required"
4708 msgstr ""
4722 msgstr "kræver mindst et filnavn eller mønster"
4709
4723
4710 msgid "at least one of -n/-c is required for -l"
4724 msgid "at least one of -n/-c is required for -l"
4711 msgstr ""
4725 msgstr "brug af -l kræver mindst en af -n/-c"
4712
4726
4713 #, python-format
4727 #, python-format
4714 msgid "%s: binary file\n"
4728 msgid "%s: binary file\n"
@@ -4744,10 +4758,10 b' msgid "no working directory: please spec'
4744 msgstr "intet arbejdskatalog: angive venligst en revision"
4758 msgstr "intet arbejdskatalog: angive venligst en revision"
4745
4759
4746 msgid "repository root cannot be destination"
4760 msgid "repository root cannot be destination"
4747 msgstr ""
4761 msgstr "depotets rod kan ikke bruges som destination"
4748
4762
4749 msgid "cannot archive plain files to stdout"
4763 msgid "cannot archive plain files to stdout"
4750 msgstr ""
4764 msgstr "flade filer kan ikke arkiveres til standarduddata"
4751
4765
4752 msgid ""
4766 msgid ""
4753 "reverse effect of earlier changeset\n"
4767 "reverse effect of earlier changeset\n"
@@ -4806,11 +4820,7 b' msgid "%s is not a parent of %s"'
4806 msgstr "%s er ikke forælder til %s"
4820 msgstr "%s er ikke forælder til %s"
4807
4821
4808 msgid "cannot use --parent on non-merge changeset"
4822 msgid "cannot use --parent on non-merge changeset"
4809 msgstr ""
4823 msgstr "kan ikke bruge --parent på en ændringer som ikke er en sammenføjning"
4810
4811 #, python-format
4812 msgid "Backed out changeset %s"
4813 msgstr ""
4814
4824
4815 #, python-format
4825 #, python-format
4816 msgid "changeset %s backs out changeset %s\n"
4826 msgid "changeset %s backs out changeset %s\n"
@@ -4824,7 +4834,7 b' msgid "the backout changeset is a new he'
4824 msgstr ""
4834 msgstr ""
4825
4835
4826 msgid "(use \"backout --merge\" if you want to auto-merge)\n"
4836 msgid "(use \"backout --merge\" if you want to auto-merge)\n"
4827 msgstr ""
4837 msgstr "(brug \"backout --merge\" hvis du vil sammenføje automatisk)\n"
4828
4838
4829 msgid ""
4839 msgid ""
4830 "subdivision search of changesets\n"
4840 "subdivision search of changesets\n"
@@ -4872,7 +4882,7 b' msgid "cannot bisect (no known bad revis'
4872 msgstr ""
4882 msgstr ""
4873
4883
4874 msgid "(use of 'hg bisect <cmd>' is deprecated)\n"
4884 msgid "(use of 'hg bisect <cmd>' is deprecated)\n"
4875 msgstr ""
4885 msgstr "(formen 'hg bisect <kommando>' er forældet)\n"
4876
4886
4877 msgid "incompatible arguments"
4887 msgid "incompatible arguments"
4878 msgstr "inkompatible argumenter"
4888 msgstr "inkompatible argumenter"
@@ -4883,7 +4893,7 b' msgstr "kan ikke finde program: %s"'
4883
4893
4884 #, python-format
4894 #, python-format
4885 msgid "failed to execute %s"
4895 msgid "failed to execute %s"
4886 msgstr ""
4896 msgstr "kunne ikke køre %s"
4887
4897
4888 #, python-format
4898 #, python-format
4889 msgid "%s killed"
4899 msgid "%s killed"
@@ -4917,10 +4927,27 b' msgid ""'
4917 " 'hg commit --close-branch' to mark this branch as closed.\n"
4927 " 'hg commit --close-branch' to mark this branch as closed.\n"
4918 " "
4928 " "
4919 msgstr ""
4929 msgstr ""
4930 "angiv eller vis navnet på den aktuelle gren\n"
4931 "\n"
4932 " Uden noget argument vises navnet på den nuværende gren. Med et\n"
4933 " argument angives arbejdskatalogets grennavn (grenen eksisterer\n"
4934 " ikke i depotet før næste deponering). Det anbefales at den primære\n"
4935 " udvikling foretages på 'default' grenen.\n"
4936 "\n"
4937 " Med mindre -f/--force bruges, så vil branch ikke lade dig bruge et\n"
4938 " grennavn som allerede eksisterer, selv hvis det er inaktivt.\n"
4939 "\n"
4940 " Brug -C/--clean for at nulstille arbejdskatalogs gren til samme\n"
4941 " gren dets forældre-ændring og derved negere end tidligere ændring.\n"
4942 "\n"
4943 " Brug kommandoen 'hg update' for at skifte til en eksisterende\n"
4944 " gren. Brug 'hg commit --close-branch' for at markere denne gren\n"
4945 " som lukket.\n"
4946 " "
4920
4947
4921 #, python-format
4948 #, python-format
4922 msgid "reset working directory to branch %s\n"
4949 msgid "reset working directory to branch %s\n"
4923 msgstr ""
4950 msgstr "nulstil arbejdskataloget til gren %s\n"
4924
4951
4925 msgid "a branch of the same name already exists (use --force to override)"
4952 msgid "a branch of the same name already exists (use --force to override)"
4926 msgstr ""
4953 msgstr ""
@@ -5003,6 +5030,22 b' msgid ""'
5003 " %p root-relative path name of file being printed\n"
5030 " %p root-relative path name of file being printed\n"
5004 " "
5031 " "
5005 msgstr ""
5032 msgstr ""
5033 "udskriv den aktuelle eller en given revision af filer\n"
5034 "\n"
5035 " Udskriver de angivne filer som de så ud ved den givne revision.\n"
5036 " Hvis der ikke angves en revision, så bruges forældre-revisionen\n"
5037 " til arbejdskataloget, eller spidsen hvis der ikke er hentet noget\n"
5038 " arbejdskatalog.\n"
5039 "\n"
5040 " Output kan gemmes i en fil hvis navn angives med et formatstreng.\n"
5041 " Reglerne for formatteringen er de samme som for export-kommandoen\n"
5042 " med følgende tilføjelser:\n"
5043 "\n"
5044 " %s grundnavn for filen som udskrives\n"
5045 " %d katalognavn for filen som blvier udskrevet\n"
5046 " eller '.' hvis filen er i katalogets rod\n"
5047 " %p rod-relativ sti for filen som bliver udkrevet\n"
5048 " "
5006
5049
5007 msgid ""
5050 msgid ""
5008 "make a copy of an existing repository\n"
5051 "make a copy of an existing repository\n"
@@ -5525,24 +5568,29 b' msgid ""'
5525 "\n"
5568 "\n"
5526 " With no arguments, show all repository head changesets.\n"
5569 " With no arguments, show all repository head changesets.\n"
5527 "\n"
5570 "\n"
5528 " Repository \"heads\" are changesets that don't have child\n"
5571 " Repository \"heads\" are changesets with no child changesets. They are\n"
5529 " changesets. They are where development generally takes place and\n"
5572 " where development generally takes place and are the usual targets\n"
5530 " are the usual targets for update and merge operations.\n"
5573 " for update and merge operations.\n"
5531 "\n"
5574 "\n"
5532 " If one or more REV is given, the \"branch heads\" will be shown for\n"
5575 " If one or more REV is given, the \"branch heads\" will be shown for\n"
5533 " the named branch associated with that revision. The name of the\n"
5576 " the named branch associated with the specified changeset(s).\n"
5534 " branch is called the revision's branch tag.\n"
5577 "\n"
5535 "\n"
5578 " Branch heads are changesets on a named branch with no descendants on\n"
5536 " Branch heads are revisions on a given named branch that do not have\n"
5579 " the same branch. A branch head could be a \"true\" (repository) head,\n"
5537 " any descendants on the same branch. A branch head could be a true head\n"
5580 " or it could be the last changeset on that branch before it was\n"
5538 " or it could be the last changeset on a branch before a new branch\n"
5581 " merged into another branch, or it could be the last changeset on the\n"
5539 " was created. If none of the branch heads are true heads, the branch\n"
5582 " branch before a new branch was created. If none of the branch heads\n"
5540 " is considered inactive. If -c/--closed is specified, also show branch\n"
5583 " are true heads, the branch is considered inactive.\n"
5541 " heads marked closed (see hg commit --close-branch).\n"
5584 "\n"
5542 "\n"
5585 " If -c/--closed is specified, also show branch heads marked closed\n"
5543 " If STARTREV is specified only those heads (or branch heads) that\n"
5586 " (see hg commit --close-branch).\n"
5544 " are descendants of STARTREV will be displayed.\n"
5587 "\n"
5545 " "
5588 " If STARTREV is specified, only those heads that are descendants of\n"
5589 " STARTREV will be displayed.\n"
5590 " "
5591 msgstr ""
5592
5593 msgid "you must specify a branch to use --closed"
5546 msgstr ""
5594 msgstr ""
5547
5595
5548 #, python-format
5596 #, python-format
@@ -6403,17 +6451,9 b' msgid "tag \'%s\' is not a local tag"'
6403 msgstr "mærkaten '%s' er ikke en lokal mærkat"
6451 msgstr "mærkaten '%s' er ikke en lokal mærkat"
6404
6452
6405 #, python-format
6453 #, python-format
6406 msgid "Removed tag %s"
6407 msgstr "Mærke %s er fjernet"
6408
6409 #, python-format
6410 msgid "tag '%s' already exists (use -f to force)"
6454 msgid "tag '%s' already exists (use -f to force)"
6411 msgstr "mærkaten '%s' eksisterer allerede (brug -f for at gennemtvinge)"
6455 msgstr "mærkaten '%s' eksisterer allerede (brug -f for at gennemtvinge)"
6412
6456
6413 #, python-format
6414 msgid "Added tag %s for changeset %s"
6415 msgstr "Tilføjede mærkat %s til ændring %s"
6416
6417 msgid ""
6457 msgid ""
6418 "list repository tags\n"
6458 "list repository tags\n"
6419 "\n"
6459 "\n"
@@ -6511,6 +6551,9 b' msgstr ""'
6511 " Se 'hg help dates' for en liste af gyldige formater til -d/--date.\n"
6551 " Se 'hg help dates' for en liste af gyldige formater til -d/--date.\n"
6512 " "
6552 " "
6513
6553
6554 msgid "cannot specify both -c/--check and -C/--clean"
6555 msgstr "man kan ikke angive både -c/--check og -C/--clean"
6556
6514 msgid "uncommitted local changes"
6557 msgid "uncommitted local changes"
6515 msgstr "udeponerede lokale ændringer"
6558 msgstr "udeponerede lokale ændringer"
6516
6559
@@ -6525,6 +6568,14 b' msgid ""'
6525 " integrity of their crosslinks and indices.\n"
6568 " integrity of their crosslinks and indices.\n"
6526 " "
6569 " "
6527 msgstr ""
6570 msgstr ""
6571 "verificer depotets integritet\n"
6572 "\n"
6573 " Verificer integreteten af det aktuelle depot.\n"
6574 "\n"
6575 " Dette vil lave en udførlig kontrol af depotets integritet.\n"
6576 " Hashværdier og tjeksummer valideres for hver indgang i\n"
6577 " historikfilen, manifæstet og fulgte filer. Desuden valideres\n"
6578 " integriteten af deres krydslinks og indekser."
6528
6579
6529 msgid "output version and copyright information"
6580 msgid "output version and copyright information"
6530 msgstr "udskriv version- og copyrightinformation"
6581 msgstr "udskriv version- og copyrightinformation"
@@ -6539,6 +6590,11 b' msgid ""'
6539 "This is free software; see the source for copying conditions. There is NO\n"
6590 "This is free software; see the source for copying conditions. There is NO\n"
6540 "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6591 "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6541 msgstr ""
6592 msgstr ""
6593 "\n"
6594 "Copyright (C) 2005-2009 Matt Mackall <mpm@selenic.com> og andre\n"
6595 "Dette er frit programmel; se kildekoden for kopieringsbetingelser. Der\n"
6596 "gives INGEN GARANTI; ikke engang for SALGBARHED eller EGNETHED FOR\n"
6597 "NOGET BESTEMT FORMÅL.\n"
6542
6598
6543 msgid "repository root directory or symbolic path name"
6599 msgid "repository root directory or symbolic path name"
6544 msgstr "depotrodfolder eller symbolsk stinavn"
6600 msgstr "depotrodfolder eller symbolsk stinavn"
@@ -6721,10 +6777,10 b' msgid "[-gbsr] [-c CMD] [REV]"'
6721 msgstr "[-gbsr] [-c KOMMANDO] [REV]"
6777 msgstr "[-gbsr] [-c KOMMANDO] [REV]"
6722
6778
6723 msgid "set branch name even if it shadows an existing branch"
6779 msgid "set branch name even if it shadows an existing branch"
6724 msgstr ""
6780 msgstr "sæt grennavnet selv hvis det overskygger en eksisterende gren"
6725
6781
6726 msgid "reset branch name to parent branch name"
6782 msgid "reset branch name to parent branch name"
6727 msgstr ""
6783 msgstr "nulstil grennavnet til forældre-grennavnet"
6728
6784
6729 msgid "[-fC] [NAME]"
6785 msgid "[-fC] [NAME]"
6730 msgstr "[-fC] [NAVN]"
6786 msgstr "[-fC] [NAVN]"
@@ -6732,8 +6788,8 b' msgstr "[-fC] [NAVN]"'
6732 msgid "show only branches that have unmerged heads"
6788 msgid "show only branches that have unmerged heads"
6733 msgstr "vil kun grene som har usammenføjne hoveder"
6789 msgstr "vil kun grene som har usammenføjne hoveder"
6734
6790
6735 msgid "show normal and closed heads"
6791 msgid "show normal and closed branches"
6736 msgstr "vis normale og lukkede hoveder"
6792 msgstr "vis normale og lukkede grene"
6737
6793
6738 msgid "[-a]"
6794 msgid "[-a]"
6739 msgstr "[-a]"
6795 msgstr "[-a]"
@@ -6847,7 +6903,7 b' msgid "[OPTION]... [-r REV1 [-r REV2]] ['
6847 msgstr "[TILVALG]... [-r REV1 [-r REV2]] [FIL]..."
6903 msgstr "[TILVALG]... [-r REV1 [-r REV2]] [FIL]..."
6848
6904
6849 msgid "diff against the second parent"
6905 msgid "diff against the second parent"
6850 msgstr ""
6906 msgstr "find forskelle i forhold til den anden forældre"
6851
6907
6852 msgid "[OPTION]... [-o OUTFILESPEC] REV..."
6908 msgid "[OPTION]... [-o OUTFILESPEC] REV..."
6853 msgstr "[TILVALG]... [-o UDFILSPECIFIKATION] REV..."
6909 msgstr "[TILVALG]... [-o UDFILSPECIFIKATION] REV..."
@@ -6879,8 +6935,11 b' msgstr "[TILVALG]... M\xc3\x98NSTER [FIL]..."'
6879 msgid "show only heads which are descendants of REV"
6935 msgid "show only heads which are descendants of REV"
6880 msgstr "vis kun hoveder som er efterkommere af REV"
6936 msgstr "vis kun hoveder som er efterkommere af REV"
6881
6937
6882 msgid "show only the active heads from open branches"
6938 msgid "show only the active branch heads from open branches"
6883 msgstr "vis kun aktive hoveder fra åbne grene"
6939 msgstr "vis kun de aktive grenhoveder fra åbne grene"
6940
6941 msgid "show normal and closed branch heads"
6942 msgstr "vis normale og lukkede grenhoveder"
6884
6943
6885 msgid "[-r STARTREV] [REV]..."
6944 msgid "[-r STARTREV] [REV]..."
6886 msgstr "[-r STARTREV] [REV]..."
6945 msgstr "[-r STARTREV] [REV]..."
@@ -7766,22 +7825,21 b' msgid ""'
7766 " Mercurial supports several ways to specify individual revisions.\n"
7825 " Mercurial supports several ways to specify individual revisions.\n"
7767 "\n"
7826 "\n"
7768 " A plain integer is treated as a revision number. Negative integers\n"
7827 " A plain integer is treated as a revision number. Negative integers\n"
7769 " are treated as topological offsets from the tip, with -1 denoting\n"
7828 " are treated as sequential offsets from the tip, with -1 denoting\n"
7770 " the tip. As such, negative numbers are only useful if you've\n"
7829 " the tip, -2 denoting the revision prior to the tip, and so forth.\n"
7771 " memorized your local tree numbers and want to save typing a single\n"
7772 " digit. This editor suggests copy and paste.\n"
7773 "\n"
7830 "\n"
7774 " A 40-digit hexadecimal string is treated as a unique revision\n"
7831 " A 40-digit hexadecimal string is treated as a unique revision\n"
7775 " identifier.\n"
7832 " identifier.\n"
7776 "\n"
7833 "\n"
7777 " A hexadecimal string less than 40 characters long is treated as a\n"
7834 " A hexadecimal string less than 40 characters long is treated as a\n"
7778 " unique revision identifier, and referred to as a short-form\n"
7835 " unique revision identifier and is referred to as a short-form\n"
7779 " identifier. A short-form identifier is only valid if it is the\n"
7836 " identifier. A short-form identifier is only valid if it is the\n"
7780 " prefix of exactly one full-length identifier.\n"
7837 " prefix of exactly one full-length identifier.\n"
7781 "\n"
7838 "\n"
7782 " Any other string is treated as a tag name, which is a symbolic\n"
7839 " Any other string is treated as a tag or branch name. A tag name is\n"
7783 " name associated with a revision identifier. Tag names may not\n"
7840 " a symbolic name associated with a revision identifier. A branch\n"
7784 " contain the \":\" character.\n"
7841 " name denotes the tipmost revision of that branch. Tag and branch\n"
7842 " names must not contain the \":\" character.\n"
7785 "\n"
7843 "\n"
7786 " The reserved name \"tip\" is a special tag that always identifies\n"
7844 " The reserved name \"tip\" is a special tag that always identifies\n"
7787 " the most recent revision.\n"
7845 " the most recent revision.\n"
@@ -7943,13 +8001,19 b' msgid ""'
7943 " - nonempty: Any text. Returns '(none)' if the string is empty.\n"
8001 " - nonempty: Any text. Returns '(none)' if the string is empty.\n"
7944 " - hgdate: Date. Returns the date as a pair of numbers:\n"
8002 " - hgdate: Date. Returns the date as a pair of numbers:\n"
7945 " \"1157407993 25200\" (Unix timestamp, timezone offset).\n"
8003 " \"1157407993 25200\" (Unix timestamp, timezone offset).\n"
7946 " - isodate: Date. Returns the date in ISO 8601 format.\n"
8004 " - isodate: Date. Returns the date in ISO 8601 format: \"2009-08-18\n"
8005 " 13:00 +0200\".\n"
8006 " - isodatesec: Date. Returns the date in ISO 8601 format, including\n"
8007 " seconds: \"2009-08-18 13:00:13 +0200\". See also the\n"
8008 " rfc3339date filter.\n"
7947 " - localdate: Date. Converts a date to local date.\n"
8009 " - localdate: Date. Converts a date to local date.\n"
7948 " - obfuscate: Any text. Returns the input text rendered as a\n"
8010 " - obfuscate: Any text. Returns the input text rendered as a\n"
7949 " sequence of XML entities.\n"
8011 " sequence of XML entities.\n"
7950 " - person: Any text. Returns the text before an email address.\n"
8012 " - person: Any text. Returns the text before an email address.\n"
7951 " - rfc822date: Date. Returns a date using the same format used\n"
8013 " - rfc822date: Date. Returns a date using the same format used\n"
7952 " in email headers.\n"
8014 " in email headers: \"Tue, 18 Aug 2009 13:00:13 +0200\".\n"
8015 " - rfc3339date: Date. Returns a date using the Internet date format\n"
8016 " specified in RFC 3339: \"2009-08-18T13:00:13+02:00\".\n"
7953 " - short: Changeset hash. Returns the short form of a changeset\n"
8017 " - short: Changeset hash. Returns the short form of a changeset\n"
7954 " hash, i.e. a 12-byte hexadecimal string.\n"
8018 " hash, i.e. a 12-byte hexadecimal string.\n"
7955 " - shortdate: Date. Returns a date like \"2006-09-18\".\n"
8019 " - shortdate: Date. Returns a date like \"2006-09-18\".\n"
@@ -9812,22 +9812,21 b' msgid ""'
9812 " Mercurial supports several ways to specify individual revisions.\n"
9812 " Mercurial supports several ways to specify individual revisions.\n"
9813 "\n"
9813 "\n"
9814 " A plain integer is treated as a revision number. Negative integers\n"
9814 " A plain integer is treated as a revision number. Negative integers\n"
9815 " are treated as topological offsets from the tip, with -1 denoting\n"
9815 " are treated as sequential offsets from the tip, with -1 denoting\n"
9816 " the tip. As such, negative numbers are only useful if you've\n"
9816 " the tip, -2 denoting the revision prior to the tip, and so forth.\n"
9817 " memorized your local tree numbers and want to save typing a single\n"
9818 " digit. This editor suggests copy and paste.\n"
9819 "\n"
9817 "\n"
9820 " A 40-digit hexadecimal string is treated as a unique revision\n"
9818 " A 40-digit hexadecimal string is treated as a unique revision\n"
9821 " identifier.\n"
9819 " identifier.\n"
9822 "\n"
9820 "\n"
9823 " A hexadecimal string less than 40 characters long is treated as a\n"
9821 " A hexadecimal string less than 40 characters long is treated as a\n"
9824 " unique revision identifier, and referred to as a short-form\n"
9822 " unique revision identifier and is referred to as a short-form\n"
9825 " identifier. A short-form identifier is only valid if it is the\n"
9823 " identifier. A short-form identifier is only valid if it is the\n"
9826 " prefix of exactly one full-length identifier.\n"
9824 " prefix of exactly one full-length identifier.\n"
9827 "\n"
9825 "\n"
9828 " Any other string is treated as a tag name, which is a symbolic\n"
9826 " Any other string is treated as a tag or branch name. A tag name is\n"
9829 " name associated with a revision identifier. Tag names may not\n"
9827 " a symbolic name associated with a revision identifier. A branch\n"
9830 " contain the \":\" character.\n"
9828 " name denotes the tipmost revision of that branch. Tag and branch\n"
9829 " names must not contain the \":\" character.\n"
9831 "\n"
9830 "\n"
9832 " The reserved name \"tip\" is a special tag that always identifies\n"
9831 " The reserved name \"tip\" is a special tag that always identifies\n"
9833 " the most recent revision.\n"
9832 " the most recent revision.\n"
@@ -9846,23 +9845,22 b' msgstr ""'
9846 " individuais.\n"
9845 " individuais.\n"
9847 "\n"
9846 "\n"
9848 " Um simples inteiro é tratado como um número de revisão. Inteiros\n"
9847 " Um simples inteiro é tratado como um número de revisão. Inteiros\n"
9849 " negativos são tratados como contados topologicamente a partir da\n"
9848 " negativos são contados a partir da tip, com -1 denotando a tip,\n"
9850 " tip, com -1 denotando a tip. Assim, números negativos são úteis\n"
9849 " -2 denotando a revisão anterior à tip, e assim por diante.\n"
9851 " apenas se você memorizou os números de sua árvore local e quiser\n"
9852 " evitar digitar um único caractere. Este editor sugere copiar e\n"
9853 " colar.\n"
9854 "\n"
9850 "\n"
9855 " Uma string hexadecimal de 40 dígitos é tratada como um\n"
9851 " Uma string hexadecimal de 40 dígitos é tratada como um\n"
9856 " identificador único de revisão.\n"
9852 " identificador único de revisão.\n"
9857 "\n"
9853 "\n"
9858 " Uma string hexadecimal de menos de 40 caracteres é tratada como\n"
9854 " Uma string hexadecimal de menos de 40 caracteres é tratada como\n"
9859 " um identificador único de revisão, e referida como um\n"
9855 " um identificador único de revisão, chamado de identificador\n"
9860 " identificador curto. Um identificador curto é válido apenas se\n"
9856 " curto. Um identificador curto é válido apenas se for o prefixo\n"
9861 " for o prefixo de um identificador completo.\n"
9857 " de um identificador completo.\n"
9862 "\n"
9858 "\n"
9863 " Qualquer outra string é tratada como um nome de etiqueta, que é\n"
9859 " Qualquer outra string é tratada como um nome de etiqueta ou\n"
9864 " um nome simbólico associado a um identificador de revisão. Nomes\n"
9860 " ramo. Um nome de etiqueta é um nome simbólico associado a um\n"
9865 " de etiqueta não podem conter o caractere \":\".\n"
9861 " identificador de revisão. Um nome de ramo denota a revisão mais\n"
9862 " recente de tal ramo. Nomes de etiqueta ou de ramo não podem\n"
9863 " conter o caractere \":\".\n"
9866 "\n"
9864 "\n"
9867 " O nome reservado \"tip\" é uma etiqueta especial que sempre\n"
9865 " O nome reservado \"tip\" é uma etiqueta especial que sempre\n"
9868 " identifica a revisão mais recente.\n"
9866 " identifica a revisão mais recente.\n"
@@ -10076,13 +10074,19 b' msgid ""'
10076 " - nonempty: Any text. Returns '(none)' if the string is empty.\n"
10074 " - nonempty: Any text. Returns '(none)' if the string is empty.\n"
10077 " - hgdate: Date. Returns the date as a pair of numbers:\n"
10075 " - hgdate: Date. Returns the date as a pair of numbers:\n"
10078 " \"1157407993 25200\" (Unix timestamp, timezone offset).\n"
10076 " \"1157407993 25200\" (Unix timestamp, timezone offset).\n"
10079 " - isodate: Date. Returns the date in ISO 8601 format.\n"
10077 " - isodate: Date. Returns the date in ISO 8601 format: \"2009-08-18\n"
10078 " 13:00 +0200\".\n"
10079 " - isodatesec: Date. Returns the date in ISO 8601 format, including\n"
10080 " seconds: \"2009-08-18 13:00:13 +0200\". See also the\n"
10081 " rfc3339date filter.\n"
10080 " - localdate: Date. Converts a date to local date.\n"
10082 " - localdate: Date. Converts a date to local date.\n"
10081 " - obfuscate: Any text. Returns the input text rendered as a\n"
10083 " - obfuscate: Any text. Returns the input text rendered as a\n"
10082 " sequence of XML entities.\n"
10084 " sequence of XML entities.\n"
10083 " - person: Any text. Returns the text before an email address.\n"
10085 " - person: Any text. Returns the text before an email address.\n"
10084 " - rfc822date: Date. Returns a date using the same format used\n"
10086 " - rfc822date: Date. Returns a date using the same format used\n"
10085 " in email headers.\n"
10087 " in email headers: \"Tue, 18 Aug 2009 13:00:13 +0200\".\n"
10088 " - rfc3339date: Date. Returns a date using the Internet date format\n"
10089 " specified in RFC 3339: \"2009-08-18T13:00:13+02:00\".\n"
10086 " - short: Changeset hash. Returns the short form of a changeset\n"
10090 " - short: Changeset hash. Returns the short form of a changeset\n"
10087 " hash, i.e. a 12-byte hexadecimal string.\n"
10091 " hash, i.e. a 12-byte hexadecimal string.\n"
10088 " - shortdate: Date. Returns a date like \"2006-09-18\".\n"
10092 " - shortdate: Date. Returns a date like \"2006-09-18\".\n"
@@ -10186,14 +10190,17 b' msgstr ""'
10186 " - nonempty: Qualquer texto. Devolve (none) se o texto for vazio.\n"
10190 " - nonempty: Qualquer texto. Devolve (none) se o texto for vazio.\n"
10187 " - hgdate: Data. Devolve a data como um par de números:\n"
10191 " - hgdate: Data. Devolve a data como um par de números:\n"
10188 " \"1157407993 25200\" (timestamp Unix, defasagem de fuso)\n"
10192 " \"1157407993 25200\" (timestamp Unix, defasagem de fuso)\n"
10189 " - isodate: Data. Devolve a data em formato ISO 8601.\n"
10193 " - isodate: Data. Devolve a data em formato ISO 8601: \"2009-08-18\n"
10194 " 13:00 +0200\".\n"
10190 " - localdate: Data. Converte para data local.\n"
10195 " - localdate: Data. Converte para data local.\n"
10191 " - obfuscate: Qualquer texto. Devolve o texto de entrada\n"
10196 " - obfuscate: Qualquer texto. Devolve o texto de entrada\n"
10192 " renderizado como uma seqüência de entidades XML.\n"
10197 " renderizado como uma seqüência de entidades XML.\n"
10193 " - person: Qualquer texto. Devolve o texto antes de um endereço\n"
10198 " - person: Qualquer texto. Devolve o texto antes de um endereço\n"
10194 " de e-mail.\n"
10199 " de e-mail.\n"
10195 " - rfc822date: Data. Devolve uma data usando o mesmo formato\n"
10200 " - rfc822date: Data. Devolve uma data usando o mesmo formato utilizado\n"
10196 " utilizado em cabeçalhos de e-mail.\n"
10201 " em cabeçalhos de e-mail: \"Tue, 18 Aug 2009 13:00:13 +0200\".\n"
10202 " - rfc3339date: Data. Devolve uma data usando o formato de data da\n"
10203 " Internet especificado na RFC 3339: \"2009-08-18T13:00:13+02:00\".\n"
10197 " - short: Hash do changeset. Devolve a forma curta do hash de\n"
10204 " - short: Hash do changeset. Devolve a forma curta do hash de\n"
10198 " um changeset, ou seja, uma string hexadecimal de 12 bytes.\n"
10205 " um changeset, ou seja, uma string hexadecimal de 12 bytes.\n"
10199 " - shortdate: Data. Devolve uma data como \"2006-09-18\".\n"
10206 " - shortdate: Data. Devolve uma data como \"2006-09-18\".\n"
@@ -546,24 +546,26 b' def copy(ui, repo, pats, opts, rename=Fa'
546
546
547 return errors
547 return errors
548
548
549 def service(opts, parentfn=None, initfn=None, runfn=None, logfile=None):
549 def service(opts, parentfn=None, initfn=None, runfn=None, logfile=None,
550 runargs=None):
550 '''Run a command as a service.'''
551 '''Run a command as a service.'''
551
552
552 if opts['daemon'] and not opts['daemon_pipefds']:
553 if opts['daemon'] and not opts['daemon_pipefds']:
553 rfd, wfd = os.pipe()
554 rfd, wfd = os.pipe()
554 args = sys.argv[:]
555 if not runargs:
555 args.append('--daemon-pipefds=%d,%d' % (rfd, wfd))
556 runargs = sys.argv[:]
557 runargs.append('--daemon-pipefds=%d,%d' % (rfd, wfd))
556 # Don't pass --cwd to the child process, because we've already
558 # Don't pass --cwd to the child process, because we've already
557 # changed directory.
559 # changed directory.
558 for i in xrange(1,len(args)):
560 for i in xrange(1,len(runargs)):
559 if args[i].startswith('--cwd='):
561 if runargs[i].startswith('--cwd='):
560 del args[i]
562 del runargs[i]
561 break
563 break
562 elif args[i].startswith('--cwd'):
564 elif runargs[i].startswith('--cwd'):
563 del args[i:i+2]
565 del runargs[i:i+2]
564 break
566 break
565 pid = os.spawnvp(os.P_NOWAIT | getattr(os, 'P_DETACH', 0),
567 pid = os.spawnvp(os.P_NOWAIT | getattr(os, 'P_DETACH', 0),
566 args[0], args)
568 runargs[0], runargs)
567 os.close(wfd)
569 os.close(wfd)
568 os.read(rfd, 1)
570 os.read(rfd, 1)
569 if parentfn:
571 if parentfn:
@@ -1356,23 +1356,25 b' def heads(ui, repo, *branchrevs, **opts)'
1356
1356
1357 With no arguments, show all repository head changesets.
1357 With no arguments, show all repository head changesets.
1358
1358
1359 Repository "heads" are changesets that don't have child
1359 Repository "heads" are changesets with no child changesets. They are
1360 changesets. They are where development generally takes place and
1360 where development generally takes place and are the usual targets
1361 are the usual targets for update and merge operations.
1361 for update and merge operations.
1362
1362
1363 If one or more REV is given, the "branch heads" will be shown for
1363 If one or more REV is given, the "branch heads" will be shown for
1364 the named branch associated with that revision. The name of the
1364 the named branch associated with the specified changeset(s).
1365 branch is called the revision's branch tag.
1365
1366
1366 Branch heads are changesets on a named branch with no descendants on
1367 Branch heads are revisions on a given named branch that do not have
1367 the same branch. A branch head could be a "true" (repository) head,
1368 any descendants on the same branch. A branch head could be a true head
1368 or it could be the last changeset on that branch before it was
1369 or it could be the last changeset on a branch before a new branch
1369 merged into another branch, or it could be the last changeset on the
1370 was created. If none of the branch heads are true heads, the branch
1370 branch before a new branch was created. If none of the branch heads
1371 is considered inactive. If -c/--closed is specified, also show branch
1371 are true heads, the branch is considered inactive.
1372 heads marked closed (see hg commit --close-branch).
1372
1373
1373 If -c/--closed is specified, also show branch heads marked closed
1374 If STARTREV is specified only those heads (or branch heads) that
1374 (see hg commit --close-branch).
1375 are descendants of STARTREV will be displayed.
1375
1376 If STARTREV is specified, only those heads that are descendants of
1377 STARTREV will be displayed.
1376 """
1378 """
1377 if opts.get('rev'):
1379 if opts.get('rev'):
1378 start = repo.lookup(opts['rev'])
1380 start = repo.lookup(opts['rev'])
@@ -38,6 +38,9 b' def _decdirs(dirs, path):'
38 class dirstate(object):
38 class dirstate(object):
39
39
40 def __init__(self, opener, ui, root):
40 def __init__(self, opener, ui, root):
41 '''Create a new dirstate object. opener is an open()-like callable
42 that can be used to open the dirstate file; root is the root of the
43 directory tracked by the dirstate.'''
41 self._opener = opener
44 self._opener = opener
42 self._root = root
45 self._root = root
43 self._rootdir = os.path.join(root, '')
46 self._rootdir = os.path.join(root, '')
@@ -47,6 +50,8 b' class dirstate(object):'
47
50
48 @propertycache
51 @propertycache
49 def _map(self):
52 def _map(self):
53 '''Return the dirstate contents as a map from filename to
54 (state, mode, size, time).'''
50 self._read()
55 self._read()
51 return self._map
56 return self._map
52
57
@@ -169,12 +174,14 b' class dirstate(object):'
169 return path
174 return path
170
175
171 def __getitem__(self, key):
176 def __getitem__(self, key):
172 ''' current states:
177 '''Return the current state of key (a filename) in the dirstate.
173 n normal
178 States are:
174 m needs merging
179 n normal
175 r marked for removal
180 m needs merging
176 a marked for addition
181 r marked for removal
177 ? not tracked'''
182 a marked for addition
183 ? not tracked
184 '''
178 return self._map.get(key, ("?",))[0]
185 return self._map.get(key, ("?",))[0]
179
186
180 def __contains__(self, key):
187 def __contains__(self, key):
@@ -373,13 +380,9 b' class dirstate(object):'
373 return
380 return
374 st = self._opener("dirstate", "w", atomictemp=True)
381 st = self._opener("dirstate", "w", atomictemp=True)
375
382
376 try:
383 # use the modification time of the newly created temporary file as the
377 gran = int(self._ui.config('dirstate', 'granularity', 1))
384 # filesystem's notion of 'now'
378 except ValueError:
385 now = int(util.fstat(st).st_mtime)
379 gran = 1
380 if gran > 0:
381 hlimit = util.fstat(st).st_mtime
382 llimit = hlimit - gran
383
386
384 cs = cStringIO.StringIO()
387 cs = cStringIO.StringIO()
385 copymap = self._copymap
388 copymap = self._copymap
@@ -389,9 +392,19 b' class dirstate(object):'
389 for f, e in self._map.iteritems():
392 for f, e in self._map.iteritems():
390 if f in copymap:
393 if f in copymap:
391 f = "%s\0%s" % (f, copymap[f])
394 f = "%s\0%s" % (f, copymap[f])
392 if gran > 0 and e[0] == 'n' and llimit < e[3] <= hlimit:
395
393 # file was updated too recently, ignore stat data
396 if e[0] == 'n' and e[3] == now:
394 e = (e[0], 0, -1, -1)
397 # The file was last modified "simultaneously" with the current
398 # write to dirstate (i.e. within the same second for file-
399 # systems with a granularity of 1 sec). This commonly happens
400 # for at least a couple of files on 'update'.
401 # The user could change the file without changing its size
402 # within the same second. Invalidate the file's stat data in
403 # dirstate, forcing future 'status' calls to compare the
404 # contents of the file. This prevents mistakenly treating such
405 # files as clean.
406 e = (e[0], 0, -1, -1) # mark entry as 'unset'
407
395 e = pack(_format, e[0], e[1], e[2], e[3], len(f))
408 e = pack(_format, e[0], e[1], e[2], e[3], len(f))
396 write(e)
409 write(e)
397 write(f)
410 write(f)
@@ -411,11 +424,11 b' class dirstate(object):'
411
424
412 def walk(self, match, unknown, ignored):
425 def walk(self, match, unknown, ignored):
413 '''
426 '''
414 walk recursively through the directory tree, finding all files
427 Walk recursively through the directory tree, finding all files
415 matched by the match function
428 matched by match.
416
429
417 results are yielded in a tuple (filename, stat), where stat
430 Return a dict mapping filename to stat-like object (either
418 and st is the stat result if the file was found in the directory.
431 mercurial.osutil.stat instance or return value of os.stat()).
419 '''
432 '''
420
433
421 def fwarn(f, msg):
434 def fwarn(f, msg):
@@ -553,12 +566,38 b' class dirstate(object):'
553 return results
566 return results
554
567
555 def status(self, match, ignored, clean, unknown):
568 def status(self, match, ignored, clean, unknown):
569 '''Determine the status of the working copy relative to the
570 dirstate and return a tuple of lists (unsure, modified, added,
571 removed, deleted, unknown, ignored, clean), where:
572
573 unsure:
574 files that might have been modified since the dirstate was
575 written, but need to be read to be sure (size is the same
576 but mtime differs)
577 modified:
578 files that have definitely been modified since the dirstate
579 was written (different size or mode)
580 added:
581 files that have been explicitly added with hg add
582 removed:
583 files that have been explicitly removed with hg remove
584 deleted:
585 files that have been deleted through other means ("missing")
586 unknown:
587 files not in the dirstate that are not ignored
588 ignored:
589 files not in the dirstate that are ignored
590 (by _dirignore())
591 clean:
592 files that have definitely not been modified since the
593 dirstate was written
594 '''
556 listignored, listclean, listunknown = ignored, clean, unknown
595 listignored, listclean, listunknown = ignored, clean, unknown
557 lookup, modified, added, unknown, ignored = [], [], [], [], []
596 lookup, modified, added, unknown, ignored = [], [], [], [], []
558 removed, deleted, clean = [], [], []
597 removed, deleted, clean = [], [], []
559
598
560 dmap = self._map
599 dmap = self._map
561 ladd = lookup.append
600 ladd = lookup.append # aka "unsure"
562 madd = modified.append
601 madd = modified.append
563 aadd = added.append
602 aadd = added.append
564 uadd = unknown.append
603 uadd = unknown.append
@@ -165,17 +165,11 b' def testpid(pid):'
165 return inst.errno != errno.ESRCH
165 return inst.errno != errno.ESRCH
166
166
167 def explain_exit(code):
167 def explain_exit(code):
168 """return a 2-tuple (desc, code) describing a process's status"""
168 """return a 2-tuple (desc, code) describing a subprocess status
169 if os.WIFEXITED(code):
169 (codes from kill are negative - not os.system/wait encoding)"""
170 val = os.WEXITSTATUS(code)
170 if code >= 0:
171 return _("exited with status %d") % val, val
171 return _("exited with status %d") % code, code
172 elif os.WIFSIGNALED(code):
172 return _("killed by signal %d") % -code, -code
173 val = os.WTERMSIG(code)
174 return _("killed by signal %d") % val, val
175 elif os.WIFSTOPPED(code):
176 val = os.WSTOPSIG(code)
177 return _("stopped by signal %d") % val, val
178 raise ValueError(_("invalid exit code"))
179
173
180 def isowner(st):
174 def isowner(st):
181 """Return True if the stat object st is from the current user."""
175 """Return True if the stat object st is from the current user."""
@@ -48,8 +48,7 b' def stream_out(repo, untrusted=False):'
48 try:
48 try:
49 repo.ui.debug('scanning\n')
49 repo.ui.debug('scanning\n')
50 for name, ename, size in repo.store.walk():
50 for name, ename, size in repo.store.walk():
51 # for backwards compat, name was partially encoded
51 entries.append((name, size))
52 entries.append((store.encodedir(name), size))
53 total_bytes += size
52 total_bytes += size
54 finally:
53 finally:
55 lock.release()
54 lock.release()
@@ -62,6 +61,7 b' def stream_out(repo, untrusted=False):'
62 yield '%d %d\n' % (len(entries), total_bytes)
61 yield '%d %d\n' % (len(entries), total_bytes)
63 for name, size in entries:
62 for name, size in entries:
64 repo.ui.debug('sending %s (%d bytes)\n' % (name, size))
63 repo.ui.debug('sending %s (%d bytes)\n' % (name, size))
65 yield '%s\0%d\n' % (name, size)
64 # partially encode name over the wire for backwards compat
65 yield '%s\0%d\n' % (store.encodedir(name), size)
66 for chunk in util.filechunkiter(repo.sopener(name), limit=size):
66 for chunk in util.filechunkiter(repo.sopener(name), limit=size):
67 yield chunk
67 yield chunk
@@ -167,7 +167,7 b' class hgsubrepo(object):'
167 self._repo.ui.note(_('removing subrepo %s\n') % self._path)
167 self._repo.ui.note(_('removing subrepo %s\n') % self._path)
168 hg.clean(self._repo, node.nullid, False)
168 hg.clean(self._repo, node.nullid, False)
169
169
170 def get(self, state):
170 def _get(self, state):
171 source, revision = state
171 source, revision = state
172 try:
172 try:
173 self._repo.lookup(revision)
173 self._repo.lookup(revision)
@@ -178,9 +178,13 b' class hgsubrepo(object):'
178 other = hg.repository(self._repo.ui, srcurl)
178 other = hg.repository(self._repo.ui, srcurl)
179 self._repo.pull(other)
179 self._repo.pull(other)
180
180
181 def get(self, state):
182 self._get(state)
183 source, revision = state
181 hg.clean(self._repo, revision, False)
184 hg.clean(self._repo, revision, False)
182
185
183 def merge(self, state):
186 def merge(self, state):
187 self._get(state)
184 hg.merge(self._repo, state[1], remind=False)
188 hg.merge(self._repo, state[1], remind=False)
185
189
186 def push(self, force):
190 def push(self, force):
@@ -357,41 +357,26 b' def system(cmd, environ={}, cwd=None, on'
357 if val is True:
357 if val is True:
358 return '1'
358 return '1'
359 return str(val)
359 return str(val)
360 oldenv = {}
361 for k in environ:
362 oldenv[k] = os.environ.get(k)
363 if cwd is not None:
364 oldcwd = os.getcwd()
365 origcmd = cmd
360 origcmd = cmd
366 if os.name == 'nt':
361 if os.name == 'nt':
367 cmd = '"%s"' % cmd
362 cmd = '"%s"' % cmd
368 try:
363 env = dict(os.environ)
369 for k, v in environ.iteritems():
364 env.update((k, py2shell(v)) for k, v in environ.iteritems())
370 os.environ[k] = py2shell(v)
365 env['HG'] = hgexecutable()
371 os.environ['HG'] = hgexecutable()
366 rc = subprocess.call(cmd, shell=True, close_fds=closefds,
372 if cwd is not None and oldcwd != cwd:
367 env=env, cwd=cwd)
373 os.chdir(cwd)
368 if sys.platform == 'OpenVMS' and rc & 1:
374 rc = os.system(cmd)
369 rc = 0
375 if sys.platform == 'OpenVMS' and rc & 1:
370 if rc and onerr:
376 rc = 0
371 errmsg = '%s %s' % (os.path.basename(origcmd.split(None, 1)[0]),
377 if rc and onerr:
372 explain_exit(rc)[0])
378 errmsg = '%s %s' % (os.path.basename(origcmd.split(None, 1)[0]),
373 if errprefix:
379 explain_exit(rc)[0])
374 errmsg = '%s: %s' % (errprefix, errmsg)
380 if errprefix:
375 try:
381 errmsg = '%s: %s' % (errprefix, errmsg)
376 onerr.warn(errmsg + '\n')
382 try:
377 except AttributeError:
383 onerr.warn(errmsg + '\n')
378 raise onerr(errmsg)
384 except AttributeError:
379 return rc
385 raise onerr(errmsg)
386 return rc
387 finally:
388 for k, v in oldenv.iteritems():
389 if v is None:
390 del os.environ[k]
391 else:
392 os.environ[k] = v
393 if cwd is not None and oldcwd != cwd:
394 os.chdir(oldcwd)
395
380
396 def checksignature(func):
381 def checksignature(func):
397 '''wrap a function with code to check for calling errors'''
382 '''wrap a function with code to check for calling errors'''
@@ -1280,9 +1265,12 b' def wrap(line, hangindent, width=None):'
1280 padding = '\n' + ' ' * hangindent
1265 padding = '\n' + ' ' * hangindent
1281 # To avoid corrupting multi-byte characters in line, we must wrap
1266 # To avoid corrupting multi-byte characters in line, we must wrap
1282 # a Unicode string instead of a bytestring.
1267 # a Unicode string instead of a bytestring.
1283 u = line.decode(encoding.encoding)
1268 try:
1284 w = padding.join(textwrap.wrap(u, width=width - hangindent))
1269 u = line.decode(encoding.encoding)
1285 return w.encode(encoding.encoding)
1270 w = padding.join(textwrap.wrap(u, width=width - hangindent))
1271 return w.encode(encoding.encoding)
1272 except UnicodeDecodeError:
1273 return padding.join(textwrap.wrap(line, width=width - hangindent))
1286
1274
1287 def iterlines(iterator):
1275 def iterlines(iterator):
1288 for chunk in iterator:
1276 for chunk in iterator:
@@ -5,6 +5,11 b' cp "$TESTDIR"/printenv.py .'
5 hg init test
5 hg init test
6 cd test
6 cd test
7 echo foo>foo
7 echo foo>foo
8 mkdir foo.d foo.d/bAr.hg.d foo.d/baR.d.hg
9 echo foo>foo.d/foo
10 echo bar>foo.d/bAr.hg.d/BaR
11 echo bar>foo.d/baR.d.hg/bAR
12
8 hg commit -A -m 1
13 hg commit -A -m 1
9 hg --config server.uncompressed=True serve -p $HGPORT -d --pid-file=../hg1.pid
14 hg --config server.uncompressed=True serve -p $HGPORT -d --pid-file=../hg1.pid
10 hg serve -p $HGPORT1 -d --pid-file=../hg2.pid
15 hg serve -p $HGPORT1 -d --pid-file=../hg2.pid
@@ -1,4 +1,7 b''
1 adding foo
1 adding foo
2 adding foo.d/bAr.hg.d/BaR
3 adding foo.d/baR.d.hg/bAR
4 adding foo.d/foo
2 abort: cannot start server at ':20060':
5 abort: cannot start server at ':20060':
3 % clone via stream
6 % clone via stream
4 streaming all changes
7 streaming all changes
@@ -10,31 +13,31 b' checking changesets'
10 checking manifests
13 checking manifests
11 crosschecking files in changesets and manifests
14 crosschecking files in changesets and manifests
12 checking files
15 checking files
13 1 files, 1 changesets, 1 total revisions
16 4 files, 1 changesets, 4 total revisions
14 % try to clone via stream, should use pull instead
17 % try to clone via stream, should use pull instead
15 requesting all changes
18 requesting all changes
16 adding changesets
19 adding changesets
17 adding manifests
20 adding manifests
18 adding file changes
21 adding file changes
19 added 1 changesets with 1 changes to 1 files
22 added 1 changesets with 4 changes to 4 files
20 updating working directory
23 updating working directory
21 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
24 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
22 % clone via pull
25 % clone via pull
23 requesting all changes
26 requesting all changes
24 adding changesets
27 adding changesets
25 adding manifests
28 adding manifests
26 adding file changes
29 adding file changes
27 added 1 changesets with 1 changes to 1 files
30 added 1 changesets with 4 changes to 4 files
28 updating working directory
31 updating working directory
29 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
32 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
30 checking changesets
33 checking changesets
31 checking manifests
34 checking manifests
32 crosschecking files in changesets and manifests
35 crosschecking files in changesets and manifests
33 checking files
36 checking files
34 1 files, 1 changesets, 1 total revisions
37 4 files, 1 changesets, 4 total revisions
35 adding bar
38 adding bar
36 % pull
39 % pull
37 changegroup hook: HG_NODE=cfbd11a1fa315300a080c3de8fe36b0fc5820acf HG_SOURCE=pull HG_URL=http://localhost/
40 changegroup hook: HG_NODE=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_SOURCE=pull HG_URL=http://localhost/
38 pulling from http://localhost/
41 pulling from http://localhost/
39 searching for changes
42 searching for changes
40 adding changesets
43 adding changesets
@@ -1,5 +1,5 b''
1 % fail
1 % fail
2 could not talk to new inotify server: No such file or directory
2 abort: could not start server: File exists
3 abort: could not start server: File exists
3 abort: could not start server: File exists
4 % inserve
4 % inserve
5 % status
5 % status
@@ -48,6 +48,11 b" echo 'ignore $Id$' > b"
48 echo % cat
48 echo % cat
49 cat a b
49 cat a b
50
50
51 echo % no kwfiles
52 hg kwfiles
53 echo % untracked candidates
54 hg -v kwfiles --unknown
55
51 echo % addremove
56 echo % addremove
52 hg addremove
57 hg addremove
53 echo % status
58 echo % status
@@ -162,6 +167,10 b' hg status'
162
167
163 echo % kwfiles
168 echo % kwfiles
164 hg kwfiles
169 hg kwfiles
170 echo % ignored files
171 hg -v kwfiles --ignore
172 echo % all files
173 hg kwfiles --all
165
174
166 echo % diff --rev
175 echo % diff --rev
167 hg diff --rev 1 | grep -v 'b/c'
176 hg diff --rev 1 | grep -v 'b/c'
@@ -42,6 +42,9 b' expand $Id$'
42 do not process $Id:
42 do not process $Id:
43 xxx $
43 xxx $
44 ignore $Id$
44 ignore $Id$
45 % no kwfiles
46 % untracked candidates
47 k a
45 % addremove
48 % addremove
46 adding a
49 adding a
47 adding b
50 adding b
@@ -181,6 +184,14 b' xxx $'
181 % kwfiles
184 % kwfiles
182 a
185 a
183 c
186 c
187 % ignored files
188 I b
189 I sym
190 % all files
191 K a
192 K c
193 I b
194 I sym
184 % diff --rev
195 % diff --rev
185 diff -r ef63ca68695b c
196 diff -r ef63ca68695b c
186 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
197 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -35,6 +35,7 b' Optional configuration items:'
35 diffstat = True # add a diffstat before the diff content
35 diffstat = True # add a diffstat before the diff content
36 sources = serve # notify if source of incoming changes in this list
36 sources = serve # notify if source of incoming changes in this list
37 # (serve == ssh or http, push, pull, bundle)
37 # (serve == ssh or http, push, pull, bundle)
38 merge = False # send notification for merges (default True)
38 [email]
39 [email]
39 from = user@host.com # email address to send as if none given
40 from = user@host.com # email address to send as if none given
40 [web]
41 [web]
General Comments 0
You need to be logged in to leave comments. Login now