##// END OF EJS Templates
rust: update the minimum version of Rust...
Raphaël Gomès -
r49117:4ee6b8b4 default
parent child Browse files
Show More
@@ -1,121 +1,121 b''
1 ===================
1 ===================
2 Mercurial Rust Code
2 Mercurial Rust Code
3 ===================
3 ===================
4
4
5 This directory contains various Rust code for the Mercurial project.
5 This directory contains various Rust code for the Mercurial project.
6 Rust is not required to use (or build) Mercurial, but using it
6 Rust is not required to use (or build) Mercurial, but using it
7 improves performance in some areas.
7 improves performance in some areas.
8
8
9 There are currently three independent rust projects:
9 There are currently three independent rust projects:
10 - chg. An implementation of chg, in rust instead of C.
10 - chg. An implementation of chg, in rust instead of C.
11 - hgcli. A project that provide a (mostly) self-contained "hg" binary,
11 - hgcli. A project that provide a (mostly) self-contained "hg" binary,
12 for ease of deployment and a bit of speed, using PyOxidizer. See
12 for ease of deployment and a bit of speed, using PyOxidizer. See
13 hgcli/README.md.
13 hgcli/README.md.
14 - hg-core (and hg-cpython): implementation of some
14 - hg-core (and hg-cpython): implementation of some
15 functionality of mercurial in rust, e.g. ancestry computations in
15 functionality of mercurial in rust, e.g. ancestry computations in
16 revision graphs, status or pull discovery. The top-level ``Cargo.toml`` file
16 revision graphs, status or pull discovery. The top-level ``Cargo.toml`` file
17 defines a workspace containing these crates.
17 defines a workspace containing these crates.
18
18
19 Using Rust code
19 Using Rust code
20 ===============
20 ===============
21
21
22 Local use (you need to clean previous build artifacts if you have
22 Local use (you need to clean previous build artifacts if you have
23 built without rust previously)::
23 built without rust previously)::
24
24
25 $ make PURE=--rust local # to use ./hg
25 $ make PURE=--rust local # to use ./hg
26 $ ./tests/run-tests.py --rust # to run all tests
26 $ ./tests/run-tests.py --rust # to run all tests
27 $ ./hg debuginstall | grep -i rust # to validate rust is in use
27 $ ./hg debuginstall | grep -i rust # to validate rust is in use
28 checking Rust extensions (installed)
28 checking Rust extensions (installed)
29 checking module policy (rust+c-allow)
29 checking module policy (rust+c-allow)
30
30
31 If the environment variable ``HGWITHRUSTEXT=cpython`` is set, the Rust
31 If the environment variable ``HGWITHRUSTEXT=cpython`` is set, the Rust
32 extension will be used by default unless ``--no-rust``.
32 extension will be used by default unless ``--no-rust``.
33
33
34 One day we may use this environment variable to switch to new experimental
34 One day we may use this environment variable to switch to new experimental
35 binding crates like a hypothetical ``HGWITHRUSTEXT=hpy``.
35 binding crates like a hypothetical ``HGWITHRUSTEXT=hpy``.
36
36
37 Special features
37 Special features
38 ================
38 ================
39
39
40 You might want to check the `features` section in ``hg-cpython/Cargo.toml``.
40 You might want to check the `features` section in ``hg-cpython/Cargo.toml``.
41 It may contain features that might be interesting to try out.
41 It may contain features that might be interesting to try out.
42
42
43 To use features from the Makefile, use the `HG_RUST_FEATURES` environment
43 To use features from the Makefile, use the `HG_RUST_FEATURES` environment
44 variable: for instance `HG_RUST_FEATURES="some-feature other-feature"`
44 variable: for instance `HG_RUST_FEATURES="some-feature other-feature"`
45
45
46 Profiling
46 Profiling
47 =========
47 =========
48
48
49 Setting the environment variable ``RUST_LOG=trace`` will make hg print
49 Setting the environment variable ``RUST_LOG=trace`` will make hg print
50 a few high level rust-related performance numbers. It can also
50 a few high level rust-related performance numbers. It can also
51 indicate why the rust code cannot be used (say, using lookarounds in
51 indicate why the rust code cannot be used (say, using lookarounds in
52 hgignore).
52 hgignore).
53
53
54 Creating a ``.cargo/config`` file with the following content enables
54 Creating a ``.cargo/config`` file with the following content enables
55 debug information in optimized builds. This make profiles more informative
55 debug information in optimized builds. This make profiles more informative
56 with source file name and line number for Rust stack frames and
56 with source file name and line number for Rust stack frames and
57 (in some cases) stack frames for Rust functions that have been inlined.
57 (in some cases) stack frames for Rust functions that have been inlined.
58
58
59 [profile.release]
59 [profile.release]
60 debug = true
60 debug = true
61
61
62 ``py-spy`` (https://github.com/benfred/py-spy) can be used to
62 ``py-spy`` (https://github.com/benfred/py-spy) can be used to
63 construct a single profile with rust functions and python functions
63 construct a single profile with rust functions and python functions
64 (as opposed to ``hg --profile``, which attributes time spent in rust
64 (as opposed to ``hg --profile``, which attributes time spent in rust
65 to some unlucky python code running shortly after the rust code, and
65 to some unlucky python code running shortly after the rust code, and
66 as opposed to tools for native code like ``perf``, which attribute
66 as opposed to tools for native code like ``perf``, which attribute
67 time to the python interpreter instead of python functions).
67 time to the python interpreter instead of python functions).
68
68
69 Example usage:
69 Example usage:
70
70
71 $ make PURE=--rust local # Don't forget to recompile after a code change
71 $ make PURE=--rust local # Don't forget to recompile after a code change
72 $ py-spy record --native --output /tmp/profile.svg -- ./hg ...
72 $ py-spy record --native --output /tmp/profile.svg -- ./hg ...
73
73
74 Developing Rust
74 Developing Rust
75 ===============
75 ===============
76
76
77 The current version of Rust in use is ``1.41.1``, because it's what Debian
77 The current version of Rust in use is ``1.48.0``, because it's what Debian
78 stable has. You can use ``rustup override set 1.41.1`` at the root of the repo
78 stable has. You can use ``rustup override set 1.48.0`` at the root of the repo
79 to make it easier on you.
79 to make it easier on you.
80
80
81 Go to the ``hg-cpython`` folder::
81 Go to the ``hg-cpython`` folder::
82
82
83 $ cd rust/hg-cpython
83 $ cd rust/hg-cpython
84
84
85 Or, only the ``hg-core`` folder. Be careful not to break compatibility::
85 Or, only the ``hg-core`` folder. Be careful not to break compatibility::
86
86
87 $ cd rust/hg-core
87 $ cd rust/hg-core
88
88
89 Simply run::
89 Simply run::
90
90
91 $ cargo build --release
91 $ cargo build --release
92
92
93 It is possible to build without ``--release``, but it is not
93 It is possible to build without ``--release``, but it is not
94 recommended if performance is of any interest: there can be an order
94 recommended if performance is of any interest: there can be an order
95 of magnitude of degradation when removing ``--release``.
95 of magnitude of degradation when removing ``--release``.
96
96
97 For faster builds, you may want to skip code generation::
97 For faster builds, you may want to skip code generation::
98
98
99 $ cargo check
99 $ cargo check
100
100
101 For even faster typing::
101 For even faster typing::
102
102
103 $ cargo c
103 $ cargo c
104
104
105 You can run only the rust-specific tests (as opposed to tests of
105 You can run only the rust-specific tests (as opposed to tests of
106 mercurial as a whole) with::
106 mercurial as a whole) with::
107
107
108 $ cargo test --all
108 $ cargo test --all
109
109
110 Formatting the code
110 Formatting the code
111 -------------------
111 -------------------
112
112
113 We use ``rustfmt`` to keep the code formatted at all times. For now, we are
113 We use ``rustfmt`` to keep the code formatted at all times. For now, we are
114 using the nightly version because it has been stable enough and provides
114 using the nightly version because it has been stable enough and provides
115 comment folding.
115 comment folding.
116
116
117 To format the entire Rust workspace::
117 To format the entire Rust workspace::
118
118
119 $ cargo +nightly fmt
119 $ cargo +nightly fmt
120
120
121 This requires you to have the nightly toolchain installed.
121 This requires you to have the nightly toolchain installed.
@@ -1,257 +1,258 b''
1 Create a repository:
1 Create a repository:
2
2
3 #if no-extraextensions
3 #if no-extraextensions
4 $ hg config
4 $ hg config
5 chgserver.idletimeout=60
5 chgserver.idletimeout=60
6 devel.all-warnings=true
6 devel.all-warnings=true
7 devel.default-date=0 0
7 devel.default-date=0 0
8 extensions.fsmonitor= (fsmonitor !)
8 extensions.fsmonitor= (fsmonitor !)
9 format.exp-rc-dirstate-v2=1 (dirstate-v2 !)
9 format.exp-rc-dirstate-v2=1 (dirstate-v2 !)
10 largefiles.usercache=$TESTTMP/.cache/largefiles
10 largefiles.usercache=$TESTTMP/.cache/largefiles
11 lfs.usercache=$TESTTMP/.cache/lfs
11 lfs.usercache=$TESTTMP/.cache/lfs
12 ui.slash=True
12 ui.slash=True
13 ui.interactive=False
13 ui.interactive=False
14 ui.detailed-exit-code=True
14 ui.detailed-exit-code=True
15 ui.merge=internal:merge
15 ui.merge=internal:merge
16 ui.mergemarkers=detailed
16 ui.mergemarkers=detailed
17 ui.promptecho=True
17 ui.promptecho=True
18 ui.ssh=* (glob)
18 ui.ssh=* (glob)
19 ui.timeout.warn=15
19 ui.timeout.warn=15
20 web.address=localhost
20 web.address=localhost
21 web\.ipv6=(?:True|False) (re)
21 web\.ipv6=(?:True|False) (re)
22 web.server-header=testing stub value
22 web.server-header=testing stub value
23 #endif
23 #endif
24
24
25 $ hg init t
25 $ hg init t
26 $ cd t
26 $ cd t
27
27
28 Prepare a changeset:
28 Prepare a changeset:
29
29
30 $ echo a > a
30 $ echo a > a
31 $ hg add a
31 $ hg add a
32
32
33 $ hg status
33 $ hg status
34 A a
34 A a
35
35
36 Writes to stdio succeed and fail appropriately
36 Writes to stdio succeed and fail appropriately
37
37
38 #if devfull
38 #if devfull
39 $ hg status 2>/dev/full
39 $ hg status 2>/dev/full
40 A a
40 A a
41
41
42 $ hg status >/dev/full
42 $ hg status >/dev/full
43 abort: No space left on device
43 abort: No space left on device
44 [255]
44 [255]
45 #endif
45 #endif
46
46
47 #if devfull
47 #if devfull
48 $ hg status >/dev/full 2>&1
48 $ hg status >/dev/full 2>&1
49 [255]
49 [255]
50
50
51 $ hg status ENOENT 2>/dev/full
51 $ hg status ENOENT 2>/dev/full
52 [255]
52 [255]
53 #endif
53 #endif
54
54
55 On Python 3, stdio may be None:
55 On Python 3, stdio may be None:
56
56
57 $ hg debuguiprompt --config ui.interactive=true 0<&-
57 $ hg debuguiprompt --config ui.interactive=true 0<&-
58 abort: Bad file descriptor
58 abort: Bad file descriptor (no-rhg !)
59 abort: response expected (rhg !)
59 [255]
60 [255]
60 $ hg version -q 0<&-
61 $ hg version -q 0<&-
61 Mercurial Distributed SCM * (glob)
62 Mercurial Distributed SCM * (glob)
62
63
63 #if py3
64 #if py3 no-rhg
64 $ hg version -q 1>&-
65 $ hg version -q 1>&-
65 abort: Bad file descriptor
66 abort: Bad file descriptor
66 [255]
67 [255]
67 #else
68 #else
68 $ hg version -q 1>&-
69 $ hg version -q 1>&-
69 #endif
70 #endif
70 $ hg unknown -q 1>&-
71 $ hg unknown -q 1>&-
71 hg: unknown command 'unknown'
72 hg: unknown command 'unknown'
72 (did you mean debugknown?)
73 (did you mean debugknown?)
73 [10]
74 [10]
74
75
75 $ hg version -q 2>&-
76 $ hg version -q 2>&-
76 Mercurial Distributed SCM * (glob)
77 Mercurial Distributed SCM * (glob)
77 $ hg unknown -q 2>&-
78 $ hg unknown -q 2>&-
78 [10]
79 [10]
79
80
80 $ hg commit -m test
81 $ hg commit -m test
81
82
82 This command is ancient:
83 This command is ancient:
83
84
84 $ hg history
85 $ hg history
85 changeset: 0:acb14030fe0a
86 changeset: 0:acb14030fe0a
86 tag: tip
87 tag: tip
87 user: test
88 user: test
88 date: Thu Jan 01 00:00:00 1970 +0000
89 date: Thu Jan 01 00:00:00 1970 +0000
89 summary: test
90 summary: test
90
91
91
92
92 Verify that updating to revision 0 via commands.update() works properly
93 Verify that updating to revision 0 via commands.update() works properly
93
94
94 $ cat <<EOF > update_to_rev0.py
95 $ cat <<EOF > update_to_rev0.py
95 > from mercurial import commands, hg, ui as uimod
96 > from mercurial import commands, hg, ui as uimod
96 > myui = uimod.ui.load()
97 > myui = uimod.ui.load()
97 > repo = hg.repository(myui, path=b'.')
98 > repo = hg.repository(myui, path=b'.')
98 > commands.update(myui, repo, rev=b"0")
99 > commands.update(myui, repo, rev=b"0")
99 > EOF
100 > EOF
100 $ hg up null
101 $ hg up null
101 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
102 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
102 $ "$PYTHON" ./update_to_rev0.py
103 $ "$PYTHON" ./update_to_rev0.py
103 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
104 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
104 $ hg identify -n
105 $ hg identify -n
105 0
106 0
106
107
107
108
108 Poke around at hashes:
109 Poke around at hashes:
109
110
110 $ hg manifest --debug
111 $ hg manifest --debug
111 b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3 644 a
112 b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3 644 a
112
113
113 $ hg cat a
114 $ hg cat a
114 a
115 a
115
116
116 Verify should succeed:
117 Verify should succeed:
117
118
118 $ hg verify
119 $ hg verify
119 checking changesets
120 checking changesets
120 checking manifests
121 checking manifests
121 crosschecking files in changesets and manifests
122 crosschecking files in changesets and manifests
122 checking files
123 checking files
123 checked 1 changesets with 1 changes to 1 files
124 checked 1 changesets with 1 changes to 1 files
124
125
125 Repository root:
126 Repository root:
126
127
127 $ hg root
128 $ hg root
128 $TESTTMP/t
129 $TESTTMP/t
129 $ hg log -l1 -T '{reporoot}\n'
130 $ hg log -l1 -T '{reporoot}\n'
130 $TESTTMP/t
131 $TESTTMP/t
131 $ hg root -Tjson | sed 's|\\\\|\\|g'
132 $ hg root -Tjson | sed 's|\\\\|\\|g'
132 [
133 [
133 {
134 {
134 "hgpath": "$TESTTMP/t/.hg",
135 "hgpath": "$TESTTMP/t/.hg",
135 "reporoot": "$TESTTMP/t",
136 "reporoot": "$TESTTMP/t",
136 "storepath": "$TESTTMP/t/.hg/store"
137 "storepath": "$TESTTMP/t/.hg/store"
137 }
138 }
138 ]
139 ]
139
140
140 At the end...
141 At the end...
141
142
142 $ cd ..
143 $ cd ..
143
144
144 Status message redirection:
145 Status message redirection:
145
146
146 $ hg init empty
147 $ hg init empty
147
148
148 status messages are sent to stdout by default:
149 status messages are sent to stdout by default:
149
150
150 $ hg outgoing -R t empty -Tjson 2>/dev/null
151 $ hg outgoing -R t empty -Tjson 2>/dev/null
151 comparing with empty
152 comparing with empty
152 searching for changes
153 searching for changes
153 [
154 [
154 {
155 {
155 "bookmarks": [],
156 "bookmarks": [],
156 "branch": "default",
157 "branch": "default",
157 "date": [0, 0],
158 "date": [0, 0],
158 "desc": "test",
159 "desc": "test",
159 "node": "acb14030fe0a21b60322c440ad2d20cf7685a376",
160 "node": "acb14030fe0a21b60322c440ad2d20cf7685a376",
160 "parents": ["0000000000000000000000000000000000000000"],
161 "parents": ["0000000000000000000000000000000000000000"],
161 "phase": "draft",
162 "phase": "draft",
162 "rev": 0,
163 "rev": 0,
163 "tags": ["tip"],
164 "tags": ["tip"],
164 "user": "test"
165 "user": "test"
165 }
166 }
166 ]
167 ]
167
168
168 which can be configured to send to stderr, so the output wouldn't be
169 which can be configured to send to stderr, so the output wouldn't be
169 interleaved:
170 interleaved:
170
171
171 $ cat <<'EOF' >> "$HGRCPATH"
172 $ cat <<'EOF' >> "$HGRCPATH"
172 > [ui]
173 > [ui]
173 > message-output = stderr
174 > message-output = stderr
174 > EOF
175 > EOF
175 $ hg outgoing -R t empty -Tjson 2>/dev/null
176 $ hg outgoing -R t empty -Tjson 2>/dev/null
176 [
177 [
177 {
178 {
178 "bookmarks": [],
179 "bookmarks": [],
179 "branch": "default",
180 "branch": "default",
180 "date": [0, 0],
181 "date": [0, 0],
181 "desc": "test",
182 "desc": "test",
182 "node": "acb14030fe0a21b60322c440ad2d20cf7685a376",
183 "node": "acb14030fe0a21b60322c440ad2d20cf7685a376",
183 "parents": ["0000000000000000000000000000000000000000"],
184 "parents": ["0000000000000000000000000000000000000000"],
184 "phase": "draft",
185 "phase": "draft",
185 "rev": 0,
186 "rev": 0,
186 "tags": ["tip"],
187 "tags": ["tip"],
187 "user": "test"
188 "user": "test"
188 }
189 }
189 ]
190 ]
190 $ hg outgoing -R t empty -Tjson >/dev/null
191 $ hg outgoing -R t empty -Tjson >/dev/null
191 comparing with empty
192 comparing with empty
192 searching for changes
193 searching for changes
193
194
194 this option should be turned off by HGPLAIN= since it may break scripting use:
195 this option should be turned off by HGPLAIN= since it may break scripting use:
195
196
196 $ HGPLAIN= hg outgoing -R t empty -Tjson 2>/dev/null
197 $ HGPLAIN= hg outgoing -R t empty -Tjson 2>/dev/null
197 comparing with empty
198 comparing with empty
198 searching for changes
199 searching for changes
199 [
200 [
200 {
201 {
201 "bookmarks": [],
202 "bookmarks": [],
202 "branch": "default",
203 "branch": "default",
203 "date": [0, 0],
204 "date": [0, 0],
204 "desc": "test",
205 "desc": "test",
205 "node": "acb14030fe0a21b60322c440ad2d20cf7685a376",
206 "node": "acb14030fe0a21b60322c440ad2d20cf7685a376",
206 "parents": ["0000000000000000000000000000000000000000"],
207 "parents": ["0000000000000000000000000000000000000000"],
207 "phase": "draft",
208 "phase": "draft",
208 "rev": 0,
209 "rev": 0,
209 "tags": ["tip"],
210 "tags": ["tip"],
210 "user": "test"
211 "user": "test"
211 }
212 }
212 ]
213 ]
213
214
214 but still overridden by --config:
215 but still overridden by --config:
215
216
216 $ HGPLAIN= hg outgoing -R t empty -Tjson --config ui.message-output=stderr \
217 $ HGPLAIN= hg outgoing -R t empty -Tjson --config ui.message-output=stderr \
217 > 2>/dev/null
218 > 2>/dev/null
218 [
219 [
219 {
220 {
220 "bookmarks": [],
221 "bookmarks": [],
221 "branch": "default",
222 "branch": "default",
222 "date": [0, 0],
223 "date": [0, 0],
223 "desc": "test",
224 "desc": "test",
224 "node": "acb14030fe0a21b60322c440ad2d20cf7685a376",
225 "node": "acb14030fe0a21b60322c440ad2d20cf7685a376",
225 "parents": ["0000000000000000000000000000000000000000"],
226 "parents": ["0000000000000000000000000000000000000000"],
226 "phase": "draft",
227 "phase": "draft",
227 "rev": 0,
228 "rev": 0,
228 "tags": ["tip"],
229 "tags": ["tip"],
229 "user": "test"
230 "user": "test"
230 }
231 }
231 ]
232 ]
232
233
233 Invalid ui.message-output option:
234 Invalid ui.message-output option:
234
235
235 $ hg log -R t --config ui.message-output=bad
236 $ hg log -R t --config ui.message-output=bad
236 abort: invalid ui.message-output destination: bad
237 abort: invalid ui.message-output destination: bad
237 [255]
238 [255]
238
239
239 Underlying message streams should be updated when ui.fout/ferr are set:
240 Underlying message streams should be updated when ui.fout/ferr are set:
240
241
241 $ cat <<'EOF' > capui.py
242 $ cat <<'EOF' > capui.py
242 > from mercurial import pycompat, registrar
243 > from mercurial import pycompat, registrar
243 > cmdtable = {}
244 > cmdtable = {}
244 > command = registrar.command(cmdtable)
245 > command = registrar.command(cmdtable)
245 > @command(b'capui', norepo=True)
246 > @command(b'capui', norepo=True)
246 > def capui(ui):
247 > def capui(ui):
247 > out = ui.fout
248 > out = ui.fout
248 > ui.fout = pycompat.bytesio()
249 > ui.fout = pycompat.bytesio()
249 > ui.status(b'status\n')
250 > ui.status(b'status\n')
250 > ui.ferr = pycompat.bytesio()
251 > ui.ferr = pycompat.bytesio()
251 > ui.warn(b'warn\n')
252 > ui.warn(b'warn\n')
252 > out.write(b'stdout: %s' % ui.fout.getvalue())
253 > out.write(b'stdout: %s' % ui.fout.getvalue())
253 > out.write(b'stderr: %s' % ui.ferr.getvalue())
254 > out.write(b'stderr: %s' % ui.ferr.getvalue())
254 > EOF
255 > EOF
255 $ hg --config extensions.capui=capui.py --config ui.message-output=stdio capui
256 $ hg --config extensions.capui=capui.py --config ui.message-output=stdio capui
256 stdout: status
257 stdout: status
257 stderr: warn
258 stderr: warn
General Comments 0
You need to be logged in to leave comments. Login now