Show More
@@ -382,14 +382,27 b" Handle frickin' frackin' gratuitous even" | |||||
382 | (set-buffer hg-prev-buffer)) |
|
382 | (set-buffer hg-prev-buffer)) | |
383 | (let ((path (or default (buffer-file-name)))) |
|
383 | (let ((path (or default (buffer-file-name)))) | |
384 | (if (or (not path) current-prefix-arg) |
|
384 | (if (or (not path) current-prefix-arg) | |
385 |
|
|
385 | (expand-file-name | |
386 | (read-file-name (format "File, directory or pattern%s: " |
|
386 | (eval (list* 'read-file-name | |
387 | (or prompt "")) |
|
387 | (format "File, directory or pattern%s: " | |
388 | (and path (file-name-directory path)) |
|
388 | (or prompt "")) | |
389 | nil nil |
|
389 | (and path (file-name-directory path)) | |
390 | (and path (file-name-nondirectory path)) |
|
390 | nil nil | |
391 | 'hg-file-history)) |
|
391 | (and path (file-name-nondirectory path)) | |
392 | path)))) |
|
392 | (if hg-running-xemacs | |
|
393 | (cons (quote 'hg-file-history) nil) | |||
|
394 | nil)))) | |||
|
395 | path)))) | |||
|
396 | ||||
|
397 | (defun hg-read-number (&optional prompt default) | |||
|
398 | "Read a integer value." | |||
|
399 | (save-excursion | |||
|
400 | (if (or (not default) current-prefix-arg) | |||
|
401 | (string-to-number | |||
|
402 | (eval (list* 'read-string | |||
|
403 | (or prompt "") | |||
|
404 | (if default (cons (format "%d" default) nil) nil)))) | |||
|
405 | default))) | |||
393 |
|
406 | |||
394 | (defun hg-read-config () |
|
407 | (defun hg-read-config () | |
395 | "Return an alist of (key . value) pairs of Mercurial config data. |
|
408 | "Return an alist of (key . value) pairs of Mercurial config data. | |
@@ -950,36 +963,55 b' With a prefix argument, prompt for the p' | |||||
950 | (kill-entire-line)) |
|
963 | (kill-entire-line)) | |
951 | (run-hooks 'hg-log-mode-hook)) |
|
964 | (run-hooks 'hg-log-mode-hook)) | |
952 |
|
965 | |||
953 | (defun hg-log (path &optional rev1 rev2) |
|
966 | (defun hg-log (path &optional rev1 rev2 log-limit) | |
954 |
"Display the revision history of PATH |
|
967 | "Display the revision history of PATH. | |
955 | REV1 defaults to hg-log-limit changes from the tip revision, while |
|
968 | History is displayed between REV1 and REV2. | |
956 | REV2 defaults to the tip. |
|
969 | Number of displayed changesets is limited to LOG-LIMIT. | |
|
970 | REV1 defaults to the tip, while | |||
|
971 | REV2 defaults to `hg-rev-completion-limit' changes from the tip revision. | |||
|
972 | LOG-LIMIT defaults to `hg-log-limit'. | |||
957 | With a prefix argument, prompt for each parameter." |
|
973 | With a prefix argument, prompt for each parameter." | |
958 | (interactive (list (hg-read-file-name " to log") |
|
974 | (interactive (list (hg-read-file-name " to log") | |
959 |
|
|
975 | (hg-read-rev " to start with" | |
960 | (hg-read-rev " to end with" (format "-%d" hg-log-limit)))) |
|
976 | "tip") | |
|
977 | (hg-read-rev " to end with" | |||
|
978 | (format "%d" (- hg-rev-completion-limit))) | |||
|
979 | (hg-read-number "Output limited to: " | |||
|
980 | hg-log-limit))) | |||
961 | (let ((a-path (hg-abbrev-file-name path)) |
|
981 | (let ((a-path (hg-abbrev-file-name path)) | |
962 |
|
|
982 | (r1 (or rev1 (format "-%d" hg-rev-completion-limit))) | |
963 |
|
|
983 | (r2 (or rev2 rev1 "tip")) | |
|
984 | (limit (format "%d" (or log-limit hg-log-limit)))) | |||
964 | (hg-view-output ((if (equal r1 r2) |
|
985 | (hg-view-output ((if (equal r1 r2) | |
965 |
|
|
986 | (format "Mercurial: Log of rev %s of %s" rev1 a-path) | |
966 | (format "Mercurial: Log from rev %s to %s of %s" |
|
987 | (format | |
967 | r1 r2 a-path))) |
|
988 | "Mercurial: at most %s log(s) from rev %s to %s of %s" | |
968 | (let ((revs (format "%s:%s" r1 r2))) |
|
989 | limit r1 r2 a-path))) | |
969 | (if (> (length path) (length (hg-root path))) |
|
990 | (eval (list* 'call-process (hg-binary) nil t nil | |
970 | (call-process (hg-binary) nil t nil "log" "-r" revs path) |
|
991 | "log" | |
971 | (call-process (hg-binary) nil t nil "log" "-r" revs))) |
|
992 | "-r" (format "%s:%s" r1 r2) | |
|
993 | "-l" limit | |||
|
994 | (if (> (length path) (length (hg-root path))) | |||
|
995 | (cons path nil) | |||
|
996 | nil))) | |||
972 | (hg-log-mode)))) |
|
997 | (hg-log-mode)))) | |
973 |
|
998 | |||
974 | (defun hg-log-repo (path &optional rev1 rev2) |
|
999 | (defun hg-log-repo (path &optional rev1 rev2 log-limit) | |
975 | "Display the revision history of the repository containing PATH. |
|
1000 | "Display the revision history of the repository containing PATH. | |
976 |
History is displayed between REV1 |
|
1001 | History is displayed between REV1 and REV2. | |
977 | REV2, which defaults to the initial revision. |
|
1002 | Number of displayed changesets is limited to LOG-LIMIT, | |
978 | Variable hg-log-limit controls the number of log entries displayed." |
|
1003 | REV1 defaults to the tip, while | |
|
1004 | REV2 defaults to `hg-rev-completion-limit' changes from the tip revision. | |||
|
1005 | LOG-LIMIT defaults to `hg-log-limit'. | |||
|
1006 | With a prefix argument, prompt for each parameter." | |||
979 | (interactive (list (hg-read-file-name " to log") |
|
1007 | (interactive (list (hg-read-file-name " to log") | |
980 |
|
|
1008 | (hg-read-rev " to start with" | |
981 | (hg-read-rev " to end with" (format "-%d" hg-log-limit)))) |
|
1009 | "tip") | |
982 | (hg-log (hg-root path) rev1 rev2)) |
|
1010 | (hg-read-rev " to end with" | |
|
1011 | (format "%d" (- hg-rev-completion-limit))) | |||
|
1012 | (hg-read-number "Output limited to: " | |||
|
1013 | hg-log-limit))) | |||
|
1014 | (hg-log (hg-root path) rev1 rev2 log-limit)) | |||
983 |
|
1015 | |||
984 | (defun hg-outgoing (&optional repo) |
|
1016 | (defun hg-outgoing (&optional repo) | |
985 | "Display changesets present locally that are not present in REPO." |
|
1017 | "Display changesets present locally that are not present in REPO." |
@@ -90,8 +90,14 b' hg' | |||||
90 | other Mercurial commands should work fine for you.</p> |
|
90 | other Mercurial commands should work fine for you.</p> | |
91 |
|
91 | |||
92 | <h1>Configuration notes</h1> |
|
92 | <h1>Configuration notes</h1> | |
93 |
<p>The default editor is 'vi'. You can set the EDITOR |
|
93 | <p>The default editor for commit messages is 'vi'. You can set the EDITOR | |
94 |
(or HGEDITOR) to specify your preference |
|
94 | (or HGEDITOR) environment variable to specify your preference or set it in | |
|
95 | mercurial.ini:</p> | |||
|
96 | <pre> | |||
|
97 | [ui] | |||
|
98 | editor = whatever | |||
|
99 | </pre> | |||
|
100 | ||||
95 |
|
101 | |||
96 | <h1>Reporting problems</h1> |
|
102 | <h1>Reporting problems</h1> | |
97 |
|
103 |
@@ -36,11 +36,14 b' installed.' | |||||
36 | files override per-installation options. |
|
36 | files override per-installation options. | |
37 |
|
37 | |||
38 | (Unix) $HOME/.hgrc:: |
|
38 | (Unix) $HOME/.hgrc:: | |
39 | (Windows) C:\Documents and Settings\USERNAME\Mercurial.ini |
|
39 | (Windows) C:\Documents and Settings\USERNAME\Mercurial.ini:: | |
|
40 | (Windows) $HOME\Mercurial.ini:: | |||
40 | Per-user configuration file, for the user running Mercurial. |
|
41 | Per-user configuration file, for the user running Mercurial. | |
41 | Options in this file apply to all Mercurial commands executed by |
|
42 | Options in this file apply to all Mercurial commands executed by | |
42 | any user in any directory. Options in this file override |
|
43 | any user in any directory. Options in this file override | |
43 | per-installation and per-system options. |
|
44 | per-installation and per-system options. | |
|
45 | On Windows system, one of these is chosen exclusively according | |||
|
46 | to definition of HOME environment variable. | |||
44 |
|
47 | |||
45 | (Unix, Windows) <repo>/.hg/hgrc:: |
|
48 | (Unix, Windows) <repo>/.hg/hgrc:: | |
46 | Per-repository configuration options that only apply in a |
|
49 | Per-repository configuration options that only apply in a |
@@ -99,7 +99,9 b' class notifier(object):' | |||||
99 |
|
99 | |||
100 | def __init__(self, ui, repo, hooktype): |
|
100 | def __init__(self, ui, repo, hooktype): | |
101 | self.ui = ui |
|
101 | self.ui = ui | |
102 |
|
|
102 | cfg = self.ui.config('notify', 'config') | |
|
103 | if cfg: | |||
|
104 | self.ui.readconfig(cfg) | |||
103 | self.repo = repo |
|
105 | self.repo = repo | |
104 | self.stripcount = int(self.ui.config('notify', 'strip', 0)) |
|
106 | self.stripcount = int(self.ui.config('notify', 'strip', 0)) | |
105 | self.root = self.strip(self.repo.root) |
|
107 | self.root = self.strip(self.repo.root) | |
@@ -123,7 +125,7 b' class notifier(object):' | |||||
123 |
|
125 | |||
124 | path = util.pconvert(path) |
|
126 | path = util.pconvert(path) | |
125 | count = self.stripcount |
|
127 | count = self.stripcount | |
126 |
while |
|
128 | while count > 0: | |
127 | c = path.find('/') |
|
129 | c = path.find('/') | |
128 | if c == -1: |
|
130 | if c == -1: | |
129 | break |
|
131 | break | |
@@ -225,6 +227,8 b' class notifier(object):' | |||||
225 | if not msgtext.endswith('\n'): |
|
227 | if not msgtext.endswith('\n'): | |
226 | self.ui.write('\n') |
|
228 | self.ui.write('\n') | |
227 | else: |
|
229 | else: | |
|
230 | self.ui.status(_('notify: sending %d subscribers %d changes\n') % | |||
|
231 | (len(self.subs), count)) | |||
228 | mail = self.ui.sendmail() |
|
232 | mail = self.ui.sendmail() | |
229 | mail.sendmail(templater.email(msg['From']), self.subs, msgtext) |
|
233 | mail.sendmail(templater.email(msg['From']), self.subs, msgtext) | |
230 |
|
234 | |||
@@ -250,7 +254,12 b' def hook(ui, repo, hooktype, node=None, ' | |||||
250 | if used as changegroup hook, send one email for all changesets in |
|
254 | if used as changegroup hook, send one email for all changesets in | |
251 | changegroup. else send one email per changeset.''' |
|
255 | changegroup. else send one email per changeset.''' | |
252 | n = notifier(ui, repo, hooktype) |
|
256 | n = notifier(ui, repo, hooktype) | |
253 |
if not n.subs |
|
257 | if not n.subs: | |
|
258 | ui.debug(_('notify: no subscribers to this repo\n')) | |||
|
259 | return | |||
|
260 | if n.skipsource(source): | |||
|
261 | ui.debug(_('notify: changes have source "%s" - skipping\n') % | |||
|
262 | source) | |||
254 | return |
|
263 | return | |
255 | node = bin(node) |
|
264 | node = bin(node) | |
256 | if hooktype == 'changegroup': |
|
265 | if hooktype == 'changegroup': |
@@ -519,7 +519,8 b' class hgweb(object):' | |||||
519 | mnode = hex(mn) |
|
519 | mnode = hex(mn) | |
520 | mf = man.read(mn) |
|
520 | mf = man.read(mn) | |
521 | rev = man.rev(mn) |
|
521 | rev = man.rev(mn) | |
522 | node = self.repo.changelog.node(rev) |
|
522 | changerev = man.linkrev(mn) | |
|
523 | node = self.repo.changelog.node(changerev) | |||
523 | mff = man.readflags(mn) |
|
524 | mff = man.readflags(mn) | |
524 |
|
525 | |||
525 | files = {} |
|
526 | files = {} |
@@ -166,37 +166,44 b' class localrepository(object):' | |||||
166 | return |
|
166 | return | |
167 | s = l.split(" ", 1) |
|
167 | s = l.split(" ", 1) | |
168 | if len(s) != 2: |
|
168 | if len(s) != 2: | |
169 |
self.ui.warn(_("%s: |
|
169 | self.ui.warn(_("%s: cannot parse entry\n") % context) | |
170 | return |
|
170 | return | |
171 | node, key = s |
|
171 | node, key = s | |
|
172 | key = key.strip() | |||
172 | try: |
|
173 | try: | |
173 | bin_n = bin(node) |
|
174 | bin_n = bin(node) | |
174 | except TypeError: |
|
175 | except TypeError: | |
175 |
self.ui.warn(_("%s: |
|
176 | self.ui.warn(_("%s: node '%s' is not well formed\n") % | |
|
177 | (context, node)) | |||
176 | return |
|
178 | return | |
177 | if bin_n not in self.changelog.nodemap: |
|
179 | if bin_n not in self.changelog.nodemap: | |
178 |
self.ui.warn(_("%s: |
|
180 | self.ui.warn(_("%s: tag '%s' refers to unknown node\n") % | |
|
181 | (context, key)) | |||
179 | return |
|
182 | return | |
180 |
self.tagscache[key |
|
183 | self.tagscache[key] = bin_n | |
181 |
|
184 | |||
182 |
# read |
|
185 | # read the tags file from each head, ending with the tip, | |
183 | # and add each tag found to the map, with "newer" ones |
|
186 | # and add each tag found to the map, with "newer" ones | |
184 | # taking precedence |
|
187 | # taking precedence | |
|
188 | heads = self.heads() | |||
|
189 | heads.reverse() | |||
185 | fl = self.file(".hgtags") |
|
190 | fl = self.file(".hgtags") | |
186 |
|
|
191 | for node in heads: | |
187 | h.reverse() |
|
192 | change = self.changelog.read(node) | |
188 | for r in h: |
|
193 | rev = self.changelog.rev(node) | |
|
194 | fn, ff = self.manifest.find(change[0], '.hgtags') | |||
|
195 | if fn is None: continue | |||
189 | count = 0 |
|
196 | count = 0 | |
190 |
for l in fl.read( |
|
197 | for l in fl.read(fn).splitlines(): | |
191 | count += 1 |
|
198 | count += 1 | |
192 |
parsetag(l, ".hgtags:%d" % |
|
199 | parsetag(l, _(".hgtags (rev %d:%s), line %d") % | |
193 |
|
200 | (rev, short(node), count)) | ||
194 | try: |
|
201 | try: | |
195 | f = self.opener("localtags") |
|
202 | f = self.opener("localtags") | |
196 | count = 0 |
|
203 | count = 0 | |
197 | for l in f: |
|
204 | for l in f: | |
198 | count += 1 |
|
205 | count += 1 | |
199 |
parsetag(l, "localtags |
|
206 | parsetag(l, _("localtags, line %d") % count) | |
200 | except IOError: |
|
207 | except IOError: | |
201 | pass |
|
208 | pass | |
202 |
|
209 |
@@ -43,48 +43,61 b' class manifest(revlog):' | |||||
43 | def diff(self, a, b): |
|
43 | def diff(self, a, b): | |
44 | return mdiff.textdiff(str(a), str(b)) |
|
44 | return mdiff.textdiff(str(a), str(b)) | |
45 |
|
45 | |||
|
46 | def _search(self, m, s, lo=0, hi=None): | |||
|
47 | '''return a tuple (start, end) that says where to find s within m. | |||
|
48 | ||||
|
49 | If the string is found m[start:end] are the line containing | |||
|
50 | that string. If start == end the string was not found and | |||
|
51 | they indicate the proper sorted insertion point. This was | |||
|
52 | taken from bisect_left, and modified to find line start/end as | |||
|
53 | it goes along. | |||
|
54 | ||||
|
55 | m should be a buffer or a string | |||
|
56 | s is a string''' | |||
|
57 | def advance(i, c): | |||
|
58 | while i < lenm and m[i] != c: | |||
|
59 | i += 1 | |||
|
60 | return i | |||
|
61 | lenm = len(m) | |||
|
62 | if not hi: | |||
|
63 | hi = lenm | |||
|
64 | while lo < hi: | |||
|
65 | mid = (lo + hi) // 2 | |||
|
66 | start = mid | |||
|
67 | while start > 0 and m[start-1] != '\n': | |||
|
68 | start -= 1 | |||
|
69 | end = advance(start, '\0') | |||
|
70 | if m[start:end] < s: | |||
|
71 | # we know that after the null there are 40 bytes of sha1 | |||
|
72 | # this translates to the bisect lo = mid + 1 | |||
|
73 | lo = advance(end + 40, '\n') + 1 | |||
|
74 | else: | |||
|
75 | # this translates to the bisect hi = mid | |||
|
76 | hi = start | |||
|
77 | end = advance(lo, '\0') | |||
|
78 | found = m[lo:end] | |||
|
79 | if cmp(s, found) == 0: | |||
|
80 | # we know that after the null there are 40 bytes of sha1 | |||
|
81 | end = advance(end + 40, '\n') | |||
|
82 | return (lo, end+1) | |||
|
83 | else: | |||
|
84 | return (lo, lo) | |||
|
85 | ||||
|
86 | def find(self, node, f): | |||
|
87 | '''look up entry for a single file efficiently. | |||
|
88 | return (node, flag) pair if found, (None, None) if not.''' | |||
|
89 | if self.mapcache and node == self.mapcache[0]: | |||
|
90 | return self.mapcache[1].get(f), self.mapcache[2].get(f) | |||
|
91 | text = self.revision(node) | |||
|
92 | start, end = self._search(text, f) | |||
|
93 | if start == end: | |||
|
94 | return None, None | |||
|
95 | l = text[start:end] | |||
|
96 | f, n = l.split('\0') | |||
|
97 | return bin(n[:40]), n[40:-1] == 'x' | |||
|
98 | ||||
46 | def add(self, map, flags, transaction, link, p1=None, p2=None, |
|
99 | def add(self, map, flags, transaction, link, p1=None, p2=None, | |
47 | changed=None): |
|
100 | changed=None): | |
48 |
|
||||
49 | # returns a tuple (start, end). If the string is found |
|
|||
50 | # m[start:end] are the line containing that string. If start == end |
|
|||
51 | # the string was not found and they indicate the proper sorted |
|
|||
52 | # insertion point. This was taken from bisect_left, and modified |
|
|||
53 | # to find line start/end as it goes along. |
|
|||
54 | # |
|
|||
55 | # m should be a buffer or a string |
|
|||
56 | # s is a string |
|
|||
57 | # |
|
|||
58 | def manifestsearch(m, s, lo=0, hi=None): |
|
|||
59 | def advance(i, c): |
|
|||
60 | while i < lenm and m[i] != c: |
|
|||
61 | i += 1 |
|
|||
62 | return i |
|
|||
63 | lenm = len(m) |
|
|||
64 | if not hi: |
|
|||
65 | hi = lenm |
|
|||
66 | while lo < hi: |
|
|||
67 | mid = (lo + hi) // 2 |
|
|||
68 | start = mid |
|
|||
69 | while start > 0 and m[start-1] != '\n': |
|
|||
70 | start -= 1 |
|
|||
71 | end = advance(start, '\0') |
|
|||
72 | if m[start:end] < s: |
|
|||
73 | # we know that after the null there are 40 bytes of sha1 |
|
|||
74 | # this translates to the bisect lo = mid + 1 |
|
|||
75 | lo = advance(end + 40, '\n') + 1 |
|
|||
76 | else: |
|
|||
77 | # this translates to the bisect hi = mid |
|
|||
78 | hi = start |
|
|||
79 | end = advance(lo, '\0') |
|
|||
80 | found = m[lo:end] |
|
|||
81 | if cmp(s, found) == 0: |
|
|||
82 | # we know that after the null there are 40 bytes of sha1 |
|
|||
83 | end = advance(end + 40, '\n') |
|
|||
84 | return (lo, end+1) |
|
|||
85 | else: |
|
|||
86 | return (lo, lo) |
|
|||
87 |
|
||||
88 | # apply the changes collected during the bisect loop to our addlist |
|
101 | # apply the changes collected during the bisect loop to our addlist | |
89 | # return a delta suitable for addrevision |
|
102 | # return a delta suitable for addrevision | |
90 | def addlistdelta(addlist, x): |
|
103 | def addlistdelta(addlist, x): | |
@@ -137,7 +150,7 b' class manifest(revlog):' | |||||
137 | for w in work: |
|
150 | for w in work: | |
138 | f = w[0] |
|
151 | f = w[0] | |
139 | # bs will either be the index of the item or the insert point |
|
152 | # bs will either be the index of the item or the insert point | |
140 |
start, end = |
|
153 | start, end = self._search(addbuf, f, start) | |
141 | if w[1] == 0: |
|
154 | if w[1] == 0: | |
142 | l = "%s\000%s%s\n" % (f, hex(map[f]), |
|
155 | l = "%s\000%s%s\n" % (f, hex(map[f]), | |
143 | flags[f] and "x" or '') |
|
156 | flags[f] and "x" or '') |
@@ -1,5 +1,6 b'' | |||||
1 | # packagescan.py - Helper module for identifing used modules. |
|
1 | # packagescan.py - Helper module for identifing used modules. | |
2 | # Used for the py2exe distutil. |
|
2 | # Used for the py2exe distutil. | |
|
3 | # This module must be the first mercurial module imported in setup.py | |||
3 | # |
|
4 | # | |
4 | # Copyright 2005 Volker Kleinfeld <Volker.Kleinfeld@gmx.de> |
|
5 | # Copyright 2005 Volker Kleinfeld <Volker.Kleinfeld@gmx.de> | |
5 | # |
|
6 | # | |
@@ -8,25 +9,58 b'' | |||||
8 | import glob |
|
9 | import glob | |
9 | import os |
|
10 | import os | |
10 | import sys |
|
11 | import sys | |
11 | import demandload |
|
|||
12 | import ihooks |
|
12 | import ihooks | |
|
13 | import types | |||
|
14 | import string | |||
|
15 | ||||
|
16 | # Install this module as fake demandload module | |||
|
17 | sys.modules['mercurial.demandload'] = sys.modules[__name__] | |||
13 |
|
18 | |||
14 |
|
|
19 | # Requiredmodules contains the modules imported by demandload. | |
|
20 | # Please note that demandload can be invoked before the | |||
|
21 | # mercurial.packagescan.scan method is invoked in case a mercurial | |||
|
22 | # module is imported. | |||
|
23 | requiredmodules = {} | |||
15 | def demandload(scope, modules): |
|
24 | def demandload(scope, modules): | |
16 |
""" fake demandload function that collects the required modules |
|
25 | """ fake demandload function that collects the required modules | |
|
26 | foo import foo | |||
|
27 | foo bar import foo, bar | |||
|
28 | foo.bar import foo.bar | |||
|
29 | foo:bar from foo import bar | |||
|
30 | foo:bar,quux from foo import bar, quux | |||
|
31 | foo.bar:quux from foo.bar import quux""" | |||
|
32 | ||||
17 | for m in modules.split(): |
|
33 | for m in modules.split(): | |
18 | mod = None |
|
34 | mod = None | |
19 | try: |
|
35 | try: | |
20 |
module, |
|
36 | module, fromlist = m.split(':') | |
21 |
|
|
37 | fromlist = fromlist.split(',') | |
22 | except: |
|
38 | except: | |
23 | module = m |
|
39 | module = m | |
24 |
|
|
40 | fromlist = [] | |
25 |
mod = __import__(module, scope, scope, |
|
41 | mod = __import__(module, scope, scope, fromlist) | |
26 | scope[module] = mod |
|
42 | if fromlist == []: | |
27 | requiredmodules[mod.__name__] = 1 |
|
43 | # mod is only the top package, but we need all packages | |
|
44 | comp = module.split('.') | |||
|
45 | i = 1 | |||
|
46 | mn = comp[0] | |||
|
47 | while True: | |||
|
48 | # mn and mod.__name__ might not be the same | |||
|
49 | scope[mn] = mod | |||
|
50 | requiredmodules[mod.__name__] = 1 | |||
|
51 | if len(comp) == i: break | |||
|
52 | mod = getattr(mod,comp[i]) | |||
|
53 | mn = string.join(comp[:i+1],'.') | |||
|
54 | i += 1 | |||
|
55 | else: | |||
|
56 | # mod is the last package in the component list | |||
|
57 | requiredmodules[mod.__name__] = 1 | |||
|
58 | for f in fromlist: | |||
|
59 | scope[f] = getattr(mod,f) | |||
|
60 | if type(scope[f]) == types.ModuleType: | |||
|
61 | requiredmodules[scope[f].__name__] = 1 | |||
28 |
|
62 | |||
29 |
def |
|
63 | def scan(libpath,packagename): | |
30 | """ helper for finding all required modules of package <packagename> """ |
|
64 | """ helper for finding all required modules of package <packagename> """ | |
31 | # Use the package in the build directory |
|
65 | # Use the package in the build directory | |
32 | libpath = os.path.abspath(libpath) |
|
66 | libpath = os.path.abspath(libpath) | |
@@ -45,8 +79,6 b' def getmodules(libpath,packagename):' | |||||
45 | pymodulefiles = glob.glob('*.py') |
|
79 | pymodulefiles = glob.glob('*.py') | |
46 | extmodulefiles = glob.glob('*.pyd') |
|
80 | extmodulefiles = glob.glob('*.pyd') | |
47 | os.chdir(cwd) |
|
81 | os.chdir(cwd) | |
48 | # Install a fake demandload module |
|
|||
49 | sys.modules['mercurial.demandload'] = sys.modules['mercurial.packagescan'] |
|
|||
50 | # Import all python modules and by that run the fake demandload |
|
82 | # Import all python modules and by that run the fake demandload | |
51 | for m in pymodulefiles: |
|
83 | for m in pymodulefiles: | |
52 | if m == '__init__.py': continue |
|
84 | if m == '__init__.py': continue | |
@@ -62,8 +94,9 b' def getmodules(libpath,packagename):' | |||||
62 | fullname = packagename+'.'+mname |
|
94 | fullname = packagename+'.'+mname | |
63 | __import__(fullname,tmp,tmp) |
|
95 | __import__(fullname,tmp,tmp) | |
64 | requiredmodules[fullname] = 1 |
|
96 | requiredmodules[fullname] = 1 | |
65 | includes = requiredmodules.keys() |
|
97 | ||
66 | return includes |
|
98 | def getmodules(): | |
|
99 | return requiredmodules.keys() | |||
67 |
|
100 | |||
68 | def importfrom(filename): |
|
101 | def importfrom(filename): | |
69 | """ |
|
102 | """ |
@@ -94,7 +94,7 b' def patch(strip, patchname, ui):' | |||||
94 | """apply the patch <patchname> to the working directory. |
|
94 | """apply the patch <patchname> to the working directory. | |
95 | a list of patched files is returned""" |
|
95 | a list of patched files is returned""" | |
96 | patcher = find_in_path('gpatch', os.environ.get('PATH', ''), 'patch') |
|
96 | patcher = find_in_path('gpatch', os.environ.get('PATH', ''), 'patch') | |
97 |
fp = os.popen(' |
|
97 | fp = os.popen('%s -p%d < "%s"' % (patcher, strip, patchname)) | |
98 | files = {} |
|
98 | files = {} | |
99 | for line in fp: |
|
99 | for line in fp: | |
100 | line = line.rstrip() |
|
100 | line = line.rstrip() |
@@ -194,7 +194,7 b' def user_rcpath():' | |||||
194 | # We are on win < nt: fetch the APPDATA directory location and use |
|
194 | # We are on win < nt: fetch the APPDATA directory location and use | |
195 | # the parent directory as the user home dir. |
|
195 | # the parent directory as the user home dir. | |
196 | appdir = shell.SHGetPathFromIDList( |
|
196 | appdir = shell.SHGetPathFromIDList( | |
197 |
|
|
197 | shell.SHGetSpecialFolderLocation(0, shellcon.CSIDL_APPDATA)) | |
198 | userdir = os.path.dirname(appdir) |
|
198 | userdir = os.path.dirname(appdir) | |
199 | return os.path.join(userdir, 'mercurial.ini') |
|
199 | return os.path.join(userdir, 'mercurial.ini') | |
200 |
|
200 |
@@ -13,6 +13,8 b' import glob' | |||||
13 | from distutils.core import setup, Extension |
|
13 | from distutils.core import setup, Extension | |
14 | from distutils.command.install_data import install_data |
|
14 | from distutils.command.install_data import install_data | |
15 |
|
15 | |||
|
16 | # mercurial.packagescan must be the first mercurial module imported | |||
|
17 | import mercurial.packagescan | |||
16 | import mercurial.version |
|
18 | import mercurial.version | |
17 |
|
19 | |||
18 | # py2exe needs to be installed to work |
|
20 | # py2exe needs to be installed to work | |
@@ -36,7 +38,6 b' try:' | |||||
36 | # Due to the use of demandload py2exe is not finding the modules. |
|
38 | # Due to the use of demandload py2exe is not finding the modules. | |
37 | # packagescan.getmodules creates a list of modules included in |
|
39 | # packagescan.getmodules creates a list of modules included in | |
38 | # the mercurial package plus depdent modules. |
|
40 | # the mercurial package plus depdent modules. | |
39 | import mercurial.packagescan |
|
|||
40 | from py2exe.build_exe import py2exe as build_exe |
|
41 | from py2exe.build_exe import py2exe as build_exe | |
41 |
|
42 | |||
42 | class py2exe_for_demandload(build_exe): |
|
43 | class py2exe_for_demandload(build_exe): | |
@@ -54,12 +55,10 b' try:' | |||||
54 | self.includes = [] |
|
55 | self.includes = [] | |
55 | else: |
|
56 | else: | |
56 | self.includes = self.includes.split(',') |
|
57 | self.includes = self.includes.split(',') | |
57 |
|
|
58 | mercurial.packagescan.scan(self.build_lib,'mercurial') | |
58 | 'mercurial') |
|
59 | mercurial.packagescan.scan(self.build_lib,'mercurial/hgweb') | |
59 |
|
|
60 | mercurial.packagescan.scan(self.build_lib,'hgext') | |
60 | 'mercurial/hgweb') |
|
61 | self.includes += mercurial.packagescan.getmodules() | |
61 | self.includes += mercurial.packagescan.getmodules(self.build_lib, |
|
|||
62 | 'hgext') |
|
|||
63 | build_exe.finalize_options(self) |
|
62 | build_exe.finalize_options(self) | |
64 | except ImportError: |
|
63 | except ImportError: | |
65 | py2exe_for_demandload = None |
|
64 | py2exe_for_demandload = None |
@@ -62,7 +62,7 b' echo %% --time' | |||||
62 | hg --cwd a --time tip 2>&1 | grep '^Time:' | sed 's/[0-9][0-9]*/x/g' |
|
62 | hg --cwd a --time tip 2>&1 | grep '^Time:' | sed 's/[0-9][0-9]*/x/g' | |
63 |
|
63 | |||
64 | echo %% --version |
|
64 | echo %% --version | |
65 | hg --version -q | sed 's/version [a-f0-9+]*/version xxx/' |
|
65 | hg --version -q | sed 's/version \([a-f0-9+]*\|unknown\)/version xxx/' | |
66 |
|
66 | |||
67 | echo %% -h/--help |
|
67 | echo %% -h/--help | |
68 | hg -h |
|
68 | hg -h |
@@ -32,12 +32,31 b' hg id' | |||||
32 | hg status |
|
32 | hg status | |
33 |
|
33 | |||
34 | hg commit -m "merge" -d "1000000 0" |
|
34 | hg commit -m "merge" -d "1000000 0" | |
|
35 | ||||
|
36 | # create fake head, make sure tag not visible afterwards | |||
|
37 | cp .hgtags tags | |||
|
38 | hg tag -d "1000000 0" last | |||
|
39 | hg rm .hgtags | |||
|
40 | hg commit -m "remove" -d "1000000 0" | |||
|
41 | ||||
|
42 | mv tags .hgtags | |||
|
43 | hg add .hgtags | |||
|
44 | hg commit -m "readd" -d "1000000 0" | |||
|
45 | ||||
|
46 | hg tags | |||
|
47 | ||||
35 | # invalid tags |
|
48 | # invalid tags | |
36 | echo "spam" >> .hgtags |
|
49 | echo "spam" >> .hgtags | |
37 | echo >> .hgtags |
|
50 | echo >> .hgtags | |
38 | echo "foo bar" >> .hgtags |
|
51 | echo "foo bar" >> .hgtags | |
39 | echo "$T invalid" | sed "s/..../a5a5/" >> .hg/localtags |
|
52 | echo "$T invalid" | sed "s/..../a5a5/" >> .hg/localtags | |
40 | hg commit -m "tags" -d "1000000 0" |
|
53 | hg commit -m "tags" -d "1000000 0" | |
|
54 | ||||
|
55 | # report tag parse error on other head | |||
|
56 | hg up 3 | |||
|
57 | echo 'x y' >> .hgtags | |||
|
58 | hg commit -m "head" -d "1000000 0" | |||
|
59 | ||||
41 | hg tags |
|
60 | hg tags | |
42 | hg tip |
|
61 | hg tip | |
43 |
|
62 |
@@ -16,17 +16,26 b' 1 files updated, 0 files merged, 0 files' | |||||
16 | (branch merge, don't forget to commit) |
|
16 | (branch merge, don't forget to commit) | |
17 | 8216907a933d+8a3ca90d111d+ tip |
|
17 | 8216907a933d+8a3ca90d111d+ tip | |
18 | M .hgtags |
|
18 | M .hgtags | |
19 | .hgtags:2: ignoring invalid tag |
|
19 | tip 6:c6af9d771a81bb9c7f267ec03491224a9f8ba1cd | |
20 | .hgtags:4: ignoring invalid tag |
|
|||
21 | localtags:1: ignoring invalid tag |
|
|||
22 | tip 4:fd868a874787a7b5af31e1675666ce691c803035 |
|
|||
23 | first 0:0acdaf8983679e0aac16e811534eb49d7ee1f2b4 |
|
20 | first 0:0acdaf8983679e0aac16e811534eb49d7ee1f2b4 | |
24 | changeset: 4:fd868a874787 |
|
21 | .hgtags (rev 7:39bba1bbbc4c), line 2: cannot parse entry | |
25 | .hgtags:2: ignoring invalid tag |
|
22 | .hgtags (rev 7:39bba1bbbc4c), line 4: node 'foo' is not well formed | |
26 | .hgtags:4: ignoring invalid tag |
|
23 | localtags, line 1: tag 'invalid' refers to unknown node | |
27 | localtags:1: ignoring invalid tag |
|
24 | 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
25 | .hgtags (rev 7:39bba1bbbc4c), line 2: cannot parse entry | |||
|
26 | .hgtags (rev 7:39bba1bbbc4c), line 4: node 'foo' is not well formed | |||
|
27 | .hgtags (rev 8:4ca6f1b1a68c), line 2: node 'x' is not well formed | |||
|
28 | localtags, line 1: tag 'invalid' refers to unknown node | |||
|
29 | tip 8:4ca6f1b1a68c77be687a03aaeb1614671ba59b20 | |||
|
30 | first 0:0acdaf8983679e0aac16e811534eb49d7ee1f2b4 | |||
|
31 | changeset: 8:4ca6f1b1a68c | |||
|
32 | .hgtags (rev 7:39bba1bbbc4c), line 2: cannot parse entry | |||
|
33 | .hgtags (rev 7:39bba1bbbc4c), line 4: node 'foo' is not well formed | |||
|
34 | .hgtags (rev 8:4ca6f1b1a68c), line 2: node 'x' is not well formed | |||
|
35 | localtags, line 1: tag 'invalid' refers to unknown node | |||
28 | tag: tip |
|
36 | tag: tip | |
|
37 | parent: 3:b2ef3841386b | |||
29 | user: test |
|
38 | user: test | |
30 | date: Mon Jan 12 13:46:40 1970 +0000 |
|
39 | date: Mon Jan 12 13:46:40 1970 +0000 | |
31 |
summary: |
|
40 | summary: head | |
32 |
|
41 |
General Comments 0
You need to be logged in to leave comments.
Login now