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 | 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 | 96 | Copyright \(C) 2005-2009 Matt Mackall. |
|
97 | 97 | Free use of this software is granted under the terms of the GNU General |
|
98 |
Public License |
|
|
98 | Public License version 2. | |
|
99 | 99 | |
|
100 | 100 | .. include:: common.txt |
@@ -106,6 +106,6 b' COPYING' | |||
|
106 | 106 | This manual page is copyright 2006 Vadim Gelfer. |
|
107 | 107 | Mercurial is copyright 2005-2009 Matt Mackall. |
|
108 | 108 | Free use of this software is granted under the terms of the GNU General |
|
109 |
Public License |
|
|
109 | Public License version 2. | |
|
110 | 110 | |
|
111 | 111 | .. include:: common.txt |
@@ -946,6 +946,6 b' COPYING' | |||
|
946 | 946 | This manual page is copyright 2005 Bryan O'Sullivan. |
|
947 | 947 | Mercurial is copyright 2005-2009 Matt Mackall. |
|
948 | 948 | Free use of this software is granted under the terms of the GNU General |
|
949 |
Public License |
|
|
949 | Public License version 2. | |
|
950 | 950 | |
|
951 | 951 | .. include:: common.txt |
@@ -160,9 +160,8 b' def colorqseries(orig, ui, repo, *dummy,' | |||
|
160 | 160 | return retval |
|
161 | 161 | |
|
162 | 162 | _patch_effects = { 'applied': ['blue', 'bold', 'underline'], |
|
163 | 'missing': ['red', 'bold'], | |
|
164 | 'unapplied': ['black', 'bold'], } | |
|
165 | ||
|
163 | 'missing': ['red', 'bold'], | |
|
164 | 'unapplied': ['black', 'bold'], } | |
|
166 | 165 | def colorwrap(orig, s): |
|
167 | 166 | '''wrap ui.write for colored diff output''' |
|
168 | 167 | lines = s.split('\n') |
@@ -153,11 +153,13 b" protomap = {'http': httpcheck," | |||
|
153 | 153 | def issvnurl(url): |
|
154 | 154 | try: |
|
155 | 155 | proto, path = url.split('://', 1) |
|
156 | path = urllib.url2pathname(path) | |
|
156 | if proto == 'file': | |
|
157 | path = urllib.url2pathname(path) | |
|
157 | 158 | except ValueError: |
|
158 | 159 | proto = 'file' |
|
159 | 160 | path = os.path.abspath(url) |
|
160 | path = path.replace(os.sep, '/') | |
|
161 | if proto == 'file': | |
|
162 | path = path.replace(os.sep, '/') | |
|
161 | 163 | check = protomap.get(proto, lambda p, p2: False) |
|
162 | 164 | while '/' in path: |
|
163 | 165 | if check(path, proto): |
@@ -42,9 +42,9 b' fast (at least faster than having to com' | |||
|
42 | 42 | ''' |
|
43 | 43 | |
|
44 | 44 | from mercurial.i18n import _ |
|
45 | from mercurial.node import short | |
|
45 | from mercurial.node import short, nullid | |
|
46 | 46 | from mercurial import cmdutil, util, commands |
|
47 | import os, shlex, shutil, tempfile | |
|
47 | import os, shlex, shutil, tempfile, re | |
|
48 | 48 | |
|
49 | 49 | def snapshot(ui, repo, files, node, tmproot): |
|
50 | 50 | '''snapshot files as of some revision |
@@ -69,7 +69,7 b' def snapshot(ui, repo, files, node, tmpr' | |||
|
69 | 69 | for fn in files: |
|
70 | 70 | wfn = util.pconvert(fn) |
|
71 | 71 | if not wfn in ctx: |
|
72 | # skipping new file after a merge ? | |
|
72 | # File doesn't exist; could be a bogus modify | |
|
73 | 73 | continue |
|
74 | 74 | ui.note(' %s\n' % wfn) |
|
75 | 75 | dest = os.path.join(base, wfn) |
@@ -96,52 +96,95 b' def dodiff(ui, repo, diffcmd, diffopts, ' | |||
|
96 | 96 | |
|
97 | 97 | revs = opts.get('rev') |
|
98 | 98 | change = opts.get('change') |
|
99 | args = ' '.join(diffopts) | |
|
100 | do3way = '$parent2' in args | |
|
99 | 101 | |
|
100 | 102 | if revs and change: |
|
101 | 103 | msg = _('cannot specify --rev and --change at the same time') |
|
102 | 104 | raise util.Abort(msg) |
|
103 | 105 | elif change: |
|
104 | 106 | node2 = repo.lookup(change) |
|
105 |
node1 = repo |
|
|
107 | node1a, node1b = repo.changelog.parents(node2) | |
|
106 | 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 | 120 | matcher = cmdutil.match(repo, pats, opts) |
|
110 |
mod |
|
|
111 | if not (modified or added or removed): | |
|
112 | return 0 | |
|
121 | mod_a, add_a, rem_a = map(set, repo.status(node1a, node2, matcher)[:3]) | |
|
122 | if do3way: | |
|
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 | 131 | tmproot = tempfile.mkdtemp(prefix='extdiff.') |
|
115 | dir2root = '' | |
|
116 | 132 | try: |
|
117 | # Always make a copy of node1 | |
|
118 | dir1 = snapshot(ui, repo, modified + removed, node1, tmproot)[0] | |
|
119 | changes = len(modified) + len(removed) + len(added) | |
|
133 | # Always make a copy of node1a (and node1b, if applicable) | |
|
134 | dir1a_files = mod_a | rem_a | ((mod_b | add_b) - add_a) | |
|
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 | 144 | # If node2 in not the wc or there is >1 change, copy it |
|
122 | if node2 or changes > 1: | |
|
123 | dir2, fns_and_mtime = snapshot(ui, repo, modified + added, node2, tmproot) | |
|
145 | dir2root = '' | |
|
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 | 154 | else: |
|
125 | 155 | # This lets the diff tool open the changed file directly |
|
126 | 156 | dir2 = '' |
|
127 | 157 | dir2root = repo.root |
|
128 | fns_and_mtime = [] | |
|
129 | 158 | |
|
130 | 159 | # If only one change, diff the files instead of the directories |
|
131 | if changes == 1 : | |
|
132 |
|
|
|
133 | dir1 = os.path.join(dir1, util.localpath(modified[0])) | |
|
134 |
|
|
|
135 | elif len(removed) : | |
|
136 | dir1 = os.path.join(dir1, util.localpath(removed[0])) | |
|
137 | dir2 = os.devnull | |
|
138 | else: | |
|
139 | dir1 = os.devnull | |
|
140 | dir2 = os.path.join(dir2root, dir2, util.localpath(added[0])) | |
|
160 | # Handle bogus modifies correctly by checking if the files exist | |
|
161 | if len(common) == 1: | |
|
162 | common_file = util.localpath(common.pop()) | |
|
163 | dir1a = os.path.join(dir1a, common_file) | |
|
164 | if not os.path.isfile(os.path.join(tmproot, dir1a)): | |
|
165 | dir1a = os.devnull | |
|
166 | if do3way: | |
|
167 | dir1b = os.path.join(dir1b, common_file) | |
|
168 | if not os.path.isfile(os.path.join(tmproot, dir1b)): | |
|
169 | dir1b = os.devnull | |
|
170 | dir2 = os.path.join(dir2root, dir2, common_file) | |
|
141 | 171 | |
|
142 | cmdline = ('%s %s %s %s' % | |
|
143 | (util.shellquote(diffcmd), ' '.join(diffopts), | |
|
144 | util.shellquote(dir1), util.shellquote(dir2))) | |
|
172 | # Function to quote file/dir names in the argument string | |
|
173 | # When not operating in 3-way mode, an empty string is returned for parent2 | |
|
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 | 188 | ui.debug('running %r in %s\n' % (cmdline, tmproot)) |
|
146 | 189 | util.system(cmdline, cwd=tmproot) |
|
147 | 190 | |
@@ -173,11 +216,11 b' def extdiff(ui, repo, *pats, **opts):' | |||
|
173 | 216 | that revision is compared to the working directory, and, when no |
|
174 | 217 | revisions are specified, the working directory files are compared |
|
175 | 218 | to its parent.''' |
|
176 |
program = opts |
|
|
177 | if opts['program']: | |
|
178 | option = opts['option'] | |
|
179 | else: | |
|
180 |
option = |
|
|
219 | program = opts.get('program') | |
|
220 | option = opts.get('option') | |
|
221 | if not program: | |
|
222 | program = 'diff' | |
|
223 | option = option or ['-Npru'] | |
|
181 | 224 | return dodiff(ui, repo, program, option, pats, opts) |
|
182 | 225 | |
|
183 | 226 | cmdtable = { |
@@ -17,28 +17,7 b' from client import client, QueryFailed' | |||
|
17 | 17 | |
|
18 | 18 | def serve(ui, repo, **opts): |
|
19 | 19 | '''start an inotify server for this repository''' |
|
20 | timeout = opts.get('timeout') | |
|
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) | |
|
20 | server.start(ui, repo.dirstate, repo.root, opts) | |
|
42 | 21 | |
|
43 | 22 | def debuginotify(ui, repo, **opts): |
|
44 | 23 | '''debugging information for inotify extension |
@@ -34,7 +34,8 b' def start_server(function):' | |||
|
34 | 34 | self.ui.debug('(starting inotify server)\n') |
|
35 | 35 | try: |
|
36 | 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 | 39 | except server.AlreadyStartedException, inst: |
|
39 | 40 | # another process may have started its own |
|
40 | 41 | # inotify server while this one was starting. |
@@ -7,7 +7,7 b'' | |||
|
7 | 7 | # GNU General Public License version 2, incorporated herein by reference. |
|
8 | 8 | |
|
9 | 9 | from mercurial.i18n import _ |
|
10 | from mercurial import osutil, util | |
|
10 | from mercurial import cmdutil, osutil, util | |
|
11 | 11 | import common |
|
12 | 12 | import errno, os, select, socket, stat, struct, sys, tempfile, time |
|
13 | 13 | |
@@ -823,52 +823,29 b' class master(object):' | |||
|
823 | 823 | sys.exit(0) |
|
824 | 824 | pollable.run() |
|
825 | 825 | |
|
826 | def start(ui, dirstate, root): | |
|
827 | def closefds(ignore): | |
|
828 | # (from python bug #1177468) | |
|
829 | # close all inherited file descriptors | |
|
830 | # Python 2.4.1 and later use /dev/urandom to seed the random module's RNG | |
|
831 | # a file descriptor is kept internally as os._urandomfd (created on demand | |
|
832 | # the first time os.urandom() is called), and should not be closed | |
|
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 | |
|
826 | def start(ui, dirstate, root, opts): | |
|
827 | timeout = opts.get('timeout') | |
|
828 | if timeout: | |
|
829 | timeout = float(timeout) * 1e3 | |
|
830 | ||
|
831 | class service(object): | |
|
832 | def init(self): | |
|
842 | 833 | try: |
|
843 | os.close(fd) | |
|
844 |
except |
|
|
845 |
|
|
|
846 | ||
|
847 | m = master(ui, dirstate, root) | |
|
848 | sys.stdout.flush() | |
|
849 | sys.stderr.flush() | |
|
834 | self.master = master(ui, dirstate, root, timeout) | |
|
835 | except AlreadyStartedException, inst: | |
|
836 | raise util.Abort(str(inst)) | |
|
850 | 837 | |
|
851 | pid = os.fork() | |
|
852 | if pid: | |
|
853 | return pid | |
|
854 | ||
|
855 | closefds(pollable.instances.keys()) | |
|
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) | |
|
838 | def run(self): | |
|
839 | try: | |
|
840 | self.master.run() | |
|
841 | finally: | |
|
842 | self.master.shutdown() | |
|
862 | 843 | |
|
863 | fd = os.open(ui.config('inotify', 'log', '/dev/null'), | |
|
864 | os.O_RDWR | os.O_CREAT | os.O_TRUNC) | |
|
865 | os.dup2(fd, 1) | |
|
866 | os.dup2(fd, 2) | |
|
867 | if fd > 2: | |
|
868 | os.close(fd) | |
|
844 | runargs = None | |
|
845 | if 'inserve' not in sys.argv: | |
|
846 | runargs = [sys.argv[0], 'inserve', '-R', root] | |
|
869 | 847 | |
|
870 | try: | |
|
871 | m.run() | |
|
872 | finally: | |
|
873 | m.shutdown() | |
|
874 | os._exit(0) | |
|
848 | service = service() | |
|
849 | logfile = ui.config('inotify', 'log') | |
|
850 | cmdutil.service(opts, initfn=service.init, runfn=service.run, | |
|
851 | logfile=logfile, runargs=runargs) |
@@ -244,12 +244,14 b' class kwfilelog(filelog.filelog):' | |||
|
244 | 244 | return t2 != text |
|
245 | 245 | return revlog.revlog.cmp(self, node, text) |
|
246 | 246 | |
|
247 |
def _status(ui, repo, kwt, |
|
|
247 | def _status(ui, repo, kwt, *pats, **opts): | |
|
248 | 248 | '''Bails out if [keyword] configuration is not active. |
|
249 | 249 | Returns status of working directory.''' |
|
250 | 250 | if kwt: |
|
251 | match = cmdutil.match(repo, pats, opts) | |
|
252 | return repo.status(match=match, unknown=unknown, clean=True) | |
|
251 | unknown = (opts.get('unknown') or opts.get('all') | |
|
252 | or opts.get('untracked')) | |
|
253 | return repo.status(match=cmdutil.match(repo, pats, opts), clean=True, | |
|
254 | unknown=unknown) | |
|
253 | 255 | if ui.configitems('keyword'): |
|
254 | 256 | raise util.Abort(_('[keyword] patterns cannot match')) |
|
255 | 257 | raise util.Abort(_('no [keyword] patterns configured')) |
@@ -259,7 +261,7 b' def _kwfwrite(ui, repo, expand, *pats, *' | |||
|
259 | 261 | if repo.dirstate.parents()[1] != nullid: |
|
260 | 262 | raise util.Abort(_('outstanding uncommitted merge')) |
|
261 | 263 | kwt = kwtools['templater'] |
|
262 |
status = _status(ui, repo, kwt, |
|
|
264 | status = _status(ui, repo, kwt, *pats, **opts) | |
|
263 | 265 | modified, added, removed, deleted = status[:4] |
|
264 | 266 | if modified or added or removed or deleted: |
|
265 | 267 | raise util.Abort(_('outstanding uncommitted changes')) |
@@ -380,30 +382,32 b' def files(ui, repo, *pats, **opts):' | |||
|
380 | 382 | See "hg help keyword" on how to construct patterns both for |
|
381 | 383 | inclusion and exclusion of files. |
|
382 | 384 | |
|
383 | Use -u/--untracked to list untracked files as well. | |
|
384 | ||
|
385 | With -a/--all and -v/--verbose the codes used to show the status | |
|
385 | With -A/--all and -v/--verbose the codes used to show the status | |
|
386 | 386 | of files are:: |
|
387 | 387 | |
|
388 | 388 | K = keyword expansion candidate |
|
389 |
k = keyword expansion candidate ( |
|
|
389 | k = keyword expansion candidate (not tracked) | |
|
390 | 390 | I = ignored |
|
391 |
i = ignored ( |
|
|
391 | i = ignored (not tracked) | |
|
392 | 392 | ''' |
|
393 | 393 | kwt = kwtools['templater'] |
|
394 |
status = _status(ui, repo, kwt, |
|
|
394 | status = _status(ui, repo, kwt, *pats, **opts) | |
|
395 | cwd = pats and repo.getcwd() or '' | |
|
395 | 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 | 400 | wctx = repo[None] |
|
398 | 401 | kwfiles = [f for f in files if kwt.iskwfile(f, wctx.flags)] |
|
399 |
kwun |
|
|
400 | cwd = pats and repo.getcwd() or '' | |
|
401 | kwfstats = (not opts.get('ignore') and | |
|
402 | (('K', kwfiles), ('k', kwuntracked),) or ()) | |
|
402 | kwunknown = [f for f in unknown if kwt.iskwfile(f, wctx.flags)] | |
|
403 | if not opts.get('ignore') or opts.get('all'): | |
|
404 | showfiles = kwfiles, kwunknown | |
|
405 | else: | |
|
406 | showfiles = [], [] | |
|
403 | 407 | if opts.get('all') or opts.get('ignore'): |
|
404 |
|
|
|
405 |
|
|
|
406 |
for char, filenames in |
|
|
408 | showfiles += ([f for f in files if f not in kwfiles], | |
|
409 | [f for f in unknown if f not in kwunknown]) | |
|
410 | for char, filenames in zip('KkIi', showfiles): | |
|
407 | 411 | fmt = (opts.get('all') or ui.verbose) and '%s %%s\n' % char or '%s\n' |
|
408 | 412 | for f in filenames: |
|
409 | 413 | ui.write(fmt % repo.pathto(f, cwd)) |
@@ -545,9 +549,12 b' cmdtable = {' | |||
|
545 | 549 | _('hg kwexpand [OPTION]... [FILE]...')), |
|
546 | 550 | 'kwfiles': |
|
547 | 551 | (files, |
|
548 |
[(' |
|
|
552 | [('A', 'all', None, _('show keyword status flags of all files')), | |
|
549 | 553 | ('i', 'ignore', None, _('show files excluded from expansion')), |
|
550 |
('u', 'un |
|
|
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 | 558 | ] + commands.walkopts, |
|
552 | 559 | _('hg kwfiles [OPTION]... [FILE]...')), |
|
553 | 560 | 'kwshrink': (shrink, commands.walkopts, |
@@ -43,6 +43,7 b' Optional configuration items::' | |||
|
43 | 43 | diffstat = True # add a diffstat before the diff content |
|
44 | 44 | sources = serve # notify if source of incoming changes in this list |
|
45 | 45 | # (serve == ssh or http, push, pull, bundle) |
|
46 | merge = False # send notification for merges (default True) | |
|
46 | 47 | [email] |
|
47 | 48 | from = user@host.com # email address to send as if none given |
|
48 | 49 | [web] |
@@ -111,6 +112,7 b' class notifier(object):' | |||
|
111 | 112 | self.test = self.ui.configbool('notify', 'test', True) |
|
112 | 113 | self.charsets = mail._charsets(self.ui) |
|
113 | 114 | self.subs = self.subscribers() |
|
115 | self.merge = self.ui.configbool('notify', 'merge', True) | |
|
114 | 116 | |
|
115 | 117 | mapfile = self.ui.config('notify', 'style') |
|
116 | 118 | template = (self.ui.config('notify', hooktype) or |
@@ -166,10 +168,13 b' class notifier(object):' | |||
|
166 | 168 | return self.ui.config('web', 'baseurl') + (path or self.root) |
|
167 | 169 | |
|
168 | 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 | 174 | self.t.show(ctx, changes=ctx.changeset(), |
|
171 | 175 | baseurl=self.ui.config('web', 'baseurl'), |
|
172 | 176 | root=self.repo.root, webroot=self.root, **props) |
|
177 | return True | |
|
173 | 178 | |
|
174 | 179 | def skipsource(self, source): |
|
175 | 180 | '''true if incoming changes from this source should be skipped.''' |
@@ -283,16 +288,29 b' def hook(ui, repo, hooktype, node=None, ' | |||
|
283 | 288 | return |
|
284 | 289 | |
|
285 | 290 | ui.pushbuffer() |
|
291 | data = '' | |
|
292 | count = 0 | |
|
286 | 293 | if hooktype == 'changegroup': |
|
287 | 294 | start, end = ctx.rev(), len(repo) |
|
288 | count = end - start | |
|
289 | 295 | for rev in xrange(start, end): |
|
290 | n.node(repo[rev]) | |
|
291 | n.diff(ctx, repo['tip']) | |
|
296 | if n.node(repo[rev]): | |
|
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 | 305 | else: |
|
293 | count = 1 | |
|
294 | n.node(ctx) | |
|
306 | if not 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 | 312 | n.diff(ctx) |
|
296 | 313 | |
|
297 | data = ui.popbuffer() | |
|
298 | n.send(ctx, count, data) | |
|
314 | data += ui.popbuffer() | |
|
315 | if count: | |
|
316 | n.send(ctx, count, data) |
@@ -17,8 +17,8 b' msgid ""' | |||
|
17 | 17 | msgstr "" |
|
18 | 18 | "Project-Id-Version: Mercurial\n" |
|
19 | 19 | "Report-Msgid-Bugs-To: <mercurial-devel@selenic.com>\n" |
|
20 |
"POT-Creation-Date: 2009-0 |
|
|
21 |
"PO-Revision-Date: 2009-0 |
|
|
20 | "POT-Creation-Date: 2009-09-29 00:26+0200\n" | |
|
21 | "PO-Revision-Date: 2009-09-29 00:41+0200\n" | |
|
22 | 22 | "Last-Translator: <mg@lazybytes.net>\n" |
|
23 | 23 | "Language-Team: Danish\n" |
|
24 | 24 | "MIME-Version: 1.0\n" |
@@ -1007,7 +1007,8 b' msgstr "CVS pserver godkendelse fejlede"' | |||
|
1007 | 1007 | #, python-format |
|
1008 | 1008 | msgid "" |
|
1009 | 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 | 1013 | #, python-format |
|
1013 | 1014 | msgid "%d bytes missing from remote file" |
@@ -1086,6 +1087,10 b' msgstr ""' | |||
|
1086 | 1087 | msgid "%d changeset entries\n" |
|
1087 | 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 | 1094 | msgid "Python ElementTree module is not available" |
|
1090 | 1095 | msgstr "Python ElementTree modulet er ikke tilstede" |
|
1091 | 1096 | |
@@ -1492,10 +1497,6 b' msgid "merging with %d:%s\\n"' | |||
|
1492 | 1497 | msgstr "sammenføjer med %d:%s\n" |
|
1493 | 1498 | |
|
1494 | 1499 | #, python-format |
|
1495 | msgid "Automated merge with %s" | |
|
1496 | msgstr "Automatisk sammenføjning med %s" | |
|
1497 | ||
|
1498 | #, python-format | |
|
1499 | 1500 | msgid "new changeset %d:%s merges remote changes with local\n" |
|
1500 | 1501 | msgstr "ny ændring %d:%s fletter fjernændringer sammen med lokale\n" |
|
1501 | 1502 | |
@@ -1576,10 +1577,6 b' msgstr ""' | |||
|
1576 | 1577 | "arbejdskopien af .hgsigs er ændret (deponer venligst .hgsigs manuelt eller " |
|
1577 | 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 | 1580 | msgid "unknown signature version" |
|
1584 | 1581 | msgstr "ukendt underskrift-version" |
|
1585 | 1582 | |
@@ -2133,7 +2130,9 b' msgstr ""' | |||
|
2133 | 2130 | msgid "" |
|
2134 | 2131 | "\n" |
|
2135 | 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 | 2137 | msgid "unhooked all commit hooks\n" |
|
2139 | 2138 | msgstr "" |
@@ -3789,22 +3788,22 b' msgid ""' | |||
|
3789 | 3788 | msgstr "" |
|
3790 | 3789 | |
|
3791 | 3790 | msgid "cannot use both abort and continue" |
|
3792 | msgstr "" | |
|
3791 | msgstr "abort og continue kan ikke angives samtidig" | |
|
3793 | 3792 | |
|
3794 | 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 | 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 | 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 | 3802 | msgid "nothing to rebase\n" |
|
3804 | 3803 | msgstr "" |
|
3805 | 3804 | |
|
3806 | 3805 | msgid "cannot use both keepbranches and extrafn" |
|
3807 | msgstr "" | |
|
3806 | msgstr "man kan ikke bruge både keepbranches og extrafn" | |
|
3808 | 3807 | |
|
3809 | 3808 | msgid "rebase merging completed\n" |
|
3810 | 3809 | msgstr "" |
@@ -3817,7 +3816,7 b' msgstr ""' | |||
|
3817 | 3816 | |
|
3818 | 3817 | #, python-format |
|
3819 | 3818 | msgid "%d revisions have been skipped\n" |
|
3820 | msgstr "" | |
|
3819 | msgstr "sprang %d revisioner over\n" | |
|
3821 | 3820 | |
|
3822 | 3821 | msgid " set parents\n" |
|
3823 | 3822 | msgstr "" |
@@ -4275,7 +4274,7 b' msgid ""' | |||
|
4275 | 4274 | msgstr "" |
|
4276 | 4275 | |
|
4277 | 4276 | #, python-format |
|
4278 | msgid "[win32mbcs] filename conversion fail with %s encoding\n" | |
|
4277 | msgid "[win32mbcs] filename conversion failed with %s encoding\n" | |
|
4279 | 4278 | msgstr "" |
|
4280 | 4279 | |
|
4281 | 4280 | msgid "[win32mbcs] cannot activate on this platform.\n" |
@@ -4668,12 +4667,27 b' msgid ""' | |||
|
4668 | 4667 | " be expensive.\n" |
|
4669 | 4668 | " " |
|
4670 | 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 | 4686 | msgid "similarity must be a number" |
|
4673 | msgstr "" | |
|
4687 | msgstr "lighedsgrad skal være et tal" | |
|
4674 | 4688 | |
|
4675 | 4689 | msgid "similarity must be between 0 and 100" |
|
4676 | msgstr "" | |
|
4690 | msgstr "lighedsgrad skal være mellem 0 og 100" | |
|
4677 | 4691 | |
|
4678 | 4692 | msgid "" |
|
4679 | 4693 | "show changeset information by line for each file\n" |
@@ -4705,10 +4719,10 b' msgstr ""' | |||
|
4705 | 4719 | " " |
|
4706 | 4720 | |
|
4707 | 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 | 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 | 4727 | #, python-format |
|
4714 | 4728 | msgid "%s: binary file\n" |
@@ -4744,10 +4758,10 b' msgid "no working directory: please spec' | |||
|
4744 | 4758 | msgstr "intet arbejdskatalog: angive venligst en revision" |
|
4745 | 4759 | |
|
4746 | 4760 | msgid "repository root cannot be destination" |
|
4747 | msgstr "" | |
|
4761 | msgstr "depotets rod kan ikke bruges som destination" | |
|
4748 | 4762 | |
|
4749 | 4763 | msgid "cannot archive plain files to stdout" |
|
4750 | msgstr "" | |
|
4764 | msgstr "flade filer kan ikke arkiveres til standarduddata" | |
|
4751 | 4765 | |
|
4752 | 4766 | msgid "" |
|
4753 | 4767 | "reverse effect of earlier changeset\n" |
@@ -4806,11 +4820,7 b' msgid "%s is not a parent of %s"' | |||
|
4806 | 4820 | msgstr "%s er ikke forælder til %s" |
|
4807 | 4821 | |
|
4808 | 4822 | msgid "cannot use --parent on non-merge changeset" |
|
4809 | msgstr "" | |
|
4810 | ||
|
4811 | #, python-format | |
|
4812 | msgid "Backed out changeset %s" | |
|
4813 | msgstr "" | |
|
4823 | msgstr "kan ikke bruge --parent på en ændringer som ikke er en sammenføjning" | |
|
4814 | 4824 | |
|
4815 | 4825 | #, python-format |
|
4816 | 4826 | msgid "changeset %s backs out changeset %s\n" |
@@ -4824,7 +4834,7 b' msgid "the backout changeset is a new he' | |||
|
4824 | 4834 | msgstr "" |
|
4825 | 4835 | |
|
4826 | 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 | 4839 | msgid "" |
|
4830 | 4840 | "subdivision search of changesets\n" |
@@ -4872,7 +4882,7 b' msgid "cannot bisect (no known bad revis' | |||
|
4872 | 4882 | msgstr "" |
|
4873 | 4883 | |
|
4874 | 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 | 4887 | msgid "incompatible arguments" |
|
4878 | 4888 | msgstr "inkompatible argumenter" |
@@ -4883,7 +4893,7 b' msgstr "kan ikke finde program: %s"' | |||
|
4883 | 4893 | |
|
4884 | 4894 | #, python-format |
|
4885 | 4895 | msgid "failed to execute %s" |
|
4886 | msgstr "" | |
|
4896 | msgstr "kunne ikke køre %s" | |
|
4887 | 4897 | |
|
4888 | 4898 | #, python-format |
|
4889 | 4899 | msgid "%s killed" |
@@ -4917,10 +4927,27 b' msgid ""' | |||
|
4917 | 4927 | " 'hg commit --close-branch' to mark this branch as closed.\n" |
|
4918 | 4928 | " " |
|
4919 | 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 | 4948 | #, python-format |
|
4922 | 4949 | msgid "reset working directory to branch %s\n" |
|
4923 | msgstr "" | |
|
4950 | msgstr "nulstil arbejdskataloget til gren %s\n" | |
|
4924 | 4951 | |
|
4925 | 4952 | msgid "a branch of the same name already exists (use --force to override)" |
|
4926 | 4953 | msgstr "" |
@@ -5003,6 +5030,22 b' msgid ""' | |||
|
5003 | 5030 | " %p root-relative path name of file being printed\n" |
|
5004 | 5031 | " " |
|
5005 | 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 | 5050 | msgid "" |
|
5008 | 5051 | "make a copy of an existing repository\n" |
@@ -5525,24 +5568,29 b' msgid ""' | |||
|
5525 | 5568 | "\n" |
|
5526 | 5569 | " With no arguments, show all repository head changesets.\n" |
|
5527 | 5570 | "\n" |
|
5528 |
" Repository \"heads\" are changesets |
|
|
5529 |
" |
|
|
5530 |
" |
|
|
5571 | " Repository \"heads\" are changesets with no child changesets. They are\n" | |
|
5572 | " where development generally takes place and are the usual targets\n" | |
|
5573 | " for update and merge operations.\n" | |
|
5531 | 5574 | "\n" |
|
5532 | 5575 | " If one or more REV is given, the \"branch heads\" will be shown for\n" |
|
5533 |
" the named branch associated with th |
|
|
5534 | " branch is called the revision's branch tag.\n" | |
|
5535 | "\n" | |
|
5536 | " Branch heads are revisions on a given named branch that do not have\n" | |
|
5537 | " any descendants on the same branch. A branch head could be a true head\n" | |
|
5538 |
" or it could be the last changeset on |
|
|
5539 |
" was created. If none of the branch heads |
|
|
5540 | " is considered inactive. If -c/--closed is specified, also show branch\n" | |
|
5541 | " heads marked closed (see hg commit --close-branch).\n" | |
|
5542 | "\n" | |
|
5543 | " If STARTREV is specified only those heads (or branch heads) that\n" | |
|
5544 | " are descendants of STARTREV will be displayed.\n" | |
|
5545 | " " | |
|
5576 | " the named branch associated with the specified changeset(s).\n" | |
|
5577 | "\n" | |
|
5578 | " Branch heads are changesets on a named branch with no descendants on\n" | |
|
5579 | " the same branch. A branch head could be a \"true\" (repository) head,\n" | |
|
5580 | " or it could be the last changeset on that branch before it was\n" | |
|
5581 | " merged into another branch, or it could be the last changeset on the\n" | |
|
5582 | " branch before a new branch was created. If none of the branch heads\n" | |
|
5583 | " are true heads, the branch is considered inactive.\n" | |
|
5584 | "\n" | |
|
5585 | " If -c/--closed is specified, also show branch heads marked closed\n" | |
|
5586 | " (see hg commit --close-branch).\n" | |
|
5587 | "\n" | |
|
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 | 5594 | msgstr "" |
|
5547 | 5595 | |
|
5548 | 5596 | #, python-format |
@@ -6403,17 +6451,9 b' msgid "tag \'%s\' is not a local tag"' | |||
|
6403 | 6451 | msgstr "mærkaten '%s' er ikke en lokal mærkat" |
|
6404 | 6452 | |
|
6405 | 6453 | #, python-format |
|
6406 | msgid "Removed tag %s" | |
|
6407 | msgstr "Mærke %s er fjernet" | |
|
6408 | ||
|
6409 | #, python-format | |
|
6410 | 6454 | msgid "tag '%s' already exists (use -f to force)" |
|
6411 | 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 | 6457 | msgid "" |
|
6418 | 6458 | "list repository tags\n" |
|
6419 | 6459 | "\n" |
@@ -6511,6 +6551,9 b' msgstr ""' | |||
|
6511 | 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 | 6557 | msgid "uncommitted local changes" |
|
6515 | 6558 | msgstr "udeponerede lokale ændringer" |
|
6516 | 6559 | |
@@ -6525,6 +6568,14 b' msgid ""' | |||
|
6525 | 6568 | " integrity of their crosslinks and indices.\n" |
|
6526 | 6569 | " " |
|
6527 | 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 | 6580 | msgid "output version and copyright information" |
|
6530 | 6581 | msgstr "udskriv version- og copyrightinformation" |
@@ -6539,6 +6590,11 b' msgid ""' | |||
|
6539 | 6590 | "This is free software; see the source for copying conditions. There is NO\n" |
|
6540 | 6591 | "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n" |
|
6541 | 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 | 6599 | msgid "repository root directory or symbolic path name" |
|
6544 | 6600 | msgstr "depotrodfolder eller symbolsk stinavn" |
@@ -6721,10 +6777,10 b' msgid "[-gbsr] [-c CMD] [REV]"' | |||
|
6721 | 6777 | msgstr "[-gbsr] [-c KOMMANDO] [REV]" |
|
6722 | 6778 | |
|
6723 | 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 | 6782 | msgid "reset branch name to parent branch name" |
|
6727 | msgstr "" | |
|
6783 | msgstr "nulstil grennavnet til forældre-grennavnet" | |
|
6728 | 6784 | |
|
6729 | 6785 | msgid "[-fC] [NAME]" |
|
6730 | 6786 | msgstr "[-fC] [NAVN]" |
@@ -6732,8 +6788,8 b' msgstr "[-fC] [NAVN]"' | |||
|
6732 | 6788 | msgid "show only branches that have unmerged heads" |
|
6733 | 6789 | msgstr "vil kun grene som har usammenføjne hoveder" |
|
6734 | 6790 | |
|
6735 |
msgid "show normal and closed he |
|
|
6736 |
msgstr "vis normale og lukkede |
|
|
6791 | msgid "show normal and closed branches" | |
|
6792 | msgstr "vis normale og lukkede grene" | |
|
6737 | 6793 | |
|
6738 | 6794 | msgid "[-a]" |
|
6739 | 6795 | msgstr "[-a]" |
@@ -6847,7 +6903,7 b' msgid "[OPTION]... [-r REV1 [-r REV2]] [' | |||
|
6847 | 6903 | msgstr "[TILVALG]... [-r REV1 [-r REV2]] [FIL]..." |
|
6848 | 6904 | |
|
6849 | 6905 | msgid "diff against the second parent" |
|
6850 | msgstr "" | |
|
6906 | msgstr "find forskelle i forhold til den anden forældre" | |
|
6851 | 6907 | |
|
6852 | 6908 | msgid "[OPTION]... [-o OUTFILESPEC] REV..." |
|
6853 | 6909 | msgstr "[TILVALG]... [-o UDFILSPECIFIKATION] REV..." |
@@ -6879,8 +6935,11 b' msgstr "[TILVALG]... M\xc3\x98NSTER [FIL]..."' | |||
|
6879 | 6935 | msgid "show only heads which are descendants of REV" |
|
6880 | 6936 | msgstr "vis kun hoveder som er efterkommere af REV" |
|
6881 | 6937 | |
|
6882 | msgid "show only the active heads from open branches" | |
|
6883 | msgstr "vis kun aktive hoveder fra åbne grene" | |
|
6938 | msgid "show only the active branch heads from open branches" | |
|
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 | 6944 | msgid "[-r STARTREV] [REV]..." |
|
6886 | 6945 | msgstr "[-r STARTREV] [REV]..." |
@@ -7766,22 +7825,21 b' msgid ""' | |||
|
7766 | 7825 | " Mercurial supports several ways to specify individual revisions.\n" |
|
7767 | 7826 | "\n" |
|
7768 | 7827 | " A plain integer is treated as a revision number. Negative integers\n" |
|
7769 |
" are treated as t |
|
|
7770 | " the tip. As such, negative numbers are only useful if you've\n" | |
|
7771 | " memorized your local tree numbers and want to save typing a single\n" | |
|
7772 | " digit. This editor suggests copy and paste.\n" | |
|
7828 | " are treated as sequential offsets from the tip, with -1 denoting\n" | |
|
7829 | " the tip, -2 denoting the revision prior to the tip, and so forth.\n" | |
|
7773 | 7830 | "\n" |
|
7774 | 7831 | " A 40-digit hexadecimal string is treated as a unique revision\n" |
|
7775 | 7832 | " identifier.\n" |
|
7776 | 7833 | "\n" |
|
7777 | 7834 | " A hexadecimal string less than 40 characters long is treated as a\n" |
|
7778 |
" unique revision identifier |
|
|
7835 | " unique revision identifier and is referred to as a short-form\n" | |
|
7779 | 7836 | " identifier. A short-form identifier is only valid if it is the\n" |
|
7780 | 7837 | " prefix of exactly one full-length identifier.\n" |
|
7781 | 7838 | "\n" |
|
7782 |
" Any other string is treated as a tag |
|
|
7783 |
" name associated with a revision identifier. |
|
|
7784 | " contain the \":\" character.\n" | |
|
7839 | " Any other string is treated as a tag or branch name. A tag name is\n" | |
|
7840 | " a symbolic name associated with a revision identifier. A branch\n" | |
|
7841 | " name denotes the tipmost revision of that branch. Tag and branch\n" | |
|
7842 | " names must not contain the \":\" character.\n" | |
|
7785 | 7843 | "\n" |
|
7786 | 7844 | " The reserved name \"tip\" is a special tag that always identifies\n" |
|
7787 | 7845 | " the most recent revision.\n" |
@@ -7943,13 +8001,19 b' msgid ""' | |||
|
7943 | 8001 | " - nonempty: Any text. Returns '(none)' if the string is empty.\n" |
|
7944 | 8002 | " - hgdate: Date. Returns the date as a pair of numbers:\n" |
|
7945 | 8003 | " \"1157407993 25200\" (Unix timestamp, timezone offset).\n" |
|
7946 |
" - isodate: Date. Returns the date in ISO 8601 format |
|
|
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 | 8009 | " - localdate: Date. Converts a date to local date.\n" |
|
7948 | 8010 | " - obfuscate: Any text. Returns the input text rendered as a\n" |
|
7949 | 8011 | " sequence of XML entities.\n" |
|
7950 | 8012 | " - person: Any text. Returns the text before an email address.\n" |
|
7951 | 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 | 8017 | " - short: Changeset hash. Returns the short form of a changeset\n" |
|
7954 | 8018 | " hash, i.e. a 12-byte hexadecimal string.\n" |
|
7955 | 8019 | " - shortdate: Date. Returns a date like \"2006-09-18\".\n" |
@@ -9812,22 +9812,21 b' msgid ""' | |||
|
9812 | 9812 | " Mercurial supports several ways to specify individual revisions.\n" |
|
9813 | 9813 | "\n" |
|
9814 | 9814 | " A plain integer is treated as a revision number. Negative integers\n" |
|
9815 |
" are treated as t |
|
|
9816 | " the tip. As such, negative numbers are only useful if you've\n" | |
|
9817 | " memorized your local tree numbers and want to save typing a single\n" | |
|
9818 | " digit. This editor suggests copy and paste.\n" | |
|
9815 | " are treated as sequential offsets from the tip, with -1 denoting\n" | |
|
9816 | " the tip, -2 denoting the revision prior to the tip, and so forth.\n" | |
|
9819 | 9817 | "\n" |
|
9820 | 9818 | " A 40-digit hexadecimal string is treated as a unique revision\n" |
|
9821 | 9819 | " identifier.\n" |
|
9822 | 9820 | "\n" |
|
9823 | 9821 | " A hexadecimal string less than 40 characters long is treated as a\n" |
|
9824 |
" unique revision identifier |
|
|
9822 | " unique revision identifier and is referred to as a short-form\n" | |
|
9825 | 9823 | " identifier. A short-form identifier is only valid if it is the\n" |
|
9826 | 9824 | " prefix of exactly one full-length identifier.\n" |
|
9827 | 9825 | "\n" |
|
9828 |
" Any other string is treated as a tag |
|
|
9829 |
" name associated with a revision identifier. |
|
|
9830 | " contain the \":\" character.\n" | |
|
9826 | " Any other string is treated as a tag or branch name. A tag name is\n" | |
|
9827 | " a symbolic name associated with a revision identifier. A branch\n" | |
|
9828 | " name denotes the tipmost revision of that branch. Tag and branch\n" | |
|
9829 | " names must not contain the \":\" character.\n" | |
|
9831 | 9830 | "\n" |
|
9832 | 9831 | " The reserved name \"tip\" is a special tag that always identifies\n" |
|
9833 | 9832 | " the most recent revision.\n" |
@@ -9846,23 +9845,22 b' msgstr ""' | |||
|
9846 | 9845 | " individuais.\n" |
|
9847 | 9846 | "\n" |
|
9848 | 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" | |
|
9850 | " tip, com -1 denotando a tip. Assim, números negativos são úteis\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" | |
|
9848 | " negativos são contados a partir da tip, com -1 denotando a tip,\n" | |
|
9849 | " -2 denotando a revisão anterior à tip, e assim por diante.\n" | |
|
9854 | 9850 | "\n" |
|
9855 | 9851 | " Uma string hexadecimal de 40 dígitos é tratada como um\n" |
|
9856 | 9852 | " identificador único de revisão.\n" |
|
9857 | 9853 | "\n" |
|
9858 | 9854 | " Uma string hexadecimal de menos de 40 caracteres é tratada como\n" |
|
9859 |
" um identificador único de revisão, |
|
|
9860 |
" |
|
|
9861 |
" |
|
|
9862 | "\n" | |
|
9863 |
" Qualquer outra string é tratada como um nome de etiqueta |
|
|
9864 | " um nome simbólico associado a um identificador de revisão. Nomes\n" | |
|
9865 | " de etiqueta não podem conter o caractere \":\".\n" | |
|
9855 | " um identificador único de revisão, chamado de identificador\n" | |
|
9856 | " curto. Um identificador curto é válido apenas se for o prefixo\n" | |
|
9857 | " de um identificador completo.\n" | |
|
9858 | "\n" | |
|
9859 | " Qualquer outra string é tratada como um nome de etiqueta ou\n" | |
|
9860 | " ramo. Um nome de etiqueta é um nome simbólico associado a um\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 | 9864 | "\n" |
|
9867 | 9865 | " O nome reservado \"tip\" é uma etiqueta especial que sempre\n" |
|
9868 | 9866 | " identifica a revisão mais recente.\n" |
@@ -10076,13 +10074,19 b' msgid ""' | |||
|
10076 | 10074 | " - nonempty: Any text. Returns '(none)' if the string is empty.\n" |
|
10077 | 10075 | " - hgdate: Date. Returns the date as a pair of numbers:\n" |
|
10078 | 10076 | " \"1157407993 25200\" (Unix timestamp, timezone offset).\n" |
|
10079 |
" - isodate: Date. Returns the date in ISO 8601 format |
|
|
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 | 10082 | " - localdate: Date. Converts a date to local date.\n" |
|
10081 | 10083 | " - obfuscate: Any text. Returns the input text rendered as a\n" |
|
10082 | 10084 | " sequence of XML entities.\n" |
|
10083 | 10085 | " - person: Any text. Returns the text before an email address.\n" |
|
10084 | 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 | 10090 | " - short: Changeset hash. Returns the short form of a changeset\n" |
|
10087 | 10091 | " hash, i.e. a 12-byte hexadecimal string.\n" |
|
10088 | 10092 | " - shortdate: Date. Returns a date like \"2006-09-18\".\n" |
@@ -10186,14 +10190,17 b' msgstr ""' | |||
|
10186 | 10190 | " - nonempty: Qualquer texto. Devolve (none) se o texto for vazio.\n" |
|
10187 | 10191 | " - hgdate: Data. Devolve a data como um par de números:\n" |
|
10188 | 10192 | " \"1157407993 25200\" (timestamp Unix, defasagem de fuso)\n" |
|
10189 |
" - isodate: Data. Devolve a data em formato ISO 8601 |
|
|
10193 | " - isodate: Data. Devolve a data em formato ISO 8601: \"2009-08-18\n" | |
|
10194 | " 13:00 +0200\".\n" | |
|
10190 | 10195 | " - localdate: Data. Converte para data local.\n" |
|
10191 | 10196 | " - obfuscate: Qualquer texto. Devolve o texto de entrada\n" |
|
10192 | 10197 | " renderizado como uma seqüência de entidades XML.\n" |
|
10193 | 10198 | " - person: Qualquer texto. Devolve o texto antes de um endereço\n" |
|
10194 | 10199 | " de e-mail.\n" |
|
10195 | " - rfc822date: Data. Devolve uma data usando o mesmo formato\n" | |
|
10196 |
" |
|
|
10200 | " - rfc822date: Data. Devolve uma data usando o mesmo formato utilizado\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 | 10204 | " - short: Hash do changeset. Devolve a forma curta do hash de\n" |
|
10198 | 10205 | " um changeset, ou seja, uma string hexadecimal de 12 bytes.\n" |
|
10199 | 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 | 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 | 551 | '''Run a command as a service.''' |
|
551 | 552 | |
|
552 | 553 | if opts['daemon'] and not opts['daemon_pipefds']: |
|
553 | 554 | rfd, wfd = os.pipe() |
|
554 | args = sys.argv[:] | |
|
555 | args.append('--daemon-pipefds=%d,%d' % (rfd, wfd)) | |
|
555 | if not runargs: | |
|
556 | runargs = sys.argv[:] | |
|
557 | runargs.append('--daemon-pipefds=%d,%d' % (rfd, wfd)) | |
|
556 | 558 | # Don't pass --cwd to the child process, because we've already |
|
557 | 559 | # changed directory. |
|
558 | for i in xrange(1,len(args)): | |
|
559 | if args[i].startswith('--cwd='): | |
|
560 | del args[i] | |
|
560 | for i in xrange(1,len(runargs)): | |
|
561 | if runargs[i].startswith('--cwd='): | |
|
562 | del runargs[i] | |
|
561 | 563 | break |
|
562 | elif args[i].startswith('--cwd'): | |
|
563 | del args[i:i+2] | |
|
564 | elif runargs[i].startswith('--cwd'): | |
|
565 | del runargs[i:i+2] | |
|
564 | 566 | break |
|
565 | 567 | pid = os.spawnvp(os.P_NOWAIT | getattr(os, 'P_DETACH', 0), |
|
566 | args[0], args) | |
|
568 | runargs[0], runargs) | |
|
567 | 569 | os.close(wfd) |
|
568 | 570 | os.read(rfd, 1) |
|
569 | 571 | if parentfn: |
@@ -1356,23 +1356,25 b' def heads(ui, repo, *branchrevs, **opts)' | |||
|
1356 | 1356 | |
|
1357 | 1357 | With no arguments, show all repository head changesets. |
|
1358 | 1358 | |
|
1359 |
Repository "heads" are changesets |
|
|
1360 |
|
|
|
1361 |
|
|
|
1359 | Repository "heads" are changesets with no child changesets. They are | |
|
1360 | where development generally takes place and are the usual targets | |
|
1361 | for update and merge operations. | |
|
1362 | 1362 | |
|
1363 | 1363 | If one or more REV is given, the "branch heads" will be shown for |
|
1364 |
the named branch associated with th |
|
|
1365 | branch is called the revision's branch tag. | |
|
1366 | ||
|
1367 | Branch heads are revisions on a given named branch that do not have | |
|
1368 | any descendants on the same branch. A branch head could be a true head | |
|
1369 |
or it could be the last changeset on |
|
|
1370 |
was created. If none of the branch heads |
|
|
1371 | is considered inactive. If -c/--closed is specified, also show branch | |
|
1372 | heads marked closed (see hg commit --close-branch). | |
|
1373 | ||
|
1374 | If STARTREV is specified only those heads (or branch heads) that | |
|
1375 | are descendants of STARTREV will be displayed. | |
|
1364 | the named branch associated with the specified changeset(s). | |
|
1365 | ||
|
1366 | Branch heads are changesets on a named branch with no descendants on | |
|
1367 | the same branch. A branch head could be a "true" (repository) head, | |
|
1368 | or it could be the last changeset on that branch before it was | |
|
1369 | merged into another branch, or it could be the last changeset on the | |
|
1370 | branch before a new branch was created. If none of the branch heads | |
|
1371 | are true heads, the branch is considered inactive. | |
|
1372 | ||
|
1373 | If -c/--closed is specified, also show branch heads marked closed | |
|
1374 | (see hg commit --close-branch). | |
|
1375 | ||
|
1376 | If STARTREV is specified, only those heads that are descendants of | |
|
1377 | STARTREV will be displayed. | |
|
1376 | 1378 | """ |
|
1377 | 1379 | if opts.get('rev'): |
|
1378 | 1380 | start = repo.lookup(opts['rev']) |
@@ -38,6 +38,9 b' def _decdirs(dirs, path):' | |||
|
38 | 38 | class dirstate(object): |
|
39 | 39 | |
|
40 | 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 | 44 | self._opener = opener |
|
42 | 45 | self._root = root |
|
43 | 46 | self._rootdir = os.path.join(root, '') |
@@ -47,6 +50,8 b' class dirstate(object):' | |||
|
47 | 50 | |
|
48 | 51 | @propertycache |
|
49 | 52 | def _map(self): |
|
53 | '''Return the dirstate contents as a map from filename to | |
|
54 | (state, mode, size, time).''' | |
|
50 | 55 | self._read() |
|
51 | 56 | return self._map |
|
52 | 57 | |
@@ -169,12 +174,14 b' class dirstate(object):' | |||
|
169 | 174 | return path |
|
170 | 175 | |
|
171 | 176 | def __getitem__(self, key): |
|
172 | ''' current states: | |
|
173 | n normal | |
|
174 |
|
|
|
175 | r marked for removal | |
|
176 |
|
|
|
177 | ? not tracked''' | |
|
177 | '''Return the current state of key (a filename) in the dirstate. | |
|
178 | States are: | |
|
179 | n normal | |
|
180 | m needs merging | |
|
181 | r marked for removal | |
|
182 | a marked for addition | |
|
183 | ? not tracked | |
|
184 | ''' | |
|
178 | 185 | return self._map.get(key, ("?",))[0] |
|
179 | 186 | |
|
180 | 187 | def __contains__(self, key): |
@@ -373,13 +380,9 b' class dirstate(object):' | |||
|
373 | 380 | return |
|
374 | 381 | st = self._opener("dirstate", "w", atomictemp=True) |
|
375 | 382 | |
|
376 | try: | |
|
377 | gran = int(self._ui.config('dirstate', 'granularity', 1)) | |
|
378 | except ValueError: | |
|
379 | gran = 1 | |
|
380 | if gran > 0: | |
|
381 | hlimit = util.fstat(st).st_mtime | |
|
382 | llimit = hlimit - gran | |
|
383 | # use the modification time of the newly created temporary file as the | |
|
384 | # filesystem's notion of 'now' | |
|
385 | now = int(util.fstat(st).st_mtime) | |
|
383 | 386 | |
|
384 | 387 | cs = cStringIO.StringIO() |
|
385 | 388 | copymap = self._copymap |
@@ -389,9 +392,19 b' class dirstate(object):' | |||
|
389 | 392 | for f, e in self._map.iteritems(): |
|
390 | 393 | if f in copymap: |
|
391 | 394 | f = "%s\0%s" % (f, copymap[f]) |
|
392 | if gran > 0 and e[0] == 'n' and llimit < e[3] <= hlimit: | |
|
393 | # file was updated too recently, ignore stat data | |
|
394 | e = (e[0], 0, -1, -1) | |
|
395 | ||
|
396 | if e[0] == 'n' and e[3] == now: | |
|
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 | 408 | e = pack(_format, e[0], e[1], e[2], e[3], len(f)) |
|
396 | 409 | write(e) |
|
397 | 410 | write(f) |
@@ -411,11 +424,11 b' class dirstate(object):' | |||
|
411 | 424 | |
|
412 | 425 | def walk(self, match, unknown, ignored): |
|
413 | 426 | ''' |
|
414 |
|
|
|
415 |
matched by |
|
|
427 | Walk recursively through the directory tree, finding all files | |
|
428 | matched by match. | |
|
416 | 429 | |
|
417 | results are yielded in a tuple (filename, stat), where stat | |
|
418 | and st is the stat result if the file was found in the directory. | |
|
430 | Return a dict mapping filename to stat-like object (either | |
|
431 | mercurial.osutil.stat instance or return value of os.stat()). | |
|
419 | 432 | ''' |
|
420 | 433 | |
|
421 | 434 | def fwarn(f, msg): |
@@ -553,12 +566,38 b' class dirstate(object):' | |||
|
553 | 566 | return results |
|
554 | 567 | |
|
555 | 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 | 595 | listignored, listclean, listunknown = ignored, clean, unknown |
|
557 | 596 | lookup, modified, added, unknown, ignored = [], [], [], [], [] |
|
558 | 597 | removed, deleted, clean = [], [], [] |
|
559 | 598 | |
|
560 | 599 | dmap = self._map |
|
561 | ladd = lookup.append | |
|
600 | ladd = lookup.append # aka "unsure" | |
|
562 | 601 | madd = modified.append |
|
563 | 602 | aadd = added.append |
|
564 | 603 | uadd = unknown.append |
@@ -165,17 +165,11 b' def testpid(pid):' | |||
|
165 | 165 | return inst.errno != errno.ESRCH |
|
166 | 166 | |
|
167 | 167 | def explain_exit(code): |
|
168 |
"""return a 2-tuple (desc, code) describing a process |
|
|
169 | if os.WIFEXITED(code): | |
|
170 | val = os.WEXITSTATUS(code) | |
|
171 |
return _("exited with status %d") % |
|
|
172 | elif os.WIFSIGNALED(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")) | |
|
168 | """return a 2-tuple (desc, code) describing a subprocess status | |
|
169 | (codes from kill are negative - not os.system/wait encoding)""" | |
|
170 | if code >= 0: | |
|
171 | return _("exited with status %d") % code, code | |
|
172 | return _("killed by signal %d") % -code, -code | |
|
179 | 173 | |
|
180 | 174 | def isowner(st): |
|
181 | 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 | 48 | try: |
|
49 | 49 | repo.ui.debug('scanning\n') |
|
50 | 50 | for name, ename, size in repo.store.walk(): |
|
51 | # for backwards compat, name was partially encoded | |
|
52 | entries.append((store.encodedir(name), size)) | |
|
51 | entries.append((name, size)) | |
|
53 | 52 | total_bytes += size |
|
54 | 53 | finally: |
|
55 | 54 | lock.release() |
@@ -62,6 +61,7 b' def stream_out(repo, untrusted=False):' | |||
|
62 | 61 | yield '%d %d\n' % (len(entries), total_bytes) |
|
63 | 62 | for name, size in entries: |
|
64 | 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 | 66 | for chunk in util.filechunkiter(repo.sopener(name), limit=size): |
|
67 | 67 | yield chunk |
@@ -167,7 +167,7 b' class hgsubrepo(object):' | |||
|
167 | 167 | self._repo.ui.note(_('removing subrepo %s\n') % self._path) |
|
168 | 168 | hg.clean(self._repo, node.nullid, False) |
|
169 | 169 | |
|
170 | def get(self, state): | |
|
170 | def _get(self, state): | |
|
171 | 171 | source, revision = state |
|
172 | 172 | try: |
|
173 | 173 | self._repo.lookup(revision) |
@@ -178,9 +178,13 b' class hgsubrepo(object):' | |||
|
178 | 178 | other = hg.repository(self._repo.ui, srcurl) |
|
179 | 179 | self._repo.pull(other) |
|
180 | 180 | |
|
181 | def get(self, state): | |
|
182 | self._get(state) | |
|
183 | source, revision = state | |
|
181 | 184 | hg.clean(self._repo, revision, False) |
|
182 | 185 | |
|
183 | 186 | def merge(self, state): |
|
187 | self._get(state) | |
|
184 | 188 | hg.merge(self._repo, state[1], remind=False) |
|
185 | 189 | |
|
186 | 190 | def push(self, force): |
@@ -357,41 +357,26 b' def system(cmd, environ={}, cwd=None, on' | |||
|
357 | 357 | if val is True: |
|
358 | 358 | return '1' |
|
359 | 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 | 360 | origcmd = cmd |
|
366 | 361 | if os.name == 'nt': |
|
367 | 362 | cmd = '"%s"' % cmd |
|
368 | try: | |
|
369 |
|
|
|
370 | os.environ[k] = py2shell(v) | |
|
371 | os.environ['HG'] = hgexecutable() | |
|
372 | if cwd is not None and oldcwd != cwd: | |
|
373 | os.chdir(cwd) | |
|
374 |
rc = |
|
|
375 | if sys.platform == 'OpenVMS' and rc & 1: | |
|
376 | rc = 0 | |
|
377 | if rc and onerr: | |
|
378 | errmsg = '%s %s' % (os.path.basename(origcmd.split(None, 1)[0]), | |
|
379 | explain_exit(rc)[0]) | |
|
380 | if errprefix: | |
|
381 | errmsg = '%s: %s' % (errprefix, errmsg) | |
|
382 | try: | |
|
383 |
|
|
|
384 | except AttributeError: | |
|
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) | |
|
363 | env = dict(os.environ) | |
|
364 | env.update((k, py2shell(v)) for k, v in environ.iteritems()) | |
|
365 | env['HG'] = hgexecutable() | |
|
366 | rc = subprocess.call(cmd, shell=True, close_fds=closefds, | |
|
367 | env=env, cwd=cwd) | |
|
368 | if sys.platform == 'OpenVMS' and rc & 1: | |
|
369 | rc = 0 | |
|
370 | if rc and onerr: | |
|
371 | errmsg = '%s %s' % (os.path.basename(origcmd.split(None, 1)[0]), | |
|
372 | explain_exit(rc)[0]) | |
|
373 | if errprefix: | |
|
374 | errmsg = '%s: %s' % (errprefix, errmsg) | |
|
375 | try: | |
|
376 | onerr.warn(errmsg + '\n') | |
|
377 | except AttributeError: | |
|
378 | raise onerr(errmsg) | |
|
379 | return rc | |
|
395 | 380 | |
|
396 | 381 | def checksignature(func): |
|
397 | 382 | '''wrap a function with code to check for calling errors''' |
@@ -1280,9 +1265,12 b' def wrap(line, hangindent, width=None):' | |||
|
1280 | 1265 | padding = '\n' + ' ' * hangindent |
|
1281 | 1266 | # To avoid corrupting multi-byte characters in line, we must wrap |
|
1282 | 1267 | # a Unicode string instead of a bytestring. |
|
1283 | u = line.decode(encoding.encoding) | |
|
1284 | w = padding.join(textwrap.wrap(u, width=width - hangindent)) | |
|
1285 | return w.encode(encoding.encoding) | |
|
1268 | try: | |
|
1269 | u = line.decode(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 | 1275 | def iterlines(iterator): |
|
1288 | 1276 | for chunk in iterator: |
@@ -5,6 +5,11 b' cp "$TESTDIR"/printenv.py .' | |||
|
5 | 5 | hg init test |
|
6 | 6 | cd test |
|
7 | 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 | 13 | hg commit -A -m 1 |
|
9 | 14 | hg --config server.uncompressed=True serve -p $HGPORT -d --pid-file=../hg1.pid |
|
10 | 15 | hg serve -p $HGPORT1 -d --pid-file=../hg2.pid |
@@ -1,4 +1,7 b'' | |||
|
1 | 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 | 5 | abort: cannot start server at ':20060': |
|
3 | 6 | % clone via stream |
|
4 | 7 | streaming all changes |
@@ -10,31 +13,31 b' checking changesets' | |||
|
10 | 13 | checking manifests |
|
11 | 14 | crosschecking files in changesets and manifests |
|
12 | 15 | checking files |
|
13 |
|
|
|
16 | 4 files, 1 changesets, 4 total revisions | |
|
14 | 17 | % try to clone via stream, should use pull instead |
|
15 | 18 | requesting all changes |
|
16 | 19 | adding changesets |
|
17 | 20 | adding manifests |
|
18 | 21 | adding file changes |
|
19 |
added 1 changesets with |
|
|
22 | added 1 changesets with 4 changes to 4 files | |
|
20 | 23 | updating working directory |
|
21 |
|
|
|
24 | 4 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
22 | 25 | % clone via pull |
|
23 | 26 | requesting all changes |
|
24 | 27 | adding changesets |
|
25 | 28 | adding manifests |
|
26 | 29 | adding file changes |
|
27 |
added 1 changesets with |
|
|
30 | added 1 changesets with 4 changes to 4 files | |
|
28 | 31 | updating working directory |
|
29 |
|
|
|
32 | 4 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
30 | 33 | checking changesets |
|
31 | 34 | checking manifests |
|
32 | 35 | crosschecking files in changesets and manifests |
|
33 | 36 | checking files |
|
34 |
|
|
|
37 | 4 files, 1 changesets, 4 total revisions | |
|
35 | 38 | adding bar |
|
36 | 39 | % pull |
|
37 |
changegroup hook: HG_NODE= |
|
|
40 | changegroup hook: HG_NODE=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_SOURCE=pull HG_URL=http://localhost/ | |
|
38 | 41 | pulling from http://localhost/ |
|
39 | 42 | searching for changes |
|
40 | 43 | adding changesets |
@@ -1,5 +1,5 b'' | |||
|
1 | 1 | % fail |
|
2 | could not talk to new inotify server: No such file or directory | |
|
2 | abort: could not start server: File exists | |
|
3 | 3 | abort: could not start server: File exists |
|
4 | 4 | % inserve |
|
5 | 5 | % status |
@@ -48,6 +48,11 b" echo 'ignore $Id$' > b" | |||
|
48 | 48 | echo % cat |
|
49 | 49 | cat a b |
|
50 | 50 | |
|
51 | echo % no kwfiles | |
|
52 | hg kwfiles | |
|
53 | echo % untracked candidates | |
|
54 | hg -v kwfiles --unknown | |
|
55 | ||
|
51 | 56 | echo % addremove |
|
52 | 57 | hg addremove |
|
53 | 58 | echo % status |
@@ -162,6 +167,10 b' hg status' | |||
|
162 | 167 | |
|
163 | 168 | echo % kwfiles |
|
164 | 169 | hg kwfiles |
|
170 | echo % ignored files | |
|
171 | hg -v kwfiles --ignore | |
|
172 | echo % all files | |
|
173 | hg kwfiles --all | |
|
165 | 174 | |
|
166 | 175 | echo % diff --rev |
|
167 | 176 | hg diff --rev 1 | grep -v 'b/c' |
@@ -42,6 +42,9 b' expand $Id$' | |||
|
42 | 42 | do not process $Id: |
|
43 | 43 | xxx $ |
|
44 | 44 | ignore $Id$ |
|
45 | % no kwfiles | |
|
46 | % untracked candidates | |
|
47 | k a | |
|
45 | 48 | % addremove |
|
46 | 49 | adding a |
|
47 | 50 | adding b |
@@ -181,6 +184,14 b' xxx $' | |||
|
181 | 184 | % kwfiles |
|
182 | 185 | a |
|
183 | 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 | 195 | % diff --rev |
|
185 | 196 | diff -r ef63ca68695b c |
|
186 | 197 | --- /dev/null Thu Jan 01 00:00:00 1970 +0000 |
@@ -35,6 +35,7 b' Optional configuration items:' | |||
|
35 | 35 | diffstat = True # add a diffstat before the diff content |
|
36 | 36 | sources = serve # notify if source of incoming changes in this list |
|
37 | 37 | # (serve == ssh or http, push, pull, bundle) |
|
38 | merge = False # send notification for merges (default True) | |
|
38 | 39 | [email] |
|
39 | 40 | from = user@host.com # email address to send as if none given |
|
40 | 41 | [web] |
General Comments 0
You need to be logged in to leave comments.
Login now