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