Show More
@@ -0,0 +1,75 b'' | |||||
|
1 | image: octobus/ci-mercurial-core | |||
|
2 | ||||
|
3 | # The runner made a clone as root. | |||
|
4 | # We make a new clone owned by user used to run the step. | |||
|
5 | before_script: | |||
|
6 | - hg clone . /tmp/mercurial-ci/ --noupdate | |||
|
7 | - hg -R /tmp/mercurial-ci/ update `hg log --rev '.' --template '{node}'` | |||
|
8 | - cd /tmp/mercurial-ci/ | |||
|
9 | - (cd tests; ls -1 test-check-*.*) > /tmp/check-tests.txt | |||
|
10 | ||||
|
11 | variables: | |||
|
12 | PYTHON: python | |||
|
13 | ||||
|
14 | .runtests_template: &runtests | |||
|
15 | script: | |||
|
16 | - cd tests/ | |||
|
17 | - echo "python used, $PYTHON" | |||
|
18 | - echo "$RUNTEST_ARGS" | |||
|
19 | - $PYTHON run-tests.py --color=always $RUNTEST_ARGS | |||
|
20 | ||||
|
21 | checks-py2: | |||
|
22 | <<: *runtests | |||
|
23 | variables: | |||
|
24 | RUNTEST_ARGS: "--time --test-list /tmp/check-tests.txt" | |||
|
25 | ||||
|
26 | checks-py3: | |||
|
27 | <<: *runtests | |||
|
28 | variables: | |||
|
29 | RUNTEST_ARGS: "--time --test-list /tmp/check-tests.txt" | |||
|
30 | PYTHON: python3 | |||
|
31 | ||||
|
32 | rust-cargo-test-py2: &rust_cargo_test | |||
|
33 | script: | |||
|
34 | - echo "python used, $PYTHON" | |||
|
35 | - make rust-tests | |||
|
36 | ||||
|
37 | rust-cargo-test-py3: | |||
|
38 | <<: *rust_cargo_test | |||
|
39 | variables: | |||
|
40 | PYTHON: python3 | |||
|
41 | ||||
|
42 | test-py2: | |||
|
43 | <<: *runtests | |||
|
44 | variables: | |||
|
45 | RUNTEST_ARGS: "--blacklist /tmp/check-tests.txt" | |||
|
46 | ||||
|
47 | test-py3: | |||
|
48 | <<: *runtests | |||
|
49 | variables: | |||
|
50 | RUNTEST_ARGS: "--blacklist /tmp/check-tests.txt" | |||
|
51 | PYTHON: python3 | |||
|
52 | ||||
|
53 | test-py2-pure: | |||
|
54 | <<: *runtests | |||
|
55 | variables: | |||
|
56 | RUNTEST_ARGS: "--pure --blacklist /tmp/check-tests.txt" | |||
|
57 | ||||
|
58 | test-py3-pure: | |||
|
59 | <<: *runtests | |||
|
60 | variables: | |||
|
61 | RUNTEST_ARGS: "--pure --blacklist /tmp/check-tests.txt" | |||
|
62 | PYTHON: python3 | |||
|
63 | ||||
|
64 | test-py2-rust: | |||
|
65 | <<: *runtests | |||
|
66 | variables: | |||
|
67 | HGWITHRUSTEXT: cpython | |||
|
68 | RUNTEST_ARGS: "--blacklist /tmp/check-tests.txt" | |||
|
69 | ||||
|
70 | test-py3-rust: | |||
|
71 | <<: *runtests | |||
|
72 | variables: | |||
|
73 | HGWITHRUSTEXT: cpython | |||
|
74 | RUNTEST_ARGS: "--blacklist /tmp/check-tests.txt" | |||
|
75 | PYTHON: python3 |
@@ -343,7 +343,9 b' def build_installer(' | |||||
343 | dist_dir = source_dir / 'dist' |
|
343 | dist_dir = source_dir / 'dist' | |
344 | wix_dir = source_dir / 'contrib' / 'packaging' / 'wix' |
|
344 | wix_dir = source_dir / 'contrib' / 'packaging' / 'wix' | |
345 |
|
345 | |||
346 |
requirements_txt = |
|
346 | requirements_txt = ( | |
|
347 | source_dir / 'contrib' / 'packaging' / 'requirements_win32.txt' | |||
|
348 | ) | |||
347 |
|
349 | |||
348 | build_py2exe( |
|
350 | build_py2exe( | |
349 | source_dir, |
|
351 | source_dir, |
@@ -35,6 +35,7 b' from mercurial import (' | |||||
35 | extensions, |
|
35 | extensions, | |
36 | hg, |
|
36 | hg, | |
37 | pycompat, |
|
37 | pycompat, | |
|
38 | rcutil, | |||
38 | ui as uimod, |
|
39 | ui as uimod, | |
39 | ) |
|
40 | ) | |
40 | from mercurial.hgweb import server as servermod |
|
41 | from mercurial.hgweb import server as servermod | |
@@ -144,6 +145,7 b' def zc_create_server(create_server, ui, ' | |||||
144 | prefix = app.ui.config(b"web", b"prefix", b"").strip(b'/') + b'/' |
|
145 | prefix = app.ui.config(b"web", b"prefix", b"").strip(b'/') + b'/' | |
145 | for repo, path in repos: |
|
146 | for repo, path in repos: | |
146 | u = app.ui.copy() |
|
147 | u = app.ui.copy() | |
|
148 | if rcutil.use_repo_hgrc(): | |||
147 | u.readconfig(os.path.join(path, b'.hg', b'hgrc')) |
|
149 | u.readconfig(os.path.join(path, b'.hg', b'hgrc')) | |
148 | name = os.path.basename(repo) |
|
150 | name = os.path.basename(repo) | |
149 | path = (prefix + repo).strip(b'/') |
|
151 | path = (prefix + repo).strip(b'/') |
@@ -1014,8 +1014,8 b' class bundlepart(object):' | |||||
1014 | self.mandatory = mandatory |
|
1014 | self.mandatory = mandatory | |
1015 |
|
1015 | |||
1016 | def __repr__(self): |
|
1016 | def __repr__(self): | |
1017 |
cls = |
|
1017 | cls = "%s.%s" % (self.__class__.__module__, self.__class__.__name__) | |
1018 |
return |
|
1018 | return '<%s object at %x; id: %s; type: %s; mandatory: %s>' % ( | |
1019 | cls, |
|
1019 | cls, | |
1020 | id(self), |
|
1020 | id(self), | |
1021 | self.id, |
|
1021 | self.id, |
@@ -37,6 +37,7 b' from . import (' | |||||
37 | hook, |
|
37 | hook, | |
38 | profiling, |
|
38 | profiling, | |
39 | pycompat, |
|
39 | pycompat, | |
|
40 | rcutil, | |||
40 | registrar, |
|
41 | registrar, | |
41 | scmutil, |
|
42 | scmutil, | |
42 | ui as uimod, |
|
43 | ui as uimod, | |
@@ -902,16 +903,19 b' def _getlocal(ui, rpath, wd=None):' | |||||
902 | _(b"error getting current working directory: %s") |
|
903 | _(b"error getting current working directory: %s") | |
903 | % encoding.strtolocal(e.strerror) |
|
904 | % encoding.strtolocal(e.strerror) | |
904 | ) |
|
905 | ) | |
|
906 | ||||
905 | path = cmdutil.findrepo(wd) or b"" |
|
907 | path = cmdutil.findrepo(wd) or b"" | |
906 | if not path: |
|
908 | if not path: | |
907 | lui = ui |
|
909 | lui = ui | |
908 | else: |
|
910 | else: | |
909 | lui = ui.copy() |
|
911 | lui = ui.copy() | |
|
912 | if rcutil.use_repo_hgrc(): | |||
910 | lui.readconfig(os.path.join(path, b".hg", b"hgrc"), path) |
|
913 | lui.readconfig(os.path.join(path, b".hg", b"hgrc"), path) | |
911 |
|
914 | |||
912 | if rpath: |
|
915 | if rpath: | |
913 | path = lui.expandpath(rpath) |
|
916 | path = lui.expandpath(rpath) | |
914 | lui = ui.copy() |
|
917 | lui = ui.copy() | |
|
918 | if rcutil.use_repo_hgrc(): | |||
915 | lui.readconfig(os.path.join(path, b".hg", b"hgrc"), path) |
|
919 | lui.readconfig(os.path.join(path, b".hg", b"hgrc"), path) | |
916 |
|
920 | |||
917 | return path, lui |
|
921 | return path, lui |
@@ -35,6 +35,7 b' from .. import (' | |||||
35 | pathutil, |
|
35 | pathutil, | |
36 | profiling, |
|
36 | profiling, | |
37 | pycompat, |
|
37 | pycompat, | |
|
38 | rcutil, | |||
38 | registrar, |
|
39 | registrar, | |
39 | scmutil, |
|
40 | scmutil, | |
40 | templater, |
|
41 | templater, | |
@@ -192,6 +193,7 b' def rawindexentries(ui, repos, req, subd' | |||||
192 | continue |
|
193 | continue | |
193 |
|
194 | |||
194 | u = ui.copy() |
|
195 | u = ui.copy() | |
|
196 | if rcutil.use_repo_hgrc(): | |||
195 | try: |
|
197 | try: | |
196 | u.readconfig(os.path.join(path, b'.hg', b'hgrc')) |
|
198 | u.readconfig(os.path.join(path, b'.hg', b'hgrc')) | |
197 | except Exception as e: |
|
199 | except Exception as e: |
@@ -255,7 +255,7 b' class linelog(object):' | |||||
255 | ) |
|
255 | ) | |
256 |
|
256 | |||
257 | def __repr__(self): |
|
257 | def __repr__(self): | |
258 |
return |
|
258 | return '<linelog at %s: maxrev=%d size=%d>' % ( | |
259 | hex(id(self)), |
|
259 | hex(id(self)), | |
260 | self._maxrev, |
|
260 | self._maxrev, | |
261 | len(self._program), |
|
261 | len(self._program), |
@@ -53,6 +53,7 b' from . import (' | |||||
53 | phases, |
|
53 | phases, | |
54 | pushkey, |
|
54 | pushkey, | |
55 | pycompat, |
|
55 | pycompat, | |
|
56 | rcutil, | |||
56 | repoview, |
|
57 | repoview, | |
57 | revset, |
|
58 | revset, | |
58 | revsetlang, |
|
59 | revsetlang, | |
@@ -676,7 +677,7 b' def loadhgrc(ui, wdirvfs, hgvfs, require' | |||||
676 | configs are loaded. For example, an extension may wish to pull in |
|
677 | configs are loaded. For example, an extension may wish to pull in | |
677 | configs from alternate files or sources. |
|
678 | configs from alternate files or sources. | |
678 | """ |
|
679 | """ | |
679 | if b'HGRCSKIPREPO' in encoding.environ: |
|
680 | if not rcutil.use_repo_hgrc(): | |
680 | return False |
|
681 | return False | |
681 | try: |
|
682 | try: | |
682 | ui.readconfig(hgvfs.join(b'hgrc'), root=wdirvfs.base) |
|
683 | ui.readconfig(hgvfs.join(b'hgrc'), root=wdirvfs.base) |
@@ -21,6 +21,7 b' from .node import (' | |||||
21 | ) |
|
21 | ) | |
22 | from .pycompat import getattr |
|
22 | from .pycompat import getattr | |
23 | from . import ( |
|
23 | from . import ( | |
|
24 | encoding, | |||
24 | error, |
|
25 | error, | |
25 | mdiff, |
|
26 | mdiff, | |
26 | pathutil, |
|
27 | pathutil, | |
@@ -868,9 +869,10 b' class treemanifest(object):' | |||||
868 | self._loadalllazy() |
|
869 | self._loadalllazy() | |
869 | return not self._dirs or all(m._isempty() for m in self._dirs.values()) |
|
870 | return not self._dirs or all(m._isempty() for m in self._dirs.values()) | |
870 |
|
871 | |||
|
872 | @encoding.strmethod | |||
871 | def __repr__(self): |
|
873 | def __repr__(self): | |
872 | return ( |
|
874 | return ( | |
873 |
b'<treemanifest dir=%s, node=%s, loaded=% |
|
875 | b'<treemanifest dir=%s, node=%s, loaded=%r, dirty=%r at 0x%x>' | |
874 | % ( |
|
876 | % ( | |
875 | self._dir, |
|
877 | self._dir, | |
876 | hex(self._node), |
|
878 | hex(self._node), |
@@ -1090,6 +1090,7 b' class recordhunk(object):' | |||||
1090 | def filename(self): |
|
1090 | def filename(self): | |
1091 | return self.header.filename() |
|
1091 | return self.header.filename() | |
1092 |
|
1092 | |||
|
1093 | @encoding.strmethod | |||
1093 | def __repr__(self): |
|
1094 | def __repr__(self): | |
1094 | return b'<hunk %r@%d>' % (self.filename(), self.fromline) |
|
1095 | return b'<hunk %r@%d>' % (self.filename(), self.fromline) | |
1095 |
|
1096 |
@@ -112,3 +112,8 b' def defaultpagerenv():' | |||||
112 | intended to be set before starting a pager. |
|
112 | intended to be set before starting a pager. | |
113 | ''' |
|
113 | ''' | |
114 | return {b'LESS': b'FRX', b'LV': b'-c'} |
|
114 | return {b'LESS': b'FRX', b'LV': b'-c'} | |
|
115 | ||||
|
116 | ||||
|
117 | def use_repo_hgrc(): | |||
|
118 | """True if repositories `.hg/hgrc` config should be read""" | |||
|
119 | return b'HGRCSKIPREPO' not in encoding.environ |
@@ -65,6 +65,41 b' def _numworkers(ui):' | |||||
65 | return min(max(countcpus(), 4), 32) |
|
65 | return min(max(countcpus(), 4), 32) | |
66 |
|
66 | |||
67 |
|
67 | |||
|
68 | if pycompat.ispy3: | |||
|
69 | ||||
|
70 | class _blockingreader(object): | |||
|
71 | def __init__(self, wrapped): | |||
|
72 | self._wrapped = wrapped | |||
|
73 | ||||
|
74 | def __getattr__(self, attr): | |||
|
75 | return getattr(self._wrapped, attr) | |||
|
76 | ||||
|
77 | # issue multiple reads until size is fulfilled | |||
|
78 | def read(self, size=-1): | |||
|
79 | if size < 0: | |||
|
80 | return self._wrapped.readall() | |||
|
81 | ||||
|
82 | buf = bytearray(size) | |||
|
83 | view = memoryview(buf) | |||
|
84 | pos = 0 | |||
|
85 | ||||
|
86 | while pos < size: | |||
|
87 | ret = self._wrapped.readinto(view[pos:]) | |||
|
88 | if not ret: | |||
|
89 | break | |||
|
90 | pos += ret | |||
|
91 | ||||
|
92 | del view | |||
|
93 | del buf[pos:] | |||
|
94 | return buf | |||
|
95 | ||||
|
96 | ||||
|
97 | else: | |||
|
98 | ||||
|
99 | def _blockingreader(wrapped): | |||
|
100 | return wrapped | |||
|
101 | ||||
|
102 | ||||
68 | if pycompat.isposix or pycompat.iswindows: |
|
103 | if pycompat.isposix or pycompat.iswindows: | |
69 | _STARTUP_COST = 0.01 |
|
104 | _STARTUP_COST = 0.01 | |
70 | # The Windows worker is thread based. If tasks are CPU bound, threads |
|
105 | # The Windows worker is thread based. If tasks are CPU bound, threads | |
@@ -226,7 +261,7 b' def _posixworker(ui, func, staticargs, a' | |||||
226 | selector = selectors.DefaultSelector() |
|
261 | selector = selectors.DefaultSelector() | |
227 | for rfd, wfd in pipes: |
|
262 | for rfd, wfd in pipes: | |
228 | os.close(wfd) |
|
263 | os.close(wfd) | |
229 | selector.register(os.fdopen(rfd, 'rb'), selectors.EVENT_READ) |
|
264 | selector.register(os.fdopen(rfd, 'rb', 0), selectors.EVENT_READ) | |
230 |
|
265 | |||
231 | def cleanup(): |
|
266 | def cleanup(): | |
232 | signal.signal(signal.SIGINT, oldhandler) |
|
267 | signal.signal(signal.SIGINT, oldhandler) | |
@@ -240,7 +275,7 b' def _posixworker(ui, func, staticargs, a' | |||||
240 | while openpipes > 0: |
|
275 | while openpipes > 0: | |
241 | for key, events in selector.select(): |
|
276 | for key, events in selector.select(): | |
242 | try: |
|
277 | try: | |
243 | res = util.pickle.load(key.fileobj) |
|
278 | res = util.pickle.load(_blockingreader(key.fileobj)) | |
244 | if hasretval and res[0]: |
|
279 | if hasretval and res[0]: | |
245 | retval.update(res[1]) |
|
280 | retval.update(res[1]) | |
246 | else: |
|
281 | else: |
@@ -271,3 +271,39 b' Test we can skip the user configuration' | |||||
271 | $ HGRCSKIPREPO=1 hg path |
|
271 | $ HGRCSKIPREPO=1 hg path | |
272 | foo = $TESTTMP/bar |
|
272 | foo = $TESTTMP/bar | |
273 |
|
273 | |||
|
274 | $ cat >> .hg/hgrc <<EOF | |||
|
275 | > [broken | |||
|
276 | > EOF | |||
|
277 | ||||
|
278 | $ hg path | |||
|
279 | hg: parse error at $TESTTMP/.hg/hgrc:3: [broken | |||
|
280 | [255] | |||
|
281 | $ HGRCSKIPREPO=1 hg path | |||
|
282 | foo = $TESTTMP/bar | |||
|
283 | ||||
|
284 | Check that hgweb respect HGRCSKIPREPO=1 | |||
|
285 | ||||
|
286 | $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log | |||
|
287 | hg: parse error at $TESTTMP/.hg/hgrc:3: [broken | |||
|
288 | [255] | |||
|
289 | $ test -f hg.pid && (cat hg.pid >> $DAEMON_PIDS) | |||
|
290 | [1] | |||
|
291 | $ killdaemons.py | |||
|
292 | $ test -f access.log && cat access.log | |||
|
293 | [1] | |||
|
294 | $ test -f errors.log && cat errors.log | |||
|
295 | [1] | |||
|
296 | ||||
|
297 | $ HGRCSKIPREPO=1 hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log | |||
|
298 | $ cat hg.pid >> $DAEMON_PIDS | |||
|
299 | $ killdaemons.py | |||
|
300 | $ cat access.log | |||
|
301 | $ cat errors.log | |||
|
302 | ||||
|
303 | Check that zeroconf respect HGRCSKIPREPO=1 | |||
|
304 | ||||
|
305 | $ hg paths --config extensions.zeroconf= | |||
|
306 | hg: parse error at $TESTTMP/.hg/hgrc:3: [broken | |||
|
307 | [255] | |||
|
308 | $ HGRCSKIPREPO=1 hg paths --config extensions.zeroconf= | |||
|
309 | foo = $TESTTMP/bar |
@@ -131,4 +131,35 b' Workers should not do cleanups in all ca' | |||||
131 | abort: known exception |
|
131 | abort: known exception | |
132 | [255] |
|
132 | [255] | |
133 |
|
133 | |||
|
134 | Do not crash on partially read result | |||
|
135 | ||||
|
136 | $ cat > $TESTTMP/detecttruncated.py <<EOF | |||
|
137 | > from __future__ import absolute_import | |||
|
138 | > import os | |||
|
139 | > import sys | |||
|
140 | > import time | |||
|
141 | > sys.unraisablehook = lambda x: None | |||
|
142 | > oldwrite = os.write | |||
|
143 | > def splitwrite(fd, string): | |||
|
144 | > ret = oldwrite(fd, string[:9]) | |||
|
145 | > if ret == 9: | |||
|
146 | > time.sleep(0.1) | |||
|
147 | > ret += oldwrite(fd, string[9:]) | |||
|
148 | > return ret | |||
|
149 | > os.write = splitwrite | |||
|
150 | > EOF | |||
|
151 | ||||
|
152 | $ hg --config "extensions.t=$abspath" --config worker.numcpus=8 --config \ | |||
|
153 | > "extensions.d=$TESTTMP/detecttruncated.py" test 100000.0 | |||
|
154 | start | |||
|
155 | run | |||
|
156 | run | |||
|
157 | run | |||
|
158 | run | |||
|
159 | run | |||
|
160 | run | |||
|
161 | run | |||
|
162 | run | |||
|
163 | done | |||
|
164 | ||||
134 | #endif |
|
165 | #endif |
General Comments 0
You need to be logged in to leave comments.
Login now