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 |
|
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 |
|
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 |
|
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 |
|
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 |
mod |
|
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 |
|
|
161 | if len(common) == 1: | |
133 | dir1 = os.path.join(dir1, util.localpath(modified[0])) |
|
162 | common_file = util.localpath(common.pop()) | |
134 |
|
|
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 |
|
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 = |
|
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 |
|
835 | except AlreadyStartedException, inst: | |
845 |
|
|
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, |
|
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, |
|
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 ( |
|
389 | k = keyword expansion candidate (not tracked) | |
390 | I = ignored |
|
390 | I = ignored | |
391 |
i = ignored ( |
|
391 | i = ignored (not tracked) | |
392 | ''' |
|
392 | ''' | |
393 | kwt = kwtools['templater'] |
|
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 | 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 |
kwun |
|
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 |
|
|
408 | showfiles += ([f for f in files if f not in kwfiles], | |
405 |
|
|
409 | [f for f in unknown if f not in kwunknown]) | |
406 |
for char, filenames in |
|
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 |
[(' |
|
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', '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 | ] + 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-0 |
|
20 | "POT-Creation-Date: 2009-09-29 00:26+0200\n" | |
21 |
"PO-Revision-Date: 2009-0 |
|
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 |
|
5571 | " Repository \"heads\" are changesets with no child changesets. They are\n" | |
5529 |
" |
|
5572 | " where development generally takes place and are the usual targets\n" | |
5530 |
" |
|
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 th |
|
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 |
|
5581 | " merged into another branch, or it could be the last changeset on the\n" | |
5539 |
" was created. If none of the branch heads |
|
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 he |
|
6791 | msgid "show normal and closed branches" | |
6736 |
msgstr "vis normale og lukkede |
|
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 t |
|
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 |
|
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 |
|
7839 | " Any other string is treated as a tag or branch name. A tag name is\n" | |
7783 |
" name associated with a revision identifier. |
|
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 |
|
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 t |
|
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 |
|
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 |
|
9826 | " Any other string is treated as a tag or branch name. A tag name is\n" | |
9829 |
" name associated with a revision identifier. |
|
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, |
|
9855 | " um identificador único de revisão, chamado de identificador\n" | |
9860 |
" |
|
9856 | " curto. Um identificador curto é válido apenas se for o prefixo\n" | |
9861 |
" |
|
9857 | " de um identificador completo.\n" | |
9862 | "\n" |
|
9858 | "\n" | |
9863 |
" Qualquer outra string é tratada como um nome de etiqueta |
|
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 |
|
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 |
|
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 |
" |
|
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 |
|
1359 | Repository "heads" are changesets with no child changesets. They are | |
1360 |
|
|
1360 | where development generally takes place and are the usual targets | |
1361 |
|
|
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 th |
|
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 |
|
1369 | merged into another branch, or it could be the last changeset on the | |
1370 |
was created. If none of the branch heads |
|
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 |
|
|
179 | n normal | |
175 | r marked for removal |
|
180 | m needs merging | |
176 |
|
|
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 |
|
|
427 | Walk recursively through the directory tree, finding all files | |
415 |
matched by |
|
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 |
|
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") % |
|
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 |
|
|
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 = |
|
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 |
|
|
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 |
|
|
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 |
|
22 | added 1 changesets with 4 changes to 4 files | |
20 | updating working directory |
|
23 | updating working directory | |
21 |
|
|
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 |
|
30 | added 1 changesets with 4 changes to 4 files | |
28 | updating working directory |
|
31 | updating working directory | |
29 |
|
|
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 |
|
|
37 | 4 files, 1 changesets, 4 total revisions | |
35 | adding bar |
|
38 | adding bar | |
36 | % pull |
|
39 | % pull | |
37 |
changegroup hook: HG_NODE= |
|
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