{"thread":{"id":"64091","subject":"[PATCH RFC 0/3] Introduce Rust and announce that it will become mandatorty","startedAt":"2025-09-04T14:27:07Z","lastAt":"2026-01-21T08:00:36Z","messageCount":210,"participants":["Patrick Steinhardt","Eric Sunshine","Junio C Hamano","brian m. carlson","Ezekiel Newren","Eli Schwartz","Matthias Aßhauer","Phillip Wood","Justin Tobler","Elijah Newren","SZEDER Gábor","Ben Knoble","Kristoffer Haugsbakk","Ramsay Jones","Sam James","John Paul Adrian Glaubitz","Johannes Schindelin","Eric Wong","Pierre-Emmanuel Patry","D. Ben Knoble"],"isPatch":true,"patchVersion":1,"patchTotal":3},"messages":[{"id":"525520","messageId":"20250904-b4-pks-rust-breaking-change-v1-0-3af1d25e0be9@pks.im","threadId":"64091","inReplyTo":null,"subject":"[PATCH RFC 0/3] Introduce Rust and announce that it will become mandatorty","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-04T14:26:42Z","receivedAt":"2025-09-04T14:27:07Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Hi,\n\nthis small patch series introduces Rust into the core of Git. This patch\nseries is designed as a test balloon, similar to how we introduced test\nballoons for C99 features in the past. The goal is threefold:\n\n  - Give us some time to experiment with Rust and introduce proper build\n    infrastructure.\n\n  - Give distributors time to ease into the new toolchain requirements.\n    Introducing Rust is impossible for some platforms and hard for\n    others.\n\n  - Announce that Git 3.0 will make Rust a mandatory part of our build\n    infrastructure.\n\nThe test balloon itself is quite uninteresting: I've chosen to convert\nthe \"varint.c\" subsystem, mostly because it is trivial and does not have\nany dependencies. But it does allow us to verify that C to Rust interop\nworks as expected, and to play around with tooling. All tests pass with\nthe \"varint.rs\" implementation.\n\nFor now, the series only contains support for Meson. If we agree to go\ndown this route I'll also introduce support for Rust into our Makefiles\nat a later point in time.\n\nFurthermore missing is additional tooling:\n\n  - At least one CI job to verify that Rust builds and works as\n    expected.\n\n  - Tooling and CI jobs to ensure that we have consistent formatting via\n    `cargo format`.\n\nAnd probably lots more. As said, the entire goal is for us to have an\neasy playground that we can experiment on and develop the infrastructure\nincrementally without yet having to commit to anything.\n\nI'm mostly splitting out the topic of introducing Rust from the larger\nseries that introduce it into xdiff so that we can focus more on the\nactual process of introducing Rust into Git and less on the potential\nfeatures that we want to build on top of it.\n\nThanks!\n\nPatrick\n\n---\nPatrick Steinhardt (3):\n      meson: add infrastructure to build internal Rust library\n      rust: implement a test balloon via the \"varint\" subsystem\n      BreakingChanges: announce Rust becoming mandatory\n\n Documentation/BreakingChanges.adoc | 20 +++++++++\n meson.build                        | 21 ++++++++-\n meson_options.txt                  |  2 +\n src/lib.rs                         |  1 +\n src/meson.build                    | 13 ++++++\n src/varint.rs                      | 92 ++++++++++++++++++++++++++++++++++++++\n 6 files changed, 147 insertions(+), 2 deletions(-)\n\n\n---\nbase-commit: 2462961280690837670d997bde64bd4ebf8ae66d\nchange-id: 20250904-b4-pks-rust-breaking-change-7167d9d3e37d\n\n"},{"id":"525521","messageId":"20250904-b4-pks-rust-breaking-change-v1-1-3af1d25e0be9@pks.im","threadId":"64091","inReplyTo":"20250904-b4-pks-rust-breaking-change-v1-0-3af1d25e0be9@pks.im","subject":"[PATCH RFC 1/3] meson: add infrastructure to build internal Rust library","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-04T14:26:43Z","receivedAt":"2025-09-04T14:27:10Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Add the infrastructure into Meson to build an internal Rust library.\nBuilding the Rust parts of Git are for now entirely optional, as they\nare mostly intended as a test balloon for both Git developers, but also\nfor distributors of Git. So for now, they may contain:\n\n  - New features that are not mission critical to Git and that users can\n    easily live without.\n\n  - Alternative implementations of small subsystems.\n\nIf these test balloons are successful, we will eventually make Rust a\nmandatory dependency for our build process in Git 3.0.\n\nThe availability of a Rust toolchain will be auto-detected by Meson at\nsetup time. This behaviour can be tweaked via the `-Drust=` feature\ntoggle.\n\nNext to the linkable Rust library, also wire up tests that can be\nexecuted via `meson test`. This allows us to use the native unit testing\ncapabilities of Rust.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n meson.build       | 16 +++++++++++++++-\n meson_options.txt |  2 ++\n src/lib.rs        |  0\n src/meson.build   | 12 ++++++++++++\n 4 files changed, 29 insertions(+), 1 deletion(-)\n\ndiff --git a/meson.build b/meson.build\nindex e8ec0eca165..1c0e98bbc14 100644\n--- a/meson.build\n+++ b/meson.build\n@@ -1702,8 +1702,21 @@ version_def_h = custom_target(\n )\n libgit_sources += version_def_h\n \n+libgit_libraries = [ ]\n+\n+if meson.version().version_compare('>=1.9.0')\n+  rust_available = add_languages('rust', native: false, required: get_option('rust'))\n+else\n+  rust_available = false\n+endif\n+rust_option = get_option('rust').disable_auto_if(not rust_available)\n+\n+if rust_option.allowed() and meson.version().version_compare('>=1.9.0')\n+  subdir('src')\n+endif\n+\n libgit = declare_dependency(\n-  link_with: static_library('git',\n+  link_with: libgit_libraries + static_library('git',\n     sources: libgit_sources,\n     c_args: libgit_c_args + [\n       '-DGIT_VERSION_H=\"' + version_def_h.full_path() + '\"',\n@@ -2239,6 +2252,7 @@ summary({\n   'pcre2': pcre2,\n   'perl': perl_features_enabled,\n   'python': target_python.found(),\n+  'rust': rust_option.allowed(),\n }, section: 'Auto-detected features', bool_yn: true)\n \n summary({\ndiff --git a/meson_options.txt b/meson_options.txt\nindex 1668f260a18..143dee9237c 100644\n--- a/meson_options.txt\n+++ b/meson_options.txt\n@@ -71,6 +71,8 @@ option('zlib_backend', type: 'combo', choices: ['auto', 'zlib', 'zlib-ng'], valu\n # Build tweaks.\n option('breaking_changes', type: 'boolean', value: false,\n   description: 'Enable upcoming breaking changes.')\n+option('rust', type: 'feature', value: 'auto',\n+  description: 'Enable building with Rust.')\n option('macos_use_homebrew_gettext', type: 'boolean', value: true,\n   description: 'Use gettext from Homebrew instead of the slightly-broken system-provided one.')\n \ndiff --git a/src/lib.rs b/src/lib.rs\nnew file mode 100644\nindex 00000000000..e69de29bb2d\ndiff --git a/src/meson.build b/src/meson.build\nnew file mode 100644\nindex 00000000000..2bd2045a8ab\n--- /dev/null\n+++ b/src/meson.build\n@@ -0,0 +1,12 @@\n+rustmod = import('rust')\n+\n+libgit_rs = static_library('git_rs',\n+  sources: [\n+    'lib.rs',\n+  ],\n+  rust_abi: 'c',\n+)\n+\n+rustmod.test('git-rs', libgit_rs)\n+\n+libgit_libraries += libgit_rs\n\n-- \n2.51.0.417.g1ba7204a04.dirty\n\n"},{"id":"525522","messageId":"20250904-b4-pks-rust-breaking-change-v1-2-3af1d25e0be9@pks.im","threadId":"64091","inReplyTo":"20250904-b4-pks-rust-breaking-change-v1-0-3af1d25e0be9@pks.im","subject":"[PATCH RFC 2/3] rust: implement a test balloon via the \"varint\" subsystem","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-04T14:26:44Z","receivedAt":"2025-09-04T14:27:13Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Implement a trivial test balloon for our Rust build infrastructure by\nreimplementing the \"varint.c\" subsystem in Rust. This subsystem is\nchosen because it is trivial to convert and because it doesn't have any\ndependencies to other components of Git.\n\nIf support for Rust is enabled, we stop compiling \"varint.c\" and instead\ncompile and use \"src/varint.rs\".\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n meson.build     |  5 +++-\n src/lib.rs      |  1 +\n src/meson.build |  1 +\n src/varint.rs   | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n 4 files changed, 98 insertions(+), 1 deletion(-)\n\ndiff --git a/meson.build b/meson.build\nindex 1c0e98bbc14..b52a68b0bb6 100644\n--- a/meson.build\n+++ b/meson.build\n@@ -522,7 +522,6 @@ libgit_sources = [\n   'usage.c',\n   'userdiff.c',\n   'utf8.c',\n-  'varint.c',\n   'version.c',\n   'versioncmp.c',\n   'walker.c',\n@@ -1713,6 +1712,10 @@ rust_option = get_option('rust').disable_auto_if(not rust_available)\n \n if rust_option.allowed() and meson.version().version_compare('>=1.9.0')\n   subdir('src')\n+else\n+  libgit_sources += [\n+    'varint.c',\n+  ]\n endif\n \n libgit = declare_dependency(\ndiff --git a/src/lib.rs b/src/lib.rs\nindex e69de29bb2d..9da70d8b57d 100644\n--- a/src/lib.rs\n+++ b/src/lib.rs\n@@ -0,0 +1 @@\n+pub mod varint;\ndiff --git a/src/meson.build b/src/meson.build\nindex 2bd2045a8ab..b3164fb5ed4 100644\n--- a/src/meson.build\n+++ b/src/meson.build\n@@ -3,6 +3,7 @@ rustmod = import('rust')\n libgit_rs = static_library('git_rs',\n   sources: [\n     'lib.rs',\n+    'varint.rs',\n   ],\n   rust_abi: 'c',\n )\ndiff --git a/src/varint.rs b/src/varint.rs\nnew file mode 100644\nindex 00000000000..3d41760a555\n--- /dev/null\n+++ b/src/varint.rs\n@@ -0,0 +1,92 @@\n+use std::os::raw::c_int;\n+use std::os::raw::c_uchar;\n+\n+#[no_mangle]\n+pub unsafe extern \"C\" fn decode_varint(bufp: *mut *const c_uchar) -> usize {\n+    let mut buf = *bufp;\n+    let mut c = *buf;\n+    let mut val = usize::from(c & 127);\n+\n+    buf = buf.add(1);\n+\n+    while (c & 128) != 0 {\n+        val += 1;\n+        if val == 0 || val.leading_zeros() < 7 {\n+            return 0; // overflow\n+        }\n+\n+        c = *buf;\n+        buf = buf.add(1);\n+\n+        val = (val << 7) + usize::from(c & 127);\n+    }\n+\n+    *bufp = buf;\n+    val\n+}\n+\n+#[no_mangle]\n+pub unsafe extern \"C\" fn encode_varint(value: usize, buf: *mut c_uchar) -> c_int {\n+    let mut varint: [u8; 16] = [0; 16];\n+    let mut pos = varint.len() - 1;\n+\n+    varint[pos] = (value & 127) as u8;\n+\n+    let mut value = value >> 7;\n+    while value != 0 {\n+        pos -= 1;\n+        value -= 1;\n+        varint[pos] = 128 | (value & 127) as u8;\n+        value >>= 7;\n+    }\n+\n+    if !buf.is_null() {\n+        std::ptr::copy_nonoverlapping(varint.as_ptr().add(pos), buf, varint.len() - pos);\n+    }\n+\n+    (varint.len() - pos) as c_int\n+}\n+\n+#[cfg(test)]\n+mod tests {\n+    use super::*;\n+\n+    #[test]\n+    fn test_decode_varint() {\n+        unsafe {\n+            assert_eq!(decode_varint(&mut [0x00].as_slice().as_ptr()), 0);\n+            assert_eq!(decode_varint(&mut [0x01].as_slice().as_ptr()), 1);\n+            assert_eq!(decode_varint(&mut [0x7f].as_slice().as_ptr()), 127);\n+            assert_eq!(decode_varint(&mut [0x80, 0x00].as_slice().as_ptr()), 128);\n+            assert_eq!(decode_varint(&mut [0x80, 0x01].as_slice().as_ptr()), 129);\n+            assert_eq!(decode_varint(&mut [0x80, 0x7f].as_slice().as_ptr()), 255);\n+        }\n+    }\n+\n+    #[test]\n+    fn test_encode_varint() {\n+        unsafe {\n+            let mut varint: [u8; 16] = [0; 16];\n+\n+            assert_eq!(encode_varint(0, std::ptr::null_mut()), 1);\n+\n+            assert_eq!(encode_varint(0, varint.as_mut_slice().as_mut_ptr()), 1);\n+            assert_eq!(varint, [0; 16]);\n+\n+            assert_eq!(encode_varint(10, varint.as_mut_slice().as_mut_ptr()), 1);\n+            assert_eq!(varint, [10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n+\n+            assert_eq!(encode_varint(127, varint.as_mut_slice().as_mut_ptr()), 1);\n+            assert_eq!(varint, [127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n+\n+            assert_eq!(encode_varint(128, varint.as_mut_slice().as_mut_ptr()), 2);\n+            assert_eq!(varint, [128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n+\n+            assert_eq!(encode_varint(129, varint.as_mut_slice().as_mut_ptr()), 2);\n+            assert_eq!(varint, [128, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n+\n+            assert_eq!(encode_varint(255, varint.as_mut_slice().as_mut_ptr()), 2);\n+            assert_eq!(varint, [128, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n+        }\n+    }\n+}\n\n-- \n2.51.0.417.g1ba7204a04.dirty\n\n"},{"id":"525523","messageId":"20250904-b4-pks-rust-breaking-change-v1-3-3af1d25e0be9@pks.im","threadId":"64091","inReplyTo":"20250904-b4-pks-rust-breaking-change-v1-0-3af1d25e0be9@pks.im","subject":"[PATCH RFC 3/3] BreakingChanges: announce Rust becoming mandatory","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-04T14:26:45Z","receivedAt":"2025-09-04T14:27:17Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Over the last couple of years the appetite for bringin Rust into the\ncodebase has grown significantly across the developer base. Introducing\nRust is a major change though and has ramifications for the whole\necosystem:\n\n  - Some platforms haven't yet been able to implement a Rust toolchain,\n    even though it is possible in theory.\n\n  - Some platforms don't have any support for Rust at all.\n\n  - Some platforms may have to figure out how to fit Rust into their\n    bootstrapping sequence.\n\nDue to this, and given that Git is a critical piece of infrastructure\nfor the whole industry, we cannot just introduce such a heavyweight\ndependency without doing our due diligence.\n\nInstead, preceding commits have introduced a test balloon into our build\ninfrastructure that convert one tiny subsystem to use Rust. For now,\nusing Rust to build that subsystem is entirely optional -- if no Rust\nsupport is available, we continue to use the C implementation. This test\nballoon has the intention to give distributions time and let them ease\ninto our adoption of Rust.\n\nHaving multiple implementations of the same subsystem is not sustainable\nthough, and the plan is to eventually be able to use Rust freely all\nacross our codebase. As such, there is the intent to make Rust become a\nmandatory part of our build process.\n\nAdd an announcement to our breaking changes that Rust will become\nmandatory in Git 3.0. A (very careful and non-binding) estimate might be\nthat this major release might be released in the second half of next\nyear, which should give distributors enough time to prepare for the\nchange.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n Documentation/BreakingChanges.adoc | 20 ++++++++++++++++++++\n 1 file changed, 20 insertions(+)\n\ndiff --git a/Documentation/BreakingChanges.adoc b/Documentation/BreakingChanges.adoc\nindex f8d2eba061..b72c4dd4a0 100644\n--- a/Documentation/BreakingChanges.adoc\n+++ b/Documentation/BreakingChanges.adoc\n@@ -165,6 +165,26 @@ A prerequisite for this change is that the ecosystem is ready to support the\n \"reftable\" format. Most importantly, alternative implementations of Git like\n JGit, libgit2 and Gitoxide need to support it.\n \n+* Git will require Rust as a mandatory part of the build process. While Git\n+  already started to adopt Rust in the Git 2.52, all parts written in Rust are\n+  optional for the time being. This includes:\n++\n+  ** Subsystems that have an alternative implementation in Rust to test\n+     interoperability between our C and Rust codebase.\n+  ** Newly written features that are not mission critical for a fully functional\n+     Git client.\n++\n+Meson auto-detects the availability of a Rust toolchain and, if available,\n+builds the optional Rust code. This can be changed by executing `meson configure\n+-Drust=(enabled|disabled|auto)`.\n++\n+These changes are meant as test balloons to allow distributors of Git to prepare\n+for Rust becoming a mandatory part of the build process. Once Git 3.0 is out,\n+Rust becomes mandatory and it will not be possible anymore to build Git without\n+it. The Git project will declare the last version before Git 3.0 to be a\n+long-term support release that is maintained until alternate Rust backends like\n+gcc-rs are able to build Git.\n+\n === Removals\n \n * Support for grafting commits has long been superseded by git-replace(1).\n\n-- \n2.51.0.417.g1ba7204a04.dirty\n\n"},{"id":"525552","messageId":"CAPig+cThyuo7=A2f7_XkE_TZmSRc5i=EFgZOw_pKgu+Ckgx70w@mail.gmail.com","threadId":"64091","inReplyTo":"20250904-b4-pks-rust-breaking-change-v1-3-3af1d25e0be9@pks.im","subject":"Re: [PATCH RFC 3/3] BreakingChanges: announce Rust becoming mandatory","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2025-09-04T17:38:52Z","receivedAt":"2025-09-04T17:39:04Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Thu, Sep 4, 2025 at 10:30 AM Patrick Steinhardt <ps@pks.im> wrote:\n> Over the last couple of years the appetite for bringin Rust into the\n> codebase has grown significantly across the developer base. Introducing\n> Rust is a major change though and has ramifications for the whole\n> ecosystem:\n\ns/bringin/bringing/\n\n> Instead, preceding commits have introduced a test balloon into our build\n> infrastructure that convert one tiny subsystem to use Rust. For now,\n> using Rust to build that subsystem is entirely optional -- if no Rust\n> support is available, we continue to use the C implementation. This test\n> balloon has the intention to give distributions time and let them ease\n> into our adoption of Rust.\n\nIf it's entirely optional and automatically disabled on platforms\nwhich don't have Rust installed/available, then it isn't a test\nballoon, is it? All previous test balloons in this project were\narchitected in such a way that Git would fail to build if the platform\nin question lacked the feature being \"test-ballooned\", and the idea\nwas that packagers of those systems would alert the Git project about\nthe problem or somehow resolve it themselves via the platform's local\nbuild infrastructure.\n\nHowever, with the approach implemented here, Git will build as usual\non all platforms on which it already builds successfully, which means\nthat the Git project is unlikely to hear complaints from packagers,\nespecially if packagers haven't followed the relevant discussion\nthreads and are unaware that a Rust test is being conducted. Moreover,\nthe project has already heard from some packagers/maintainers that\nRust support is lacking or (currently) impossible, so the project\nalready has the sort of knowledge that a test balloon is intended to\nelicit.\n\nThat's not to say that the changes implemented by this series can't be\nvaluable, but rather that for these patches to be valuable, you\nprobably need some way to advertise the test more loudly so that\npackagers actually attempt the Rust build. One possible way to rectify\nthis shortcoming would be to enable the Rust code by default in the\nGit project but give packagers a way to opt out of it if they can't\nmake it work on their platforms.\n\n> Having multiple implementations of the same subsystem is not sustainable\n> though, and the plan is to eventually be able to use Rust freely all\n> across our codebase. As such, there is the intent to make Rust become a\n> mandatory part of our build process.\n>\n> Add an announcement to our breaking changes that Rust will become\n> mandatory in Git 3.0. A (very careful and non-binding) estimate might be\n> that this major release might be released in the second half of next\n> year, which should give distributors enough time to prepare for the\n> change.\n>\n> Signed-off-by: Patrick Steinhardt <ps@pks.im>\n"},{"id":"525560","messageId":"xmqqzfba6oih.fsf@gitster.g","threadId":"64091","inReplyTo":"20250904-b4-pks-rust-breaking-change-v1-1-3af1d25e0be9@pks.im","subject":"Re: [PATCH RFC 1/3] meson: add infrastructure to build internal Rust library","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-09-04T18:50:14Z","receivedAt":"2025-09-04T18:50:17Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> Add the infrastructure into Meson to build an internal Rust library.\n\nI am a bit surprised that Meson needs to learn Rust now.  How have\nyou been dealing with contrib/libgit-{sys,rs}?\n\n> Building the Rust parts of Git are for now entirely optional, as they\n> are mostly intended as a test balloon for both Git developers, but also\n> for distributors of Git. So for now, they may contain:\n>\n>   - New features that are not mission critical to Git and that users can\n>     easily live without.\n>\n>   - Alternative implementations of small subsystems.\n>\n> If these test balloons are successful, we will eventually make Rust a\n> mandatory dependency for our build process in Git 3.0.\n>\n> The availability of a Rust toolchain will be auto-detected by Meson at\n> setup time. This behaviour can be tweaked via the `-Drust=` feature\n> toggle.\n>\n> Next to the linkable Rust library, also wire up tests that can be\n> executed via `meson test`. This allows us to use the native unit testing\n> capabilities of Rust.\n\nOK.\n\n> Signed-off-by: Patrick Steinhardt <ps@pks.im>\n> ---\n>  meson.build       | 16 +++++++++++++++-\n>  meson_options.txt |  2 ++\n>  src/lib.rs        |  0\n>  src/meson.build   | 12 ++++++++++++\n>  4 files changed, 29 insertions(+), 1 deletion(-)\n"},{"id":"525566","messageId":"aLoNc5S6PVW8jLu5@fruit.crustytoothpaste.net","threadId":"64091","inReplyTo":"20250904-b4-pks-rust-breaking-change-v1-1-3af1d25e0be9@pks.im","subject":"Re: [PATCH RFC 1/3] meson: add infrastructure to build internal Rust library","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2025-09-04T22:06:43Z","receivedAt":"2025-09-04T22:06:45Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On 2025-09-04 at 14:26:43, Patrick Steinhardt wrote:\n> Add the infrastructure into Meson to build an internal Rust library.\n> Building the Rust parts of Git are for now entirely optional, as they\n> are mostly intended as a test balloon for both Git developers, but also\n> for distributors of Git. So for now, they may contain:\n> \n>   - New features that are not mission critical to Git and that users can\n>     easily live without.\n> \n>   - Alternative implementations of small subsystems.\n> \n> If these test balloons are successful, we will eventually make Rust a\n> mandatory dependency for our build process in Git 3.0.\n> \n> The availability of a Rust toolchain will be auto-detected by Meson at\n> setup time. This behaviour can be tweaked via the `-Drust=` feature\n> toggle.\n> \n> Next to the linkable Rust library, also wire up tests that can be\n> executed via `meson test`. This allows us to use the native unit testing\n> capabilities of Rust.\n\nI don't see any changes in this series that wire up the Makefile to do\nthe same thing.  Lots of people use the Makefile, or things based on the\nMakefile like the autotools, so we'll want to make sure this\nautodetection works there.  For instance, I build with the Makefile, we\nbuild with it at work, and Debian builds only with the Makefile.\n\nWe also probably need to test this configuration in CI as well.\n\n> diff --git a/meson.build b/meson.build\n> index e8ec0eca165..1c0e98bbc14 100644\n> --- a/meson.build\n> +++ b/meson.build\n> @@ -1702,8 +1702,21 @@ version_def_h = custom_target(\n>  )\n>  libgit_sources += version_def_h\n>  \n> +libgit_libraries = [ ]\n> +\n> +if meson.version().version_compare('>=1.9.0')\n\nI think we need a different approach.  Debian 13, which was just\nreleased, only supports meson 1.7.0, and you have to use testing or\nunstable to get 1.9.0.  There are no versions of Ubuntu, released or\nnot, that support meson 1.9.0.\n\nIf we require this version, practically nobody is going to actually test\nthis case.\n\nOur platform support policy implies that we should be requiring nothing\ngreater than meson 0.56.2, which is available in Debian 11 and has LTS\nsupport until 2026-08-31.  Ubuntu 22.04 offers 0.61.2.\n-- \nbrian m. carlson (they/them)\nToronto, Ontario, CA\n"},{"id":"525568","messageId":"aLoUuxfQmxHdqiYe@fruit.crustytoothpaste.net","threadId":"64091","inReplyTo":"20250904-b4-pks-rust-breaking-change-v1-2-3af1d25e0be9@pks.im","subject":"Re: [PATCH RFC 2/3] rust: implement a test balloon via the \"varint\" subsystem","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2025-09-04T22:37:47Z","receivedAt":"2025-09-04T22:37:49Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On 2025-09-04 at 14:26:44, Patrick Steinhardt wrote:\n> diff --git a/meson.build b/meson.build\n> index 1c0e98bbc14..b52a68b0bb6 100644\n> --- a/meson.build\n> +++ b/meson.build\n> @@ -522,7 +522,6 @@ libgit_sources = [\n>    'usage.c',\n>    'userdiff.c',\n>    'utf8.c',\n> -  'varint.c',\n>    'version.c',\n>    'versioncmp.c',\n>    'walker.c',\n> @@ -1713,6 +1712,10 @@ rust_option = get_option('rust').disable_auto_if(not rust_available)\n>  \n>  if rust_option.allowed() and meson.version().version_compare('>=1.9.0')\n>    subdir('src')\n> +else\n> +  libgit_sources += [\n> +    'varint.c',\n> +  ]\n>  endif\n\nCan we also add a #define constant when building?  For instance, if I'm\nwriting interop code in Rust, I'll need to be able to do something like\nthis:\n\n    int do_foobar()\n    {\n    #ifdef RUST\n      /* Call some code */\n    #else\n      die(_(\"interoperability not supported\"));\n    #endif\n    }\n-- \nbrian m. carlson (they/them)\nToronto, Ontario, CA\n"},{"id":"525570","messageId":"xmqqa5397s4i.fsf@gitster.g","threadId":"64091","inReplyTo":"aLoNc5S6PVW8jLu5@fruit.crustytoothpaste.net","subject":"Re: [PATCH RFC 1/3] meson: add infrastructure to build internal Rust library","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-09-04T22:46:53Z","receivedAt":"2025-09-04T22:46:57Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"brian m. carlson\" <sandals@crustytoothpaste.net> writes:\n\n> I don't see any changes in this series that wire up the Makefile to do\n> the same thing.  Lots of people use the Makefile, or things based on the\n> Makefile like the autotools, so we'll want to make sure this\n> autodetection works there.  For instance, I build with the Makefile, we\n> build with it at work, and Debian builds only with the Makefile.\n\nYeah, that is a bit disappointing, but I was not surprised, as that\nis what the cover letter promised to give us ;-)\n\n> We also probably need to test this configuration in CI as well.\n>\n>> diff --git a/meson.build b/meson.build\n>> index e8ec0eca165..1c0e98bbc14 100644\n>> --- a/meson.build\n>> +++ b/meson.build\n>> @@ -1702,8 +1702,21 @@ version_def_h = custom_target(\n>>  )\n>>  libgit_sources += version_def_h\n>>  \n>> +libgit_libraries = [ ]\n>> +\n>> +if meson.version().version_compare('>=1.9.0')\n>\n> I think we need a different approach.  Debian 13, which was just\n> released, only supports meson 1.7.0, and you have to use testing or\n> unstable to get 1.9.0.  There are no versions of Ubuntu, released or\n> not, that support meson 1.9.0.\n>\n> If we require this version, practically nobody is going to actually test\n> this case.\n>\n> Our platform support policy implies that we should be requiring nothing\n> greater than meson 0.56.2, which is available in Debian 11 and has LTS\n> support until 2026-08-31.  Ubuntu 22.04 offers 0.61.2.\n\nThanks for reminding all of us.\n"},{"id":"525575","messageId":"CAH=ZcbANoa8Qjbz4OmdZatBi5b+RQVnatF+7pmffA4SQh=EFCw@mail.gmail.com","threadId":"64091","inReplyTo":"20250904-b4-pks-rust-breaking-change-v1-2-3af1d25e0be9@pks.im","subject":"Re: [PATCH RFC 2/3] rust: implement a test balloon via the \"varint\" subsystem","fromName":"Ezekiel Newren","fromEmail":"ezekielnewren@gmail.com","sentAt":"2025-09-04T23:39:45Z","receivedAt":"2025-09-04T23:39:58Z","isPatch":true,"sender":{"key":"ezekielnewren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/18313324?v=4"},"body":"On Thu, Sep 4, 2025 at 8:27 AM Patrick Steinhardt <ps@pks.im> wrote:\n> Implement a trivial test balloon for our Rust build infrastructure by\n> reimplementing the \"varint.c\" subsystem in Rust. This subsystem is\n> chosen because it is trivial to convert and because it doesn't have any\n> dependencies to other components of Git.\n\nHuh, I thought Meson couldn't run Rust tests. It's refreshing to see\nsomeone else try a different approach on bringing Rust to Git.\n\nThere are a few reasons why I picked Cargo instead of Meson to build Rust:\n  1. Needs to work with make.\n  2. I've heard that using crates in Meson is quite painful.\n  3. My understanding is that someday in the distant future Rust will\nsupplant C in Git.\n  3. The IDE RustRover only understands Cargo.\n\nAs I mentioned in another thread: The reason why I made Rust a hard\ndependency is because it's easier to develop and talk about that way.\nI'm open to suggestions on how to make Rust optional.\n"},{"id":"525582","messageId":"013a3006-d220-424d-a28d-fb273c523c71@gentoo.org","threadId":"64091","inReplyTo":"aLoNc5S6PVW8jLu5@fruit.crustytoothpaste.net","subject":"Re: [PATCH RFC 1/3] meson: add infrastructure to build internal Rust library","fromName":"Eli Schwartz","fromEmail":"eschwartz@gentoo.org","sentAt":"2025-09-05T01:16:03Z","receivedAt":"2025-09-05T01:16:09Z","isPatch":true,"sender":{"key":"eschwartz@gentoo.org","avatar":"https://avatars.githubusercontent.com/u/6551424?v=4"},"body":"On 9/4/25 6:06 PM, brian m. carlson wrote:\n\n>> +if meson.version().version_compare('>=1.9.0')\n> \n> I think we need a different approach.  Debian 13, which was just\n> released, only supports meson 1.7.0, and you have to use testing or\n> unstable to get 1.9.0.  There are no versions of Ubuntu, released or\n> not, that support meson 1.9.0.\n> \n> If we require this version, practically nobody is going to actually test\n> this case.\n> \n> Our platform support policy implies that we should be requiring nothing\n> greater than meson 0.56.2, which is available in Debian 11 and has LTS\n> support until 2026-08-31.  Ubuntu 22.04 offers 0.61.2.\n\n\nHmm. Patrick -- do you mind documenting why you decided to use this\nversion guard at all? Off the top of my head I'm not sure why you'd need\nthis.\n\nIn src/meson.build,\n\n+libgit_rs = static_library('git_rs',\n+  sources: [\n+    'lib.rs',\n+  ],\n+  rust_abi: 'c',\n+)\n\n\n\nrust_abi is new in meson 1.3.0, but it's just a rename for clarity of\nrust_crate_type, available since meson 0.42.0, so please use the\nbackwards-compatible name...\n\n\n-- \nEli Schwartz\n"},{"id":"525583","messageId":"85b9def3-ae1c-4535-9d56-be6f08eaa8d7@gentoo.org","threadId":"64091","inReplyTo":"CAH=ZcbANoa8Qjbz4OmdZatBi5b+RQVnatF+7pmffA4SQh=EFCw@mail.gmail.com","subject":"Re: [PATCH RFC 2/3] rust: implement a test balloon via the \"varint\" subsystem","fromName":"Eli Schwartz","fromEmail":"eschwartz@gentoo.org","sentAt":"2025-09-05T02:00:45Z","receivedAt":"2025-09-05T02:00:50Z","isPatch":true,"sender":{"key":"eschwartz@gentoo.org","avatar":"https://avatars.githubusercontent.com/u/6551424?v=4"},"body":"On 9/4/25 7:39 PM, Ezekiel Newren wrote:\n> On Thu, Sep 4, 2025 at 8:27 AM Patrick Steinhardt <ps@pks.im> wrote:\n>> Implement a trivial test balloon for our Rust build infrastructure by\n>> reimplementing the \"varint.c\" subsystem in Rust. This subsystem is\n>> chosen because it is trivial to convert and because it doesn't have any\n>> dependencies to other components of Git.\n> \n> Huh, I thought Meson couldn't run Rust tests. It's refreshing to see\n> someone else try a different approach on bringing Rust to Git.\n> \n> There are a few reasons why I picked Cargo instead of Meson to build Rust:\n>   1. Needs to work with make.\n\n\nIf the rust code is defined as a crate, meson can auto-import that crate\nvia parsing Cargo.toml, so perhaps this can simply be done by creating a\n\n[lib]\ncrate-type = 'cdylib'\n\nand... importing it as a meson subproject. You'd be able to build it\nwith cargo build, if you really want to (and the Makefile may have to)\nbut Meson would not be limited to this.\n\n\n>   2. I've heard that using crates in Meson is quite painful.\n\n\nThis is specific to build.rs, and it is \"difficult\" in the sense that\nmeson cannot compile build.rs into an executable depending on other crates.\n\nCompiling it into an executable depending on other crates is a\nprerequisite for running it and parsing its stdout into a list of\ndefines (rust calls them --cfg) to pass as command line flags for the\nreal build target.\n\nMeson has official guidance for doing that work in-process by writing a\n\"plugin\" meson.build:\n\nhttps://mesonbuild.com/Wrap-dependency-system-manual.html#cargo-wraps\n\nbuild.rs is not something which any crate likes to have anyway. Most\ncrates therefore don't. And don't have any problem being used by meson.\n\n\n>   3. My understanding is that someday in the distant future Rust will\n> supplant C in Git.\n\n\nAnd you will want a build system that understands both compiling rust,\nand installing files in general (cargo cannot do this) and installing a\nquite wide variety of data files (implicitly the previous point means\ncargo cannot do this either).\n\nWho knows? Maybe in the \"distant\" future, Meson will have even more\nadditional support for Rust. I think I may have heard a rumor that Meson\nis open source, so contributors will probably be welcome. I also heard\nanother rumor that QEMU has been contributing a lot to this, and Gnome\nand Mesa as well.\n\nIf it's all part of the distant future anyway, we can *certainly* try to\nhelp shape the future to fit our needs, and experiment with different\nways to achieve that.\n\n...\n\nBTW: running tests with cargo is a genuine nightmare hellscape. As a\nlinux distro packager, I don't know what is wrong with cargo but I sure\nas heck know that if I run `cargo build` followed by `cargo test`, the\nresulting binary, if installed, will have incorrect behavior.\n\nhttps://gitweb.gentoo.org/repo/gentoo.git/commit/dev-util/ruff?id=f10d64828e9c33b2a1951c9a0e1fa84e4a736875\n\nMeson has sane behavior here, because two completely different build\ntargets (a program and a unittest) don't create the *same* file.\n\nI am very nervous about trusting cargo for predictable behavior.\n\n\n>   3. The IDE RustRover only understands Cargo.\n\nSince Meson 0.64 we generate the rust-analyzer official format for\nintegration:\n\nhttps://mesonbuild.com/Rust.html#use-with-rustanalyzer\n\nWe're very much open to ideas about how to improve this but my\nunderstanding was that rust itself expects you to use this special file\n-- why doesn't RustRover use it?\n\nIs RustRover (a very specific thirdparty IDE) a dealbreaker, one way or\nanother?\n\n\n> As I mentioned in another thread: The reason why I made Rust a hard\n> dependency is because it's easier to develop and talk about that way.\n> I'm open to suggestions on how to make Rust optional.\n\n\n-- \nEli Schwartz\n"},{"id":"525594","messageId":"aLqWFBqNranJWSFh@pks.im","threadId":"64091","inReplyTo":"xmqqa5397s4i.fsf@gitster.g","subject":"Re: [PATCH RFC 1/3] meson: add infrastructure to build internal Rust library","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-05T07:49:40Z","receivedAt":"2025-09-05T07:49:55Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Thu, Sep 04, 2025 at 03:46:53PM -0700, Junio C Hamano wrote:\n> \"brian m. carlson\" <sandals@crustytoothpaste.net> writes:\n> \n> > I don't see any changes in this series that wire up the Makefile to do\n> > the same thing.  Lots of people use the Makefile, or things based on the\n> > Makefile like the autotools, so we'll want to make sure this\n> > autodetection works there.  For instance, I build with the Makefile, we\n> > build with it at work, and Debian builds only with the Makefile.\n> \n> Yeah, that is a bit disappointing, but I was not surprised, as that\n> is what the cover letter promised to give us ;-)\n\nYup. This series is currently RFC, so I was first seeking feedback on\nit and encourage discussions on the general direction. I mostly did it\nfor Meson only because it was easier, but if we agree on the direction\nof this patch series I'll implement it in our Makefile in subsequent\nversions, as well.\n\n> > We also probably need to test this configuration in CI as well.\n> >\n> >> diff --git a/meson.build b/meson.build\n> >> index e8ec0eca165..1c0e98bbc14 100644\n> >> --- a/meson.build\n> >> +++ b/meson.build\n> >> @@ -1702,8 +1702,21 @@ version_def_h = custom_target(\n> >>  )\n> >>  libgit_sources += version_def_h\n> >>  \n> >> +libgit_libraries = [ ]\n> >> +\n> >> +if meson.version().version_compare('>=1.9.0')\n> >\n> > I think we need a different approach.  Debian 13, which was just\n> > released, only supports meson 1.7.0, and you have to use testing or\n> > unstable to get 1.9.0.  There are no versions of Ubuntu, released or\n> > not, that support meson 1.9.0.\n> >\n> > If we require this version, practically nobody is going to actually test\n> > this case.\n> >\n> > Our platform support policy implies that we should be requiring nothing\n> > greater than meson 0.56.2, which is available in Debian 11 and has LTS\n> > support until 2026-08-31.  Ubuntu 22.04 offers 0.61.2.\n> \n> Thanks for reminding all of us.\n\nEli mentioned that this version check shouldn't even be needed, so I can\nprobably drop it altogether. Will have a look.\n\nPatrick\n"},{"id":"525595","messageId":"aLqWKYkj98QUDxRi@pks.im","threadId":"64091","inReplyTo":"013a3006-d220-424d-a28d-fb273c523c71@gentoo.org","subject":"Re: [PATCH RFC 1/3] meson: add infrastructure to build internal Rust library","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-05T07:50:01Z","receivedAt":"2025-09-05T07:50:08Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Thu, Sep 04, 2025 at 09:16:03PM -0400, Eli Schwartz wrote:\n> On 9/4/25 6:06 PM, brian m. carlson wrote:\n> \n> >> +if meson.version().version_compare('>=1.9.0')\n> > \n> > I think we need a different approach.  Debian 13, which was just\n> > released, only supports meson 1.7.0, and you have to use testing or\n> > unstable to get 1.9.0.  There are no versions of Ubuntu, released or\n> > not, that support meson 1.9.0.\n> > \n> > If we require this version, practically nobody is going to actually test\n> > this case.\n> > \n> > Our platform support policy implies that we should be requiring nothing\n> > greater than meson 0.56.2, which is available in Debian 11 and has LTS\n> > support until 2026-08-31.  Ubuntu 22.04 offers 0.61.2.\n> \n> \n> Hmm. Patrick -- do you mind documenting why you decided to use this\n> version guard at all? Off the top of my head I'm not sure why you'd need\n> this.\n> \n> In src/meson.build,\n> \n> +libgit_rs = static_library('git_rs',\n> +  sources: [\n> +    'lib.rs',\n> +  ],\n> +  rust_abi: 'c',\n> +)\n> \n> \n> \n> rust_abi is new in meson 1.3.0, but it's just a rename for clarity of\n> rust_crate_type, available since meson 0.42.0, so please use the\n> backwards-compatible name...\n\nOh. I think I misunderstood the following sentence [1]:\n\n    (Since 1.9.0) Rust supports mixed targets, but only supports using\n    rustc as the linker for such targets. If you need to use a non-Rust\n    linker, or support Meson < 1.9.0, see below.\n\nI thought that only with Meson 1.9 you could link Rust libraries with C\nlibraries. But I guess this rather means that you can now have a single\ntarget that has both '.c' and '.rs' sources?\n\nIn any way, thanks for the hint, will drop.\n\nPatrick\n\n[1]: https://mesonbuild.com/Rust.html#mixing-rust-and-nonrust-sources\n"},{"id":"525596","messageId":"aLqXEcTMH-qoRHNs@pks.im","threadId":"64091","inReplyTo":"xmqqzfba6oih.fsf@gitster.g","subject":"Re: [PATCH RFC 1/3] meson: add infrastructure to build internal Rust library","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-05T07:53:53Z","receivedAt":"2025-09-05T07:54:02Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Thu, Sep 04, 2025 at 11:50:14AM -0700, Junio C Hamano wrote:\n> Patrick Steinhardt <ps@pks.im> writes:\n> \n> > Add the infrastructure into Meson to build an internal Rust library.\n> \n> I am a bit surprised that Meson needs to learn Rust now.  How have\n> you been dealing with contrib/libgit-{sys,rs}?\n\nNeither of these are wired up in Meson right now. There aren't really\nany users, they don't expose a lot of functionality, and both of these\nlibraries aren't actively developed right now. So I didn't yet have any\nmotivation to wire them up just yet.\n\nI also think we should reevaluate these once we officially support Rust\nin core Git. It feels way more reasonable to design our new core Rust\ncode in a way that it can be pulled in as a crate right from the start.\nMaybe it's just a matter of moving those libraries out of \"contrib/\" and\ninto our core Rust code?\n\nPatrick\n"},{"id":"525597","messageId":"aLqXGP5K6so13rCc@pks.im","threadId":"64091","inReplyTo":"aLoUuxfQmxHdqiYe@fruit.crustytoothpaste.net","subject":"Re: [PATCH RFC 2/3] rust: implement a test balloon via the \"varint\" subsystem","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-05T07:54:00Z","receivedAt":"2025-09-05T07:54:08Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Thu, Sep 04, 2025 at 10:37:47PM +0000, brian m. carlson wrote:\n> On 2025-09-04 at 14:26:44, Patrick Steinhardt wrote:\n> > diff --git a/meson.build b/meson.build\n> > index 1c0e98bbc14..b52a68b0bb6 100644\n> > --- a/meson.build\n> > +++ b/meson.build\n> > @@ -1713,6 +1712,10 @@ rust_option = get_option('rust').disable_auto_if(not rust_available)\n> >  \n> >  if rust_option.allowed() and meson.version().version_compare('>=1.9.0')\n> >    subdir('src')\n> > +else\n> > +  libgit_sources += [\n> > +    'varint.c',\n> > +  ]\n> >  endif\n> \n> Can we also add a #define constant when building?  For instance, if I'm\n> writing interop code in Rust, I'll need to be able to do something like\n> this:\n> \n>     int do_foobar()\n>     {\n>     #ifdef RUST\n>       /* Call some code */\n>     #else\n>       die(_(\"interoperability not supported\"));\n>     #endif\n>     }\n\nSure, that sounds like a useful addition. I can add it to the next\nversion already if you want to, or we can add it at a later point once\nit becomes needed.\n\nPatrick\n"},{"id":"525598","messageId":"aLqXHYb2jZpCKzp7@pks.im","threadId":"64091","inReplyTo":"85b9def3-ae1c-4535-9d56-be6f08eaa8d7@gentoo.org","subject":"Re: [PATCH RFC 2/3] rust: implement a test balloon via the \"varint\" subsystem","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-05T07:54:05Z","receivedAt":"2025-09-05T07:54:13Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Thu, Sep 04, 2025 at 10:00:45PM -0400, Eli Schwartz wrote:\n> On 9/4/25 7:39 PM, Ezekiel Newren wrote:\n> > On Thu, Sep 4, 2025 at 8:27 AM Patrick Steinhardt <ps@pks.im> wrote:\n> >> Implement a trivial test balloon for our Rust build infrastructure by\n> >> reimplementing the \"varint.c\" subsystem in Rust. This subsystem is\n> >> chosen because it is trivial to convert and because it doesn't have any\n> >> dependencies to other components of Git.\n> > \n> > Huh, I thought Meson couldn't run Rust tests. It's refreshing to see\n> > someone else try a different approach on bringing Rust to Git.\n> > \n> > There are a few reasons why I picked Cargo instead of Meson to build Rust:\n> >   1. Needs to work with make.\n> \n> \n> If the rust code is defined as a crate, meson can auto-import that crate\n> via parsing Cargo.toml, so perhaps this can simply be done by creating a\n> \n> [lib]\n> crate-type = 'cdylib'\n> \n> and... importing it as a meson subproject. You'd be able to build it\n> with cargo build, if you really want to (and the Makefile may have to)\n> but Meson would not be limited to this.\n\nThat sounds like a sensible thing to do. Just to clarify, this doesn't\nneed the experimental Cargo wraps, right? Is there any documentation for\nhow to set this up?\n\nPatrick\n"},{"id":"525599","messageId":"aLqXIwIU_L1Z1wIL@pks.im","threadId":"64091","inReplyTo":"CAPig+cThyuo7=A2f7_XkE_TZmSRc5i=EFgZOw_pKgu+Ckgx70w@mail.gmail.com","subject":"Re: [PATCH RFC 3/3] BreakingChanges: announce Rust becoming mandatory","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-05T07:54:11Z","receivedAt":"2025-09-05T07:54:18Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Thu, Sep 04, 2025 at 01:38:52PM -0400, Eric Sunshine wrote:\n> On Thu, Sep 4, 2025 at 10:30 AM Patrick Steinhardt <ps@pks.im> wrote:\n> > Over the last couple of years the appetite for bringin Rust into the\n> > codebase has grown significantly across the developer base. Introducing\n> > Rust is a major change though and has ramifications for the whole\n> > ecosystem:\n> \n> s/bringin/bringing/\n> \n> > Instead, preceding commits have introduced a test balloon into our build\n> > infrastructure that convert one tiny subsystem to use Rust. For now,\n> > using Rust to build that subsystem is entirely optional -- if no Rust\n> > support is available, we continue to use the C implementation. This test\n> > balloon has the intention to give distributions time and let them ease\n> > into our adoption of Rust.\n> \n> If it's entirely optional and automatically disabled on platforms\n> which don't have Rust installed/available, then it isn't a test\n> balloon, is it? All previous test balloons in this project were\n> architected in such a way that Git would fail to build if the platform\n> in question lacked the feature being \"test-ballooned\", and the idea\n> was that packagers of those systems would alert the Git project about\n> the problem or somehow resolve it themselves via the platform's local\n> build infrastructure.\n> \n> However, with the approach implemented here, Git will build as usual\n> on all platforms on which it already builds successfully, which means\n> that the Git project is unlikely to hear complaints from packagers,\n> especially if packagers haven't followed the relevant discussion\n> threads and are unaware that a Rust test is being conducted. Moreover,\n> the project has already heard from some packagers/maintainers that\n> Rust support is lacking or (currently) impossible, so the project\n> already has the sort of knowledge that a test balloon is intended to\n> elicit.\n> \n> That's not to say that the changes implemented by this series can't be\n> valuable, but rather that for these patches to be valuable, you\n> probably need some way to advertise the test more loudly so that\n> packagers actually attempt the Rust build. One possible way to rectify\n> this shortcoming would be to enable the Rust code by default in the\n> Git project but give packagers a way to opt out of it if they can't\n> make it work on their platforms.\n\nVery true indeed. Thinking about this, how about we make this a\nmulti-step process?\n\n  1. Introduce the feature as \"auto\"-detected on Meson and disabled in\n     our Makefile. This allows us to get comfortable with the tooling\n     and address any issues we find iteratively.\n\n  2. Change Meson to default to \"-Drust=enabled\" and change our Makefile\n     to make Rust opt-out instead of opt-in. Distros can still disable\n     this, but should now be alert that something is upcoming.\n\n  3. Remove the feature toggles altogether. Rust is now mandatory.\n\nIf this patch series here lands (1) would be the status quo. In one or\ntwo releases we could then do (2). And with Git 3.0 we can finally do\n(3).\n\nI'll add this process to the BreakingChanges document to give readers\nsome guidance.\n\nPatrick\n"},{"id":"525609","messageId":"20250905-b4-pks-rust-breaking-change-v2-0-6939cbf4a0b8@pks.im","threadId":"64091","inReplyTo":"20250904-b4-pks-rust-breaking-change-v1-0-3af1d25e0be9@pks.im","subject":"[PATCH RFC v2 0/7] Introduce Rust and announce that it will become mandatorty","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-05T11:50:56Z","receivedAt":"2025-09-05T11:51:07Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Hi,\n\nthis small patch series introduces Rust into the core of Git. This patch\nseries is designed as a test balloon, similar to how we introduced test\nballoons for C99 features in the past. The goal is threefold:\n\n  - Give us some time to experiment with Rust and introduce proper build\n    infrastructure.\n\n  - Give distributors time to ease into the new toolchain requirements.\n    Introducing Rust is impossible for some platforms and hard for\n    others.\n\n  - Announce that Git 3.0 will make Rust a mandatory part of our build\n    infrastructure.\n\nThe test balloon itself is quite uninteresting: I've chosen to convert\nthe \"varint.c\" subsystem, mostly because it is trivial and does not have\nany dependencies. But it does allow us to verify that C to Rust interop\nworks as expected, and to play around with tooling. All tests pass with\nthe \"varint.rs\" implementation.\n\nFor now, the series only contains support for Meson. If we agree to go\ndown this route I'll also introduce support for Rust into our Makefiles\nat a later point in time.\n\nFurthermore missing is additional tooling:\n\n  - At least one CI job to verify that Rust builds and works as\n    expected.\n\n  - Tooling and CI jobs to ensure that we have consistent formatting via\n    `cargo format`.\n\nAnd probably lots more. As said, the entire goal is for us to have an\neasy playground that we can experiment on and develop the infrastructure\nincrementally without yet having to commit to anything.\n\nI'm mostly splitting out the topic of introducing Rust from the larger\nseries that introduce it into xdiff so that we can focus more on the\nactual process of introducing Rust into Git and less on the potential\nfeatures that we want to build on top of it.\n\nChanges in v2:\n  - Introduce support for building the Rust library via our Makefile.\n  - Introduce a '-DWITH_RUST' define. This define is used to print\n    whether or not Git is built with Rust via `git version\n    --build-options`.\n  - Adjust Meson to not depend on v1.9.0 and newer anymore.\n  - Introduce a roadmap into our BreakingChanges document to explain how\n    we'll iterate towards mandatory Rust support.\n  - Rework the Fedora job to do a full compile-and-test run with Meson\n    and breaking changes enabled.\n  - Adapt our breaking-changes jobs to enable Rust support.\n  - Link to v1: https://lore.kernel.org/r/20250904-b4-pks-rust-breaking-change-v1-0-3af1d25e0be9@pks.im\n\nThanks!\n\nPatrick\n\n---\nPatrick Steinhardt (7):\n      meson: add infrastructure to build internal Rust library\n      Makefile: introduce infrastructure to build internal Rust library\n      help: report on whether or not Rust is enabled\n      rust: implement a test balloon via the \"varint\" subsystem\n      BreakingChanges: announce Rust becoming mandatory\n      ci: convert \"pedantic\" job into full build with breaking changes\n      ci: enable Rust for breaking-changes jobs\n\n .github/workflows/main.yml         |  4 +-\n .gitignore                         |  2 +\n .gitlab-ci.yml                     |  4 +-\n Cargo.toml                         |  9 ++++\n Documentation/BreakingChanges.adoc | 36 +++++++++++++++\n Makefile                           | 47 ++++++++++++++++++-\n ci/install-dependencies.sh         |  4 +-\n ci/run-build-and-tests.sh          | 31 +++++--------\n help.c                             |  6 +++\n meson.build                        | 17 ++++++-\n meson_options.txt                  |  2 +\n src/lib.rs                         |  1 +\n src/meson.build                    | 16 +++++++\n src/varint.rs                      | 92 ++++++++++++++++++++++++++++++++++++++\n 14 files changed, 240 insertions(+), 31 deletions(-)\n\nRange-diff versus v1:\n\n1:  4df400823c ! 1:  8f6e89bc7d meson: add infrastructure to build internal Rust library\n    @@ meson.build: version_def_h = custom_target(\n      \n     +libgit_libraries = [ ]\n     +\n    -+if meson.version().version_compare('>=1.9.0')\n    -+  rust_available = add_languages('rust', native: false, required: get_option('rust'))\n    -+else\n    -+  rust_available = false\n    -+endif\n    ++rust_available = add_languages('rust', native: false, required: get_option('rust'))\n     +rust_option = get_option('rust').disable_auto_if(not rust_available)\n    -+\n    -+if rust_option.allowed() and meson.version().version_compare('>=1.9.0')\n    ++if rust_option.allowed()\n     +  subdir('src')\n    ++  libgit_c_args += '-DWITH_RUST'\n     +endif\n     +\n      libgit = declare_dependency(\n    @@ src/lib.rs (new)\n     \n      ## src/meson.build (new) ##\n     @@\n    -+rustmod = import('rust')\n    -+\n     +libgit_rs = static_library('git_rs',\n     +  sources: [\n     +    'lib.rs',\n     +  ],\n    -+  rust_abi: 'c',\n    ++  rust_crate_type: 'staticlib',\n     +)\n    -+\n    -+rustmod.test('git-rs', libgit_rs)\n    -+\n     +libgit_libraries += libgit_rs\n    ++\n    ++# The 'rust' module was only introduced in Meson 1.0. Furthermore, the module\n    ++# does not seem to work on macOS as expected right now. As such, we only\n    ++# conditionally enable tests.\n    ++if meson.version().version_compare('>=1.0.0') and host_machine.system() != 'darwin'\n    ++  rustmod = import('rust')\n    ++  rustmod.test('rust', libgit_rs)\n    ++endif\n-:  ---------- > 2:  cd1d642d04 Makefile: introduce infrastructure to build internal Rust library\n-:  ---------- > 3:  e60a8353a4 help: report on whether or not Rust is enabled\n2:  575f6de44d ! 4:  b27811aea4 rust: implement a test balloon via the \"varint\" subsystem\n    @@ Commit message\n     \n         Signed-off-by: Patrick Steinhardt <ps@pks.im>\n     \n    + ## Makefile ##\n    +@@ Makefile: LIB_OBJS += urlmatch.o\n    + LIB_OBJS += usage.o\n    + LIB_OBJS += userdiff.o\n    + LIB_OBJS += utf8.o\n    ++ifndef WITH_RUST\n    + LIB_OBJS += varint.o\n    ++endif\n    + LIB_OBJS += version.o\n    + LIB_OBJS += versioncmp.o\n    + LIB_OBJS += walker.o\n    +\n      ## meson.build ##\n     @@ meson.build: libgit_sources = [\n        'usage.c',\n    @@ meson.build: libgit_sources = [\n        'versioncmp.c',\n        'walker.c',\n     @@ meson.build: rust_option = get_option('rust').disable_auto_if(not rust_available)\n    - \n    - if rust_option.allowed() and meson.version().version_compare('>=1.9.0')\n    + if rust_option.allowed()\n        subdir('src')\n    +   libgit_c_args += '-DWITH_RUST'\n     +else\n     +  libgit_sources += [\n     +    'varint.c',\n    @@ src/lib.rs\n     +pub mod varint;\n     \n      ## src/meson.build ##\n    -@@ src/meson.build: rustmod = import('rust')\n    +@@\n      libgit_rs = static_library('git_rs',\n        sources: [\n          'lib.rs',\n     +    'varint.rs',\n        ],\n    -   rust_abi: 'c',\n    +   rust_crate_type: 'staticlib',\n      )\n     \n      ## src/varint.rs (new) ##\n3:  e54393392a < -:  ---------- BreakingChanges: announce Rust becoming mandatory\n-:  ---------- > 5:  d5946e0114 BreakingChanges: announce Rust becoming mandatory\n-:  ---------- > 6:  0d367976de ci: convert \"pedantic\" job into full build with breaking changes\n-:  ---------- > 7:  82086a5328 ci: enable Rust for breaking-changes jobs\n\n---\nbase-commit: 2462961280690837670d997bde64bd4ebf8ae66d\nchange-id: 20250904-b4-pks-rust-breaking-change-7167d9d3e37d\n\n"},{"id":"525610","messageId":"20250905-b4-pks-rust-breaking-change-v2-1-6939cbf4a0b8@pks.im","threadId":"64091","inReplyTo":"20250905-b4-pks-rust-breaking-change-v2-0-6939cbf4a0b8@pks.im","subject":"[PATCH RFC v2 1/7] meson: add infrastructure to build internal Rust library","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-05T11:50:57Z","receivedAt":"2025-09-05T11:51:10Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Add the infrastructure into Meson to build an internal Rust library.\nBuilding the Rust parts of Git are for now entirely optional, as they\nare mostly intended as a test balloon for both Git developers, but also\nfor distributors of Git. So for now, they may contain:\n\n  - New features that are not mission critical to Git and that users can\n    easily live without.\n\n  - Alternative implementations of small subsystems.\n\nIf these test balloons are successful, we will eventually make Rust a\nmandatory dependency for our build process in Git 3.0.\n\nThe availability of a Rust toolchain will be auto-detected by Meson at\nsetup time. This behaviour can be tweaked via the `-Drust=` feature\ntoggle.\n\nNext to the linkable Rust library, also wire up tests that can be\nexecuted via `meson test`. This allows us to use the native unit testing\ncapabilities of Rust.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n meson.build       | 12 +++++++++++-\n meson_options.txt |  2 ++\n src/lib.rs        |  0\n src/meson.build   | 15 +++++++++++++++\n 4 files changed, 28 insertions(+), 1 deletion(-)\n\ndiff --git a/meson.build b/meson.build\nindex e8ec0eca165..5b2e9af1bf1 100644\n--- a/meson.build\n+++ b/meson.build\n@@ -1702,8 +1702,17 @@ version_def_h = custom_target(\n )\n libgit_sources += version_def_h\n \n+libgit_libraries = [ ]\n+\n+rust_available = add_languages('rust', native: false, required: get_option('rust'))\n+rust_option = get_option('rust').disable_auto_if(not rust_available)\n+if rust_option.allowed()\n+  subdir('src')\n+  libgit_c_args += '-DWITH_RUST'\n+endif\n+\n libgit = declare_dependency(\n-  link_with: static_library('git',\n+  link_with: libgit_libraries + static_library('git',\n     sources: libgit_sources,\n     c_args: libgit_c_args + [\n       '-DGIT_VERSION_H=\"' + version_def_h.full_path() + '\"',\n@@ -2239,6 +2248,7 @@ summary({\n   'pcre2': pcre2,\n   'perl': perl_features_enabled,\n   'python': target_python.found(),\n+  'rust': rust_option.allowed(),\n }, section: 'Auto-detected features', bool_yn: true)\n \n summary({\ndiff --git a/meson_options.txt b/meson_options.txt\nindex 1668f260a18..143dee9237c 100644\n--- a/meson_options.txt\n+++ b/meson_options.txt\n@@ -71,6 +71,8 @@ option('zlib_backend', type: 'combo', choices: ['auto', 'zlib', 'zlib-ng'], valu\n # Build tweaks.\n option('breaking_changes', type: 'boolean', value: false,\n   description: 'Enable upcoming breaking changes.')\n+option('rust', type: 'feature', value: 'auto',\n+  description: 'Enable building with Rust.')\n option('macos_use_homebrew_gettext', type: 'boolean', value: true,\n   description: 'Use gettext from Homebrew instead of the slightly-broken system-provided one.')\n \ndiff --git a/src/lib.rs b/src/lib.rs\nnew file mode 100644\nindex 00000000000..e69de29bb2d\ndiff --git a/src/meson.build b/src/meson.build\nnew file mode 100644\nindex 00000000000..eb752651d35\n--- /dev/null\n+++ b/src/meson.build\n@@ -0,0 +1,15 @@\n+libgit_rs = static_library('git_rs',\n+  sources: [\n+    'lib.rs',\n+  ],\n+  rust_crate_type: 'staticlib',\n+)\n+libgit_libraries += libgit_rs\n+\n+# The 'rust' module was only introduced in Meson 1.0. Furthermore, the module\n+# does not seem to work on macOS as expected right now. As such, we only\n+# conditionally enable tests.\n+if meson.version().version_compare('>=1.0.0') and host_machine.system() != 'darwin'\n+  rustmod = import('rust')\n+  rustmod.test('rust', libgit_rs)\n+endif\n\n-- \n2.51.0.417.g1ba7204a04.dirty\n\n"},{"id":"525611","messageId":"20250905-b4-pks-rust-breaking-change-v2-2-6939cbf4a0b8@pks.im","threadId":"64091","inReplyTo":"20250905-b4-pks-rust-breaking-change-v2-0-6939cbf4a0b8@pks.im","subject":"[PATCH RFC v2 2/7] Makefile: introduce infrastructure to build internal Rust library","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-05T11:50:58Z","receivedAt":"2025-09-05T11:51:13Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Introduce infrastructure to build the internal Rust library. This\nmirrors the infrastructure we have added to Meson in the preceding\ncommit. Developers can enable the infrastructure by passing the new\n`WITH_RUST` build toggle.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n .gitignore |  2 ++\n Cargo.toml |  9 +++++++++\n Makefile   | 45 +++++++++++++++++++++++++++++++++++++++++++--\n 3 files changed, 54 insertions(+), 2 deletions(-)\n\ndiff --git a/.gitignore b/.gitignore\nindex 1803023427..0833453cf6 100644\n--- a/.gitignore\n+++ b/.gitignore\n@@ -1,4 +1,6 @@\n /fuzz_corpora\n+/target/\n+/Cargo.lock\n /GIT-BUILD-DIR\n /GIT-BUILD-OPTIONS\n /GIT-CFLAGS\ndiff --git a/Cargo.toml b/Cargo.toml\nnew file mode 100644\nindex 0000000000..17a4f4da0c\n--- /dev/null\n+++ b/Cargo.toml\n@@ -0,0 +1,9 @@\n+[package]\n+name = \"git\"\n+version = \"0.1.0\"\n+edition = \"2021\"\n+\n+[lib]\n+crate-type = [\"staticlib\"]\n+\n+[dependencies]\ndiff --git a/Makefile b/Makefile\nindex 555b7f4dc3..e7b3c8e57b 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -483,6 +483,14 @@ include shared.mak\n # Define LIBPCREDIR=/foo/bar if your PCRE header and library files are\n # in /foo/bar/include and /foo/bar/lib directories.\n #\n+# == Optional Rust support ==\n+#\n+# Define WITH_RUST if you want to include features and subsystems written in\n+# Rust into Git. For now, Rust is still an optional feature of the build\n+# process. With Git 3.0 though, Rust will always be enabled.\n+#\n+# Building Rust code requires Cargo.\n+#\n # == SHA-1 and SHA-256 defines ==\n #\n # === SHA-1 backend ===\n@@ -918,6 +926,11 @@ TEST_SHELL_PATH = $(SHELL_PATH)\n LIB_FILE = libgit.a\n XDIFF_LIB = xdiff/lib.a\n REFTABLE_LIB = reftable/libreftable.a\n+ifdef DEBUG\n+RUST_LIB = target/debug/libgit.a\n+else\n+RUST_LIB = target/release/libgit.a\n+endif\n \n GENERATED_H += command-list.h\n GENERATED_H += config-list.h\n@@ -1387,8 +1400,12 @@ CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/unit-test.o\n \n UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o\n \n-# xdiff and reftable libs may in turn depend on what is in libgit.a\n-GITLIBS = common-main.o $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(LIB_FILE)\n+GITLIBS = common-main.o $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB)\n+ifdef WITH_RUST\n+GITLIBS += $(RUST_LIB)\n+endif\n+# Other libs may in turn depend on what is in libgit.a.\n+GITLIBS += $(LIB_FILE)\n EXTLIBS =\n \n GIT_USER_AGENT = git/$(GIT_VERSION)\n@@ -1411,6 +1428,19 @@ BASIC_LDFLAGS =\n ARFLAGS = rcs\n PTHREAD_CFLAGS =\n \n+# Rust flags\n+CARGO_ARGS =\n+ifndef V\n+CARGO_ARGS += --quiet\n+endif\n+ifndef DEBUG\n+CARGO_ARGS += --release\n+endif\n+\n+ifdef WITH_RUST\n+BASIC_CFLAGS += -DWITH_RUST\n+endif\n+\n # For the 'sparse' target\n SPARSE_FLAGS ?= -std=gnu99 -D__STDC_NO_VLA__\n SP_EXTRA_FLAGS =\n@@ -2918,6 +2948,16 @@ scalar$X: scalar.o GIT-LDFLAGS $(GITLIBS)\n $(LIB_FILE): $(LIB_OBJS)\n \t$(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^\n \n+$(RUST_LIB): FORCE\n+\t@OLD_STAT=\"$$(stat $@ 2>/dev/null)\"; \\\n+\t    cargo build $(CARGO_ARGS); \\\n+\t    if test $$? != 0 || test x\"$$OLD_STAT\" != x\"$$(stat $@ 2>/dev/null)\"; then \\\n+\t\techo '   ' CARGO $@; \\\n+\t    fi\n+\n+.PHONY: rust\n+rust: $(RUST_LIB)\n+\n $(XDIFF_LIB): $(XDIFF_OBJS)\n \t$(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^\n \n@@ -3768,6 +3808,7 @@ clean: profile-clean coverage-clean cocciclean\n \t$(RM) $(FUZZ_PROGRAMS)\n \t$(RM) $(SP_OBJ)\n \t$(RM) $(HCC)\n+\t$(RM) -r target/ Cargo.lock\n \t$(RM) version-def.h\n \t$(RM) -r $(dep_dirs) $(compdb_dir) compile_commands.json\n \t$(RM) $(test_bindir_programs)\n\n-- \n2.51.0.417.g1ba7204a04.dirty\n\n"},{"id":"525612","messageId":"20250905-b4-pks-rust-breaking-change-v2-3-6939cbf4a0b8@pks.im","threadId":"64091","inReplyTo":"20250905-b4-pks-rust-breaking-change-v2-0-6939cbf4a0b8@pks.im","subject":"[PATCH RFC v2 3/7] help: report on whether or not Rust is enabled","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-05T11:50:59Z","receivedAt":"2025-09-05T11:51:16Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"We're about to introduce support for Rust into the core of Git, where\nsome (trivial) subsystems are converted to Rust. These subsystems will\nalso retain a C implementation though as Rust is not yet mandatory.\nConsequently, it now becomes possible for a Git version to have bugs\nthat are specific to whether or not it is built with Rust support\noverall.\n\nExpose information about whether or not Git was built with Rust via our\nbuild info. This means that both `git version --build-options`, but also\n`git bugreport` will now expose that bit of information. Hopefully, this\nshould make it easier for us to discover any Rust-specific issues.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n help.c | 6 ++++++\n 1 file changed, 6 insertions(+)\n\ndiff --git a/help.c b/help.c\nindex bb20498cfd..5854dd4a7e 100644\n--- a/help.c\n+++ b/help.c\n@@ -791,6 +791,12 @@ void get_version_info(struct strbuf *buf, int show_build_options)\n \t\tstrbuf_addf(buf, \"shell-path: %s\\n\", SHELL_PATH);\n \t\t/* NEEDSWORK: also save and output GIT-BUILD_OPTIONS? */\n \n+#if defined WITH_RUST\n+\t\tstrbuf_addstr(buf, \"rust: enabled\\n\");\n+#else\n+\t\tstrbuf_addstr(buf, \"rust: disabled\\n\");\n+#endif\n+\n \t\tif (fsmonitor_ipc__is_supported())\n \t\t\tstrbuf_addstr(buf, \"feature: fsmonitor--daemon\\n\");\n #if defined LIBCURL_VERSION\n\n-- \n2.51.0.417.g1ba7204a04.dirty\n\n"},{"id":"525613","messageId":"20250905-b4-pks-rust-breaking-change-v2-4-6939cbf4a0b8@pks.im","threadId":"64091","inReplyTo":"20250905-b4-pks-rust-breaking-change-v2-0-6939cbf4a0b8@pks.im","subject":"[PATCH RFC v2 4/7] rust: implement a test balloon via the \"varint\" subsystem","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-05T11:51:00Z","receivedAt":"2025-09-05T11:51:19Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Implement a trivial test balloon for our Rust build infrastructure by\nreimplementing the \"varint.c\" subsystem in Rust. This subsystem is\nchosen because it is trivial to convert and because it doesn't have any\ndependencies to other components of Git.\n\nIf support for Rust is enabled, we stop compiling \"varint.c\" and instead\ncompile and use \"src/varint.rs\".\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n Makefile        |  2 ++\n meson.build     |  5 +++-\n src/lib.rs      |  1 +\n src/meson.build |  1 +\n src/varint.rs   | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n 5 files changed, 100 insertions(+), 1 deletion(-)\n\ndiff --git a/Makefile b/Makefile\nindex e7b3c8e57bf..8fd13a36db9 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -1209,7 +1209,9 @@ LIB_OBJS += urlmatch.o\n LIB_OBJS += usage.o\n LIB_OBJS += userdiff.o\n LIB_OBJS += utf8.o\n+ifndef WITH_RUST\n LIB_OBJS += varint.o\n+endif\n LIB_OBJS += version.o\n LIB_OBJS += versioncmp.o\n LIB_OBJS += walker.o\ndiff --git a/meson.build b/meson.build\nindex 5b2e9af1bf1..da9a8c8dea0 100644\n--- a/meson.build\n+++ b/meson.build\n@@ -522,7 +522,6 @@ libgit_sources = [\n   'usage.c',\n   'userdiff.c',\n   'utf8.c',\n-  'varint.c',\n   'version.c',\n   'versioncmp.c',\n   'walker.c',\n@@ -1709,6 +1708,10 @@ rust_option = get_option('rust').disable_auto_if(not rust_available)\n if rust_option.allowed()\n   subdir('src')\n   libgit_c_args += '-DWITH_RUST'\n+else\n+  libgit_sources += [\n+    'varint.c',\n+  ]\n endif\n \n libgit = declare_dependency(\ndiff --git a/src/lib.rs b/src/lib.rs\nindex e69de29bb2d..9da70d8b57d 100644\n--- a/src/lib.rs\n+++ b/src/lib.rs\n@@ -0,0 +1 @@\n+pub mod varint;\ndiff --git a/src/meson.build b/src/meson.build\nindex eb752651d35..4fc793fb17d 100644\n--- a/src/meson.build\n+++ b/src/meson.build\n@@ -1,6 +1,7 @@\n libgit_rs = static_library('git_rs',\n   sources: [\n     'lib.rs',\n+    'varint.rs',\n   ],\n   rust_crate_type: 'staticlib',\n )\ndiff --git a/src/varint.rs b/src/varint.rs\nnew file mode 100644\nindex 00000000000..3d41760a555\n--- /dev/null\n+++ b/src/varint.rs\n@@ -0,0 +1,92 @@\n+use std::os::raw::c_int;\n+use std::os::raw::c_uchar;\n+\n+#[no_mangle]\n+pub unsafe extern \"C\" fn decode_varint(bufp: *mut *const c_uchar) -> usize {\n+    let mut buf = *bufp;\n+    let mut c = *buf;\n+    let mut val = usize::from(c & 127);\n+\n+    buf = buf.add(1);\n+\n+    while (c & 128) != 0 {\n+        val += 1;\n+        if val == 0 || val.leading_zeros() < 7 {\n+            return 0; // overflow\n+        }\n+\n+        c = *buf;\n+        buf = buf.add(1);\n+\n+        val = (val << 7) + usize::from(c & 127);\n+    }\n+\n+    *bufp = buf;\n+    val\n+}\n+\n+#[no_mangle]\n+pub unsafe extern \"C\" fn encode_varint(value: usize, buf: *mut c_uchar) -> c_int {\n+    let mut varint: [u8; 16] = [0; 16];\n+    let mut pos = varint.len() - 1;\n+\n+    varint[pos] = (value & 127) as u8;\n+\n+    let mut value = value >> 7;\n+    while value != 0 {\n+        pos -= 1;\n+        value -= 1;\n+        varint[pos] = 128 | (value & 127) as u8;\n+        value >>= 7;\n+    }\n+\n+    if !buf.is_null() {\n+        std::ptr::copy_nonoverlapping(varint.as_ptr().add(pos), buf, varint.len() - pos);\n+    }\n+\n+    (varint.len() - pos) as c_int\n+}\n+\n+#[cfg(test)]\n+mod tests {\n+    use super::*;\n+\n+    #[test]\n+    fn test_decode_varint() {\n+        unsafe {\n+            assert_eq!(decode_varint(&mut [0x00].as_slice().as_ptr()), 0);\n+            assert_eq!(decode_varint(&mut [0x01].as_slice().as_ptr()), 1);\n+            assert_eq!(decode_varint(&mut [0x7f].as_slice().as_ptr()), 127);\n+            assert_eq!(decode_varint(&mut [0x80, 0x00].as_slice().as_ptr()), 128);\n+            assert_eq!(decode_varint(&mut [0x80, 0x01].as_slice().as_ptr()), 129);\n+            assert_eq!(decode_varint(&mut [0x80, 0x7f].as_slice().as_ptr()), 255);\n+        }\n+    }\n+\n+    #[test]\n+    fn test_encode_varint() {\n+        unsafe {\n+            let mut varint: [u8; 16] = [0; 16];\n+\n+            assert_eq!(encode_varint(0, std::ptr::null_mut()), 1);\n+\n+            assert_eq!(encode_varint(0, varint.as_mut_slice().as_mut_ptr()), 1);\n+            assert_eq!(varint, [0; 16]);\n+\n+            assert_eq!(encode_varint(10, varint.as_mut_slice().as_mut_ptr()), 1);\n+            assert_eq!(varint, [10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n+\n+            assert_eq!(encode_varint(127, varint.as_mut_slice().as_mut_ptr()), 1);\n+            assert_eq!(varint, [127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n+\n+            assert_eq!(encode_varint(128, varint.as_mut_slice().as_mut_ptr()), 2);\n+            assert_eq!(varint, [128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n+\n+            assert_eq!(encode_varint(129, varint.as_mut_slice().as_mut_ptr()), 2);\n+            assert_eq!(varint, [128, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n+\n+            assert_eq!(encode_varint(255, varint.as_mut_slice().as_mut_ptr()), 2);\n+            assert_eq!(varint, [128, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n+        }\n+    }\n+}\n\n-- \n2.51.0.417.g1ba7204a04.dirty\n\n"},{"id":"525614","messageId":"20250905-b4-pks-rust-breaking-change-v2-5-6939cbf4a0b8@pks.im","threadId":"64091","inReplyTo":"20250905-b4-pks-rust-breaking-change-v2-0-6939cbf4a0b8@pks.im","subject":"[PATCH RFC v2 5/7] BreakingChanges: announce Rust becoming mandatory","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-05T11:51:01Z","receivedAt":"2025-09-05T11:51:23Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Over the last couple of years the appetite for bringin Rust into the\ncodebase has grown significantly across the developer base. Introducing\nRust is a major change though and has ramifications for the whole\necosystem:\n\n  - Some platforms haven't yet been able to implement a Rust toolchain,\n    even though it is possible in theory.\n\n  - Some platforms don't have any support for Rust at all.\n\n  - Some platforms may have to figure out how to fit Rust into their\n    bootstrapping sequence.\n\nDue to this, and given that Git is a critical piece of infrastructure\nfor the whole industry, we cannot just introduce such a heavyweight\ndependency without doing our due diligence.\n\nInstead, preceding commits have introduced a test balloon into our build\ninfrastructure that convert one tiny subsystem to use Rust. For now,\nusing Rust to build that subsystem is entirely optional -- if no Rust\nsupport is available, we continue to use the C implementation. This test\nballoon has the intention to give distributions time and let them ease\ninto our adoption of Rust.\n\nHaving multiple implementations of the same subsystem is not sustainable\nthough, and the plan is to eventually be able to use Rust freely all\nacross our codebase. As such, there is the intent to make Rust become a\nmandatory part of our build process.\n\nAdd an announcement to our breaking changes that Rust will become\nmandatory in Git 3.0. A (very careful and non-binding) estimate might be\nthat this major release might be released in the second half of next\nyear, which should give distributors enough time to prepare for the\nchange.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n Documentation/BreakingChanges.adoc | 36 ++++++++++++++++++++++++++++++++++++\n 1 file changed, 36 insertions(+)\n\ndiff --git a/Documentation/BreakingChanges.adoc b/Documentation/BreakingChanges.adoc\nindex f8d2eba061..dbb15b6a57 100644\n--- a/Documentation/BreakingChanges.adoc\n+++ b/Documentation/BreakingChanges.adoc\n@@ -165,6 +165,42 @@ A prerequisite for this change is that the ecosystem is ready to support the\n \"reftable\" format. Most importantly, alternative implementations of Git like\n JGit, libgit2 and Gitoxide need to support it.\n \n+* Git will require Rust as a mandatory part of the build process. While Git\n+  already started to adopt Rust in the Git 2.52, all parts written in Rust are\n+  optional for the time being. This includes:\n++\n+  ** Subsystems that have an alternative implementation in Rust to test\n+     interoperability between our C and Rust codebase.\n+  ** Newly written features that are not mission critical for a fully functional\n+     Git client.\n++\n+These changes are meant as test balloons to allow distributors of Git to prepare\n+for Rust becoming a mandatory part of the build process. There will be multiple\n+milestones for the introduction of Rust:\n++\n+1. Initially, with Git 2.52, support for Rust will be auto-detected by Rust and\n+   disabled in our Makefile so that the project can sort out the initial\n+   infrastructure.\n+2. In Git 2.53, support for Rust will be made mandatory in case Git is compiled\n+   with breaking changes. Breaking changes can be enabled for Meson by saying\n+   `meson configure -Dbreaking_changes=true` and for Makefiles via `make\n+   WITH_BREAKING_CHANGES=YesPlease`. It will still be possible to compile with\n+   breaking changes, but explicitly disable Rust.\n+3. In Git 2.54, both build systems will default-enable support for Rust so that\n+   builds will break if Rust is not available on the build host. The use of Rust\n+   can still be explicitly disabled via build flags.\n+4. In Git 3.0, the build options will be removed and support for Rust is\n+   mandatory.\n++\n+You can explicitly ask both Meson and our Makefile-based system to enable Rust\n+by saying `meson configure -Drust=enabled` and `make WITH_RUST=YesPlease`,\n+respectively.\n++\n+The Git project will declare the last version before Git 3.0 to be a long-term\n+support release that is maintained until alternate Rust backends like gcc-rs are\n+able to build Git. The Git project may need to rely on distributions to help\n+with identifying and backporting important bugfixes.\n+\n === Removals\n \n * Support for grafting commits has long been superseded by git-replace(1).\n\n-- \n2.51.0.417.g1ba7204a04.dirty\n\n"},{"id":"525615","messageId":"20250905-b4-pks-rust-breaking-change-v2-6-6939cbf4a0b8@pks.im","threadId":"64091","inReplyTo":"20250905-b4-pks-rust-breaking-change-v2-0-6939cbf4a0b8@pks.im","subject":"[PATCH RFC v2 6/7] ci: convert \"pedantic\" job into full build with breaking changes","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-05T11:51:02Z","receivedAt":"2025-09-05T11:51:26Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The \"pedantic\" CI job is building on Fedora with `DEVOPTS=pedantic`.\nThis build flag doesn't do anything anymore starting with 6a8cbc41ba\n(developer: enable pedantic by default, 2021-09-03), where we have\nflipped the default so that developers have to opt-out of pedantic\nbuilds via the \"no-pedantic\" option. As such, all this job really does\nis to do a normal build on Fedora, which isn't all that interesting.\n\nConvert that job into a full build-and-test job that uses Meson with\nbreaking changes enabled. This plugs two gaps:\n\n  - We now test on another distro that we didn't run tests on\n    beforehand.\n\n  - We verify that breaking changes work as expected with Meson.\n\nFurthermore, in a subsequent commit we'll modify both jobs that use\nbreaking changes to also enable Rust. By converting the Fedora job to\nuse Meson, we ensure that we test our Rust build infrastructure for both\nbuild systems.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n .github/workflows/main.yml |  4 ++--\n .gitlab-ci.yml             |  4 ++--\n ci/install-dependencies.sh |  2 +-\n ci/run-build-and-tests.sh  | 29 ++++++++---------------------\n 4 files changed, 13 insertions(+), 26 deletions(-)\n\ndiff --git a/.github/workflows/main.yml b/.github/workflows/main.yml\nindex d122e79415..393ea4d1cc 100644\n--- a/.github/workflows/main.yml\n+++ b/.github/workflows/main.yml\n@@ -379,6 +379,8 @@ jobs:\n         - jobname: linux-breaking-changes\n           cc: gcc\n           image: ubuntu:rolling\n+        - jobname: fedora-breaking-changes-meson\n+          image: fedora:latest\n         - jobname: linux-leaks\n           image: ubuntu:rolling\n           cc: gcc\n@@ -396,8 +398,6 @@ jobs:\n         # Supported until 2025-04-02.\n         - jobname: linux32\n           image: i386/ubuntu:focal\n-        - jobname: pedantic\n-          image: fedora:latest\n         # A RHEL 8 compatible distro.  Supported until 2029-05-31.\n         - jobname: almalinux-8\n           image: almalinux:8\ndiff --git a/.gitlab-ci.yml b/.gitlab-ci.yml\nindex af10ebb59a..4248506909 100644\n--- a/.gitlab-ci.yml\n+++ b/.gitlab-ci.yml\n@@ -45,6 +45,8 @@ test:linux:\n       - jobname: linux-breaking-changes\n         image: ubuntu:20.04\n         CC: gcc\n+      - jobname: fedora-breaking-changes-meson\n+        image: fedora:latest\n       - jobname: linux-TEST-vars\n         image: ubuntu:20.04\n         CC: gcc\n@@ -58,8 +60,6 @@ test:linux:\n       - jobname: linux-asan-ubsan\n         image: ubuntu:rolling\n         CC: clang\n-      - jobname: pedantic\n-        image: fedora:latest\n       - jobname: linux-musl-meson\n         image: alpine:latest\n       - jobname: linux32\ndiff --git a/ci/install-dependencies.sh b/ci/install-dependencies.sh\nindex d061a47293..4eaf3514d6 100755\n--- a/ci/install-dependencies.sh\n+++ b/ci/install-dependencies.sh\n@@ -31,7 +31,7 @@ alpine-*)\n \t;;\n fedora-*|almalinux-*)\n \tdnf -yq update >/dev/null &&\n-\tdnf -yq install shadow-utils sudo make gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel >/dev/null\n+\tdnf -yq install shadow-utils sudo meson ninja pkg-config gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel >/dev/null\n \t;;\n ubuntu-*|i386/ubuntu-*|debian-*)\n \t# Required so that apt doesn't wait for user input on certain packages.\ndiff --git a/ci/run-build-and-tests.sh b/ci/run-build-and-tests.sh\nindex 01823fd0f1..3680446649 100755\n--- a/ci/run-build-and-tests.sh\n+++ b/ci/run-build-and-tests.sh\n@@ -5,12 +5,11 @@\n \n . ${0%/*}/lib.sh\n \n-run_tests=t\n-\n case \"$jobname\" in\n-linux-breaking-changes)\n+fedora-breaking-changes-musl|linux-breaking-changes)\n \texport GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main\n \texport WITH_BREAKING_CHANGES=YesPlease\n+\tMESONFLAGS=\"$MESONFLAGS -Dbreaking_changes=true\"\n \t;;\n linux-TEST-vars)\n \texport OPENSSL_SHA1_UNSAFE=YesPlease\n@@ -36,12 +35,6 @@ linux-sha256)\n linux-reftable|linux-reftable-leaks|osx-reftable)\n \texport GIT_TEST_DEFAULT_REF_FORMAT=reftable\n \t;;\n-pedantic)\n-\t# Don't run the tests; we only care about whether Git can be\n-\t# built.\n-\texport DEVOPTS=pedantic\n-\trun_tests=\n-\t;;\n esac\n \n case \"$jobname\" in\n@@ -54,21 +47,15 @@ case \"$jobname\" in\n \t\t-Dtest_output_directory=\"${TEST_OUTPUT_DIRECTORY:-$(pwd)/t}\" \\\n \t\t$MESONFLAGS\n \tgroup \"Build\" meson compile -C build --\n-\tif test -n \"$run_tests\"\n-\tthen\n-\t\tgroup \"Run tests\" meson test -C build --print-errorlogs --test-args=\"$GIT_TEST_OPTS\" || (\n-\t\t\t./t/aggregate-results.sh \"${TEST_OUTPUT_DIRECTORY:-t}/test-results\"\n-\t\t\thandle_failed_tests\n-\t\t)\n-\tfi\n+\tgroup \"Run tests\" meson test -C build --print-errorlogs --test-args=\"$GIT_TEST_OPTS\" || (\n+\t\t./t/aggregate-results.sh \"${TEST_OUTPUT_DIRECTORY:-t}/test-results\"\n+\t\thandle_failed_tests\n+\t)\n \t;;\n *)\n \tgroup Build make\n-\tif test -n \"$run_tests\"\n-\tthen\n-\t\tgroup \"Run tests\" make test ||\n-\t\thandle_failed_tests\n-\tfi\n+\tgroup \"Run tests\" make test ||\n+\thandle_failed_tests\n \t;;\n esac\n \n\n-- \n2.51.0.417.g1ba7204a04.dirty\n\n"},{"id":"525616","messageId":"20250905-b4-pks-rust-breaking-change-v2-7-6939cbf4a0b8@pks.im","threadId":"64091","inReplyTo":"20250905-b4-pks-rust-breaking-change-v2-0-6939cbf4a0b8@pks.im","subject":"[PATCH RFC v2 7/7] ci: enable Rust for breaking-changes jobs","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-05T11:51:03Z","receivedAt":"2025-09-05T11:51:28Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Enable Rust for our breaking-changes jobs so that we can verify that the\nbuild infrastructure and the converted Rust subsystems work as expected.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n ci/install-dependencies.sh | 4 ++--\n ci/run-build-and-tests.sh  | 2 ++\n 2 files changed, 4 insertions(+), 2 deletions(-)\n\ndiff --git a/ci/install-dependencies.sh b/ci/install-dependencies.sh\nindex 4eaf3514d6..4c58c7238e 100755\n--- a/ci/install-dependencies.sh\n+++ b/ci/install-dependencies.sh\n@@ -31,7 +31,7 @@ alpine-*)\n \t;;\n fedora-*|almalinux-*)\n \tdnf -yq update >/dev/null &&\n-\tdnf -yq install shadow-utils sudo meson ninja pkg-config gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel >/dev/null\n+\tdnf -yq install shadow-utils sudo meson ninja pkg-config gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel rustc >/dev/null\n \t;;\n ubuntu-*|i386/ubuntu-*|debian-*)\n \t# Required so that apt doesn't wait for user input on certain packages.\n@@ -58,7 +58,7 @@ ubuntu-*|i386/ubuntu-*|debian-*)\n \t\tmake libssl-dev libcurl4-openssl-dev libexpat-dev wget sudo default-jre \\\n \t\ttcl tk gettext zlib1g-dev perl-modules liberror-perl libauthen-sasl-perl \\\n \t\tlibemail-valid-perl libio-pty-perl libio-socket-ssl-perl libnet-smtp-ssl-perl libdbd-sqlite3-perl libcgi-pm-perl \\\n-\t\tlibsecret-1-dev libpcre2-dev meson ninja-build pkg-config \\\n+\t\tlibsecret-1-dev libpcre2-dev meson ninja-build pkg-config cargo \\\n \t\t${CC_PACKAGE:-${CC:-gcc}} $PYTHON_PACKAGE\n \n \tcase \"$distro\" in\ndiff --git a/ci/run-build-and-tests.sh b/ci/run-build-and-tests.sh\nindex 3680446649..c718bd101a 100755\n--- a/ci/run-build-and-tests.sh\n+++ b/ci/run-build-and-tests.sh\n@@ -9,7 +9,9 @@ case \"$jobname\" in\n fedora-breaking-changes-musl|linux-breaking-changes)\n \texport GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main\n \texport WITH_BREAKING_CHANGES=YesPlease\n+\texport WITH_RUST=YesPlease\n \tMESONFLAGS=\"$MESONFLAGS -Dbreaking_changes=true\"\n+\tMESONFLAGS=\"$MESONFLAGS -Drust=enabled\"\n \t;;\n linux-TEST-vars)\n \texport OPENSSL_SHA1_UNSAFE=YesPlease\n\n-- \n2.51.0.417.g1ba7204a04.dirty\n\n"},{"id":"525622","messageId":"DB9P250MB0692264976781C194B7D6194A503A@DB9P250MB0692.EURP250.PROD.OUTLOOK.COM","threadId":"64091","inReplyTo":"20250905-b4-pks-rust-breaking-change-v2-5-6939cbf4a0b8@pks.im","subject":"Re: [PATCH RFC v2 5/7] BreakingChanges: announce Rust becoming mandatory","fromName":"Matthias Aßhauer","fromEmail":"mha1993@live.de","sentAt":"2025-09-05T12:45:46Z","receivedAt":"2025-09-05T12:46:00Z","isPatch":true,"sender":{"key":"mha1993@live.de","avatar":"https://avatars.githubusercontent.com/u/6178234?v=4"},"body":"\n\nOn Fri, 5 Sep 2025, Patrick Steinhardt wrote:\n\n> Over the last couple of years the appetite for bringin Rust into the\n> codebase has grown significantly across the developer base. Introducing\n> Rust is a major change though and has ramifications for the whole\n> ecosystem:\n>\n>  - Some platforms haven't yet been able to implement a Rust toolchain,\n>    even though it is possible in theory.\n>\n>  - Some platforms don't have any support for Rust at all.\n\nWhat's the difference between these two kinds of platform? It should be \ntheoretically possible to build rust tooling for all of them, right?\n\n>  - Some platforms may have to figure out how to fit Rust into their\n>    bootstrapping sequence.\n>\n> Due to this, and given that Git is a critical piece of infrastructure\n> for the whole industry, we cannot just introduce such a heavyweight\n> dependency without doing our due diligence.\n>\n> Instead, preceding commits have introduced a test balloon into our build\n> infrastructure that convert one tiny subsystem to use Rust. For now,\n> using Rust to build that subsystem is entirely optional -- if no Rust\n> support is available, we continue to use the C implementation. This test\n> balloon has the intention to give distributions time and let them ease\n> into our adoption of Rust.\n>\n> Having multiple implementations of the same subsystem is not sustainable\n> though, and the plan is to eventually be able to use Rust freely all\n> across our codebase. As such, there is the intent to make Rust become a\n> mandatory part of our build process.\n>\n> Add an announcement to our breaking changes that Rust will become\n> mandatory in Git 3.0. A (very careful and non-binding) estimate might be\n> that this major release might be released in the second half of next\n> year, which should give distributors enough time to prepare for the\n> change.\n>\n> Signed-off-by: Patrick Steinhardt <ps@pks.im>\n> ---\n> Documentation/BreakingChanges.adoc | 36 ++++++++++++++++++++++++++++++++++++\n> 1 file changed, 36 insertions(+)\n>\n> diff --git a/Documentation/BreakingChanges.adoc b/Documentation/BreakingChanges.adoc\n> index f8d2eba061..dbb15b6a57 100644\n> --- a/Documentation/BreakingChanges.adoc\n> +++ b/Documentation/BreakingChanges.adoc\n> @@ -165,6 +165,42 @@ A prerequisite for this change is that the ecosystem is ready to support the\n> \"reftable\" format. Most importantly, alternative implementations of Git like\n> JGit, libgit2 and Gitoxide need to support it.\n>\n> +* Git will require Rust as a mandatory part of the build process. While Git\n> +  already started to adopt Rust in the Git 2.52, all parts written in Rust are\n> +  optional for the time being. This includes:\n> ++\n> +  ** Subsystems that have an alternative implementation in Rust to test\n> +     interoperability between our C and Rust codebase.\n> +  ** Newly written features that are not mission critical for a fully functional\n> +     Git client.\n> ++\n> +These changes are meant as test balloons to allow distributors of Git to prepare\n> +for Rust becoming a mandatory part of the build process. There will be multiple\n> +milestones for the introduction of Rust:\n> ++\n> +1. Initially, with Git 2.52, support for Rust will be auto-detected by Rust and\n\nSupport for Rust will be detected by Rust? Should that say \"by Meson\"?\n\n> +   disabled in our Makefile so that the project can sort out the initial\n> +   infrastructure.\n> +2. In Git 2.53, support for Rust will be made mandatory in case Git is compiled\n> +   with breaking changes. Breaking changes can be enabled for Meson by saying\n> +   `meson configure -Dbreaking_changes=true` and for Makefiles via `make\n> +   WITH_BREAKING_CHANGES=YesPlease`. It will still be possible to compile with\n> +   breaking changes, but explicitly disable Rust.\n\nMandatory, but not mandatory? opt-out?\n\n> +3. In Git 2.54, both build systems will default-enable support for Rust so that\n> +   builds will break if Rust is not available on the build host. The use of Rust\n> +   can still be explicitly disabled via build flags.\n\nI assume you mean that we will default to building with Rust, even when \nbuilding without breaking changes, but I feel like the wording could be \nmore explicit.\n\nAssuming packagers read this when 2.52 is released, 2.54 would give them \nroughly 16-26 ish weeks of a heads up, assuming our typical 8-13 week \ndevelopment cycles.\n\n> +4. In Git 3.0, the build options will be removed and support for Rust is\n> +   mandatory.\n> ++\n> +You can explicitly ask both Meson and our Makefile-based system to enable Rust\n> +by saying `meson configure -Drust=enabled` and `make WITH_RUST=YesPlease`,\n> +respectively.\n> ++\n> +The Git project will declare the last version before Git 3.0 to be a long-term\n> +support release that is maintained until alternate Rust backends like gcc-rs are\n> +able to build Git. The Git project may need to rely on distributions to help\n\nDo we want to commit to promising support until gccrs is ready? What if \ngccrs ends up abandoned? Or takes an unexpectedly long time to reach a \nstage where it can build Git? It might make sense to give this LTS release \na time limit instead, or in addidtion.\n\n> +with identifying and backporting important bugfixes.\n> +\n> === Removals\n>\n> * Support for grafting commits has long been superseded by git-replace(1).\n>\n> -- \n> 2.51.0.417.g1ba7204a04.dirty\n>\n>\n"},{"id":"525628","messageId":"7040d009-2a1f-4962-abcc-80b82b89f1e6@gentoo.org","threadId":"64091","inReplyTo":"aLqWKYkj98QUDxRi@pks.im","subject":"Re: [PATCH RFC 1/3] meson: add infrastructure to build internal Rust library","fromName":"Eli Schwartz","fromEmail":"eschwartz@gentoo.org","sentAt":"2025-09-05T13:20:20Z","receivedAt":"2025-09-05T13:20:25Z","isPatch":true,"sender":{"key":"eschwartz@gentoo.org","avatar":"https://avatars.githubusercontent.com/u/6551424?v=4"},"body":"On 9/5/25 3:50 AM, Patrick Steinhardt wrote:\n> On Thu, Sep 04, 2025 at 09:16:03PM -0400, Eli Schwartz wrote:\n>> Hmm. Patrick -- do you mind documenting why you decided to use this\n>> version guard at all? Off the top of my head I'm not sure why you'd need\n>> this.\n>>\n>> In src/meson.build,\n>>\n>> +libgit_rs = static_library('git_rs',\n>> +  sources: [\n>> +    'lib.rs',\n>> +  ],\n>> +  rust_abi: 'c',\n>> +)\n>>\n>>\n>>\n>> rust_abi is new in meson 1.3.0, but it's just a rename for clarity of\n>> rust_crate_type, available since meson 0.42.0, so please use the\n>> backwards-compatible name...\n> \n> Oh. I think I misunderstood the following sentence [1]:\n> \n>     (Since 1.9.0) Rust supports mixed targets, but only supports using\n>     rustc as the linker for such targets. If you need to use a non-Rust\n>     linker, or support Meson < 1.9.0, see below.\n> \n> I thought that only with Meson 1.9 you could link Rust libraries with C\n> libraries. But I guess this rather means that you can now have a single\n> target that has both '.c' and '.rs' sources?\n> \n> In any way, thanks for the hint, will drop.\n> \n> Patrick\n> \n> [1]: https://mesonbuild.com/Rust.html#mixing-rust-and-nonrust-sources\n\n\nYes -- a single target is something like a libXXXX.so or a libXXXX.a\nfile, and there are significant nuances in how a build system backend\nneeds to run rustc in order to emit the final C interface (or merge into\nan executable). Once it is exported to C, though, it is \"normal\" C code\nand anything may link to it freely, even for much older versions of Meson.\n\nThe previous (<1.9.0) gold standard for Rust / C interop in Meson, was\nthe far more well-trodden path of \"use libraries, not *.o files\" (which\nis also more straightforward in cargo, of course ;)).\n\n\n-- \nEli Schwartz\n"},{"id":"525631","messageId":"aLrnwOGKaAjLj0Bo@pks.im","threadId":"64091","inReplyTo":"DB9P250MB0692264976781C194B7D6194A503A@DB9P250MB0692.EURP250.PROD.OUTLOOK.COM","subject":"Re: [PATCH RFC v2 5/7] BreakingChanges: announce Rust becoming mandatory","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-05T13:38:08Z","receivedAt":"2025-09-05T13:38:17Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Fri, Sep 05, 2025 at 02:45:46PM +0200, Matthias Aßhauer wrote:\n> On Fri, 5 Sep 2025, Patrick Steinhardt wrote:\n> > Over the last couple of years the appetite for bringin Rust into the\n> > codebase has grown significantly across the developer base. Introducing\n> > Rust is a major change though and has ramifications for the whole\n> > ecosystem:\n> > \n> >  - Some platforms haven't yet been able to implement a Rust toolchain,\n> >    even though it is possible in theory.\n> > \n> >  - Some platforms don't have any support for Rust at all.\n> \n> What's the difference between these two kinds of platform? It should be\n> theoretically possible to build rust tooling for all of them, right?\n\nThe first platform is something where Rust just hasn't been wired up\nyet. This involves for Cygwin, or the Darwin ports of Gentoo's portage\ntree. Rust is available for those platforms in theory, but in practice\nit's not there yet.\n\nThe second platform is where there is no Rust compiler available at all.\nSo for example NonStop, Intel Itanium, Alpha.\n\nI'll try to clarify this in the next version.\n\n> > diff --git a/Documentation/BreakingChanges.adoc b/Documentation/BreakingChanges.adoc\n> > index f8d2eba061..dbb15b6a57 100644\n> > --- a/Documentation/BreakingChanges.adoc\n> > +++ b/Documentation/BreakingChanges.adoc\n> > @@ -165,6 +165,42 @@ A prerequisite for this change is that the ecosystem is ready to support the\n> > \"reftable\" format. Most importantly, alternative implementations of Git like\n> > JGit, libgit2 and Gitoxide need to support it.\n> > \n> > +* Git will require Rust as a mandatory part of the build process. While Git\n> > +  already started to adopt Rust in the Git 2.52, all parts written in Rust are\n> > +  optional for the time being. This includes:\n> > ++\n> > +  ** Subsystems that have an alternative implementation in Rust to test\n> > +     interoperability between our C and Rust codebase.\n> > +  ** Newly written features that are not mission critical for a fully functional\n> > +     Git client.\n> > ++\n> > +These changes are meant as test balloons to allow distributors of Git to prepare\n> > +for Rust becoming a mandatory part of the build process. There will be multiple\n> > +milestones for the introduction of Rust:\n> > ++\n> > +1. Initially, with Git 2.52, support for Rust will be auto-detected by Rust and\n> \n> Support for Rust will be detected by Rust? Should that say \"by Meson\"?\n\nAh, yes.\n\n> > +   disabled in our Makefile so that the project can sort out the initial\n> > +   infrastructure.\n> > +2. In Git 2.53, support for Rust will be made mandatory in case Git is compiled\n> > +   with breaking changes. Breaking changes can be enabled for Meson by saying\n> > +   `meson configure -Dbreaking_changes=true` and for Makefiles via `make\n> > +   WITH_BREAKING_CHANGES=YesPlease`. It will still be possible to compile with\n> > +   breaking changes, but explicitly disable Rust.\n> \n> Mandatory, but not mandatory? opt-out?\n\nTrue, this reads a bit awkward.\n\n> > +3. In Git 2.54, both build systems will default-enable support for Rust so that\n> > +   builds will break if Rust is not available on the build host. The use of Rust\n> > +   can still be explicitly disabled via build flags.\n> \n> I assume you mean that we will default to building with Rust, even when\n> building without breaking changes, but I feel like the wording could be more\n> explicit.\n> \n> Assuming packagers read this when 2.52 is released, 2.54 would give them\n> roughly 16-26 ish weeks of a heads up, assuming our typical 8-13 week\n> development cycles.\n\nOk.\n\nDoes this revised version of the plan read better to you?\n\n    1. Initially, with Git 2.52, support for Rust will be auto-detected by Meson and\n       disabled in our Makefile so that the project can sort out the initial\n       infrastructure.\n    2. In Git 2.53, support for Rust will be enabled by default in case Git is\n       compiled with breaking changes. Breaking changes can be enabled for Meson by\n       saying `meson configure -Dbreaking_changes=true` and for Makefile-based\n       builds via `make WITH_BREAKING_CHANGES=YesPlease`. It will still be possible\n       to compile with breaking changes, but explicitly disable Rust.\n    3. In Git 2.54, both build systems will default-enable support for Rust even\n       when breaking changes aren't enabled. Consequently, builds will break by\n       default if Rust is not available on the build host. The use of Rust can still\n       be explicitly disabled via build flags.\n    4. In Git 3.0, the build options will be removed and support for Rust is\n       mandatory.\n\n> > +4. In Git 3.0, the build options will be removed and support for Rust is\n> > +   mandatory.\n> > ++\n> > +You can explicitly ask both Meson and our Makefile-based system to enable Rust\n> > +by saying `meson configure -Drust=enabled` and `make WITH_RUST=YesPlease`,\n> > +respectively.\n> > ++\n> > +The Git project will declare the last version before Git 3.0 to be a long-term\n> > +support release that is maintained until alternate Rust backends like gcc-rs are\n> > +able to build Git. The Git project may need to rely on distributions to help\n> \n> Do we want to commit to promising support until gccrs is ready? What if\n> gccrs ends up abandoned? Or takes an unexpectedly long time to reach a stage\n> where it can build Git? It might make sense to give this LTS release a time\n> limit instead, or in addidtion.\n\nYeah, I wasn't quite clear on that one, either. An alternative:\n\n  - We will maintain the LTS release for 8 release cycles, which equates\n    to roughly two years. It sounds like a lot, but recent security\n    releases have stretched quite far into the past.\n\n  - If there are still dependents after these two years we will hand\n    over maintainership of the LTS branch to dependents. So they will be\n    responsible for the backporting.\n\nThis really only is a suggestion though. I'm especially waiting for\nJunio's feedback here to see whether he thinks that this is a reasonable\nthing to do.\n\nPatrick\n"},{"id":"525632","messageId":"033d35f5-6158-4402-b7f4-aaf525a3e64d@gentoo.org","threadId":"64091","inReplyTo":"aLqXHYb2jZpCKzp7@pks.im","subject":"Re: [PATCH RFC 2/3] rust: implement a test balloon via the \"varint\" subsystem","fromName":"Eli Schwartz","fromEmail":"eschwartz@gentoo.org","sentAt":"2025-09-05T13:39:04Z","receivedAt":"2025-09-05T13:39:10Z","isPatch":true,"sender":{"key":"eschwartz@gentoo.org","avatar":"https://avatars.githubusercontent.com/u/6551424?v=4"},"body":"On 9/5/25 3:54 AM, Patrick Steinhardt wrote:\n> On Thu, Sep 04, 2025 at 10:00:45PM -0400, Eli Schwartz wrote:\n\n>> If the rust code is defined as a crate, meson can auto-import that crate\n>> via parsing Cargo.toml, so perhaps this can simply be done by creating a\n>>\n>> [lib]\n>> crate-type = 'cdylib'\n>>\n>> and... importing it as a meson subproject. You'd be able to build it\n>> with cargo build, if you really want to (and the Makefile may have to)\n>> but Meson would not be limited to this.\n> \n> That sounds like a sensible thing to do. Just to clarify, this doesn't\n> need the experimental Cargo wraps, right? Is there any documentation for\n> how to set this up?\n\n\nExperimental cargo wraps are new since 1.3.0\n\nhttps://mesonbuild.com/Release-notes-for-1-3-0.html#automatic-fallback-to-cmake-and-cargo-subproject\nhttps://mesonbuild.com/Wrap-dependency-system-manual.html#cargo-wraps\n\nIt operates by synthesizing a virtual `meson.build` file for you via\ntranslation of ordinary Cargo.toml. A copy of the synthesized file is\nwritten out to ${build_dir}/subprojects/foobar-1-rs/ (or whatever the\nsubproject is named), so you can actually see what a manually written\nmeson.build would look like.\n\nAnd e.g. tweak it a bit. (Since it's a virtual file, it always writes\n`meson_version : '>= currentver'` to avoid ever triggering \"feature new\"\nwarnings, and also stubs out `rust_dependency_map : {}`, but you can\ndelete both.)\n\n\n-- \nEli Schwartz\n"},{"id":"525636","messageId":"8a5394eb-bad4-42e0-82a8-fa73123e205a@gmail.com","threadId":"64091","inReplyTo":"20250905-b4-pks-rust-breaking-change-v2-0-6939cbf4a0b8@pks.im","subject":"Re: [PATCH RFC v2 0/7] Introduce Rust and announce that it will become mandatorty","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2025-09-05T14:14:25Z","receivedAt":"2025-09-05T14:14:28Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Patrick\n\nOn 05/09/2025 12:50, Patrick Steinhardt wrote:\n> Hi,\n> \n> this small patch series introduces Rust into the core of Git. This patch\n> series is designed as a test balloon, similar to how we introduced test\n> balloons for C99 features in the past. The goal is threefold:\n> \n>    - Give us some time to experiment with Rust and introduce proper build\n>      infrastructure.\n> \n>    - Give distributors time to ease into the new toolchain requirements.\n>      Introducing Rust is impossible for some platforms and hard for\n>      others.\n\nThese sound good\n\n>    - Announce that Git 3.0 will make Rust a mandatory part of our build\n>      infrastructure.\n\nI'm not sure if we really want to wait that long. So far Git 3.0 has \nbeen about user facing changes rather than build requirements. In [1] I \nsuggested a period of six months from the initial announcement to making \nrust mandatory to allow distributors time to either adjust their build \nprocedures or notify their users that they will only be offering \nsecurity updates in the future.\n> The test balloon itself is quite uninteresting: I've chosen to convert\n> the \"varint.c\" subsystem, mostly because it is trivial and does not have\n> any dependencies. But it does allow us to verify that C to Rust interop\n> works as expected, and to play around with tooling. All tests pass with\n> the \"varint.rs\" implementation.\n> \n> For now, the series only contains support for Meson. If we agree to go\n> down this route I'll also introduce support for Rust into our Makefiles\n> at a later point in time.\n\nIt looks like this version does include the necessary Makefile changes \nwhich is great. I do think though, that for the test balloon to be \nvaluable, we need make building with rust the default with an error \nmessage that tells people how to build without rust if that fails. \nOtherwise it is easy for people building on platforms without rust \nsupport to miss that we're going to be making it mandatory soon.\n\nThanks\n\nPhillip\n\n[1] \nhttps://lore.kernel.org/git/ba386547-10e0-45e2-95ad-c47e84919abf@gmail.com\n\n> Furthermore missing is additional tooling:\n> \n>    - At least one CI job to verify that Rust builds and works as\n>      expected.\n> \n>    - Tooling and CI jobs to ensure that we have consistent formatting via\n>      `cargo format`.\n> \n> And probably lots more. As said, the entire goal is for us to have an\n> easy playground that we can experiment on and develop the infrastructure\n> incrementally without yet having to commit to anything.\n> \n> I'm mostly splitting out the topic of introducing Rust from the larger\n> series that introduce it into xdiff so that we can focus more on the\n> actual process of introducing Rust into Git and less on the potential\n> features that we want to build on top of it.\n> \n> Changes in v2:\n>    - Introduce support for building the Rust library via our Makefile.\n>    - Introduce a '-DWITH_RUST' define. This define is used to print\n>      whether or not Git is built with Rust via `git version\n>      --build-options`.\n>    - Adjust Meson to not depend on v1.9.0 and newer anymore.\n>    - Introduce a roadmap into our BreakingChanges document to explain how\n>      we'll iterate towards mandatory Rust support.\n>    - Rework the Fedora job to do a full compile-and-test run with Meson\n>      and breaking changes enabled.\n>    - Adapt our breaking-changes jobs to enable Rust support.\n>    - Link to v1: https://lore.kernel.org/r/20250904-b4-pks-rust-breaking-change-v1-0-3af1d25e0be9@pks.im\n> \n> Thanks!\n> \n> Patrick\n> \n> ---\n> Patrick Steinhardt (7):\n>        meson: add infrastructure to build internal Rust library\n>        Makefile: introduce infrastructure to build internal Rust library\n>        help: report on whether or not Rust is enabled\n>        rust: implement a test balloon via the \"varint\" subsystem\n>        BreakingChanges: announce Rust becoming mandatory\n>        ci: convert \"pedantic\" job into full build with breaking changes\n>        ci: enable Rust for breaking-changes jobs\n> \n>   .github/workflows/main.yml         |  4 +-\n>   .gitignore                         |  2 +\n>   .gitlab-ci.yml                     |  4 +-\n>   Cargo.toml                         |  9 ++++\n>   Documentation/BreakingChanges.adoc | 36 +++++++++++++++\n>   Makefile                           | 47 ++++++++++++++++++-\n>   ci/install-dependencies.sh         |  4 +-\n>   ci/run-build-and-tests.sh          | 31 +++++--------\n>   help.c                             |  6 +++\n>   meson.build                        | 17 ++++++-\n>   meson_options.txt                  |  2 +\n>   src/lib.rs                         |  1 +\n>   src/meson.build                    | 16 +++++++\n>   src/varint.rs                      | 92 ++++++++++++++++++++++++++++++++++++++\n>   14 files changed, 240 insertions(+), 31 deletions(-)\n> \n> Range-diff versus v1:\n> \n> 1:  4df400823c ! 1:  8f6e89bc7d meson: add infrastructure to build internal Rust library\n>      @@ meson.build: version_def_h = custom_target(\n>        \n>       +libgit_libraries = [ ]\n>       +\n>      -+if meson.version().version_compare('>=1.9.0')\n>      -+  rust_available = add_languages('rust', native: false, required: get_option('rust'))\n>      -+else\n>      -+  rust_available = false\n>      -+endif\n>      ++rust_available = add_languages('rust', native: false, required: get_option('rust'))\n>       +rust_option = get_option('rust').disable_auto_if(not rust_available)\n>      -+\n>      -+if rust_option.allowed() and meson.version().version_compare('>=1.9.0')\n>      ++if rust_option.allowed()\n>       +  subdir('src')\n>      ++  libgit_c_args += '-DWITH_RUST'\n>       +endif\n>       +\n>        libgit = declare_dependency(\n>      @@ src/lib.rs (new)\n>       \n>        ## src/meson.build (new) ##\n>       @@\n>      -+rustmod = import('rust')\n>      -+\n>       +libgit_rs = static_library('git_rs',\n>       +  sources: [\n>       +    'lib.rs',\n>       +  ],\n>      -+  rust_abi: 'c',\n>      ++  rust_crate_type: 'staticlib',\n>       +)\n>      -+\n>      -+rustmod.test('git-rs', libgit_rs)\n>      -+\n>       +libgit_libraries += libgit_rs\n>      ++\n>      ++# The 'rust' module was only introduced in Meson 1.0. Furthermore, the module\n>      ++# does not seem to work on macOS as expected right now. As such, we only\n>      ++# conditionally enable tests.\n>      ++if meson.version().version_compare('>=1.0.0') and host_machine.system() != 'darwin'\n>      ++  rustmod = import('rust')\n>      ++  rustmod.test('rust', libgit_rs)\n>      ++endif\n> -:  ---------- > 2:  cd1d642d04 Makefile: introduce infrastructure to build internal Rust library\n> -:  ---------- > 3:  e60a8353a4 help: report on whether or not Rust is enabled\n> 2:  575f6de44d ! 4:  b27811aea4 rust: implement a test balloon via the \"varint\" subsystem\n>      @@ Commit message\n>       \n>           Signed-off-by: Patrick Steinhardt <ps@pks.im>\n>       \n>      + ## Makefile ##\n>      +@@ Makefile: LIB_OBJS += urlmatch.o\n>      + LIB_OBJS += usage.o\n>      + LIB_OBJS += userdiff.o\n>      + LIB_OBJS += utf8.o\n>      ++ifndef WITH_RUST\n>      + LIB_OBJS += varint.o\n>      ++endif\n>      + LIB_OBJS += version.o\n>      + LIB_OBJS += versioncmp.o\n>      + LIB_OBJS += walker.o\n>      +\n>        ## meson.build ##\n>       @@ meson.build: libgit_sources = [\n>          'usage.c',\n>      @@ meson.build: libgit_sources = [\n>          'versioncmp.c',\n>          'walker.c',\n>       @@ meson.build: rust_option = get_option('rust').disable_auto_if(not rust_available)\n>      -\n>      - if rust_option.allowed() and meson.version().version_compare('>=1.9.0')\n>      + if rust_option.allowed()\n>          subdir('src')\n>      +   libgit_c_args += '-DWITH_RUST'\n>       +else\n>       +  libgit_sources += [\n>       +    'varint.c',\n>      @@ src/lib.rs\n>       +pub mod varint;\n>       \n>        ## src/meson.build ##\n>      -@@ src/meson.build: rustmod = import('rust')\n>      +@@\n>        libgit_rs = static_library('git_rs',\n>          sources: [\n>            'lib.rs',\n>       +    'varint.rs',\n>          ],\n>      -   rust_abi: 'c',\n>      +   rust_crate_type: 'staticlib',\n>        )\n>       \n>        ## src/varint.rs (new) ##\n> 3:  e54393392a < -:  ---------- BreakingChanges: announce Rust becoming mandatory\n> -:  ---------- > 5:  d5946e0114 BreakingChanges: announce Rust becoming mandatory\n> -:  ---------- > 6:  0d367976de ci: convert \"pedantic\" job into full build with breaking changes\n> -:  ---------- > 7:  82086a5328 ci: enable Rust for breaking-changes jobs\n> \n> ---\n> base-commit: 2462961280690837670d997bde64bd4ebf8ae66d\n> change-id: 20250904-b4-pks-rust-breaking-change-7167d9d3e37d\n> \n> \n\n"},{"id":"525638","messageId":"c9397330-0cc5-488a-9027-c0e869bb4b5d@gmail.com","threadId":"64091","inReplyTo":"DB9P250MB0692264976781C194B7D6194A503A@DB9P250MB0692.EURP250.PROD.OUTLOOK.COM","subject":"Re: [PATCH RFC v2 5/7] BreakingChanges: announce Rust becoming mandatory","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2025-09-05T14:22:42Z","receivedAt":"2025-09-05T14:22:46Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"On 05/09/2025 13:45, Matthias Aßhauer wrote:\n> On Fri, 5 Sep 2025, Patrick Steinhardt wrote:\n> \n>> ++\n>> +The Git project will declare the last version before Git 3.0 to be a \n>> long-term\n>> +support release that is maintained until alternate Rust backends like \n>> gcc-rs are\n>> +able to build Git. The Git project may need to rely on distributions \n>> to help\n> \n> Do we want to commit to promising support until gccrs is ready? What if \n> gccrs ends up abandoned? Or takes an unexpectedly long time to reach a \n> stage where it can build Git? It might make sense to give this LTS \n> release a time limit instead, or in addidtion.\n\nYes, this feels way too open ended. I think we need to be realistic \nabout how long we can offer security updates for an LTS version. A lot \nof the security updates are written by developers at companies that have \nvery little or no commercial interest in platforms that don't support \nrust. While those companies do have an interest in helping to keep the \nwider ecosystem secure it is hard to see them funding security work on \nniche systems indefinitely. Giving platforms without a rust compiler two \nor three years to either port rust or prepare to take on the work of \nsecurity updates for their platform themselves seems like a more \nrealistic balance to me.\n\nThanks\n\nPhillip\n\n"},{"id":"525639","messageId":"aLrzqR2Z9jz5CuJu@pks.im","threadId":"64091","inReplyTo":"8a5394eb-bad4-42e0-82a8-fa73123e205a@gmail.com","subject":"Re: [PATCH RFC v2 0/7] Introduce Rust and announce that it will become mandatorty","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-05T14:28:57Z","receivedAt":"2025-09-05T14:29:05Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Fri, Sep 05, 2025 at 03:14:25PM +0100, Phillip Wood wrote:\n> On 05/09/2025 12:50, Patrick Steinhardt wrote:\n> > this small patch series introduces Rust into the core of Git. This patch\n> > series is designed as a test balloon, similar to how we introduced test\n> > balloons for C99 features in the past. The goal is threefold:\n> > \n> >    - Give us some time to experiment with Rust and introduce proper build\n> >      infrastructure.\n> > \n> >    - Give distributors time to ease into the new toolchain requirements.\n> >      Introducing Rust is impossible for some platforms and hard for\n> >      others.\n> \n> These sound good\n> \n> >    - Announce that Git 3.0 will make Rust a mandatory part of our build\n> >      infrastructure.\n> \n> I'm not sure if we really want to wait that long. So far Git 3.0 has been\n> about user facing changes rather than build requirements. In [1] I suggested\n> a period of six months from the initial announcement to making rust\n> mandatory to allow distributors time to either adjust their build procedures\n> or notify their users that they will only be offering security updates in\n> the future.\n\nMore on that below.\n\n> > The test balloon itself is quite uninteresting: I've chosen to convert\n> > the \"varint.c\" subsystem, mostly because it is trivial and does not have\n> > any dependencies. But it does allow us to verify that C to Rust interop\n> > works as expected, and to play around with tooling. All tests pass with\n> > the \"varint.rs\" implementation.\n> > \n> > For now, the series only contains support for Meson. If we agree to go\n> > down this route I'll also introduce support for Rust into our Makefiles\n> > at a later point in time.\n> \n> It looks like this version does include the necessary Makefile changes which\n> is great. I do think though, that for the test balloon to be valuable, we\n> need make building with rust the default with an error message that tells\n> people how to build without rust if that fails. Otherwise it is easy for\n> people building on platforms without rust support to miss that we're going\n> to be making it mandatory soon.\n\nI have a plan layed out in the BreakingChanges document that mentions\nhow I'm proposing to do the transition:\n\n  1. We introduce it with auto-detection for Meson and default-disabled\n     for our Makefile in Git 2.52.\n\n  2. We enable Rust by default in case WITH_BREAKING_CHANGES is enabled\n     in Git 2.53.\n\n  3. We always enable Rust by default in Git 2.54.\n\n  4. We unconditionally enable Rust in Git 3.0.\n\nThis is basically gradually tightening the screws, which both gives us\ntime to build the infra and gives downstream time to become aware of the\nchange and adapt.\n\nI think making it mandatory in Git 3.0 makes sense because I also\npropose to make the last version without mandatory Rust be an LTS\nversion. And if we connect that with it being the last version before\n3.0 I think that's an additional benefit, as there will be other\nbreaking changes in 3.0.\n\nIn the end it kind of hinges on when we think we want to release Git\n3.0. If we can agree on the above plan, we could also think about making\nGit 2.55 become 3.0 instead. That'd be in a bit less than a year from\nnow, which I think is a good timeframe for that breaking release. I\npersonally don't see a reason to push it out into the future for way\nlonger than that, and it would be good anyway if we built some consensus\naround its release date.\n\nPatrick\n"},{"id":"525641","messageId":"11394b17-905a-4888-981c-c5b4a7f8cd62@gentoo.org","threadId":"64091","inReplyTo":"DB9P250MB0692264976781C194B7D6194A503A@DB9P250MB0692.EURP250.PROD.OUTLOOK.COM","subject":"Re: [PATCH RFC v2 5/7] BreakingChanges: announce Rust becoming mandatory","fromName":"Eli Schwartz","fromEmail":"eschwartz@gentoo.org","sentAt":"2025-09-05T14:32:49Z","receivedAt":"2025-09-05T14:32:56Z","isPatch":true,"sender":{"key":"eschwartz@gentoo.org","avatar":"https://avatars.githubusercontent.com/u/6551424?v=4"},"body":"On 9/5/25 8:45 AM, Matthias Aßhauer wrote:\n> \n> \n> On Fri, 5 Sep 2025, Patrick Steinhardt wrote:\n> \n>> Over the last couple of years the appetite for bringin Rust into the\n>> codebase has grown significantly across the developer base. Introducing\n>> Rust is a major change though and has ramifications for the whole\n>> ecosystem:\n>>\n>>  - Some platforms haven't yet been able to implement a Rust toolchain,\n>>    even though it is possible in theory.\n>>\n>>  - Some platforms don't have any support for Rust at all.\n> \n> What's the difference between these two kinds of platform? It should be\n> theoretically possible to build rust tooling for all of them, right?\n\n\nLLVM is theoretically an open source project. So is Rust. We can ask\npeople on those platforms how successful they have been at the political\nside of convincing the Rust project to allowlist the platforms inside\nlow-level case statements of platform-specific defines, in order to\nattempt the first round of \"try running make, see what breaks and start\nfixing it\".\n\nHint: it did not go well, in the sense that the rust maintainers even\naccepted the validity of making a proposal in the first place.\n\nLLVM is easier to work with, at least in that sense. But not all\nplatforms are supported by LLVM either, and you do need a stable release\nof LLVM to support the platform before you can begin work on rust at all.\n\nThat is the advantage of GCC-rs -- it has much broader platform support,\nso if the rust frontend works at all, it will likely also work on the\nspecific platform you care about (and the GCC developers usually don't\nbite, even if you want to enable experimental support for new platforms).\n\n\n\n>> +The Git project will declare the last version before Git 3.0 to be a\n>> long-term\n>> +support release that is maintained until alternate Rust backends like\n>> gcc-rs are\n>> +able to build Git. The Git project may need to rely on distributions\n>> to help\n> \n> Do we want to commit to promising support until gccrs is ready? What if\n> gccrs ends up abandoned? Or takes an unexpectedly long time to reach a\n> stage where it can build Git? It might make sense to give this LTS\n> release a time limit instead, or in addidtion.\n\n\nWell, that will one way or another mean users of such platforms cannot\nuse git at all, not even old versions, lest they be hacked. Bit of a\nproblem for an application that mainly exists for the purpose of\ncommunicating over the network. I suppose such platforms can finally\nleave the world of DVCSes, given:\n\n- jj, breezy, and mercurial all use rust already\n- bitkeeper and monotone are dead\n- darcs is written in GHC (haskell) which is far less available than\n  rust\n\nMaybe it will be the great subversion renaissance.\n\n...\n\nAt any rate I do not expect GCC-rs to be abandoned, huge effort has been\nput into it, many people are interested, they have funding to work on\nit, and projects such as the Linux kernel want to see it exist because\nthey depend on GCC for their C code, want to have Rust code, and the\nkernel security mitigations depend in part on being able to use the same\nbytecode format for all code, to enable LTO and CFI visibility across\nlanguages.\n\nIt is quite *unreasonable* to assume that interest will fade. No more\nthan to assume that *Git*s interest in Rust will fade. The chances of it\nbeing *abandoned* without https://github.com/rust-lang/rust itself\nsupporting at least all interesting Linux Kernel architectures including\nuse of GCC as an alternative codegen backend, are... very low, in my\nopinion.\n\nObviously, lacking the ability to prophesize the future, no one can know\nif it will \"takes an unexpectedly long time\". Although again,\nsignificant interest and all that. Not sure that would be my biggest\nworry. They seem to be making reasonably effective use of their time\nprojections so far, though I will be happy to take correction if someone\nknows something I've missed...\n\n\n-- \nEli Schwartz\n"},{"id":"525642","messageId":"9fcda14f-d4d4-4db4-ae77-d9408bfae035@gentoo.org","threadId":"64091","inReplyTo":"aLrnwOGKaAjLj0Bo@pks.im","subject":"Re: [PATCH RFC v2 5/7] BreakingChanges: announce Rust becoming mandatory","fromName":"Eli Schwartz","fromEmail":"eschwartz@gentoo.org","sentAt":"2025-09-05T14:38:16Z","receivedAt":"2025-09-05T14:38:19Z","isPatch":true,"sender":{"key":"eschwartz@gentoo.org","avatar":"https://avatars.githubusercontent.com/u/6551424?v=4"},"body":"On 9/5/25 9:38 AM, Patrick Steinhardt wrote:\n\n>> Do we want to commit to promising support until gccrs is ready? What if\n>> gccrs ends up abandoned? Or takes an unexpectedly long time to reach a stage\n>> where it can build Git? It might make sense to give this LTS release a time\n>> limit instead, or in addidtion.\n> \n> Yeah, I wasn't quite clear on that one, either. An alternative:\n> \n>   - We will maintain the LTS release for 8 release cycles, which equates\n>     to roughly two years. It sounds like a lot, but recent security\n>     releases have stretched quite far into the past.\n> \n>   - If there are still dependents after these two years we will hand\n>     over maintainership of the LTS branch to dependents. So they will be\n>     responsible for the backporting.\n> \n> This really only is a suggestion though. I'm especially waiting for\n> Junio's feedback here to see whether he thinks that this is a reasonable\n> thing to do.\n\n\nThis seems reasonable to me -- people who still need that LTS should be\nallowed to ensure it still works, and be expected to commit to the bit\n-- but with the emphasis that I would consider it absolutely mandatory\nthat the git project accepts to host that branch, and it won't just\nexist in some other shadowy corner of the internet.\n\n\n-- \nEli Schwartz\n"},{"id":"525652","messageId":"l3apalzo6m5kydmfn6c376rswnfw5h34xpxauqarvxmlaksf6i@dhhdbat6gso3","threadId":"64091","inReplyTo":"20250905-b4-pks-rust-breaking-change-v2-1-6939cbf4a0b8@pks.im","subject":"Re: [PATCH RFC v2 1/7] meson: add infrastructure to build internal Rust library","fromName":"Justin Tobler","fromEmail":"jltobler@gmail.com","sentAt":"2025-09-05T17:47:20Z","receivedAt":"2025-09-05T17:47:22Z","isPatch":true,"sender":{"key":"jltobler@gmail.com","avatar":"https://avatars.githubusercontent.com/u/53454972?v=4"},"body":"On 25/09/05 01:50PM, Patrick Steinhardt wrote:\n> +# The 'rust' module was only introduced in Meson 1.0. Furthermore, the module\n> +# does not seem to work on macOS as expected right now. As such, we only\n> +# conditionally enable tests.\n> +if meson.version().version_compare('>=1.0.0') and host_machine.system() != 'darwin'\n> +  rustmod = import('rust')\n> +  rustmod.test('rust', libgit_rs)\n> +endif\n\nOut of curiousity, what is the problem that we are seeing with macOS? I\nremoved the darwin guard statement and didn't notice any problems when\nrunning `meson test rust`. Is this a well known problem with the Rust\nmodule?\n\n-Justin\n"},{"id":"525668","messageId":"aLs7SwT-Gd6hXuvH@fruit.crustytoothpaste.net","threadId":"64091","inReplyTo":"11394b17-905a-4888-981c-c5b4a7f8cd62@gentoo.org","subject":"Re: [PATCH RFC v2 5/7] BreakingChanges: announce Rust becoming mandatory","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2025-09-05T19:34:35Z","receivedAt":"2025-09-05T19:34:37Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On 2025-09-05 at 14:32:49, Eli Schwartz wrote:\n> LLVM is theoretically an open source project. So is Rust. We can ask\n> people on those platforms how successful they have been at the political\n> side of convincing the Rust project to allowlist the platforms inside\n> low-level case statements of platform-specific defines, in order to\n> attempt the first round of \"try running make, see what breaks and start\n> fixing it\".\n> \n> Hint: it did not go well, in the sense that the rust maintainers even\n> accepted the validity of making a proposal in the first place.\n> \n> LLVM is easier to work with, at least in that sense. But not all\n> platforms are supported by LLVM either, and you do need a stable release\n> of LLVM to support the platform before you can begin work on rust at all.\n\nIt is possible to build with a custom LLVM because all of the\ndistributions do it, so it is possible to build the work out of tree and\nthen add it when everything is ready.  I mentioned elsewhere in the\ndiscussions that LLVM upstream said that work on IA-64 could continue\nout of tree and then it could be re-added if there was sufficient\nmaintenance and support, so this is at least in theory a viable option.\n\nIf LLVM and Rust upstreams are just completely unreasonable and won't\naccept certain platforms at all (which I doubt), then distros can carry\npatches.  It's not pretty and it's a bunch of hassle, but it's common.\n\nI'll also say that LLVM is a pretty useful piece of software that most\ndistros will want to have.  It provides clangd, which is one of the the\nmajor C and C++ LSPs; it's used by Doxygen, which is a major\ndocumentation generator; and it's used by Mesa and PostgreSQL, which are\npieces of software people will want to use.  And, as well, it provides a\ncomplete compiler toolchain.  So I think there are compelling reasons\nwhy porting LLVM is valuable functionality to have anyway, in addition\nto the fact that it also gets you most of the way towards Rust (and a\nvariety of other, less common languages).\n\n> That is the advantage of GCC-rs -- it has much broader platform support,\n> so if the rust frontend works at all, it will likely also work on the\n> specific platform you care about (and the GCC developers usually don't\n> bite, even if you want to enable experimental support for new platforms).\n\nI agree gccrs is a great project and of course I want it to succeed.\nClearly having multiple independent implementations makes it easier to\nfind bugs and increases portability.  And if it means that we get better\nplatform support, fantastic.\n\nHowever, if your complaint is that Rust upstream will not allow\nplatform-specific defines and other incremental work without support in\nLLVM or other core toolchain components, then I don't see how gccrs is\ngoing to convince them otherwise.  I also pointed out elsewhere that the\ncompiler is but one part of the equation and that libstd and libcore,\nwhich are shared between the implementations, plus their dependencies,\nare absolutely required for Rust to work on any platform.  If Rust\nupstream doesn't allow support for the standard libraries, then distros\nwill have to carry patches, gccrs or not.\n\nTo be clear, I do support this kind of incremental work since it's a\nvaluable way to do large projects (and it's what I did for SHA-256 in\nGit and am doing for SHA-1/SHA-256 interop), but saying, \"brian and\nother Git contributors say this is a good idea\" may not be more\nconvincing.  To the extent I can encourage this kind of thing, I am\nhappy to do so, though.\n\n> > Do we want to commit to promising support until gccrs is ready? What if\n> > gccrs ends up abandoned? Or takes an unexpectedly long time to reach a\n> > stage where it can build Git? It might make sense to give this LTS\n> > release a time limit instead, or in addidtion.\n\nI think a two-year limit is reasonable.  As anyone who speaks Spanish\nwill tell you, there's a degree of uncertainty when speculating about\nthe future, so we cannot guarantee that gccrs, however promising it\nmight currently appear, will be usable or viable in that time.  We\ncannot agree to backport patches forever if gccrs doesn't materialize,\nso a time limit seems like a good idea.\n\n_However_, I will state that I am interested in seeing if we can get\nmrustc to build Git's Rust code.  I understand that it is not intended\nto do that (it's intended primarily to bootstrap Rust) and it definitely\nwill require some patches to get working, but I think it's at least a\npossibility and it seems like a much lower effort way to solve the\nproblem.  It will probably involve some inconvenience on our part\nbecause it's very limited in its toolchain and fake cargo, but I would\nbe willing to deal with said inconvenience for the purposes of\nportability.  And it works now and is (for its limited purpose) actively\nmaintained.\n\n> Well, that will one way or another mean users of such platforms cannot\n> use git at all, not even old versions, lest they be hacked. Bit of a\n> problem for an application that mainly exists for the purpose of\n> communicating over the network. I suppose such platforms can finally\n> leave the world of DVCSes, given:\n> \n> - jj, breezy, and mercurial all use rust already\n> - bitkeeper and monotone are dead\n> - darcs is written in GHC (haskell) which is far less available than\n>   rust\n\nThere are other Git-compatible options.  There's Game of Trees, which\nuses Git repositories and is being designed by OpenBSD.  It isn't\ndrop-in compatible, since it's designed to meet the OpenBSD team's\nneeds, but it appears to be basically functional (and is shipped in\nDebian, no less).\n\nThere's also libgit2 and Dulwich, which also implement Git repositories.\n\nSo there are options for people who want to use Git on platforms that\ndon't support Rust.  I suspect that the lack of Git on certain platforms\nwill actually be more of a problem for those platforms than for Git,\nthough.\n-- \nbrian m. carlson (they/them)\nToronto, Ontario, CA\n"},{"id":"525671","messageId":"aLs_QZ9eBGevcGfb@fruit.crustytoothpaste.net","threadId":"64091","inReplyTo":"20250905-b4-pks-rust-breaking-change-v2-3-6939cbf4a0b8@pks.im","subject":"Re: [PATCH RFC v2 3/7] help: report on whether or not Rust is enabled","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2025-09-05T19:51:29Z","receivedAt":"2025-09-05T19:51:31Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On 2025-09-05 at 11:50:59, Patrick Steinhardt wrote:\n> diff --git a/help.c b/help.c\n> index bb20498cfd..5854dd4a7e 100644\n> --- a/help.c\n> +++ b/help.c\n> @@ -791,6 +791,12 @@ void get_version_info(struct strbuf *buf, int show_build_options)\n>  \t\tstrbuf_addf(buf, \"shell-path: %s\\n\", SHELL_PATH);\n>  \t\t/* NEEDSWORK: also save and output GIT-BUILD_OPTIONS? */\n>  \n> +#if defined WITH_RUST\n> +\t\tstrbuf_addstr(buf, \"rust: enabled\\n\");\n> +#else\n> +\t\tstrbuf_addstr(buf, \"rust: disabled\\n\");\n> +#endif\n> +\n\nI think this is a great idea and likely to be super helpful.  Thanks for\nincluding it.\n-- \nbrian m. carlson (they/them)\nToronto, Ontario, CA\n"},{"id":"525672","messageId":"aLtAXYUQ1GRRL6xg@fruit.crustytoothpaste.net","threadId":"64091","inReplyTo":"20250905-b4-pks-rust-breaking-change-v2-7-6939cbf4a0b8@pks.im","subject":"Re: [PATCH RFC v2 7/7] ci: enable Rust for breaking-changes jobs","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2025-09-05T19:56:13Z","receivedAt":"2025-09-05T19:56:15Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On 2025-09-05 at 11:51:03, Patrick Steinhardt wrote:\n> diff --git a/ci/install-dependencies.sh b/ci/install-dependencies.sh\n> index 4eaf3514d6..4c58c7238e 100755\n> --- a/ci/install-dependencies.sh\n> +++ b/ci/install-dependencies.sh\n> @@ -31,7 +31,7 @@ alpine-*)\n>  \t;;\n>  fedora-*|almalinux-*)\n>  \tdnf -yq update >/dev/null &&\n> -\tdnf -yq install shadow-utils sudo meson ninja pkg-config gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel >/dev/null\n> +\tdnf -yq install shadow-utils sudo meson ninja pkg-config gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel rustc >/dev/null\n\nI know nothing about how Fedora packages Rust.  Do we need a cargo\npackage here as well, is that automatically included, or is it\nunnecessary?\n\n>  ubuntu-*|i386/ubuntu-*|debian-*)\n>  \t# Required so that apt doesn't wait for user input on certain packages.\n> @@ -58,7 +58,7 @@ ubuntu-*|i386/ubuntu-*|debian-*)\n>  \t\tmake libssl-dev libcurl4-openssl-dev libexpat-dev wget sudo default-jre \\\n>  \t\ttcl tk gettext zlib1g-dev perl-modules liberror-perl libauthen-sasl-perl \\\n>  \t\tlibemail-valid-perl libio-pty-perl libio-socket-ssl-perl libnet-smtp-ssl-perl libdbd-sqlite3-perl libcgi-pm-perl \\\n> -\t\tlibsecret-1-dev libpcre2-dev meson ninja-build pkg-config \\\n> +\t\tlibsecret-1-dev libpcre2-dev meson ninja-build pkg-config cargo \\\n>  \t\t${CC_PACKAGE:-${CC:-gcc}} $PYTHON_PACKAGE\n\nSeems reasonable.  That will definitely pull in rustc as well.\n\n>  \tcase \"$distro\" in\n> diff --git a/ci/run-build-and-tests.sh b/ci/run-build-and-tests.sh\n> index 3680446649..c718bd101a 100755\n> --- a/ci/run-build-and-tests.sh\n> +++ b/ci/run-build-and-tests.sh\n> @@ -9,7 +9,9 @@ case \"$jobname\" in\n>  fedora-breaking-changes-musl|linux-breaking-changes)\n>  \texport GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main\n>  \texport WITH_BREAKING_CHANGES=YesPlease\n> +\texport WITH_RUST=YesPlease\n>  \tMESONFLAGS=\"$MESONFLAGS -Dbreaking_changes=true\"\n> +\tMESONFLAGS=\"$MESONFLAGS -Drust=enabled\"\n\nLooks good.\n-- \nbrian m. carlson (they/them)\nToronto, Ontario, CA\n"},{"id":"525674","messageId":"aLtGYlTXktuzxD0q@fruit.crustytoothpaste.net","threadId":"64091","inReplyTo":"20250905-b4-pks-rust-breaking-change-v2-2-6939cbf4a0b8@pks.im","subject":"Re: [PATCH RFC v2 2/7] Makefile: introduce infrastructure to build internal Rust library","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2025-09-05T20:21:54Z","receivedAt":"2025-09-05T20:21:56Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On 2025-09-05 at 11:50:58, Patrick Steinhardt wrote:\n> Introduce infrastructure to build the internal Rust library. This\n> mirrors the infrastructure we have added to Meson in the preceding\n> commit. Developers can enable the infrastructure by passing the new\n> `WITH_RUST` build toggle.\n\nThe idea here seems great and I'm fully on board…\n\n> diff --git a/Makefile b/Makefile\n> index 555b7f4dc3..e7b3c8e57b 100644\n> --- a/Makefile\n> +++ b/Makefile\n> @@ -483,6 +483,14 @@ include shared.mak\n>  # Define LIBPCREDIR=/foo/bar if your PCRE header and library files are\n>  # in /foo/bar/include and /foo/bar/lib directories.\n>  #\n> +# == Optional Rust support ==\n> +#\n> +# Define WITH_RUST if you want to include features and subsystems written in\n> +# Rust into Git. For now, Rust is still an optional feature of the build\n> +# process. With Git 3.0 though, Rust will always be enabled.\n> +#\n> +# Building Rust code requires Cargo.\n> +#\n>  # == SHA-1 and SHA-256 defines ==\n>  #\n>  # === SHA-1 backend ===\n> @@ -918,6 +926,11 @@ TEST_SHELL_PATH = $(SHELL_PATH)\n>  LIB_FILE = libgit.a\n>  XDIFF_LIB = xdiff/lib.a\n>  REFTABLE_LIB = reftable/libreftable.a\n> +ifdef DEBUG\n> +RUST_LIB = target/debug/libgit.a\n> +else\n> +RUST_LIB = target/release/libgit.a\n> +endif\n>  \n>  GENERATED_H += command-list.h\n>  GENERATED_H += config-list.h\n> @@ -1387,8 +1400,12 @@ CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/unit-test.o\n>  \n>  UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o\n>  \n> -# xdiff and reftable libs may in turn depend on what is in libgit.a\n> -GITLIBS = common-main.o $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(LIB_FILE)\n> +GITLIBS = common-main.o $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB)\n> +ifdef WITH_RUST\n> +GITLIBS += $(RUST_LIB)\n> +endif\n> +# Other libs may in turn depend on what is in libgit.a.\n> +GITLIBS += $(LIB_FILE)\n>  EXTLIBS =\n>  \n>  GIT_USER_AGENT = git/$(GIT_VERSION)\n> @@ -1411,6 +1428,19 @@ BASIC_LDFLAGS =\n>  ARFLAGS = rcs\n>  PTHREAD_CFLAGS =\n>  \n> +# Rust flags\n> +CARGO_ARGS =\n> +ifndef V\n> +CARGO_ARGS += --quiet\n> +endif\n> +ifndef DEBUG\n> +CARGO_ARGS += --release\n> +endif\n> +\n> +ifdef WITH_RUST\n> +BASIC_CFLAGS += -DWITH_RUST\n> +endif\n\n…but unfortunately, all of this code is above the `-include config.mak`\nline, so if I set `WITH_RUST=1` in `config.mak`, it doesn't work: no\n`target` directory is created and `git version --build-options` says\nRust isn't enabled.  (It does work if I specify `WITH_RUST=1` on the\ncommand line, though.)\n\nMight it be a better idea to place this with the conditional code\nfarther down so it's properly honoured when configured in `config.mak`\nand friends?\n\nI am very pleased by the fact that cargo is quiet by default, though,\nand otherwise it seems to be well integrated into our build system.\nThis patch seems smaller than I was expecting, which is nice.\n-- \nbrian m. carlson (they/them)\nToronto, Ontario, CA\n"},{"id":"525675","messageId":"xmqq8qis399g.fsf@gitster.g","threadId":"64091","inReplyTo":"20250905-b4-pks-rust-breaking-change-v2-7-6939cbf4a0b8@pks.im","subject":"Re: [PATCH RFC v2 7/7] ci: enable Rust for breaking-changes jobs","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-09-05T21:00:11Z","receivedAt":"2025-09-05T21:00:15Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> diff --git a/ci/run-build-and-tests.sh b/ci/run-build-and-tests.sh\n> index 3680446649..c718bd101a 100755\n> --- a/ci/run-build-and-tests.sh\n> +++ b/ci/run-build-and-tests.sh\n> @@ -9,7 +9,9 @@ case \"$jobname\" in\n>  fedora-breaking-changes-musl|linux-breaking-changes)\n>  \texport GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main\n>  \texport WITH_BREAKING_CHANGES=YesPlease\n> +\texport WITH_RUST=YesPlease\n>  \tMESONFLAGS=\"$MESONFLAGS -Dbreaking_changes=true\"\n> +\tMESONFLAGS=\"$MESONFLAGS -Drust=enabled\"\n>  \t;;\n>  linux-TEST-vars)\n>  \texport OPENSSL_SHA1_UNSAFE=YesPlease\n\nThis had a slight interaction with other topics in flight that\ntargets 3.0 boundary.  I believe the resolution I did was correct,\nbut please double check for sanity.\n\nThanks.\n"},{"id":"525679","messageId":"xmqqy0qs1sk5.fsf@gitster.g","threadId":"64091","inReplyTo":"20250905-b4-pks-rust-breaking-change-v2-4-6939cbf4a0b8@pks.im","subject":"Re: [PATCH RFC v2 4/7] rust: implement a test balloon via the \"varint\" subsystem","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-09-05T21:46:18Z","receivedAt":"2025-09-05T21:46:22Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> diff --git a/src/varint.rs b/src/varint.rs\n> new file mode 100644\n> index 00000000000..3d41760a555\n> --- /dev/null\n> +++ b/src/varint.rs\n> @@ -0,0 +1,92 @@\n> +use std::os::raw::c_int;\n> +use std::os::raw::c_uchar;\n> +\n> +#[no_mangle]\n> +pub unsafe extern \"C\" fn decode_varint(bufp: *mut *const c_uchar) -> usize {\n> +    let mut buf = *bufp;\n> +    let mut c = *buf;\n> +    let mut val = usize::from(c & 127);\n> +\n> +    buf = buf.add(1);\n> +\n> +    while (c & 128) != 0 {\n> +        val += 1;\n> +        if val == 0 || val.leading_zeros() < 7 {\n> +            return 0; // overflow\n> +        }\n> +\n> +        c = *buf;\n> +        buf = buf.add(1);\n> +\n> +        val = (val << 7) + usize::from(c & 127);\n> +    }\n> +\n> +    *bufp = buf;\n> +    val\n> +}\n\nThis (and the encoding side) looks quite faithful translation of the\noriginal in C.  Interestingly, disassembly I saw looked a lot more\noptimized than the C variant compiled with clang-19 -O2.  The\ndifference probably is largely due to its omitting frame pointer.\n\nThe comparison to detect overflow compiled to direct comparison with\n0x1ffffffffffffff (both in C and rustc/LLVM), which was amusing,\ntoo.\n"},{"id":"525681","messageId":"xmqqqzwk1q3z.fsf@gitster.g","threadId":"64091","inReplyTo":"xmqqy0qs1sk5.fsf@gitster.g","subject":"Re: [PATCH RFC v2 4/7] rust: implement a test balloon via the \"varint\" subsystem","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-09-05T22:39:12Z","receivedAt":"2025-09-05T22:39:16Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> ...  Interestingly, disassembly I saw looked a lot more\n> optimized than the C variant compiled with clang-19 -O2.\n\nThat was a false alarm.  With right compilation option passed, C\nversion of decode_varint() compiled to identical assembly as what\nrustc/llvm produced.\n\n"},{"id":"525682","messageId":"aLtsjvV3GWyFByMq@fruit.crustytoothpaste.net","threadId":"64091","inReplyTo":"xmqqqzwk1q3z.fsf@gitster.g","subject":"Re: [PATCH RFC v2 4/7] rust: implement a test balloon via the \"varint\" subsystem","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2025-09-05T23:04:46Z","receivedAt":"2025-09-05T23:04:49Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On 2025-09-05 at 22:39:12, Junio C Hamano wrote:\n> Junio C Hamano <gitster@pobox.com> writes:\n> \n> > ...  Interestingly, disassembly I saw looked a lot more\n> > optimized than the C variant compiled with clang-19 -O2.\n> \n> That was a false alarm.  With right compilation option passed, C\n> version of decode_varint() compiled to identical assembly as what\n> rustc/llvm produced.\n\nThat's not unexpected, I'd say, especially since the code is very\nsimilar and uses very similar data structures, including pointers.\n\nHowever, as we adopt Rust more in the future, we may see some\nperformance optimizations because Rust allows making more guarantees\nabout data.  For instance, the C compiler must deal with the fact that\nyou can cast a const pointer to a non-const pointer, but Rust does not\nallow you cast or transmute an immutable slice to a mutable one or\naccess it mutably at the same time, so the compiler can then assume that\nthe data will not be modified, including by another thread, and optimize\naccordingly.\n-- \nbrian m. carlson (they/them)\nToronto, Ontario, CA\n"},{"id":"525695","messageId":"xmqqzfb7yuw1.fsf@gitster.g","threadId":"64091","inReplyTo":"20250905-b4-pks-rust-breaking-change-v2-6-6939cbf4a0b8@pks.im","subject":"Re: [PATCH RFC v2 6/7] ci: convert \"pedantic\" job into full build with breaking changes","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-09-07T00:21:50Z","receivedAt":"2025-09-07T00:21:54Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n>  fedora-*|almalinux-*)\n>  \tdnf -yq update >/dev/null &&\n> -\tdnf -yq install shadow-utils sudo make gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel >/dev/null\n> +\tdnf -yq install shadow-utils sudo meson ninja pkg-config gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel >/dev/null\n\nThis drops \"make\" and adds \"meson ninja pkg-config\".\n\nhttps://github.com/git/git/actions/runs/17506343802/job/49765327830\n\nseems to indicate that AlmaLinux is unable to find meson and ninja.\n\n"},{"id":"525698","messageId":"CABPp-BGpdEP9+CTApknmGNO=b=66bFKVzWL2s3gmgCMtTBTjPA@mail.gmail.com","threadId":"64091","inReplyTo":"aLrzqR2Z9jz5CuJu@pks.im","subject":"Re: [PATCH RFC v2 0/7] Introduce Rust and announce that it will become mandatorty","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2025-09-07T04:31:02Z","receivedAt":"2025-09-07T04:31:14Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Fri, Sep 5, 2025 at 7:29 AM Patrick Steinhardt <ps@pks.im> wrote:\n>\n\n> > It looks like this version does include the necessary Makefile changes which\n> > is great. I do think though, that for the test balloon to be valuable, we\n> > need make building with rust the default with an error message that tells\n> > people how to build without rust if that fails. Otherwise it is easy for\n> > people building on platforms without rust support to miss that we're going\n> > to be making it mandatory soon.\n>\n> I have a plan layed out in the BreakingChanges document that mentions\n> how I'm proposing to do the transition:\n>\n>   1. We introduce it with auto-detection for Meson and default-disabled\n>      for our Makefile in Git 2.52.\n>\n>   2. We enable Rust by default in case WITH_BREAKING_CHANGES is enabled\n>      in Git 2.53.\n>\n>   3. We always enable Rust by default in Git 2.54.\n\nI don't see how steps 1 & 2 help at all.  We now know we want to make\nRust mandatory eventually, and should provide distributors and\nplatforms as much notice as possible so they are aware.  But what\nyou've proposed is another libgit-rs or libgit-sys -- an optional\ncomponent that no one will know about unless they go looking for it.\nI don't see how those two steps provide any incremental help to\nanybody over what libgit-rs and libgit-sys have done.  From my point\nof view, Rust should be enabled by default in Git 2.52, with a simple\nknob provided to let distributors/platforms/users turn it off and\nbuild without it.\n\n>   4. We unconditionally enable Rust in Git 3.0.\n>\n> This is basically gradually tightening the screws, which both gives us\n> time to build the infra and gives downstream time to become aware of the\n> change and adapt.\n>\n> I think making it mandatory in Git 3.0 makes sense because I also\n> propose to make the last version without mandatory Rust be an LTS\n> version. And if we connect that with it being the last version before\n> 3.0 I think that's an additional benefit, as there will be other\n> breaking changes in 3.0.\n>\n> In the end it kind of hinges on when we think we want to release Git\n> 3.0. If we can agree on the above plan, we could also think about making\n> Git 2.55 become 3.0 instead. That'd be in a bit less than a year from\n> now, which I think is a good timeframe for that breaking release. I\n> personally don't see a reason to push it out into the future for way\n> longer than that, and it would be good anyway if we built some consensus\n> around its release date.\n\nI see your plan, but I agree with Phillip that I don't see why it\nmakes sense to lump the Rust transition with the 3.0 transition.\n\nSetting that aside for a moment, the idea of Git 2.55 becoming 3.0\nseems like a good idea to me, assuming that doesn't rush brian on the\nsha1/sha256 interop (since I think that's probably the paramount\nfeature of 3.0).\n"},{"id":"525699","messageId":"CABPp-BGF9Ds=9bLKbWFEuatGmGycemwTMiyez_s3XMJR=M6xQw@mail.gmail.com","threadId":"64091","inReplyTo":"20250905-b4-pks-rust-breaking-change-v2-1-6939cbf4a0b8@pks.im","subject":"Re: [PATCH RFC v2 1/7] meson: add infrastructure to build internal Rust library","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2025-09-07T04:54:18Z","receivedAt":"2025-09-07T04:54:31Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Fri, Sep 5, 2025 at 4:51 AM Patrick Steinhardt <ps@pks.im> wrote:\n>\n> Add the infrastructure into Meson to build an internal Rust library.\n> Building the Rust parts of Git are for now entirely optional, as they\n> are mostly intended as a test balloon for both Git developers, but also\n> for distributors of Git. So for now, they may contain:\n>\n>   - New features that are not mission critical to Git and that users can\n>     easily live without.\n>\n>   - Alternative implementations of small subsystems.\n>\n> If these test balloons are successful, we will eventually make Rust a\n> mandatory dependency for our build process in Git 3.0.\n\nOkay.\n\n> The availability of a Rust toolchain will be auto-detected by Meson at\n> setup time. This behaviour can be tweaked via the `-Drust=` feature\n> toggle.\n\nThis goes against what you said above, because it turns it into\nsomething other than a test balloon.  As I've said elsewhere, I don't\nthink this part is helpful; it reduces the amount of notice that\ndistributors and platforms have about our intent to make Rust\nmandatory.\n\n> Next to the linkable Rust library, also wire up tests that can be\n> executed via `meson test`. This allows us to use the native unit testing\n> capabilities of Rust.\n\nCool.\n\n> Signed-off-by: Patrick Steinhardt <ps@pks.im>\n> ---\n>  meson.build       | 12 +++++++++++-\n>  meson_options.txt |  2 ++\n>  src/lib.rs        |  0\n>  src/meson.build   | 15 +++++++++++++++\n>  4 files changed, 28 insertions(+), 1 deletion(-)\n>\n> diff --git a/meson.build b/meson.build\n> index e8ec0eca165..5b2e9af1bf1 100644\n> --- a/meson.build\n> +++ b/meson.build\n> @@ -1702,8 +1702,17 @@ version_def_h = custom_target(\n>  )\n>  libgit_sources += version_def_h\n>\n> +libgit_libraries = [ ]\n> +\n> +rust_available = add_languages('rust', native: false, required: get_option('rust'))\n> +rust_option = get_option('rust').disable_auto_if(not rust_available)\n> +if rust_option.allowed()\n> +  subdir('src')\n> +  libgit_c_args += '-DWITH_RUST'\n> +endif\n> +\n>  libgit = declare_dependency(\n> -  link_with: static_library('git',\n> +  link_with: libgit_libraries + static_library('git',\n>      sources: libgit_sources,\n>      c_args: libgit_c_args + [\n>        '-DGIT_VERSION_H=\"' + version_def_h.full_path() + '\"',\n> @@ -2239,6 +2248,7 @@ summary({\n>    'pcre2': pcre2,\n>    'perl': perl_features_enabled,\n>    'python': target_python.found(),\n> +  'rust': rust_option.allowed(),\n>  }, section: 'Auto-detected features', bool_yn: true)\n>\n>  summary({\n> diff --git a/meson_options.txt b/meson_options.txt\n> index 1668f260a18..143dee9237c 100644\n> --- a/meson_options.txt\n> +++ b/meson_options.txt\n> @@ -71,6 +71,8 @@ option('zlib_backend', type: 'combo', choices: ['auto', 'zlib', 'zlib-ng'], valu\n>  # Build tweaks.\n>  option('breaking_changes', type: 'boolean', value: false,\n>    description: 'Enable upcoming breaking changes.')\n> +option('rust', type: 'feature', value: 'auto',\n> +  description: 'Enable building with Rust.')\n>  option('macos_use_homebrew_gettext', type: 'boolean', value: true,\n>    description: 'Use gettext from Homebrew instead of the slightly-broken system-provided one.')\n>\n> diff --git a/src/lib.rs b/src/lib.rs\n> new file mode 100644\n> index 00000000000..e69de29bb2d\n> diff --git a/src/meson.build b/src/meson.build\n> new file mode 100644\n> index 00000000000..eb752651d35\n> --- /dev/null\n> +++ b/src/meson.build\n> @@ -0,0 +1,15 @@\n> +libgit_rs = static_library('git_rs',\n> +  sources: [\n> +    'lib.rs',\n> +  ],\n> +  rust_crate_type: 'staticlib',\n> +)\n> +libgit_libraries += libgit_rs\n> +\n> +# The 'rust' module was only introduced in Meson 1.0. Furthermore, the module\n> +# does not seem to work on macOS as expected right now. As such, we only\n> +# conditionally enable tests.\n> +if meson.version().version_compare('>=1.0.0') and host_machine.system() != 'darwin'\n> +  rustmod = import('rust')\n> +  rustmod.test('rust', libgit_rs)\n> +endif\n\nWould it make sense to invoke 'cargo test' as one step of 'meson test'\non mac as an alternative, so that mac users also can run the tests?\n"},{"id":"525700","messageId":"CABPp-BEWS2=uHAjEf5YdahC3gxbjJ5L3NpYEgSSmsUa1dK=aeQ@mail.gmail.com","threadId":"64091","inReplyTo":"20250905-b4-pks-rust-breaking-change-v2-2-6939cbf4a0b8@pks.im","subject":"Re: [PATCH RFC v2 2/7] Makefile: introduce infrastructure to build internal Rust library","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2025-09-07T04:58:44Z","receivedAt":"2025-09-07T04:58:58Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Fri, Sep 5, 2025 at 4:51 AM Patrick Steinhardt <ps@pks.im> wrote:\n>\n> Introduce infrastructure to build the internal Rust library. This\n> mirrors the infrastructure we have added to Meson in the preceding\n> commit. Developers can enable the infrastructure by passing the new\n> `WITH_RUST` build toggle.\n\nSo, again, this makes it not a test balloon, which reduces the amount\nof notice distributors will get.  I'd prefer a WITHOUT_RUST build\ntoggle, so they get as much notice as possible.\n\n> Signed-off-by: Patrick Steinhardt <ps@pks.im>\n> ---\n>  .gitignore |  2 ++\n>  Cargo.toml |  9 +++++++++\n>  Makefile   | 45 +++++++++++++++++++++++++++++++++++++++++++--\n>  3 files changed, 54 insertions(+), 2 deletions(-)\n>\n> diff --git a/.gitignore b/.gitignore\n> index 1803023427..0833453cf6 100644\n> --- a/.gitignore\n> +++ b/.gitignore\n> @@ -1,4 +1,6 @@\n>  /fuzz_corpora\n> +/target/\n> +/Cargo.lock\n>  /GIT-BUILD-DIR\n>  /GIT-BUILD-OPTIONS\n>  /GIT-CFLAGS\n> diff --git a/Cargo.toml b/Cargo.toml\n> new file mode 100644\n> index 0000000000..17a4f4da0c\n> --- /dev/null\n> +++ b/Cargo.toml\n> @@ -0,0 +1,9 @@\n> +[package]\n> +name = \"git\"\n> +version = \"0.1.0\"\n> +edition = \"2021\"\n> +\n> +[lib]\n> +crate-type = [\"staticlib\"]\n> +\n> +[dependencies]\n> diff --git a/Makefile b/Makefile\n> index 555b7f4dc3..e7b3c8e57b 100644\n> --- a/Makefile\n> +++ b/Makefile\n> @@ -483,6 +483,14 @@ include shared.mak\n>  # Define LIBPCREDIR=/foo/bar if your PCRE header and library files are\n>  # in /foo/bar/include and /foo/bar/lib directories.\n>  #\n> +# == Optional Rust support ==\n> +#\n> +# Define WITH_RUST if you want to include features and subsystems written in\n> +# Rust into Git. For now, Rust is still an optional feature of the build\n> +# process. With Git 3.0 though, Rust will always be enabled.\n> +#\n> +# Building Rust code requires Cargo.\n> +#\n>  # == SHA-1 and SHA-256 defines ==\n>  #\n>  # === SHA-1 backend ===\n> @@ -918,6 +926,11 @@ TEST_SHELL_PATH = $(SHELL_PATH)\n>  LIB_FILE = libgit.a\n>  XDIFF_LIB = xdiff/lib.a\n>  REFTABLE_LIB = reftable/libreftable.a\n> +ifdef DEBUG\n> +RUST_LIB = target/debug/libgit.a\n> +else\n> +RUST_LIB = target/release/libgit.a\n> +endif\n>\n>  GENERATED_H += command-list.h\n>  GENERATED_H += config-list.h\n> @@ -1387,8 +1400,12 @@ CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/unit-test.o\n>\n>  UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o\n>\n> -# xdiff and reftable libs may in turn depend on what is in libgit.a\n> -GITLIBS = common-main.o $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(LIB_FILE)\n> +GITLIBS = common-main.o $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB)\n> +ifdef WITH_RUST\n> +GITLIBS += $(RUST_LIB)\n> +endif\n> +# Other libs may in turn depend on what is in libgit.a.\n> +GITLIBS += $(LIB_FILE)\n>  EXTLIBS =\n>\n>  GIT_USER_AGENT = git/$(GIT_VERSION)\n> @@ -1411,6 +1428,19 @@ BASIC_LDFLAGS =\n>  ARFLAGS = rcs\n>  PTHREAD_CFLAGS =\n>\n> +# Rust flags\n> +CARGO_ARGS =\n> +ifndef V\n> +CARGO_ARGS += --quiet\n> +endif\n> +ifndef DEBUG\n> +CARGO_ARGS += --release\n> +endif\n> +\n> +ifdef WITH_RUST\n> +BASIC_CFLAGS += -DWITH_RUST\n> +endif\n> +\n>  # For the 'sparse' target\n>  SPARSE_FLAGS ?= -std=gnu99 -D__STDC_NO_VLA__\n>  SP_EXTRA_FLAGS =\n> @@ -2918,6 +2948,16 @@ scalar$X: scalar.o GIT-LDFLAGS $(GITLIBS)\n>  $(LIB_FILE): $(LIB_OBJS)\n>         $(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^\n>\n> +$(RUST_LIB): FORCE\n> +       @OLD_STAT=\"$$(stat $@ 2>/dev/null)\"; \\\n> +           cargo build $(CARGO_ARGS); \\\n> +           if test $$? != 0 || test x\"$$OLD_STAT\" != x\"$$(stat $@ 2>/dev/null)\"; then \\\n> +               echo '   ' CARGO $@; \\\n> +           fi\n> +\n> +.PHONY: rust\n> +rust: $(RUST_LIB)\n> +\n>  $(XDIFF_LIB): $(XDIFF_OBJS)\n>         $(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^\n>\n> @@ -3768,6 +3808,7 @@ clean: profile-clean coverage-clean cocciclean\n>         $(RM) $(FUZZ_PROGRAMS)\n>         $(RM) $(SP_OBJ)\n>         $(RM) $(HCC)\n> +       $(RM) -r target/ Cargo.lock\n>         $(RM) version-def.h\n>         $(RM) -r $(dep_dirs) $(compdb_dir) compile_commands.json\n>         $(RM) $(test_bindir_programs)\n>\n> --\n> 2.51.0.417.g1ba7204a04.dirty\n\nJohannes provided some additional tooling (an extra library to\ndownload from git-for-windows) that was needed for building and\nlinking against Rust on Windows, which Ezekiel incorporated into his\nseries.  Is that not needed here for some reason, or are we just not\ndiscovering that it's needed since you haven't created a test balloon\nyet?\n"},{"id":"525701","messageId":"CABPp-BE3L6cT9KVjQLmFfXY2+6LKwTba9uFCCdJSKhdgb2wD2Q@mail.gmail.com","threadId":"64091","inReplyTo":"aLs_QZ9eBGevcGfb@fruit.crustytoothpaste.net","subject":"Re: [PATCH RFC v2 3/7] help: report on whether or not Rust is enabled","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2025-09-07T05:00:01Z","receivedAt":"2025-09-07T05:00:14Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Fri, Sep 5, 2025 at 12:51 PM brian m. carlson\n<sandals@crustytoothpaste.net> wrote:\n>\n> On 2025-09-05 at 11:50:59, Patrick Steinhardt wrote:\n> > diff --git a/help.c b/help.c\n> > index bb20498cfd..5854dd4a7e 100644\n> > --- a/help.c\n> > +++ b/help.c\n> > @@ -791,6 +791,12 @@ void get_version_info(struct strbuf *buf, int show_build_options)\n> >               strbuf_addf(buf, \"shell-path: %s\\n\", SHELL_PATH);\n> >               /* NEEDSWORK: also save and output GIT-BUILD_OPTIONS? */\n> >\n> > +#if defined WITH_RUST\n> > +             strbuf_addstr(buf, \"rust: enabled\\n\");\n> > +#else\n> > +             strbuf_addstr(buf, \"rust: disabled\\n\");\n> > +#endif\n> > +\n>\n> I think this is a great idea and likely to be super helpful.  Thanks for\n> including it.\n\nAgreed, this is nice attention to detail that I would have overlooked.\nMuch appreciated.\n"},{"id":"525702","messageId":"CABPp-BFXRbaHk9U3BX+d12bZ+ryGOp+btR0ODMw+HtD7xd+MBQ@mail.gmail.com","threadId":"64091","inReplyTo":"20250905-b4-pks-rust-breaking-change-v2-5-6939cbf4a0b8@pks.im","subject":"Re: [PATCH RFC v2 5/7] BreakingChanges: announce Rust becoming mandatory","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2025-09-07T05:25:27Z","receivedAt":"2025-09-07T05:25:39Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Fri, Sep 5, 2025 at 4:51 AM Patrick Steinhardt <ps@pks.im> wrote:\n>\n> Over the last couple of years the appetite for bringin Rust into the\n> codebase has grown significantly across the developer base. Introducing\n> Rust is a major change though and has ramifications for the whole\n> ecosystem:\n>\n>   - Some platforms haven't yet been able to implement a Rust toolchain,\n>     even though it is possible in theory.\n>\n>   - Some platforms don't have any support for Rust at all.\n>\n>   - Some platforms may have to figure out how to fit Rust into their\n>     bootstrapping sequence.\n>\n> Due to this, and given that Git is a critical piece of infrastructure\n> for the whole industry, we cannot just introduce such a heavyweight\n> dependency without doing our due diligence.\n>\n> Instead, preceding commits have introduced a test balloon into our build\n> infrastructure that convert one tiny subsystem to use Rust.  For now,\n> using Rust to build that subsystem is entirely optional -- if no Rust\n> support is available, we continue to use the C implementation. This test\n> balloon has the intention to give distributions time and let them ease\n> into our adoption of Rust.\n\nThis paragraph appears to contradict itself -- it says we introduced a\ntest balloon, but then explains how the test balloon isn't actually a\ntest balloon (i.e. that we simply silently use the C implementation if\nRust isn't available).\n\n> Having multiple implementations of the same subsystem is not sustainable\n> though, and the plan is to eventually be able to use Rust freely all\n> across our codebase. As such, there is the intent to make Rust become a\n> mandatory part of our build process.\n>\n> Add an announcement to our breaking changes that Rust will become\n> mandatory in Git 3.0. A (very careful and non-binding) estimate might be\n> that this major release might be released in the second half of next\n> year, which should give distributors enough time to prepare for the\n> change.\n\nWhile I disagree with lumping the change with 3.0, I appreciate the\ngoal to provide additional notice.  I think it really ought to be part\nof the release notes for 2.52 instead of the BreakingChanges document,\nbut having some kind of announcement is the most important part.\nThanks for proposing some wording.\n\n> Signed-off-by: Patrick Steinhardt <ps@pks.im>\n> ---\n>  Documentation/BreakingChanges.adoc | 36 ++++++++++++++++++++++++++++++++++++\n>  1 file changed, 36 insertions(+)\n>\n> diff --git a/Documentation/BreakingChanges.adoc b/Documentation/BreakingChanges.adoc\n> index f8d2eba061..dbb15b6a57 100644\n> --- a/Documentation/BreakingChanges.adoc\n> +++ b/Documentation/BreakingChanges.adoc\n> @@ -165,6 +165,42 @@ A prerequisite for this change is that the ecosystem is ready to support the\n>  \"reftable\" format. Most importantly, alternative implementations of Git like\n>  JGit, libgit2 and Gitoxide need to support it.\n>\n> +* Git will require Rust as a mandatory part of the build process. While Git\n> +  already started to adopt Rust in the Git 2.52, all parts written in Rust are\n> +  optional for the time being. This includes:\n\nThis isn't quite accurate; perhaps:\n\n...While Git already started to adopt Rust into the core in Git 2.52\n(and as an optional \"contrib\" component back in Git 2.49), all\nparts...\n\n> ++\n> +  ** Subsystems that have an alternative implementation in Rust to test\n> +     interoperability between our C and Rust codebase.\n> +  ** Newly written features that are not mission critical for a fully functional\n> +     Git client.\n> ++\n> +These changes are meant as test balloons to allow distributors of Git to prepare\n> +for Rust becoming a mandatory part of the build process. There will be multiple\n> +milestones for the introduction of Rust:\n> ++\n> +1. Initially, with Git 2.52, support for Rust will be auto-detected by Rust and\n> +   disabled in our Makefile so that the project can sort out the initial\n> +   infrastructure.\n> +2. In Git 2.53, support for Rust will be made mandatory in case Git is compiled\n> +   with breaking changes. Breaking changes can be enabled for Meson by saying\n> +   `meson configure -Dbreaking_changes=true` and for Makefiles via `make\n> +   WITH_BREAKING_CHANGES=YesPlease`. It will still be possible to compile with\n> +   breaking changes, but explicitly disable Rust.\n\nAs stated in https://lore.kernel.org/git/20250904-b4-pks-rust-breaking-change-v1-0-3af1d25e0be9@pks.im/T/#mf9283df5e7724fd00a6fe23e1777b77fcdf0c12d,\nI don't see how these two step help at all, and think we should jump\nstraight to step 3 with Git 2.52.\n\n> +3. In Git 2.54, both build systems will default-enable support for Rust so that\n> +   builds will break if Rust is not available on the build host. The use of Rust\n> +   can still be explicitly disabled via build flags.\n> +4. In Git 3.0, the build options will be removed and support for Rust is\n> +   mandatory.\n> ++\n> +You can explicitly ask both Meson and our Makefile-based system to enable Rust\n> +by saying `meson configure -Drust=enabled` and `make WITH_RUST=YesPlease`,\n> +respectively.\n\nI think we should instead allow folks to ask Meson and Maskfile to\ndisable Rust, otherwise we haven't provided a test balloon yet.\n\n> ++\n> +The Git project will declare the last version before Git 3.0 to be a long-term\n> +support release that is maintained until alternate Rust backends like gcc-rs are\n> +able to build Git. The Git project may need to rely on distributions to help\n> +with identifying and backporting important bugfixes.\n\nI disagree with tying the timeline to gcc-rs being able to build git;\nI think that part of this paragraph should be stricken.\n"},{"id":"525703","messageId":"CABPp-BFw-Oqp71jW5SYCKYOWtjWFSQPOsUVWdF7EnzftwAR2vw@mail.gmail.com","threadId":"64091","inReplyTo":"aLrnwOGKaAjLj0Bo@pks.im","subject":"Re: [PATCH RFC v2 5/7] BreakingChanges: announce Rust becoming mandatory","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2025-09-07T05:31:07Z","receivedAt":"2025-09-07T05:31:19Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Fri, Sep 5, 2025 at 6:38 AM Patrick Steinhardt <ps@pks.im> wrote:\n>\n> On Fri, Sep 05, 2025 at 02:45:46PM +0200, Matthias Aßhauer wrote:\n\n> > Do we want to commit to promising support until gccrs is ready? What if\n> > gccrs ends up abandoned? Or takes an unexpectedly long time to reach a stage\n> > where it can build Git? It might make sense to give this LTS release a time\n> > limit instead, or in addidtion.\n>\n> Yeah, I wasn't quite clear on that one, either. An alternative:\n>\n>   - We will maintain the LTS release for 8 release cycles, which equates\n>     to roughly two years. It sounds like a lot, but recent security\n>     releases have stretched quite far into the past.\n>\n>   - If there are still dependents after these two years we will hand\n>     over maintainership of the LTS branch to dependents. So they will be\n>     responsible for the backporting.\n>\n> This really only is a suggestion though. I'm especially waiting for\n> Junio's feedback here to see whether he thinks that this is a reasonable\n> thing to do.\n\nOver at https://lore.kernel.org/git/xmqqplc43o7c.fsf@gitster.g/, Junio\nsaid multiple years isn't something he's willing to promise, but\nsuggests 18 months might be doable.\n\nI have a suspicion that if you want a promised level of support,\nyou'll not only get something less than what distributors want, but\nsomething far less than we'll provide in practice.  I'm curious if the\nalternative wording over at\nhttps://lore.kernel.org/git/CABPp-BG3Zcw63vNziy86MvYNubefn1SmPvXefpqpA=a+42KT8A@mail.gmail.com/\nis more likely to be realistic:\n\n\"We'll weigh the severity of each security issue and the cost to\nbackport and give the last C-only version significant extra weight in\nour considerations\"\n\nI know it may not be what distributors want, but overpromising also\nhas deleterious effects, so...\n"},{"id":"525709","messageId":"aL2kPUokmioiXCOG@szeder.dev","threadId":"64091","inReplyTo":"20250905-b4-pks-rust-breaking-change-v2-2-6939cbf4a0b8@pks.im","subject":"Re: [PATCH RFC v2 2/7] Makefile: introduce infrastructure to build internal Rust library","fromName":"SZEDER Gábor","fromEmail":"szeder.dev@gmail.com","sentAt":"2025-09-07T15:26:53Z","receivedAt":"2025-09-07T15:26:57Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"On Fri, Sep 05, 2025 at 01:50:58PM +0200, Patrick Steinhardt wrote:\n> Introduce infrastructure to build the internal Rust library. This\n> mirrors the infrastructure we have added to Meson in the preceding\n> commit. Developers can enable the infrastructure by passing the new\n> `WITH_RUST` build toggle.\n> \n> Signed-off-by: Patrick Steinhardt <ps@pks.im>\n> ---\n>  .gitignore |  2 ++\n>  Cargo.toml |  9 +++++++++\n>  Makefile   | 45 +++++++++++++++++++++++++++++++++++++++++++--\n>  3 files changed, 54 insertions(+), 2 deletions(-)\n\n> diff --git a/Makefile b/Makefile\n> index 555b7f4dc3..e7b3c8e57b 100644\n> --- a/Makefile\n> +++ b/Makefile\n> @@ -483,6 +483,14 @@ include shared.mak\n>  # Define LIBPCREDIR=/foo/bar if your PCRE header and library files are\n>  # in /foo/bar/include and /foo/bar/lib directories.\n>  #\n> +# == Optional Rust support ==\n> +#\n> +# Define WITH_RUST if you want to include features and subsystems written in\n> +# Rust into Git. For now, Rust is still an optional feature of the build\n> +# process. With Git 3.0 though, Rust will always be enabled.\n> +#\n> +# Building Rust code requires Cargo.\n> +#\n>  # == SHA-1 and SHA-256 defines ==\n>  #\n>  # === SHA-1 backend ===\n> @@ -918,6 +926,11 @@ TEST_SHELL_PATH = $(SHELL_PATH)\n>  LIB_FILE = libgit.a\n>  XDIFF_LIB = xdiff/lib.a\n>  REFTABLE_LIB = reftable/libreftable.a\n> +ifdef DEBUG\n> +RUST_LIB = target/debug/libgit.a\n> +else\n> +RUST_LIB = target/release/libgit.a\n> +endif\n>  \n>  GENERATED_H += command-list.h\n>  GENERATED_H += config-list.h\n> @@ -1387,8 +1400,12 @@ CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/unit-test.o\n>  \n>  UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o\n>  \n> -# xdiff and reftable libs may in turn depend on what is in libgit.a\n> -GITLIBS = common-main.o $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(LIB_FILE)\n> +GITLIBS = common-main.o $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB)\n> +ifdef WITH_RUST\n> +GITLIBS += $(RUST_LIB)\n> +endif\n> +# Other libs may in turn depend on what is in libgit.a.\n> +GITLIBS += $(LIB_FILE)\n>  EXTLIBS =\n>  \n>  GIT_USER_AGENT = git/$(GIT_VERSION)\n> @@ -1411,6 +1428,19 @@ BASIC_LDFLAGS =\n>  ARFLAGS = rcs\n>  PTHREAD_CFLAGS =\n>  \n> +# Rust flags\n> +CARGO_ARGS =\n> +ifndef V\n> +CARGO_ARGS += --quiet\n> +endif\n> +ifndef DEBUG\n> +CARGO_ARGS += --release\n> +endif\n> +\n> +ifdef WITH_RUST\n> +BASIC_CFLAGS += -DWITH_RUST\n> +endif\n> +\n>  # For the 'sparse' target\n>  SPARSE_FLAGS ?= -std=gnu99 -D__STDC_NO_VLA__\n>  SP_EXTRA_FLAGS =\n> @@ -2918,6 +2948,16 @@ scalar$X: scalar.o GIT-LDFLAGS $(GITLIBS)\n>  $(LIB_FILE): $(LIB_OBJS)\n>  \t$(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^\n>  \n> +$(RUST_LIB): FORCE\n\nWhy is this target FORCE-d instead of declaring its dependencies?\n\n> +\t@OLD_STAT=\"$$(stat $@ 2>/dev/null)\"; \\\n> +\t    cargo build $(CARGO_ARGS); \\\n> +\t    if test $$? != 0 || test x\"$$OLD_STAT\" != x\"$$(stat $@ 2>/dev/null)\"; then \\\n> +\t\techo '   ' CARGO $@; \\\n> +\t    fi\n\nThis hides 'cargo's exit code from 'make', so a failure to build the\nRust components won't abort the build.  So once we have a successfully\nbuilt Rust library and were to inadvertently introduce a syntax error\ninto the Rust code:\n\n  $ echo foo >src/varint.rs \n  $ make WITH_RUST=1\n  error: expected one of `!` or `::`, found `<eof>`\n   --> src/varint.rs:1:1\n    |\n  1 | foo\n    | ^^^ expected one of `!` or `::`\n\n  error: could not compile `git` (lib) due to previous error\n      CARGO target/release/libgit.a\n      SUBDIR git-gui\n      SUBDIR gitk-git\n      SUBDIR templates\n  $ echo $?\n  0\n\nAlso note that the error message is printed before the command that\nproduced that error; it should be the other way around.\n\n> +\n> +.PHONY: rust\n> +rust: $(RUST_LIB)\n> +\n>  $(XDIFF_LIB): $(XDIFF_OBJS)\n>  \t$(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^\n>  \n> @@ -3768,6 +3808,7 @@ clean: profile-clean coverage-clean cocciclean\n>  \t$(RM) $(FUZZ_PROGRAMS)\n>  \t$(RM) $(SP_OBJ)\n>  \t$(RM) $(HCC)\n> +\t$(RM) -r target/ Cargo.lock\n>  \t$(RM) version-def.h\n>  \t$(RM) -r $(dep_dirs) $(compdb_dir) compile_commands.json\n>  \t$(RM) $(test_bindir_programs)\n> \n> -- \n> 2.51.0.417.g1ba7204a04.dirty\n> \n"},{"id":"525743","messageId":"8A7DBC60-286A-48FE-A3D3-CAFC11FD3AEA@gmail.com","threadId":"64091","inReplyTo":"20250904-b4-pks-rust-breaking-change-v1-2-3af1d25e0be9@pks.im","subject":"Re: [PATCH RFC 2/3] rust: implement a test balloon via the \"varint\" subsystem","fromName":"Ben Knoble","fromEmail":"ben.knoble@gmail.com","sentAt":"2025-09-07T20:07:17Z","receivedAt":"2025-09-07T20:07:28Z","isPatch":true,"sender":{"key":"ben.knoble@gmail.com","avatar":"https://avatars.githubusercontent.com/u/22802209?v=4"},"body":"\n> Le 4 sept. 2025 à 10:27, Patrick Steinhardt <ps@pks.im> a écrit :\n> \n> ﻿Implement a trivial test balloon for our Rust build infrastructure by\n> reimplementing the \"varint.c\" subsystem in Rust. This subsystem is\n> chosen because it is trivial to convert and because it doesn't have any\n> dependencies to other components of Git.\n> \n> If support for Rust is enabled, we stop compiling \"varint.c\" and instead\n> compile and use \"src/varint.rs\".\n> \n> Signed-off-by: Patrick Steinhardt <ps@pks.im>\n> ---\n> meson.build     |  5 +++-\n> src/lib.rs      |  1 +\n> src/meson.build |  1 +\n> src/varint.rs   | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n> 4 files changed, 98 insertions(+), 1 deletion(-)\n> \n> diff --git a/src/varint.rs b/src/varint.rs\n> new file mode 100644\n> index 00000000000..3d41760a555\n> --- /dev/null\n> +++ b/src/varint.rs\n> @@ -0,0 +1,92 @@\n> +use std::os::raw::c_int;\n> +use std::os::raw::c_uchar;\n> +\n> +#[no_mangle]\n> +pub unsafe extern \"C\" fn decode_varint(bufp: *mut *const c_uchar) -> usize {\n> +    let mut buf = *bufp;\n> +    let mut c = *buf;\n> +    let mut val = usize::from(c & 127);\n> +\n> +    buf = buf.add(1);\n> +\n> +    while (c & 128) != 0 {\n> +        val += 1;\n> +        if val == 0 || val.leading_zeros() < 7 {\n> +            return 0; // overflow\n\nHm. I thought overflows panic in debug builds, in which case checking afterwards is too late? Does unsafe change that?"},{"id":"525753","messageId":"xmqq8qipzhg3.fsf@gitster.g","threadId":"64091","inReplyTo":"8A7DBC60-286A-48FE-A3D3-CAFC11FD3AEA@gmail.com","subject":"Re: [PATCH RFC 2/3] rust: implement a test balloon via the \"varint\" subsystem","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-09-08T04:39:08Z","receivedAt":"2025-09-08T04:39:12Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ben Knoble <ben.knoble@gmail.com> writes:\n\n>> +#[no_mangle]\n>> +pub unsafe extern \"C\" fn decode_varint(bufp: *mut *const c_uchar) -> usize {\n>> +    let mut buf = *bufp;\n>> +    let mut c = *buf;\n>> +    let mut val = usize::from(c & 127);\n>> +\n>> +    buf = buf.add(1);\n>> +\n>> +    while (c & 128) != 0 {\n>> +        val += 1;\n>> +        if val == 0 || val.leading_zeros() < 7 {\n>> +            return 0; // overflow\n>\n> Hm. I thought overflows panic in debug builds, in which case\n> checking afterwards is too late? Does unsafe change that?\n\nThis code is a very faithful conversion from C so if somebody does\nnot read Rust well, they can safely refer to the original in C.\n\nIn either variant, the leading zero's check asks \"can we shift val\nby 7 bits to the left?\" _before_ it actually shifts val (and or'es\nin the lower bits of c), so the \"overflow\" check is \"if we processed\nany more data we _would_ overflow, so we stop before overflowing\".\n\nIOW, the code _is_ avoiding the \"too late\" condition.\n\nThis is a tangent, but as many people pointed out, calling this a\ntest balloon is misreading.  This is quite different from what we\ntraditionally called a test balloon, where \n\n - we were already fairly sure that the construct is safe, but\n   wanted to be extra careful to smoke out anybody who has trouble\n   with it;\n\n - hence we use the construct in question in a place where nobody\n   can compile it out, hoping that anybody with a system incapable\n   of handling the construct in question would be broken badly,\n   reporting the breakage to us;\n\n - this is done with an understanding that even a single \"the\n   compiler on this this platform with more than dozen thousands\n   users cannot groke it\" would automatically stop us, causing us to\n   revert that test balloon code for _everybody_, refraining from\n   using that construct for _everybody_ until the situation changes.\n\nThis thing is different at all points.  We are not \"fairlu sure that\nRust is safe to use for everybody\"  Far from it.  We are confident\nthat requiring Rust would break known people.  We are doing this not\nbecause we intend to stop once we know of folks who would be broken.\nFar from it.\n\nIt would really be nice to find a niche that can be a new optional\nfeature that is not essential to the functioning of the system\nimplemented in an already modularized part of the system (e.g., an\noptional merge strategy, diff algorithm, built-in textconv filter, a\nnew ref backend, etc.).  Then we can introduce Rust, knowing that\nsome Rust-challenged systems will not be able to use these optional\nfeatures.  What Brian mentioned about two-hash interop feature,\nbeing only available on Rust-capable systems, could be such an\noptional feature, and if it can be done that way, that would be very\nwelcome.  If we can have Rust goodness soon enough without making it\nmandatory in too short a timeframe, that would be ideal.\n\nI already said that I find 6 months advance notice to folks on\nRust-challenged systems is way too short to be any good.  If the\nonly reason we give advance notice is because we want to make an\nexcuse of cutting them off sooner while being able to say that we\ngave them advance notice, that may be sufficient.  But if we truly\nwant to help them by giving enough time to them so that they can\nhelp their platform themselves, by lobbying, fundraising, or\notherwise campaigning to have usable Rust on their system, I really\ndo not think it is sufficient.\n\nThanks.\n"},{"id":"525768","messageId":"aL56ZIxSTJFNemvH@pks.im","threadId":"64091","inReplyTo":"xmqq8qis399g.fsf@gitster.g","subject":"Re: [PATCH RFC v2 7/7] ci: enable Rust for breaking-changes jobs","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-08T06:40:36Z","receivedAt":"2025-09-08T06:40:44Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Fri, Sep 05, 2025 at 02:00:11PM -0700, Junio C Hamano wrote:\n> Patrick Steinhardt <ps@pks.im> writes:\n> \n> > diff --git a/ci/run-build-and-tests.sh b/ci/run-build-and-tests.sh\n> > index 3680446649..c718bd101a 100755\n> > --- a/ci/run-build-and-tests.sh\n> > +++ b/ci/run-build-and-tests.sh\n> > @@ -9,7 +9,9 @@ case \"$jobname\" in\n> >  fedora-breaking-changes-musl|linux-breaking-changes)\n> >  \texport GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main\n> >  \texport WITH_BREAKING_CHANGES=YesPlease\n> > +\texport WITH_RUST=YesPlease\n> >  \tMESONFLAGS=\"$MESONFLAGS -Dbreaking_changes=true\"\n> > +\tMESONFLAGS=\"$MESONFLAGS -Drust=enabled\"\n> >  \t;;\n> >  linux-TEST-vars)\n> >  \texport OPENSSL_SHA1_UNSAFE=YesPlease\n> \n> This had a slight interaction with other topics in flight that\n> targets 3.0 boundary.  I believe the resolution I did was correct,\n> but please double check for sanity.\n\nYup, the resolution looks good to me. Thanks!\n\nPatrick\n"},{"id":"525769","messageId":"aL56cTrpAInqPJbJ@pks.im","threadId":"64091","inReplyTo":"aLtAXYUQ1GRRL6xg@fruit.crustytoothpaste.net","subject":"Re: [PATCH RFC v2 7/7] ci: enable Rust for breaking-changes jobs","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-08T06:40:49Z","receivedAt":"2025-09-08T06:40:57Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Fri, Sep 05, 2025 at 07:56:13PM +0000, brian m. carlson wrote:\n> On 2025-09-05 at 11:51:03, Patrick Steinhardt wrote:\n> > diff --git a/ci/install-dependencies.sh b/ci/install-dependencies.sh\n> > index 4eaf3514d6..4c58c7238e 100755\n> > --- a/ci/install-dependencies.sh\n> > +++ b/ci/install-dependencies.sh\n> > @@ -31,7 +31,7 @@ alpine-*)\n> >  \t;;\n> >  fedora-*|almalinux-*)\n> >  \tdnf -yq update >/dev/null &&\n> > -\tdnf -yq install shadow-utils sudo meson ninja pkg-config gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel >/dev/null\n> > +\tdnf -yq install shadow-utils sudo meson ninja pkg-config gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel rustc >/dev/null\n> \n> I know nothing about how Fedora packages Rust.  Do we need a cargo\n> package here as well, is that automatically included, or is it\n> unnecessary?\n\nFedora uses Meson, which doesn't (yet?) need Cargo for the build infra.\nI'll probably adapt this eventually to use the Cargo wraps, at which\npoint in time we'll need it as well.\n\nPatrick\n"},{"id":"525770","messageId":"aL56eP7v-qfVKxu2@pks.im","threadId":"64091","inReplyTo":"aLtGYlTXktuzxD0q@fruit.crustytoothpaste.net","subject":"Re: [PATCH RFC v2 2/7] Makefile: introduce infrastructure to build internal Rust library","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-08T06:40:56Z","receivedAt":"2025-09-08T06:41:03Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Fri, Sep 05, 2025 at 08:21:54PM +0000, brian m. carlson wrote:\n> On 2025-09-05 at 11:50:58, Patrick Steinhardt wrote:\n> > diff --git a/Makefile b/Makefile\n> > index 555b7f4dc3..e7b3c8e57b 100644\n> > --- a/Makefile\n> > +++ b/Makefile\n> > @@ -1411,6 +1428,19 @@ BASIC_LDFLAGS =\n> >  ARFLAGS = rcs\n> >  PTHREAD_CFLAGS =\n> >  \n> > +# Rust flags\n> > +CARGO_ARGS =\n> > +ifndef V\n> > +CARGO_ARGS += --quiet\n> > +endif\n> > +ifndef DEBUG\n> > +CARGO_ARGS += --release\n> > +endif\n> > +\n> > +ifdef WITH_RUST\n> > +BASIC_CFLAGS += -DWITH_RUST\n> > +endif\n> \n> …but unfortunately, all of this code is above the `-include config.mak`\n> line, so if I set `WITH_RUST=1` in `config.mak`, it doesn't work: no\n> `target` directory is created and `git version --build-options` says\n> Rust isn't enabled.  (It does work if I specify `WITH_RUST=1` on the\n> command line, though.)\n> \n> Might it be a better idea to place this with the conditional code\n> farther down so it's properly honoured when configured in `config.mak`\n> and friends?\n\nOops, good catch!\n\nPatrick\n"},{"id":"525771","messageId":"aL56niL8LW-NbxDI@pks.im","threadId":"64091","inReplyTo":"CABPp-BEWS2=uHAjEf5YdahC3gxbjJ5L3NpYEgSSmsUa1dK=aeQ@mail.gmail.com","subject":"Re: [PATCH RFC v2 2/7] Makefile: introduce infrastructure to build internal Rust library","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-08T06:41:34Z","receivedAt":"2025-09-08T06:41:42Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Sat, Sep 06, 2025 at 09:58:44PM -0700, Elijah Newren wrote:\n> On Fri, Sep 5, 2025 at 4:51 AM Patrick Steinhardt <ps@pks.im> wrote:\n> > @@ -3768,6 +3808,7 @@ clean: profile-clean coverage-clean cocciclean\n> >         $(RM) $(FUZZ_PROGRAMS)\n> >         $(RM) $(SP_OBJ)\n> >         $(RM) $(HCC)\n> > +       $(RM) -r target/ Cargo.lock\n> >         $(RM) version-def.h\n> >         $(RM) -r $(dep_dirs) $(compdb_dir) compile_commands.json\n> >         $(RM) $(test_bindir_programs)\n> >\n> > --\n> > 2.51.0.417.g1ba7204a04.dirty\n> \n> Johannes provided some additional tooling (an extra library to\n> download from git-for-windows) that was needed for building and\n> linking against Rust on Windows, which Ezekiel incorporated into his\n> series.  Is that not needed here for some reason, or are we just not\n> discovering that it's needed since you haven't created a test balloon\n> yet?\n\nAs Rust is opt-in initially we can take it slow and first land a minimum\nviable change with limited platform support. So I intentionally limited\nthe scope for now, but once this series lands we (or I) should iterate\nand also bring up other platforms.\n\nPatrick\n"},{"id":"525772","messageId":"aL56pzCk0Qmb5gRN@pks.im","threadId":"64091","inReplyTo":"aL2kPUokmioiXCOG@szeder.dev","subject":"Re: [PATCH RFC v2 2/7] Makefile: introduce infrastructure to build internal Rust library","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-08T06:41:43Z","receivedAt":"2025-09-08T06:41:51Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Sun, Sep 07, 2025 at 05:26:53PM +0200, SZEDER Gábor wrote:\n> On Fri, Sep 05, 2025 at 01:50:58PM +0200, Patrick Steinhardt wrote:\n> > diff --git a/Makefile b/Makefile\n> > index 555b7f4dc3..e7b3c8e57b 100644\n> > --- a/Makefile\n> > +++ b/Makefile\n> > @@ -2918,6 +2948,16 @@ scalar$X: scalar.o GIT-LDFLAGS $(GITLIBS)\n> >  $(LIB_FILE): $(LIB_OBJS)\n> >  \t$(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^\n> >  \n> > +$(RUST_LIB): FORCE\n> \n> Why is this target FORCE-d instead of declaring its dependencies?\n\nI was mostly doing that because cargo itself doesn't take any arguments,\nso it's quite easy for the list to grow stale. Let me adapt it though to\ntake proper dependencies for now.\n\nPatrick\n"},{"id":"525773","messageId":"aL56sBX-omMKIp2y@pks.im","threadId":"64091","inReplyTo":"xmqqzfb7yuw1.fsf@gitster.g","subject":"Re: [PATCH RFC v2 6/7] ci: convert \"pedantic\" job into full build with breaking changes","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-08T06:41:52Z","receivedAt":"2025-09-08T06:41:59Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Sat, Sep 06, 2025 at 05:21:50PM -0700, Junio C Hamano wrote:\n> Patrick Steinhardt <ps@pks.im> writes:\n> \n> >  fedora-*|almalinux-*)\n> >  \tdnf -yq update >/dev/null &&\n> > -\tdnf -yq install shadow-utils sudo make gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel >/dev/null\n> > +\tdnf -yq install shadow-utils sudo meson ninja pkg-config gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel >/dev/null\n> \n> This drops \"make\" and adds \"meson ninja pkg-config\".\n> \n> https://github.com/git/git/actions/runs/17506343802/job/49765327830\n> \n> seems to indicate that AlmaLinux is unable to find meson and ninja.\n\nOh, I completely missed that we have AlmaLinux in our pipelines.\nShould've taken a closer look seeing the above case statement. Will fix.\n\nPatrick\n"},{"id":"525774","messageId":"aL56vFa2SXlCDFWC@pks.im","threadId":"64091","inReplyTo":"l3apalzo6m5kydmfn6c376rswnfw5h34xpxauqarvxmlaksf6i@dhhdbat6gso3","subject":"Re: [PATCH RFC v2 1/7] meson: add infrastructure to build internal Rust library","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-08T06:42:04Z","receivedAt":"2025-09-08T06:42:12Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Fri, Sep 05, 2025 at 12:47:20PM -0500, Justin Tobler wrote:\n> On 25/09/05 01:50PM, Patrick Steinhardt wrote:\n> > +# The 'rust' module was only introduced in Meson 1.0. Furthermore, the module\n> > +# does not seem to work on macOS as expected right now. As such, we only\n> > +# conditionally enable tests.\n> > +if meson.version().version_compare('>=1.0.0') and host_machine.system() != 'darwin'\n> > +  rustmod = import('rust')\n> > +  rustmod.test('rust', libgit_rs)\n> > +endif\n> \n> Out of curiousity, what is the problem that we are seeing with macOS? I\n> removed the darwin guard statement and didn't notice any problems when\n> running `meson test rust`. Is this a well known problem with the Rust\n> module?\n\nIt's this:\n\n    Rust linker for the host machine: rustc -C linker=clang ld64 1053.12\n    WARNING: Unknown keyword argument(s) in target rustxx: prelink, pic, rust_abi.\n    src/meson.build:12:10: ERROR: Fatal warnings enabled, aborting\n\nI haven't yet found a time to look into it more in depth, and assume\nthat it's fixed in more recent versions of Meson.\n\nPatrick\n"},{"id":"525775","messageId":"aL56xRcJTCU2wttG@pks.im","threadId":"64091","inReplyTo":"CABPp-BGF9Ds=9bLKbWFEuatGmGycemwTMiyez_s3XMJR=M6xQw@mail.gmail.com","subject":"Re: [PATCH RFC v2 1/7] meson: add infrastructure to build internal Rust library","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-08T06:42:13Z","receivedAt":"2025-09-08T06:42:20Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Sat, Sep 06, 2025 at 09:54:18PM -0700, Elijah Newren wrote:\n> On Fri, Sep 5, 2025 at 4:51 AM Patrick Steinhardt <ps@pks.im> wrote:\n> >\n> > Add the infrastructure into Meson to build an internal Rust library.\n> > Building the Rust parts of Git are for now entirely optional, as they\n> > are mostly intended as a test balloon for both Git developers, but also\n> > for distributors of Git. So for now, they may contain:\n> >\n> >   - New features that are not mission critical to Git and that users can\n> >     easily live without.\n> >\n> >   - Alternative implementations of small subsystems.\n> >\n> > If these test balloons are successful, we will eventually make Rust a\n> > mandatory dependency for our build process in Git 3.0.\n> \n> Okay.\n> \n> > The availability of a Rust toolchain will be auto-detected by Meson at\n> > setup time. This behaviour can be tweaked via the `-Drust=` feature\n> > toggle.\n> \n> This goes against what you said above, because it turns it into\n> something other than a test balloon.  As I've said elsewhere, I don't\n> think this part is helpful; it reduces the amount of notice that\n> distributors and platforms have about our intent to make Rust\n> mandatory.\n\nSee the BreakingChanges document later in this series, which talks about\nthis. Makes me wonder whether I should reverse the order of patches so\nthat the BreakingChanges are more prominent.\n\n> > diff --git a/src/meson.build b/src/meson.build\n> > new file mode 100644\n> > index 00000000000..eb752651d35\n> > --- /dev/null\n> > +++ b/src/meson.build\n> > @@ -0,0 +1,15 @@\n> > +libgit_rs = static_library('git_rs',\n> > +  sources: [\n> > +    'lib.rs',\n> > +  ],\n> > +  rust_crate_type: 'staticlib',\n> > +)\n> > +libgit_libraries += libgit_rs\n> > +\n> > +# The 'rust' module was only introduced in Meson 1.0. Furthermore, the module\n> > +# does not seem to work on macOS as expected right now. As such, we only\n> > +# conditionally enable tests.\n> > +if meson.version().version_compare('>=1.0.0') and host_machine.system() != 'darwin'\n> > +  rustmod = import('rust')\n> > +  rustmod.test('rust', libgit_rs)\n> > +endif\n> \n> Would it make sense to invoke 'cargo test' as one step of 'meson test'\n> on mac as an alternative, so that mac users also can run the tests?\n\nMaybe. I'll revisit the Meson code anyway to figure out how to get Cargo\nsupport in there natively.\n\nPatrick\n"},{"id":"525776","messageId":"aL561B_js3l_FGqD@pks.im","threadId":"64091","inReplyTo":"9fcda14f-d4d4-4db4-ae77-d9408bfae035@gentoo.org","subject":"Re: [PATCH RFC v2 5/7] BreakingChanges: announce Rust becoming mandatory","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-08T06:42:28Z","receivedAt":"2025-09-08T06:42:36Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Fri, Sep 05, 2025 at 10:38:16AM -0400, Eli Schwartz wrote:\n> On 9/5/25 9:38 AM, Patrick Steinhardt wrote:\n> \n> >> Do we want to commit to promising support until gccrs is ready? What if\n> >> gccrs ends up abandoned? Or takes an unexpectedly long time to reach a stage\n> >> where it can build Git? It might make sense to give this LTS release a time\n> >> limit instead, or in addidtion.\n> > \n> > Yeah, I wasn't quite clear on that one, either. An alternative:\n> > \n> >   - We will maintain the LTS release for 8 release cycles, which equates\n> >     to roughly two years. It sounds like a lot, but recent security\n> >     releases have stretched quite far into the past.\n> > \n> >   - If there are still dependents after these two years we will hand\n> >     over maintainership of the LTS branch to dependents. So they will be\n> >     responsible for the backporting.\n> > \n> > This really only is a suggestion though. I'm especially waiting for\n> > Junio's feedback here to see whether he thinks that this is a reasonable\n> > thing to do.\n> \n> \n> This seems reasonable to me -- people who still need that LTS should be\n> allowed to ensure it still works, and be expected to commit to the bit\n> -- but with the emphasis that I would consider it absolutely mandatory\n> that the git project accepts to host that branch, and it won't just\n> exist in some other shadowy corner of the internet.\n\nOh, yes, that's what I meant to imply. We hand over maintainership, but\nit should ultimately still be sent to the Git mailing list, have proper\nreviews and be merged by Junio.\n\nI'll reword this accordingly.\n\nPatrick\n"},{"id":"525777","messageId":"aL563ZzHK-43YeCi@pks.im","threadId":"64091","inReplyTo":"CABPp-BFw-Oqp71jW5SYCKYOWtjWFSQPOsUVWdF7EnzftwAR2vw@mail.gmail.com","subject":"Re: [PATCH RFC v2 5/7] BreakingChanges: announce Rust becoming mandatory","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-08T06:42:37Z","receivedAt":"2025-09-08T06:42:45Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Sat, Sep 06, 2025 at 10:31:07PM -0700, Elijah Newren wrote:\n> On Fri, Sep 5, 2025 at 6:38 AM Patrick Steinhardt <ps@pks.im> wrote:\n> >\n> > On Fri, Sep 05, 2025 at 02:45:46PM +0200, Matthias Aßhauer wrote:\n> \n> > > Do we want to commit to promising support until gccrs is ready? What if\n> > > gccrs ends up abandoned? Or takes an unexpectedly long time to reach a stage\n> > > where it can build Git? It might make sense to give this LTS release a time\n> > > limit instead, or in addidtion.\n> >\n> > Yeah, I wasn't quite clear on that one, either. An alternative:\n> >\n> >   - We will maintain the LTS release for 8 release cycles, which equates\n> >     to roughly two years. It sounds like a lot, but recent security\n> >     releases have stretched quite far into the past.\n> >\n> >   - If there are still dependents after these two years we will hand\n> >     over maintainership of the LTS branch to dependents. So they will be\n> >     responsible for the backporting.\n> >\n> > This really only is a suggestion though. I'm especially waiting for\n> > Junio's feedback here to see whether he thinks that this is a reasonable\n> > thing to do.\n> \n> Over at https://lore.kernel.org/git/xmqqplc43o7c.fsf@gitster.g/, Junio\n> said multiple years isn't something he's willing to promise, but\n> suggests 18 months might be doable.\n> \n> I have a suspicion that if you want a promised level of support,\n> you'll not only get something less than what distributors want, but\n> something far less than we'll provide in practice.  I'm curious if the\n> alternative wording over at\n> https://lore.kernel.org/git/CABPp-BG3Zcw63vNziy86MvYNubefn1SmPvXefpqpA=a+42KT8A@mail.gmail.com/\n> is more likely to be realistic:\n> \n> \"We'll weigh the severity of each security issue and the cost to\n> backport and give the last C-only version significant extra weight in\n> our considerations\"\n> \n> I know it may not be what distributors want, but overpromising also\n> has deleterious effects, so...\n\nI think at least for the security releases we should promise to handle\nthose. I do not think it's sensible to have a release branch that is\nstill officially supported, but that contains known vulnerabilities.\n\nHistorically this wasn't too much of a problem, either. We always aim to\nkeep security fixes as minimal as possible, which also helps with the\nbackporting process. Our last security release for example even spanned\nover 8 releases, so if that's anything to go by we even underpromise :)\n\nPatrick\n"},{"id":"525778","messageId":"aL57ONmEKTmqFhIZ@pks.im","threadId":"64091","inReplyTo":"CABPp-BGpdEP9+CTApknmGNO=b=66bFKVzWL2s3gmgCMtTBTjPA@mail.gmail.com","subject":"Re: [PATCH RFC v2 0/7] Introduce Rust and announce that it will become mandatorty","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-08T06:44:08Z","receivedAt":"2025-09-08T06:44:18Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Sat, Sep 06, 2025 at 09:31:02PM -0700, Elijah Newren wrote:\n> On Fri, Sep 5, 2025 at 7:29 AM Patrick Steinhardt <ps@pks.im> wrote:\n> > > It looks like this version does include the necessary Makefile changes which\n> > > is great. I do think though, that for the test balloon to be valuable, we\n> > > need make building with rust the default with an error message that tells\n> > > people how to build without rust if that fails. Otherwise it is easy for\n> > > people building on platforms without rust support to miss that we're going\n> > > to be making it mandatory soon.\n> >\n> > I have a plan layed out in the BreakingChanges document that mentions\n> > how I'm proposing to do the transition:\n> >\n> >   1. We introduce it with auto-detection for Meson and default-disabled\n> >      for our Makefile in Git 2.52.\n> >\n> >   2. We enable Rust by default in case WITH_BREAKING_CHANGES is enabled\n> >      in Git 2.53.\n> >\n> >   3. We always enable Rust by default in Git 2.54.\n> \n> I don't see how steps 1 & 2 help at all.  We now know we want to make\n> Rust mandatory eventually, and should provide distributors and\n> platforms as much notice as possible so they are aware.  But what\n> you've proposed is another libgit-rs or libgit-sys -- an optional\n> component that no one will know about unless they go looking for it.\n> I don't see how those two steps provide any incremental help to\n> anybody over what libgit-rs and libgit-sys have done.  From my point\n> of view, Rust should be enabled by default in Git 2.52, with a simple\n> knob provided to let distributors/platforms/users turn it off and\n> build without it.\n\nIt helps because it allows us to slowly build out the infrastructure. We\ndon't yet need answers to every question that we currently have if we\ninitially have the Rust infra default-disabled.\n\nI very much expect that there'll be some issues with our initial first\nsteps. So I'd rather want to avoid to expose developers or distros to\nthese issues directly, because that might train them to immediately\ndisable Rust right from the start.\n\n> >   4. We unconditionally enable Rust in Git 3.0.\n> >\n> > This is basically gradually tightening the screws, which both gives us\n> > time to build the infra and gives downstream time to become aware of the\n> > change and adapt.\n> >\n> > I think making it mandatory in Git 3.0 makes sense because I also\n> > propose to make the last version without mandatory Rust be an LTS\n> > version. And if we connect that with it being the last version before\n> > 3.0 I think that's an additional benefit, as there will be other\n> > breaking changes in 3.0.\n> >\n> > In the end it kind of hinges on when we think we want to release Git\n> > 3.0. If we can agree on the above plan, we could also think about making\n> > Git 2.55 become 3.0 instead. That'd be in a bit less than a year from\n> > now, which I think is a good timeframe for that breaking release. I\n> > personally don't see a reason to push it out into the future for way\n> > longer than that, and it would be good anyway if we built some consensus\n> > around its release date.\n> \n> I see your plan, but I agree with Phillip that I don't see why it\n> makes sense to lump the Rust transition with the 3.0 transition.\n\nI don't necessarily think we need to do it with 3.0, agreed. But as\nJunio mentioned [1], 6 months feels too short for him to make Rust\nmandatory, so we're realistically looking at a period of at least one\nyear to make this happen.\n\nSo it felt like a good match to tie these two together. The primary\nmotivation is that other breaking changes that we introduce with 3.0 may\ncause minor inconveniences, as well. So that means that we help not only\nnon-Rust platforms with the proposed LTS release, but also potentially\nothers.\n\nThat being said, I really hope that most of the other changes should be\nrather uneventful. I don't want to create a Python 3-style split.\n\n> Setting that aside for a moment, the idea of Git 2.55 becoming 3.0\n> seems like a good idea to me, assuming that doesn't rush brian on the\n> sha1/sha256 interop (since I think that's probably the paramount\n> feature of 3.0).\n\nYeah, the interop is definitely an important factor and the last part\nthat I think is still missing for Git 3.0 to become viable.\n\nPatrick\n"},{"id":"525779","messageId":"aL57QdS2DAFUOgsl@pks.im","threadId":"64091","inReplyTo":"8A7DBC60-286A-48FE-A3D3-CAFC11FD3AEA@gmail.com","subject":"Re: [PATCH RFC 2/3] rust: implement a test balloon via the \"varint\" subsystem","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-08T06:44:17Z","receivedAt":"2025-09-08T06:44:25Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Sun, Sep 07, 2025 at 04:07:17PM -0400, Ben Knoble wrote:\n> > diff --git a/src/varint.rs b/src/varint.rs\n> > new file mode 100644\n> > index 00000000000..3d41760a555\n> > --- /dev/null\n> > +++ b/src/varint.rs\n> > @@ -0,0 +1,92 @@\n> > +use std::os::raw::c_int;\n> > +use std::os::raw::c_uchar;\n> > +\n> > +#[no_mangle]\n> > +pub unsafe extern \"C\" fn decode_varint(bufp: *mut *const c_uchar) -> usize {\n> > +    let mut buf = *bufp;\n> > +    let mut c = *buf;\n> > +    let mut val = usize::from(c & 127);\n> > +\n> > +    buf = buf.add(1);\n> > +\n> > +    while (c & 128) != 0 {\n> > +        val += 1;\n> > +        if val == 0 || val.leading_zeros() < 7 {\n> > +            return 0; // overflow\n> \n> Hm. I thought overflows panic in debug builds, in which case checking\n> afterwards is too late? Does unsafe change that?\n\nI've added a test now and made this an explicit `wrapping_add()`.\n\nPatrick\n"},{"id":"525791","messageId":"aL7Abgdbi0-aIm6Y@pks.im","threadId":"64091","inReplyTo":"xmqq8qipzhg3.fsf@gitster.g","subject":"Re: [PATCH RFC 2/3] rust: implement a test balloon via the \"varint\" subsystem","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-08T11:39:26Z","receivedAt":"2025-09-08T11:39:39Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Sun, Sep 07, 2025 at 09:39:08PM -0700, Junio C Hamano wrote:\n> This is a tangent, but as many people pointed out, calling this a\n> test balloon is misreading.  This is quite different from what we\n> traditionally called a test balloon, where \n> \n>  - we were already fairly sure that the construct is safe, but\n>    wanted to be extra careful to smoke out anybody who has trouble\n>    with it;\n> \n>  - hence we use the construct in question in a place where nobody\n>    can compile it out, hoping that anybody with a system incapable\n>    of handling the construct in question would be broken badly,\n>    reporting the breakage to us;\n> \n>  - this is done with an understanding that even a single \"the\n>    compiler on this this platform with more than dozen thousands\n>    users cannot groke it\" would automatically stop us, causing us to\n>    revert that test balloon code for _everybody_, refraining from\n>    using that construct for _everybody_ until the situation changes.\n> \n> This thing is different at all points.  We are not \"fairlu sure that\n> Rust is safe to use for everybody\"  Far from it.  We are confident\n> that requiring Rust would break known people.  We are doing this not\n> because we intend to stop once we know of folks who would be broken.\n> Far from it.\n\nThat's fair. I still think that this conversion is viable though. The\nmain intent here is to start building the infrastructure for Rust, which\nmay take a bit of iteration to fully get there. And the earlier we start\nwith the process the better, so I think we should go ahead with this\nregardless.\n\nFrom that perspective it still feels like a test balloon to me. The\nintent here is less to figure out whether anything breaks. It's more\nthat we need to have some Rust code in central parts of Git to be able\nto tell whether our Rust infra works in the first place. And it allows\ndownstream packagers to give it a try, as well, so that they can start\nto report any issues with our infra before it becomes mandatory.\n\nI don't mind much whether we want to call it a \"test balloon\" or not.\nBut giving it a name helps, and \"test balloon\" is the closest match and\nI don't really have a better name. If somebody else does I'm happy to\nadapt the wording though.\n\n> It would really be nice to find a niche that can be a new optional\n> feature that is not essential to the functioning of the system\n> implemented in an already modularized part of the system (e.g., an\n> optional merge strategy, diff algorithm, built-in textconv filter, a\n> new ref backend, etc.).  Then we can introduce Rust, knowing that\n> some Rust-challenged systems will not be able to use these optional\n> features.  What Brian mentioned about two-hash interop feature,\n> being only available on Rust-capable systems, could be such an\n> optional feature, and if it can be done that way, that would be very\n> welcome.  If we can have Rust goodness soon enough without making it\n> mandatory in too short a timeframe, that would be ideal.\n\nI feel like this is something we should _also_ do. But for now I'd like\nto continue with \"varint.rs\": it's easy to convert, self-contained and\nallows us to iterate on our tooling while we don't have a better\nsubsystem or feature to convert yet.\n\n> I already said that I find 6 months advance notice to folks on\n> Rust-challenged systems is way too short to be any good.  If the\n> only reason we give advance notice is because we want to make an\n> excuse of cutting them off sooner while being able to say that we\n> gave them advance notice, that may be sufficient.  But if we truly\n> want to help them by giving enough time to them so that they can\n> help their platform themselves, by lobbying, fundraising, or\n> otherwise campaigning to have usable Rust on their system, I really\n> do not think it is sufficient.\n\nYeah, agreed, six months feels insufficient. My current timeline\nsuggests roughly a year before we make it mandatory with 3.0 with\nvarious in-between steps that gradually ease into Rust to alert\npackagers. Which still may not be sufficient, but it should hopefully\nokayish if we also commit to 1.5 years of security fixes.\n\nIn any case, the exact timeline very much is an open discussion point.\n\nPatrick\n"},{"id":"525813","messageId":"20250908-b4-pks-rust-breaking-change-v3-0-1cd7189fed3b@pks.im","threadId":"64091","inReplyTo":"20250904-b4-pks-rust-breaking-change-v1-0-3af1d25e0be9@pks.im","subject":"[PATCH RFC v3 0/8] Introduce Rust and announce that it will become mandatorty","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-08T14:13:07Z","receivedAt":"2025-09-08T14:13:23Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Hi,\n\nthis small patch series introduces Rust into the core of Git. This patch\nseries is designed as a test balloon, similar to how we introduced test\nballoons for C99 features in the past. The goal is threefold:\n\n  - Give us some time to experiment with Rust and introduce proper build\n    infrastructure.\n\n  - Give distributors time to ease into the new toolchain requirements.\n    Introducing Rust is impossible for some platforms and hard for\n    others.\n\n  - Announce that Git 3.0 will make Rust a mandatory part of our build\n    infrastructure.\n\nThe test balloon itself is quite uninteresting: I've chosen to convert\nthe \"varint.c\" subsystem, mostly because it is trivial and does not have\nany dependencies. But it does allow us to verify that C to Rust interop\nworks as expected, and to play around with tooling. All tests pass with\nthe \"varint.rs\" implementation.\n\nFor now, the series only contains support for Meson. If we agree to go\ndown this route I'll also introduce support for Rust into our Makefiles\nat a later point in time.\n\nFurthermore missing is additional tooling:\n\n  - At least one CI job to verify that Rust builds and works as\n    expected.\n\n  - Tooling and CI jobs to ensure that we have consistent formatting via\n    `cargo format`.\n\nAnd probably lots more. As said, the entire goal is for us to have an\neasy playground that we can experiment on and develop the infrastructure\nincrementally without yet having to commit to anything.\n\nI'm mostly splitting out the topic of introducing Rust from the larger\nseries that introduce it into xdiff so that we can focus more on the\nactual process of introducing Rust into Git and less on the potential\nfeatures that we want to build on top of it.\n\nChanges in v2:\n  - Introduce support for building the Rust library via our Makefile.\n  - Introduce a '-DWITH_RUST' define. This define is used to print\n    whether or not Git is built with Rust via `git version\n    --build-options`.\n  - Adjust Meson to not depend on v1.9.0 and newer anymore.\n  - Introduce a roadmap into our BreakingChanges document to explain how\n    we'll iterate towards mandatory Rust support.\n  - Rework the Fedora job to do a full compile-and-test run with Meson\n    and breaking changes enabled.\n  - Adapt our breaking-changes jobs to enable Rust support.\n  - Link to v1: https://lore.kernel.org/r/20250904-b4-pks-rust-breaking-change-v1-0-3af1d25e0be9@pks.im\n\nChanges in v3:\n  - Reorder all uses of `WITH_RUST` after the include of \"config.mak\".\n  - Add a test to verify overflow behaviour in Rust and explicitly use\n    `add_wrapping()`.\n  - Use explicit dependencies for the Rust library in our Makefile.\n  - Fix Alma Linux CI job.\n  - Stop tying maintenance of our LTS release to the availability of\n    gcc-rs.\n  - Add a fallback to Meson to use cargo directly.\n  - I've fixed the Rust edition to 2018 for now. This is intentionally\n    conservative so that we might be able to use Rust 1.49. For now, we\n    don't have any reason to use a newer edition, either. So let's take\n    the oldest version we can live with for now and then bump it as\n    required.\n  - Link to v2: https://lore.kernel.org/r/20250905-b4-pks-rust-breaking-change-v2-0-6939cbf4a0b8@pks.im\n\nThanks!\n\nPatrick\n\n---\nPatrick Steinhardt (8):\n      meson: add infrastructure to build internal Rust library\n      Makefile: reorder sources after includes\n      Makefile: introduce infrastructure to build internal Rust library\n      help: report on whether or not Rust is enabled\n      rust: implement a test balloon via the \"varint\" subsystem\n      BreakingChanges: announce Rust becoming mandatory\n      ci: convert \"pedantic\" job into full build with breaking changes\n      ci: enable Rust for breaking-changes jobs\n\n .github/workflows/main.yml         |   4 +-\n .gitignore                         |   1 +\n .gitlab-ci.yml                     |   4 +-\n Cargo.lock                         |  22 ++++\n Cargo.toml                         |   9 ++\n Documentation/BreakingChanges.adoc |  41 +++++++\n Makefile                           | 214 ++++++++++++++++++++++---------------\n ci/install-dependencies.sh         |   8 +-\n ci/run-build-and-tests.sh          |  31 ++----\n help.c                             |   6 ++\n meson.build                        |  24 ++++-\n meson_options.txt                  |   2 +\n shared.mak                         |   1 +\n src/lib.rs                         |   1 +\n src/meson.build                    |  64 +++++++++++\n src/varint.rs                      |  95 ++++++++++++++++\n 16 files changed, 411 insertions(+), 116 deletions(-)\n\nRange-diff versus v2:\n\n1:  3792d2518c < -:  ---------- meson: add infrastructure to build internal Rust library\n-:  ---------- > 1:  d995aef28c meson: add infrastructure to build internal Rust library\n-:  ---------- > 2:  610e97e435 Makefile: reorder sources after includes\n2:  9c3a78cb1e ! 3:  8b6251d4d2 Makefile: introduce infrastructure to build internal Rust library\n    @@ .gitignore\n     @@\n      /fuzz_corpora\n     +/target/\n    -+/Cargo.lock\n      /GIT-BUILD-DIR\n      /GIT-BUILD-OPTIONS\n      /GIT-CFLAGS\n     \n    - ## Cargo.toml (new) ##\n    -@@\n    -+[package]\n    -+name = \"git\"\n    -+version = \"0.1.0\"\n    -+edition = \"2021\"\n    -+\n    -+[lib]\n    -+crate-type = [\"staticlib\"]\n    -+\n    -+[dependencies]\n    -\n      ## Makefile ##\n     @@ Makefile: include shared.mak\n      # Define LIBPCREDIR=/foo/bar if your PCRE header and library files are\n    @@ Makefile: include shared.mak\n      # == SHA-1 and SHA-256 defines ==\n      #\n      # === SHA-1 backend ===\n    +@@ Makefile: OBJECTS =\n    + OTHER_PROGRAMS =\n    + PROGRAM_OBJS =\n    + PROGRAMS =\n    ++RUST_SOURCES =\n    + EXCLUDED_PROGRAMS =\n    + SCRIPT_PERL =\n    + SCRIPT_PYTHON =\n     @@ Makefile: TEST_SHELL_PATH = $(SHELL_PATH)\n      LIB_FILE = libgit.a\n      XDIFF_LIB = xdiff/lib.a\n    @@ Makefile: TEST_SHELL_PATH = $(SHELL_PATH)\n     +RUST_LIB = target/release/libgit.a\n     +endif\n      \n    - GENERATED_H += command-list.h\n    - GENERATED_H += config-list.h\n    -@@ Makefile: CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/unit-test.o\n    - \n    - UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o\n    - \n    --# xdiff and reftable libs may in turn depend on what is in libgit.a\n    --GITLIBS = common-main.o $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(LIB_FILE)\n    -+GITLIBS = common-main.o $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB)\n    -+ifdef WITH_RUST\n    -+GITLIBS += $(RUST_LIB)\n    -+endif\n    -+# Other libs may in turn depend on what is in libgit.a.\n    -+GITLIBS += $(LIB_FILE)\n    - EXTLIBS =\n    - \n    - GIT_USER_AGENT = git/$(GIT_VERSION)\n    + # xdiff and reftable libs may in turn depend on what is in libgit.a\n    + GITLIBS = common-main.o $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(LIB_FILE)\n     @@ Makefile: BASIC_LDFLAGS =\n      ARFLAGS = rcs\n      PTHREAD_CFLAGS =\n    @@ Makefile: BASIC_LDFLAGS =\n     +CARGO_ARGS += --release\n     +endif\n     +\n    + # For the 'sparse' target\n    + SPARSE_FLAGS ?= -std=gnu99 -D__STDC_NO_VLA__\n    + SP_EXTRA_FLAGS =\n    +@@ Makefile: CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/unit-test.o\n    + \n    + UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o\n    + \n    ++RUST_SOURCES += src/lib.rs\n    ++\n    + GIT-VERSION-FILE: FORCE\n    + \t@OLD=$$(cat $@ 2>/dev/null || :) && \\\n    + \t$(call version_gen,\"$(shell pwd)\",GIT-VERSION-FILE.in,$@) && \\\n    +@@ Makefile: endif\n    + ALL_CFLAGS = $(DEVELOPER_CFLAGS) $(CPPFLAGS) $(CFLAGS) $(CFLAGS_APPEND)\n    + ALL_LDFLAGS = $(LDFLAGS) $(LDFLAGS_APPEND)\n    + \n     +ifdef WITH_RUST\n     +BASIC_CFLAGS += -DWITH_RUST\n    ++GITLIBS += $(RUST_LIB)\n     +endif\n     +\n    - # For the 'sparse' target\n    - SPARSE_FLAGS ?= -std=gnu99 -D__STDC_NO_VLA__\n    - SP_EXTRA_FLAGS =\n    + ifdef SANITIZE\n    + SANITIZERS := $(foreach flag,$(subst $(comma),$(space),$(SANITIZE)),$(flag))\n    + BASIC_CFLAGS += -fsanitize=$(SANITIZE) -fno-sanitize-recover=$(SANITIZE)\n     @@ Makefile: scalar$X: scalar.o GIT-LDFLAGS $(GITLIBS)\n      $(LIB_FILE): $(LIB_OBJS)\n      \t$(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^\n      \n    -+$(RUST_LIB): FORCE\n    -+\t@OLD_STAT=\"$$(stat $@ 2>/dev/null)\"; \\\n    -+\t    cargo build $(CARGO_ARGS); \\\n    -+\t    if test $$? != 0 || test x\"$$OLD_STAT\" != x\"$$(stat $@ 2>/dev/null)\"; then \\\n    -+\t\techo '   ' CARGO $@; \\\n    -+\t    fi\n    ++$(RUST_LIB): Cargo.toml $(RUST_SOURCES)\n    ++\t$(QUIET_CARGO)cargo build $(CARGO_ARGS)\n     +\n     +.PHONY: rust\n     +rust: $(RUST_LIB)\n    @@ Makefile: clean: profile-clean coverage-clean cocciclean\n      \t$(RM) $(FUZZ_PROGRAMS)\n      \t$(RM) $(SP_OBJ)\n      \t$(RM) $(HCC)\n    -+\t$(RM) -r target/ Cargo.lock\n    ++\t$(RM) -r target/\n      \t$(RM) version-def.h\n      \t$(RM) -r $(dep_dirs) $(compdb_dir) compile_commands.json\n      \t$(RM) $(test_bindir_programs)\n    +\n    + ## shared.mak ##\n    +@@ shared.mak: ifndef V\n    + \tQUIET_MKDIR_P_PARENT  = @echo '   ' MKDIR -p $(@D);\n    + \n    + ## Used in \"Makefile\"\n    ++\tQUIET_CARGO    = @echo '   ' CARGO $@;\n    + \tQUIET_CC       = @echo '   ' CC $@;\n    + \tQUIET_AR       = @echo '   ' AR $@;\n    + \tQUIET_LINK     = @echo '   ' LINK $@;\n3:  d83c8c2b14 = 4:  0335ff2303 help: report on whether or not Rust is enabled\n4:  f9dd2ecb73 ! 5:  318212c5c9 rust: implement a test balloon via the \"varint\" subsystem\n    @@ Makefile: LIB_OBJS += urlmatch.o\n      LIB_OBJS += version.o\n      LIB_OBJS += versioncmp.o\n      LIB_OBJS += walker.o\n    +@@ Makefile: CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/unit-test.o\n    + UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o\n    + \n    + RUST_SOURCES += src/lib.rs\n    ++RUST_SOURCES += src/varint.rs\n    + \n    + GIT-VERSION-FILE: FORCE\n    + \t@OLD=$$(cat $@ 2>/dev/null || :) && \\\n     \n      ## meson.build ##\n     @@ meson.build: libgit_sources = [\n    @@ src/lib.rs\n     \n      ## src/meson.build ##\n     @@\n    - libgit_rs = static_library('git_rs',\n    -   sources: [\n    -     'lib.rs',\n    -+    'varint.rs',\n    -   ],\n    -   rust_crate_type: 'staticlib',\n    - )\n    + libgit_rs_sources = [\n    +   'lib.rs',\n    ++  'varint.rs',\n    + ]\n    + \n    + if meson.version().version_compare('>=1.5.0')\n     \n      ## src/varint.rs (new) ##\n     @@\n    @@ src/varint.rs (new)\n     +    buf = buf.add(1);\n     +\n     +    while (c & 128) != 0 {\n    -+        val += 1;\n    ++        val = val.wrapping_add(1);\n     +        if val == 0 || val.leading_zeros() < 7 {\n     +            return 0; // overflow\n     +        }\n    @@ src/varint.rs (new)\n     +            assert_eq!(decode_varint(&mut [0x80, 0x00].as_slice().as_ptr()), 128);\n     +            assert_eq!(decode_varint(&mut [0x80, 0x01].as_slice().as_ptr()), 129);\n     +            assert_eq!(decode_varint(&mut [0x80, 0x7f].as_slice().as_ptr()), 255);\n    ++\n    ++            // Overflows are expected to return 0.\n    ++            assert_eq!(decode_varint(&mut [0x88; 16].as_slice().as_ptr()), 0);\n     +        }\n     +    }\n     +\n5:  5d411a195f ! 6:  a540626932 BreakingChanges: announce Rust becoming mandatory\n    @@ Commit message\n         Rust is a major change though and has ramifications for the whole\n         ecosystem:\n     \n    -      - Some platforms haven't yet been able to implement a Rust toolchain,\n    -        even though it is possible in theory.\n    +      - Some platforms have a Rust toolchain available, but have not yet\n    +        integrated it into their build infrastructure.\n     \n           - Some platforms don't have any support for Rust at all.\n     \n    @@ Documentation/BreakingChanges.adoc: A prerequisite for this change is that the e\n      JGit, libgit2 and Gitoxide need to support it.\n      \n     +* Git will require Rust as a mandatory part of the build process. While Git\n    -+  already started to adopt Rust in the Git 2.52, all parts written in Rust are\n    ++  already started to adopt Rust in Git 2.52, all parts written in Rust are\n     +  optional for the time being. This includes:\n     ++\n     +  ** Subsystems that have an alternative implementation in Rust to test\n    @@ Documentation/BreakingChanges.adoc: A prerequisite for this change is that the e\n     +for Rust becoming a mandatory part of the build process. There will be multiple\n     +milestones for the introduction of Rust:\n     ++\n    -+1. Initially, with Git 2.52, support for Rust will be auto-detected by Rust and\n    ++1. Initially, with Git 2.52, support for Rust will be auto-detected by Meson and\n     +   disabled in our Makefile so that the project can sort out the initial\n     +   infrastructure.\n    -+2. In Git 2.53, support for Rust will be made mandatory in case Git is compiled\n    -+   with breaking changes. Breaking changes can be enabled for Meson by saying\n    -+   `meson configure -Dbreaking_changes=true` and for Makefiles via `make\n    -+   WITH_BREAKING_CHANGES=YesPlease`. It will still be possible to compile with\n    -+   breaking changes, but explicitly disable Rust.\n    -+3. In Git 2.54, both build systems will default-enable support for Rust so that\n    -+   builds will break if Rust is not available on the build host. The use of Rust\n    -+   can still be explicitly disabled via build flags.\n    ++2. In Git 2.53, support for Rust will be enabled by default in case Git is\n    ++   compiled with breaking changes. Breaking changes can be enabled for Meson by\n    ++   saying `meson configure -Dbreaking_changes=true` and for Makefile-based\n    ++   builds via `make WITH_BREAKING_CHANGES=YesPlease`. It will still be possible\n    ++   to compile with breaking changes, but explicitly disable Rust.\n    ++3. In Git 2.54, both build systems will default-enable support for Rust even\n    ++   when breaking changes aren't enabled. Consequently, builds will break by\n    ++   default if Rust is not available on the build host. The use of Rust can still\n    ++   be explicitly disabled via build flags.\n     +4. In Git 3.0, the build options will be removed and support for Rust is\n     +   mandatory.\n     ++\n    @@ Documentation/BreakingChanges.adoc: A prerequisite for this change is that the e\n     +respectively.\n     ++\n     +The Git project will declare the last version before Git 3.0 to be a long-term\n    -+support release that is maintained until alternate Rust backends like gcc-rs are\n    -+able to build Git. The Git project may need to rely on distributions to help\n    -+with identifying and backporting important bugfixes.\n    ++support release. This long-term release will receive important bug fixes for at\n    ++least four release cycles and security fixes for six release cycles. The Git\n    ++project will hand over maintainership of the long-term release to distributors\n    ++in case they need to extend the life of that long-term release even further. In\n    ++that case, the backporting process will be handled by these distributors, but\n    ++the backported patches will be reviewed on the mailing list and pulled in by the\n    ++Git maintainer.\n     +\n      === Removals\n      \n6:  210225628a ! 7:  d4459e0294 ci: convert \"pedantic\" job into full build with breaking changes\n    @@ .gitlab-ci.yml: test:linux:\n     \n      ## ci/install-dependencies.sh ##\n     @@ ci/install-dependencies.sh: alpine-*)\n    + \t\tbash cvs gnupg perl-cgi perl-dbd-sqlite perl-io-tty >/dev/null\n      \t;;\n      fedora-*|almalinux-*)\n    ++\tcase \"$jobname\" in\n    ++\t*-meson)\n    ++\t\tMESON_DEPS=\"meson ninja\";;\n    ++\tesac\n      \tdnf -yq update >/dev/null &&\n     -\tdnf -yq install shadow-utils sudo make gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel >/dev/null\n    -+\tdnf -yq install shadow-utils sudo meson ninja pkg-config gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel >/dev/null\n    ++\tdnf -yq install shadow-utils sudo make pkg-config gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel $MESON_DEPS >/dev/null\n      \t;;\n      ubuntu-*|i386/ubuntu-*|debian-*)\n      \t# Required so that apt doesn't wait for user input on certain packages.\n7:  e6cc22407f ! 8:  5893f85cee ci: enable Rust for breaking-changes jobs\n    @@ Commit message\n         Signed-off-by: Patrick Steinhardt <ps@pks.im>\n     \n      ## ci/install-dependencies.sh ##\n    -@@ ci/install-dependencies.sh: alpine-*)\n    - \t;;\n    - fedora-*|almalinux-*)\n    +@@ ci/install-dependencies.sh: fedora-*|almalinux-*)\n    + \t\tMESON_DEPS=\"meson ninja\";;\n    + \tesac\n      \tdnf -yq update >/dev/null &&\n    --\tdnf -yq install shadow-utils sudo meson ninja pkg-config gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel >/dev/null\n    -+\tdnf -yq install shadow-utils sudo meson ninja pkg-config gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel rustc >/dev/null\n    +-\tdnf -yq install shadow-utils sudo make pkg-config gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel $MESON_DEPS >/dev/null\n    ++\tdnf -yq install shadow-utils sudo make pkg-config gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel $MESON_DEPS rustc >/dev/null\n      \t;;\n      ubuntu-*|i386/ubuntu-*|debian-*)\n      \t# Required so that apt doesn't wait for user input on certain packages.\n\n---\nbase-commit: 2462961280690837670d997bde64bd4ebf8ae66d\nchange-id: 20250904-b4-pks-rust-breaking-change-7167d9d3e37d\n\n"},{"id":"525814","messageId":"20250908-b4-pks-rust-breaking-change-v3-1-1cd7189fed3b@pks.im","threadId":"64091","inReplyTo":"20250908-b4-pks-rust-breaking-change-v3-0-1cd7189fed3b@pks.im","subject":"[PATCH RFC v3 1/8] meson: add infrastructure to build internal Rust library","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-08T14:13:08Z","receivedAt":"2025-09-08T14:13:27Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Add the infrastructure into Meson to build an internal Rust library.\nBuilding the Rust parts of Git are for now entirely optional, as they\nare mostly intended as a test balloon for both Git developers, but also\nfor distributors of Git. So for now, they may contain:\n\n  - New features that are not mission critical to Git and that users can\n    easily live without.\n\n  - Alternative implementations of small subsystems.\n\nIf these test balloons are successful, we will eventually make Rust a\nmandatory dependency for our build process in Git 3.0.\n\nThe availability of a Rust toolchain will be auto-detected by Meson at\nsetup time. This behaviour can be tweaked via the `-Drust=` feature\ntoggle.\n\nNext to the linkable Rust library, also wire up tests that can be\nexecuted via `meson test`. This allows us to use the native unit testing\ncapabilities of Rust.\n\nNote that the Rust edition is currently set to 2018. This edition is\nsupported by Rust 1.49, which is the target for the upcoming gcc-rs\nbackend. For now we don't use any features of Rust that would require a\nnewer version, so settling on this old version makes sense so that\ngcc-rs may become an alternative backend for compiling Git. If we _do_\nwant to introduce features that were added in more recent editions of\nRust though we should reevaluate that choice.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n Cargo.lock        | 22 +++++++++++++++++++\n Cargo.toml        |  9 ++++++++\n meson.build       | 19 ++++++++++++++++-\n meson_options.txt |  2 ++\n src/lib.rs        |  0\n src/meson.build   | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++\n 6 files changed, 114 insertions(+), 1 deletion(-)\n\ndiff --git a/Cargo.lock b/Cargo.lock\nnew file mode 100644\nindex 00000000000..2b80a01e22a\n--- /dev/null\n+++ b/Cargo.lock\n@@ -0,0 +1,22 @@\n+# This file is automatically @generated by Cargo.\n+# It is not intended for manual editing.\n+# Fix this to version 3. This is required so that older toolchains can still\n+# read the lock file. Furthermore, while an argument could be made that we\n+# should not even commit the \"Cargo.lock\" file in the first place, there's two\n+# reasons to still do so:\n+#\n+#   - It thwarts supply-chain attacks by committing checksums into the\n+#     repository.\n+#\n+#   - It is required by Meson so that it can extract Cargo dependencies.\n+#\n+# Cargo dependencies can be accessed in Meson via:\n+#\n+#   dependency('${package_name}-${package_api_version}-rs')\n+#\n+# E.g. with a dependency \"time-0.3.43\", you would pass \"time-0.3-rs\".\n+version = 3\n+\n+[[package]]\n+name = \"git\"\n+version = \"0.1.0\"\ndiff --git a/Cargo.toml b/Cargo.toml\nnew file mode 100644\nindex 00000000000..b9a41dbc792\n--- /dev/null\n+++ b/Cargo.toml\n@@ -0,0 +1,9 @@\n+[package]\n+name = \"git\"\n+version = \"0.1.0\"\n+edition = \"2018\"\n+\n+[lib]\n+crate-type = [\"staticlib\"]\n+\n+[dependencies]\ndiff --git a/meson.build b/meson.build\nindex e8ec0eca165..3d6601225ba 100644\n--- a/meson.build\n+++ b/meson.build\n@@ -220,7 +220,7 @@ project('git', 'c',\n   # learned to define __STDC_VERSION__ with C11 and later. We thus require\n   # GNU C99 and fall back to C11. Meson only learned to handle the fallback\n   # with version 1.3.0, so on older versions we use GNU C99 unconditionally.\n-  default_options: meson.version().version_compare('>=1.3.0') ? ['c_std=gnu99,c11'] : ['c_std=gnu99'],\n+  default_options: meson.version().version_compare('>=1.3.0') ? ['rust_std=2018', 'c_std=gnu99,c11'] : ['rust_std=2018', 'c_std=gnu99'],\n )\n \n fs = import('fs')\n@@ -1702,6 +1702,22 @@ version_def_h = custom_target(\n )\n libgit_sources += version_def_h\n \n+# Starting with Meson 1.5, it knows to parse the \"Cargo.lock\" file and extract\n+# dependencies from it. So from hereon we don't need Cargo anymore to build\n+# Git.\n+if meson.version().version_compare('>=1.5.0')\n+  rust_available = add_languages('rust', native: false, required: get_option('rust'))\n+else\n+  cargo = find_program('cargo', dirs: program_path, native: true, required: get_option('rust'))\n+  rust_available = cargo.found()\n+endif\n+rust_option = get_option('rust').disable_auto_if(not rust_available)\n+\n+if rust_option.allowed()\n+  subdir('src')\n+  libgit_c_args += '-DWITH_RUST'\n+endif\n+\n libgit = declare_dependency(\n   link_with: static_library('git',\n     sources: libgit_sources,\n@@ -2239,6 +2255,7 @@ summary({\n   'pcre2': pcre2,\n   'perl': perl_features_enabled,\n   'python': target_python.found(),\n+  'rust': rust_option.allowed(),\n }, section: 'Auto-detected features', bool_yn: true)\n \n summary({\ndiff --git a/meson_options.txt b/meson_options.txt\nindex 1668f260a18..143dee9237c 100644\n--- a/meson_options.txt\n+++ b/meson_options.txt\n@@ -71,6 +71,8 @@ option('zlib_backend', type: 'combo', choices: ['auto', 'zlib', 'zlib-ng'], valu\n # Build tweaks.\n option('breaking_changes', type: 'boolean', value: false,\n   description: 'Enable upcoming breaking changes.')\n+option('rust', type: 'feature', value: 'auto',\n+  description: 'Enable building with Rust.')\n option('macos_use_homebrew_gettext', type: 'boolean', value: true,\n   description: 'Use gettext from Homebrew instead of the slightly-broken system-provided one.')\n \ndiff --git a/src/lib.rs b/src/lib.rs\nnew file mode 100644\nindex 00000000000..e69de29bb2d\ndiff --git a/src/meson.build b/src/meson.build\nnew file mode 100644\nindex 00000000000..59e810b4d41\n--- /dev/null\n+++ b/src/meson.build\n@@ -0,0 +1,63 @@\n+libgit_rs_sources = [\n+  'lib.rs',\n+]\n+\n+if meson.version().version_compare('>=1.5.0')\n+  libgit_rs = static_library('git_rs',\n+    sources: libgit_rs_sources,\n+    rust_abi: 'c',\n+  )\n+\n+  # The Rust module does not seem to work on macOS as expected right now. As\n+  # such, we only conditionally enable tests.\n+  if get_option('tests') and host_machine.system() != 'darwin'\n+    rustmod = import('rust')\n+    rustmod.test('rust', libgit_rs)\n+  endif\n+else\n+  cargo_command = [\n+    cargo,\n+    'build',\n+    '--lib',\n+    '--quiet',\n+    '--manifest-path',\n+    meson.project_source_root() / 'Cargo.toml',\n+    '--target-dir',\n+    meson.current_build_dir() / 'target',\n+    # `--out-dir` is unstable, but supported since 2018. It's been recently\n+    # renamed to `--artifact-dir`, but for now both options are supported.\n+    '-Z',\n+    'unstable-options',\n+    '--out-dir',\n+    meson.current_build_dir(),\n+  ]\n+\n+  if get_option('buildtype') == 'release'\n+    cargo_command += '--release'\n+  endif\n+\n+  libgit_rs = custom_target('git_rs',\n+    input: libgit_rs_sources + [\n+      meson.project_source_root() / 'Cargo.lock',\n+      meson.project_source_root() / 'Cargo.toml',\n+    ],\n+    output: 'libgit.a',\n+    command: cargo_command,\n+  )\n+\n+  if get_option('tests')\n+    test('rust', cargo,\n+      args: [\n+        'test',\n+        '--manifest-path',\n+        meson.project_source_root() / 'Cargo.toml',\n+        '--target-dir',\n+        meson.current_build_dir() / 'target',\n+      ],\n+      timeout: 0,\n+      protocol: 'rust',\n+    )\n+  endif\n+endif\n+\n+libgit_dependencies += declare_dependency(link_with: libgit_rs)\n\n-- \n2.51.0.417.g1ba7204a04.dirty\n\n"},{"id":"525815","messageId":"20250908-b4-pks-rust-breaking-change-v3-2-1cd7189fed3b@pks.im","threadId":"64091","inReplyTo":"20250908-b4-pks-rust-breaking-change-v3-0-1cd7189fed3b@pks.im","subject":"[PATCH RFC v3 2/8] Makefile: reorder sources after includes","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-08T14:13:09Z","receivedAt":"2025-09-08T14:13:29Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"In an upcoming change we'll make some of the sources compile\nconditionally based on whether or not `WITH_RUST` is defined. To let\ndevelopers specify that flag in their \"config.mak\" we'll thus have to\nreorder our sources so that they come after the include of that file.\n\nDo so.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n Makefile | 176 +++++++++++++++++++++++++++++++--------------------------------\n 1 file changed, 88 insertions(+), 88 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 555b7f4dc3..7e52625d75 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -919,6 +919,94 @@ LIB_FILE = libgit.a\n XDIFF_LIB = xdiff/lib.a\n REFTABLE_LIB = reftable/libreftable.a\n \n+# xdiff and reftable libs may in turn depend on what is in libgit.a\n+GITLIBS = common-main.o $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(LIB_FILE)\n+EXTLIBS =\n+\n+GIT_USER_AGENT = git/$(GIT_VERSION)\n+\n+ifeq ($(wildcard sha1collisiondetection/lib/sha1.h),sha1collisiondetection/lib/sha1.h)\n+DC_SHA1_SUBMODULE = auto\n+endif\n+\n+# Set CFLAGS, LDFLAGS and other *FLAGS variables. These might be\n+# tweaked by config.* below as well as the command-line, both of\n+# which'll override these defaults.\n+# Older versions of GCC may require adding \"-std=gnu99\" at the end.\n+CFLAGS = -g -O2 -Wall\n+LDFLAGS =\n+CC_LD_DYNPATH = -Wl,-rpath,\n+BASIC_CFLAGS = -I.\n+BASIC_LDFLAGS =\n+\n+# library flags\n+ARFLAGS = rcs\n+PTHREAD_CFLAGS =\n+\n+# For the 'sparse' target\n+SPARSE_FLAGS ?= -std=gnu99 -D__STDC_NO_VLA__\n+SP_EXTRA_FLAGS =\n+\n+# For informing GIT-BUILD-OPTIONS of the SANITIZE=leak,address targets\n+SANITIZE_LEAK =\n+SANITIZE_ADDRESS =\n+\n+# For the 'coccicheck' target\n+SPATCH_INCLUDE_FLAGS = --all-includes\n+SPATCH_FLAGS =\n+SPATCH_TEST_FLAGS =\n+\n+# If *.o files are present, have \"coccicheck\" depend on them, with\n+# COMPUTE_HEADER_DEPENDENCIES this will speed up the common-case of\n+# only needing to re-generate coccicheck results for the users of a\n+# given API if it's changed, and not all files in the project. If\n+# COMPUTE_HEADER_DEPENDENCIES=no this will be unset too.\n+SPATCH_USE_O_DEPENDENCIES = YesPlease\n+\n+# Set SPATCH_CONCAT_COCCI to concatenate the contrib/cocci/*.cocci\n+# files into a single contrib/cocci/ALL.cocci before running\n+# \"coccicheck\".\n+#\n+# Pros:\n+#\n+# - Speeds up a one-shot run of \"make coccicheck\", as we won't have to\n+#   parse *.[ch] files N times for the N *.cocci rules\n+#\n+# Cons:\n+#\n+# - Will make incremental development of *.cocci slower, as\n+#   e.g. changing strbuf.cocci will re-run all *.cocci.\n+#\n+# - Makes error and performance analysis harder, as rules will be\n+#   applied from a monolithic ALL.cocci, rather than\n+#   e.g. strbuf.cocci. To work around this either undefine this, or\n+#   generate a specific patch, e.g. this will always use strbuf.cocci,\n+#   not ALL.cocci:\n+#\n+#\tmake contrib/coccinelle/strbuf.cocci.patch\n+SPATCH_CONCAT_COCCI = YesPlease\n+\n+# Rebuild 'coccicheck' if $(SPATCH), its flags etc. change\n+TRACK_SPATCH_DEFINES =\n+TRACK_SPATCH_DEFINES += $(SPATCH)\n+TRACK_SPATCH_DEFINES += $(SPATCH_INCLUDE_FLAGS)\n+TRACK_SPATCH_DEFINES += $(SPATCH_FLAGS)\n+TRACK_SPATCH_DEFINES += $(SPATCH_TEST_FLAGS)\n+GIT-SPATCH-DEFINES: FORCE\n+\t@FLAGS='$(TRACK_SPATCH_DEFINES)'; \\\n+\t    if test x\"$$FLAGS\" != x\"`cat GIT-SPATCH-DEFINES 2>/dev/null`\" ; then \\\n+\t\techo >&2 \"    * new spatch flags\"; \\\n+\t\techo \"$$FLAGS\" >GIT-SPATCH-DEFINES; \\\n+            fi\n+\n+include config.mak.uname\n+-include config.mak.autogen\n+-include config.mak\n+\n+ifdef DEVELOPER\n+include config.mak.dev\n+endif\n+\n GENERATED_H += command-list.h\n GENERATED_H += config-list.h\n GENERATED_H += hook-list.h\n@@ -1387,94 +1475,6 @@ CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/unit-test.o\n \n UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o\n \n-# xdiff and reftable libs may in turn depend on what is in libgit.a\n-GITLIBS = common-main.o $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(LIB_FILE)\n-EXTLIBS =\n-\n-GIT_USER_AGENT = git/$(GIT_VERSION)\n-\n-ifeq ($(wildcard sha1collisiondetection/lib/sha1.h),sha1collisiondetection/lib/sha1.h)\n-DC_SHA1_SUBMODULE = auto\n-endif\n-\n-# Set CFLAGS, LDFLAGS and other *FLAGS variables. These might be\n-# tweaked by config.* below as well as the command-line, both of\n-# which'll override these defaults.\n-# Older versions of GCC may require adding \"-std=gnu99\" at the end.\n-CFLAGS = -g -O2 -Wall\n-LDFLAGS =\n-CC_LD_DYNPATH = -Wl,-rpath,\n-BASIC_CFLAGS = -I.\n-BASIC_LDFLAGS =\n-\n-# library flags\n-ARFLAGS = rcs\n-PTHREAD_CFLAGS =\n-\n-# For the 'sparse' target\n-SPARSE_FLAGS ?= -std=gnu99 -D__STDC_NO_VLA__\n-SP_EXTRA_FLAGS =\n-\n-# For informing GIT-BUILD-OPTIONS of the SANITIZE=leak,address targets\n-SANITIZE_LEAK =\n-SANITIZE_ADDRESS =\n-\n-# For the 'coccicheck' target\n-SPATCH_INCLUDE_FLAGS = --all-includes\n-SPATCH_FLAGS =\n-SPATCH_TEST_FLAGS =\n-\n-# If *.o files are present, have \"coccicheck\" depend on them, with\n-# COMPUTE_HEADER_DEPENDENCIES this will speed up the common-case of\n-# only needing to re-generate coccicheck results for the users of a\n-# given API if it's changed, and not all files in the project. If\n-# COMPUTE_HEADER_DEPENDENCIES=no this will be unset too.\n-SPATCH_USE_O_DEPENDENCIES = YesPlease\n-\n-# Set SPATCH_CONCAT_COCCI to concatenate the contrib/cocci/*.cocci\n-# files into a single contrib/cocci/ALL.cocci before running\n-# \"coccicheck\".\n-#\n-# Pros:\n-#\n-# - Speeds up a one-shot run of \"make coccicheck\", as we won't have to\n-#   parse *.[ch] files N times for the N *.cocci rules\n-#\n-# Cons:\n-#\n-# - Will make incremental development of *.cocci slower, as\n-#   e.g. changing strbuf.cocci will re-run all *.cocci.\n-#\n-# - Makes error and performance analysis harder, as rules will be\n-#   applied from a monolithic ALL.cocci, rather than\n-#   e.g. strbuf.cocci. To work around this either undefine this, or\n-#   generate a specific patch, e.g. this will always use strbuf.cocci,\n-#   not ALL.cocci:\n-#\n-#\tmake contrib/coccinelle/strbuf.cocci.patch\n-SPATCH_CONCAT_COCCI = YesPlease\n-\n-# Rebuild 'coccicheck' if $(SPATCH), its flags etc. change\n-TRACK_SPATCH_DEFINES =\n-TRACK_SPATCH_DEFINES += $(SPATCH)\n-TRACK_SPATCH_DEFINES += $(SPATCH_INCLUDE_FLAGS)\n-TRACK_SPATCH_DEFINES += $(SPATCH_FLAGS)\n-TRACK_SPATCH_DEFINES += $(SPATCH_TEST_FLAGS)\n-GIT-SPATCH-DEFINES: FORCE\n-\t@FLAGS='$(TRACK_SPATCH_DEFINES)'; \\\n-\t    if test x\"$$FLAGS\" != x\"`cat GIT-SPATCH-DEFINES 2>/dev/null`\" ; then \\\n-\t\techo >&2 \"    * new spatch flags\"; \\\n-\t\techo \"$$FLAGS\" >GIT-SPATCH-DEFINES; \\\n-            fi\n-\n-include config.mak.uname\n--include config.mak.autogen\n--include config.mak\n-\n-ifdef DEVELOPER\n-include config.mak.dev\n-endif\n-\n GIT-VERSION-FILE: FORCE\n \t@OLD=$$(cat $@ 2>/dev/null || :) && \\\n \t$(call version_gen,\"$(shell pwd)\",GIT-VERSION-FILE.in,$@) && \\\n\n-- \n2.51.0.417.g1ba7204a04.dirty\n\n"},{"id":"525816","messageId":"20250908-b4-pks-rust-breaking-change-v3-3-1cd7189fed3b@pks.im","threadId":"64091","inReplyTo":"20250908-b4-pks-rust-breaking-change-v3-0-1cd7189fed3b@pks.im","subject":"[PATCH RFC v3 3/8] Makefile: introduce infrastructure to build internal Rust library","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-08T14:13:10Z","receivedAt":"2025-09-08T14:13:31Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Introduce infrastructure to build the internal Rust library. This\nmirrors the infrastructure we have added to Meson in the preceding\ncommit. Developers can enable the infrastructure by passing the new\n`WITH_RUST` build toggle.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n .gitignore |  1 +\n Makefile   | 37 +++++++++++++++++++++++++++++++++++++\n shared.mak |  1 +\n 3 files changed, 39 insertions(+)\n\ndiff --git a/.gitignore b/.gitignore\nindex 1803023427..60c3ba2d97 100644\n--- a/.gitignore\n+++ b/.gitignore\n@@ -1,4 +1,5 @@\n /fuzz_corpora\n+/target/\n /GIT-BUILD-DIR\n /GIT-BUILD-OPTIONS\n /GIT-CFLAGS\ndiff --git a/Makefile b/Makefile\nindex 7e52625d75..94950a0ffe 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -483,6 +483,14 @@ include shared.mak\n # Define LIBPCREDIR=/foo/bar if your PCRE header and library files are\n # in /foo/bar/include and /foo/bar/lib directories.\n #\n+# == Optional Rust support ==\n+#\n+# Define WITH_RUST if you want to include features and subsystems written in\n+# Rust into Git. For now, Rust is still an optional feature of the build\n+# process. With Git 3.0 though, Rust will always be enabled.\n+#\n+# Building Rust code requires Cargo.\n+#\n # == SHA-1 and SHA-256 defines ==\n #\n # === SHA-1 backend ===\n@@ -683,6 +691,7 @@ OBJECTS =\n OTHER_PROGRAMS =\n PROGRAM_OBJS =\n PROGRAMS =\n+RUST_SOURCES =\n EXCLUDED_PROGRAMS =\n SCRIPT_PERL =\n SCRIPT_PYTHON =\n@@ -918,6 +927,11 @@ TEST_SHELL_PATH = $(SHELL_PATH)\n LIB_FILE = libgit.a\n XDIFF_LIB = xdiff/lib.a\n REFTABLE_LIB = reftable/libreftable.a\n+ifdef DEBUG\n+RUST_LIB = target/debug/libgit.a\n+else\n+RUST_LIB = target/release/libgit.a\n+endif\n \n # xdiff and reftable libs may in turn depend on what is in libgit.a\n GITLIBS = common-main.o $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(LIB_FILE)\n@@ -943,6 +957,15 @@ BASIC_LDFLAGS =\n ARFLAGS = rcs\n PTHREAD_CFLAGS =\n \n+# Rust flags\n+CARGO_ARGS =\n+ifndef V\n+CARGO_ARGS += --quiet\n+endif\n+ifndef DEBUG\n+CARGO_ARGS += --release\n+endif\n+\n # For the 'sparse' target\n SPARSE_FLAGS ?= -std=gnu99 -D__STDC_NO_VLA__\n SP_EXTRA_FLAGS =\n@@ -1475,6 +1498,8 @@ CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/unit-test.o\n \n UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o\n \n+RUST_SOURCES += src/lib.rs\n+\n GIT-VERSION-FILE: FORCE\n \t@OLD=$$(cat $@ 2>/dev/null || :) && \\\n \t$(call version_gen,\"$(shell pwd)\",GIT-VERSION-FILE.in,$@) && \\\n@@ -1504,6 +1529,11 @@ endif\n ALL_CFLAGS = $(DEVELOPER_CFLAGS) $(CPPFLAGS) $(CFLAGS) $(CFLAGS_APPEND)\n ALL_LDFLAGS = $(LDFLAGS) $(LDFLAGS_APPEND)\n \n+ifdef WITH_RUST\n+BASIC_CFLAGS += -DWITH_RUST\n+GITLIBS += $(RUST_LIB)\n+endif\n+\n ifdef SANITIZE\n SANITIZERS := $(foreach flag,$(subst $(comma),$(space),$(SANITIZE)),$(flag))\n BASIC_CFLAGS += -fsanitize=$(SANITIZE) -fno-sanitize-recover=$(SANITIZE)\n@@ -2918,6 +2948,12 @@ scalar$X: scalar.o GIT-LDFLAGS $(GITLIBS)\n $(LIB_FILE): $(LIB_OBJS)\n \t$(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^\n \n+$(RUST_LIB): Cargo.toml $(RUST_SOURCES)\n+\t$(QUIET_CARGO)cargo build $(CARGO_ARGS)\n+\n+.PHONY: rust\n+rust: $(RUST_LIB)\n+\n $(XDIFF_LIB): $(XDIFF_OBJS)\n \t$(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^\n \n@@ -3768,6 +3804,7 @@ clean: profile-clean coverage-clean cocciclean\n \t$(RM) $(FUZZ_PROGRAMS)\n \t$(RM) $(SP_OBJ)\n \t$(RM) $(HCC)\n+\t$(RM) -r target/\n \t$(RM) version-def.h\n \t$(RM) -r $(dep_dirs) $(compdb_dir) compile_commands.json\n \t$(RM) $(test_bindir_programs)\ndiff --git a/shared.mak b/shared.mak\nindex 5c7bc94785..0e7492076e 100644\n--- a/shared.mak\n+++ b/shared.mak\n@@ -56,6 +56,7 @@ ifndef V\n \tQUIET_MKDIR_P_PARENT  = @echo '   ' MKDIR -p $(@D);\n \n ## Used in \"Makefile\"\n+\tQUIET_CARGO    = @echo '   ' CARGO $@;\n \tQUIET_CC       = @echo '   ' CC $@;\n \tQUIET_AR       = @echo '   ' AR $@;\n \tQUIET_LINK     = @echo '   ' LINK $@;\n\n-- \n2.51.0.417.g1ba7204a04.dirty\n\n"},{"id":"525817","messageId":"20250908-b4-pks-rust-breaking-change-v3-4-1cd7189fed3b@pks.im","threadId":"64091","inReplyTo":"20250908-b4-pks-rust-breaking-change-v3-0-1cd7189fed3b@pks.im","subject":"[PATCH RFC v3 4/8] help: report on whether or not Rust is enabled","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-08T14:13:11Z","receivedAt":"2025-09-08T14:13:34Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"We're about to introduce support for Rust into the core of Git, where\nsome (trivial) subsystems are converted to Rust. These subsystems will\nalso retain a C implementation though as Rust is not yet mandatory.\nConsequently, it now becomes possible for a Git version to have bugs\nthat are specific to whether or not it is built with Rust support\noverall.\n\nExpose information about whether or not Git was built with Rust via our\nbuild info. This means that both `git version --build-options`, but also\n`git bugreport` will now expose that bit of information. Hopefully, this\nshould make it easier for us to discover any Rust-specific issues.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n help.c | 6 ++++++\n 1 file changed, 6 insertions(+)\n\ndiff --git a/help.c b/help.c\nindex bb20498cfd..5854dd4a7e 100644\n--- a/help.c\n+++ b/help.c\n@@ -791,6 +791,12 @@ void get_version_info(struct strbuf *buf, int show_build_options)\n \t\tstrbuf_addf(buf, \"shell-path: %s\\n\", SHELL_PATH);\n \t\t/* NEEDSWORK: also save and output GIT-BUILD_OPTIONS? */\n \n+#if defined WITH_RUST\n+\t\tstrbuf_addstr(buf, \"rust: enabled\\n\");\n+#else\n+\t\tstrbuf_addstr(buf, \"rust: disabled\\n\");\n+#endif\n+\n \t\tif (fsmonitor_ipc__is_supported())\n \t\t\tstrbuf_addstr(buf, \"feature: fsmonitor--daemon\\n\");\n #if defined LIBCURL_VERSION\n\n-- \n2.51.0.417.g1ba7204a04.dirty\n\n"},{"id":"525818","messageId":"20250908-b4-pks-rust-breaking-change-v3-5-1cd7189fed3b@pks.im","threadId":"64091","inReplyTo":"20250908-b4-pks-rust-breaking-change-v3-0-1cd7189fed3b@pks.im","subject":"[PATCH RFC v3 5/8] rust: implement a test balloon via the \"varint\" subsystem","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-08T14:13:12Z","receivedAt":"2025-09-08T14:13:37Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Implement a trivial test balloon for our Rust build infrastructure by\nreimplementing the \"varint.c\" subsystem in Rust. This subsystem is\nchosen because it is trivial to convert and because it doesn't have any\ndependencies to other components of Git.\n\nIf support for Rust is enabled, we stop compiling \"varint.c\" and instead\ncompile and use \"src/varint.rs\".\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n Makefile        |  3 ++\n meson.build     |  5 ++-\n src/lib.rs      |  1 +\n src/meson.build |  1 +\n src/varint.rs   | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n 5 files changed, 104 insertions(+), 1 deletion(-)\n\ndiff --git a/Makefile b/Makefile\nindex 94950a0ffe2..7640d0d76ac 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -1307,7 +1307,9 @@ LIB_OBJS += urlmatch.o\n LIB_OBJS += usage.o\n LIB_OBJS += userdiff.o\n LIB_OBJS += utf8.o\n+ifndef WITH_RUST\n LIB_OBJS += varint.o\n+endif\n LIB_OBJS += version.o\n LIB_OBJS += versioncmp.o\n LIB_OBJS += walker.o\n@@ -1499,6 +1501,7 @@ CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/unit-test.o\n UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o\n \n RUST_SOURCES += src/lib.rs\n+RUST_SOURCES += src/varint.rs\n \n GIT-VERSION-FILE: FORCE\n \t@OLD=$$(cat $@ 2>/dev/null || :) && \\\ndiff --git a/meson.build b/meson.build\nindex 3d6601225ba..48b80cb832c 100644\n--- a/meson.build\n+++ b/meson.build\n@@ -522,7 +522,6 @@ libgit_sources = [\n   'usage.c',\n   'userdiff.c',\n   'utf8.c',\n-  'varint.c',\n   'version.c',\n   'versioncmp.c',\n   'walker.c',\n@@ -1716,6 +1715,10 @@ rust_option = get_option('rust').disable_auto_if(not rust_available)\n if rust_option.allowed()\n   subdir('src')\n   libgit_c_args += '-DWITH_RUST'\n+else\n+  libgit_sources += [\n+    'varint.c',\n+  ]\n endif\n \n libgit = declare_dependency(\ndiff --git a/src/lib.rs b/src/lib.rs\nindex e69de29bb2d..9da70d8b57d 100644\n--- a/src/lib.rs\n+++ b/src/lib.rs\n@@ -0,0 +1 @@\n+pub mod varint;\ndiff --git a/src/meson.build b/src/meson.build\nindex 59e810b4d41..03b71a5c7bd 100644\n--- a/src/meson.build\n+++ b/src/meson.build\n@@ -1,5 +1,6 @@\n libgit_rs_sources = [\n   'lib.rs',\n+  'varint.rs',\n ]\n \n if meson.version().version_compare('>=1.5.0')\ndiff --git a/src/varint.rs b/src/varint.rs\nnew file mode 100644\nindex 00000000000..7e50cfa09fe\n--- /dev/null\n+++ b/src/varint.rs\n@@ -0,0 +1,95 @@\n+use std::os::raw::c_int;\n+use std::os::raw::c_uchar;\n+\n+#[no_mangle]\n+pub unsafe extern \"C\" fn decode_varint(bufp: *mut *const c_uchar) -> usize {\n+    let mut buf = *bufp;\n+    let mut c = *buf;\n+    let mut val = usize::from(c & 127);\n+\n+    buf = buf.add(1);\n+\n+    while (c & 128) != 0 {\n+        val = val.wrapping_add(1);\n+        if val == 0 || val.leading_zeros() < 7 {\n+            return 0; // overflow\n+        }\n+\n+        c = *buf;\n+        buf = buf.add(1);\n+\n+        val = (val << 7) + usize::from(c & 127);\n+    }\n+\n+    *bufp = buf;\n+    val\n+}\n+\n+#[no_mangle]\n+pub unsafe extern \"C\" fn encode_varint(value: usize, buf: *mut c_uchar) -> c_int {\n+    let mut varint: [u8; 16] = [0; 16];\n+    let mut pos = varint.len() - 1;\n+\n+    varint[pos] = (value & 127) as u8;\n+\n+    let mut value = value >> 7;\n+    while value != 0 {\n+        pos -= 1;\n+        value -= 1;\n+        varint[pos] = 128 | (value & 127) as u8;\n+        value >>= 7;\n+    }\n+\n+    if !buf.is_null() {\n+        std::ptr::copy_nonoverlapping(varint.as_ptr().add(pos), buf, varint.len() - pos);\n+    }\n+\n+    (varint.len() - pos) as c_int\n+}\n+\n+#[cfg(test)]\n+mod tests {\n+    use super::*;\n+\n+    #[test]\n+    fn test_decode_varint() {\n+        unsafe {\n+            assert_eq!(decode_varint(&mut [0x00].as_slice().as_ptr()), 0);\n+            assert_eq!(decode_varint(&mut [0x01].as_slice().as_ptr()), 1);\n+            assert_eq!(decode_varint(&mut [0x7f].as_slice().as_ptr()), 127);\n+            assert_eq!(decode_varint(&mut [0x80, 0x00].as_slice().as_ptr()), 128);\n+            assert_eq!(decode_varint(&mut [0x80, 0x01].as_slice().as_ptr()), 129);\n+            assert_eq!(decode_varint(&mut [0x80, 0x7f].as_slice().as_ptr()), 255);\n+\n+            // Overflows are expected to return 0.\n+            assert_eq!(decode_varint(&mut [0x88; 16].as_slice().as_ptr()), 0);\n+        }\n+    }\n+\n+    #[test]\n+    fn test_encode_varint() {\n+        unsafe {\n+            let mut varint: [u8; 16] = [0; 16];\n+\n+            assert_eq!(encode_varint(0, std::ptr::null_mut()), 1);\n+\n+            assert_eq!(encode_varint(0, varint.as_mut_slice().as_mut_ptr()), 1);\n+            assert_eq!(varint, [0; 16]);\n+\n+            assert_eq!(encode_varint(10, varint.as_mut_slice().as_mut_ptr()), 1);\n+            assert_eq!(varint, [10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n+\n+            assert_eq!(encode_varint(127, varint.as_mut_slice().as_mut_ptr()), 1);\n+            assert_eq!(varint, [127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n+\n+            assert_eq!(encode_varint(128, varint.as_mut_slice().as_mut_ptr()), 2);\n+            assert_eq!(varint, [128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n+\n+            assert_eq!(encode_varint(129, varint.as_mut_slice().as_mut_ptr()), 2);\n+            assert_eq!(varint, [128, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n+\n+            assert_eq!(encode_varint(255, varint.as_mut_slice().as_mut_ptr()), 2);\n+            assert_eq!(varint, [128, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n+        }\n+    }\n+}\n\n-- \n2.51.0.417.g1ba7204a04.dirty\n\n"},{"id":"525819","messageId":"20250908-b4-pks-rust-breaking-change-v3-6-1cd7189fed3b@pks.im","threadId":"64091","inReplyTo":"20250908-b4-pks-rust-breaking-change-v3-0-1cd7189fed3b@pks.im","subject":"[PATCH RFC v3 6/8] BreakingChanges: announce Rust becoming mandatory","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-08T14:13:13Z","receivedAt":"2025-09-08T14:13:41Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Over the last couple of years the appetite for bringin Rust into the\ncodebase has grown significantly across the developer base. Introducing\nRust is a major change though and has ramifications for the whole\necosystem:\n\n  - Some platforms have a Rust toolchain available, but have not yet\n    integrated it into their build infrastructure.\n\n  - Some platforms don't have any support for Rust at all.\n\n  - Some platforms may have to figure out how to fit Rust into their\n    bootstrapping sequence.\n\nDue to this, and given that Git is a critical piece of infrastructure\nfor the whole industry, we cannot just introduce such a heavyweight\ndependency without doing our due diligence.\n\nInstead, preceding commits have introduced a test balloon into our build\ninfrastructure that convert one tiny subsystem to use Rust. For now,\nusing Rust to build that subsystem is entirely optional -- if no Rust\nsupport is available, we continue to use the C implementation. This test\nballoon has the intention to give distributions time and let them ease\ninto our adoption of Rust.\n\nHaving multiple implementations of the same subsystem is not sustainable\nthough, and the plan is to eventually be able to use Rust freely all\nacross our codebase. As such, there is the intent to make Rust become a\nmandatory part of our build process.\n\nAdd an announcement to our breaking changes that Rust will become\nmandatory in Git 3.0. A (very careful and non-binding) estimate might be\nthat this major release might be released in the second half of next\nyear, which should give distributors enough time to prepare for the\nchange.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n Documentation/BreakingChanges.adoc | 41 ++++++++++++++++++++++++++++++++++++++\n 1 file changed, 41 insertions(+)\n\ndiff --git a/Documentation/BreakingChanges.adoc b/Documentation/BreakingChanges.adoc\nindex f8d2eba061..b6ae2241f8 100644\n--- a/Documentation/BreakingChanges.adoc\n+++ b/Documentation/BreakingChanges.adoc\n@@ -165,6 +165,47 @@ A prerequisite for this change is that the ecosystem is ready to support the\n \"reftable\" format. Most importantly, alternative implementations of Git like\n JGit, libgit2 and Gitoxide need to support it.\n \n+* Git will require Rust as a mandatory part of the build process. While Git\n+  already started to adopt Rust in Git 2.52, all parts written in Rust are\n+  optional for the time being. This includes:\n++\n+  ** Subsystems that have an alternative implementation in Rust to test\n+     interoperability between our C and Rust codebase.\n+  ** Newly written features that are not mission critical for a fully functional\n+     Git client.\n++\n+These changes are meant as test balloons to allow distributors of Git to prepare\n+for Rust becoming a mandatory part of the build process. There will be multiple\n+milestones for the introduction of Rust:\n++\n+1. Initially, with Git 2.52, support for Rust will be auto-detected by Meson and\n+   disabled in our Makefile so that the project can sort out the initial\n+   infrastructure.\n+2. In Git 2.53, support for Rust will be enabled by default in case Git is\n+   compiled with breaking changes. Breaking changes can be enabled for Meson by\n+   saying `meson configure -Dbreaking_changes=true` and for Makefile-based\n+   builds via `make WITH_BREAKING_CHANGES=YesPlease`. It will still be possible\n+   to compile with breaking changes, but explicitly disable Rust.\n+3. In Git 2.54, both build systems will default-enable support for Rust even\n+   when breaking changes aren't enabled. Consequently, builds will break by\n+   default if Rust is not available on the build host. The use of Rust can still\n+   be explicitly disabled via build flags.\n+4. In Git 3.0, the build options will be removed and support for Rust is\n+   mandatory.\n++\n+You can explicitly ask both Meson and our Makefile-based system to enable Rust\n+by saying `meson configure -Drust=enabled` and `make WITH_RUST=YesPlease`,\n+respectively.\n++\n+The Git project will declare the last version before Git 3.0 to be a long-term\n+support release. This long-term release will receive important bug fixes for at\n+least four release cycles and security fixes for six release cycles. The Git\n+project will hand over maintainership of the long-term release to distributors\n+in case they need to extend the life of that long-term release even further. In\n+that case, the backporting process will be handled by these distributors, but\n+the backported patches will be reviewed on the mailing list and pulled in by the\n+Git maintainer.\n+\n === Removals\n \n * Support for grafting commits has long been superseded by git-replace(1).\n\n-- \n2.51.0.417.g1ba7204a04.dirty\n\n"},{"id":"525820","messageId":"20250908-b4-pks-rust-breaking-change-v3-7-1cd7189fed3b@pks.im","threadId":"64091","inReplyTo":"20250908-b4-pks-rust-breaking-change-v3-0-1cd7189fed3b@pks.im","subject":"[PATCH RFC v3 7/8] ci: convert \"pedantic\" job into full build with breaking changes","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-08T14:13:14Z","receivedAt":"2025-09-08T14:13:43Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The \"pedantic\" CI job is building on Fedora with `DEVOPTS=pedantic`.\nThis build flag doesn't do anything anymore starting with 6a8cbc41ba\n(developer: enable pedantic by default, 2021-09-03), where we have\nflipped the default so that developers have to opt-out of pedantic\nbuilds via the \"no-pedantic\" option. As such, all this job really does\nis to do a normal build on Fedora, which isn't all that interesting.\n\nConvert that job into a full build-and-test job that uses Meson with\nbreaking changes enabled. This plugs two gaps:\n\n  - We now test on another distro that we didn't run tests on\n    beforehand.\n\n  - We verify that breaking changes work as expected with Meson.\n\nFurthermore, in a subsequent commit we'll modify both jobs that use\nbreaking changes to also enable Rust. By converting the Fedora job to\nuse Meson, we ensure that we test our Rust build infrastructure for both\nbuild systems.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n .github/workflows/main.yml |  4 ++--\n .gitlab-ci.yml             |  4 ++--\n ci/install-dependencies.sh |  6 +++++-\n ci/run-build-and-tests.sh  | 29 ++++++++---------------------\n 4 files changed, 17 insertions(+), 26 deletions(-)\n\ndiff --git a/.github/workflows/main.yml b/.github/workflows/main.yml\nindex d122e79415..393ea4d1cc 100644\n--- a/.github/workflows/main.yml\n+++ b/.github/workflows/main.yml\n@@ -379,6 +379,8 @@ jobs:\n         - jobname: linux-breaking-changes\n           cc: gcc\n           image: ubuntu:rolling\n+        - jobname: fedora-breaking-changes-meson\n+          image: fedora:latest\n         - jobname: linux-leaks\n           image: ubuntu:rolling\n           cc: gcc\n@@ -396,8 +398,6 @@ jobs:\n         # Supported until 2025-04-02.\n         - jobname: linux32\n           image: i386/ubuntu:focal\n-        - jobname: pedantic\n-          image: fedora:latest\n         # A RHEL 8 compatible distro.  Supported until 2029-05-31.\n         - jobname: almalinux-8\n           image: almalinux:8\ndiff --git a/.gitlab-ci.yml b/.gitlab-ci.yml\nindex af10ebb59a..4248506909 100644\n--- a/.gitlab-ci.yml\n+++ b/.gitlab-ci.yml\n@@ -45,6 +45,8 @@ test:linux:\n       - jobname: linux-breaking-changes\n         image: ubuntu:20.04\n         CC: gcc\n+      - jobname: fedora-breaking-changes-meson\n+        image: fedora:latest\n       - jobname: linux-TEST-vars\n         image: ubuntu:20.04\n         CC: gcc\n@@ -58,8 +60,6 @@ test:linux:\n       - jobname: linux-asan-ubsan\n         image: ubuntu:rolling\n         CC: clang\n-      - jobname: pedantic\n-        image: fedora:latest\n       - jobname: linux-musl-meson\n         image: alpine:latest\n       - jobname: linux32\ndiff --git a/ci/install-dependencies.sh b/ci/install-dependencies.sh\nindex d061a47293..35bd05b85b 100755\n--- a/ci/install-dependencies.sh\n+++ b/ci/install-dependencies.sh\n@@ -30,8 +30,12 @@ alpine-*)\n \t\tbash cvs gnupg perl-cgi perl-dbd-sqlite perl-io-tty >/dev/null\n \t;;\n fedora-*|almalinux-*)\n+\tcase \"$jobname\" in\n+\t*-meson)\n+\t\tMESON_DEPS=\"meson ninja\";;\n+\tesac\n \tdnf -yq update >/dev/null &&\n-\tdnf -yq install shadow-utils sudo make gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel >/dev/null\n+\tdnf -yq install shadow-utils sudo make pkg-config gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel $MESON_DEPS >/dev/null\n \t;;\n ubuntu-*|i386/ubuntu-*|debian-*)\n \t# Required so that apt doesn't wait for user input on certain packages.\ndiff --git a/ci/run-build-and-tests.sh b/ci/run-build-and-tests.sh\nindex 01823fd0f1..3680446649 100755\n--- a/ci/run-build-and-tests.sh\n+++ b/ci/run-build-and-tests.sh\n@@ -5,12 +5,11 @@\n \n . ${0%/*}/lib.sh\n \n-run_tests=t\n-\n case \"$jobname\" in\n-linux-breaking-changes)\n+fedora-breaking-changes-musl|linux-breaking-changes)\n \texport GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main\n \texport WITH_BREAKING_CHANGES=YesPlease\n+\tMESONFLAGS=\"$MESONFLAGS -Dbreaking_changes=true\"\n \t;;\n linux-TEST-vars)\n \texport OPENSSL_SHA1_UNSAFE=YesPlease\n@@ -36,12 +35,6 @@ linux-sha256)\n linux-reftable|linux-reftable-leaks|osx-reftable)\n \texport GIT_TEST_DEFAULT_REF_FORMAT=reftable\n \t;;\n-pedantic)\n-\t# Don't run the tests; we only care about whether Git can be\n-\t# built.\n-\texport DEVOPTS=pedantic\n-\trun_tests=\n-\t;;\n esac\n \n case \"$jobname\" in\n@@ -54,21 +47,15 @@ case \"$jobname\" in\n \t\t-Dtest_output_directory=\"${TEST_OUTPUT_DIRECTORY:-$(pwd)/t}\" \\\n \t\t$MESONFLAGS\n \tgroup \"Build\" meson compile -C build --\n-\tif test -n \"$run_tests\"\n-\tthen\n-\t\tgroup \"Run tests\" meson test -C build --print-errorlogs --test-args=\"$GIT_TEST_OPTS\" || (\n-\t\t\t./t/aggregate-results.sh \"${TEST_OUTPUT_DIRECTORY:-t}/test-results\"\n-\t\t\thandle_failed_tests\n-\t\t)\n-\tfi\n+\tgroup \"Run tests\" meson test -C build --print-errorlogs --test-args=\"$GIT_TEST_OPTS\" || (\n+\t\t./t/aggregate-results.sh \"${TEST_OUTPUT_DIRECTORY:-t}/test-results\"\n+\t\thandle_failed_tests\n+\t)\n \t;;\n *)\n \tgroup Build make\n-\tif test -n \"$run_tests\"\n-\tthen\n-\t\tgroup \"Run tests\" make test ||\n-\t\thandle_failed_tests\n-\tfi\n+\tgroup \"Run tests\" make test ||\n+\thandle_failed_tests\n \t;;\n esac\n \n\n-- \n2.51.0.417.g1ba7204a04.dirty\n\n"},{"id":"525821","messageId":"20250908-b4-pks-rust-breaking-change-v3-8-1cd7189fed3b@pks.im","threadId":"64091","inReplyTo":"20250908-b4-pks-rust-breaking-change-v3-0-1cd7189fed3b@pks.im","subject":"[PATCH RFC v3 8/8] ci: enable Rust for breaking-changes jobs","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-08T14:13:15Z","receivedAt":"2025-09-08T14:13:47Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Enable Rust for our breaking-changes jobs so that we can verify that the\nbuild infrastructure and the converted Rust subsystems work as expected.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n ci/install-dependencies.sh | 4 ++--\n ci/run-build-and-tests.sh  | 2 ++\n 2 files changed, 4 insertions(+), 2 deletions(-)\n\ndiff --git a/ci/install-dependencies.sh b/ci/install-dependencies.sh\nindex 35bd05b85b..d377ea2b94 100755\n--- a/ci/install-dependencies.sh\n+++ b/ci/install-dependencies.sh\n@@ -35,7 +35,7 @@ fedora-*|almalinux-*)\n \t\tMESON_DEPS=\"meson ninja\";;\n \tesac\n \tdnf -yq update >/dev/null &&\n-\tdnf -yq install shadow-utils sudo make pkg-config gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel $MESON_DEPS >/dev/null\n+\tdnf -yq install shadow-utils sudo make pkg-config gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel $MESON_DEPS rustc >/dev/null\n \t;;\n ubuntu-*|i386/ubuntu-*|debian-*)\n \t# Required so that apt doesn't wait for user input on certain packages.\n@@ -62,7 +62,7 @@ ubuntu-*|i386/ubuntu-*|debian-*)\n \t\tmake libssl-dev libcurl4-openssl-dev libexpat-dev wget sudo default-jre \\\n \t\ttcl tk gettext zlib1g-dev perl-modules liberror-perl libauthen-sasl-perl \\\n \t\tlibemail-valid-perl libio-pty-perl libio-socket-ssl-perl libnet-smtp-ssl-perl libdbd-sqlite3-perl libcgi-pm-perl \\\n-\t\tlibsecret-1-dev libpcre2-dev meson ninja-build pkg-config \\\n+\t\tlibsecret-1-dev libpcre2-dev meson ninja-build pkg-config cargo \\\n \t\t${CC_PACKAGE:-${CC:-gcc}} $PYTHON_PACKAGE\n \n \tcase \"$distro\" in\ndiff --git a/ci/run-build-and-tests.sh b/ci/run-build-and-tests.sh\nindex 3680446649..c718bd101a 100755\n--- a/ci/run-build-and-tests.sh\n+++ b/ci/run-build-and-tests.sh\n@@ -9,7 +9,9 @@ case \"$jobname\" in\n fedora-breaking-changes-musl|linux-breaking-changes)\n \texport GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main\n \texport WITH_BREAKING_CHANGES=YesPlease\n+\texport WITH_RUST=YesPlease\n \tMESONFLAGS=\"$MESONFLAGS -Dbreaking_changes=true\"\n+\tMESONFLAGS=\"$MESONFLAGS -Drust=enabled\"\n \t;;\n linux-TEST-vars)\n \texport OPENSSL_SHA1_UNSAFE=YesPlease\n\n-- \n2.51.0.417.g1ba7204a04.dirty\n\n"},{"id":"525822","messageId":"c63c64f6-da6f-49a4-b317-9417cd1cfff2@app.fastmail.com","threadId":"64091","inReplyTo":"20250908-b4-pks-rust-breaking-change-v3-0-1cd7189fed3b@pks.im","subject":"Re: [PATCH RFC v3 0/8] Introduce Rust and announce that it will become mandatorty","fromName":"Kristoffer Haugsbakk","fromEmail":"kristofferhaugsbakk@fastmail.com","sentAt":"2025-09-08T14:20:53Z","receivedAt":"2025-09-08T14:22:40Z","isPatch":true,"sender":{"key":"kristofferhaugsbakk@fastmail.com","avatar":null},"body":"On Mon, Sep 8, 2025, at 16:13, Patrick Steinhardt wrote:\n> [PATCH RFC v3 0/8] Introduce Rust and announce that it will become mandatorty\n\ns/mandatorty/mandatory/\n\n> Hi,\n>\n> this small patch series introduces Rust into the core of Git. This patch\n> series is designed as a test balloon, similar to how we introduced test\n> balloons for C99 features in the past. The goal is threefold:\n>[snip]\n\n-- \nKristoffer Haugsbakk\n\n"},{"id":"525866","messageId":"CAH=ZcbA_8JM1hdUAfFe3ho0ShuniguEpV1308S0nCkCHOCsmmg@mail.gmail.com","threadId":"64091","inReplyTo":"20250908-b4-pks-rust-breaking-change-v3-5-1cd7189fed3b@pks.im","subject":"Re: [PATCH RFC v3 5/8] rust: implement a test balloon via the \"varint\" subsystem","fromName":"Ezekiel Newren","fromEmail":"ezekielnewren@gmail.com","sentAt":"2025-09-08T17:19:20Z","receivedAt":"2025-09-08T17:19:33Z","isPatch":true,"sender":{"key":"ezekielnewren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/18313324?v=4"},"body":"On Mon, Sep 8, 2025 at 8:13 AM Patrick Steinhardt <ps@pks.im> wrote:\n> +use std::os::raw::c_int;\n> +use std::os::raw::c_uchar;\n\nI'd really rather avoid using C types in Rust, in favor of using Rust\ntypes in C. I have written a commit that talks about why C should use\nRust primitive types and why Rust should avoid using C types, here:\nhttps://lore.kernel.org/git/2a7d5b05c18d4a96f1905b7043d47c62d367cd2a.1757274320.git.gitgitgadget@gmail.com/.\nIn my opinion, the type c_void is the only appropriate C type that\nshould be used on the Rust side, and should be used sparingly.\n\nThe std::os::raw::c_* directly inherits the problems of core::ffi,\nwhich changes over time and seems to make a best guess at the correct\ndefinition for a given platform/target. This probably isn't a problem\nfor all platforms that Rust supports currently, but can anyone say\nthat Rust got it right for all C compilers of all platforms/targets?\n\nTo give an example: c_long is defined in [1,2]\n\n// Rust version 1.63.0\nmod c_long_definition {\n    cfg_if! {\n        if #[cfg(all(target_pointer_width = \"64\", not(windows)))] {\n            pub type c_long = i64;\n            pub type NonZero_c_long = crate::num::NonZeroI64;\n            pub type c_ulong = u64;\n            pub type NonZero_c_ulong = crate::num::NonZeroU64;\n        } else {\n            // The minimal size of `long` in the C standard is 32 bits\n            pub type c_long = i32;\n            pub type NonZero_c_long = crate::num::NonZeroI32;\n            pub type c_ulong = u32;\n            pub type NonZero_c_ulong = crate::num::NonZeroU32;\n        }\n    }\n}\n\n// Rust version 1.89.0\nmod c_long_definition {\n    crate::cfg_select! {\n        any(\n            all(target_pointer_width = \"64\", not(windows)),\n            // wasm32 Linux ABI uses 64-bit long\n            all(target_arch = \"wasm32\", target_os = \"linux\")\n        ) => {\n            pub(super) type c_long = i64;\n            pub(super) type c_ulong = u64;\n        }\n        _ => {\n            // The minimal size of `long` in the C standard is 32 bits\n            pub(super) type c_long = i32;\n            pub(super) type c_ulong = u32;\n        }\n    }\n}\n\n[1] c_long in 1.63.0\nhttps://doc.rust-lang.org/1.63.0/src/core/ffi/mod.rs.html#175-189:\n[2] c_long in 1.89.0\nhttps://doc.rust-lang.org/1.89.0/src/core/ffi/primitives.rs.html#135-151:\n"},{"id":"525885","messageId":"aL9UIeyUqmwwPt2c@fruit.crustytoothpaste.net","threadId":"64091","inReplyTo":"20250908-b4-pks-rust-breaking-change-v3-1-1cd7189fed3b@pks.im","subject":"Re: [PATCH RFC v3 1/8] meson: add infrastructure to build internal Rust library","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2025-09-08T22:09:37Z","receivedAt":"2025-09-08T22:09:40Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On 2025-09-08 at 14:13:08, Patrick Steinhardt wrote:\n> diff --git a/Cargo.lock b/Cargo.lock\n> new file mode 100644\n> index 00000000000..2b80a01e22a\n> --- /dev/null\n> +++ b/Cargo.lock\n> @@ -0,0 +1,22 @@\n> +# This file is automatically @generated by Cargo.\n> +# It is not intended for manual editing.\n> +# Fix this to version 3. This is required so that older toolchains can still\n> +# read the lock file. Furthermore, while an argument could be made that we\n> +# should not even commit the \"Cargo.lock\" file in the first place, there's two\n> +# reasons to still do so:\n> +#\n> +#   - It thwarts supply-chain attacks by committing checksums into the\n> +#     repository.\n> +#\n> +#   - It is required by Meson so that it can extract Cargo dependencies.\n\nIf we check this in, then we basically cannot use any dependencies.  As\nI mentioned elsewhere, the problem is that invariably, if we're going to\npin to an older version of Rust, we're going to be faced with the\nproblem that some crate is going to require a security update that is\nalso going to break older versions of Rust, and we will then have users\naggressively demanding on the list that we update it immediately and\nship a new release, breaking those older compilers.  (And yes, I've seen\nthis happen with Go dependencies on Git LFS, even when the vulnerable\ncode is not used.)\n\nThis is made worse by the fact that you want to support Rust 1.49\ninstead of Rust 1.63, as I proposed.  Absent some compelling proposal on\nhow we're going to deal with this situation, I think we need to omit\n`Cargo.lock`.\n\nI think the better approach is to leave it out and use Cargo to build\nthe Rust code instead of having Meson do it directly.\n\n> +# Starting with Meson 1.5, it knows to parse the \"Cargo.lock\" file and extract\n> +# dependencies from it. So from hereon we don't need Cargo anymore to build\n> +# Git.\n\nAh, yes, I've already broken this in my branch (early this morning, in\nfact).  I've added a `build.rs` file (used by Cargo) which is necessary\nto properly link the tests against `libgit.a`.  (I'm using the hashing\ncode in some of my tests.) Meson fails to honour that and so the\ncompilation breaks.\n\nI don't think it's going to be viable to try to maintain two separate\nbuild systems that build the Rust code.  Everyone who uses rust-analyzer\n(the Rust LSP) will use Cargo because that's the build system it uses,\nand everyone uses Cargo anyway, so as a practical matter we need to\nsupport it.  Trying to have Meson do its own thing is unlikely to work\nhere, and it demands that we use the `Cargo.lock` file, which we'd like\nto avoid.\n\n> +  cargo_command = [\n> +    cargo,\n> +    'build',\n> +    '--lib',\n> +    '--quiet',\n> +    '--manifest-path',\n> +    meson.project_source_root() / 'Cargo.toml',\n> +    '--target-dir',\n> +    meson.current_build_dir() / 'target',\n> +    # `--out-dir` is unstable, but supported since 2018. It's been recently\n> +    # renamed to `--artifact-dir`, but for now both options are supported.\n> +    '-Z',\n> +    'unstable-options',\n\n`-Z` is only accepted in nightly versions of the compiler.  This won't\nwork with stable Rust and it definitely won't work with either 1.63 or\n1.49.  It didn't work for me using Rust 1.89.0 when I removed the other\nbranch.\n-- \nbrian m. carlson (they/them)\nToronto, Ontario, CA\n"},{"id":"525886","messageId":"aL9XOj1sVmHGjDRn@fruit.crustytoothpaste.net","threadId":"64091","inReplyTo":"CAH=ZcbA_8JM1hdUAfFe3ho0ShuniguEpV1308S0nCkCHOCsmmg@mail.gmail.com","subject":"Re: [PATCH RFC v3 5/8] rust: implement a test balloon via the \"varint\" subsystem","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2025-09-08T22:22:50Z","receivedAt":"2025-09-08T22:22:52Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On 2025-09-08 at 17:19:20, Ezekiel Newren wrote:\n> On Mon, Sep 8, 2025 at 8:13 AM Patrick Steinhardt <ps@pks.im> wrote:\n> > +use std::os::raw::c_int;\n> > +use std::os::raw::c_uchar;\n> \n> I'd really rather avoid using C types in Rust, in favor of using Rust\n> types in C. I have written a commit that talks about why C should use\n> Rust primitive types and why Rust should avoid using C types, here:\n> https://lore.kernel.org/git/2a7d5b05c18d4a96f1905b7043d47c62d367cd2a.1757274320.git.gitgitgadget@gmail.com/.\n> In my opinion, the type c_void is the only appropriate C type that\n> should be used on the Rust side, and should be used sparingly.\n> \n> The std::os::raw::c_* directly inherits the problems of core::ffi,\n> which changes over time and seems to make a best guess at the correct\n> definition for a given platform/target. This probably isn't a problem\n> for all platforms that Rust supports currently, but can anyone say\n> that Rust got it right for all C compilers of all platforms/targets?\n\nIt also poses problems because if we use `c_ulong` and it's 64 bit, then\ntrying to do a `.into()` to convert it to a `u64` will cause the\ncompiler and linters to complain, even if it does compile successfully.\nBut on 32-bit systems or Windows, `c_ulong` will be `u32` and it will be\nrequired to convert, since Rust doesn't allow automatic conversion\nbetween types.  I have some personal Rust code which works with\n`mode_t`, which on some Unix systems is 16 bits and on some systems is\n32 bits and it has made me want to scream quite a bit.  It gets even\nworse if the types differ in signedness.\n\nIt would be better to do `usize` and `u8` on the Rust side here and\n`size_t` and `uint8_t` on the C side.  I think `unsigned char` and `u8`\nis also fine, since we are not targeting systems where `unsigned char`\nis not 8 bits in size.\n\nI don't know how you plan to deal with the fact that Rust doesn't expose\n`uintmax_t`, but I think that's 64-bit on all known systems (because\nmaking it 128-bit would break ABI and nobody wants to bump libc's\nSONAME), so you could try `u64` and `uint64_t` for the value instead.\n-- \nbrian m. carlson (they/them)\nToronto, Ontario, CA\n"},{"id":"525887","messageId":"aL9gDXNJCGH0eIsY@fruit.crustytoothpaste.net","threadId":"64091","inReplyTo":"aL57ONmEKTmqFhIZ@pks.im","subject":"Re: [PATCH RFC v2 0/7] Introduce Rust and announce that it will become mandatorty","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2025-09-08T23:00:29Z","receivedAt":"2025-09-08T23:00:31Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On 2025-09-08 at 06:44:08, Patrick Steinhardt wrote:\n> > Setting that aside for a moment, the idea of Git 2.55 becoming 3.0\n> > seems like a good idea to me, assuming that doesn't rush brian on the\n> > sha1/sha256 interop (since I think that's probably the paramount\n> > feature of 3.0).\n> \n> Yeah, the interop is definitely an important factor and the last part\n> that I think is still missing for Git 3.0 to become viable.\n\nI am definitely working on this at the moment and here's what I have\nworking:\n\n* Pack index v3\n* Fetching and pushing for full (non-shallow, non-partial) clones\n  without submodules\n\nAnd I'm working on these:\n\n* The new binary loose object map (I was debugging round-tripping this\n  morning)\n* Shallow fetches (which, due to the quarantine usage, need a binary\n  loose object map rather than the `loose-object-idx` file, since the\n  quarantine can't merge the two `loose-object-idx` files together)\n\nAnd then I'll get to these:\n\n* Shallow pushes\n* Partial clone\n* Garbage collecting and repacking binary loose object maps\n* Submodule handling in the protocol\n\nI will need to switch soon to writing my presentation for Git Merge,\nthough, but afterwards I'm going to go back through the testsuite and\nsee what else is failing.  I expect partial and shallow clones to fix a\nlot of the remaining tests, but there are still going to be some\nproblems to deal with.\n\nNote that shallow and partial clones where the server supports only\none algorithm won't work with interoperability, since those lack full\ndata and the client side won't be able to map the objects between\nalgorithms.  There's also the problem that accepting submodule mappings\nintroduces a security risk, since it's possible for the other side to\nsend commit A in SHA-1 but commit B in SHA-256 and there's no real way\nto detect that unless you have the submodule on your side.\n\nI may end up asking for some assistance in polishing and sending in what\nI have.  Most of what I have is reasonably good quality[0] and should be\nbisectable, but I'm up to 81 patches before the Rust part of the code\n(which so far has 12 patches) and I'm worried I won't be able to both\nwrite it and get it sent in in nice-sized series before 3.0 is likely to\nhappen.\n\nAlternatively, we could maybe accept that interoperability is a\nnice-to-have for Git 3.0 and not an essential.  It's not mentioned in\nthe BreakingChanges document, so it's perhaps not a requirement.  We\ncould also have someone work on this as part of their job to get it\nhandled more quickly[1].\n\nFinally, I am currently interested in working on the interop code (but\nhave no problem handing it off if that works better for the project),\nbut I cannot guarantee that I will absolutely have time or inclination\nto continue.\n\n[0] There are some patches marked WIP with a reason as to why they need\nwork, but those are few and far between.\n[1] I think it's unlikely that this will be able to be me for reasons\nwhich I cannot share at the moment but hope to be able to later on,\nmaybe at the Contributor Summit.  I'll keep an eye out in case it\nbecomes possible, though.\n-- \nbrian m. carlson (they/them)\nToronto, Ontario, CA\n"},{"id":"525889","messageId":"EF337F13-64D2-4A17-BF7D-FE77E3064E35@gmail.com","threadId":"64091","inReplyTo":"xmqq8qipzhg3.fsf@gitster.g","subject":"Re: [PATCH RFC 2/3] rust: implement a test balloon via the \"varint\" subsystem","fromName":"Ben Knoble","fromEmail":"ben.knoble@gmail.com","sentAt":"2025-09-09T00:49:45Z","receivedAt":"2025-09-09T00:49:58Z","isPatch":true,"sender":{"key":"ben.knoble@gmail.com","avatar":"https://avatars.githubusercontent.com/u/22802209?v=4"},"body":"\n> Le 8 sept. 2025 à 00:39, Junio C Hamano <gitster@pobox.com> a écrit :\n> \n> ﻿Ben Knoble <ben.knoble@gmail.com> writes:\n> \n>>> +#[no_mangle]\n>>> +pub unsafe extern \"C\" fn decode_varint(bufp: *mut *const c_uchar) -> usize {\n>>> +    let mut buf = *bufp;\n>>> +    let mut c = *buf;\n>>> +    let mut val = usize::from(c & 127);\n>>> +\n>>> +    buf = buf.add(1);\n>>> +\n>>> +    while (c & 128) != 0 {\n>>> +        val += 1;\n>>> +        if val == 0 || val.leading_zeros() < 7 {\n>>> +            return 0; // overflow\n>> \n>> Hm. I thought overflows panic in debug builds, in which case\n>> checking afterwards is too late? Does unsafe change that?\n> \n> This code is a very faithful conversion from C so if somebody does\n> not read Rust well, they can safely refer to the original in C.\n> \n> In either variant, the leading zero's check asks \"can we shift val\n> by 7 bits to the left?\" _before_ it actually shifts val (and or'es\n> in the lower bits of c), so the \"overflow\" check is \"if we processed\n> any more data we _would_ overflow, so we stop before overflowing\".\n> \n> IOW, the code _is_ avoiding the \"too late\" condition.\n\nMaybe I wasn’t clear, sorry: don’t we already have overflow if after val+=1 we also have val==0? In C with unsigned types AFAIK that’s the normal modular arithmetic, but I thought I recalled that such (unsigned) overflow panics in Rust in debug builds (not in release).\n\nSo that’s my « checking afterwards » above.\n\nI’ll see if I can double-check my memory though. "},{"id":"525890","messageId":"aL98-Dq9HC5eDOcM@fruit.crustytoothpaste.net","threadId":"64091","inReplyTo":"aL9UIeyUqmwwPt2c@fruit.crustytoothpaste.net","subject":"Re: [PATCH RFC v3 1/8] meson: add infrastructure to build internal Rust library","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2025-09-09T01:03:52Z","receivedAt":"2025-09-09T01:03:54Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On 2025-09-08 at 22:09:37, brian m. carlson wrote:\n> Ah, yes, I've already broken this in my branch (early this morning, in\n> fact).  I've added a `build.rs` file (used by Cargo) which is necessary\n> to properly link the tests against `libgit.a`.  (I'm using the hashing\n> code in some of my tests.) Meson fails to honour that and so the\n> compilation breaks.\n\nIf you're interested in seeing what I mean, you can clone my\n`sha256-interop-part-2` from https://github.com/bk2204/git.git, which\nhas your v2 merged into it.  You can do `make -j12 all` and then `cargo\ntest`, which should work and pass the tests.\n-- \nbrian m. carlson (they/them)\nToronto, Ontario, CA\n"},{"id":"525901","messageId":"CABPp-BEW8TYaffOED34bTy98X=CDZeA+r=X+kMR-GRwuqRDfjg@mail.gmail.com","threadId":"64091","inReplyTo":"aL57ONmEKTmqFhIZ@pks.im","subject":"Re: [PATCH RFC v2 0/7] Introduce Rust and announce that it will become mandatorty","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2025-09-09T06:33:45Z","receivedAt":"2025-09-09T06:33:57Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Sun, Sep 7, 2025 at 11:44 PM Patrick Steinhardt <ps@pks.im> wrote:\n>\n> On Sat, Sep 06, 2025 at 09:31:02PM -0700, Elijah Newren wrote:\n> > On Fri, Sep 5, 2025 at 7:29 AM Patrick Steinhardt <ps@pks.im> wrote:\n[...]\n> > > I have a plan layed out in the BreakingChanges document that mentions\n> > > how I'm proposing to do the transition:\n> > >\n> > >   1. We introduce it with auto-detection for Meson and default-disabled\n> > >      for our Makefile in Git 2.52.\n> > >\n> > >   2. We enable Rust by default in case WITH_BREAKING_CHANGES is enabled\n> > >      in Git 2.53.\n> > >\n> > >   3. We always enable Rust by default in Git 2.54.\n> >\n> > I don't see how steps 1 & 2 help at all.  We now know we want to make\n> > Rust mandatory eventually, and should provide distributors and\n> > platforms as much notice as possible so they are aware.  But what\n> > you've proposed is another libgit-rs or libgit-sys -- an optional\n> > component that no one will know about unless they go looking for it.\n> > I don't see how those two steps provide any incremental help to\n> > anybody over what libgit-rs and libgit-sys have done.  From my point\n> > of view, Rust should be enabled by default in Git 2.52, with a simple\n> > knob provided to let distributors/platforms/users turn it off and\n> > build without it.\n>\n> It helps because it allows us to slowly build out the infrastructure. We\n> don't yet need answers to every question that we currently have if we\n> initially have the Rust infra default-disabled.\n\nOne of the things I find very unfortunate about this series, is we\nhave a new contributor who was trying to send in patches, and instead\nof providing feedback, suggesting alternatives, or asking if he'd do\nit differently (which he actually said he was willing to do [1]), it\nsends out a competing patch series to replace his instead.  (And this\nhappened shortly after someone else interjected patches because of\ninterest in the first area he touched, forcing him to pivot once\nalready[2].)  Further, despite him having solved how to get it running\non all platforms we run in CI with some big help from the\ngit-for-windows folks, this series discards all of that.  It lends to\na feeling that he might be working on important and interesting\ntopics, but his changes aren't welcome and it's not worth providing\nfeedback for him to modify them to become so.  That's almost certainly\nnot your intent, but that is the effect that sending a competing patch\nseries likely is going to have.\n\n[1] https://lore.kernel.org/git/CAH=ZcbBLAKaE733_2_2qbFTYCfwGq37RfF-Z3vaKL1ZR49msAA@mail.gmail.com/\n[2] https://lore.kernel.org/git/xmqqzfbvfxs6.fsf@gitster.g/\n\n> I very much expect that there'll be some issues with our initial first\n> steps. So I'd rather want to avoid to expose developers or distros to\n> these issues directly, because that might train them to immediately\n> disable Rust right from the start.\n\nI don't understand why that matters.  The whole point you gave to\nmotivate this series was to make distributors aware that mandatory\nRust is coming.  If they disable it early on, that requires them to\nhave been made aware, so mission achieved.  Making it optional and\noff-by-default means they get no notice until multiple releases down\nthe road until you do turn it on, shortening the window they have to\nbe alerted and prepared.  To me, this feels like you're snatching\ndefeat from the jaws of victory.\n"},{"id":"525938","messageId":"7c25d5a6-1b34-485e-93f9-25bbe37d5bd4@gmail.com","threadId":"64091","inReplyTo":"aLrzqR2Z9jz5CuJu@pks.im","subject":"Re: [PATCH RFC v2 0/7] Introduce Rust and announce that it will become mandatorty","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2025-09-09T09:12:39Z","receivedAt":"2025-09-09T09:12:44Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Patrick\n\nOn 05/09/2025 15:28, Patrick Steinhardt wrote:\n> On Fri, Sep 05, 2025 at 03:14:25PM +0100, Phillip Wood wrote:\n>>\n>> It looks like this version does include the necessary Makefile changes which\n>> is great. I do think though, that for the test balloon to be valuable, we\n>> need make building with rust the default with an error message that tells\n>> people how to build without rust if that fails. Otherwise it is easy for\n>> people building on platforms without rust support to miss that we're going\n>> to be making it mandatory soon.\n> \n> I have a plan layed out in the BreakingChanges document that mentions\n> how I'm proposing to do the transition:\n> \n>    1. We introduce it with auto-detection for Meson and default-disabled\n>       for our Makefile in Git 2.52.\n\nI'm not sure how much this helps us. You've said elsewhere that you \ndon't want to be inundated with bug reports which is fair enough, but \nI'm fairly skeptical that we're going to get enough people enabling this \nget a useful amount of early feedback. So I wonder if it would be better \njust to bite the bullet and enable it by default from the start. I think \nI saw Elijah making a similar argument elsewhere in this thread.\n> In the end it kind of hinges on when we think we want to release Git\n> 3.0. If we can agree on the above plan, we could also think about making\n> Git 2.55 become 3.0 instead. That'd be in a bit less than a year from\n> now, which I think is a good timeframe for that breaking release. I\n> personally don't see a reason to push it out into the future for way\n> longer than that, and it would be good anyway if we built some consensus\n> around its release date.\n\nIt would definitely be good to firm up the date for a Git 3.0 release. \nI've been thinking whether there are any config defaults we might want \nto change like \"commit.verbose\" and \"merge.conflictStyle\" and enabling \n\"--reapply-cherry-pick --empty=false\" by default for \"git rebase\". \nHaving a firm deadline would focus my mind!\n\nThanks\n\nPhillip\n\n\n> Patrick\n\n"},{"id":"525965","messageId":"xmqqfrcvve6e.fsf@gitster.g","threadId":"64091","inReplyTo":"EF337F13-64D2-4A17-BF7D-FE77E3064E35@gmail.com","subject":"Re: [PATCH RFC 2/3] rust: implement a test balloon via the \"varint\" subsystem","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-09-09T15:27:53Z","receivedAt":"2025-09-09T15:27:58Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ben Knoble <ben.knoble@gmail.com> writes:\n\n>> Le 8 sept. 2025 à 00:39, Junio C Hamano <gitster@pobox.com> a écrit :\n>> \n>> ﻿Ben Knoble <ben.knoble@gmail.com> writes:\n>> \n>>>> +#[no_mangle]\n>>>> +pub unsafe extern \"C\" fn decode_varint(bufp: *mut *const c_uchar) -> usize {\n>>>> +    let mut buf = *bufp;\n>>>> +    let mut c = *buf;\n>>>> +    let mut val = usize::from(c & 127);\n>>>> +\n>>>> +    buf = buf.add(1);\n>>>> +\n>>>> +    while (c & 128) != 0 {\n>>>> +        val += 1;\n>>>> +        if val == 0 || val.leading_zeros() < 7 {\n>>>> +            return 0; // overflow\n>>> \n>>> Hm. I thought overflows panic in debug builds, in which case\n>>> checking afterwards is too late? Does unsafe change that?\n>> \n>> This code is a very faithful conversion from C so if somebody does\n>> not read Rust well, they can safely refer to the original in C.\n>> \n>> In either variant, the leading zero's check asks \"can we shift val\n>> by 7 bits to the left?\" _before_ it actually shifts val (and or'es\n>> in the lower bits of c), so the \"overflow\" check is \"if we processed\n>> any more data we _would_ overflow, so we stop before overflowing\".\n>> \n>> IOW, the code _is_ avoiding the \"too late\" condition.\n>\n> Maybe I wasn’t clear, sorry: don’t we already have overflow if\n> after val+=1 we also have val==0? In C with unsigned types AFAIK\n> that’s the normal modular arithmetic, but I thought I recalled\n> that such (unsigned) overflow panics in Rust in debug builds (not\n> in release).\n>\n> So that’s my « checking afterwards » above.\n>\n> I’ll see if I can double-check my memory though. \n\nAhh, you meant \"can we safely add 1 to val here without\noverflowing?\"\n\nYou probably are correct.  If val in the last round had top 7 bits\nall 0 and we shifted the lower 7 bits of 'c' in, and if that made\nval all 1 bit, then in the modular arithmetic, we may get val==0\nafter adding 1 to it, but that may indeed be \"overflow\"ing.\n\nThanks.\n"},{"id":"526013","messageId":"aME1Bfv-IPq0zRG5@pks.im","threadId":"64091","inReplyTo":"7c25d5a6-1b34-485e-93f9-25bbe37d5bd4@gmail.com","subject":"Re: [PATCH RFC v2 0/7] Introduce Rust and announce that it will become mandatorty","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-10T08:21:25Z","receivedAt":"2025-09-10T08:21:39Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Tue, Sep 09, 2025 at 10:12:39AM +0100, Phillip Wood wrote:\n> On 05/09/2025 15:28, Patrick Steinhardt wrote:\n> > On Fri, Sep 05, 2025 at 03:14:25PM +0100, Phillip Wood wrote:\n> > > \n> > > It looks like this version does include the necessary Makefile changes which\n> > > is great. I do think though, that for the test balloon to be valuable, we\n> > > need make building with rust the default with an error message that tells\n> > > people how to build without rust if that fails. Otherwise it is easy for\n> > > people building on platforms without rust support to miss that we're going\n> > > to be making it mandatory soon.\n> > \n> > I have a plan layed out in the BreakingChanges document that mentions\n> > how I'm proposing to do the transition:\n> > \n> >    1. We introduce it with auto-detection for Meson and default-disabled\n> >       for our Makefile in Git 2.52.\n> \n> I'm not sure how much this helps us. You've said elsewhere that you don't\n> want to be inundated with bug reports which is fair enough, but I'm fairly\n> skeptical that we're going to get enough people enabling this get a useful\n> amount of early feedback. So I wonder if it would be better just to bite the\n> bullet and enable it by default from the start. I think I saw Elijah making\n> a similar argument elsewhere in this thread.\n\nThe patch series may not be ready for all platforms yet though. Windows\nsupport is still untested and probably not working, so I first need to\nget that done. This is basically the reason why I'm proposing to have it\nauto-detected at first: I want to be able to iterate without breaking\nany platforms yet.\n\nHow about we do a compromise: we initially introduce it\ndefault-disabled, but default-enable it in the next release already\ninstead of first tying it to `-Dbreaking_changes=true`? That would\naccelerate the proposed timeline a bit.\n\nPatrick\n"},{"id":"526014","messageId":"aME1ETcGAbhoO49n@pks.im","threadId":"64091","inReplyTo":"CABPp-BEW8TYaffOED34bTy98X=CDZeA+r=X+kMR-GRwuqRDfjg@mail.gmail.com","subject":"Re: [PATCH RFC v2 0/7] Introduce Rust and announce that it will become mandatorty","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-10T08:21:37Z","receivedAt":"2025-09-10T08:21:44Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Mon, Sep 08, 2025 at 11:33:45PM -0700, Elijah Newren wrote:\n> On Sun, Sep 7, 2025 at 11:44 PM Patrick Steinhardt <ps@pks.im> wrote:\n> >\n> > On Sat, Sep 06, 2025 at 09:31:02PM -0700, Elijah Newren wrote:\n> > > On Fri, Sep 5, 2025 at 7:29 AM Patrick Steinhardt <ps@pks.im> wrote:\n> [...]\n> > > > I have a plan layed out in the BreakingChanges document that mentions\n> > > > how I'm proposing to do the transition:\n> > > >\n> > > >   1. We introduce it with auto-detection for Meson and default-disabled\n> > > >      for our Makefile in Git 2.52.\n> > > >\n> > > >   2. We enable Rust by default in case WITH_BREAKING_CHANGES is enabled\n> > > >      in Git 2.53.\n> > > >\n> > > >   3. We always enable Rust by default in Git 2.54.\n> > >\n> > > I don't see how steps 1 & 2 help at all.  We now know we want to make\n> > > Rust mandatory eventually, and should provide distributors and\n> > > platforms as much notice as possible so they are aware.  But what\n> > > you've proposed is another libgit-rs or libgit-sys -- an optional\n> > > component that no one will know about unless they go looking for it.\n> > > I don't see how those two steps provide any incremental help to\n> > > anybody over what libgit-rs and libgit-sys have done.  From my point\n> > > of view, Rust should be enabled by default in Git 2.52, with a simple\n> > > knob provided to let distributors/platforms/users turn it off and\n> > > build without it.\n> >\n> > It helps because it allows us to slowly build out the infrastructure. We\n> > don't yet need answers to every question that we currently have if we\n> > initially have the Rust infra default-disabled.\n> \n> One of the things I find very unfortunate about this series, is we\n> have a new contributor who was trying to send in patches, and instead\n> of providing feedback, suggesting alternatives, or asking if he'd do\n> it differently (which he actually said he was willing to do [1]), it\n> sends out a competing patch series to replace his instead.  (And this\n> happened shortly after someone else interjected patches because of\n> interest in the first area he touched, forcing him to pivot once\n> already[2].)  Further, despite him having solved how to get it running\n> on all platforms we run in CI with some big help from the\n> git-for-windows folks, this series discards all of that.  It lends to\n> a feeling that he might be working on important and interesting\n> topics, but his changes aren't welcome and it's not worth providing\n> feedback for him to modify them to become so.  That's almost certainly\n> not your intent, but that is the effect that sending a competing patch\n> series likely is going to have.\n> \n> [1] https://lore.kernel.org/git/CAH=ZcbBLAKaE733_2_2qbFTYCfwGq37RfF-Z3vaKL1ZR49msAA@mail.gmail.com/\n> [2] https://lore.kernel.org/git/xmqqzfbvfxs6.fsf@gitster.g/\n\nFirst to say: I'm not trying to say that his changes are not welcome\nhere. What I'm trying to do with my patch series is to reconcile the\ndifferent camps that we have in our project and to find a way forward so\nthat Ezekiels work eventually becomes unblocked.\n\nAnd regarding the Windows changes: yes, I haven't picked those yet. I\nwanted to first get to a minimum working proposal so that we can focus\nthe discussion more on the roadmap, which I think is the more important\ndiscussion compared to the technical discussion.\n\nAs I mentioned, I do plan to implement Windows support as a next step\nonce we have agreed on the initial baseline.\n\nPatrick\n"},{"id":"526015","messageId":"aME1GoS8M8QvkB-B@pks.im","threadId":"64091","inReplyTo":"aL9gDXNJCGH0eIsY@fruit.crustytoothpaste.net","subject":"Re: [PATCH RFC v2 0/7] Introduce Rust and announce that it will become mandatorty","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-10T08:21:46Z","receivedAt":"2025-09-10T08:21:54Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Mon, Sep 08, 2025 at 11:00:29PM +0000, brian m. carlson wrote:\n> I may end up asking for some assistance in polishing and sending in what\n> I have.  Most of what I have is reasonably good quality[0] and should be\n> bisectable, but I'm up to 81 patches before the Rust part of the code\n> (which so far has 12 patches) and I'm worried I won't be able to both\n> write it and get it sent in in nice-sized series before 3.0 is likely to\n> happen.\n\nOh, I didn't expect it to be that much work. In any case, I would be\nhappy to help out with this effort in case there's anything concrete we\ncan do here.\n\n> Alternatively, we could maybe accept that interoperability is a\n> nice-to-have for Git 3.0 and not an essential.  It's not mentioned in\n> the BreakingChanges document, so it's perhaps not a requirement.  We\n> could also have someone work on this as part of their job to get it\n> handled more quickly[1].\n\nI wouldn't mind that outcome, either.\n\n> Finally, I am currently interested in working on the interop code (but\n> have no problem handing it off if that works better for the project),\n> but I cannot guarantee that I will absolutely have time or inclination\n> to continue.\n\nThat is very fair indeed. I don't have the intention to force anybody's\nhands with the proposed 3.0 timeline.\n\nPatrick\n"},{"id":"526016","messageId":"aME1KgygXon5jOQC@pks.im","threadId":"64091","inReplyTo":"aL9XOj1sVmHGjDRn@fruit.crustytoothpaste.net","subject":"Re: [PATCH RFC v3 5/8] rust: implement a test balloon via the \"varint\" subsystem","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-10T08:22:02Z","receivedAt":"2025-09-10T08:22:10Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Mon, Sep 08, 2025 at 10:22:50PM +0000, brian m. carlson wrote:\n> On 2025-09-08 at 17:19:20, Ezekiel Newren wrote:\n> > On Mon, Sep 8, 2025 at 8:13 AM Patrick Steinhardt <ps@pks.im> wrote:\n> > > +use std::os::raw::c_int;\n> > > +use std::os::raw::c_uchar;\n> > \n> > I'd really rather avoid using C types in Rust, in favor of using Rust\n> > types in C. I have written a commit that talks about why C should use\n> > Rust primitive types and why Rust should avoid using C types, here:\n> > https://lore.kernel.org/git/2a7d5b05c18d4a96f1905b7043d47c62d367cd2a.1757274320.git.gitgitgadget@gmail.com/.\n> > In my opinion, the type c_void is the only appropriate C type that\n> > should be used on the Rust side, and should be used sparingly.\n> > \n> > The std::os::raw::c_* directly inherits the problems of core::ffi,\n> > which changes over time and seems to make a best guess at the correct\n> > definition for a given platform/target. This probably isn't a problem\n> > for all platforms that Rust supports currently, but can anyone say\n> > that Rust got it right for all C compilers of all platforms/targets?\n> \n> It also poses problems because if we use `c_ulong` and it's 64 bit, then\n> trying to do a `.into()` to convert it to a `u64` will cause the\n> compiler and linters to complain, even if it does compile successfully.\n> But on 32-bit systems or Windows, `c_ulong` will be `u32` and it will be\n> required to convert, since Rust doesn't allow automatic conversion\n> between types.  I have some personal Rust code which works with\n> `mode_t`, which on some Unix systems is 16 bits and on some systems is\n> 32 bits and it has made me want to scream quite a bit.  It gets even\n> worse if the types differ in signedness.\n> \n> It would be better to do `usize` and `u8` on the Rust side here and\n> `size_t` and `uint8_t` on the C side.  I think `unsigned char` and `u8`\n> is also fine, since we are not targeting systems where `unsigned char`\n> is not 8 bits in size.\n> \n> I don't know how you plan to deal with the fact that Rust doesn't expose\n> `uintmax_t`, but I think that's 64-bit on all known systems (because\n> making it 128-bit would break ABI and nobody wants to bump libc's\n> SONAME), so you could try `u64` and `uint64_t` for the value instead.\n\nFair. I think for now I'll add a preparatory patch to make the width of\nintegers explicit in the C part. But if we agree on the approach picked\nby Ezekiel I think it does make sense to unify this towards Rust types\neventually.\n\nPatrick\n"},{"id":"526017","messageId":"aME1M4YsMsrmu2Vg@pks.im","threadId":"64091","inReplyTo":"aL9UIeyUqmwwPt2c@fruit.crustytoothpaste.net","subject":"Re: [PATCH RFC v3 1/8] meson: add infrastructure to build internal Rust library","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-10T08:22:11Z","receivedAt":"2025-09-10T08:22:19Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Mon, Sep 08, 2025 at 10:09:37PM +0000, brian m. carlson wrote:\n> On 2025-09-08 at 14:13:08, Patrick Steinhardt wrote:\n> > diff --git a/Cargo.lock b/Cargo.lock\n> > new file mode 100644\n> > index 00000000000..2b80a01e22a\n> > --- /dev/null\n> > +++ b/Cargo.lock\n> > @@ -0,0 +1,22 @@\n> > +# This file is automatically @generated by Cargo.\n> > +# It is not intended for manual editing.\n> > +# Fix this to version 3. This is required so that older toolchains can still\n> > +# read the lock file. Furthermore, while an argument could be made that we\n> > +# should not even commit the \"Cargo.lock\" file in the first place, there's two\n> > +# reasons to still do so:\n> > +#\n> > +#   - It thwarts supply-chain attacks by committing checksums into the\n> > +#     repository.\n> > +#\n> > +#   - It is required by Meson so that it can extract Cargo dependencies.\n> \n> If we check this in, then we basically cannot use any dependencies.  As\n> I mentioned elsewhere, the problem is that invariably, if we're going to\n> pin to an older version of Rust, we're going to be faced with the\n> problem that some crate is going to require a security update that is\n> also going to break older versions of Rust, and we will then have users\n> aggressively demanding on the list that we update it immediately and\n> ship a new release, breaking those older compilers.  (And yes, I've seen\n> this happen with Go dependencies on Git LFS, even when the vulnerable\n> code is not used.)\n\nHm. This one just feels weird to me. Doesn't it break reproducible\nbuilds and create new attack vectors for supply-chain attacks?\n\n> This is made worse by the fact that you want to support Rust 1.49\n> instead of Rust 1.63, as I proposed.  Absent some compelling proposal on\n> how we're going to deal with this situation, I think we need to omit\n> `Cargo.lock`.\n\nJust to clarify: this is only initially, until we have a good reason to\npick a later version of Rust. Right now, to the best of my knowledge\n(and please correct me if I'm wrong), we don't have any reason to use\nRust 1.63 yet.\n\nI'd like to pick the minimum version with a certain intent, where the\ncurrent intent is that 1.49 may ease the pressure on downstream users of\nGit via gcc-rs at one point in time. Once there are reasons for why we\nwant a newer version of Rust though we should definitely discuss whether\nit makes sense for us to bump the requirements.\n\nDoes that make sense?\n\n> I think the better approach is to leave it out and use Cargo to build\n> the Rust code instead of having Meson do it directly.\n> \n> > +# Starting with Meson 1.5, it knows to parse the \"Cargo.lock\" file and extract\n> > +# dependencies from it. So from hereon we don't need Cargo anymore to build\n> > +# Git.\n> \n> Ah, yes, I've already broken this in my branch (early this morning, in\n> fact).  I've added a `build.rs` file (used by Cargo) which is necessary\n> to properly link the tests against `libgit.a`.  (I'm using the hashing\n> code in some of my tests.) Meson fails to honour that and so the\n> compilation breaks.\n\nToo bad.\n\n> I don't think it's going to be viable to try to maintain two separate\n> build systems that build the Rust code.  Everyone who uses rust-analyzer\n> (the Rust LSP) will use Cargo because that's the build system it uses,\n> and everyone uses Cargo anyway, so as a practical matter we need to\n> support it.  Trying to have Meson do its own thing is unlikely to work\n> here, and it demands that we use the `Cargo.lock` file, which we'd like\n> to avoid.\n\nUnfortunate, but probably fair. Let's take the simple route for now and\npotentially iterate down the road.\n\n> > +  cargo_command = [\n> > +    cargo,\n> > +    'build',\n> > +    '--lib',\n> > +    '--quiet',\n> > +    '--manifest-path',\n> > +    meson.project_source_root() / 'Cargo.toml',\n> > +    '--target-dir',\n> > +    meson.current_build_dir() / 'target',\n> > +    # `--out-dir` is unstable, but supported since 2018. It's been recently\n> > +    # renamed to `--artifact-dir`, but for now both options are supported.\n> > +    '-Z',\n> > +    'unstable-options',\n> \n> `-Z` is only accepted in nightly versions of the compiler.  This won't\n> work with stable Rust and it definitely won't work with either 1.63 or\n> 1.49.  It didn't work for me using Rust 1.89.0 when I removed the other\n> branch.\n\nHuh, weird. No idea why it works on my system with Rust 1.89.0 then.\n\nIt's kind of puzzling that something as simple as specifying where Cargo\nputs the build artifacts is a nightly feature. All I really want is to\nsay `cargo build -o $PATH`. Oh, well...\n\nPatrick\n"},{"id":"526018","messageId":"740cf3c1-2d82-4675-ab22-80d1f362395e@gmail.com","threadId":"64091","inReplyTo":"aME1Bfv-IPq0zRG5@pks.im","subject":"Re: [PATCH RFC v2 0/7] Introduce Rust and announce that it will become mandatorty","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2025-09-10T09:32:02Z","receivedAt":"2025-09-10T09:32:06Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"On 10/09/2025 09:21, Patrick Steinhardt wrote:\n> On Tue, Sep 09, 2025 at 10:12:39AM +0100, Phillip Wood wrote:\n>> On 05/09/2025 15:28, Patrick Steinhardt wrote:\n>>> \n>>> I have a plan layed out in the BreakingChanges document that mentions\n>>> how I'm proposing to do the transition:\n>>>\n>>>     1. We introduce it with auto-detection for Meson and default-disabled\n>>>        for our Makefile in Git 2.52.\n>>\n>> I'm not sure how much this helps us. You've said elsewhere that you don't\n>> want to be inundated with bug reports which is fair enough, but I'm fairly\n>> skeptical that we're going to get enough people enabling this get a useful\n>> amount of early feedback. So I wonder if it would be better just to bite the\n>> bullet and enable it by default from the start. I think I saw Elijah making\n>> a similar argument elsewhere in this thread.\n> \n> The patch series may not be ready for all platforms yet though. Windows\n> support is still untested and probably not working, so I first need to\n> get that done. This is basically the reason why I'm proposing to have it\n> auto-detected at first: I want to be able to iterate without breaking\n> any platforms yet.\n> \n> How about we do a compromise: we initially introduce it\n> default-disabled, but default-enable it in the next release already\n> instead of first tying it to `-Dbreaking_changes=true`? That would\n> accelerate the proposed timeline a bit.\n\nIf we really can't get the windows support working before the next \nrelease then making it disabled by default on that platform makes sense \nand in that case it is probably simpler to make the default the same \nacross all platforms. It would be nice to get the windows side working, \nI had assumed that would be fairly easy because the patches exist in \nEzekiel's series but maybe I'm missing something. I'm also hopeless at \nkeeping track of when the next release is so maybe there isn't much time.\n\nThanks\n\nPhillip\n\n"},{"id":"526021","messageId":"aMFXqww91uxp_xCk@pks.im","threadId":"64091","inReplyTo":"740cf3c1-2d82-4675-ab22-80d1f362395e@gmail.com","subject":"Re: [PATCH RFC v2 0/7] Introduce Rust and announce that it will become mandatorty","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-10T10:49:15Z","receivedAt":"2025-09-10T10:49:25Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Wed, Sep 10, 2025 at 10:32:02AM +0100, Phillip Wood wrote:\n> On 10/09/2025 09:21, Patrick Steinhardt wrote:\n> > On Tue, Sep 09, 2025 at 10:12:39AM +0100, Phillip Wood wrote:\n> > > On 05/09/2025 15:28, Patrick Steinhardt wrote:\n> > > > \n> > > > I have a plan layed out in the BreakingChanges document that mentions\n> > > > how I'm proposing to do the transition:\n> > > > \n> > > >     1. We introduce it with auto-detection for Meson and default-disabled\n> > > >        for our Makefile in Git 2.52.\n> > > \n> > > I'm not sure how much this helps us. You've said elsewhere that you don't\n> > > want to be inundated with bug reports which is fair enough, but I'm fairly\n> > > skeptical that we're going to get enough people enabling this get a useful\n> > > amount of early feedback. So I wonder if it would be better just to bite the\n> > > bullet and enable it by default from the start. I think I saw Elijah making\n> > > a similar argument elsewhere in this thread.\n> > \n> > The patch series may not be ready for all platforms yet though. Windows\n> > support is still untested and probably not working, so I first need to\n> > get that done. This is basically the reason why I'm proposing to have it\n> > auto-detected at first: I want to be able to iterate without breaking\n> > any platforms yet.\n> > \n> > How about we do a compromise: we initially introduce it\n> > default-disabled, but default-enable it in the next release already\n> > instead of first tying it to `-Dbreaking_changes=true`? That would\n> > accelerate the proposed timeline a bit.\n> \n> If we really can't get the windows support working before the next release\n> then making it disabled by default on that platform makes sense and in that\n> case it is probably simpler to make the default the same across all\n> platforms. It would be nice to get the windows side working, I had assumed\n> that would be fairly easy because the patches exist in Ezekiel's series but\n> maybe I'm missing something. I'm also hopeless at keeping track of when the\n> next release is so maybe there isn't much time.\n\nOh, it's probably not going to be hard, and yes, I'll pick the patches\nfrom Ezekiel's series in the follow-up.\n\nMy intention here is to focus more on the overall roadmap in this patch\nseries though, so I'm trying to keep it as simple as possible initially.\nAgreeing on the roadmap is the more important thing, and seeing that we\ntalk about a timeline that is going to stretch across at least a year I\ndon't see a reason why we would need to rush making this opt-out rather\nthan opt-in.\n\nOne step at a time :)\n\nPatrick\n"},{"id":"526044","messageId":"20250910-b4-pks-rust-breaking-change-v4-0-4a63fc69278d@pks.im","threadId":"64091","inReplyTo":"20250904-b4-pks-rust-breaking-change-v1-0-3af1d25e0be9@pks.im","subject":"[PATCH RFC v4 0/9] Introduce Rust and announce that it will become mandatory","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-10T15:35:46Z","receivedAt":"2025-09-10T15:36:01Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Hi,\n\nthis small patch series introduces Rust into the core of Git. This patch\nseries is designed as a test balloon, similar to how we introduced test\nballoons for C99 features in the past. The goal is threefold:\n\n  - Give us some time to experiment with Rust and introduce proper build\n    infrastructure.\n\n  - Give distributors time to ease into the new toolchain requirements.\n    Introducing Rust is impossible for some platforms and hard for\n    others.\n\n  - Announce that Git 3.0 will make Rust a mandatory part of our build\n    infrastructure.\n\nThe test balloon itself is quite uninteresting: I've chosen to convert\nthe \"varint.c\" subsystem, mostly because it is trivial and does not have\nany dependencies. But it does allow us to verify that C to Rust interop\nworks as expected, and to play around with tooling. All tests pass with\nthe \"varint.rs\" implementation.\n\nFor now, the series only contains support for Meson. If we agree to go\ndown this route I'll also introduce support for Rust into our Makefiles\nat a later point in time.\n\nFurthermore missing is additional tooling:\n\n  - At least one CI job to verify that Rust builds and works as\n    expected.\n\n  - Tooling and CI jobs to ensure that we have consistent formatting via\n    `cargo format`.\n\nAnd probably lots more. As said, the entire goal is for us to have an\neasy playground that we can experiment on and develop the infrastructure\nincrementally without yet having to commit to anything.\n\nI'm mostly splitting out the topic of introducing Rust from the larger\nseries that introduce it into xdiff so that we can focus more on the\nactual process of introducing Rust into Git and less on the potential\nfeatures that we want to build on top of it.\n\nChanges in v2:\n  - Introduce support for building the Rust library via our Makefile.\n  - Introduce a '-DWITH_RUST' define. This define is used to print\n    whether or not Git is built with Rust via `git version\n    --build-options`.\n  - Adjust Meson to not depend on v1.9.0 and newer anymore.\n  - Introduce a roadmap into our BreakingChanges document to explain how\n    we'll iterate towards mandatory Rust support.\n  - Rework the Fedora job to do a full compile-and-test run with Meson\n    and breaking changes enabled.\n  - Adapt our breaking-changes jobs to enable Rust support.\n  - Link to v1: https://lore.kernel.org/r/20250904-b4-pks-rust-breaking-change-v1-0-3af1d25e0be9@pks.im\n\nChanges in v3:\n  - Reorder all uses of `WITH_RUST` after the include of \"config.mak\".\n  - Add a test to verify overflow behaviour in Rust and explicitly use\n    `add_wrapping()`.\n  - Use explicit dependencies for the Rust library in our Makefile.\n  - Fix Alma Linux CI job.\n  - Stop tying maintenance of our LTS release to the availability of\n    gcc-rs.\n  - Add a fallback to Meson to use cargo directly.\n  - I've fixed the Rust edition to 2018 for now. This is intentionally\n    conservative so that we might be able to use Rust 1.49. For now, we\n    don't have any reason to use a newer edition, either. So let's take\n    the oldest version we can live with for now and then bump it as\n    required.\n  - Link to v2: https://lore.kernel.org/r/20250905-b4-pks-rust-breaking-change-v2-0-6939cbf4a0b8@pks.im\n\nChanges in v4:\n  - Convert \"varint.c\" to use explicit integer width so that we don't\n    need to use C types in Rust.\n  - Adapt Meson to unconditionally use Cargo.\n  - Don't use the unstable `--out-dir` option in Cargo. Instead, we\n    resort to a wrapper script in Meson.\n  - Shorten the timeline a bit to drop the extra step that ties Rust\n    support to `-Dbreaking_changes=true`. This accelerates the timeline\n    until distros are made forcibly aware of the upcoming changes in\n    Rust.\n  - Link to v3: https://lore.kernel.org/r/20250908-b4-pks-rust-breaking-change-v3-0-1cd7189fed3b@pks.im\n\nThanks!\n\nPatrick\n\n---\nPatrick Steinhardt (9):\n      meson: add infrastructure to build internal Rust library\n      Makefile: reorder sources after includes\n      Makefile: introduce infrastructure to build internal Rust library\n      help: report on whether or not Rust is enabled\n      varint: use explicit width for integers\n      varint: reimplement as test balloon for Rust\n      BreakingChanges: announce Rust becoming mandatory\n      ci: convert \"pedantic\" job into full build with breaking changes\n      ci: enable Rust for breaking-changes jobs\n\n .github/workflows/main.yml         |   4 +-\n .gitignore                         |   2 +\n .gitlab-ci.yml                     |   4 +-\n Cargo.toml                         |   9 ++\n Documentation/BreakingChanges.adoc |  36 +++++++\n Makefile                           | 214 ++++++++++++++++++++++---------------\n ci/install-dependencies.sh         |   8 +-\n ci/run-build-and-tests.sh          |  31 ++----\n dir.c                              |  18 ++--\n help.c                             |   6 ++\n meson.build                        |  15 ++-\n meson_options.txt                  |   2 +\n read-cache.c                       |   6 +-\n shared.mak                         |   1 +\n src/cargo-meson.sh                 |  32 ++++++\n src/lib.rs                         |   1 +\n src/meson.build                    |  41 +++++++\n src/varint.rs                      |  92 ++++++++++++++++\n varint.c                           |   6 +-\n varint.h                           |   4 +-\n 20 files changed, 401 insertions(+), 131 deletions(-)\n\nRange-diff versus v3:\n\n 1:  a25408af71 <  -:  ---------- meson: add infrastructure to build internal Rust library\n -:  ---------- >  1:  ccdb7e264d meson: add infrastructure to build internal Rust library\n 2:  a9c639b0f3 =  2:  b88c80f7e9 Makefile: reorder sources after includes\n 3:  ccac54a247 !  3:  873f9d82f5 Makefile: introduce infrastructure to build internal Rust library\n    @@ .gitignore\n     @@\n      /fuzz_corpora\n     +/target/\n    ++/Cargo.lock\n      /GIT-BUILD-DIR\n      /GIT-BUILD-OPTIONS\n      /GIT-CFLAGS\n 4:  b357ff9463 =  4:  4e70509175 help: report on whether or not Rust is enabled\n -:  ---------- >  5:  bb4cf7cc82 varint: use explicit width for integers\n 5:  03a5e2ff68 !  6:  ef7b522b32 rust: implement a test balloon via the \"varint\" subsystem\n    @@ Metadata\n     Author: Patrick Steinhardt <ps@pks.im>\n     \n      ## Commit message ##\n    -    rust: implement a test balloon via the \"varint\" subsystem\n    +    varint: reimplement as test balloon for Rust\n     \n         Implement a trivial test balloon for our Rust build infrastructure by\n         reimplementing the \"varint.c\" subsystem in Rust. This subsystem is\n    @@ meson.build: libgit_sources = [\n        'version.c',\n        'versioncmp.c',\n        'walker.c',\n    -@@ meson.build: rust_option = get_option('rust').disable_auto_if(not rust_available)\n    +@@ meson.build: rust_option = get_option('rust').disable_auto_if(not cargo.found())\n      if rust_option.allowed()\n        subdir('src')\n        libgit_c_args += '-DWITH_RUST'\n    @@ src/meson.build\n     +  'varint.rs',\n      ]\n      \n    - if meson.version().version_compare('>=1.5.0')\n    + # Unfortunately we must use a wrapper command to move the output file into the\n     \n      ## src/varint.rs (new) ##\n     @@\n    -+use std::os::raw::c_int;\n    -+use std::os::raw::c_uchar;\n    -+\n     +#[no_mangle]\n    -+pub unsafe extern \"C\" fn decode_varint(bufp: *mut *const c_uchar) -> usize {\n    ++pub unsafe extern \"C\" fn decode_varint(bufp: *mut *const u8) -> usize {\n     +    let mut buf = *bufp;\n     +    let mut c = *buf;\n     +    let mut val = usize::from(c & 127);\n    @@ src/varint.rs (new)\n     +}\n     +\n     +#[no_mangle]\n    -+pub unsafe extern \"C\" fn encode_varint(value: usize, buf: *mut c_uchar) -> c_int {\n    ++pub unsafe extern \"C\" fn encode_varint(value: usize, buf: *mut u8) -> u8 {\n     +    let mut varint: [u8; 16] = [0; 16];\n     +    let mut pos = varint.len() - 1;\n     +\n    @@ src/varint.rs (new)\n     +        std::ptr::copy_nonoverlapping(varint.as_ptr().add(pos), buf, varint.len() - pos);\n     +    }\n     +\n    -+    (varint.len() - pos) as c_int\n    ++    (varint.len() - pos) as u8\n     +}\n     +\n     +#[cfg(test)]\n 6:  c88c614031 !  7:  55ce2bd5b2 BreakingChanges: announce Rust becoming mandatory\n    @@ Documentation/BreakingChanges.adoc: A prerequisite for this change is that the e\n     +1. Initially, with Git 2.52, support for Rust will be auto-detected by Meson and\n     +   disabled in our Makefile so that the project can sort out the initial\n     +   infrastructure.\n    -+2. In Git 2.53, support for Rust will be enabled by default in case Git is\n    -+   compiled with breaking changes. Breaking changes can be enabled for Meson by\n    -+   saying `meson configure -Dbreaking_changes=true` and for Makefile-based\n    -+   builds via `make WITH_BREAKING_CHANGES=YesPlease`. It will still be possible\n    -+   to compile with breaking changes, but explicitly disable Rust.\n    -+3. In Git 2.54, both build systems will default-enable support for Rust even\n    -+   when breaking changes aren't enabled. Consequently, builds will break by\n    -+   default if Rust is not available on the build host. The use of Rust can still\n    -+   be explicitly disabled via build flags.\n    -+4. In Git 3.0, the build options will be removed and support for Rust is\n    ++2. In Git 2.53, both build systems will default-enable support for Rust.\n    ++   Consequently, builds will break by default if Rust is not available on the\n    ++   build host. The use of Rust can still be explicitly disabled via build\n    ++   flags.\n    ++3. In Git 3.0, the build options will be removed and support for Rust is\n     +   mandatory.\n     ++\n     +You can explicitly ask both Meson and our Makefile-based system to enable Rust\n 7:  d4ef0c752e =  8:  16c5158046 ci: convert \"pedantic\" job into full build with breaking changes\n 8:  d6df25d0c1 !  9:  1831fce645 ci: enable Rust for breaking-changes jobs\n    @@ ci/install-dependencies.sh: fedora-*|almalinux-*)\n      \tesac\n      \tdnf -yq update >/dev/null &&\n     -\tdnf -yq install shadow-utils sudo make pkg-config gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel $MESON_DEPS >/dev/null\n    -+\tdnf -yq install shadow-utils sudo make pkg-config gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel $MESON_DEPS rustc >/dev/null\n    ++\tdnf -yq install shadow-utils sudo make pkg-config gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel $MESON_DEPS cargo >/dev/null\n      \t;;\n      ubuntu-*|i386/ubuntu-*|debian-*)\n      \t# Required so that apt doesn't wait for user input on certain packages.\n\n---\nbase-commit: 2462961280690837670d997bde64bd4ebf8ae66d\nchange-id: 20250904-b4-pks-rust-breaking-change-7167d9d3e37d\n\n"},{"id":"526045","messageId":"20250910-b4-pks-rust-breaking-change-v4-1-4a63fc69278d@pks.im","threadId":"64091","inReplyTo":"20250910-b4-pks-rust-breaking-change-v4-0-4a63fc69278d@pks.im","subject":"[PATCH RFC v4 1/9] meson: add infrastructure to build internal Rust library","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-10T15:35:47Z","receivedAt":"2025-09-10T15:36:04Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Add the infrastructure into Meson to build an internal Rust library.\nBuilding the Rust parts of Git are for now entirely optional, as they\nare mostly intended as a test balloon for both Git developers, but also\nfor distributors of Git. So for now, they may contain:\n\n  - New features that are not mission critical to Git and that users can\n    easily live without.\n\n  - Alternative implementations of small subsystems.\n\nIf these test balloons are successful, we will eventually make Rust a\nmandatory dependency for our build process in Git 3.0.\n\nThe availability of a Rust toolchain will be auto-detected by Meson at\nsetup time. This behaviour can be tweaked via the `-Drust=` feature\ntoggle.\n\nNext to the linkable Rust library, also wire up tests that can be\nexecuted via `meson test`. This allows us to use the native unit testing\ncapabilities of Rust.\n\nNote that the Rust edition is currently set to 2018. This edition is\nsupported by Rust 1.49, which is the target for the upcoming gcc-rs\nbackend. For now we don't use any features of Rust that would require a\nnewer version, so settling on this old version makes sense so that\ngcc-rs may become an alternative backend for compiling Git. If we _do_\nwant to introduce features that were added in more recent editions of\nRust though we should reevaluate that choice.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n Cargo.toml         |  9 +++++++++\n meson.build        | 10 +++++++++-\n meson_options.txt  |  2 ++\n src/cargo-meson.sh | 32 ++++++++++++++++++++++++++++++++\n src/lib.rs         |  0\n src/meson.build    | 40 ++++++++++++++++++++++++++++++++++++++++\n 6 files changed, 92 insertions(+), 1 deletion(-)\n\ndiff --git a/Cargo.toml b/Cargo.toml\nnew file mode 100644\nindex 00000000000..b9a41dbc792\n--- /dev/null\n+++ b/Cargo.toml\n@@ -0,0 +1,9 @@\n+[package]\n+name = \"git\"\n+version = \"0.1.0\"\n+edition = \"2018\"\n+\n+[lib]\n+crate-type = [\"staticlib\"]\n+\n+[dependencies]\ndiff --git a/meson.build b/meson.build\nindex e8ec0eca165..234a9e9d6fd 100644\n--- a/meson.build\n+++ b/meson.build\n@@ -220,7 +220,7 @@ project('git', 'c',\n   # learned to define __STDC_VERSION__ with C11 and later. We thus require\n   # GNU C99 and fall back to C11. Meson only learned to handle the fallback\n   # with version 1.3.0, so on older versions we use GNU C99 unconditionally.\n-  default_options: meson.version().version_compare('>=1.3.0') ? ['c_std=gnu99,c11'] : ['c_std=gnu99'],\n+  default_options: meson.version().version_compare('>=1.3.0') ? ['rust_std=2018', 'c_std=gnu99,c11'] : ['rust_std=2018', 'c_std=gnu99'],\n )\n \n fs = import('fs')\n@@ -1702,6 +1702,13 @@ version_def_h = custom_target(\n )\n libgit_sources += version_def_h\n \n+cargo = find_program('cargo', dirs: program_path, native: true, required: get_option('rust'))\n+rust_option = get_option('rust').disable_auto_if(not cargo.found())\n+if rust_option.allowed()\n+  subdir('src')\n+  libgit_c_args += '-DWITH_RUST'\n+endif\n+\n libgit = declare_dependency(\n   link_with: static_library('git',\n     sources: libgit_sources,\n@@ -2239,6 +2246,7 @@ summary({\n   'pcre2': pcre2,\n   'perl': perl_features_enabled,\n   'python': target_python.found(),\n+  'rust': rust_option.allowed(),\n }, section: 'Auto-detected features', bool_yn: true)\n \n summary({\ndiff --git a/meson_options.txt b/meson_options.txt\nindex 1668f260a18..143dee9237c 100644\n--- a/meson_options.txt\n+++ b/meson_options.txt\n@@ -71,6 +71,8 @@ option('zlib_backend', type: 'combo', choices: ['auto', 'zlib', 'zlib-ng'], valu\n # Build tweaks.\n option('breaking_changes', type: 'boolean', value: false,\n   description: 'Enable upcoming breaking changes.')\n+option('rust', type: 'feature', value: 'auto',\n+  description: 'Enable building with Rust.')\n option('macos_use_homebrew_gettext', type: 'boolean', value: true,\n   description: 'Use gettext from Homebrew instead of the slightly-broken system-provided one.')\n \ndiff --git a/src/cargo-meson.sh b/src/cargo-meson.sh\nnew file mode 100755\nindex 00000000000..f29745beb36\n--- /dev/null\n+++ b/src/cargo-meson.sh\n@@ -0,0 +1,32 @@\n+#!/bin/sh\n+\n+if test \"$#\" -lt 2\n+then\n+\texit 1\n+fi\n+\n+SOURCE_DIR=\"$1\"\n+BUILD_DIR=\"$2\"\n+BUILD_TYPE=debug\n+\n+shift 2\n+\n+for arg\n+do\n+\tcase \"$arg\" in\n+\t--release)\n+\t\tBUILD_TYPE=release;;\n+\tesac\n+done\n+\n+cargo build --lib --quiet --manifest-path=\"$SOURCE_DIR/Cargo.toml\" --target-dir=\"$BUILD_DIR\" \"$@\"\n+RET=$?\n+if test $RET -ne 0\n+then\n+\texit $RET\n+fi\n+\n+if ! cmp \"$BUILD_DIR/$BUILD_TYPE/libgit.a\" \"$BUILD_DIR/libgit.a\" >/dev/null 2>&1\n+then\n+\tcp \"$BUILD_DIR/$BUILD_TYPE/libgit.a\" \"$BUILD_DIR/libgit.a\"\n+fi\ndiff --git a/src/lib.rs b/src/lib.rs\nnew file mode 100644\nindex 00000000000..e69de29bb2d\ndiff --git a/src/meson.build b/src/meson.build\nnew file mode 100644\nindex 00000000000..734de0b4fa9\n--- /dev/null\n+++ b/src/meson.build\n@@ -0,0 +1,40 @@\n+libgit_rs_sources = [\n+  'lib.rs',\n+]\n+\n+# Unfortunately we must use a wrapper command to move the output file into the\n+# current build directory. This can fixed once `cargo build --artifact-dir`\n+# stabilizes. See https://github.com/rust-lang/cargo/issues/6790 for that\n+# effort.\n+cargo_command = [\n+  shell,\n+  meson.current_source_dir() / 'cargo-meson.sh',\n+  meson.project_source_root(),\n+  meson.current_build_dir(),\n+]\n+if get_option('buildtype') == 'release'\n+  cargo_command += '--release'\n+endif\n+\n+libgit_rs = custom_target('git_rs',\n+  input: libgit_rs_sources + [\n+    meson.project_source_root() / 'Cargo.toml',\n+  ],\n+  output: 'libgit.a',\n+  command: cargo_command,\n+)\n+libgit_dependencies += declare_dependency(link_with: libgit_rs)\n+\n+if get_option('tests')\n+  test('rust', cargo,\n+    args: [\n+      'test',\n+      '--manifest-path',\n+      meson.project_source_root() / 'Cargo.toml',\n+      '--target-dir',\n+      meson.current_build_dir() / 'target',\n+    ],\n+    timeout: 0,\n+    protocol: 'rust',\n+  )\n+endif\n\n-- \n2.51.0.450.g87641ccf93.dirty\n\n"},{"id":"526046","messageId":"20250910-b4-pks-rust-breaking-change-v4-2-4a63fc69278d@pks.im","threadId":"64091","inReplyTo":"20250910-b4-pks-rust-breaking-change-v4-0-4a63fc69278d@pks.im","subject":"[PATCH RFC v4 2/9] Makefile: reorder sources after includes","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-10T15:35:48Z","receivedAt":"2025-09-10T15:36:07Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"In an upcoming change we'll make some of the sources compile\nconditionally based on whether or not `WITH_RUST` is defined. To let\ndevelopers specify that flag in their \"config.mak\" we'll thus have to\nreorder our sources so that they come after the include of that file.\n\nDo so.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n Makefile | 176 +++++++++++++++++++++++++++++++--------------------------------\n 1 file changed, 88 insertions(+), 88 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 555b7f4dc3..7e52625d75 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -919,6 +919,94 @@ LIB_FILE = libgit.a\n XDIFF_LIB = xdiff/lib.a\n REFTABLE_LIB = reftable/libreftable.a\n \n+# xdiff and reftable libs may in turn depend on what is in libgit.a\n+GITLIBS = common-main.o $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(LIB_FILE)\n+EXTLIBS =\n+\n+GIT_USER_AGENT = git/$(GIT_VERSION)\n+\n+ifeq ($(wildcard sha1collisiondetection/lib/sha1.h),sha1collisiondetection/lib/sha1.h)\n+DC_SHA1_SUBMODULE = auto\n+endif\n+\n+# Set CFLAGS, LDFLAGS and other *FLAGS variables. These might be\n+# tweaked by config.* below as well as the command-line, both of\n+# which'll override these defaults.\n+# Older versions of GCC may require adding \"-std=gnu99\" at the end.\n+CFLAGS = -g -O2 -Wall\n+LDFLAGS =\n+CC_LD_DYNPATH = -Wl,-rpath,\n+BASIC_CFLAGS = -I.\n+BASIC_LDFLAGS =\n+\n+# library flags\n+ARFLAGS = rcs\n+PTHREAD_CFLAGS =\n+\n+# For the 'sparse' target\n+SPARSE_FLAGS ?= -std=gnu99 -D__STDC_NO_VLA__\n+SP_EXTRA_FLAGS =\n+\n+# For informing GIT-BUILD-OPTIONS of the SANITIZE=leak,address targets\n+SANITIZE_LEAK =\n+SANITIZE_ADDRESS =\n+\n+# For the 'coccicheck' target\n+SPATCH_INCLUDE_FLAGS = --all-includes\n+SPATCH_FLAGS =\n+SPATCH_TEST_FLAGS =\n+\n+# If *.o files are present, have \"coccicheck\" depend on them, with\n+# COMPUTE_HEADER_DEPENDENCIES this will speed up the common-case of\n+# only needing to re-generate coccicheck results for the users of a\n+# given API if it's changed, and not all files in the project. If\n+# COMPUTE_HEADER_DEPENDENCIES=no this will be unset too.\n+SPATCH_USE_O_DEPENDENCIES = YesPlease\n+\n+# Set SPATCH_CONCAT_COCCI to concatenate the contrib/cocci/*.cocci\n+# files into a single contrib/cocci/ALL.cocci before running\n+# \"coccicheck\".\n+#\n+# Pros:\n+#\n+# - Speeds up a one-shot run of \"make coccicheck\", as we won't have to\n+#   parse *.[ch] files N times for the N *.cocci rules\n+#\n+# Cons:\n+#\n+# - Will make incremental development of *.cocci slower, as\n+#   e.g. changing strbuf.cocci will re-run all *.cocci.\n+#\n+# - Makes error and performance analysis harder, as rules will be\n+#   applied from a monolithic ALL.cocci, rather than\n+#   e.g. strbuf.cocci. To work around this either undefine this, or\n+#   generate a specific patch, e.g. this will always use strbuf.cocci,\n+#   not ALL.cocci:\n+#\n+#\tmake contrib/coccinelle/strbuf.cocci.patch\n+SPATCH_CONCAT_COCCI = YesPlease\n+\n+# Rebuild 'coccicheck' if $(SPATCH), its flags etc. change\n+TRACK_SPATCH_DEFINES =\n+TRACK_SPATCH_DEFINES += $(SPATCH)\n+TRACK_SPATCH_DEFINES += $(SPATCH_INCLUDE_FLAGS)\n+TRACK_SPATCH_DEFINES += $(SPATCH_FLAGS)\n+TRACK_SPATCH_DEFINES += $(SPATCH_TEST_FLAGS)\n+GIT-SPATCH-DEFINES: FORCE\n+\t@FLAGS='$(TRACK_SPATCH_DEFINES)'; \\\n+\t    if test x\"$$FLAGS\" != x\"`cat GIT-SPATCH-DEFINES 2>/dev/null`\" ; then \\\n+\t\techo >&2 \"    * new spatch flags\"; \\\n+\t\techo \"$$FLAGS\" >GIT-SPATCH-DEFINES; \\\n+            fi\n+\n+include config.mak.uname\n+-include config.mak.autogen\n+-include config.mak\n+\n+ifdef DEVELOPER\n+include config.mak.dev\n+endif\n+\n GENERATED_H += command-list.h\n GENERATED_H += config-list.h\n GENERATED_H += hook-list.h\n@@ -1387,94 +1475,6 @@ CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/unit-test.o\n \n UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o\n \n-# xdiff and reftable libs may in turn depend on what is in libgit.a\n-GITLIBS = common-main.o $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(LIB_FILE)\n-EXTLIBS =\n-\n-GIT_USER_AGENT = git/$(GIT_VERSION)\n-\n-ifeq ($(wildcard sha1collisiondetection/lib/sha1.h),sha1collisiondetection/lib/sha1.h)\n-DC_SHA1_SUBMODULE = auto\n-endif\n-\n-# Set CFLAGS, LDFLAGS and other *FLAGS variables. These might be\n-# tweaked by config.* below as well as the command-line, both of\n-# which'll override these defaults.\n-# Older versions of GCC may require adding \"-std=gnu99\" at the end.\n-CFLAGS = -g -O2 -Wall\n-LDFLAGS =\n-CC_LD_DYNPATH = -Wl,-rpath,\n-BASIC_CFLAGS = -I.\n-BASIC_LDFLAGS =\n-\n-# library flags\n-ARFLAGS = rcs\n-PTHREAD_CFLAGS =\n-\n-# For the 'sparse' target\n-SPARSE_FLAGS ?= -std=gnu99 -D__STDC_NO_VLA__\n-SP_EXTRA_FLAGS =\n-\n-# For informing GIT-BUILD-OPTIONS of the SANITIZE=leak,address targets\n-SANITIZE_LEAK =\n-SANITIZE_ADDRESS =\n-\n-# For the 'coccicheck' target\n-SPATCH_INCLUDE_FLAGS = --all-includes\n-SPATCH_FLAGS =\n-SPATCH_TEST_FLAGS =\n-\n-# If *.o files are present, have \"coccicheck\" depend on them, with\n-# COMPUTE_HEADER_DEPENDENCIES this will speed up the common-case of\n-# only needing to re-generate coccicheck results for the users of a\n-# given API if it's changed, and not all files in the project. If\n-# COMPUTE_HEADER_DEPENDENCIES=no this will be unset too.\n-SPATCH_USE_O_DEPENDENCIES = YesPlease\n-\n-# Set SPATCH_CONCAT_COCCI to concatenate the contrib/cocci/*.cocci\n-# files into a single contrib/cocci/ALL.cocci before running\n-# \"coccicheck\".\n-#\n-# Pros:\n-#\n-# - Speeds up a one-shot run of \"make coccicheck\", as we won't have to\n-#   parse *.[ch] files N times for the N *.cocci rules\n-#\n-# Cons:\n-#\n-# - Will make incremental development of *.cocci slower, as\n-#   e.g. changing strbuf.cocci will re-run all *.cocci.\n-#\n-# - Makes error and performance analysis harder, as rules will be\n-#   applied from a monolithic ALL.cocci, rather than\n-#   e.g. strbuf.cocci. To work around this either undefine this, or\n-#   generate a specific patch, e.g. this will always use strbuf.cocci,\n-#   not ALL.cocci:\n-#\n-#\tmake contrib/coccinelle/strbuf.cocci.patch\n-SPATCH_CONCAT_COCCI = YesPlease\n-\n-# Rebuild 'coccicheck' if $(SPATCH), its flags etc. change\n-TRACK_SPATCH_DEFINES =\n-TRACK_SPATCH_DEFINES += $(SPATCH)\n-TRACK_SPATCH_DEFINES += $(SPATCH_INCLUDE_FLAGS)\n-TRACK_SPATCH_DEFINES += $(SPATCH_FLAGS)\n-TRACK_SPATCH_DEFINES += $(SPATCH_TEST_FLAGS)\n-GIT-SPATCH-DEFINES: FORCE\n-\t@FLAGS='$(TRACK_SPATCH_DEFINES)'; \\\n-\t    if test x\"$$FLAGS\" != x\"`cat GIT-SPATCH-DEFINES 2>/dev/null`\" ; then \\\n-\t\techo >&2 \"    * new spatch flags\"; \\\n-\t\techo \"$$FLAGS\" >GIT-SPATCH-DEFINES; \\\n-            fi\n-\n-include config.mak.uname\n--include config.mak.autogen\n--include config.mak\n-\n-ifdef DEVELOPER\n-include config.mak.dev\n-endif\n-\n GIT-VERSION-FILE: FORCE\n \t@OLD=$$(cat $@ 2>/dev/null || :) && \\\n \t$(call version_gen,\"$(shell pwd)\",GIT-VERSION-FILE.in,$@) && \\\n\n-- \n2.51.0.450.g87641ccf93.dirty\n\n"},{"id":"526047","messageId":"20250910-b4-pks-rust-breaking-change-v4-3-4a63fc69278d@pks.im","threadId":"64091","inReplyTo":"20250910-b4-pks-rust-breaking-change-v4-0-4a63fc69278d@pks.im","subject":"[PATCH RFC v4 3/9] Makefile: introduce infrastructure to build internal Rust library","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-10T15:35:49Z","receivedAt":"2025-09-10T15:36:09Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Introduce infrastructure to build the internal Rust library. This\nmirrors the infrastructure we have added to Meson in the preceding\ncommit. Developers can enable the infrastructure by passing the new\n`WITH_RUST` build toggle.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n .gitignore |  2 ++\n Makefile   | 37 +++++++++++++++++++++++++++++++++++++\n shared.mak |  1 +\n 3 files changed, 40 insertions(+)\n\ndiff --git a/.gitignore b/.gitignore\nindex 1803023427..0833453cf6 100644\n--- a/.gitignore\n+++ b/.gitignore\n@@ -1,4 +1,6 @@\n /fuzz_corpora\n+/target/\n+/Cargo.lock\n /GIT-BUILD-DIR\n /GIT-BUILD-OPTIONS\n /GIT-CFLAGS\ndiff --git a/Makefile b/Makefile\nindex 7e52625d75..94950a0ffe 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -483,6 +483,14 @@ include shared.mak\n # Define LIBPCREDIR=/foo/bar if your PCRE header and library files are\n # in /foo/bar/include and /foo/bar/lib directories.\n #\n+# == Optional Rust support ==\n+#\n+# Define WITH_RUST if you want to include features and subsystems written in\n+# Rust into Git. For now, Rust is still an optional feature of the build\n+# process. With Git 3.0 though, Rust will always be enabled.\n+#\n+# Building Rust code requires Cargo.\n+#\n # == SHA-1 and SHA-256 defines ==\n #\n # === SHA-1 backend ===\n@@ -683,6 +691,7 @@ OBJECTS =\n OTHER_PROGRAMS =\n PROGRAM_OBJS =\n PROGRAMS =\n+RUST_SOURCES =\n EXCLUDED_PROGRAMS =\n SCRIPT_PERL =\n SCRIPT_PYTHON =\n@@ -918,6 +927,11 @@ TEST_SHELL_PATH = $(SHELL_PATH)\n LIB_FILE = libgit.a\n XDIFF_LIB = xdiff/lib.a\n REFTABLE_LIB = reftable/libreftable.a\n+ifdef DEBUG\n+RUST_LIB = target/debug/libgit.a\n+else\n+RUST_LIB = target/release/libgit.a\n+endif\n \n # xdiff and reftable libs may in turn depend on what is in libgit.a\n GITLIBS = common-main.o $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(LIB_FILE)\n@@ -943,6 +957,15 @@ BASIC_LDFLAGS =\n ARFLAGS = rcs\n PTHREAD_CFLAGS =\n \n+# Rust flags\n+CARGO_ARGS =\n+ifndef V\n+CARGO_ARGS += --quiet\n+endif\n+ifndef DEBUG\n+CARGO_ARGS += --release\n+endif\n+\n # For the 'sparse' target\n SPARSE_FLAGS ?= -std=gnu99 -D__STDC_NO_VLA__\n SP_EXTRA_FLAGS =\n@@ -1475,6 +1498,8 @@ CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/unit-test.o\n \n UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o\n \n+RUST_SOURCES += src/lib.rs\n+\n GIT-VERSION-FILE: FORCE\n \t@OLD=$$(cat $@ 2>/dev/null || :) && \\\n \t$(call version_gen,\"$(shell pwd)\",GIT-VERSION-FILE.in,$@) && \\\n@@ -1504,6 +1529,11 @@ endif\n ALL_CFLAGS = $(DEVELOPER_CFLAGS) $(CPPFLAGS) $(CFLAGS) $(CFLAGS_APPEND)\n ALL_LDFLAGS = $(LDFLAGS) $(LDFLAGS_APPEND)\n \n+ifdef WITH_RUST\n+BASIC_CFLAGS += -DWITH_RUST\n+GITLIBS += $(RUST_LIB)\n+endif\n+\n ifdef SANITIZE\n SANITIZERS := $(foreach flag,$(subst $(comma),$(space),$(SANITIZE)),$(flag))\n BASIC_CFLAGS += -fsanitize=$(SANITIZE) -fno-sanitize-recover=$(SANITIZE)\n@@ -2918,6 +2948,12 @@ scalar$X: scalar.o GIT-LDFLAGS $(GITLIBS)\n $(LIB_FILE): $(LIB_OBJS)\n \t$(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^\n \n+$(RUST_LIB): Cargo.toml $(RUST_SOURCES)\n+\t$(QUIET_CARGO)cargo build $(CARGO_ARGS)\n+\n+.PHONY: rust\n+rust: $(RUST_LIB)\n+\n $(XDIFF_LIB): $(XDIFF_OBJS)\n \t$(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^\n \n@@ -3768,6 +3804,7 @@ clean: profile-clean coverage-clean cocciclean\n \t$(RM) $(FUZZ_PROGRAMS)\n \t$(RM) $(SP_OBJ)\n \t$(RM) $(HCC)\n+\t$(RM) -r target/\n \t$(RM) version-def.h\n \t$(RM) -r $(dep_dirs) $(compdb_dir) compile_commands.json\n \t$(RM) $(test_bindir_programs)\ndiff --git a/shared.mak b/shared.mak\nindex 5c7bc94785..0e7492076e 100644\n--- a/shared.mak\n+++ b/shared.mak\n@@ -56,6 +56,7 @@ ifndef V\n \tQUIET_MKDIR_P_PARENT  = @echo '   ' MKDIR -p $(@D);\n \n ## Used in \"Makefile\"\n+\tQUIET_CARGO    = @echo '   ' CARGO $@;\n \tQUIET_CC       = @echo '   ' CC $@;\n \tQUIET_AR       = @echo '   ' AR $@;\n \tQUIET_LINK     = @echo '   ' LINK $@;\n\n-- \n2.51.0.450.g87641ccf93.dirty\n\n"},{"id":"526048","messageId":"20250910-b4-pks-rust-breaking-change-v4-4-4a63fc69278d@pks.im","threadId":"64091","inReplyTo":"20250910-b4-pks-rust-breaking-change-v4-0-4a63fc69278d@pks.im","subject":"[PATCH RFC v4 4/9] help: report on whether or not Rust is enabled","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-10T15:35:50Z","receivedAt":"2025-09-10T15:36:11Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"We're about to introduce support for Rust into the core of Git, where\nsome (trivial) subsystems are converted to Rust. These subsystems will\nalso retain a C implementation though as Rust is not yet mandatory.\nConsequently, it now becomes possible for a Git version to have bugs\nthat are specific to whether or not it is built with Rust support\noverall.\n\nExpose information about whether or not Git was built with Rust via our\nbuild info. This means that both `git version --build-options`, but also\n`git bugreport` will now expose that bit of information. Hopefully, this\nshould make it easier for us to discover any Rust-specific issues.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n help.c | 6 ++++++\n 1 file changed, 6 insertions(+)\n\ndiff --git a/help.c b/help.c\nindex bb20498cfd..5854dd4a7e 100644\n--- a/help.c\n+++ b/help.c\n@@ -791,6 +791,12 @@ void get_version_info(struct strbuf *buf, int show_build_options)\n \t\tstrbuf_addf(buf, \"shell-path: %s\\n\", SHELL_PATH);\n \t\t/* NEEDSWORK: also save and output GIT-BUILD_OPTIONS? */\n \n+#if defined WITH_RUST\n+\t\tstrbuf_addstr(buf, \"rust: enabled\\n\");\n+#else\n+\t\tstrbuf_addstr(buf, \"rust: disabled\\n\");\n+#endif\n+\n \t\tif (fsmonitor_ipc__is_supported())\n \t\t\tstrbuf_addstr(buf, \"feature: fsmonitor--daemon\\n\");\n #if defined LIBCURL_VERSION\n\n-- \n2.51.0.450.g87641ccf93.dirty\n\n"},{"id":"526049","messageId":"20250910-b4-pks-rust-breaking-change-v4-5-4a63fc69278d@pks.im","threadId":"64091","inReplyTo":"20250910-b4-pks-rust-breaking-change-v4-0-4a63fc69278d@pks.im","subject":"[PATCH RFC v4 5/9] varint: use explicit width for integers","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-10T15:35:51Z","receivedAt":"2025-09-10T15:36:15Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The varint subsystem currently uses implcit widths for integers. On the\none hand we use `uintmax_t` for the actual value. On the other hand, we\nuse `int` for the length of the encoded varint.\n\nBoth of these have known maximum vaules, as we only support at most 16\nbytes when encoding varints. Thus, we know that we won't ever exceed\n`uint64_t` for the actual value and `uint8_t` for the prefix length.\n\nRefactor the code to use explicit widths. Besides making the logic\nplatform-independent, it also makes our life a bit easier in the next\ncommit, where we reimplement \"varint.c\" in Rust.\n\nSuggested-by: Ezekiel Newren <ezekielnewren@gmail.com>\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n dir.c        | 18 ++++++++++--------\n read-cache.c |  6 ++++--\n varint.c     |  6 +++---\n varint.h     |  4 ++--\n 4 files changed, 19 insertions(+), 15 deletions(-)\n\ndiff --git a/dir.c b/dir.c\nindex 71108ac79b7..0a67a99cb3d 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -3579,7 +3579,8 @@ static void write_one_dir(struct untracked_cache_dir *untracked,\n \tstruct stat_data stat_data;\n \tstruct strbuf *out = &wd->out;\n \tunsigned char intbuf[16];\n-\tunsigned int intlen, value;\n+\tunsigned int value;\n+\tuint8_t intlen;\n \tint i = wd->index++;\n \n \t/*\n@@ -3632,7 +3633,7 @@ void write_untracked_extension(struct strbuf *out, struct untracked_cache *untra\n \tstruct ondisk_untracked_cache *ouc;\n \tstruct write_data wd;\n \tunsigned char varbuf[16];\n-\tint varint_len;\n+\tuint8_t varint_len;\n \tconst unsigned hashsz = the_hash_algo->rawsz;\n \n \tCALLOC_ARRAY(ouc, 1);\n@@ -3738,7 +3739,7 @@ static int read_one_dir(struct untracked_cache_dir **untracked_,\n \tstruct untracked_cache_dir ud, *untracked;\n \tconst unsigned char *data = rd->data, *end = rd->end;\n \tconst unsigned char *eos;\n-\tunsigned int value;\n+\tuint64_t value;\n \tint i;\n \n \tmemset(&ud, 0, sizeof(ud));\n@@ -3830,7 +3831,8 @@ struct untracked_cache *read_untracked_extension(const void *data, unsigned long\n \tstruct read_data rd;\n \tconst unsigned char *next = data, *end = (const unsigned char *)data + sz;\n \tconst char *ident;\n-\tint ident_len;\n+\tuint64_t ident_len;\n+\tuint64_t varint_len;\n \tssize_t len;\n \tconst char *exclude_per_dir;\n \tconst unsigned hashsz = the_hash_algo->rawsz;\n@@ -3867,8 +3869,8 @@ struct untracked_cache *read_untracked_extension(const void *data, unsigned long\n \tif (next >= end)\n \t\tgoto done2;\n \n-\tlen = decode_varint(&next);\n-\tif (next > end || len == 0)\n+\tvarint_len = decode_varint(&next);\n+\tif (next > end || varint_len == 0)\n \t\tgoto done2;\n \n \trd.valid      = ewah_new();\n@@ -3877,9 +3879,9 @@ struct untracked_cache *read_untracked_extension(const void *data, unsigned long\n \trd.data\t      = next;\n \trd.end\t      = end;\n \trd.index      = 0;\n-\tALLOC_ARRAY(rd.ucd, len);\n+\tALLOC_ARRAY(rd.ucd, varint_len);\n \n-\tif (read_one_dir(&uc->root, &rd) || rd.index != len)\n+\tif (read_one_dir(&uc->root, &rd) || rd.index != varint_len)\n \t\tgoto done;\n \n \tnext = rd.data;\ndiff --git a/read-cache.c b/read-cache.c\nindex 06ad74db228..41b44148b1e 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -1807,7 +1807,7 @@ static struct cache_entry *create_from_disk(struct mem_pool *ce_mem_pool,\n \n \tif (expand_name_field) {\n \t\tconst unsigned char *cp = (const unsigned char *)name;\n-\t\tsize_t strip_len, previous_len;\n+\t\tuint64_t strip_len, previous_len;\n \n \t\t/* If we're at the beginning of a block, ignore the previous name */\n \t\tstrip_len = decode_varint(&cp);\n@@ -2655,8 +2655,10 @@ static int ce_write_entry(struct hashfile *f, struct cache_entry *ce,\n \t\thashwrite(f, ce->name, len);\n \t\thashwrite(f, padding, align_padding_size(size, len));\n \t} else {\n-\t\tint common, to_remove, prefix_size;\n+\t\tint common, to_remove;\n+\t\tuint8_t prefix_size;\n \t\tunsigned char to_remove_vi[16];\n+\n \t\tfor (common = 0;\n \t\t     (common < previous_name->len &&\n \t\t      ce->name[common] &&\ndiff --git a/varint.c b/varint.c\nindex 409c4977a1e..03cd54416b6 100644\n--- a/varint.c\n+++ b/varint.c\n@@ -1,11 +1,11 @@\n #include \"git-compat-util.h\"\n #include \"varint.h\"\n \n-uintmax_t decode_varint(const unsigned char **bufp)\n+uint64_t decode_varint(const unsigned char **bufp)\n {\n \tconst unsigned char *buf = *bufp;\n \tunsigned char c = *buf++;\n-\tuintmax_t val = c & 127;\n+\tuint64_t val = c & 127;\n \twhile (c & 128) {\n \t\tval += 1;\n \t\tif (!val || MSB(val, 7))\n@@ -17,7 +17,7 @@ uintmax_t decode_varint(const unsigned char **bufp)\n \treturn val;\n }\n \n-int encode_varint(uintmax_t value, unsigned char *buf)\n+uint8_t encode_varint(uint64_t value, unsigned char *buf)\n {\n \tunsigned char varint[16];\n \tunsigned pos = sizeof(varint) - 1;\ndiff --git a/varint.h b/varint.h\nindex f78bb0ca528..eb401935bd2 100644\n--- a/varint.h\n+++ b/varint.h\n@@ -1,7 +1,7 @@\n #ifndef VARINT_H\n #define VARINT_H\n \n-int encode_varint(uintmax_t, unsigned char *);\n-uintmax_t decode_varint(const unsigned char **);\n+uint8_t encode_varint(uint64_t, unsigned char *);\n+uint64_t decode_varint(const unsigned char **);\n \n #endif /* VARINT_H */\n\n-- \n2.51.0.450.g87641ccf93.dirty\n\n"},{"id":"526050","messageId":"20250910-b4-pks-rust-breaking-change-v4-6-4a63fc69278d@pks.im","threadId":"64091","inReplyTo":"20250910-b4-pks-rust-breaking-change-v4-0-4a63fc69278d@pks.im","subject":"[PATCH RFC v4 6/9] varint: reimplement as test balloon for Rust","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-10T15:35:52Z","receivedAt":"2025-09-10T15:36:18Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Implement a trivial test balloon for our Rust build infrastructure by\nreimplementing the \"varint.c\" subsystem in Rust. This subsystem is\nchosen because it is trivial to convert and because it doesn't have any\ndependencies to other components of Git.\n\nIf support for Rust is enabled, we stop compiling \"varint.c\" and instead\ncompile and use \"src/varint.rs\".\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n Makefile        |  3 ++\n meson.build     |  5 +++-\n src/lib.rs      |  1 +\n src/meson.build |  1 +\n src/varint.rs   | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n 5 files changed, 101 insertions(+), 1 deletion(-)\n\ndiff --git a/Makefile b/Makefile\nindex 94950a0ffe2..7640d0d76ac 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -1307,7 +1307,9 @@ LIB_OBJS += urlmatch.o\n LIB_OBJS += usage.o\n LIB_OBJS += userdiff.o\n LIB_OBJS += utf8.o\n+ifndef WITH_RUST\n LIB_OBJS += varint.o\n+endif\n LIB_OBJS += version.o\n LIB_OBJS += versioncmp.o\n LIB_OBJS += walker.o\n@@ -1499,6 +1501,7 @@ CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/unit-test.o\n UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o\n \n RUST_SOURCES += src/lib.rs\n+RUST_SOURCES += src/varint.rs\n \n GIT-VERSION-FILE: FORCE\n \t@OLD=$$(cat $@ 2>/dev/null || :) && \\\ndiff --git a/meson.build b/meson.build\nindex 234a9e9d6fd..37dfa286017 100644\n--- a/meson.build\n+++ b/meson.build\n@@ -522,7 +522,6 @@ libgit_sources = [\n   'usage.c',\n   'userdiff.c',\n   'utf8.c',\n-  'varint.c',\n   'version.c',\n   'versioncmp.c',\n   'walker.c',\n@@ -1707,6 +1706,10 @@ rust_option = get_option('rust').disable_auto_if(not cargo.found())\n if rust_option.allowed()\n   subdir('src')\n   libgit_c_args += '-DWITH_RUST'\n+else\n+  libgit_sources += [\n+    'varint.c',\n+  ]\n endif\n \n libgit = declare_dependency(\ndiff --git a/src/lib.rs b/src/lib.rs\nindex e69de29bb2d..9da70d8b57d 100644\n--- a/src/lib.rs\n+++ b/src/lib.rs\n@@ -0,0 +1 @@\n+pub mod varint;\ndiff --git a/src/meson.build b/src/meson.build\nindex 734de0b4fa9..b19ef4c0b51 100644\n--- a/src/meson.build\n+++ b/src/meson.build\n@@ -1,5 +1,6 @@\n libgit_rs_sources = [\n   'lib.rs',\n+  'varint.rs',\n ]\n \n # Unfortunately we must use a wrapper command to move the output file into the\ndiff --git a/src/varint.rs b/src/varint.rs\nnew file mode 100644\nindex 00000000000..10c83e1f439\n--- /dev/null\n+++ b/src/varint.rs\n@@ -0,0 +1,92 @@\n+#[no_mangle]\n+pub unsafe extern \"C\" fn decode_varint(bufp: *mut *const u8) -> usize {\n+    let mut buf = *bufp;\n+    let mut c = *buf;\n+    let mut val = usize::from(c & 127);\n+\n+    buf = buf.add(1);\n+\n+    while (c & 128) != 0 {\n+        val = val.wrapping_add(1);\n+        if val == 0 || val.leading_zeros() < 7 {\n+            return 0; // overflow\n+        }\n+\n+        c = *buf;\n+        buf = buf.add(1);\n+\n+        val = (val << 7) + usize::from(c & 127);\n+    }\n+\n+    *bufp = buf;\n+    val\n+}\n+\n+#[no_mangle]\n+pub unsafe extern \"C\" fn encode_varint(value: usize, buf: *mut u8) -> u8 {\n+    let mut varint: [u8; 16] = [0; 16];\n+    let mut pos = varint.len() - 1;\n+\n+    varint[pos] = (value & 127) as u8;\n+\n+    let mut value = value >> 7;\n+    while value != 0 {\n+        pos -= 1;\n+        value -= 1;\n+        varint[pos] = 128 | (value & 127) as u8;\n+        value >>= 7;\n+    }\n+\n+    if !buf.is_null() {\n+        std::ptr::copy_nonoverlapping(varint.as_ptr().add(pos), buf, varint.len() - pos);\n+    }\n+\n+    (varint.len() - pos) as u8\n+}\n+\n+#[cfg(test)]\n+mod tests {\n+    use super::*;\n+\n+    #[test]\n+    fn test_decode_varint() {\n+        unsafe {\n+            assert_eq!(decode_varint(&mut [0x00].as_slice().as_ptr()), 0);\n+            assert_eq!(decode_varint(&mut [0x01].as_slice().as_ptr()), 1);\n+            assert_eq!(decode_varint(&mut [0x7f].as_slice().as_ptr()), 127);\n+            assert_eq!(decode_varint(&mut [0x80, 0x00].as_slice().as_ptr()), 128);\n+            assert_eq!(decode_varint(&mut [0x80, 0x01].as_slice().as_ptr()), 129);\n+            assert_eq!(decode_varint(&mut [0x80, 0x7f].as_slice().as_ptr()), 255);\n+\n+            // Overflows are expected to return 0.\n+            assert_eq!(decode_varint(&mut [0x88; 16].as_slice().as_ptr()), 0);\n+        }\n+    }\n+\n+    #[test]\n+    fn test_encode_varint() {\n+        unsafe {\n+            let mut varint: [u8; 16] = [0; 16];\n+\n+            assert_eq!(encode_varint(0, std::ptr::null_mut()), 1);\n+\n+            assert_eq!(encode_varint(0, varint.as_mut_slice().as_mut_ptr()), 1);\n+            assert_eq!(varint, [0; 16]);\n+\n+            assert_eq!(encode_varint(10, varint.as_mut_slice().as_mut_ptr()), 1);\n+            assert_eq!(varint, [10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n+\n+            assert_eq!(encode_varint(127, varint.as_mut_slice().as_mut_ptr()), 1);\n+            assert_eq!(varint, [127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n+\n+            assert_eq!(encode_varint(128, varint.as_mut_slice().as_mut_ptr()), 2);\n+            assert_eq!(varint, [128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n+\n+            assert_eq!(encode_varint(129, varint.as_mut_slice().as_mut_ptr()), 2);\n+            assert_eq!(varint, [128, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n+\n+            assert_eq!(encode_varint(255, varint.as_mut_slice().as_mut_ptr()), 2);\n+            assert_eq!(varint, [128, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n+        }\n+    }\n+}\n\n-- \n2.51.0.450.g87641ccf93.dirty\n\n"},{"id":"526051","messageId":"20250910-b4-pks-rust-breaking-change-v4-7-4a63fc69278d@pks.im","threadId":"64091","inReplyTo":"20250910-b4-pks-rust-breaking-change-v4-0-4a63fc69278d@pks.im","subject":"[PATCH RFC v4 7/9] BreakingChanges: announce Rust becoming mandatory","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-10T15:35:53Z","receivedAt":"2025-09-10T15:36:21Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Over the last couple of years the appetite for bringin Rust into the\ncodebase has grown significantly across the developer base. Introducing\nRust is a major change though and has ramifications for the whole\necosystem:\n\n  - Some platforms have a Rust toolchain available, but have not yet\n    integrated it into their build infrastructure.\n\n  - Some platforms don't have any support for Rust at all.\n\n  - Some platforms may have to figure out how to fit Rust into their\n    bootstrapping sequence.\n\nDue to this, and given that Git is a critical piece of infrastructure\nfor the whole industry, we cannot just introduce such a heavyweight\ndependency without doing our due diligence.\n\nInstead, preceding commits have introduced a test balloon into our build\ninfrastructure that convert one tiny subsystem to use Rust. For now,\nusing Rust to build that subsystem is entirely optional -- if no Rust\nsupport is available, we continue to use the C implementation. This test\nballoon has the intention to give distributions time and let them ease\ninto our adoption of Rust.\n\nHaving multiple implementations of the same subsystem is not sustainable\nthough, and the plan is to eventually be able to use Rust freely all\nacross our codebase. As such, there is the intent to make Rust become a\nmandatory part of our build process.\n\nAdd an announcement to our breaking changes that Rust will become\nmandatory in Git 3.0. A (very careful and non-binding) estimate might be\nthat this major release might be released in the second half of next\nyear, which should give distributors enough time to prepare for the\nchange.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n Documentation/BreakingChanges.adoc | 36 ++++++++++++++++++++++++++++++++++++\n 1 file changed, 36 insertions(+)\n\ndiff --git a/Documentation/BreakingChanges.adoc b/Documentation/BreakingChanges.adoc\nindex f8d2eba061..3550e9fc27 100644\n--- a/Documentation/BreakingChanges.adoc\n+++ b/Documentation/BreakingChanges.adoc\n@@ -165,6 +165,42 @@ A prerequisite for this change is that the ecosystem is ready to support the\n \"reftable\" format. Most importantly, alternative implementations of Git like\n JGit, libgit2 and Gitoxide need to support it.\n \n+* Git will require Rust as a mandatory part of the build process. While Git\n+  already started to adopt Rust in Git 2.52, all parts written in Rust are\n+  optional for the time being. This includes:\n++\n+  ** Subsystems that have an alternative implementation in Rust to test\n+     interoperability between our C and Rust codebase.\n+  ** Newly written features that are not mission critical for a fully functional\n+     Git client.\n++\n+These changes are meant as test balloons to allow distributors of Git to prepare\n+for Rust becoming a mandatory part of the build process. There will be multiple\n+milestones for the introduction of Rust:\n++\n+1. Initially, with Git 2.52, support for Rust will be auto-detected by Meson and\n+   disabled in our Makefile so that the project can sort out the initial\n+   infrastructure.\n+2. In Git 2.53, both build systems will default-enable support for Rust.\n+   Consequently, builds will break by default if Rust is not available on the\n+   build host. The use of Rust can still be explicitly disabled via build\n+   flags.\n+3. In Git 3.0, the build options will be removed and support for Rust is\n+   mandatory.\n++\n+You can explicitly ask both Meson and our Makefile-based system to enable Rust\n+by saying `meson configure -Drust=enabled` and `make WITH_RUST=YesPlease`,\n+respectively.\n++\n+The Git project will declare the last version before Git 3.0 to be a long-term\n+support release. This long-term release will receive important bug fixes for at\n+least four release cycles and security fixes for six release cycles. The Git\n+project will hand over maintainership of the long-term release to distributors\n+in case they need to extend the life of that long-term release even further. In\n+that case, the backporting process will be handled by these distributors, but\n+the backported patches will be reviewed on the mailing list and pulled in by the\n+Git maintainer.\n+\n === Removals\n \n * Support for grafting commits has long been superseded by git-replace(1).\n\n-- \n2.51.0.450.g87641ccf93.dirty\n\n"},{"id":"526052","messageId":"20250910-b4-pks-rust-breaking-change-v4-8-4a63fc69278d@pks.im","threadId":"64091","inReplyTo":"20250910-b4-pks-rust-breaking-change-v4-0-4a63fc69278d@pks.im","subject":"[PATCH RFC v4 8/9] ci: convert \"pedantic\" job into full build with breaking changes","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-10T15:35:54Z","receivedAt":"2025-09-10T15:36:25Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The \"pedantic\" CI job is building on Fedora with `DEVOPTS=pedantic`.\nThis build flag doesn't do anything anymore starting with 6a8cbc41ba\n(developer: enable pedantic by default, 2021-09-03), where we have\nflipped the default so that developers have to opt-out of pedantic\nbuilds via the \"no-pedantic\" option. As such, all this job really does\nis to do a normal build on Fedora, which isn't all that interesting.\n\nConvert that job into a full build-and-test job that uses Meson with\nbreaking changes enabled. This plugs two gaps:\n\n  - We now test on another distro that we didn't run tests on\n    beforehand.\n\n  - We verify that breaking changes work as expected with Meson.\n\nFurthermore, in a subsequent commit we'll modify both jobs that use\nbreaking changes to also enable Rust. By converting the Fedora job to\nuse Meson, we ensure that we test our Rust build infrastructure for both\nbuild systems.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n .github/workflows/main.yml |  4 ++--\n .gitlab-ci.yml             |  4 ++--\n ci/install-dependencies.sh |  6 +++++-\n ci/run-build-and-tests.sh  | 29 ++++++++---------------------\n 4 files changed, 17 insertions(+), 26 deletions(-)\n\ndiff --git a/.github/workflows/main.yml b/.github/workflows/main.yml\nindex d122e79415..393ea4d1cc 100644\n--- a/.github/workflows/main.yml\n+++ b/.github/workflows/main.yml\n@@ -379,6 +379,8 @@ jobs:\n         - jobname: linux-breaking-changes\n           cc: gcc\n           image: ubuntu:rolling\n+        - jobname: fedora-breaking-changes-meson\n+          image: fedora:latest\n         - jobname: linux-leaks\n           image: ubuntu:rolling\n           cc: gcc\n@@ -396,8 +398,6 @@ jobs:\n         # Supported until 2025-04-02.\n         - jobname: linux32\n           image: i386/ubuntu:focal\n-        - jobname: pedantic\n-          image: fedora:latest\n         # A RHEL 8 compatible distro.  Supported until 2029-05-31.\n         - jobname: almalinux-8\n           image: almalinux:8\ndiff --git a/.gitlab-ci.yml b/.gitlab-ci.yml\nindex af10ebb59a..4248506909 100644\n--- a/.gitlab-ci.yml\n+++ b/.gitlab-ci.yml\n@@ -45,6 +45,8 @@ test:linux:\n       - jobname: linux-breaking-changes\n         image: ubuntu:20.04\n         CC: gcc\n+      - jobname: fedora-breaking-changes-meson\n+        image: fedora:latest\n       - jobname: linux-TEST-vars\n         image: ubuntu:20.04\n         CC: gcc\n@@ -58,8 +60,6 @@ test:linux:\n       - jobname: linux-asan-ubsan\n         image: ubuntu:rolling\n         CC: clang\n-      - jobname: pedantic\n-        image: fedora:latest\n       - jobname: linux-musl-meson\n         image: alpine:latest\n       - jobname: linux32\ndiff --git a/ci/install-dependencies.sh b/ci/install-dependencies.sh\nindex d061a47293..35bd05b85b 100755\n--- a/ci/install-dependencies.sh\n+++ b/ci/install-dependencies.sh\n@@ -30,8 +30,12 @@ alpine-*)\n \t\tbash cvs gnupg perl-cgi perl-dbd-sqlite perl-io-tty >/dev/null\n \t;;\n fedora-*|almalinux-*)\n+\tcase \"$jobname\" in\n+\t*-meson)\n+\t\tMESON_DEPS=\"meson ninja\";;\n+\tesac\n \tdnf -yq update >/dev/null &&\n-\tdnf -yq install shadow-utils sudo make gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel >/dev/null\n+\tdnf -yq install shadow-utils sudo make pkg-config gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel $MESON_DEPS >/dev/null\n \t;;\n ubuntu-*|i386/ubuntu-*|debian-*)\n \t# Required so that apt doesn't wait for user input on certain packages.\ndiff --git a/ci/run-build-and-tests.sh b/ci/run-build-and-tests.sh\nindex 01823fd0f1..3680446649 100755\n--- a/ci/run-build-and-tests.sh\n+++ b/ci/run-build-and-tests.sh\n@@ -5,12 +5,11 @@\n \n . ${0%/*}/lib.sh\n \n-run_tests=t\n-\n case \"$jobname\" in\n-linux-breaking-changes)\n+fedora-breaking-changes-musl|linux-breaking-changes)\n \texport GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main\n \texport WITH_BREAKING_CHANGES=YesPlease\n+\tMESONFLAGS=\"$MESONFLAGS -Dbreaking_changes=true\"\n \t;;\n linux-TEST-vars)\n \texport OPENSSL_SHA1_UNSAFE=YesPlease\n@@ -36,12 +35,6 @@ linux-sha256)\n linux-reftable|linux-reftable-leaks|osx-reftable)\n \texport GIT_TEST_DEFAULT_REF_FORMAT=reftable\n \t;;\n-pedantic)\n-\t# Don't run the tests; we only care about whether Git can be\n-\t# built.\n-\texport DEVOPTS=pedantic\n-\trun_tests=\n-\t;;\n esac\n \n case \"$jobname\" in\n@@ -54,21 +47,15 @@ case \"$jobname\" in\n \t\t-Dtest_output_directory=\"${TEST_OUTPUT_DIRECTORY:-$(pwd)/t}\" \\\n \t\t$MESONFLAGS\n \tgroup \"Build\" meson compile -C build --\n-\tif test -n \"$run_tests\"\n-\tthen\n-\t\tgroup \"Run tests\" meson test -C build --print-errorlogs --test-args=\"$GIT_TEST_OPTS\" || (\n-\t\t\t./t/aggregate-results.sh \"${TEST_OUTPUT_DIRECTORY:-t}/test-results\"\n-\t\t\thandle_failed_tests\n-\t\t)\n-\tfi\n+\tgroup \"Run tests\" meson test -C build --print-errorlogs --test-args=\"$GIT_TEST_OPTS\" || (\n+\t\t./t/aggregate-results.sh \"${TEST_OUTPUT_DIRECTORY:-t}/test-results\"\n+\t\thandle_failed_tests\n+\t)\n \t;;\n *)\n \tgroup Build make\n-\tif test -n \"$run_tests\"\n-\tthen\n-\t\tgroup \"Run tests\" make test ||\n-\t\thandle_failed_tests\n-\tfi\n+\tgroup \"Run tests\" make test ||\n+\thandle_failed_tests\n \t;;\n esac\n \n\n-- \n2.51.0.450.g87641ccf93.dirty\n\n"},{"id":"526053","messageId":"20250910-b4-pks-rust-breaking-change-v4-9-4a63fc69278d@pks.im","threadId":"64091","inReplyTo":"20250910-b4-pks-rust-breaking-change-v4-0-4a63fc69278d@pks.im","subject":"[PATCH RFC v4 9/9] ci: enable Rust for breaking-changes jobs","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-10T15:35:55Z","receivedAt":"2025-09-10T15:36:28Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Enable Rust for our breaking-changes jobs so that we can verify that the\nbuild infrastructure and the converted Rust subsystems work as expected.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n ci/install-dependencies.sh | 4 ++--\n ci/run-build-and-tests.sh  | 2 ++\n 2 files changed, 4 insertions(+), 2 deletions(-)\n\ndiff --git a/ci/install-dependencies.sh b/ci/install-dependencies.sh\nindex 35bd05b85b..0d3aa496fc 100755\n--- a/ci/install-dependencies.sh\n+++ b/ci/install-dependencies.sh\n@@ -35,7 +35,7 @@ fedora-*|almalinux-*)\n \t\tMESON_DEPS=\"meson ninja\";;\n \tesac\n \tdnf -yq update >/dev/null &&\n-\tdnf -yq install shadow-utils sudo make pkg-config gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel $MESON_DEPS >/dev/null\n+\tdnf -yq install shadow-utils sudo make pkg-config gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel $MESON_DEPS cargo >/dev/null\n \t;;\n ubuntu-*|i386/ubuntu-*|debian-*)\n \t# Required so that apt doesn't wait for user input on certain packages.\n@@ -62,7 +62,7 @@ ubuntu-*|i386/ubuntu-*|debian-*)\n \t\tmake libssl-dev libcurl4-openssl-dev libexpat-dev wget sudo default-jre \\\n \t\ttcl tk gettext zlib1g-dev perl-modules liberror-perl libauthen-sasl-perl \\\n \t\tlibemail-valid-perl libio-pty-perl libio-socket-ssl-perl libnet-smtp-ssl-perl libdbd-sqlite3-perl libcgi-pm-perl \\\n-\t\tlibsecret-1-dev libpcre2-dev meson ninja-build pkg-config \\\n+\t\tlibsecret-1-dev libpcre2-dev meson ninja-build pkg-config cargo \\\n \t\t${CC_PACKAGE:-${CC:-gcc}} $PYTHON_PACKAGE\n \n \tcase \"$distro\" in\ndiff --git a/ci/run-build-and-tests.sh b/ci/run-build-and-tests.sh\nindex 3680446649..c718bd101a 100755\n--- a/ci/run-build-and-tests.sh\n+++ b/ci/run-build-and-tests.sh\n@@ -9,7 +9,9 @@ case \"$jobname\" in\n fedora-breaking-changes-musl|linux-breaking-changes)\n \texport GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main\n \texport WITH_BREAKING_CHANGES=YesPlease\n+\texport WITH_RUST=YesPlease\n \tMESONFLAGS=\"$MESONFLAGS -Dbreaking_changes=true\"\n+\tMESONFLAGS=\"$MESONFLAGS -Drust=enabled\"\n \t;;\n linux-TEST-vars)\n \texport OPENSSL_SHA1_UNSAFE=YesPlease\n\n-- \n2.51.0.450.g87641ccf93.dirty\n\n"},{"id":"526087","messageId":"xmqqv7lqqat0.fsf@gitster.g","threadId":"64091","inReplyTo":"20250910-b4-pks-rust-breaking-change-v4-5-4a63fc69278d@pks.im","subject":"Re: [PATCH RFC v4 5/9] varint: use explicit width for integers","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-09-10T21:04:11Z","receivedAt":"2025-09-10T21:04:14Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> The varint subsystem currently uses implcit widths for integers. On the\n> one hand we use `uintmax_t` for the actual value. On the other hand, we\n> use `int` for the length of the encoded varint.\n>\n> Both of these have known maximum vaules, as we only support at most 16\n> bytes when encoding varints. Thus, we know that we won't ever exceed\n> `uint64_t` for the actual value and `uint8_t` for the prefix length.\n>\n> Refactor the code to use explicit widths. Besides making the logic\n> platform-independent, it also makes our life a bit easier in the next\n> commit, where we reimplement \"varint.c\" in Rust.\n>\n> Suggested-by: Ezekiel Newren <ezekielnewren@gmail.com>\n> Signed-off-by: Patrick Steinhardt <ps@pks.im>\n> ---\n>  dir.c        | 18 ++++++++++--------\n>  read-cache.c |  6 ++++--\n>  varint.c     |  6 +++---\n>  varint.h     |  4 ++--\n>  4 files changed, 19 insertions(+), 15 deletions(-)\n...\n> -int encode_varint(uintmax_t, unsigned char *);\n> -uintmax_t decode_varint(const unsigned char **);\n> +uint8_t encode_varint(uint64_t, unsigned char *);\n> +uint64_t decode_varint(const unsigned char **);\n\nOK.  I do not think there is a reason why we MUST use u8, even\nthough in practice 255 bytes is plenty for any \"integer\" that varint\nwould want to express, so I'll let it go.\n\nI have no objection to uint64_t side of the equation.  We would not\nbe using 128-bit integer to express sizes of object representation\nin the packfiles anyway.\n\nWhen this series meets Ezekiel's series, I would imagine that there\nwill be \"which one between uint64_t and u64 should we use\"\ndiscussion.  I'd prefer uint64_t as that is what is used in the part\nof the code that are not yet told about the other parts moving to\nRust.  Consistency throughout the codebase is good.\n"},{"id":"526090","messageId":"xmqqldmmqa1z.fsf@gitster.g","threadId":"64091","inReplyTo":"20250910-b4-pks-rust-breaking-change-v4-7-4a63fc69278d@pks.im","subject":"Re: [PATCH RFC v4 7/9] BreakingChanges: announce Rust becoming mandatory","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-09-10T21:20:24Z","receivedAt":"2025-09-10T21:20:28Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> +* Git will require Rust as a mandatory part of the build process. While Git\n> +  already started to adopt Rust in Git 2.52, all parts written in Rust are\n> +  optional for the time being. This includes:\n> ++\n> +  ** Subsystems that have an alternative implementation in Rust to test\n> +     interoperability between our C and Rust codebase.\n> +  ** Newly written features that are not mission critical for a fully functional\n> +     Git client.\n\nThis is a bit funny way to phrase the intent, even though I do fully\nsupport the intent expressed here.\n\nWhen this topic becomes part of the code base, we are likely to have\nvarint in the first category, but if we have nothing that falls in\nthe second category, that would feel somewhat odd.\n\n> +These changes are meant as test balloons to allow distributors of Git to prepare\n> +for Rust becoming a mandatory part of the build process. There will be multiple\n\nAre they still \"test balloons\"?  I thought that we established that\nthe point of these breaking changes is quite different from what we\nhave called \"test balloons\" for.  It is not like allowing them\nanything (like interfering to delay or stop, which would not likely\nto happen at this point if this patch gets part of the code base),\nbut is used as a bit more forceful way for us to tell them and make\nsure they are aware of the upcoming change.\n\n> +milestones for the introduction of Rust:\n> ++\n> +1. Initially, with Git 2.52, support for Rust will be auto-detected by Meson and\n> +   disabled in our Makefile so that the project can sort out the initial\n> +   infrastructure.\n> +2. In Git 2.53, both build systems will default-enable support for Rust.\n> +   Consequently, builds will break by default if Rust is not available on the\n> +   build host. The use of Rust can still be explicitly disabled via build\n> +   flags.\n> +3. In Git 3.0, the build options will be removed and support for Rust is\n> +   mandatory.\n\nI like the vagueness of the gap between step 2 and 3 here ;-)\n\n> +The Git project will declare the last version before Git 3.0 to be a long-term\n> +support release. This long-term release will receive important bug fixes for at\n> +least four release cycles and security fixes for six release cycles. The Git\n> +project will hand over maintainership of the long-term release to distributors\n> +in case they need to extend the life of that long-term release even further. In\n> +that case, the backporting process will be handled by these distributors, but\n> +the backported patches will be reviewed on the mailing list and pulled in by the\n> +Git maintainer.\n\nI am having a hard time imagining the practicality of this \"hand\nover but we still review\" arrangement.  Some of the security fixes\nare embargoed, and the reason why we are jetissoning the stale\ncodebase is presumably because nobody is willing to work on it other\nthan the \"community support\" folks.  I can imagine that we would\nqualify them into the git-security cabal and let them use the forum\nto coordinate among themselves, but then to what degree in the\n\"community support themselves\" process is our involvement expected?\nAs long as we can make sure that they do not leak before the\nofficial embargoed release, they do not need an official stamp of\napproval from the project or by the Git maintainer---that is what it\nmeans to \"hand over maintainer ship\", at least to me.\n\nIn other words, I like what I see in this paragraph, but I do not\nthink we can practically live with the part of the sentence after\nthe last \", but\".\n\nThanks.\n"},{"id":"526096","messageId":"53a9efd2-52d7-4520-81eb-2129ccfd26d4@app.fastmail.com","threadId":"64091","inReplyTo":"20250910-b4-pks-rust-breaking-change-v4-7-4a63fc69278d@pks.im","subject":"Re: [PATCH RFC v4 7/9] BreakingChanges: announce Rust becoming mandatory","fromName":"Kristoffer Haugsbakk","fromEmail":"kristofferhaugsbakk@fastmail.com","sentAt":"2025-09-10T21:42:05Z","receivedAt":"2025-09-10T21:42:27Z","isPatch":true,"sender":{"key":"kristofferhaugsbakk@fastmail.com","avatar":null},"body":"On Wed, Sep 10, 2025, at 17:35, Patrick Steinhardt wrote:\n> Over the last couple of years the appetite for bringin Rust into the\n\ns/bringin/bringing/\n\nhttps://lore.kernel.org/git/CAPig+cThyuo7=A2f7_XkE_TZmSRc5i=EFgZOw_pKgu+Ckgx70w@mail.gmail.com/\n\n>[snip]\n> ---\n>  Documentation/BreakingChanges.adoc | 36 ++++++++++++++++++++++++++++++++++++\n>  1 file changed, 36 insertions(+)\n>\n> diff --git a/Documentation/BreakingChanges.adoc\n> b/Documentation/BreakingChanges.adoc\n> index f8d2eba061..3550e9fc27 100644\n> --- a/Documentation/BreakingChanges.adoc\n> +++ b/Documentation/BreakingChanges.adoc\n> @@ -165,6 +165,42 @@ A prerequisite for this change is that the\n> ecosystem is ready to support the\n>  \"reftable\" format. Most importantly, alternative implementations of\n> Git like\n>  JGit, libgit2 and Gitoxide need to support it.\n>\n> +* Git will require Rust as a mandatory part of the build process.\n> While Git\n> +  already started to adopt Rust in Git 2.52, all parts written in Rust\n> are\n> +  optional for the time being. This includes:\n> ++\n> +  ** Subsystems that have an alternative implementation in Rust to test\n> +     interoperability between our C and Rust codebase.\n> +  ** Newly written features that are not mission critical for a fully\n> functional\n> +     Git client.\n> ++\n> +These changes are meant as test balloons to allow distributors of Git\n> to prepare\n> +for Rust becoming a mandatory part of the build process. There will be\n> multiple\n> +milestones for the introduction of Rust:\n> ++\n> +1. Initially, with Git 2.52, support for Rust will be auto-detected by\n> Meson and\n> +   disabled in our Makefile so that the project can sort out the\n> initial\n> +   infrastructure.\n> +2. In Git 2.53, both build systems will default-enable support for\n> Rust.\n> +   Consequently, builds will break by default if Rust is not available\n> on the\n> +   build host. The use of Rust can still be explicitly disabled via\n> build\n> +   flags.\n> +3. In Git 3.0, the build options will be removed and support for Rust\n> is\n> +   mandatory.\n> ++\n\nSome minutiae: the HTML output is like\n\n    3. In Git 3.0, ...\n\n       You can explicitly ...\n\nBut it seems from the text that the paragraph after (3) should go back\nto the previous level:\n\n    3. In ...\n\n    You ...\n\nYou’ll need to put these three list items in an `--` in order to get the\nlatter.  Or that’s one option (that I tried).\n\n> +You can explicitly ask both Meson and our Makefile-based system to\n> enable Rust\n> +by saying `meson configure -Drust=enabled` and `make\n> WITH_RUST=YesPlease`,\n> +respectively.\n>[snip]\n"},{"id":"526150","messageId":"aMNAR35R8aCXhVjM@fruit.crustytoothpaste.net","threadId":"64091","inReplyTo":"20250910-b4-pks-rust-breaking-change-v4-1-4a63fc69278d@pks.im","subject":"Re: [PATCH RFC v4 1/9] meson: add infrastructure to build internal Rust library","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2025-09-11T21:33:59Z","receivedAt":"2025-09-11T21:34:02Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On 2025-09-10 at 15:35:47, Patrick Steinhardt wrote:\n> diff --git a/src/cargo-meson.sh b/src/cargo-meson.sh\n> new file mode 100755\n> index 00000000000..f29745beb36\n> --- /dev/null\n> +++ b/src/cargo-meson.sh\n> @@ -0,0 +1,32 @@\n> +#!/bin/sh\n> +\n> +if test \"$#\" -lt 2\n> +then\n> +\texit 1\n> +fi\n> +\n> +SOURCE_DIR=\"$1\"\n> +BUILD_DIR=\"$2\"\n> +BUILD_TYPE=debug\n> +\n> +shift 2\n> +\n> +for arg\n> +do\n> +\tcase \"$arg\" in\n> +\t--release)\n> +\t\tBUILD_TYPE=release;;\n> +\tesac\n> +done\n> +\n> +cargo build --lib --quiet --manifest-path=\"$SOURCE_DIR/Cargo.toml\" --target-dir=\"$BUILD_DIR\" \"$@\"\n> +RET=$?\n> +if test $RET -ne 0\n> +then\n> +\texit $RET\n> +fi\n> +\n> +if ! cmp \"$BUILD_DIR/$BUILD_TYPE/libgit.a\" \"$BUILD_DIR/libgit.a\" >/dev/null 2>&1\n> +then\n> +\tcp \"$BUILD_DIR/$BUILD_TYPE/libgit.a\" \"$BUILD_DIR/libgit.a\"\n> +fi\n\nOkay, this seems like a reasonable approach.  It would be nicer to not\nhave to do this, but we've got to work with what we've got.\n\nIf I get mrustc working, this could also be a nice way to abstract that\nfunctionality in a useful way.\n\n> diff --git a/src/lib.rs b/src/lib.rs\n> new file mode 100644\n> index 00000000000..e69de29bb2d\n\nAn empty file seems like a good start.\n-- \nbrian m. carlson (they/them)\nToronto, Ontario, CA\n"},{"id":"526151","messageId":"aMNFao0yGZ6yzKKv@fruit.crustytoothpaste.net","threadId":"64091","inReplyTo":"20250910-b4-pks-rust-breaking-change-v4-0-4a63fc69278d@pks.im","subject":"Re: [PATCH RFC v4 0/9] Introduce Rust and announce that it will become mandatory","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2025-09-11T21:55:54Z","receivedAt":"2025-09-11T21:55:57Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On 2025-09-10 at 15:35:46, Patrick Steinhardt wrote:\n> Hi,\n> \n> this small patch series introduces Rust into the core of Git. This patch\n> series is designed as a test balloon, similar to how we introduced test\n> balloons for C99 features in the past. The goal is threefold:\n> \n>   - Give us some time to experiment with Rust and introduce proper build\n>     infrastructure.\n> \n>   - Give distributors time to ease into the new toolchain requirements.\n>     Introducing Rust is impossible for some platforms and hard for\n>     others.\n> \n>   - Announce that Git 3.0 will make Rust a mandatory part of our build\n>     infrastructure.\n> \n> The test balloon itself is quite uninteresting: I've chosen to convert\n> the \"varint.c\" subsystem, mostly because it is trivial and does not have\n> any dependencies. But it does allow us to verify that C to Rust interop\n> works as expected, and to play around with tooling. All tests pass with\n> the \"varint.rs\" implementation.\n> \n> For now, the series only contains support for Meson. If we agree to go\n> down this route I'll also introduce support for Rust into our Makefiles\n> at a later point in time.\n> \n> Furthermore missing is additional tooling:\n> \n>   - At least one CI job to verify that Rust builds and works as\n>     expected.\n> \n>   - Tooling and CI jobs to ensure that we have consistent formatting via\n>     `cargo format`.\n> \n> And probably lots more. As said, the entire goal is for us to have an\n> easy playground that we can experiment on and develop the infrastructure\n> incrementally without yet having to commit to anything.\n\nI may end up sending in a patch or two for these if I have some time.\n\nI did note the discussion about what the LTS process looks like, which I\ndon't have strong opinions about but do want to make sure the project\n(including folks on the security list) is willing to support.  Other\nthan that, this series looked reasonable to me.  I also confirmed that\nit works with my existing sha256-interop-part-2 series, which I\nappreciate.\n\nI think once we have agreement on the LTS process, this should be good\nto go.\n-- \nbrian m. carlson (they/them)\nToronto, Ontario, CA\n"},{"id":"526198","messageId":"aMRADFAoh68aWkdD@szeder.dev","threadId":"64091","inReplyTo":"20250910-b4-pks-rust-breaking-change-v4-0-4a63fc69278d@pks.im","subject":"Re: [PATCH RFC v4 0/9] Introduce Rust and announce that it will become mandatory","fromName":"SZEDER Gábor","fromEmail":"szeder.dev@gmail.com","sentAt":"2025-09-12T15:45:16Z","receivedAt":"2025-09-12T15:45:41Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"On Wed, Sep 10, 2025 at 05:35:46PM +0200, Patrick Steinhardt wrote:\n> Hi,\n> \n> this small patch series introduces Rust into the core of Git. This patch\n> series is designed as a test balloon, similar to how we introduced test\n> balloons for C99 features in the past. The goal is threefold:\n> \n>   - Give us some time to experiment with Rust and introduce proper build\n>     infrastructure.\n> \n>   - Give distributors time to ease into the new toolchain requirements.\n>     Introducing Rust is impossible for some platforms and hard for\n>     others.\n> \n>   - Announce that Git 3.0 will make Rust a mandatory part of our build\n>     infrastructure.\n> \n> The test balloon itself is quite uninteresting: I've chosen to convert\n> the \"varint.c\" subsystem, mostly because it is trivial and does not have\n> any dependencies. But it does allow us to verify that C to Rust interop\n> works as expected, and to play around with tooling. All tests pass with\n> the \"varint.rs\" implementation.\n> \n> For now, the series only contains support for Meson. If we agree to go\n> down this route I'll also introduce support for Rust into our Makefiles\n> at a later point in time.\n> \n> Furthermore missing is additional tooling:\n> \n>   - At least one CI job to verify that Rust builds and works as\n>     expected.\n> \n>   - Tooling and CI jobs to ensure that we have consistent formatting via\n>     `cargo format`.\n> \n> And probably lots more. As said, the entire goal is for us to have an\n> easy playground that we can experiment on and develop the infrastructure\n> incrementally without yet having to commit to anything.\n> \n> I'm mostly splitting out the topic of introducing Rust from the larger\n> series that introduce it into xdiff so that we can focus more on the\n> actual process of introducing Rust into Git and less on the potential\n> features that we want to build on top of it.\n> \n> Changes in v2:\n>   - Introduce support for building the Rust library via our Makefile.\n>   - Introduce a '-DWITH_RUST' define. This define is used to print\n>     whether or not Git is built with Rust via `git version\n>     --build-options`.\n>   - Adjust Meson to not depend on v1.9.0 and newer anymore.\n>   - Introduce a roadmap into our BreakingChanges document to explain how\n>     we'll iterate towards mandatory Rust support.\n>   - Rework the Fedora job to do a full compile-and-test run with Meson\n>     and breaking changes enabled.\n>   - Adapt our breaking-changes jobs to enable Rust support.\n>   - Link to v1: https://lore.kernel.org/r/20250904-b4-pks-rust-breaking-change-v1-0-3af1d25e0be9@pks.im\n> \n> Changes in v3:\n>   - Reorder all uses of `WITH_RUST` after the include of \"config.mak\".\n>   - Add a test to verify overflow behaviour in Rust and explicitly use\n>     `add_wrapping()`.\n>   - Use explicit dependencies for the Rust library in our Makefile.\n>   - Fix Alma Linux CI job.\n>   - Stop tying maintenance of our LTS release to the availability of\n>     gcc-rs.\n>   - Add a fallback to Meson to use cargo directly.\n>   - I've fixed the Rust edition to 2018 for now. This is intentionally\n>     conservative so that we might be able to use Rust 1.49. For now, we\n>     don't have any reason to use a newer edition, either. So let's take\n>     the oldest version we can live with for now and then bump it as\n>     required.\n>   - Link to v2: https://lore.kernel.org/r/20250905-b4-pks-rust-breaking-change-v2-0-6939cbf4a0b8@pks.im\n> \n> Changes in v4:\n>   - Convert \"varint.c\" to use explicit integer width so that we don't\n>     need to use C types in Rust.\n>   - Adapt Meson to unconditionally use Cargo.\n>   - Don't use the unstable `--out-dir` option in Cargo. Instead, we\n>     resort to a wrapper script in Meson.\n>   - Shorten the timeline a bit to drop the extra step that ties Rust\n>     support to `-Dbreaking_changes=true`. This accelerates the timeline\n>     until distros are made forcibly aware of the upcoming changes in\n>     Rust.\n>   - Link to v3: https://lore.kernel.org/r/20250908-b4-pks-rust-breaking-change-v3-0-1cd7189fed3b@pks.im\n> \n> Thanks!\n> \n> Patrick\n> \n> ---\n> Patrick Steinhardt (9):\n>       meson: add infrastructure to build internal Rust library\n>       Makefile: reorder sources after includes\n>       Makefile: introduce infrastructure to build internal Rust library\n>       help: report on whether or not Rust is enabled\n>       varint: use explicit width for integers\n>       varint: reimplement as test balloon for Rust\n>       BreakingChanges: announce Rust becoming mandatory\n>       ci: convert \"pedantic\" job into full build with breaking changes\n>       ci: enable Rust for breaking-changes jobs\n> \n>  .github/workflows/main.yml         |   4 +-\n>  .gitignore                         |   2 +\n>  .gitlab-ci.yml                     |   4 +-\n>  Cargo.toml                         |   9 ++\n>  Documentation/BreakingChanges.adoc |  36 +++++++\n>  Makefile                           | 214 ++++++++++++++++++++++---------------\n>  ci/install-dependencies.sh         |   8 +-\n>  ci/run-build-and-tests.sh          |  31 ++----\n>  dir.c                              |  18 ++--\n>  help.c                             |   6 ++\n>  meson.build                        |  15 ++-\n>  meson_options.txt                  |   2 +\n>  read-cache.c                       |   6 +-\n>  shared.mak                         |   1 +\n>  src/cargo-meson.sh                 |  32 ++++++\n>  src/lib.rs                         |   1 +\n>  src/meson.build                    |  41 +++++++\n>  src/varint.rs                      |  92 ++++++++++++++++\n>  varint.c                           |   6 +-\n>  varint.h                           |   4 +-\n>  20 files changed, 401 insertions(+), 131 deletions(-)\n> \n> Range-diff versus v3:\n> \n>  1:  a25408af71 <  -:  ---------- meson: add infrastructure to build internal Rust library\n>  -:  ---------- >  1:  ccdb7e264d meson: add infrastructure to build internal Rust library\n>  2:  a9c639b0f3 =  2:  b88c80f7e9 Makefile: reorder sources after includes\n>  3:  ccac54a247 !  3:  873f9d82f5 Makefile: introduce infrastructure to build internal Rust library\n>     @@ .gitignore\n>      @@\n>       /fuzz_corpora\n>      +/target/\n>     ++/Cargo.lock\n\nThe Cargo.lock build artifact is back in .gitignore in this version of\nthe patch series, but the 'clean' target is not updated accordingly to\nremove it.\n\n>       /GIT-BUILD-DIR\n>       /GIT-BUILD-OPTIONS\n>       /GIT-CFLAGS\n>  4:  b357ff9463 =  4:  4e70509175 help: report on whether or not Rust is enabled\n"},{"id":"526204","messageId":"xmqqplbvmy11.fsf@gitster.g","threadId":"64091","inReplyTo":"aMRADFAoh68aWkdD@szeder.dev","subject":"Re: [PATCH RFC v4 0/9] Introduce Rust and announce that it will become mandatory","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-09-12T16:32:58Z","receivedAt":"2025-09-12T16:33:02Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"SZEDER Gábor <szeder.dev@gmail.com> writes:\n\n>>  3:  ccac54a247 !  3:  873f9d82f5 Makefile: introduce infrastructure to build internal Rust library\n>>     @@ .gitignore\n>>      @@\n>>       /fuzz_corpora\n>>      +/target/\n>>     ++/Cargo.lock\n>\n> The Cargo.lock build artifact is back in .gitignore in this version of\n> the patch series, but the 'clean' target is not updated accordingly to\n> remove it.\n\nI too noticed a leftover Cargo.lock file but was a bit too\ndistracted to report it (and instead kept going with \"git clean -f\"\nX-<); my bad.\n\nThanks for being extra careful.\n"},{"id":"526338","messageId":"aMfvgxm_aIaf8vxG@pks.im","threadId":"64091","inReplyTo":"xmqqplbvmy11.fsf@gitster.g","subject":"Re: [PATCH RFC v4 0/9] Introduce Rust and announce that it will become mandatory","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-15T10:50:43Z","receivedAt":"2025-09-15T10:50:57Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Fri, Sep 12, 2025 at 09:32:58AM -0700, Junio C Hamano wrote:\n> SZEDER Gábor <szeder.dev@gmail.com> writes:\n> \n> >>  3:  ccac54a247 !  3:  873f9d82f5 Makefile: introduce infrastructure to build internal Rust library\n> >>     @@ .gitignore\n> >>      @@\n> >>       /fuzz_corpora\n> >>      +/target/\n> >>     ++/Cargo.lock\n> >\n> > The Cargo.lock build artifact is back in .gitignore in this version of\n> > the patch series, but the 'clean' target is not updated accordingly to\n> > remove it.\n> \n> I too noticed a leftover Cargo.lock file but was a bit too\n> distracted to report it (and instead kept going with \"git clean -f\"\n> X-<); my bad.\n> \n> Thanks for being extra careful.\n\nAh, good catch indeed! Will fix, thanks.\n\nPatrick\n"},{"id":"526339","messageId":"aMfwGHL7dh8dk2cQ@pks.im","threadId":"64091","inReplyTo":"xmqqldmmqa1z.fsf@gitster.g","subject":"Re: [PATCH RFC v4 7/9] BreakingChanges: announce Rust becoming mandatory","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-15T10:53:12Z","receivedAt":"2025-09-15T10:53:19Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Wed, Sep 10, 2025 at 02:20:24PM -0700, Junio C Hamano wrote:\n> Patrick Steinhardt <ps@pks.im> writes:\n> \n> > +* Git will require Rust as a mandatory part of the build process. While Git\n> > +  already started to adopt Rust in Git 2.52, all parts written in Rust are\n> > +  optional for the time being. This includes:\n> > ++\n> > +  ** Subsystems that have an alternative implementation in Rust to test\n> > +     interoperability between our C and Rust codebase.\n> > +  ** Newly written features that are not mission critical for a fully functional\n> > +     Git client.\n> \n> This is a bit funny way to phrase the intent, even though I do fully\n> support the intent expressed here.\n> \n> When this topic becomes part of the code base, we are likely to have\n> varint in the first category, but if we have nothing that falls in\n> the second category, that would feel somewhat odd.\n\nThe intent here is to open the door for those. So yes, right now we\ndon't have anything in the second category yet. But the intent here is\nto explicitly say that people are free to do it even if there is no such\nuser in our tree yet. And with the SHA256 interop code we already have\nthis feature in the working anyway :)\n\n> > +These changes are meant as test balloons to allow distributors of Git to prepare\n> > +for Rust becoming a mandatory part of the build process. There will be multiple\n> \n> Are they still \"test balloons\"?  I thought that we established that\n> the point of these breaking changes is quite different from what we\n> have called \"test balloons\" for.  It is not like allowing them\n> anything (like interfering to delay or stop, which would not likely\n> to happen at this point if this patch gets part of the code base),\n> but is used as a bit more forceful way for us to tell them and make\n> sure they are aware of the upcoming change.\n\nI'm mostly just lacking a better term here and haven't seen a different\nterm proposed anywhere. I think it's close enough to a test balloon to\ncall it that, but if anybody has a better way to name this thing I'm\nhappy to adapt.\n\n> > +The Git project will declare the last version before Git 3.0 to be a long-term\n> > +support release. This long-term release will receive important bug fixes for at\n> > +least four release cycles and security fixes for six release cycles. The Git\n> > +project will hand over maintainership of the long-term release to distributors\n> > +in case they need to extend the life of that long-term release even further. In\n> > +that case, the backporting process will be handled by these distributors, but\n> > +the backported patches will be reviewed on the mailing list and pulled in by the\n> > +Git maintainer.\n> \n> I am having a hard time imagining the practicality of this \"hand\n> over but we still review\" arrangement.  Some of the security fixes\n> are embargoed, and the reason why we are jetissoning the stale\n> codebase is presumably because nobody is willing to work on it other\n> than the \"community support\" folks.  I can imagine that we would\n> qualify them into the git-security cabal and let them use the forum\n> to coordinate among themselves, but then to what degree in the\n> \"community support themselves\" process is our involvement expected?\n> As long as we can make sure that they do not leak before the\n> official embargoed release, they do not need an official stamp of\n> approval from the project or by the Git maintainer---that is what it\n> means to \"hand over maintainer ship\", at least to me.\n> \n> In other words, I like what I see in this paragraph, but I do not\n> think we can practically live with the part of the sentence after\n> the last \", but\".\n\nI think the most important part here is that this community-supported\nLTS release should still live in the canonical repositories. We should\navoid the situation where we hand over maintainership to such a degree\nthat the end result (the tagged LTS release) lives somewhere else.\nOtherwise we risk chaos and a plethora of different LTS releases, which\nwould be harmful both for us and those that rely on the LTS releases.\n\nSo this requires us/you to pull in those changes into the LTS release\nbranch. And that from my point of view mandates that we also review\nwhatever is being proposed for the backports. The mode thus essentially\nbecomes that somebody else does the legwork of selecting patches that\nneed to be backported and massaging them so that they apply to the old\nGit version. But other than that we still follow the normal processes.\n\nAnd yes, that probably means that a trusted LTS maintainer should be on\ngit-security@ so that they are aware of upcoming security releases.\n\nPatrick\n"},{"id":"526340","messageId":"aMfwLCJkvJnRVuqa@pks.im","threadId":"64091","inReplyTo":"53a9efd2-52d7-4520-81eb-2129ccfd26d4@app.fastmail.com","subject":"Re: [PATCH RFC v4 7/9] BreakingChanges: announce Rust becoming mandatory","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-15T10:53:32Z","receivedAt":"2025-09-15T10:53:39Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Wed, Sep 10, 2025 at 11:42:05PM +0200, Kristoffer Haugsbakk wrote:\n> On Wed, Sep 10, 2025, at 17:35, Patrick Steinhardt wrote:\n> > +These changes are meant as test balloons to allow distributors of Git\n> > to prepare\n> > +for Rust becoming a mandatory part of the build process. There will be\n> > multiple\n> > +milestones for the introduction of Rust:\n> > ++\n> > +1. Initially, with Git 2.52, support for Rust will be auto-detected by\n> > Meson and\n> > +   disabled in our Makefile so that the project can sort out the\n> > initial\n> > +   infrastructure.\n> > +2. In Git 2.53, both build systems will default-enable support for\n> > Rust.\n> > +   Consequently, builds will break by default if Rust is not available\n> > on the\n> > +   build host. The use of Rust can still be explicitly disabled via\n> > build\n> > +   flags.\n> > +3. In Git 3.0, the build options will be removed and support for Rust\n> > is\n> > +   mandatory.\n> > ++\n> \n> Some minutiae: the HTML output is like\n> \n>     3. In Git 3.0, ...\n> \n>        You can explicitly ...\n> \n> But it seems from the text that the paragraph after (3) should go back\n> to the previous level:\n> \n>     3. In ...\n> \n>     You ...\n> \n> You’ll need to put these three list items in an `--` in order to get the\n> latter.  Or that’s one option (that I tried).\n\nAh, indeed. Thanks for your careful eyes, fixed locally now.\n\nPatrick\n"},{"id":"526341","messageId":"aMfwRP3AC-PHrljU@pks.im","threadId":"64091","inReplyTo":"aMNFao0yGZ6yzKKv@fruit.crustytoothpaste.net","subject":"Re: [PATCH RFC v4 0/9] Introduce Rust and announce that it will become mandatory","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-15T10:53:56Z","receivedAt":"2025-09-15T10:54:03Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Thu, Sep 11, 2025 at 09:55:54PM +0000, brian m. carlson wrote:\n> I may end up sending in a patch or two for these if I have some time.\n\nSure! No pressure here, us being able to iterate is why I wanted to make\nthings opt-in in the first release.\n\n> I did note the discussion about what the LTS process looks like, which I\n> don't have strong opinions about but do want to make sure the project\n> (including folks on the security list) is willing to support.  Other\n> than that, this series looked reasonable to me.  I also confirmed that\n> it works with my existing sha256-interop-part-2 series, which I\n> appreciate.\n\nThat's awesome, thanks for confirming.\n\n> I think once we have agreement on the LTS process, this should be good\n> to go.\n\nYay! In any case, I would be okay to help out with the LTS process as\nlong as it's still owned by the Git project.\n\nPatrick\n"},{"id":"526343","messageId":"20250915-b4-pks-rust-breaking-change-v5-0-dc3a32fbb216@pks.im","threadId":"64091","inReplyTo":"20250904-b4-pks-rust-breaking-change-v1-0-3af1d25e0be9@pks.im","subject":"[PATCH v5 0/9] Introduce Rust and announce that it will become mandatory","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-15T11:22:47Z","receivedAt":"2025-09-15T11:23:07Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Hi,\n\nthis small patch series introduces Rust into the core of Git. This patch\nseries is designed as a test balloon, similar to how we introduced test\nballoons for C99 features in the past. The goal is threefold:\n\n  - Give us some time to experiment with Rust and introduce proper build\n    infrastructure.\n\n  - Give distributors time to ease into the new toolchain requirements.\n    Introducing Rust is impossible for some platforms and hard for\n    others.\n\n  - Announce that Git 3.0 will make Rust a mandatory part of our build\n    infrastructure.\n\nThe test balloon itself is quite uninteresting: I've chosen to convert\nthe \"varint.c\" subsystem, mostly because it is trivial and does not have\nany dependencies. But it does allow us to verify that C to Rust interop\nworks as expected, and to play around with tooling. All tests pass with\nthe \"varint.rs\" implementation.\n\nFor now, the series only contains support for Meson. If we agree to go\ndown this route I'll also introduce support for Rust into our Makefiles\nat a later point in time.\n\nFurthermore missing is additional tooling:\n\n  - At least one CI job to verify that Rust builds and works as\n    expected.\n\n  - Tooling and CI jobs to ensure that we have consistent formatting via\n    `cargo format`.\n\nAnd probably lots more. As said, the entire goal is for us to have an\neasy playground that we can experiment on and develop the infrastructure\nincrementally without yet having to commit to anything.\n\nI'm mostly splitting out the topic of introducing Rust from the larger\nseries that introduce it into xdiff so that we can focus more on the\nactual process of introducing Rust into Git and less on the potential\nfeatures that we want to build on top of it.\n\nChanges in v2:\n  - Introduce support for building the Rust library via our Makefile.\n  - Introduce a '-DWITH_RUST' define. This define is used to print\n    whether or not Git is built with Rust via `git version\n    --build-options`.\n  - Adjust Meson to not depend on v1.9.0 and newer anymore.\n  - Introduce a roadmap into our BreakingChanges document to explain how\n    we'll iterate towards mandatory Rust support.\n  - Rework the Fedora job to do a full compile-and-test run with Meson\n    and breaking changes enabled.\n  - Adapt our breaking-changes jobs to enable Rust support.\n  - Link to v1: https://lore.kernel.org/r/20250904-b4-pks-rust-breaking-change-v1-0-3af1d25e0be9@pks.im\n\nChanges in v3:\n  - Reorder all uses of `WITH_RUST` after the include of \"config.mak\".\n  - Add a test to verify overflow behaviour in Rust and explicitly use\n    `add_wrapping()`.\n  - Use explicit dependencies for the Rust library in our Makefile.\n  - Fix Alma Linux CI job.\n  - Stop tying maintenance of our LTS release to the availability of\n    gcc-rs.\n  - Add a fallback to Meson to use cargo directly.\n  - I've fixed the Rust edition to 2018 for now. This is intentionally\n    conservative so that we might be able to use Rust 1.49. For now, we\n    don't have any reason to use a newer edition, either. So let's take\n    the oldest version we can live with for now and then bump it as\n    required.\n  - Link to v2: https://lore.kernel.org/r/20250905-b4-pks-rust-breaking-change-v2-0-6939cbf4a0b8@pks.im\n\nChanges in v4:\n  - Convert \"varint.c\" to use explicit integer width so that we don't\n    need to use C types in Rust.\n  - Adapt Meson to unconditionally use Cargo.\n  - Don't use the unstable `--out-dir` option in Cargo. Instead, we\n    resort to a wrapper script in Meson.\n  - Shorten the timeline a bit to drop the extra step that ties Rust\n    support to `-Dbreaking_changes=true`. This accelerates the timeline\n    until distros are made forcibly aware of the upcoming changes in\n    Rust.\n  - Link to v3: https://lore.kernel.org/r/20250908-b4-pks-rust-breaking-change-v3-0-1cd7189fed3b@pks.im\n\nChanges in v5:\n  - Fix indentation in the BreakingChanges document.\n  - Fix a commit message typo.\n  - Include \"Cargo.lock\" in the `make clean` target again.\n  - Link to v4: https://lore.kernel.org/r/20250910-b4-pks-rust-breaking-change-v4-0-4a63fc69278d@pks.im\n\nThanks!\n\nPatrick\n\n---\nPatrick Steinhardt (9):\n      meson: add infrastructure to build internal Rust library\n      Makefile: reorder sources after includes\n      Makefile: introduce infrastructure to build internal Rust library\n      help: report on whether or not Rust is enabled\n      varint: use explicit width for integers\n      varint: reimplement as test balloon for Rust\n      BreakingChanges: announce Rust becoming mandatory\n      ci: convert \"pedantic\" job into full build with breaking changes\n      ci: enable Rust for breaking-changes jobs\n\n .github/workflows/main.yml         |   4 +-\n .gitignore                         |   2 +\n .gitlab-ci.yml                     |   4 +-\n Cargo.toml                         |   9 ++\n Documentation/BreakingChanges.adoc |  38 +++++++\n Makefile                           | 214 ++++++++++++++++++++++---------------\n ci/install-dependencies.sh         |   8 +-\n ci/run-build-and-tests.sh          |  31 ++----\n dir.c                              |  18 ++--\n help.c                             |   6 ++\n meson.build                        |  15 ++-\n meson_options.txt                  |   2 +\n read-cache.c                       |   6 +-\n shared.mak                         |   1 +\n src/cargo-meson.sh                 |  32 ++++++\n src/lib.rs                         |   1 +\n src/meson.build                    |  41 +++++++\n src/varint.rs                      |  92 ++++++++++++++++\n varint.c                           |   6 +-\n varint.h                           |   4 +-\n 20 files changed, 403 insertions(+), 131 deletions(-)\n\nRange-diff versus v4:\n\n 1:  8e009fe5c3 =  1:  fae7d374da meson: add infrastructure to build internal Rust library\n 2:  ad75e8afe1 =  2:  6202951039 Makefile: reorder sources after includes\n 3:  9f182beba6 !  3:  a8ee5c33b5 Makefile: introduce infrastructure to build internal Rust library\n    @@ Makefile: clean: profile-clean coverage-clean cocciclean\n      \t$(RM) $(FUZZ_PROGRAMS)\n      \t$(RM) $(SP_OBJ)\n      \t$(RM) $(HCC)\n    -+\t$(RM) -r target/\n    ++\t$(RM) -r Cargo.lock target/\n      \t$(RM) version-def.h\n      \t$(RM) -r $(dep_dirs) $(compdb_dir) compile_commands.json\n      \t$(RM) $(test_bindir_programs)\n 4:  06cfc7ae33 =  4:  484c5a984f help: report on whether or not Rust is enabled\n 5:  882d1e1f25 =  5:  c366ddd005 varint: use explicit width for integers\n 6:  01405d242e =  6:  bb3f7b2606 varint: reimplement as test balloon for Rust\n 7:  2e5e1ff9a1 !  7:  a96e89b4c4 BreakingChanges: announce Rust becoming mandatory\n    @@ Metadata\n      ## Commit message ##\n         BreakingChanges: announce Rust becoming mandatory\n     \n    -    Over the last couple of years the appetite for bringin Rust into the\n    +    Over the last couple of years the appetite for bringing Rust into the\n         codebase has grown significantly across the developer base. Introducing\n         Rust is a major change though and has ramifications for the whole\n         ecosystem:\n    @@ Documentation/BreakingChanges.adoc: A prerequisite for this change is that the e\n     +for Rust becoming a mandatory part of the build process. There will be multiple\n     +milestones for the introduction of Rust:\n     ++\n    ++--\n     +1. Initially, with Git 2.52, support for Rust will be auto-detected by Meson and\n     +   disabled in our Makefile so that the project can sort out the initial\n     +   infrastructure.\n    @@ Documentation/BreakingChanges.adoc: A prerequisite for this change is that the e\n     +   flags.\n     +3. In Git 3.0, the build options will be removed and support for Rust is\n     +   mandatory.\n    ++--\n     ++\n     +You can explicitly ask both Meson and our Makefile-based system to enable Rust\n     +by saying `meson configure -Drust=enabled` and `make WITH_RUST=YesPlease`,\n 8:  bd7170e906 =  8:  403731a732 ci: convert \"pedantic\" job into full build with breaking changes\n 9:  f922a60198 =  9:  606786ce90 ci: enable Rust for breaking-changes jobs\n\n---\nbase-commit: 2462961280690837670d997bde64bd4ebf8ae66d\nchange-id: 20250904-b4-pks-rust-breaking-change-7167d9d3e37d\n\n"},{"id":"526344","messageId":"20250915-b4-pks-rust-breaking-change-v5-1-dc3a32fbb216@pks.im","threadId":"64091","inReplyTo":"20250915-b4-pks-rust-breaking-change-v5-0-dc3a32fbb216@pks.im","subject":"[PATCH v5 1/9] meson: add infrastructure to build internal Rust library","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-15T11:22:48Z","receivedAt":"2025-09-15T11:23:10Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Add the infrastructure into Meson to build an internal Rust library.\nBuilding the Rust parts of Git are for now entirely optional, as they\nare mostly intended as a test balloon for both Git developers, but also\nfor distributors of Git. So for now, they may contain:\n\n  - New features that are not mission critical to Git and that users can\n    easily live without.\n\n  - Alternative implementations of small subsystems.\n\nIf these test balloons are successful, we will eventually make Rust a\nmandatory dependency for our build process in Git 3.0.\n\nThe availability of a Rust toolchain will be auto-detected by Meson at\nsetup time. This behaviour can be tweaked via the `-Drust=` feature\ntoggle.\n\nNext to the linkable Rust library, also wire up tests that can be\nexecuted via `meson test`. This allows us to use the native unit testing\ncapabilities of Rust.\n\nNote that the Rust edition is currently set to 2018. This edition is\nsupported by Rust 1.49, which is the target for the upcoming gcc-rs\nbackend. For now we don't use any features of Rust that would require a\nnewer version, so settling on this old version makes sense so that\ngcc-rs may become an alternative backend for compiling Git. If we _do_\nwant to introduce features that were added in more recent editions of\nRust though we should reevaluate that choice.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n Cargo.toml         |  9 +++++++++\n meson.build        | 10 +++++++++-\n meson_options.txt  |  2 ++\n src/cargo-meson.sh | 32 ++++++++++++++++++++++++++++++++\n src/lib.rs         |  0\n src/meson.build    | 40 ++++++++++++++++++++++++++++++++++++++++\n 6 files changed, 92 insertions(+), 1 deletion(-)\n\ndiff --git a/Cargo.toml b/Cargo.toml\nnew file mode 100644\nindex 00000000000..b9a41dbc792\n--- /dev/null\n+++ b/Cargo.toml\n@@ -0,0 +1,9 @@\n+[package]\n+name = \"git\"\n+version = \"0.1.0\"\n+edition = \"2018\"\n+\n+[lib]\n+crate-type = [\"staticlib\"]\n+\n+[dependencies]\ndiff --git a/meson.build b/meson.build\nindex e8ec0eca165..234a9e9d6fd 100644\n--- a/meson.build\n+++ b/meson.build\n@@ -220,7 +220,7 @@ project('git', 'c',\n   # learned to define __STDC_VERSION__ with C11 and later. We thus require\n   # GNU C99 and fall back to C11. Meson only learned to handle the fallback\n   # with version 1.3.0, so on older versions we use GNU C99 unconditionally.\n-  default_options: meson.version().version_compare('>=1.3.0') ? ['c_std=gnu99,c11'] : ['c_std=gnu99'],\n+  default_options: meson.version().version_compare('>=1.3.0') ? ['rust_std=2018', 'c_std=gnu99,c11'] : ['rust_std=2018', 'c_std=gnu99'],\n )\n \n fs = import('fs')\n@@ -1702,6 +1702,13 @@ version_def_h = custom_target(\n )\n libgit_sources += version_def_h\n \n+cargo = find_program('cargo', dirs: program_path, native: true, required: get_option('rust'))\n+rust_option = get_option('rust').disable_auto_if(not cargo.found())\n+if rust_option.allowed()\n+  subdir('src')\n+  libgit_c_args += '-DWITH_RUST'\n+endif\n+\n libgit = declare_dependency(\n   link_with: static_library('git',\n     sources: libgit_sources,\n@@ -2239,6 +2246,7 @@ summary({\n   'pcre2': pcre2,\n   'perl': perl_features_enabled,\n   'python': target_python.found(),\n+  'rust': rust_option.allowed(),\n }, section: 'Auto-detected features', bool_yn: true)\n \n summary({\ndiff --git a/meson_options.txt b/meson_options.txt\nindex 1668f260a18..143dee9237c 100644\n--- a/meson_options.txt\n+++ b/meson_options.txt\n@@ -71,6 +71,8 @@ option('zlib_backend', type: 'combo', choices: ['auto', 'zlib', 'zlib-ng'], valu\n # Build tweaks.\n option('breaking_changes', type: 'boolean', value: false,\n   description: 'Enable upcoming breaking changes.')\n+option('rust', type: 'feature', value: 'auto',\n+  description: 'Enable building with Rust.')\n option('macos_use_homebrew_gettext', type: 'boolean', value: true,\n   description: 'Use gettext from Homebrew instead of the slightly-broken system-provided one.')\n \ndiff --git a/src/cargo-meson.sh b/src/cargo-meson.sh\nnew file mode 100755\nindex 00000000000..f29745beb36\n--- /dev/null\n+++ b/src/cargo-meson.sh\n@@ -0,0 +1,32 @@\n+#!/bin/sh\n+\n+if test \"$#\" -lt 2\n+then\n+\texit 1\n+fi\n+\n+SOURCE_DIR=\"$1\"\n+BUILD_DIR=\"$2\"\n+BUILD_TYPE=debug\n+\n+shift 2\n+\n+for arg\n+do\n+\tcase \"$arg\" in\n+\t--release)\n+\t\tBUILD_TYPE=release;;\n+\tesac\n+done\n+\n+cargo build --lib --quiet --manifest-path=\"$SOURCE_DIR/Cargo.toml\" --target-dir=\"$BUILD_DIR\" \"$@\"\n+RET=$?\n+if test $RET -ne 0\n+then\n+\texit $RET\n+fi\n+\n+if ! cmp \"$BUILD_DIR/$BUILD_TYPE/libgit.a\" \"$BUILD_DIR/libgit.a\" >/dev/null 2>&1\n+then\n+\tcp \"$BUILD_DIR/$BUILD_TYPE/libgit.a\" \"$BUILD_DIR/libgit.a\"\n+fi\ndiff --git a/src/lib.rs b/src/lib.rs\nnew file mode 100644\nindex 00000000000..e69de29bb2d\ndiff --git a/src/meson.build b/src/meson.build\nnew file mode 100644\nindex 00000000000..734de0b4fa9\n--- /dev/null\n+++ b/src/meson.build\n@@ -0,0 +1,40 @@\n+libgit_rs_sources = [\n+  'lib.rs',\n+]\n+\n+# Unfortunately we must use a wrapper command to move the output file into the\n+# current build directory. This can fixed once `cargo build --artifact-dir`\n+# stabilizes. See https://github.com/rust-lang/cargo/issues/6790 for that\n+# effort.\n+cargo_command = [\n+  shell,\n+  meson.current_source_dir() / 'cargo-meson.sh',\n+  meson.project_source_root(),\n+  meson.current_build_dir(),\n+]\n+if get_option('buildtype') == 'release'\n+  cargo_command += '--release'\n+endif\n+\n+libgit_rs = custom_target('git_rs',\n+  input: libgit_rs_sources + [\n+    meson.project_source_root() / 'Cargo.toml',\n+  ],\n+  output: 'libgit.a',\n+  command: cargo_command,\n+)\n+libgit_dependencies += declare_dependency(link_with: libgit_rs)\n+\n+if get_option('tests')\n+  test('rust', cargo,\n+    args: [\n+      'test',\n+      '--manifest-path',\n+      meson.project_source_root() / 'Cargo.toml',\n+      '--target-dir',\n+      meson.current_build_dir() / 'target',\n+    ],\n+    timeout: 0,\n+    protocol: 'rust',\n+  )\n+endif\n\n-- \n2.51.0.450.g87641ccf93.dirty\n\n"},{"id":"526345","messageId":"20250915-b4-pks-rust-breaking-change-v5-2-dc3a32fbb216@pks.im","threadId":"64091","inReplyTo":"20250915-b4-pks-rust-breaking-change-v5-0-dc3a32fbb216@pks.im","subject":"[PATCH v5 2/9] Makefile: reorder sources after includes","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-15T11:22:49Z","receivedAt":"2025-09-15T11:23:12Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"In an upcoming change we'll make some of the sources compile\nconditionally based on whether or not `WITH_RUST` is defined. To let\ndevelopers specify that flag in their \"config.mak\" we'll thus have to\nreorder our sources so that they come after the include of that file.\n\nDo so.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n Makefile | 176 +++++++++++++++++++++++++++++++--------------------------------\n 1 file changed, 88 insertions(+), 88 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 555b7f4dc3..7e52625d75 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -919,6 +919,94 @@ LIB_FILE = libgit.a\n XDIFF_LIB = xdiff/lib.a\n REFTABLE_LIB = reftable/libreftable.a\n \n+# xdiff and reftable libs may in turn depend on what is in libgit.a\n+GITLIBS = common-main.o $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(LIB_FILE)\n+EXTLIBS =\n+\n+GIT_USER_AGENT = git/$(GIT_VERSION)\n+\n+ifeq ($(wildcard sha1collisiondetection/lib/sha1.h),sha1collisiondetection/lib/sha1.h)\n+DC_SHA1_SUBMODULE = auto\n+endif\n+\n+# Set CFLAGS, LDFLAGS and other *FLAGS variables. These might be\n+# tweaked by config.* below as well as the command-line, both of\n+# which'll override these defaults.\n+# Older versions of GCC may require adding \"-std=gnu99\" at the end.\n+CFLAGS = -g -O2 -Wall\n+LDFLAGS =\n+CC_LD_DYNPATH = -Wl,-rpath,\n+BASIC_CFLAGS = -I.\n+BASIC_LDFLAGS =\n+\n+# library flags\n+ARFLAGS = rcs\n+PTHREAD_CFLAGS =\n+\n+# For the 'sparse' target\n+SPARSE_FLAGS ?= -std=gnu99 -D__STDC_NO_VLA__\n+SP_EXTRA_FLAGS =\n+\n+# For informing GIT-BUILD-OPTIONS of the SANITIZE=leak,address targets\n+SANITIZE_LEAK =\n+SANITIZE_ADDRESS =\n+\n+# For the 'coccicheck' target\n+SPATCH_INCLUDE_FLAGS = --all-includes\n+SPATCH_FLAGS =\n+SPATCH_TEST_FLAGS =\n+\n+# If *.o files are present, have \"coccicheck\" depend on them, with\n+# COMPUTE_HEADER_DEPENDENCIES this will speed up the common-case of\n+# only needing to re-generate coccicheck results for the users of a\n+# given API if it's changed, and not all files in the project. If\n+# COMPUTE_HEADER_DEPENDENCIES=no this will be unset too.\n+SPATCH_USE_O_DEPENDENCIES = YesPlease\n+\n+# Set SPATCH_CONCAT_COCCI to concatenate the contrib/cocci/*.cocci\n+# files into a single contrib/cocci/ALL.cocci before running\n+# \"coccicheck\".\n+#\n+# Pros:\n+#\n+# - Speeds up a one-shot run of \"make coccicheck\", as we won't have to\n+#   parse *.[ch] files N times for the N *.cocci rules\n+#\n+# Cons:\n+#\n+# - Will make incremental development of *.cocci slower, as\n+#   e.g. changing strbuf.cocci will re-run all *.cocci.\n+#\n+# - Makes error and performance analysis harder, as rules will be\n+#   applied from a monolithic ALL.cocci, rather than\n+#   e.g. strbuf.cocci. To work around this either undefine this, or\n+#   generate a specific patch, e.g. this will always use strbuf.cocci,\n+#   not ALL.cocci:\n+#\n+#\tmake contrib/coccinelle/strbuf.cocci.patch\n+SPATCH_CONCAT_COCCI = YesPlease\n+\n+# Rebuild 'coccicheck' if $(SPATCH), its flags etc. change\n+TRACK_SPATCH_DEFINES =\n+TRACK_SPATCH_DEFINES += $(SPATCH)\n+TRACK_SPATCH_DEFINES += $(SPATCH_INCLUDE_FLAGS)\n+TRACK_SPATCH_DEFINES += $(SPATCH_FLAGS)\n+TRACK_SPATCH_DEFINES += $(SPATCH_TEST_FLAGS)\n+GIT-SPATCH-DEFINES: FORCE\n+\t@FLAGS='$(TRACK_SPATCH_DEFINES)'; \\\n+\t    if test x\"$$FLAGS\" != x\"`cat GIT-SPATCH-DEFINES 2>/dev/null`\" ; then \\\n+\t\techo >&2 \"    * new spatch flags\"; \\\n+\t\techo \"$$FLAGS\" >GIT-SPATCH-DEFINES; \\\n+            fi\n+\n+include config.mak.uname\n+-include config.mak.autogen\n+-include config.mak\n+\n+ifdef DEVELOPER\n+include config.mak.dev\n+endif\n+\n GENERATED_H += command-list.h\n GENERATED_H += config-list.h\n GENERATED_H += hook-list.h\n@@ -1387,94 +1475,6 @@ CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/unit-test.o\n \n UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o\n \n-# xdiff and reftable libs may in turn depend on what is in libgit.a\n-GITLIBS = common-main.o $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(LIB_FILE)\n-EXTLIBS =\n-\n-GIT_USER_AGENT = git/$(GIT_VERSION)\n-\n-ifeq ($(wildcard sha1collisiondetection/lib/sha1.h),sha1collisiondetection/lib/sha1.h)\n-DC_SHA1_SUBMODULE = auto\n-endif\n-\n-# Set CFLAGS, LDFLAGS and other *FLAGS variables. These might be\n-# tweaked by config.* below as well as the command-line, both of\n-# which'll override these defaults.\n-# Older versions of GCC may require adding \"-std=gnu99\" at the end.\n-CFLAGS = -g -O2 -Wall\n-LDFLAGS =\n-CC_LD_DYNPATH = -Wl,-rpath,\n-BASIC_CFLAGS = -I.\n-BASIC_LDFLAGS =\n-\n-# library flags\n-ARFLAGS = rcs\n-PTHREAD_CFLAGS =\n-\n-# For the 'sparse' target\n-SPARSE_FLAGS ?= -std=gnu99 -D__STDC_NO_VLA__\n-SP_EXTRA_FLAGS =\n-\n-# For informing GIT-BUILD-OPTIONS of the SANITIZE=leak,address targets\n-SANITIZE_LEAK =\n-SANITIZE_ADDRESS =\n-\n-# For the 'coccicheck' target\n-SPATCH_INCLUDE_FLAGS = --all-includes\n-SPATCH_FLAGS =\n-SPATCH_TEST_FLAGS =\n-\n-# If *.o files are present, have \"coccicheck\" depend on them, with\n-# COMPUTE_HEADER_DEPENDENCIES this will speed up the common-case of\n-# only needing to re-generate coccicheck results for the users of a\n-# given API if it's changed, and not all files in the project. If\n-# COMPUTE_HEADER_DEPENDENCIES=no this will be unset too.\n-SPATCH_USE_O_DEPENDENCIES = YesPlease\n-\n-# Set SPATCH_CONCAT_COCCI to concatenate the contrib/cocci/*.cocci\n-# files into a single contrib/cocci/ALL.cocci before running\n-# \"coccicheck\".\n-#\n-# Pros:\n-#\n-# - Speeds up a one-shot run of \"make coccicheck\", as we won't have to\n-#   parse *.[ch] files N times for the N *.cocci rules\n-#\n-# Cons:\n-#\n-# - Will make incremental development of *.cocci slower, as\n-#   e.g. changing strbuf.cocci will re-run all *.cocci.\n-#\n-# - Makes error and performance analysis harder, as rules will be\n-#   applied from a monolithic ALL.cocci, rather than\n-#   e.g. strbuf.cocci. To work around this either undefine this, or\n-#   generate a specific patch, e.g. this will always use strbuf.cocci,\n-#   not ALL.cocci:\n-#\n-#\tmake contrib/coccinelle/strbuf.cocci.patch\n-SPATCH_CONCAT_COCCI = YesPlease\n-\n-# Rebuild 'coccicheck' if $(SPATCH), its flags etc. change\n-TRACK_SPATCH_DEFINES =\n-TRACK_SPATCH_DEFINES += $(SPATCH)\n-TRACK_SPATCH_DEFINES += $(SPATCH_INCLUDE_FLAGS)\n-TRACK_SPATCH_DEFINES += $(SPATCH_FLAGS)\n-TRACK_SPATCH_DEFINES += $(SPATCH_TEST_FLAGS)\n-GIT-SPATCH-DEFINES: FORCE\n-\t@FLAGS='$(TRACK_SPATCH_DEFINES)'; \\\n-\t    if test x\"$$FLAGS\" != x\"`cat GIT-SPATCH-DEFINES 2>/dev/null`\" ; then \\\n-\t\techo >&2 \"    * new spatch flags\"; \\\n-\t\techo \"$$FLAGS\" >GIT-SPATCH-DEFINES; \\\n-            fi\n-\n-include config.mak.uname\n--include config.mak.autogen\n--include config.mak\n-\n-ifdef DEVELOPER\n-include config.mak.dev\n-endif\n-\n GIT-VERSION-FILE: FORCE\n \t@OLD=$$(cat $@ 2>/dev/null || :) && \\\n \t$(call version_gen,\"$(shell pwd)\",GIT-VERSION-FILE.in,$@) && \\\n\n-- \n2.51.0.450.g87641ccf93.dirty\n\n"},{"id":"526346","messageId":"20250915-b4-pks-rust-breaking-change-v5-3-dc3a32fbb216@pks.im","threadId":"64091","inReplyTo":"20250915-b4-pks-rust-breaking-change-v5-0-dc3a32fbb216@pks.im","subject":"[PATCH v5 3/9] Makefile: introduce infrastructure to build internal Rust library","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-15T11:22:50Z","receivedAt":"2025-09-15T11:23:16Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Introduce infrastructure to build the internal Rust library. This\nmirrors the infrastructure we have added to Meson in the preceding\ncommit. Developers can enable the infrastructure by passing the new\n`WITH_RUST` build toggle.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n .gitignore |  2 ++\n Makefile   | 37 +++++++++++++++++++++++++++++++++++++\n shared.mak |  1 +\n 3 files changed, 40 insertions(+)\n\ndiff --git a/.gitignore b/.gitignore\nindex 1803023427..0833453cf6 100644\n--- a/.gitignore\n+++ b/.gitignore\n@@ -1,4 +1,6 @@\n /fuzz_corpora\n+/target/\n+/Cargo.lock\n /GIT-BUILD-DIR\n /GIT-BUILD-OPTIONS\n /GIT-CFLAGS\ndiff --git a/Makefile b/Makefile\nindex 7e52625d75..e8518198fc 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -483,6 +483,14 @@ include shared.mak\n # Define LIBPCREDIR=/foo/bar if your PCRE header and library files are\n # in /foo/bar/include and /foo/bar/lib directories.\n #\n+# == Optional Rust support ==\n+#\n+# Define WITH_RUST if you want to include features and subsystems written in\n+# Rust into Git. For now, Rust is still an optional feature of the build\n+# process. With Git 3.0 though, Rust will always be enabled.\n+#\n+# Building Rust code requires Cargo.\n+#\n # == SHA-1 and SHA-256 defines ==\n #\n # === SHA-1 backend ===\n@@ -683,6 +691,7 @@ OBJECTS =\n OTHER_PROGRAMS =\n PROGRAM_OBJS =\n PROGRAMS =\n+RUST_SOURCES =\n EXCLUDED_PROGRAMS =\n SCRIPT_PERL =\n SCRIPT_PYTHON =\n@@ -918,6 +927,11 @@ TEST_SHELL_PATH = $(SHELL_PATH)\n LIB_FILE = libgit.a\n XDIFF_LIB = xdiff/lib.a\n REFTABLE_LIB = reftable/libreftable.a\n+ifdef DEBUG\n+RUST_LIB = target/debug/libgit.a\n+else\n+RUST_LIB = target/release/libgit.a\n+endif\n \n # xdiff and reftable libs may in turn depend on what is in libgit.a\n GITLIBS = common-main.o $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(LIB_FILE)\n@@ -943,6 +957,15 @@ BASIC_LDFLAGS =\n ARFLAGS = rcs\n PTHREAD_CFLAGS =\n \n+# Rust flags\n+CARGO_ARGS =\n+ifndef V\n+CARGO_ARGS += --quiet\n+endif\n+ifndef DEBUG\n+CARGO_ARGS += --release\n+endif\n+\n # For the 'sparse' target\n SPARSE_FLAGS ?= -std=gnu99 -D__STDC_NO_VLA__\n SP_EXTRA_FLAGS =\n@@ -1475,6 +1498,8 @@ CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/unit-test.o\n \n UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o\n \n+RUST_SOURCES += src/lib.rs\n+\n GIT-VERSION-FILE: FORCE\n \t@OLD=$$(cat $@ 2>/dev/null || :) && \\\n \t$(call version_gen,\"$(shell pwd)\",GIT-VERSION-FILE.in,$@) && \\\n@@ -1504,6 +1529,11 @@ endif\n ALL_CFLAGS = $(DEVELOPER_CFLAGS) $(CPPFLAGS) $(CFLAGS) $(CFLAGS_APPEND)\n ALL_LDFLAGS = $(LDFLAGS) $(LDFLAGS_APPEND)\n \n+ifdef WITH_RUST\n+BASIC_CFLAGS += -DWITH_RUST\n+GITLIBS += $(RUST_LIB)\n+endif\n+\n ifdef SANITIZE\n SANITIZERS := $(foreach flag,$(subst $(comma),$(space),$(SANITIZE)),$(flag))\n BASIC_CFLAGS += -fsanitize=$(SANITIZE) -fno-sanitize-recover=$(SANITIZE)\n@@ -2918,6 +2948,12 @@ scalar$X: scalar.o GIT-LDFLAGS $(GITLIBS)\n $(LIB_FILE): $(LIB_OBJS)\n \t$(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^\n \n+$(RUST_LIB): Cargo.toml $(RUST_SOURCES)\n+\t$(QUIET_CARGO)cargo build $(CARGO_ARGS)\n+\n+.PHONY: rust\n+rust: $(RUST_LIB)\n+\n $(XDIFF_LIB): $(XDIFF_OBJS)\n \t$(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^\n \n@@ -3768,6 +3804,7 @@ clean: profile-clean coverage-clean cocciclean\n \t$(RM) $(FUZZ_PROGRAMS)\n \t$(RM) $(SP_OBJ)\n \t$(RM) $(HCC)\n+\t$(RM) -r Cargo.lock target/\n \t$(RM) version-def.h\n \t$(RM) -r $(dep_dirs) $(compdb_dir) compile_commands.json\n \t$(RM) $(test_bindir_programs)\ndiff --git a/shared.mak b/shared.mak\nindex 5c7bc94785..0e7492076e 100644\n--- a/shared.mak\n+++ b/shared.mak\n@@ -56,6 +56,7 @@ ifndef V\n \tQUIET_MKDIR_P_PARENT  = @echo '   ' MKDIR -p $(@D);\n \n ## Used in \"Makefile\"\n+\tQUIET_CARGO    = @echo '   ' CARGO $@;\n \tQUIET_CC       = @echo '   ' CC $@;\n \tQUIET_AR       = @echo '   ' AR $@;\n \tQUIET_LINK     = @echo '   ' LINK $@;\n\n-- \n2.51.0.450.g87641ccf93.dirty\n\n"},{"id":"526347","messageId":"20250915-b4-pks-rust-breaking-change-v5-4-dc3a32fbb216@pks.im","threadId":"64091","inReplyTo":"20250915-b4-pks-rust-breaking-change-v5-0-dc3a32fbb216@pks.im","subject":"[PATCH v5 4/9] help: report on whether or not Rust is enabled","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-15T11:22:51Z","receivedAt":"2025-09-15T11:23:19Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"We're about to introduce support for Rust into the core of Git, where\nsome (trivial) subsystems are converted to Rust. These subsystems will\nalso retain a C implementation though as Rust is not yet mandatory.\nConsequently, it now becomes possible for a Git version to have bugs\nthat are specific to whether or not it is built with Rust support\noverall.\n\nExpose information about whether or not Git was built with Rust via our\nbuild info. This means that both `git version --build-options`, but also\n`git bugreport` will now expose that bit of information. Hopefully, this\nshould make it easier for us to discover any Rust-specific issues.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n help.c | 6 ++++++\n 1 file changed, 6 insertions(+)\n\ndiff --git a/help.c b/help.c\nindex bb20498cfd..5854dd4a7e 100644\n--- a/help.c\n+++ b/help.c\n@@ -791,6 +791,12 @@ void get_version_info(struct strbuf *buf, int show_build_options)\n \t\tstrbuf_addf(buf, \"shell-path: %s\\n\", SHELL_PATH);\n \t\t/* NEEDSWORK: also save and output GIT-BUILD_OPTIONS? */\n \n+#if defined WITH_RUST\n+\t\tstrbuf_addstr(buf, \"rust: enabled\\n\");\n+#else\n+\t\tstrbuf_addstr(buf, \"rust: disabled\\n\");\n+#endif\n+\n \t\tif (fsmonitor_ipc__is_supported())\n \t\t\tstrbuf_addstr(buf, \"feature: fsmonitor--daemon\\n\");\n #if defined LIBCURL_VERSION\n\n-- \n2.51.0.450.g87641ccf93.dirty\n\n"},{"id":"526348","messageId":"20250915-b4-pks-rust-breaking-change-v5-5-dc3a32fbb216@pks.im","threadId":"64091","inReplyTo":"20250915-b4-pks-rust-breaking-change-v5-0-dc3a32fbb216@pks.im","subject":"[PATCH v5 5/9] varint: use explicit width for integers","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-15T11:22:52Z","receivedAt":"2025-09-15T11:23:23Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The varint subsystem currently uses implcit widths for integers. On the\none hand we use `uintmax_t` for the actual value. On the other hand, we\nuse `int` for the length of the encoded varint.\n\nBoth of these have known maximum vaules, as we only support at most 16\nbytes when encoding varints. Thus, we know that we won't ever exceed\n`uint64_t` for the actual value and `uint8_t` for the prefix length.\n\nRefactor the code to use explicit widths. Besides making the logic\nplatform-independent, it also makes our life a bit easier in the next\ncommit, where we reimplement \"varint.c\" in Rust.\n\nSuggested-by: Ezekiel Newren <ezekielnewren@gmail.com>\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n dir.c        | 18 ++++++++++--------\n read-cache.c |  6 ++++--\n varint.c     |  6 +++---\n varint.h     |  4 ++--\n 4 files changed, 19 insertions(+), 15 deletions(-)\n\ndiff --git a/dir.c b/dir.c\nindex 71108ac79b7..0a67a99cb3d 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -3579,7 +3579,8 @@ static void write_one_dir(struct untracked_cache_dir *untracked,\n \tstruct stat_data stat_data;\n \tstruct strbuf *out = &wd->out;\n \tunsigned char intbuf[16];\n-\tunsigned int intlen, value;\n+\tunsigned int value;\n+\tuint8_t intlen;\n \tint i = wd->index++;\n \n \t/*\n@@ -3632,7 +3633,7 @@ void write_untracked_extension(struct strbuf *out, struct untracked_cache *untra\n \tstruct ondisk_untracked_cache *ouc;\n \tstruct write_data wd;\n \tunsigned char varbuf[16];\n-\tint varint_len;\n+\tuint8_t varint_len;\n \tconst unsigned hashsz = the_hash_algo->rawsz;\n \n \tCALLOC_ARRAY(ouc, 1);\n@@ -3738,7 +3739,7 @@ static int read_one_dir(struct untracked_cache_dir **untracked_,\n \tstruct untracked_cache_dir ud, *untracked;\n \tconst unsigned char *data = rd->data, *end = rd->end;\n \tconst unsigned char *eos;\n-\tunsigned int value;\n+\tuint64_t value;\n \tint i;\n \n \tmemset(&ud, 0, sizeof(ud));\n@@ -3830,7 +3831,8 @@ struct untracked_cache *read_untracked_extension(const void *data, unsigned long\n \tstruct read_data rd;\n \tconst unsigned char *next = data, *end = (const unsigned char *)data + sz;\n \tconst char *ident;\n-\tint ident_len;\n+\tuint64_t ident_len;\n+\tuint64_t varint_len;\n \tssize_t len;\n \tconst char *exclude_per_dir;\n \tconst unsigned hashsz = the_hash_algo->rawsz;\n@@ -3867,8 +3869,8 @@ struct untracked_cache *read_untracked_extension(const void *data, unsigned long\n \tif (next >= end)\n \t\tgoto done2;\n \n-\tlen = decode_varint(&next);\n-\tif (next > end || len == 0)\n+\tvarint_len = decode_varint(&next);\n+\tif (next > end || varint_len == 0)\n \t\tgoto done2;\n \n \trd.valid      = ewah_new();\n@@ -3877,9 +3879,9 @@ struct untracked_cache *read_untracked_extension(const void *data, unsigned long\n \trd.data\t      = next;\n \trd.end\t      = end;\n \trd.index      = 0;\n-\tALLOC_ARRAY(rd.ucd, len);\n+\tALLOC_ARRAY(rd.ucd, varint_len);\n \n-\tif (read_one_dir(&uc->root, &rd) || rd.index != len)\n+\tif (read_one_dir(&uc->root, &rd) || rd.index != varint_len)\n \t\tgoto done;\n \n \tnext = rd.data;\ndiff --git a/read-cache.c b/read-cache.c\nindex 06ad74db228..41b44148b1e 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -1807,7 +1807,7 @@ static struct cache_entry *create_from_disk(struct mem_pool *ce_mem_pool,\n \n \tif (expand_name_field) {\n \t\tconst unsigned char *cp = (const unsigned char *)name;\n-\t\tsize_t strip_len, previous_len;\n+\t\tuint64_t strip_len, previous_len;\n \n \t\t/* If we're at the beginning of a block, ignore the previous name */\n \t\tstrip_len = decode_varint(&cp);\n@@ -2655,8 +2655,10 @@ static int ce_write_entry(struct hashfile *f, struct cache_entry *ce,\n \t\thashwrite(f, ce->name, len);\n \t\thashwrite(f, padding, align_padding_size(size, len));\n \t} else {\n-\t\tint common, to_remove, prefix_size;\n+\t\tint common, to_remove;\n+\t\tuint8_t prefix_size;\n \t\tunsigned char to_remove_vi[16];\n+\n \t\tfor (common = 0;\n \t\t     (common < previous_name->len &&\n \t\t      ce->name[common] &&\ndiff --git a/varint.c b/varint.c\nindex 409c4977a1e..03cd54416b6 100644\n--- a/varint.c\n+++ b/varint.c\n@@ -1,11 +1,11 @@\n #include \"git-compat-util.h\"\n #include \"varint.h\"\n \n-uintmax_t decode_varint(const unsigned char **bufp)\n+uint64_t decode_varint(const unsigned char **bufp)\n {\n \tconst unsigned char *buf = *bufp;\n \tunsigned char c = *buf++;\n-\tuintmax_t val = c & 127;\n+\tuint64_t val = c & 127;\n \twhile (c & 128) {\n \t\tval += 1;\n \t\tif (!val || MSB(val, 7))\n@@ -17,7 +17,7 @@ uintmax_t decode_varint(const unsigned char **bufp)\n \treturn val;\n }\n \n-int encode_varint(uintmax_t value, unsigned char *buf)\n+uint8_t encode_varint(uint64_t value, unsigned char *buf)\n {\n \tunsigned char varint[16];\n \tunsigned pos = sizeof(varint) - 1;\ndiff --git a/varint.h b/varint.h\nindex f78bb0ca528..eb401935bd2 100644\n--- a/varint.h\n+++ b/varint.h\n@@ -1,7 +1,7 @@\n #ifndef VARINT_H\n #define VARINT_H\n \n-int encode_varint(uintmax_t, unsigned char *);\n-uintmax_t decode_varint(const unsigned char **);\n+uint8_t encode_varint(uint64_t, unsigned char *);\n+uint64_t decode_varint(const unsigned char **);\n \n #endif /* VARINT_H */\n\n-- \n2.51.0.450.g87641ccf93.dirty\n\n"},{"id":"526349","messageId":"20250915-b4-pks-rust-breaking-change-v5-6-dc3a32fbb216@pks.im","threadId":"64091","inReplyTo":"20250915-b4-pks-rust-breaking-change-v5-0-dc3a32fbb216@pks.im","subject":"[PATCH v5 6/9] varint: reimplement as test balloon for Rust","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-15T11:22:53Z","receivedAt":"2025-09-15T11:23:26Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Implement a trivial test balloon for our Rust build infrastructure by\nreimplementing the \"varint.c\" subsystem in Rust. This subsystem is\nchosen because it is trivial to convert and because it doesn't have any\ndependencies to other components of Git.\n\nIf support for Rust is enabled, we stop compiling \"varint.c\" and instead\ncompile and use \"src/varint.rs\".\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n Makefile        |  3 ++\n meson.build     |  5 +++-\n src/lib.rs      |  1 +\n src/meson.build |  1 +\n src/varint.rs   | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n 5 files changed, 101 insertions(+), 1 deletion(-)\n\ndiff --git a/Makefile b/Makefile\nindex e8518198fcb..d7d6f6eefcb 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -1307,7 +1307,9 @@ LIB_OBJS += urlmatch.o\n LIB_OBJS += usage.o\n LIB_OBJS += userdiff.o\n LIB_OBJS += utf8.o\n+ifndef WITH_RUST\n LIB_OBJS += varint.o\n+endif\n LIB_OBJS += version.o\n LIB_OBJS += versioncmp.o\n LIB_OBJS += walker.o\n@@ -1499,6 +1501,7 @@ CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/unit-test.o\n UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o\n \n RUST_SOURCES += src/lib.rs\n+RUST_SOURCES += src/varint.rs\n \n GIT-VERSION-FILE: FORCE\n \t@OLD=$$(cat $@ 2>/dev/null || :) && \\\ndiff --git a/meson.build b/meson.build\nindex 234a9e9d6fd..37dfa286017 100644\n--- a/meson.build\n+++ b/meson.build\n@@ -522,7 +522,6 @@ libgit_sources = [\n   'usage.c',\n   'userdiff.c',\n   'utf8.c',\n-  'varint.c',\n   'version.c',\n   'versioncmp.c',\n   'walker.c',\n@@ -1707,6 +1706,10 @@ rust_option = get_option('rust').disable_auto_if(not cargo.found())\n if rust_option.allowed()\n   subdir('src')\n   libgit_c_args += '-DWITH_RUST'\n+else\n+  libgit_sources += [\n+    'varint.c',\n+  ]\n endif\n \n libgit = declare_dependency(\ndiff --git a/src/lib.rs b/src/lib.rs\nindex e69de29bb2d..9da70d8b57d 100644\n--- a/src/lib.rs\n+++ b/src/lib.rs\n@@ -0,0 +1 @@\n+pub mod varint;\ndiff --git a/src/meson.build b/src/meson.build\nindex 734de0b4fa9..b19ef4c0b51 100644\n--- a/src/meson.build\n+++ b/src/meson.build\n@@ -1,5 +1,6 @@\n libgit_rs_sources = [\n   'lib.rs',\n+  'varint.rs',\n ]\n \n # Unfortunately we must use a wrapper command to move the output file into the\ndiff --git a/src/varint.rs b/src/varint.rs\nnew file mode 100644\nindex 00000000000..10c83e1f439\n--- /dev/null\n+++ b/src/varint.rs\n@@ -0,0 +1,92 @@\n+#[no_mangle]\n+pub unsafe extern \"C\" fn decode_varint(bufp: *mut *const u8) -> usize {\n+    let mut buf = *bufp;\n+    let mut c = *buf;\n+    let mut val = usize::from(c & 127);\n+\n+    buf = buf.add(1);\n+\n+    while (c & 128) != 0 {\n+        val = val.wrapping_add(1);\n+        if val == 0 || val.leading_zeros() < 7 {\n+            return 0; // overflow\n+        }\n+\n+        c = *buf;\n+        buf = buf.add(1);\n+\n+        val = (val << 7) + usize::from(c & 127);\n+    }\n+\n+    *bufp = buf;\n+    val\n+}\n+\n+#[no_mangle]\n+pub unsafe extern \"C\" fn encode_varint(value: usize, buf: *mut u8) -> u8 {\n+    let mut varint: [u8; 16] = [0; 16];\n+    let mut pos = varint.len() - 1;\n+\n+    varint[pos] = (value & 127) as u8;\n+\n+    let mut value = value >> 7;\n+    while value != 0 {\n+        pos -= 1;\n+        value -= 1;\n+        varint[pos] = 128 | (value & 127) as u8;\n+        value >>= 7;\n+    }\n+\n+    if !buf.is_null() {\n+        std::ptr::copy_nonoverlapping(varint.as_ptr().add(pos), buf, varint.len() - pos);\n+    }\n+\n+    (varint.len() - pos) as u8\n+}\n+\n+#[cfg(test)]\n+mod tests {\n+    use super::*;\n+\n+    #[test]\n+    fn test_decode_varint() {\n+        unsafe {\n+            assert_eq!(decode_varint(&mut [0x00].as_slice().as_ptr()), 0);\n+            assert_eq!(decode_varint(&mut [0x01].as_slice().as_ptr()), 1);\n+            assert_eq!(decode_varint(&mut [0x7f].as_slice().as_ptr()), 127);\n+            assert_eq!(decode_varint(&mut [0x80, 0x00].as_slice().as_ptr()), 128);\n+            assert_eq!(decode_varint(&mut [0x80, 0x01].as_slice().as_ptr()), 129);\n+            assert_eq!(decode_varint(&mut [0x80, 0x7f].as_slice().as_ptr()), 255);\n+\n+            // Overflows are expected to return 0.\n+            assert_eq!(decode_varint(&mut [0x88; 16].as_slice().as_ptr()), 0);\n+        }\n+    }\n+\n+    #[test]\n+    fn test_encode_varint() {\n+        unsafe {\n+            let mut varint: [u8; 16] = [0; 16];\n+\n+            assert_eq!(encode_varint(0, std::ptr::null_mut()), 1);\n+\n+            assert_eq!(encode_varint(0, varint.as_mut_slice().as_mut_ptr()), 1);\n+            assert_eq!(varint, [0; 16]);\n+\n+            assert_eq!(encode_varint(10, varint.as_mut_slice().as_mut_ptr()), 1);\n+            assert_eq!(varint, [10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n+\n+            assert_eq!(encode_varint(127, varint.as_mut_slice().as_mut_ptr()), 1);\n+            assert_eq!(varint, [127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n+\n+            assert_eq!(encode_varint(128, varint.as_mut_slice().as_mut_ptr()), 2);\n+            assert_eq!(varint, [128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n+\n+            assert_eq!(encode_varint(129, varint.as_mut_slice().as_mut_ptr()), 2);\n+            assert_eq!(varint, [128, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n+\n+            assert_eq!(encode_varint(255, varint.as_mut_slice().as_mut_ptr()), 2);\n+            assert_eq!(varint, [128, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n+        }\n+    }\n+}\n\n-- \n2.51.0.450.g87641ccf93.dirty\n\n"},{"id":"526350","messageId":"20250915-b4-pks-rust-breaking-change-v5-7-dc3a32fbb216@pks.im","threadId":"64091","inReplyTo":"20250915-b4-pks-rust-breaking-change-v5-0-dc3a32fbb216@pks.im","subject":"[PATCH v5 7/9] BreakingChanges: announce Rust becoming mandatory","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-15T11:22:54Z","receivedAt":"2025-09-15T11:23:29Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Over the last couple of years the appetite for bringing Rust into the\ncodebase has grown significantly across the developer base. Introducing\nRust is a major change though and has ramifications for the whole\necosystem:\n\n  - Some platforms have a Rust toolchain available, but have not yet\n    integrated it into their build infrastructure.\n\n  - Some platforms don't have any support for Rust at all.\n\n  - Some platforms may have to figure out how to fit Rust into their\n    bootstrapping sequence.\n\nDue to this, and given that Git is a critical piece of infrastructure\nfor the whole industry, we cannot just introduce such a heavyweight\ndependency without doing our due diligence.\n\nInstead, preceding commits have introduced a test balloon into our build\ninfrastructure that convert one tiny subsystem to use Rust. For now,\nusing Rust to build that subsystem is entirely optional -- if no Rust\nsupport is available, we continue to use the C implementation. This test\nballoon has the intention to give distributions time and let them ease\ninto our adoption of Rust.\n\nHaving multiple implementations of the same subsystem is not sustainable\nthough, and the plan is to eventually be able to use Rust freely all\nacross our codebase. As such, there is the intent to make Rust become a\nmandatory part of our build process.\n\nAdd an announcement to our breaking changes that Rust will become\nmandatory in Git 3.0. A (very careful and non-binding) estimate might be\nthat this major release might be released in the second half of next\nyear, which should give distributors enough time to prepare for the\nchange.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n Documentation/BreakingChanges.adoc | 38 ++++++++++++++++++++++++++++++++++++++\n 1 file changed, 38 insertions(+)\n\ndiff --git a/Documentation/BreakingChanges.adoc b/Documentation/BreakingChanges.adoc\nindex f8d2eba061..0512411030 100644\n--- a/Documentation/BreakingChanges.adoc\n+++ b/Documentation/BreakingChanges.adoc\n@@ -165,6 +165,44 @@ A prerequisite for this change is that the ecosystem is ready to support the\n \"reftable\" format. Most importantly, alternative implementations of Git like\n JGit, libgit2 and Gitoxide need to support it.\n \n+* Git will require Rust as a mandatory part of the build process. While Git\n+  already started to adopt Rust in Git 2.52, all parts written in Rust are\n+  optional for the time being. This includes:\n++\n+  ** Subsystems that have an alternative implementation in Rust to test\n+     interoperability between our C and Rust codebase.\n+  ** Newly written features that are not mission critical for a fully functional\n+     Git client.\n++\n+These changes are meant as test balloons to allow distributors of Git to prepare\n+for Rust becoming a mandatory part of the build process. There will be multiple\n+milestones for the introduction of Rust:\n++\n+--\n+1. Initially, with Git 2.52, support for Rust will be auto-detected by Meson and\n+   disabled in our Makefile so that the project can sort out the initial\n+   infrastructure.\n+2. In Git 2.53, both build systems will default-enable support for Rust.\n+   Consequently, builds will break by default if Rust is not available on the\n+   build host. The use of Rust can still be explicitly disabled via build\n+   flags.\n+3. In Git 3.0, the build options will be removed and support for Rust is\n+   mandatory.\n+--\n++\n+You can explicitly ask both Meson and our Makefile-based system to enable Rust\n+by saying `meson configure -Drust=enabled` and `make WITH_RUST=YesPlease`,\n+respectively.\n++\n+The Git project will declare the last version before Git 3.0 to be a long-term\n+support release. This long-term release will receive important bug fixes for at\n+least four release cycles and security fixes for six release cycles. The Git\n+project will hand over maintainership of the long-term release to distributors\n+in case they need to extend the life of that long-term release even further. In\n+that case, the backporting process will be handled by these distributors, but\n+the backported patches will be reviewed on the mailing list and pulled in by the\n+Git maintainer.\n+\n === Removals\n \n * Support for grafting commits has long been superseded by git-replace(1).\n\n-- \n2.51.0.450.g87641ccf93.dirty\n\n"},{"id":"526351","messageId":"20250915-b4-pks-rust-breaking-change-v5-8-dc3a32fbb216@pks.im","threadId":"64091","inReplyTo":"20250915-b4-pks-rust-breaking-change-v5-0-dc3a32fbb216@pks.im","subject":"[PATCH v5 8/9] ci: convert \"pedantic\" job into full build with breaking changes","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-15T11:22:55Z","receivedAt":"2025-09-15T11:23:32Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The \"pedantic\" CI job is building on Fedora with `DEVOPTS=pedantic`.\nThis build flag doesn't do anything anymore starting with 6a8cbc41ba\n(developer: enable pedantic by default, 2021-09-03), where we have\nflipped the default so that developers have to opt-out of pedantic\nbuilds via the \"no-pedantic\" option. As such, all this job really does\nis to do a normal build on Fedora, which isn't all that interesting.\n\nConvert that job into a full build-and-test job that uses Meson with\nbreaking changes enabled. This plugs two gaps:\n\n  - We now test on another distro that we didn't run tests on\n    beforehand.\n\n  - We verify that breaking changes work as expected with Meson.\n\nFurthermore, in a subsequent commit we'll modify both jobs that use\nbreaking changes to also enable Rust. By converting the Fedora job to\nuse Meson, we ensure that we test our Rust build infrastructure for both\nbuild systems.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n .github/workflows/main.yml |  4 ++--\n .gitlab-ci.yml             |  4 ++--\n ci/install-dependencies.sh |  6 +++++-\n ci/run-build-and-tests.sh  | 29 ++++++++---------------------\n 4 files changed, 17 insertions(+), 26 deletions(-)\n\ndiff --git a/.github/workflows/main.yml b/.github/workflows/main.yml\nindex d122e79415..393ea4d1cc 100644\n--- a/.github/workflows/main.yml\n+++ b/.github/workflows/main.yml\n@@ -379,6 +379,8 @@ jobs:\n         - jobname: linux-breaking-changes\n           cc: gcc\n           image: ubuntu:rolling\n+        - jobname: fedora-breaking-changes-meson\n+          image: fedora:latest\n         - jobname: linux-leaks\n           image: ubuntu:rolling\n           cc: gcc\n@@ -396,8 +398,6 @@ jobs:\n         # Supported until 2025-04-02.\n         - jobname: linux32\n           image: i386/ubuntu:focal\n-        - jobname: pedantic\n-          image: fedora:latest\n         # A RHEL 8 compatible distro.  Supported until 2029-05-31.\n         - jobname: almalinux-8\n           image: almalinux:8\ndiff --git a/.gitlab-ci.yml b/.gitlab-ci.yml\nindex af10ebb59a..4248506909 100644\n--- a/.gitlab-ci.yml\n+++ b/.gitlab-ci.yml\n@@ -45,6 +45,8 @@ test:linux:\n       - jobname: linux-breaking-changes\n         image: ubuntu:20.04\n         CC: gcc\n+      - jobname: fedora-breaking-changes-meson\n+        image: fedora:latest\n       - jobname: linux-TEST-vars\n         image: ubuntu:20.04\n         CC: gcc\n@@ -58,8 +60,6 @@ test:linux:\n       - jobname: linux-asan-ubsan\n         image: ubuntu:rolling\n         CC: clang\n-      - jobname: pedantic\n-        image: fedora:latest\n       - jobname: linux-musl-meson\n         image: alpine:latest\n       - jobname: linux32\ndiff --git a/ci/install-dependencies.sh b/ci/install-dependencies.sh\nindex d061a47293..35bd05b85b 100755\n--- a/ci/install-dependencies.sh\n+++ b/ci/install-dependencies.sh\n@@ -30,8 +30,12 @@ alpine-*)\n \t\tbash cvs gnupg perl-cgi perl-dbd-sqlite perl-io-tty >/dev/null\n \t;;\n fedora-*|almalinux-*)\n+\tcase \"$jobname\" in\n+\t*-meson)\n+\t\tMESON_DEPS=\"meson ninja\";;\n+\tesac\n \tdnf -yq update >/dev/null &&\n-\tdnf -yq install shadow-utils sudo make gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel >/dev/null\n+\tdnf -yq install shadow-utils sudo make pkg-config gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel $MESON_DEPS >/dev/null\n \t;;\n ubuntu-*|i386/ubuntu-*|debian-*)\n \t# Required so that apt doesn't wait for user input on certain packages.\ndiff --git a/ci/run-build-and-tests.sh b/ci/run-build-and-tests.sh\nindex 01823fd0f1..3680446649 100755\n--- a/ci/run-build-and-tests.sh\n+++ b/ci/run-build-and-tests.sh\n@@ -5,12 +5,11 @@\n \n . ${0%/*}/lib.sh\n \n-run_tests=t\n-\n case \"$jobname\" in\n-linux-breaking-changes)\n+fedora-breaking-changes-musl|linux-breaking-changes)\n \texport GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main\n \texport WITH_BREAKING_CHANGES=YesPlease\n+\tMESONFLAGS=\"$MESONFLAGS -Dbreaking_changes=true\"\n \t;;\n linux-TEST-vars)\n \texport OPENSSL_SHA1_UNSAFE=YesPlease\n@@ -36,12 +35,6 @@ linux-sha256)\n linux-reftable|linux-reftable-leaks|osx-reftable)\n \texport GIT_TEST_DEFAULT_REF_FORMAT=reftable\n \t;;\n-pedantic)\n-\t# Don't run the tests; we only care about whether Git can be\n-\t# built.\n-\texport DEVOPTS=pedantic\n-\trun_tests=\n-\t;;\n esac\n \n case \"$jobname\" in\n@@ -54,21 +47,15 @@ case \"$jobname\" in\n \t\t-Dtest_output_directory=\"${TEST_OUTPUT_DIRECTORY:-$(pwd)/t}\" \\\n \t\t$MESONFLAGS\n \tgroup \"Build\" meson compile -C build --\n-\tif test -n \"$run_tests\"\n-\tthen\n-\t\tgroup \"Run tests\" meson test -C build --print-errorlogs --test-args=\"$GIT_TEST_OPTS\" || (\n-\t\t\t./t/aggregate-results.sh \"${TEST_OUTPUT_DIRECTORY:-t}/test-results\"\n-\t\t\thandle_failed_tests\n-\t\t)\n-\tfi\n+\tgroup \"Run tests\" meson test -C build --print-errorlogs --test-args=\"$GIT_TEST_OPTS\" || (\n+\t\t./t/aggregate-results.sh \"${TEST_OUTPUT_DIRECTORY:-t}/test-results\"\n+\t\thandle_failed_tests\n+\t)\n \t;;\n *)\n \tgroup Build make\n-\tif test -n \"$run_tests\"\n-\tthen\n-\t\tgroup \"Run tests\" make test ||\n-\t\thandle_failed_tests\n-\tfi\n+\tgroup \"Run tests\" make test ||\n+\thandle_failed_tests\n \t;;\n esac\n \n\n-- \n2.51.0.450.g87641ccf93.dirty\n\n"},{"id":"526352","messageId":"20250915-b4-pks-rust-breaking-change-v5-9-dc3a32fbb216@pks.im","threadId":"64091","inReplyTo":"20250915-b4-pks-rust-breaking-change-v5-0-dc3a32fbb216@pks.im","subject":"[PATCH v5 9/9] ci: enable Rust for breaking-changes jobs","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-15T11:22:56Z","receivedAt":"2025-09-15T11:23:35Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Enable Rust for our breaking-changes jobs so that we can verify that the\nbuild infrastructure and the converted Rust subsystems work as expected.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n ci/install-dependencies.sh | 4 ++--\n ci/run-build-and-tests.sh  | 2 ++\n 2 files changed, 4 insertions(+), 2 deletions(-)\n\ndiff --git a/ci/install-dependencies.sh b/ci/install-dependencies.sh\nindex 35bd05b85b..0d3aa496fc 100755\n--- a/ci/install-dependencies.sh\n+++ b/ci/install-dependencies.sh\n@@ -35,7 +35,7 @@ fedora-*|almalinux-*)\n \t\tMESON_DEPS=\"meson ninja\";;\n \tesac\n \tdnf -yq update >/dev/null &&\n-\tdnf -yq install shadow-utils sudo make pkg-config gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel $MESON_DEPS >/dev/null\n+\tdnf -yq install shadow-utils sudo make pkg-config gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel $MESON_DEPS cargo >/dev/null\n \t;;\n ubuntu-*|i386/ubuntu-*|debian-*)\n \t# Required so that apt doesn't wait for user input on certain packages.\n@@ -62,7 +62,7 @@ ubuntu-*|i386/ubuntu-*|debian-*)\n \t\tmake libssl-dev libcurl4-openssl-dev libexpat-dev wget sudo default-jre \\\n \t\ttcl tk gettext zlib1g-dev perl-modules liberror-perl libauthen-sasl-perl \\\n \t\tlibemail-valid-perl libio-pty-perl libio-socket-ssl-perl libnet-smtp-ssl-perl libdbd-sqlite3-perl libcgi-pm-perl \\\n-\t\tlibsecret-1-dev libpcre2-dev meson ninja-build pkg-config \\\n+\t\tlibsecret-1-dev libpcre2-dev meson ninja-build pkg-config cargo \\\n \t\t${CC_PACKAGE:-${CC:-gcc}} $PYTHON_PACKAGE\n \n \tcase \"$distro\" in\ndiff --git a/ci/run-build-and-tests.sh b/ci/run-build-and-tests.sh\nindex 3680446649..c718bd101a 100755\n--- a/ci/run-build-and-tests.sh\n+++ b/ci/run-build-and-tests.sh\n@@ -9,7 +9,9 @@ case \"$jobname\" in\n fedora-breaking-changes-musl|linux-breaking-changes)\n \texport GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main\n \texport WITH_BREAKING_CHANGES=YesPlease\n+\texport WITH_RUST=YesPlease\n \tMESONFLAGS=\"$MESONFLAGS -Dbreaking_changes=true\"\n+\tMESONFLAGS=\"$MESONFLAGS -Drust=enabled\"\n \t;;\n linux-TEST-vars)\n \texport OPENSSL_SHA1_UNSAFE=YesPlease\n\n-- \n2.51.0.450.g87641ccf93.dirty\n\n"},{"id":"526376","messageId":"xmqqsegnhc7p.fsf@gitster.g","threadId":"64091","inReplyTo":"20250915-b4-pks-rust-breaking-change-v5-0-dc3a32fbb216@pks.im","subject":"Re: [PATCH v5 0/9] Introduce Rust and announce that it will become mandatory","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-09-15T17:12:10Z","receivedAt":"2025-09-15T17:12:13Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> Changes in v5:\n>   - Fix indentation in the BreakingChanges document.\n>   - Fix a commit message typo.\n>   - Include \"Cargo.lock\" in the `make clean` target again.\n>   - Link to v4: https://lore.kernel.org/r/20250910-b4-pks-rust-breaking-change-v4-0-4a63fc69278d@pks.im\n\nIt seems that we are converging with smaller and smaller changes\nbetween iterations?  Will queue.\n\nThanks.\n"},{"id":"526414","messageId":"CAH=ZcbB0Qv=b-hdB2EVW-D-dob4NnzyWDYGEThYZm94S0V7OGg@mail.gmail.com","threadId":"64091","inReplyTo":"20250915-b4-pks-rust-breaking-change-v5-0-dc3a32fbb216@pks.im","subject":"Re: [PATCH v5 0/9] Introduce Rust and announce that it will become mandatory","fromName":"Ezekiel Newren","fromEmail":"ezekielnewren@gmail.com","sentAt":"2025-09-16T02:03:29Z","receivedAt":"2025-09-16T02:03:42Z","isPatch":true,"sender":{"key":"ezekielnewren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/18313324?v=4"},"body":"I am currently working on a patch series that makes Rust optional and\naddresses several concerns that this series does not:\n  * Rust calling C: Makefile has no way to build or run Rust so it\nwould have to call cargo test, but that doesn't work unless build.rs\ntells cargo where libgit.a is (among other things).\n  * Build tooling alignment: My build_rust.sh is called by make and\nmeson which eliminates defining how to build Rust in 2 places.\n  * Cargo vs Meson: Meson is adding support for Rust and it's getting\nbetter, but Cargo is the canonical build system for Rust. cargo is\nreleased in lockstep with rustc, and we _have_ to use cargo when\nbuilding with make because Meson won't be available in that case.\n  * Crates: Patrick's series assumes the Git codebase is _the_ crate\n    * cbindgen: Cbindgen outputs a single header file for each crate,\nwith only 1 we'll have an unmanageably large auto generated header\nfile.\n    * Modularity: Using multiple crates makes Git more modular. Elijah\ntold me that there was some desire to make Git more modular.\n    * Cargo Dependencies: Patrick wrote his series with Meson first in\nmind which doesn't address how we'll be able to use crates from\ncrates.io\n  * CI:\n    * Sparse coverage: I think there's only one target that tests his changes.\n    * With vs Without Rust: I don't see anywhere that he covers\nbuilding with vs without Rust in CI\n  * Build integration: Meson has to have every .rs file specified\nwhere as the default layout of a Rust project allows Cargo to just\nknow where to look for .rs files\n"},{"id":"526440","messageId":"aMk2mo5OHPNQi0PW@pks.im","threadId":"64091","inReplyTo":"CAH=ZcbB0Qv=b-hdB2EVW-D-dob4NnzyWDYGEThYZm94S0V7OGg@mail.gmail.com","subject":"Re: [PATCH v5 0/9] Introduce Rust and announce that it will become mandatory","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-16T10:06:18Z","receivedAt":"2025-09-16T10:06:27Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Mon, Sep 15, 2025 at 08:03:29PM -0600, Ezekiel Newren wrote:\n> I am currently working on a patch series that makes Rust optional and\n> addresses several concerns that this series does not:\n>   * Rust calling C: Makefile has no way to build or run Rust so it\n> would have to call cargo test, but that doesn't work unless build.rs\n> tells cargo where libgit.a is (among other things).\n>   * Build tooling alignment: My build_rust.sh is called by make and\n> meson which eliminates defining how to build Rust in 2 places.\n>   * Cargo vs Meson: Meson is adding support for Rust and it's getting\n> better, but Cargo is the canonical build system for Rust. cargo is\n> released in lockstep with rustc, and we _have_ to use cargo when\n> building with make because Meson won't be available in that case.\n>   * Crates: Patrick's series assumes the Git codebase is _the_ crate\n>     * cbindgen: Cbindgen outputs a single header file for each crate,\n> with only 1 we'll have an unmanageably large auto generated header\n> file.\n>     * Modularity: Using multiple crates makes Git more modular. Elijah\n> told me that there was some desire to make Git more modular.\n>     * Cargo Dependencies: Patrick wrote his series with Meson first in\n> mind which doesn't address how we'll be able to use crates from\n> crates.io\n>   * CI:\n>     * Sparse coverage: I think there's only one target that tests his changes.\n>     * With vs Without Rust: I don't see anywhere that he covers\n> building with vs without Rust in CI\n>   * Build integration: Meson has to have every .rs file specified\n> where as the default layout of a Rust project allows Cargo to just\n> know where to look for .rs files\n\nYeah, as I mentioned my patch series here really aims at getting an\nminimum viable user of Rust into the Git codebase so that we can focus\nthe discussion more on the roadmap towards Rust rather than the actual\nRust infrastructure. The whole infra is very simplistic because of that,\nbut that is intentional for now.\n\nOnce we have agreed on the roadmap I very much expect that we will\niterate on it to allow for more complex use cases. My next step would\nhave been to pick patches from your series that make all of this work\non Windows. But of course I don't have to be the (only) one to iterate\non the initial simple infrasturcture, this should ideally be an effort\nby the whole community.\n\nAnd yes, many of the points you mention above are things we'll have to\naddress over time to make Rust a viable alternative to implement\nanything more complex than the trivial \"varint.c\" thing. I think that\niteration is key here: let's start simple and then gradually build out\nthe infrastructure.\n\nPatrick\n"},{"id":"526513","messageId":"1feb8bd5-ef47-4cf4-b306-e38c5edac601@ramsayjones.plus.com","threadId":"64091","inReplyTo":"CAH=ZcbB0Qv=b-hdB2EVW-D-dob4NnzyWDYGEThYZm94S0V7OGg@mail.gmail.com","subject":"Re: [PATCH v5 0/9] Introduce Rust and announce that it will become mandatory","fromName":"Ramsay Jones","fromEmail":"ramsay@ramsayjones.plus.com","sentAt":"2025-09-16T22:25:26Z","receivedAt":"2025-09-16T22:28:43Z","isPatch":true,"sender":{"key":"ramsay@ramsayjones.plus.com","avatar":"https://avatars.githubusercontent.com/u/33702710?v=4"},"body":"\n\nOn 16/09/2025 03:03, Ezekiel Newren wrote:\n> I am currently working on a patch series that makes Rust optional and\n> addresses several concerns that this series does not:\n>   * Rust calling C: Makefile has no way to build or run Rust so it\n> would have to call cargo test, but that doesn't work unless build.rs\n> tells cargo where libgit.a is (among other things).\n>   * Build tooling alignment: My build_rust.sh is called by make and\n\nI meant to mention during the initial 'xdiff series' that running\nthe build_rust.sh script failed for me on Linux Mint 22.2, because:\n\n  $ rustc --version\n  rustc 1.75.0 (82e1608df 2023-12-21) (built from a source tarball)\n  $ cargo --version\n  cargo 1.75.0\n  $ rustup --version\n  Command 'rustup' not found, but can be installed with:\n  sudo apt install rustup\n  $ \n\n[if you try to install rustup, it offers to remove rustc and cargo!]\n\n> meson which eliminates defining how to build Rust in 2 places.\n>   * Cargo vs Meson: Meson is adding support for Rust and it's getting\n> better, but Cargo is the canonical build system for Rust. cargo is\n> released in lockstep with rustc, and we _have_ to use cargo when\n> building with make because Meson won't be available in that case.\n>   * Crates: Patrick's series assumes the Git codebase is _the_ crate\n>     * cbindgen: Cbindgen outputs a single header file for each crate,\n\nAlso:\n\n  $ cbindgen --version\n  Command 'cbindgen' not found, but can be installed with:\n  sudo apt install cbindgen\n  $ \n\n[I haven't tried installing cbindgen, so I don't know if it would uninstall\nrustc and cargo :) ]\n\nATB,\nRamsay Jones\n\n\n"},{"id":"526517","messageId":"CAH=ZcbA47pzMu9VsrTC2Ni9_RN6iPKmaaDNNxSvx1dtroza+Mg@mail.gmail.com","threadId":"64091","inReplyTo":"1feb8bd5-ef47-4cf4-b306-e38c5edac601@ramsayjones.plus.com","subject":"Re: [PATCH v5 0/9] Introduce Rust and announce that it will become mandatory","fromName":"Ezekiel Newren","fromEmail":"ezekielnewren@gmail.com","sentAt":"2025-09-16T23:38:48Z","receivedAt":"2025-09-16T23:39:01Z","isPatch":true,"sender":{"key":"ezekielnewren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/18313324?v=4"},"body":"On Tue, Sep 16, 2025 at 5:05 PM Ramsay Jones\n<ramsay@ramsayjones.plus.com> wrote:\n> I meant to mention during the initial 'xdiff series' that running\n> the build_rust.sh script failed for me on Linux Mint 22.2, because:\n>\n>   $ rustc --version\n>   rustc 1.75.0 (82e1608df 2023-12-21) (built from a source tarball)\n>   $ cargo --version\n>   cargo 1.75.0\n>   $ rustup --version\n>   Command 'rustup' not found, but can be installed with:\n>   sudo apt install rustup\n>   $\n>\n> [if you try to install rustup, it offers to remove rustc and cargo!]\n\nThe parts of my CI code that use rustup should not be interpreted as\nthe right or wrong way to acquire rustc + cargo. So long as the\ndistribution you're using has an appropriate rustc and cargo version\nthen it doesn't matter. The reason why I used rustup in the github\nworkflows is because rustup makes it easy to install different\ntoolchains. rustc and cargo are released in lockstep so it's confusing\nwhen they're not both part of the same package in a distro.\n\n> Also:\n>\n>   $ cbindgen --version\n>   Command 'cbindgen' not found, but can be installed with:\n>   sudo apt install cbindgen\n>   $\n>\n> [I haven't tried installing cbindgen, so I don't know if it would uninstall\n> rustc and cargo :) ]\n\nAgain this is confusing because cbindgen is a crate that can be\ninstalled via 'cargo install cbindgen` and then run as `cbindgen`. I\nthink it would be worthwhile to go over some Rust terminology:\n[rustc]: The rust compiler.\n[cargo]: Canonical build system + package manager. Even rustc uses\ncargo to build itself.\n[rustup]: Rust toolchain manager. This provides rustc and cargo + other stuff.\n[crate]: The unit of compilation. In C it's akin to a single library\nfile or executable. It follows the structure of\nmy_crate\n├── Cargo.toml\n└── src\n    ├── do_that.rs\n    ├── do_this.rs\n    └── lib.rs\nWhere src/lib.rs (the entry point) means it's a library crate and\nmain.rs (the entry point) would mean it's an executable crate (though\nyou can define both in the same crate).\n\nThis means for each crate there will be lib<crate>.a and optionally\ninterop/<crate>.h. So places like xdiff and reftable would be easy to\nfit into the concept of a crate. The rest of Git would take some doing\nto organize into crates.\n"},{"id":"526571","messageId":"87plbpffk1.fsf@gentoo.org","threadId":"64091","inReplyTo":"aMk2mo5OHPNQi0PW@pks.im","subject":"Re: [PATCH v5 0/9] Introduce Rust and announce that it will become mandatory","fromName":"Sam James","fromEmail":"sam@gentoo.org","sentAt":"2025-09-17T12:07:26Z","receivedAt":"2025-09-17T12:07:32Z","isPatch":true,"sender":{"key":"sam@gentoo.org","avatar":"https://avatars.githubusercontent.com/u/11667869?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> On Mon, Sep 15, 2025 at 08:03:29PM -0600, Ezekiel Newren wrote:\n>> I am currently working on a patch series that makes Rust optional and\n>> addresses several concerns that this series does not:\n>>   * Rust calling C: Makefile has no way to build or run Rust so it\n>> would have to call cargo test, but that doesn't work unless build.rs\n>> tells cargo where libgit.a is (among other things).\n>>   * Build tooling alignment: My build_rust.sh is called by make and\n>> meson which eliminates defining how to build Rust in 2 places.\n>>   * Cargo vs Meson: Meson is adding support for Rust and it's getting\n>> better, but Cargo is the canonical build system for Rust. cargo is\n>> released in lockstep with rustc, and we _have_ to use cargo when\n>> building with make because Meson won't be available in that case.\n>>   * Crates: Patrick's series assumes the Git codebase is _the_ crate\n>>     * cbindgen: Cbindgen outputs a single header file for each crate,\n>> with only 1 we'll have an unmanageably large auto generated header\n>> file.\n>>     * Modularity: Using multiple crates makes Git more modular. Elijah\n>> told me that there was some desire to make Git more modular.\n>>     * Cargo Dependencies: Patrick wrote his series with Meson first in\n>> mind which doesn't address how we'll be able to use crates from\n>> crates.io\n>>   * CI:\n>>     * Sparse coverage: I think there's only one target that tests his changes.\n>>     * With vs Without Rust: I don't see anywhere that he covers\n>> building with vs without Rust in CI\n>>   * Build integration: Meson has to have every .rs file specified\n>> where as the default layout of a Rust project allows Cargo to just\n>> know where to look for .rs files\n>\n> Yeah, as I mentioned my patch series here really aims at getting an\n> minimum viable user of Rust into the Git codebase so that we can focus\n> the discussion more on the roadmap towards Rust rather than the actual\n> Rust infrastructure. The whole infra is very simplistic because of that,\n> but that is intentional for now.\n>\n> Once we have agreed on the roadmap I very much expect that we will\n> iterate on it to allow for more complex use cases. My next step would\n> have been to pick patches from your series that make all of this work\n> on Windows. But of course I don't have to be the (only) one to iterate\n> on the initial simple infrasturcture, this should ideally be an effort\n> by the whole community.\n>\n> And yes, many of the points you mention above are things we'll have to\n> address over time to make Rust a viable alternative to implement\n> anything more complex than the trivial \"varint.c\" thing. I think that\n> iteration is key here: let's start simple and then gradually build out\n> the infrastructure.\n\nI think adding external crates especially will need discussion given the\nlicencing and \"offline\" issues (which are solvable but they should be\nexamined).\n\n>\n> Patrick\n"},{"id":"526605","messageId":"CAH=ZcbC51LbvubZuLQvajJqUJHARCjF5_ZBXWDS+DAcBvUMwfA@mail.gmail.com","threadId":"64091","inReplyTo":"87plbpffk1.fsf@gentoo.org","subject":"Re: [PATCH v5 0/9] Introduce Rust and announce that it will become mandatory","fromName":"Ezekiel Newren","fromEmail":"ezekielnewren@gmail.com","sentAt":"2025-09-17T17:30:53Z","receivedAt":"2025-09-17T17:31:07Z","isPatch":true,"sender":{"key":"ezekielnewren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/18313324?v=4"},"body":"On Wed, Sep 17, 2025 at 6:07 AM Sam James <sam@gentoo.org> wrote:\n> I think adding external crates especially will need discussion given the\n> licencing and \"offline\" issues (which are solvable but they should be\n> examined).\n\nI agree. My opinion is that creating a new crate in Git should be its\nown commit. Same with adding a dependency to an existing crate in Git.\nJust because it'll be easy to add depdendencies doesn't mean we should\nadd them willy nilly. But making them easy to add encourages trying\nout tools to see if it's a good idea or not.\n"},{"id":"526611","messageId":"20044de2-3a72-4888-a380-fa35e5a224c4@ramsayjones.plus.com","threadId":"64091","inReplyTo":"CAH=ZcbA47pzMu9VsrTC2Ni9_RN6iPKmaaDNNxSvx1dtroza+Mg@mail.gmail.com","subject":"Re: [PATCH v5 0/9] Introduce Rust and announce that it will become mandatory","fromName":"Ramsay Jones","fromEmail":"ramsay@ramsayjones.plus.com","sentAt":"2025-09-17T18:32:12Z","receivedAt":"2025-09-17T18:35:26Z","isPatch":true,"sender":{"key":"ramsay@ramsayjones.plus.com","avatar":"https://avatars.githubusercontent.com/u/33702710?v=4"},"body":"\n\nOn 17/09/2025 00:38, Ezekiel Newren wrote:\n> On Tue, Sep 16, 2025 at 5:05 PM Ramsay Jones\n> <ramsay@ramsayjones.plus.com> wrote:\n>> I meant to mention during the initial 'xdiff series' that running\n>> the build_rust.sh script failed for me on Linux Mint 22.2, because:\n>>\n>>   $ rustc --version\n>>   rustc 1.75.0 (82e1608df 2023-12-21) (built from a source tarball)\n>>   $ cargo --version\n>>   cargo 1.75.0\n>>   $ rustup --version\n>>   Command 'rustup' not found, but can be installed with:\n>>   sudo apt install rustup\n>>   $\n>>\n>> [if you try to install rustup, it offers to remove rustc and cargo!]\n> \n> The parts of my CI code that use rustup should not be interpreted as\n> the right or wrong way to acquire rustc + cargo. So long as the\n> distribution you're using has an appropriate rustc and cargo version\n> then it doesn't matter. The reason why I used rustup in the github\n> workflows is because rustup makes it easy to install different\n> toolchains. rustc and cargo are released in lockstep so it's confusing\n> when they're not both part of the same package in a distro.\n\nAh, sorry, I was not very clear. The 'build_rust.sh' script unconditionally\nuses the rustup command, assuming that every developer has it installed, but\nnot all devs _will_ have it installed (relying on their distro's packages for\nrustc and cargo).\n\nIf memory serves (and it may not), rustup was only used to determine if the\ncurrent platform was windows (so that it could set the library file extension\nto '*.a' or '*.lib'). It should not be too difficult to find some other means\nto determine that. (famous last words!)\n\n> \n>> Also:\n>>\n>>   $ cbindgen --version\n>>   Command 'cbindgen' not found, but can be installed with:\n>>   sudo apt install cbindgen\n>>   $\n>>\n>> [I haven't tried installing cbindgen, so I don't know if it would uninstall\n>> rustc and cargo :) ]\n> \n> Again this is confusing because cbindgen is a crate that can be\n> installed via 'cargo install cbindgen` and then run as `cbindgen`. I\n> think it would be worthwhile to go over some Rust terminology:\n\nSo, is the (I guess debian) cbindgen package an executable or a crate?\n(can you execute a crate?). BTW the package version is 0.26.0-3.\n\n\nATB,\nRamsay Jones\n\n\n"},{"id":"526638","messageId":"aMsxhp6ZO2Cdz7+k@szeder.dev","threadId":"64091","inReplyTo":"20250915-b4-pks-rust-breaking-change-v5-7-dc3a32fbb216@pks.im","subject":"Re: [PATCH v5 7/9] BreakingChanges: announce Rust becoming mandatory","fromName":"SZEDER Gábor","fromEmail":"szeder.dev@gmail.com","sentAt":"2025-09-17T22:09:10Z","receivedAt":"2025-09-17T22:09:14Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"On Mon, Sep 15, 2025 at 01:22:54PM +0200, Patrick Steinhardt wrote:\n> Over the last couple of years the appetite for bringing Rust into the\n> codebase has grown significantly across the developer base. Introducing\n> Rust is a major change though and has ramifications for the whole\n> ecosystem:\n> \n>   - Some platforms have a Rust toolchain available, but have not yet\n>     integrated it into their build infrastructure.\n> \n>   - Some platforms don't have any support for Rust at all.\n> \n>   - Some platforms may have to figure out how to fit Rust into their\n>     bootstrapping sequence.\n> \n> Due to this, and given that Git is a critical piece of infrastructure\n> for the whole industry, we cannot just introduce such a heavyweight\n> dependency without doing our due diligence.\n> \n> Instead, preceding commits have introduced a test balloon into our build\n> infrastructure that convert one tiny subsystem to use Rust. For now,\n> using Rust to build that subsystem is entirely optional -- if no Rust\n> support is available, we continue to use the C implementation. This test\n> balloon has the intention to give distributions time and let them ease\n> into our adoption of Rust.\n> \n> Having multiple implementations of the same subsystem is not sustainable\n> though, and the plan is to eventually be able to use Rust freely all\n> across our codebase. As such, there is the intent to make Rust become a\n> mandatory part of our build process.\n> \n> Add an announcement to our breaking changes that Rust will become\n> mandatory in Git 3.0. A (very careful and non-binding) estimate might be\n> that this major release might be released in the second half of next\n> year, which should give distributors enough time to prepare for the\n> change.\n> \n> Signed-off-by: Patrick Steinhardt <ps@pks.im>\n> ---\n>  Documentation/BreakingChanges.adoc | 38 ++++++++++++++++++++++++++++++++++++++\n>  1 file changed, 38 insertions(+)\n> \n> diff --git a/Documentation/BreakingChanges.adoc b/Documentation/BreakingChanges.adoc\n> index f8d2eba061..0512411030 100644\n> --- a/Documentation/BreakingChanges.adoc\n> +++ b/Documentation/BreakingChanges.adoc\n> @@ -165,6 +165,44 @@ A prerequisite for this change is that the ecosystem is ready to support the\n>  \"reftable\" format. Most importantly, alternative implementations of Git like\n>  JGit, libgit2 and Gitoxide need to support it.\n>  \n> +* Git will require Rust as a mandatory part of the build process. While Git\n> +  already started to adopt Rust in Git 2.52, all parts written in Rust are\n> +  optional for the time being. This includes:\n> ++\n> +  ** Subsystems that have an alternative implementation in Rust to test\n> +     interoperability between our C and Rust codebase.\n> +  ** Newly written features that are not mission critical for a fully functional\n> +     Git client.\n> ++\n> +These changes are meant as test balloons to allow distributors of Git to prepare\n> +for Rust becoming a mandatory part of the build process. There will be multiple\n> +milestones for the introduction of Rust:\n> ++\n> +--\n> +1. Initially, with Git 2.52, support for Rust will be auto-detected by Meson and\n> +   disabled in our Makefile so that the project can sort out the initial\n> +   infrastructure.\n> +2. In Git 2.53, both build systems will default-enable support for Rust.\n> +   Consequently, builds will break by default if Rust is not available on the\n> +   build host. The use of Rust can still be explicitly disabled via build\n> +   flags.\n> +3. In Git 3.0, the build options will be removed and support for Rust is\n> +   mandatory.\n> +--\n> ++\n> +You can explicitly ask both Meson and our Makefile-based system to enable Rust\n> +by saying `meson configure -Drust=enabled` and `make WITH_RUST=YesPlease`,\n> +respectively.\n> ++\n> +The Git project will declare the last version before Git 3.0 to be a long-term\n> +support release. This long-term release will receive important bug fixes for at\n> +least four release cycles and security fixes for six release cycles. The Git\n> +project will hand over maintainership of the long-term release to distributors\n> +in case they need to extend the life of that long-term release even further. In\n> +that case, the backporting process will be handled by these distributors, but\n> +the backported patches will be reviewed on the mailing list and pulled in by the\n> +Git maintainer.\n\nProviding an LTS release for those platforms that can't jump on the\nRust bandwagon is great, but...\n\nGit 3.0 will switch the default hash algorithm for newly initialized\nrepositories to SHA-256, which, presumably, will also encourage SHA-1\n-> SHA-256 migrations in existing repositories.  Alas, it appears that\nthe SHA-1/SHA-256 interop feature will only be available in Rust.\n\nHow will this affect those platforms without Rust?  What will and\nwon't work on such platforms?\n\nI think it should be called out explicitly in the justification that\nwhatever limitations this imposes on those platforms with respect to\nhash function transition, the project has duly considered that and is\nOK with it.\n\n"},{"id":"526649","messageId":"aMteF4VTq2C5sAhK@fruit.crustytoothpaste.net","threadId":"64091","inReplyTo":"aMsxhp6ZO2Cdz7+k@szeder.dev","subject":"Re: [PATCH v5 7/9] BreakingChanges: announce Rust becoming mandatory","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2025-09-18T01:19:19Z","receivedAt":"2025-09-18T01:19:28Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On 2025-09-17 at 22:09:10, SZEDER Gábor wrote:\n> Providing an LTS release for those platforms that can't jump on the\n> Rust bandwagon is great, but...\n> \n> Git 3.0 will switch the default hash algorithm for newly initialized\n> repositories to SHA-256, which, presumably, will also encourage SHA-1\n> -> SHA-256 migrations in existing repositories.  Alas, it appears that\n> the SHA-1/SHA-256 interop feature will only be available in Rust.\n> \n> How will this affect those platforms without Rust?  What will and\n> won't work on such platforms?\n\nOn Git 3.0, nothing will work without Rust because it will be mandatory.\nHowever, people who want to perform the conversion can do that by\nbooting a Linux VM[0] and converting the repository there, then pushing\nit somewhere.  The only inconvenience is that you'll have to have a flag\nday for working with the repository on older Git: you won't be able to\ndynamically pull from or push to a repository with a different main\nalgorithm than you.\n\nOne of my first patches is that setting extensions.compatObjectFormat\nwithout Rust will simply die and say that's not supported.  If that\nconfig value is unset, then Git up to 3.0 will simply function as\nnormal, so full single-hash compatibility is assured.  We already have\nthat: SHA-256 repositories work just fine with SHA-256 remotes and SHA-1\nrepositories work just fine with SHA-1 remotes, but they're currently\nnot interoperable.\n\n> I think it should be called out explicitly in the justification that\n> whatever limitations this imposes on those platforms with respect to\n> hash function transition, the project has duly considered that and is\n> OK with it.\n\nI am fine with this and I don't think this is a problem.\n\nI will mention that I have also already written the code in Rust and it\nis elegant and tidy and more efficient, better tested, and shorter than\nthe equivalent C code.  Writing the code also took much less time than\nthe equivalent C code would have.  I am not planning to rewrite it in C,\nsince I already have a substantial amount of other interoperability work\nto do, so unless someone else is planning on doing so, the project has\ntwo choices: use the Rust code and accept that, or decide that they\ndon't want the interoperability work for Git 3.0.\n\nI want to point out that so far, all of the SHA-256 work, including the\ninteroperability work, has been on my own time.  I understand that my\ncontributions to the project have to be acceptable to the project, but I\nalso am not willing to rewrite a bunch of work because we already\ndecided that we were going to do something and then changed our mind.\nIf the project wants to be fickle on this matter, then other\ncontributors can do the interoperability work on those terms.\n\nI realize the decision to incorporate Rust was made recently, but the\nbinary loose object maps are a blocker for some of the protocol work I'm\ndoing, and if we want the interoperability functionality in Git 3.0 in a\nyear, then I can't afford to wait here, since this kind of discussion\ntends to drag on extensively.\n\n[0] Debian actually offers multiarch support, so as long as Debian has\nsupport for the architecture you're running on, you can boot a Debian VM\nof your native architecture, install amd64 or arm64 packages and QEMU,\nand then run those binaries in emulation.  It will be slow, but it works\nfor virtually all architectures.  I've done something similar with\nrisc64 containers on my amd64 laptop.\n-- \nbrian m. carlson (they/them)\nToronto, Ontario, CA\n"},{"id":"526653","messageId":"CABPp-BEiK49f_UB5UPe3qM9O7vQGGFJ8Nshw1f6W_6Lw7HRL6Q@mail.gmail.com","threadId":"64091","inReplyTo":"20250915-b4-pks-rust-breaking-change-v5-0-dc3a32fbb216@pks.im","subject":"Re: [PATCH v5 0/9] Introduce Rust and announce that it will become mandatory","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2025-09-18T03:47:58Z","receivedAt":"2025-09-18T03:48:10Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"Hi Patrick,\n\nOn Mon, Sep 15, 2025 at 4:23 AM Patrick Steinhardt <ps@pks.im> wrote:\n>\n> Hi,\n>\n> this small patch series introduces Rust into the core of Git. This patch\n> series is designed as a test balloon, similar to how we introduced test\n> balloons for C99 features in the past. The goal is threefold:\n>\n>   - Give us some time to experiment with Rust and introduce proper build\n>     infrastructure.\n>\n>   - Give distributors time to ease into the new toolchain requirements.\n>     Introducing Rust is impossible for some platforms and hard for\n>     others.\n>\n>   - Announce that Git 3.0 will make Rust a mandatory part of our build\n>     infrastructure.\n>\n> The test balloon itself is quite uninteresting: I've chosen to convert\n> the \"varint.c\" subsystem, mostly because it is trivial and does not have\n> any dependencies. But it does allow us to verify that C to Rust interop\n> works as expected, and to play around with tooling. All tests pass with\n> the \"varint.rs\" implementation.\n>\n> For now, the series only contains support for Meson. If we agree to go\n> down this route I'll also introduce support for Rust into our Makefiles\n> at a later point in time.\n>\n> Furthermore missing is additional tooling:\n>\n>   - At least one CI job to verify that Rust builds and works as\n>     expected.\n>\n>   - Tooling and CI jobs to ensure that we have consistent formatting via\n>     `cargo format`.\n>\n> And probably lots more. As said, the entire goal is for us to have an\n> easy playground that we can experiment on and develop the infrastructure\n> incrementally without yet having to commit to anything.\n>\n> I'm mostly splitting out the topic of introducing Rust from the larger\n> series that introduce it into xdiff so that we can focus more on the\n> actual process of introducing Rust into Git and less on the potential\n> features that we want to build on top of it.\n>\n> Changes in v2:\n>   - Introduce support for building the Rust library via our Makefile.\n>   - Introduce a '-DWITH_RUST' define. This define is used to print\n>     whether or not Git is built with Rust via `git version\n>     --build-options`.\n>   - Adjust Meson to not depend on v1.9.0 and newer anymore.\n>   - Introduce a roadmap into our BreakingChanges document to explain how\n>     we'll iterate towards mandatory Rust support.\n>   - Rework the Fedora job to do a full compile-and-test run with Meson\n>     and breaking changes enabled.\n>   - Adapt our breaking-changes jobs to enable Rust support.\n>   - Link to v1: https://lore.kernel.org/r/20250904-b4-pks-rust-breaking-change-v1-0-3af1d25e0be9@pks.im\n>\n> Changes in v3:\n>   - Reorder all uses of `WITH_RUST` after the include of \"config.mak\".\n>   - Add a test to verify overflow behaviour in Rust and explicitly use\n>     `add_wrapping()`.\n>   - Use explicit dependencies for the Rust library in our Makefile.\n>   - Fix Alma Linux CI job.\n>   - Stop tying maintenance of our LTS release to the availability of\n>     gcc-rs.\n>   - Add a fallback to Meson to use cargo directly.\n>   - I've fixed the Rust edition to 2018 for now. This is intentionally\n>     conservative so that we might be able to use Rust 1.49. For now, we\n>     don't have any reason to use a newer edition, either. So let's take\n>     the oldest version we can live with for now and then bump it as\n>     required.\n>   - Link to v2: https://lore.kernel.org/r/20250905-b4-pks-rust-breaking-change-v2-0-6939cbf4a0b8@pks.im\n>\n> Changes in v4:\n>   - Convert \"varint.c\" to use explicit integer width so that we don't\n>     need to use C types in Rust.\n>   - Adapt Meson to unconditionally use Cargo.\n>   - Don't use the unstable `--out-dir` option in Cargo. Instead, we\n>     resort to a wrapper script in Meson.\n>   - Shorten the timeline a bit to drop the extra step that ties Rust\n>     support to `-Dbreaking_changes=true`. This accelerates the timeline\n>     until distros are made forcibly aware of the upcoming changes in\n>     Rust.\n>   - Link to v3: https://lore.kernel.org/r/20250908-b4-pks-rust-breaking-change-v3-0-1cd7189fed3b@pks.im\n>\n> Changes in v5:\n>   - Fix indentation in the BreakingChanges document.\n>   - Fix a commit message typo.\n>   - Include \"Cargo.lock\" in the `make clean` target again.\n>   - Link to v4: https://lore.kernel.org/r/20250910-b4-pks-rust-breaking-change-v4-0-4a63fc69278d@pks.im\n\nPatch 7 still has the same error as v2; could we get the wording\ncorrected?  I suggested an alternative already[*]:\n\n\"...While Git already started to adopt Rust in Git 2.52, all parts...\"\n\n=>\n\n\"...While Git already started to adopt Rust into the core in Git 2.52\n(and as an optional \"contrib\" component back in Git 2.49), all\nparts...\"\n\n\nAlso, as discussed over at\nhttps://lore.kernel.org/git/xmqqy0qcae6z.fsf@gitster.g/, would you be\nwilling to re-roll a single-patch v6 (with just your updated patch 7),\nand let Junio merge that?  That would get the important timeline that\nyou wanted landed, and then Ezekiel could pull your varint and help\nchanges together with brian's Documentation change and Johannes'\ngit-for-windows change to create a test balloon and introduce Rust and\nhave it build on all CI'd platforms.\n\nThanks,\nElijah\n"},{"id":"526770","messageId":"72d0a316-ee3d-45a0-8122-77c52911614b@gmail.com","threadId":"64091","inReplyTo":"20250915-b4-pks-rust-breaking-change-v5-7-dc3a32fbb216@pks.im","subject":"Re: [PATCH v5 7/9] BreakingChanges: announce Rust becoming mandatory","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2025-09-19T13:59:58Z","receivedAt":"2025-09-19T14:00:05Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Patrick\n\nOn 15/09/2025 12:22, Patrick Steinhardt wrote:\n> Over the last couple of years the appetite for bringing Rust into the\n> codebase has grown significantly across the developer base. Introducing\n> Rust is a major change though and has ramifications for the whole\n> ecosystem:\n> \n>    - Some platforms have a Rust toolchain available, but have not yet\n>      integrated it into their build infrastructure.\n> \n>    - Some platforms don't have any support for Rust at all.\n> \n>    - Some platforms may have to figure out how to fit Rust into their\n>      bootstrapping sequence.\n> \n> Due to this, and given that Git is a critical piece of infrastructure\n> for the whole industry, we cannot just introduce such a heavyweight\n> dependency without doing our due diligence.\n\nI'm not sure what you mean by \"doing our due diligence\" here. We already \nknow that requiring a rust compiler will make it impossible to build git \non some currently supported platforms. Isn't the purpose of this patch \nto give them notice so they have some time to come up with a plan for \neither (a) accelerating rust support on their platform, or (b) for how \nmaintain the LTS branch after the we stop supporting it?\n\n> +1. Initially, with Git 2.52, support for Rust will be auto-detected by Meson and\n> +   disabled in our Makefile so that the project can sort out the initial\n> +   infrastructure.\n> +2. In Git 2.53, both build systems will default-enable support for Rust.\n> +   Consequently, builds will break by default if Rust is not available on the\n> +   build host. The use of Rust can still be explicitly disabled via build\n> +   flags.\n> +3. In Git 3.0, the build options will be removed and support for Rust is\n> +   mandatory.\n> +--\n> ++\n> +You can explicitly ask both Meson and our Makefile-based system to enable Rust\n> +by saying `meson configure -Drust=enabled` and `make WITH_RUST=YesPlease`,\n> +respectively.\n\nThis is helpful but ideally before Git 2.53 we'd make the Makefile and \nmeson print that information if they fail due to a missing rust compiler.\n\n> ++\n> +The Git project will declare the last version before Git 3.0 to be a long-term\n> +support release. This long-term release will receive important bug fixes for at\n> +least four release cycles and security fixes for six release cycles. The Git\n> +project will hand over maintainership of the long-term release to distributors\n> +in case they need to extend the life of that long-term release even further. In\n> +that case, the backporting process will be handled by these distributors, but\n> +the backported patches will be reviewed on the mailing list and pulled in by the\n> +Git maintainer.\n\nDidn't Junio have some qualms about the last part of this paragraph? I \nthought he suggested that once we hand over maintaining the LTS release \nthe people responsible for it could use the security list to coordinate \ntheir work and would be responsible for pushing fixes the the LTS branch \nthemselves.\n\nThanks for working on this, it will be good to have a formal plan in our \nDocumentation that we can refer to.\n\nPhillip\n\n>   === Removals\n>   \n>   * Support for grafting commits has long been superseded by git-replace(1).\n> \n\n"},{"id":"526796","messageId":"6674eb07df107d786b747ccd6dce4555d36d5d2c.camel@physik.fu-berlin.de","threadId":"64091","inReplyTo":"20250904-b4-pks-rust-breaking-change-v1-0-3af1d25e0be9@pks.im","subject":"Re: [PATCH RFC 0/3] Introduce Rust and announce that it will become mandatorty","fromName":"John Paul Adrian Glaubitz","fromEmail":"glaubitz@physik.fu-berlin.de","sentAt":"2025-09-19T18:41:45Z","receivedAt":"2025-09-19T18:41:51Z","isPatch":true,"sender":{"key":"glaubitz@physik.fu-berlin.de","avatar":"https://avatars.githubusercontent.com/u/1647645?v=4"},"body":"Hello Patrick,\n\nOn Thu, 2025-09-04 at 16:26 +0200, Patrick Steinhardt wrote:\n> this small patch series introduces Rust into the core of Git. This patch\n> series is designed as a test balloon, similar to how we introduced test\n> balloons for C99 features in the past. The goal is threefold:\n> \n>   - Give us some time to experiment with Rust and introduce proper build\n>     infrastructure.\n> \n>   - Give distributors time to ease into the new toolchain requirements.\n>     Introducing Rust is impossible for some platforms and hard for\n>     others.\n> \n>   - Announce that Git 3.0 will make Rust a mandatory part of our build\n>     infrastructure.\n\nI'm one of Debian's maintainers in Debian Ports and I maintain Debian unstable\non older and more obscure architectures such as alpha, hppa, m68k, sh4 and sparc64.\n\nOf all the architectures in Debian, there are currently four architectures that\ndon't support rustc. Those are alpha, hppa, m68k and sh4 [1]. For m68k, the\nsituation is special as both LLVM and rustc already support m68k but with Linux\nstill defaulting to 16-bit alignment on this architecture [2], building LLVM and\nrustc is currently not possible. I'm working on a switch to 32-bit alignment\nthough which is default for NetBSD/m68k and also what specified in the official\nSysV ELF ABI documentation.\n\nIn general, I'm not against introducing Rust support into existing projects. However,\nI wished projects would be a little more patient until either the GCC codegen in\nrustc called rustc_codegen_gcc [3] or the Rust frontend in GCC have become ready\nfor prime time.\n\nMy hope would be that more talented Rust developers would help support the two\nGCC Rust projects so that these become ready for prime time sooner and that one\nof the last blockers for introducing the Rust language across a lot of open source\nprojects would go away.\n\nI'm not an expert with the Non-Stop operating system, but I could imagine that\na working Rust frontend in GCC would ease porting the Rust language to that\nplatform as well.\n\nCheers,\nAdrian\n\n> [1] https://buildd.debian.org/status/package.php?p=rustc&suite=sid\n> [2] https://wiki.debian.org/M68k/Alignment\n> [3] https://rust-for-linux.com/rustc_codegen_gcc\n> [4] https://rust-for-linux.com/gccrs\n\n-- \n .''`.  John Paul Adrian Glaubitz\n: :' :  Debian Developer\n`. `'   Physicist\n  `-    GPG: 62FF 8A75 84E0 2956 9546  0006 7426 3B37 F5B5 F913\n"},{"id":"526924","messageId":"aNFIjWKX2Wa6GEkA@pks.im","threadId":"64091","inReplyTo":"6674eb07df107d786b747ccd6dce4555d36d5d2c.camel@physik.fu-berlin.de","subject":"Re: [PATCH RFC 0/3] Introduce Rust and announce that it will become mandatorty","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-22T13:01:01Z","receivedAt":"2025-09-22T13:01:17Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Fri, Sep 19, 2025 at 08:41:45PM +0200, John Paul Adrian Glaubitz wrote:\n> On Thu, 2025-09-04 at 16:26 +0200, Patrick Steinhardt wrote:\n> > this small patch series introduces Rust into the core of Git. This patch\n> > series is designed as a test balloon, similar to how we introduced test\n> > balloons for C99 features in the past. The goal is threefold:\n> > \n> >   - Give us some time to experiment with Rust and introduce proper build\n> >     infrastructure.\n> > \n> >   - Give distributors time to ease into the new toolchain requirements.\n> >     Introducing Rust is impossible for some platforms and hard for\n> >     others.\n> > \n> >   - Announce that Git 3.0 will make Rust a mandatory part of our build\n> >     infrastructure.\n> \n> I'm one of Debian's maintainers in Debian Ports and I maintain Debian unstable\n> on older and more obscure architectures such as alpha, hppa, m68k, sh4 and sparc64.\n> \n> Of all the architectures in Debian, there are currently four architectures that\n> don't support rustc. Those are alpha, hppa, m68k and sh4 [1]. For m68k, the\n> situation is special as both LLVM and rustc already support m68k but with Linux\n> still defaulting to 16-bit alignment on this architecture [2], building LLVM and\n> rustc is currently not possible. I'm working on a switch to 32-bit alignment\n> though which is default for NetBSD/m68k and also what specified in the official\n> SysV ELF ABI documentation.\n> \n> In general, I'm not against introducing Rust support into existing projects. However,\n> I wished projects would be a little more patient until either the GCC codegen in\n> rustc called rustc_codegen_gcc [3] or the Rust frontend in GCC have become ready\n> for prime time.\n\nThanks for raising these concerns, I really appreciate that! Making\nplatform maintainers aware of this upcoming change was one of the goals\nof announcing the breaking change in the first place, so I'm happy to\nsee that this discussion is happening now :) After all, we are aware\nthat the proposed change can create hardships for downstream\ndistributions and maintainers.\n\nThe timeline I have layed out right now is trying to cater towards\ngccrs, at least to a certain extent. As Pierre-Emmanuel mentioned in\n[1], gccrs _may_ start to become ready next year with a target version\nof Rust 1.49. Given proposed timelines, Git 3.0 with mandatory Rust\nwould be released at the end of next year, which would hopefully be\nafter gccrs slowly becoming a viable alternative to compile Rust.\n\nThis is also the reason why I've picked Rust 2018 as the edition, as\nRust 1.49 doesn't know about any later editions.\n\nOf course, given that the work on gccrs is driven by volunteers to the\nbest of my understanding I don't want to \"force\" them to get this done\nby that point, and Pierre-Emmanual also made clear that the initial\nrelease is still likely to have many bugs. So it may be the case that\ngccrs or any other codegen is not ready yet at that point in time. If\nso, we might have to reopen the discussion of whether or not we really\nwant to switch over to mandatory Rust with Git 3.0.\n\nUltimately, I guess that this will also depend on how much of a pain it\nis for us to keep Rust non-mandatory. We don't have a lot of experience\nwith Rust in our codebase yet, but if we eventually see that it's a\nbreeze to keep it optional I think we should consider deferring the date\nwhere it's becoming mandatory.\n\nAll to say: I don't think we should blindly pull the trigger with Git\n3.0. I think we should take a more nuanced approach and consider:\n\n  - Any of the learnings we had with the initial Rust infra and how hard\n    it is to keep it optional.\n\n  - The status quo of the ecosystem and whether we can expect either\n    gccrs or rustc_codegen_gcc to become stable.\n\nThat being said, I think we should keep the current intent spelt out in\nour breaking changes document so that we can get more feedback from\ndownstream maintainers that aren't currently aware of the porposed\nupcoming change.\n\nThanks!\n\nPatrick\n\n[1]: <7bf054a1-0196-4ad8-aaa4-a432cd2c93a5@embecosm.com>\n"},{"id":"526925","messageId":"aNFImn9toejLzIJR@pks.im","threadId":"64091","inReplyTo":"72d0a316-ee3d-45a0-8122-77c52911614b@gmail.com","subject":"Re: [PATCH v5 7/9] BreakingChanges: announce Rust becoming mandatory","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-22T13:01:14Z","receivedAt":"2025-09-22T13:01:22Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Fri, Sep 19, 2025 at 02:59:58PM +0100, Phillip Wood wrote:\n> On 15/09/2025 12:22, Patrick Steinhardt wrote:\n> > Over the last couple of years the appetite for bringing Rust into the\n> > codebase has grown significantly across the developer base. Introducing\n> > Rust is a major change though and has ramifications for the whole\n> > ecosystem:\n> > \n> >    - Some platforms have a Rust toolchain available, but have not yet\n> >      integrated it into their build infrastructure.\n> > \n> >    - Some platforms don't have any support for Rust at all.\n> > \n> >    - Some platforms may have to figure out how to fit Rust into their\n> >      bootstrapping sequence.\n> > \n> > Due to this, and given that Git is a critical piece of infrastructure\n> > for the whole industry, we cannot just introduce such a heavyweight\n> > dependency without doing our due diligence.\n> \n> I'm not sure what you mean by \"doing our due diligence\" here. We already\n> know that requiring a rust compiler will make it impossible to build git on\n> some currently supported platforms. Isn't the purpose of this patch to give\n> them notice so they have some time to come up with a plan for either (a)\n> accelerating rust support on their platform, or (b) for how maintain the LTS\n> branch after the we stop supporting it?\n\nYeah, I consider having an announcement of our intent out there as being\nthat \"due diligence\". The scope of breakage may be much bigger than we\ncurrently anticipate, and if we eventually see that a significant\nportion of the ecosystem would break I think we should take a step back\nand reevaluate.\n\n> > +1. Initially, with Git 2.52, support for Rust will be auto-detected by Meson and\n> > +   disabled in our Makefile so that the project can sort out the initial\n> > +   infrastructure.\n> > +2. In Git 2.53, both build systems will default-enable support for Rust.\n> > +   Consequently, builds will break by default if Rust is not available on the\n> > +   build host. The use of Rust can still be explicitly disabled via build\n> > +   flags.\n> > +3. In Git 3.0, the build options will be removed and support for Rust is\n> > +   mandatory.\n> > +--\n> > ++\n> > +You can explicitly ask both Meson and our Makefile-based system to enable Rust\n> > +by saying `meson configure -Drust=enabled` and `make WITH_RUST=YesPlease`,\n> > +respectively.\n> \n> This is helpful but ideally before Git 2.53 we'd make the Makefile and meson\n> print that information if they fail due to a missing rust compiler.\n\nThe intent here is to allow us a bit of time to iterate on the build\ninfra before making either of the build systems error out. Ezekiel has a\nbunch of follow-ups that we'll want to land to also unblock support on\nWindows and to implement things we don't yet have, like Rust-accessible\nC bindings.\n\nIs there any particular reason why you want to accelerate this timeline\nand make the build systems error out right from the start?\n\n> > +The Git project will declare the last version before Git 3.0 to be a long-term\n> > +support release. This long-term release will receive important bug fixes for at\n> > +least four release cycles and security fixes for six release cycles. The Git\n> > +project will hand over maintainership of the long-term release to distributors\n> > +in case they need to extend the life of that long-term release even further. In\n> > +that case, the backporting process will be handled by these distributors, but\n> > +the backported patches will be reviewed on the mailing list and pulled in by the\n> > +Git maintainer.\n> \n> Didn't Junio have some qualms about the last part of this paragraph? I\n> thought he suggested that once we hand over maintaining the LTS release the\n> people responsible for it could use the security list to coordinate their\n> work and would be responsible for pushing fixes the the LTS branch\n> themselves.\n> \n> Thanks for working on this, it will be good to have a formal plan in our\n> Documentation that we can refer to.\n\nYeah, I addressed that feedback in [1]. Junio didn't reply to that part\nyet, and I didn't have any idea for how to improve that part. I'm happy\nto do so though if this still feels problematic to anyone.\n\nPatrick\n\n[1]: <aMfwGHL7dh8dk2cQ@pks.im>\n"},{"id":"526937","messageId":"f23fb338-3039-4c86-a36e-439d68d14acc@gmail.com","threadId":"64091","inReplyTo":"aNFImn9toejLzIJR@pks.im","subject":"Re: [PATCH v5 7/9] BreakingChanges: announce Rust becoming mandatory","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2025-09-22T14:07:40Z","receivedAt":"2025-09-22T14:07:43Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Patrick\n\nOn 22/09/2025 14:01, Patrick Steinhardt wrote:\n> On Fri, Sep 19, 2025 at 02:59:58PM +0100, Phillip Wood wrote:\n>> On 15/09/2025 12:22, Patrick Steinhardt wrote:\n>>> \n>>> +You can explicitly ask both Meson and our Makefile-based system to enable Rust\n>>> +by saying `meson configure -Drust=enabled` and `make WITH_RUST=YesPlease`,\n>>> +respectively.\n>>\n>> This is helpful but ideally before Git 2.53 we'd make the Makefile and meson\n>> print that information if they fail due to a missing rust compiler.\n> \n> The intent here is to allow us a bit of time to iterate on the build\n> infra before making either of the build systems error out. Ezekiel has a\n> bunch of follow-ups that we'll want to land to also unblock support on\n> Windows and to implement things we don't yet have, like Rust-accessible\n> C bindings.\n> \n> Is there any particular reason why you want to accelerate this timeline\n> and make the build systems error out right from the start?\n\nI'm not suggesting that. I'm saying when rust is enabled by default in \nGit 2.53, if the Makefile cannot find a rust compiler it should print a \nmessage that says how to build git without rust so that users do not \nhave to wade through this document or our release notes to find out how \nto do that.\n\nThanks\n\nPhillip\n\n"},{"id":"526939","messageId":"aNFfbGWbOl5ziCJV@pks.im","threadId":"64091","inReplyTo":"f23fb338-3039-4c86-a36e-439d68d14acc@gmail.com","subject":"Re: [PATCH v5 7/9] BreakingChanges: announce Rust becoming mandatory","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-22T14:38:36Z","receivedAt":"2025-09-22T14:38:46Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Mon, Sep 22, 2025 at 03:07:40PM +0100, Phillip Wood wrote:\n> Hi Patrick\n> \n> On 22/09/2025 14:01, Patrick Steinhardt wrote:\n> > On Fri, Sep 19, 2025 at 02:59:58PM +0100, Phillip Wood wrote:\n> > > On 15/09/2025 12:22, Patrick Steinhardt wrote:\n> > > > \n> > > > +You can explicitly ask both Meson and our Makefile-based system to enable Rust\n> > > > +by saying `meson configure -Drust=enabled` and `make WITH_RUST=YesPlease`,\n> > > > +respectively.\n> > > \n> > > This is helpful but ideally before Git 2.53 we'd make the Makefile and meson\n> > > print that information if they fail due to a missing rust compiler.\n> > \n> > The intent here is to allow us a bit of time to iterate on the build\n> > infra before making either of the build systems error out. Ezekiel has a\n> > bunch of follow-ups that we'll want to land to also unblock support on\n> > Windows and to implement things we don't yet have, like Rust-accessible\n> > C bindings.\n> > \n> > Is there any particular reason why you want to accelerate this timeline\n> > and make the build systems error out right from the start?\n> \n> I'm not suggesting that. I'm saying when rust is enabled by default in Git\n> 2.53, if the Makefile cannot find a rust compiler it should print a message\n> that says how to build git without rust so that users do not have to wade\n> through this document or our release notes to find out how to do that.\n\nAh, sorry, I misread what you were saying. This would be a useful thing\nto do indeed.\n\nPatrick\n"},{"id":"526949","messageId":"xmqqsegev4jp.fsf@gitster.g","threadId":"64091","inReplyTo":"aMfwGHL7dh8dk2cQ@pks.im","subject":"Re: [PATCH RFC v4 7/9] BreakingChanges: announce Rust becoming mandatory","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-09-22T16:24:26Z","receivedAt":"2025-09-22T16:24:29Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n>> I am having a hard time imagining the practicality of this \"hand\n>> over but we still review\" arrangement.  Some of the security fixes\n>> are embargoed, and the reason why we are jetissoning the stale\n>> codebase is presumably because nobody is willing to work on it other\n>> than the \"community support\" folks.  I can imagine that we would\n>> qualify them into the git-security cabal and let them use the forum\n>> to coordinate among themselves, but then to what degree in the\n>> \"community support themselves\" process is our involvement expected?\n>> As long as we can make sure that they do not leak before the\n>> official embargoed release, they do not need an official stamp of\n>> approval from the project or by the Git maintainer---that is what it\n>> means to \"hand over maintainer ship\", at least to me.\n>> \n>> In other words, I like what I see in this paragraph, but I do not\n>> think we can practically live with the part of the sentence after\n>> the last \", but\".\n>\n> I think the most important part here is that this community-supported\n> LTS release should still live in the canonical repositories. We should\n> avoid the situation where we hand over maintainership to such a degree\n> that the end result (the tagged LTS release) lives somewhere else.\n\nWhy is it a bad thing?  The official repository can have a README.md\nwith a single entry \"maintenance releases for Git 2.98 LTS (most\nnotably with no Rust requirements) are found at this separate site\".\n\n> Otherwise we risk chaos and a plethora of different LTS releases, which\n> would be harmful both for us and those that rely on the LTS releases.\n\nNo risk for that as long as we have a single \"go there\" pointer, right?\n\n> And yes, that probably means that a trusted LTS maintainer should be on\n> git-security@ so that they are aware of upcoming security releases.\n\nAbsolutely.\n\nAnd there should be a community of those who are working on helping\nthe backporting effort around that LTS maintainer that ensures there\nis no \"chaos and a plethora of different LTS releases\".\n\nWe might occasionally update what is listed in \"git ls-remote --tags\"\nfrom our repository by syncing with them only for convenience, but\nthe important point is that the community supported LTS should have\nits own official site, which is different from the cutting/bleeding\nedge.  Most importantly, a coordinated disclosure would say that the\nupdate to versions of\n\n - Git 3.0 to Git 3.4 are found $HERE, \n - Git for Windows 3.0, 3.2, and 3.4 are found $THERE\n - Git 2.98 are found $COMMUNITY_LTS\n\nto make sure that people know where to find their updates.\n\nSo, no, I do not think we should unnecessarily mix community LTS and\nthe main project.\n\n\n\n"},{"id":"526965","messageId":"aNGkt/DdnbjNu3s8@szeder.dev","threadId":"64091","inReplyTo":"aMteF4VTq2C5sAhK@fruit.crustytoothpaste.net","subject":"Re: [PATCH v5 7/9] BreakingChanges: announce Rust becoming mandatory","fromName":"SZEDER Gábor","fromEmail":"szeder.dev@gmail.com","sentAt":"2025-09-22T19:34:15Z","receivedAt":"2025-09-22T19:34:18Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"On Thu, Sep 18, 2025 at 01:19:19AM +0000, brian m. carlson wrote:\n> On 2025-09-17 at 22:09:10, SZEDER Gábor wrote:\n> > Providing an LTS release for those platforms that can't jump on the\n> > Rust bandwagon is great, but...\n> > \n> > Git 3.0 will switch the default hash algorithm for newly initialized\n> > repositories to SHA-256, which, presumably, will also encourage SHA-1\n> > -> SHA-256 migrations in existing repositories.  Alas, it appears that\n> > the SHA-1/SHA-256 interop feature will only be available in Rust.\n> > \n> > How will this affect those platforms without Rust?  What will and\n> > won't work on such platforms?\n> \n> On Git 3.0, nothing will work without Rust because it will be mandatory.\n\nWell, \"What will and won't work with respect to hash transition\" was\nwhat I meant but, alas, didn't convey.\n\n> However, people who want to perform the conversion can do that by\n> booting a Linux VM[0] and converting the repository there, then pushing\n> it somewhere.  The only inconvenience is that you'll have to have a flag\n> day for working with the repository on older Git: you won't be able to\n> dynamically pull from or push to a repository with a different main\n> algorithm than you.\n> \n> One of my first patches is that setting extensions.compatObjectFormat\n> without Rust will simply die and say that's not supported.  If that\n> config value is unset, then Git up to 3.0 will simply function as\n> normal, so full single-hash compatibility is assured.  We already have\n> that: SHA-256 repositories work just fine with SHA-256 remotes and SHA-1\n> repositories work just fine with SHA-1 remotes, but they're currently\n> not interoperable.\n\nThanks for the explanation.  I think this would indeed be a worthwhile\naddition to the commit message, or perhaps even to the BreakingChanges\ndocument.\n\n> > I think it should be called out explicitly in the justification that\n> > whatever limitations this imposes on those platforms with respect to\n> > hash function transition, the project has duly considered that and is\n> > OK with it.\n> \n> I am fine with this and I don't think this is a problem.\n\nNot sure I can agree with that, though.\n\n\n> I realize the decision to incorporate Rust was made recently,\n\nIndeed it was.\n\n"},{"id":"526984","messageId":"xmqq348etd9n.fsf@gitster.g","threadId":"64091","inReplyTo":"aNGkt/DdnbjNu3s8@szeder.dev","subject":"Re: [PATCH v5 7/9] BreakingChanges: announce Rust becoming mandatory","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-09-22T20:59:00Z","receivedAt":"2025-09-22T20:59:04Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"SZEDER Gábor <szeder.dev@gmail.com> writes:\n\n> On Thu, Sep 18, 2025 at 01:19:19AM +0000, brian m. carlson wrote:\n>> On 2025-09-17 at 22:09:10, SZEDER Gábor wrote:\n>> > Providing an LTS release for those platforms that can't jump on the\n>> > Rust bandwagon is great, but...\n>> > \n>> > Git 3.0 will switch the default hash algorithm for newly initialized\n>> > repositories to SHA-256, which, presumably, will also encourage SHA-1\n>> > -> SHA-256 migrations in existing repositories.  Alas, it appears that\n>> > the SHA-1/SHA-256 interop feature will only be available in Rust.\n>> > \n>> > How will this affect those platforms without Rust?  What will and\n>> > won't work on such platforms?\n>> \n>> On Git 3.0, nothing will work without Rust because it will be mandatory.\n>\n> Well, \"What will and won't work with respect to hash transition\" was\n> what I meant but, alas, didn't convey.\n\nBut \"here is a topic to consolidate everything we talked about\nstarting to use Rust\" Ezekiel works on incorporates the \"dip our\ntoes in water rewrite of varint.c into Rust\" Patrick started and\n\"Rust will become mandatory\" policy document written by brian [*].\nAt 3.0, the WITH_BREAKING_CHANGES conditional compilation option is\nremoved and the conditional code paths protected by that macro\nbecomes unconditional.  When that happens, you won't have a git\nbinary from the source for that version of Git at all, unless you\ncan turn varint.rs into varint.o (which typically is done by\ncompiling the source with Rust toolchain).\n\nSo I would think \"nothing will work\" is a very fair assessment of\nthe consequence of that policy.  And the answer would be the same\nfor \"with respect to hash transition\" question, I would think.\n\nThe version of the document in this thread talks about 2.52 (opt-in)\nand 2.53 (opt-out) before jumping to 3.0 (no way to opt-out) but it\ndoes not say anything about how far out that big version bump is.\nBut the numbers I remember hearing was in the orders of 18 monts or\nso if I am not mistaken?\n\nAs I already said a few times (e.g. <xmqq8qipzhg3.fsf@gitster.g>), I\nfeel that the timeline hinted by any of these documents that were\nproposed is way too aggressive for affected people to practically\nprepare for.\n\nBy the way, I was hoping that the hash compatibility work can be\ndone as an opt-in item available only for those with Rust, while\nRustless folks are forever stuck in a single hash algorithm world,\nand be released well before Git 3.0 that makes Rust mandatory.  That\ndoes not change the fact that nothing will work wrt hash transition\nfor Rustless folks, though ;-).\n\n\n[Footnote]\n\n* By the way, I _think_ I never saw that policy document until\n  Ezekiel started his topic and sent it out as one of the component\n  patches; how did it get there from brian to Ezekiel's topic?\n"},{"id":"527000","messageId":"aNHKdFkiGLPcLEjP@fruit.crustytoothpaste.net","threadId":"64091","inReplyTo":"xmqq348etd9n.fsf@gitster.g","subject":"Re: [PATCH v5 7/9] BreakingChanges: announce Rust becoming mandatory","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2025-09-22T22:15:16Z","receivedAt":"2025-09-22T22:15:19Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On 2025-09-22 at 20:59:00, Junio C Hamano wrote:\n> The version of the document in this thread talks about 2.52 (opt-in)\n> and 2.53 (opt-out) before jumping to 3.0 (no way to opt-out) but it\n> does not say anything about how far out that big version bump is.\n> But the numbers I remember hearing was in the orders of 18 monts or\n> so if I am not mistaken?\n\nI think the plan was 4 release cycles, or about a year.  Git 3.0 was\ngoing to replace 2.55.\n\n> As I already said a few times (e.g. <xmqq8qipzhg3.fsf@gitster.g>), I\n> feel that the timeline hinted by any of these documents that were\n> proposed is way too aggressive for affected people to practically\n> prepare for.\n\nI don't think it's substantially more aggressive than the\ninteroperability code.  Both are aggressive timelines, but getting LLVM\nported to some of the affected targets isn't out of the question\n(especially since older versions of it supported some of those targets)\nand once that's done, I'm pretty sure Rust upstream would be on board\nwith supporting those systems.\n\n> By the way, I was hoping that the hash compatibility work can be\n> done as an opt-in item available only for those with Rust, while\n> Rustless folks are forever stuck in a single hash algorithm world,\n> and be released well before Git 3.0 that makes Rust mandatory.  That\n> does not change the fact that nothing will work wrt hash transition\n> for Rustless folks, though ;-).\n\nI would love to have the interoperability work in sooner, but I don't\nthink it's realistic.  I have about 100 patches and I expect a total of\n200 to 400 for the entire work.  That means someone has to send in 50 to\n100 patches every one of the four release cycles before 3.0 and get\nthem sufficiently polished to get accepted, including any necessary\nre-rolls.  I don't think you actually want me to send all of those\npatches for one cycle at once, either.\n\nEven with time to work on it at work, that's a lot of time and effort\nfor one person, and I also have personal responsibilities to family and\nfriends (someone has to cook dinner, for instance).  We'll see if\nadditional assistance is forthcoming, in which case timelines could\npossibly be more aggressive.\n\nOtherwise, if we want Git 3.0 to contain the interoperability work and\nare unwilling to ship without it, then we may have a longer timeframe\nfor Git 3.0, and it may be more like replacing Git 2.57 or 2.58 instead.\n\n> [Footnote]\n> \n> * By the way, I _think_ I never saw that policy document until\n>   Ezekiel started his topic and sent it out as one of the component\n>   patches; how did it get there from brian to Ezekiel's topic?\n\nI had it in a branch of mine that I was going to submit at some point\nand I mentioned it to Ezekiel, who modified it and incorporated it.  The\noriginal branch should be `rust` on my remote for those who are\ninterested.\n-- \nbrian m. carlson (they/them)\nToronto, Ontario, CA\n"},{"id":"527004","messageId":"xmqqplbiqeol.fsf@gitster.g","threadId":"64091","inReplyTo":"aNHKdFkiGLPcLEjP@fruit.crustytoothpaste.net","subject":"Re: [PATCH v5 7/9] BreakingChanges: announce Rust becoming mandatory","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-09-22T22:56:42Z","receivedAt":"2025-09-22T22:56:46Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"brian m. carlson\" <sandals@crustytoothpaste.net> writes:\n\n\n>> As I already said a few times (e.g. <xmqq8qipzhg3.fsf@gitster.g>), I\n>> feel that the timeline hinted by any of these documents that were\n>> proposed is way too aggressive for affected people to practically\n>> prepare for.\n>\n> I don't think it's substantially more aggressive than the\n> interoperability code.  Both are aggressive timelines, but getting LLVM\n> ported to some of the affected targets isn't out of the question\n> (especially since older versions of it supported some of those targets)\n> and once that's done, I'm pretty sure Rust upstream would be on board\n> with supporting those systems.\n\nOur timeline being agressive to cause more intense work on our\npeople is one thing.  It does not make much sense to me to compare\nit with the timeline being aggressive to others who do not control\nour timeline.\n\nPutting it in another way, I'd call it hopelessly optimistic to\nexpect that those currently without Rust can somehow come up with a\nplan to help their vendors (or they may be vendors themselves, then\nconvince their management) prepare their platforms to support Rust\nwithin 18 months.  And giving them ultimatum based on the optimism\nwas never my favorite part of this whole thing.\n\n\n>> [Footnote]\n>> \n>> * By the way, I _think_ I never saw that policy document until\n>>   Ezekiel started his topic and sent it out as one of the component\n>>   patches; how did it get there from brian to Ezekiel's topic?\n>\n> I had it in a branch of mine that I was going to submit at some point\n> and I mentioned it to Ezekiel, who modified it and incorporated it.  The\n> original branch should be `rust` on my remote for those who are\n> interested.\n\nI figured that something like that happened.  I was mostly\ninterested in how firm those original authors supported the version\nwith Ezekiel's changes, as outsides would not be able to telll how\nextensive the change were.\n\nThanks.\n"},{"id":"527008","messageId":"CAH=ZcbCiSWSQQBEcqA9PTsrG2qgpo7a7zx_ahcUS227p0zELDw@mail.gmail.com","threadId":"64091","inReplyTo":"xmqq348etd9n.fsf@gitster.g","subject":"Re: [PATCH v5 7/9] BreakingChanges: announce Rust becoming mandatory","fromName":"Ezekiel Newren","fromEmail":"ezekielnewren@gmail.com","sentAt":"2025-09-23T00:43:31Z","receivedAt":"2025-09-23T00:43:45Z","isPatch":true,"sender":{"key":"ezekielnewren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/18313324?v=4"},"body":"On Mon, Sep 22, 2025 at 2:59 PM Junio C Hamano <gitster@pobox.com> wrote:\n> * By the way, I _think_ I never saw that policy document until\n>   Ezekiel started his topic and sent it out as one of the component\n>   patches; how did it get there from brian to Ezekiel's topic?\n\nYou'll have to ask Elijah that. I was oblivious to it until Elijah\npointed it out to me, and now I've forgotten.\n"},{"id":"527014","messageId":"CABPp-BFd4T4sJV=3uB_vfvSddQWeAdr=2x4T8i61VQHWJMW=tA@mail.gmail.com","threadId":"64091","inReplyTo":"xmqqplbiqeol.fsf@gitster.g","subject":"Re: [PATCH v5 7/9] BreakingChanges: announce Rust becoming mandatory","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2025-09-23T01:59:46Z","receivedAt":"2025-09-23T01:59:58Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Mon, Sep 22, 2025 at 3:56 PM Junio C Hamano <gitster@pobox.com> wrote:\n> >> [Footnote]\n> >>\n> >> * By the way, I _think_ I never saw that policy document until\n> >>   Ezekiel started his topic and sent it out as one of the component\n> >>   patches; how did it get there from brian to Ezekiel's topic?\n> >\n> > I had it in a branch of mine that I was going to submit at some point\n> > and I mentioned it to Ezekiel, who modified it and incorporated it.  The\n> > original branch should be `rust` on my remote for those who are\n> > interested.\n>\n> I figured that something like that happened.  I was mostly\n> interested in how firm those original authors supported the version\n> with Ezekiel's changes, as outsides would not be able to telll how\n> extensive the change were.\n>\n> Thanks.\n\nFootnote 1 of https://lore.kernel.org/git/aHlwZPbiKnakMN75@fruit.crustytoothpaste.net/\n"},{"id":"527021","messageId":"aNIoFePhTc5vGc_-@pks.im","threadId":"64091","inReplyTo":"xmqqplbiqeol.fsf@gitster.g","subject":"Re: [PATCH v5 7/9] BreakingChanges: announce Rust becoming mandatory","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-23T04:54:45Z","receivedAt":"2025-09-23T04:54:53Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Mon, Sep 22, 2025 at 03:56:42PM -0700, Junio C Hamano wrote:\n> \"brian m. carlson\" <sandals@crustytoothpaste.net> writes:\n> >> As I already said a few times (e.g. <xmqq8qipzhg3.fsf@gitster.g>), I\n> >> feel that the timeline hinted by any of these documents that were\n> >> proposed is way too aggressive for affected people to practically\n> >> prepare for.\n> >\n> > I don't think it's substantially more aggressive than the\n> > interoperability code.  Both are aggressive timelines, but getting LLVM\n> > ported to some of the affected targets isn't out of the question\n> > (especially since older versions of it supported some of those targets)\n> > and once that's done, I'm pretty sure Rust upstream would be on board\n> > with supporting those systems.\n> \n> Our timeline being agressive to cause more intense work on our\n> people is one thing.  It does not make much sense to me to compare\n> it with the timeline being aggressive to others who do not control\n> our timeline.\n> \n> Putting it in another way, I'd call it hopelessly optimistic to\n> expect that those currently without Rust can somehow come up with a\n> plan to help their vendors (or they may be vendors themselves, then\n> convince their management) prepare their platforms to support Rust\n> within 18 months.  And giving them ultimatum based on the optimism\n> was never my favorite part of this whole thing.\n\nWe have made other breaking changes conditional on the wider ecosystem.\nFor example, using reftable by default is conditioned on the ecosystem\nhaving catched up and supporting this new format.\n\nDo we maybe want to do the same with Rust? We can for example add\nsomething like the following paragraph:\n\n    We will carefully evaluate the impact on downstream distributions\n    before making Rust mandatory in Git 3.0. If we see that the impact\n    on downstream distributions would be significant, we may decide to\n    defer this breaking change. This will also take into account our own\n    learnings with how painful it is to keep Rust an optional component.\n\nThe intent would be to alert distributors, but not \"blindly\" pull the\ntrigger. Instead, we should take a step back and evaluate both how the\nRust ecosystem looks like at the Git 3.0 boundary and how painful it is\nfor us to keep it as an optional component.\n\nPatrick\n"},{"id":"527024","messageId":"aNIw23JzQE1vz2JD@pks.im","threadId":"64091","inReplyTo":"xmqqsegev4jp.fsf@gitster.g","subject":"Re: [PATCH RFC v4 7/9] BreakingChanges: announce Rust becoming mandatory","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-23T05:32:11Z","receivedAt":"2025-09-23T05:32:19Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Mon, Sep 22, 2025 at 09:24:26AM -0700, Junio C Hamano wrote:\n> Patrick Steinhardt <ps@pks.im> writes:\n> \n> >> I am having a hard time imagining the practicality of this \"hand\n> >> over but we still review\" arrangement.  Some of the security fixes\n> >> are embargoed, and the reason why we are jetissoning the stale\n> >> codebase is presumably because nobody is willing to work on it other\n> >> than the \"community support\" folks.  I can imagine that we would\n> >> qualify them into the git-security cabal and let them use the forum\n> >> to coordinate among themselves, but then to what degree in the\n> >> \"community support themselves\" process is our involvement expected?\n> >> As long as we can make sure that they do not leak before the\n> >> official embargoed release, they do not need an official stamp of\n> >> approval from the project or by the Git maintainer---that is what it\n> >> means to \"hand over maintainer ship\", at least to me.\n> >> \n> >> In other words, I like what I see in this paragraph, but I do not\n> >> think we can practically live with the part of the sentence after\n> >> the last \", but\".\n> >\n> > I think the most important part here is that this community-supported\n> > LTS release should still live in the canonical repositories. We should\n> > avoid the situation where we hand over maintainership to such a degree\n> > that the end result (the tagged LTS release) lives somewhere else.\n> \n> Why is it a bad thing?  The official repository can have a README.md\n> with a single entry \"maintenance releases for Git 2.98 LTS (most\n> notably with no Rust requirements) are found at this separate site\".\n\nThere's a couple reasons:\n\n  - The LTS maintainer may not be as familiar with the Git codebase as\n    we are, so they would benefit from the usual processes on the\n    mailing list.\n\n  - The LTS maintainer may not be as trusted as other regulars on the\n    mailing list are, so we (from my POV) may want to avoid having a\n    basically unobserved fork elsewhere.\n\n  - The end result would still be \"git\", and users will come to us to\n    complain about issues in the LTS release.\n\n  - Initial releases of the LTS release branch that are managed by us\n    would sit in our repo, whereas subsequent releases would sit in the\n    LTS release. This will likely cause confusion.\n\n  - We reduce chances of a hard fork of Git.\n\nSo with these in mind I think it would be sensible to keep the LTS\nrelease as part of the canonical repository.\n\n> > Otherwise we risk chaos and a plethora of different LTS releases, which\n> > would be harmful both for us and those that rely on the LTS releases.\n> \n> No risk for that as long as we have a single \"go there\" pointer, right?\n\nIt somewhat reduces the risk, true. I still worry a bit about\nencouraging a hard fork.\n\n> > And yes, that probably means that a trusted LTS maintainer should be on\n> > git-security@ so that they are aware of upcoming security releases.\n> \n> Absolutely.\n> \n> And there should be a community of those who are working on helping\n> the backporting effort around that LTS maintainer that ensures there\n> is no \"chaos and a plethora of different LTS releases\".\n\nFair.\n\n> We might occasionally update what is listed in \"git ls-remote --tags\"\n> from our repository by syncing with them only for convenience, but\n> the important point is that the community supported LTS should have\n> its own official site, which is different from the cutting/bleeding\n> edge.  Most importantly, a coordinated disclosure would say that the\n> update to versions of\n> \n>  - Git 3.0 to Git 3.4 are found $HERE, \n>  - Git for Windows 3.0, 3.2, and 3.4 are found $THERE\n>  - Git 2.98 are found $COMMUNITY_LTS\n> \n> to make sure that people know where to find their updates.\n> \n> So, no, I do not think we should unnecessarily mix community LTS and\n> the main project.\n\nHow about the following tradeoff: the community LTS is developed outside\nof the usual Git workflow, for example on a forge, so that the LTS\nmaintainers can work in their preferred flow. But eventually, once they\nwant to do a release they send a pull request to the Git mailing list\nand then the tag lives in the canonical Git repository.\n\nIt gives the LTS maintainers flexibility, but still makes the canonical\nrepository the single source of truth for Git releases. Furthermore,\nwe'd have a way to double check the results before creating the tags.\n\nPatrick\n"},{"id":"527029","messageId":"61e4895a-415e-f2ba-97d7-23aa99334191@gmx.de","threadId":"64091","inReplyTo":"aNIw23JzQE1vz2JD@pks.im","subject":"LTS \"lieutenant\", was Re: [PATCH RFC v4 7/9] BreakingChanges: announce Rust becoming mandatory","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2025-09-23T08:53:02Z","receivedAt":"2025-09-23T08:53:22Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi Patrick,\n\nOn Tue, 23 Sep 2025, Patrick Steinhardt wrote:\n\n> On Mon, Sep 22, 2025 at 09:24:26AM -0700, Junio C Hamano wrote:\n> > Patrick Steinhardt <ps@pks.im> writes:\n> > \n> > >> I am having a hard time imagining the practicality of this \"hand\n> > >> over but we still review\" arrangement.  Some of the security fixes\n> > >> are embargoed, and the reason why we are jetissoning the stale\n> > >> codebase is presumably because nobody is willing to work on it other\n> > >> than the \"community support\" folks.  I can imagine that we would\n> > >> qualify them into the git-security cabal and let them use the forum\n> > >> to coordinate among themselves, but then to what degree in the\n> > >> \"community support themselves\" process is our involvement expected?\n> > >> As long as we can make sure that they do not leak before the\n> > >> official embargoed release, they do not need an official stamp of\n> > >> approval from the project or by the Git maintainer---that is what it\n> > >> means to \"hand over maintainer ship\", at least to me.\n> > >> \n> > >> In other words, I like what I see in this paragraph, but I do not\n> > >> think we can practically live with the part of the sentence after\n> > >> the last \", but\".\n> > >\n> > > I think the most important part here is that this community-supported\n> > > LTS release should still live in the canonical repositories. We should\n> > > avoid the situation where we hand over maintainership to such a degree\n> > > that the end result (the tagged LTS release) lives somewhere else.\n> > \n> > Why is it a bad thing?  The official repository can have a README.md\n> > with a single entry \"maintenance releases for Git 2.98 LTS (most\n> > notably with no Rust requirements) are found at this separate site\".\n> \n> There's a couple reasons:\n> \n>   - The LTS maintainer may not be as familiar with the Git codebase as\n>     we are, so they would benefit from the usual processes on the\n>     mailing list.\n\nBasically: It's a matter of trust.\n\n>   - The LTS maintainer may not be as trusted as other regulars on the\n>     mailing list are, so we (from my POV) may want to avoid having a\n>     basically unobserved fork elsewhere.\n\nBasically: It's a matter of trust.\n\n>   - The end result would still be \"git\", and users will come to us to\n>     complain about issues in the LTS release.\n\nBasically: Users would still only trust the main Git project.\n\n>   - Initial releases of the LTS release branch that are managed by us\n>     would sit in our repo, whereas subsequent releases would sit in the\n>     LTS release. This will likely cause confusion.\n\nAnd confusion sows distrust, I agree.\n\n>   - We reduce chances of a hard fork of Git.\n> \n> So with these in mind I think it would be sensible to keep the LTS\n> release as part of the canonical repository.\n\nI agree, and I have to say that I am puzzled that it was even a question.\n\n> > So, no, I do not think we should unnecessarily mix community LTS and\n> > the main project.\n> \n> How about the following tradeoff: the community LTS is developed outside\n> of the usual Git workflow, for example on a forge, so that the LTS\n> maintainers can work in their preferred flow. But eventually, once they\n> want to do a release they send a pull request to the Git mailing list\n> and then the tag lives in the canonical Git repository.\n> \n> It gives the LTS maintainers flexibility, but still makes the canonical\n> repository the single source of truth for Git releases. Furthermore,\n> we'd have a way to double check the results before creating the tags.\n\nI have to admit that it sounds quite odd an idea to \"hand off LTS support\"\nto a completely different entity. It flies counter to everything I have\nlearned in this industry. There has been exactly zero instance worth\nmentioning where an LTS release maintained outside of the main project has\nbeen accepted as anything remotely official. There is no reason to believe\nthat Git would be the first.\n\nLet me propose an alternative, one that is much more likely to be accepted\nby actual Git users, including professional ones: How about assigning a\ntrusted, prolific Git contributor as LTS maintainer? One who is deeply\nfamiliar with the Git project and can, if the need arises, help the Git\nproject steer clear of unnecessary conflict-making e.g. via\nintentionally-incompatible bug fixes on the non-LTS branch? Kind of like\nthe lieutenants in the Linux kernel project.\n\nNaturally, I am thinking of you, Patrick. You have demonstrated diligent\nwork in the Git project, are highly trusted both inside and outside the\nGit project, and you seem to genuinely care about the long-term success of\nthe Git project.\n\nAn additional benefit of this would be to have a dependable release policy\nfor older release trains, just like other projects have. I have heard the\ndesire for such a policy many times.\n\nCiao,\nJohannes\n\nP.S.: As you probably know from my past interactions on this mailing list,\nI am not typically one to dump work on others; I am more than willing to\nassist you in the LTS maintenance tasks in any way I can.\n"},{"id":"527040","messageId":"20250923-b4-pks-rust-breaking-change-v6-0-59076fee486a@pks.im","threadId":"64091","inReplyTo":"20250904-b4-pks-rust-breaking-change-v1-0-3af1d25e0be9@pks.im","subject":"[PATCH v6 0/9] Introduce Rust and announce that it will become mandatory","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-23T09:45:19Z","receivedAt":"2025-09-23T09:45:31Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Hi,\n\nthis small patch series introduces Rust into the core of Git. This patch\nseries is designed as a test balloon, similar to how we introduced test\nballoons for C99 features in the past. The goal is threefold:\n\n  - Give us some time to experiment with Rust and introduce proper build\n    infrastructure.\n\n  - Give distributors time to ease into the new toolchain requirements.\n    Introducing Rust is impossible for some platforms and hard for\n    others.\n\n  - Announce that Git 3.0 will make Rust a mandatory part of our build\n    infrastructure.\n\nThe test balloon itself is quite uninteresting: I've chosen to convert\nthe \"varint.c\" subsystem, mostly because it is trivial and does not have\nany dependencies. But it does allow us to verify that C to Rust interop\nworks as expected, and to play around with tooling. All tests pass with\nthe \"varint.rs\" implementation.\n\nFor now, the series only contains support for Meson. If we agree to go\ndown this route I'll also introduce support for Rust into our Makefiles\nat a later point in time.\n\nFurthermore missing is additional tooling:\n\n  - At least one CI job to verify that Rust builds and works as\n    expected.\n\n  - Tooling and CI jobs to ensure that we have consistent formatting via\n    `cargo format`.\n\nAnd probably lots more. As said, the entire goal is for us to have an\neasy playground that we can experiment on and develop the infrastructure\nincrementally without yet having to commit to anything.\n\nI'm mostly splitting out the topic of introducing Rust from the larger\nseries that introduce it into xdiff so that we can focus more on the\nactual process of introducing Rust into Git and less on the potential\nfeatures that we want to build on top of it.\n\nChanges in v2:\n  - Introduce support for building the Rust library via our Makefile.\n  - Introduce a '-DWITH_RUST' define. This define is used to print\n    whether or not Git is built with Rust via `git version\n    --build-options`.\n  - Adjust Meson to not depend on v1.9.0 and newer anymore.\n  - Introduce a roadmap into our BreakingChanges document to explain how\n    we'll iterate towards mandatory Rust support.\n  - Rework the Fedora job to do a full compile-and-test run with Meson\n    and breaking changes enabled.\n  - Adapt our breaking-changes jobs to enable Rust support.\n  - Link to v1: https://lore.kernel.org/r/20250904-b4-pks-rust-breaking-change-v1-0-3af1d25e0be9@pks.im\n\nChanges in v3:\n  - Reorder all uses of `WITH_RUST` after the include of \"config.mak\".\n  - Add a test to verify overflow behaviour in Rust and explicitly use\n    `add_wrapping()`.\n  - Use explicit dependencies for the Rust library in our Makefile.\n  - Fix Alma Linux CI job.\n  - Stop tying maintenance of our LTS release to the availability of\n    gcc-rs.\n  - Add a fallback to Meson to use cargo directly.\n  - I've fixed the Rust edition to 2018 for now. This is intentionally\n    conservative so that we might be able to use Rust 1.49. For now, we\n    don't have any reason to use a newer edition, either. So let's take\n    the oldest version we can live with for now and then bump it as\n    required.\n  - Link to v2: https://lore.kernel.org/r/20250905-b4-pks-rust-breaking-change-v2-0-6939cbf4a0b8@pks.im\n\nChanges in v4:\n  - Convert \"varint.c\" to use explicit integer width so that we don't\n    need to use C types in Rust.\n  - Adapt Meson to unconditionally use Cargo.\n  - Don't use the unstable `--out-dir` option in Cargo. Instead, we\n    resort to a wrapper script in Meson.\n  - Shorten the timeline a bit to drop the extra step that ties Rust\n    support to `-Dbreaking_changes=true`. This accelerates the timeline\n    until distros are made forcibly aware of the upcoming changes in\n    Rust.\n  - Link to v3: https://lore.kernel.org/r/20250908-b4-pks-rust-breaking-change-v3-0-1cd7189fed3b@pks.im\n\nChanges in v5:\n  - Fix indentation in the BreakingChanges document.\n  - Fix a commit message typo.\n  - Include \"Cargo.lock\" in the `make clean` target again.\n  - Link to v4: https://lore.kernel.org/r/20250910-b4-pks-rust-breaking-change-v4-0-4a63fc69278d@pks.im\n\nChanges in v6:\n  - Give attribution to Ezekiel for kickstarting the Rust adoption\n    again. I'm happy to change how I do the attribution.\n  - Fix \"varint.rs\" to use `u64` instead of `usize`. Issues like these\n    will eventually be catched by cbindgen.\n  - Adapt the breaking changes document to mention that we already have\n    Rust in our tree starting with Git 2.49.\n  - Mention that we won't blindly make Rust mandatory, but consider the\n    impact on downstream distributions.\n  - Slightly reword how we'll handle LTS maintainership. This probably\n    still is an ongoing discussion.\n  - Link to v5: https://lore.kernel.org/r/20250915-b4-pks-rust-breaking-change-v5-0-dc3a32fbb216@pks.im\n\nThanks!\n\nPatrick\n\n---\nPatrick Steinhardt (9):\n      meson: add infrastructure to build internal Rust library\n      Makefile: reorder sources after includes\n      Makefile: introduce infrastructure to build internal Rust library\n      help: report on whether or not Rust is enabled\n      varint: use explicit width for integers\n      varint: reimplement as test balloon for Rust\n      BreakingChanges: announce Rust becoming mandatory\n      ci: convert \"pedantic\" job into full build with breaking changes\n      ci: enable Rust for breaking-changes jobs\n\n .github/workflows/main.yml         |   4 +-\n .gitignore                         |   2 +\n .gitlab-ci.yml                     |   4 +-\n Cargo.toml                         |   9 ++\n Documentation/BreakingChanges.adoc |  45 ++++++++\n Makefile                           | 214 ++++++++++++++++++++++---------------\n ci/install-dependencies.sh         |   8 +-\n ci/run-build-and-tests.sh          |  31 ++----\n dir.c                              |  18 ++--\n help.c                             |   6 ++\n meson.build                        |  15 ++-\n meson_options.txt                  |   2 +\n read-cache.c                       |   6 +-\n shared.mak                         |   1 +\n src/cargo-meson.sh                 |  32 ++++++\n src/lib.rs                         |   1 +\n src/meson.build                    |  41 +++++++\n src/varint.rs                      |  92 ++++++++++++++++\n varint.c                           |   6 +-\n varint.h                           |   4 +-\n 20 files changed, 410 insertions(+), 131 deletions(-)\n\nRange-diff versus v5:\n\n 1:  22925bf016 !  1:  06872fe524 meson: add infrastructure to build internal Rust library\n    @@ Commit message\n         want to introduce features that were added in more recent editions of\n         Rust though we should reevaluate that choice.\n     \n    +    Inspired-by: Ezekiel Newren <ezekielnewren@gmail.com>\n         Signed-off-by: Patrick Steinhardt <ps@pks.im>\n     \n      ## Cargo.toml (new) ##\n 2:  bcd30c4e0f =  2:  0f243f137e Makefile: reorder sources after includes\n 3:  45663309c3 !  3:  cb078bdffc Makefile: introduce infrastructure to build internal Rust library\n    @@ Commit message\n         commit. Developers can enable the infrastructure by passing the new\n         `WITH_RUST` build toggle.\n     \n    +    Inspired-by: Ezekiel Newren <ezekielnewren@gmail.com>\n         Signed-off-by: Patrick Steinhardt <ps@pks.im>\n     \n      ## .gitignore ##\n 4:  1eec68d6a3 =  4:  b043011938 help: report on whether or not Rust is enabled\n 5:  95f705fc07 =  5:  b3b415b277 varint: use explicit width for integers\n 6:  2d36e3bb54 !  6:  435e5c3ae5 varint: reimplement as test balloon for Rust\n    @@ src/meson.build\n      ## src/varint.rs (new) ##\n     @@\n     +#[no_mangle]\n    -+pub unsafe extern \"C\" fn decode_varint(bufp: *mut *const u8) -> usize {\n    ++pub unsafe extern \"C\" fn decode_varint(bufp: *mut *const u8) -> u64 {\n     +    let mut buf = *bufp;\n     +    let mut c = *buf;\n    -+    let mut val = usize::from(c & 127);\n    ++    let mut val = u64::from(c & 127);\n     +\n     +    buf = buf.add(1);\n     +\n    @@ src/varint.rs (new)\n     +        c = *buf;\n     +        buf = buf.add(1);\n     +\n    -+        val = (val << 7) + usize::from(c & 127);\n    ++        val = (val << 7) + u64::from(c & 127);\n     +    }\n     +\n     +    *bufp = buf;\n    @@ src/varint.rs (new)\n     +}\n     +\n     +#[no_mangle]\n    -+pub unsafe extern \"C\" fn encode_varint(value: usize, buf: *mut u8) -> u8 {\n    ++pub unsafe extern \"C\" fn encode_varint(value: u64, buf: *mut u8) -> u8 {\n     +    let mut varint: [u8; 16] = [0; 16];\n     +    let mut pos = varint.len() - 1;\n     +\n 7:  92590e9f87 !  7:  3f0cb3550a BreakingChanges: announce Rust becoming mandatory\n    @@ Documentation/BreakingChanges.adoc: A prerequisite for this change is that the e\n      JGit, libgit2 and Gitoxide need to support it.\n      \n     +* Git will require Rust as a mandatory part of the build process. While Git\n    -+  already started to adopt Rust in Git 2.52, all parts written in Rust are\n    ++  already started to adopt Rust in Git 2.49, all parts written in Rust are\n     +  optional for the time being. This includes:\n     ++\n    ++  ** The Rust wrapper around libgit.a that is part of \"contrib/\" and which has\n    ++     been introduced in Git 2.49.\n     +  ** Subsystems that have an alternative implementation in Rust to test\n     +     interoperability between our C and Rust codebase.\n     +  ** Newly written features that are not mission critical for a fully functional\n    @@ Documentation/BreakingChanges.adoc: A prerequisite for this change is that the e\n     +project will hand over maintainership of the long-term release to distributors\n     +in case they need to extend the life of that long-term release even further. In\n     +that case, the backporting process will be handled by these distributors, but\n    -+the backported patches will be reviewed on the mailing list and pulled in by the\n    -+Git maintainer.\n    ++the long-term release tags will be created in the canonical Git repository.\n    +++\n    ++We will evaluate the impact on downstream distributions before making Rust\n    ++mandatory in Git 3.0. If we see that the impact on downstream distributions\n    ++would be significant, we may decide to defer this breaking change to a\n    ++subsequent minor release. This evaluation will also take into account our own\n    ++learnings with how painful it is to keep Rust an optional component.\n     +\n      === Removals\n      \n 8:  3c7b2edeb4 =  8:  e5dc29bc1c ci: convert \"pedantic\" job into full build with breaking changes\n 9:  c3803ab47b =  9:  9fcaa8c540 ci: enable Rust for breaking-changes jobs\n\n---\nbase-commit: 2462961280690837670d997bde64bd4ebf8ae66d\nchange-id: 20250904-b4-pks-rust-breaking-change-7167d9d3e37d\n\n"},{"id":"527041","messageId":"20250923-b4-pks-rust-breaking-change-v6-1-59076fee486a@pks.im","threadId":"64091","inReplyTo":"20250923-b4-pks-rust-breaking-change-v6-0-59076fee486a@pks.im","subject":"[PATCH v6 1/9] meson: add infrastructure to build internal Rust library","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-23T09:45:20Z","receivedAt":"2025-09-23T09:45:34Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Add the infrastructure into Meson to build an internal Rust library.\nBuilding the Rust parts of Git are for now entirely optional, as they\nare mostly intended as a test balloon for both Git developers, but also\nfor distributors of Git. So for now, they may contain:\n\n  - New features that are not mission critical to Git and that users can\n    easily live without.\n\n  - Alternative implementations of small subsystems.\n\nIf these test balloons are successful, we will eventually make Rust a\nmandatory dependency for our build process in Git 3.0.\n\nThe availability of a Rust toolchain will be auto-detected by Meson at\nsetup time. This behaviour can be tweaked via the `-Drust=` feature\ntoggle.\n\nNext to the linkable Rust library, also wire up tests that can be\nexecuted via `meson test`. This allows us to use the native unit testing\ncapabilities of Rust.\n\nNote that the Rust edition is currently set to 2018. This edition is\nsupported by Rust 1.49, which is the target for the upcoming gcc-rs\nbackend. For now we don't use any features of Rust that would require a\nnewer version, so settling on this old version makes sense so that\ngcc-rs may become an alternative backend for compiling Git. If we _do_\nwant to introduce features that were added in more recent editions of\nRust though we should reevaluate that choice.\n\nInspired-by: Ezekiel Newren <ezekielnewren@gmail.com>\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n Cargo.toml         |  9 +++++++++\n meson.build        | 10 +++++++++-\n meson_options.txt  |  2 ++\n src/cargo-meson.sh | 32 ++++++++++++++++++++++++++++++++\n src/lib.rs         |  0\n src/meson.build    | 40 ++++++++++++++++++++++++++++++++++++++++\n 6 files changed, 92 insertions(+), 1 deletion(-)\n\ndiff --git a/Cargo.toml b/Cargo.toml\nnew file mode 100644\nindex 00000000000..b9a41dbc792\n--- /dev/null\n+++ b/Cargo.toml\n@@ -0,0 +1,9 @@\n+[package]\n+name = \"git\"\n+version = \"0.1.0\"\n+edition = \"2018\"\n+\n+[lib]\n+crate-type = [\"staticlib\"]\n+\n+[dependencies]\ndiff --git a/meson.build b/meson.build\nindex e8ec0eca165..234a9e9d6fd 100644\n--- a/meson.build\n+++ b/meson.build\n@@ -220,7 +220,7 @@ project('git', 'c',\n   # learned to define __STDC_VERSION__ with C11 and later. We thus require\n   # GNU C99 and fall back to C11. Meson only learned to handle the fallback\n   # with version 1.3.0, so on older versions we use GNU C99 unconditionally.\n-  default_options: meson.version().version_compare('>=1.3.0') ? ['c_std=gnu99,c11'] : ['c_std=gnu99'],\n+  default_options: meson.version().version_compare('>=1.3.0') ? ['rust_std=2018', 'c_std=gnu99,c11'] : ['rust_std=2018', 'c_std=gnu99'],\n )\n \n fs = import('fs')\n@@ -1702,6 +1702,13 @@ version_def_h = custom_target(\n )\n libgit_sources += version_def_h\n \n+cargo = find_program('cargo', dirs: program_path, native: true, required: get_option('rust'))\n+rust_option = get_option('rust').disable_auto_if(not cargo.found())\n+if rust_option.allowed()\n+  subdir('src')\n+  libgit_c_args += '-DWITH_RUST'\n+endif\n+\n libgit = declare_dependency(\n   link_with: static_library('git',\n     sources: libgit_sources,\n@@ -2239,6 +2246,7 @@ summary({\n   'pcre2': pcre2,\n   'perl': perl_features_enabled,\n   'python': target_python.found(),\n+  'rust': rust_option.allowed(),\n }, section: 'Auto-detected features', bool_yn: true)\n \n summary({\ndiff --git a/meson_options.txt b/meson_options.txt\nindex 1668f260a18..143dee9237c 100644\n--- a/meson_options.txt\n+++ b/meson_options.txt\n@@ -71,6 +71,8 @@ option('zlib_backend', type: 'combo', choices: ['auto', 'zlib', 'zlib-ng'], valu\n # Build tweaks.\n option('breaking_changes', type: 'boolean', value: false,\n   description: 'Enable upcoming breaking changes.')\n+option('rust', type: 'feature', value: 'auto',\n+  description: 'Enable building with Rust.')\n option('macos_use_homebrew_gettext', type: 'boolean', value: true,\n   description: 'Use gettext from Homebrew instead of the slightly-broken system-provided one.')\n \ndiff --git a/src/cargo-meson.sh b/src/cargo-meson.sh\nnew file mode 100755\nindex 00000000000..f29745beb36\n--- /dev/null\n+++ b/src/cargo-meson.sh\n@@ -0,0 +1,32 @@\n+#!/bin/sh\n+\n+if test \"$#\" -lt 2\n+then\n+\texit 1\n+fi\n+\n+SOURCE_DIR=\"$1\"\n+BUILD_DIR=\"$2\"\n+BUILD_TYPE=debug\n+\n+shift 2\n+\n+for arg\n+do\n+\tcase \"$arg\" in\n+\t--release)\n+\t\tBUILD_TYPE=release;;\n+\tesac\n+done\n+\n+cargo build --lib --quiet --manifest-path=\"$SOURCE_DIR/Cargo.toml\" --target-dir=\"$BUILD_DIR\" \"$@\"\n+RET=$?\n+if test $RET -ne 0\n+then\n+\texit $RET\n+fi\n+\n+if ! cmp \"$BUILD_DIR/$BUILD_TYPE/libgit.a\" \"$BUILD_DIR/libgit.a\" >/dev/null 2>&1\n+then\n+\tcp \"$BUILD_DIR/$BUILD_TYPE/libgit.a\" \"$BUILD_DIR/libgit.a\"\n+fi\ndiff --git a/src/lib.rs b/src/lib.rs\nnew file mode 100644\nindex 00000000000..e69de29bb2d\ndiff --git a/src/meson.build b/src/meson.build\nnew file mode 100644\nindex 00000000000..734de0b4fa9\n--- /dev/null\n+++ b/src/meson.build\n@@ -0,0 +1,40 @@\n+libgit_rs_sources = [\n+  'lib.rs',\n+]\n+\n+# Unfortunately we must use a wrapper command to move the output file into the\n+# current build directory. This can fixed once `cargo build --artifact-dir`\n+# stabilizes. See https://github.com/rust-lang/cargo/issues/6790 for that\n+# effort.\n+cargo_command = [\n+  shell,\n+  meson.current_source_dir() / 'cargo-meson.sh',\n+  meson.project_source_root(),\n+  meson.current_build_dir(),\n+]\n+if get_option('buildtype') == 'release'\n+  cargo_command += '--release'\n+endif\n+\n+libgit_rs = custom_target('git_rs',\n+  input: libgit_rs_sources + [\n+    meson.project_source_root() / 'Cargo.toml',\n+  ],\n+  output: 'libgit.a',\n+  command: cargo_command,\n+)\n+libgit_dependencies += declare_dependency(link_with: libgit_rs)\n+\n+if get_option('tests')\n+  test('rust', cargo,\n+    args: [\n+      'test',\n+      '--manifest-path',\n+      meson.project_source_root() / 'Cargo.toml',\n+      '--target-dir',\n+      meson.current_build_dir() / 'target',\n+    ],\n+    timeout: 0,\n+    protocol: 'rust',\n+  )\n+endif\n\n-- \n2.51.0.536.g15c5d4f767.dirty\n\n"},{"id":"527042","messageId":"20250923-b4-pks-rust-breaking-change-v6-2-59076fee486a@pks.im","threadId":"64091","inReplyTo":"20250923-b4-pks-rust-breaking-change-v6-0-59076fee486a@pks.im","subject":"[PATCH v6 2/9] Makefile: reorder sources after includes","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-23T09:45:21Z","receivedAt":"2025-09-23T09:45:37Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"In an upcoming change we'll make some of the sources compile\nconditionally based on whether or not `WITH_RUST` is defined. To let\ndevelopers specify that flag in their \"config.mak\" we'll thus have to\nreorder our sources so that they come after the include of that file.\n\nDo so.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n Makefile | 176 +++++++++++++++++++++++++++++++--------------------------------\n 1 file changed, 88 insertions(+), 88 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 555b7f4dc3..7e52625d75 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -919,6 +919,94 @@ LIB_FILE = libgit.a\n XDIFF_LIB = xdiff/lib.a\n REFTABLE_LIB = reftable/libreftable.a\n \n+# xdiff and reftable libs may in turn depend on what is in libgit.a\n+GITLIBS = common-main.o $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(LIB_FILE)\n+EXTLIBS =\n+\n+GIT_USER_AGENT = git/$(GIT_VERSION)\n+\n+ifeq ($(wildcard sha1collisiondetection/lib/sha1.h),sha1collisiondetection/lib/sha1.h)\n+DC_SHA1_SUBMODULE = auto\n+endif\n+\n+# Set CFLAGS, LDFLAGS and other *FLAGS variables. These might be\n+# tweaked by config.* below as well as the command-line, both of\n+# which'll override these defaults.\n+# Older versions of GCC may require adding \"-std=gnu99\" at the end.\n+CFLAGS = -g -O2 -Wall\n+LDFLAGS =\n+CC_LD_DYNPATH = -Wl,-rpath,\n+BASIC_CFLAGS = -I.\n+BASIC_LDFLAGS =\n+\n+# library flags\n+ARFLAGS = rcs\n+PTHREAD_CFLAGS =\n+\n+# For the 'sparse' target\n+SPARSE_FLAGS ?= -std=gnu99 -D__STDC_NO_VLA__\n+SP_EXTRA_FLAGS =\n+\n+# For informing GIT-BUILD-OPTIONS of the SANITIZE=leak,address targets\n+SANITIZE_LEAK =\n+SANITIZE_ADDRESS =\n+\n+# For the 'coccicheck' target\n+SPATCH_INCLUDE_FLAGS = --all-includes\n+SPATCH_FLAGS =\n+SPATCH_TEST_FLAGS =\n+\n+# If *.o files are present, have \"coccicheck\" depend on them, with\n+# COMPUTE_HEADER_DEPENDENCIES this will speed up the common-case of\n+# only needing to re-generate coccicheck results for the users of a\n+# given API if it's changed, and not all files in the project. If\n+# COMPUTE_HEADER_DEPENDENCIES=no this will be unset too.\n+SPATCH_USE_O_DEPENDENCIES = YesPlease\n+\n+# Set SPATCH_CONCAT_COCCI to concatenate the contrib/cocci/*.cocci\n+# files into a single contrib/cocci/ALL.cocci before running\n+# \"coccicheck\".\n+#\n+# Pros:\n+#\n+# - Speeds up a one-shot run of \"make coccicheck\", as we won't have to\n+#   parse *.[ch] files N times for the N *.cocci rules\n+#\n+# Cons:\n+#\n+# - Will make incremental development of *.cocci slower, as\n+#   e.g. changing strbuf.cocci will re-run all *.cocci.\n+#\n+# - Makes error and performance analysis harder, as rules will be\n+#   applied from a monolithic ALL.cocci, rather than\n+#   e.g. strbuf.cocci. To work around this either undefine this, or\n+#   generate a specific patch, e.g. this will always use strbuf.cocci,\n+#   not ALL.cocci:\n+#\n+#\tmake contrib/coccinelle/strbuf.cocci.patch\n+SPATCH_CONCAT_COCCI = YesPlease\n+\n+# Rebuild 'coccicheck' if $(SPATCH), its flags etc. change\n+TRACK_SPATCH_DEFINES =\n+TRACK_SPATCH_DEFINES += $(SPATCH)\n+TRACK_SPATCH_DEFINES += $(SPATCH_INCLUDE_FLAGS)\n+TRACK_SPATCH_DEFINES += $(SPATCH_FLAGS)\n+TRACK_SPATCH_DEFINES += $(SPATCH_TEST_FLAGS)\n+GIT-SPATCH-DEFINES: FORCE\n+\t@FLAGS='$(TRACK_SPATCH_DEFINES)'; \\\n+\t    if test x\"$$FLAGS\" != x\"`cat GIT-SPATCH-DEFINES 2>/dev/null`\" ; then \\\n+\t\techo >&2 \"    * new spatch flags\"; \\\n+\t\techo \"$$FLAGS\" >GIT-SPATCH-DEFINES; \\\n+            fi\n+\n+include config.mak.uname\n+-include config.mak.autogen\n+-include config.mak\n+\n+ifdef DEVELOPER\n+include config.mak.dev\n+endif\n+\n GENERATED_H += command-list.h\n GENERATED_H += config-list.h\n GENERATED_H += hook-list.h\n@@ -1387,94 +1475,6 @@ CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/unit-test.o\n \n UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o\n \n-# xdiff and reftable libs may in turn depend on what is in libgit.a\n-GITLIBS = common-main.o $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(LIB_FILE)\n-EXTLIBS =\n-\n-GIT_USER_AGENT = git/$(GIT_VERSION)\n-\n-ifeq ($(wildcard sha1collisiondetection/lib/sha1.h),sha1collisiondetection/lib/sha1.h)\n-DC_SHA1_SUBMODULE = auto\n-endif\n-\n-# Set CFLAGS, LDFLAGS and other *FLAGS variables. These might be\n-# tweaked by config.* below as well as the command-line, both of\n-# which'll override these defaults.\n-# Older versions of GCC may require adding \"-std=gnu99\" at the end.\n-CFLAGS = -g -O2 -Wall\n-LDFLAGS =\n-CC_LD_DYNPATH = -Wl,-rpath,\n-BASIC_CFLAGS = -I.\n-BASIC_LDFLAGS =\n-\n-# library flags\n-ARFLAGS = rcs\n-PTHREAD_CFLAGS =\n-\n-# For the 'sparse' target\n-SPARSE_FLAGS ?= -std=gnu99 -D__STDC_NO_VLA__\n-SP_EXTRA_FLAGS =\n-\n-# For informing GIT-BUILD-OPTIONS of the SANITIZE=leak,address targets\n-SANITIZE_LEAK =\n-SANITIZE_ADDRESS =\n-\n-# For the 'coccicheck' target\n-SPATCH_INCLUDE_FLAGS = --all-includes\n-SPATCH_FLAGS =\n-SPATCH_TEST_FLAGS =\n-\n-# If *.o files are present, have \"coccicheck\" depend on them, with\n-# COMPUTE_HEADER_DEPENDENCIES this will speed up the common-case of\n-# only needing to re-generate coccicheck results for the users of a\n-# given API if it's changed, and not all files in the project. If\n-# COMPUTE_HEADER_DEPENDENCIES=no this will be unset too.\n-SPATCH_USE_O_DEPENDENCIES = YesPlease\n-\n-# Set SPATCH_CONCAT_COCCI to concatenate the contrib/cocci/*.cocci\n-# files into a single contrib/cocci/ALL.cocci before running\n-# \"coccicheck\".\n-#\n-# Pros:\n-#\n-# - Speeds up a one-shot run of \"make coccicheck\", as we won't have to\n-#   parse *.[ch] files N times for the N *.cocci rules\n-#\n-# Cons:\n-#\n-# - Will make incremental development of *.cocci slower, as\n-#   e.g. changing strbuf.cocci will re-run all *.cocci.\n-#\n-# - Makes error and performance analysis harder, as rules will be\n-#   applied from a monolithic ALL.cocci, rather than\n-#   e.g. strbuf.cocci. To work around this either undefine this, or\n-#   generate a specific patch, e.g. this will always use strbuf.cocci,\n-#   not ALL.cocci:\n-#\n-#\tmake contrib/coccinelle/strbuf.cocci.patch\n-SPATCH_CONCAT_COCCI = YesPlease\n-\n-# Rebuild 'coccicheck' if $(SPATCH), its flags etc. change\n-TRACK_SPATCH_DEFINES =\n-TRACK_SPATCH_DEFINES += $(SPATCH)\n-TRACK_SPATCH_DEFINES += $(SPATCH_INCLUDE_FLAGS)\n-TRACK_SPATCH_DEFINES += $(SPATCH_FLAGS)\n-TRACK_SPATCH_DEFINES += $(SPATCH_TEST_FLAGS)\n-GIT-SPATCH-DEFINES: FORCE\n-\t@FLAGS='$(TRACK_SPATCH_DEFINES)'; \\\n-\t    if test x\"$$FLAGS\" != x\"`cat GIT-SPATCH-DEFINES 2>/dev/null`\" ; then \\\n-\t\techo >&2 \"    * new spatch flags\"; \\\n-\t\techo \"$$FLAGS\" >GIT-SPATCH-DEFINES; \\\n-            fi\n-\n-include config.mak.uname\n--include config.mak.autogen\n--include config.mak\n-\n-ifdef DEVELOPER\n-include config.mak.dev\n-endif\n-\n GIT-VERSION-FILE: FORCE\n \t@OLD=$$(cat $@ 2>/dev/null || :) && \\\n \t$(call version_gen,\"$(shell pwd)\",GIT-VERSION-FILE.in,$@) && \\\n\n-- \n2.51.0.536.g15c5d4f767.dirty\n\n"},{"id":"527043","messageId":"20250923-b4-pks-rust-breaking-change-v6-3-59076fee486a@pks.im","threadId":"64091","inReplyTo":"20250923-b4-pks-rust-breaking-change-v6-0-59076fee486a@pks.im","subject":"[PATCH v6 3/9] Makefile: introduce infrastructure to build internal Rust library","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-23T09:45:22Z","receivedAt":"2025-09-23T09:45:41Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Introduce infrastructure to build the internal Rust library. This\nmirrors the infrastructure we have added to Meson in the preceding\ncommit. Developers can enable the infrastructure by passing the new\n`WITH_RUST` build toggle.\n\nInspired-by: Ezekiel Newren <ezekielnewren@gmail.com>\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n .gitignore |  2 ++\n Makefile   | 37 +++++++++++++++++++++++++++++++++++++\n shared.mak |  1 +\n 3 files changed, 40 insertions(+)\n\ndiff --git a/.gitignore b/.gitignore\nindex 1803023427..0833453cf6 100644\n--- a/.gitignore\n+++ b/.gitignore\n@@ -1,4 +1,6 @@\n /fuzz_corpora\n+/target/\n+/Cargo.lock\n /GIT-BUILD-DIR\n /GIT-BUILD-OPTIONS\n /GIT-CFLAGS\ndiff --git a/Makefile b/Makefile\nindex 7e52625d75..e8518198fc 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -483,6 +483,14 @@ include shared.mak\n # Define LIBPCREDIR=/foo/bar if your PCRE header and library files are\n # in /foo/bar/include and /foo/bar/lib directories.\n #\n+# == Optional Rust support ==\n+#\n+# Define WITH_RUST if you want to include features and subsystems written in\n+# Rust into Git. For now, Rust is still an optional feature of the build\n+# process. With Git 3.0 though, Rust will always be enabled.\n+#\n+# Building Rust code requires Cargo.\n+#\n # == SHA-1 and SHA-256 defines ==\n #\n # === SHA-1 backend ===\n@@ -683,6 +691,7 @@ OBJECTS =\n OTHER_PROGRAMS =\n PROGRAM_OBJS =\n PROGRAMS =\n+RUST_SOURCES =\n EXCLUDED_PROGRAMS =\n SCRIPT_PERL =\n SCRIPT_PYTHON =\n@@ -918,6 +927,11 @@ TEST_SHELL_PATH = $(SHELL_PATH)\n LIB_FILE = libgit.a\n XDIFF_LIB = xdiff/lib.a\n REFTABLE_LIB = reftable/libreftable.a\n+ifdef DEBUG\n+RUST_LIB = target/debug/libgit.a\n+else\n+RUST_LIB = target/release/libgit.a\n+endif\n \n # xdiff and reftable libs may in turn depend on what is in libgit.a\n GITLIBS = common-main.o $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(LIB_FILE)\n@@ -943,6 +957,15 @@ BASIC_LDFLAGS =\n ARFLAGS = rcs\n PTHREAD_CFLAGS =\n \n+# Rust flags\n+CARGO_ARGS =\n+ifndef V\n+CARGO_ARGS += --quiet\n+endif\n+ifndef DEBUG\n+CARGO_ARGS += --release\n+endif\n+\n # For the 'sparse' target\n SPARSE_FLAGS ?= -std=gnu99 -D__STDC_NO_VLA__\n SP_EXTRA_FLAGS =\n@@ -1475,6 +1498,8 @@ CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/unit-test.o\n \n UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o\n \n+RUST_SOURCES += src/lib.rs\n+\n GIT-VERSION-FILE: FORCE\n \t@OLD=$$(cat $@ 2>/dev/null || :) && \\\n \t$(call version_gen,\"$(shell pwd)\",GIT-VERSION-FILE.in,$@) && \\\n@@ -1504,6 +1529,11 @@ endif\n ALL_CFLAGS = $(DEVELOPER_CFLAGS) $(CPPFLAGS) $(CFLAGS) $(CFLAGS_APPEND)\n ALL_LDFLAGS = $(LDFLAGS) $(LDFLAGS_APPEND)\n \n+ifdef WITH_RUST\n+BASIC_CFLAGS += -DWITH_RUST\n+GITLIBS += $(RUST_LIB)\n+endif\n+\n ifdef SANITIZE\n SANITIZERS := $(foreach flag,$(subst $(comma),$(space),$(SANITIZE)),$(flag))\n BASIC_CFLAGS += -fsanitize=$(SANITIZE) -fno-sanitize-recover=$(SANITIZE)\n@@ -2918,6 +2948,12 @@ scalar$X: scalar.o GIT-LDFLAGS $(GITLIBS)\n $(LIB_FILE): $(LIB_OBJS)\n \t$(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^\n \n+$(RUST_LIB): Cargo.toml $(RUST_SOURCES)\n+\t$(QUIET_CARGO)cargo build $(CARGO_ARGS)\n+\n+.PHONY: rust\n+rust: $(RUST_LIB)\n+\n $(XDIFF_LIB): $(XDIFF_OBJS)\n \t$(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^\n \n@@ -3768,6 +3804,7 @@ clean: profile-clean coverage-clean cocciclean\n \t$(RM) $(FUZZ_PROGRAMS)\n \t$(RM) $(SP_OBJ)\n \t$(RM) $(HCC)\n+\t$(RM) -r Cargo.lock target/\n \t$(RM) version-def.h\n \t$(RM) -r $(dep_dirs) $(compdb_dir) compile_commands.json\n \t$(RM) $(test_bindir_programs)\ndiff --git a/shared.mak b/shared.mak\nindex 5c7bc94785..0e7492076e 100644\n--- a/shared.mak\n+++ b/shared.mak\n@@ -56,6 +56,7 @@ ifndef V\n \tQUIET_MKDIR_P_PARENT  = @echo '   ' MKDIR -p $(@D);\n \n ## Used in \"Makefile\"\n+\tQUIET_CARGO    = @echo '   ' CARGO $@;\n \tQUIET_CC       = @echo '   ' CC $@;\n \tQUIET_AR       = @echo '   ' AR $@;\n \tQUIET_LINK     = @echo '   ' LINK $@;\n\n-- \n2.51.0.536.g15c5d4f767.dirty\n\n"},{"id":"527044","messageId":"20250923-b4-pks-rust-breaking-change-v6-4-59076fee486a@pks.im","threadId":"64091","inReplyTo":"20250923-b4-pks-rust-breaking-change-v6-0-59076fee486a@pks.im","subject":"[PATCH v6 4/9] help: report on whether or not Rust is enabled","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-23T09:45:23Z","receivedAt":"2025-09-23T09:45:44Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"We're about to introduce support for Rust into the core of Git, where\nsome (trivial) subsystems are converted to Rust. These subsystems will\nalso retain a C implementation though as Rust is not yet mandatory.\nConsequently, it now becomes possible for a Git version to have bugs\nthat are specific to whether or not it is built with Rust support\noverall.\n\nExpose information about whether or not Git was built with Rust via our\nbuild info. This means that both `git version --build-options`, but also\n`git bugreport` will now expose that bit of information. Hopefully, this\nshould make it easier for us to discover any Rust-specific issues.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n help.c | 6 ++++++\n 1 file changed, 6 insertions(+)\n\ndiff --git a/help.c b/help.c\nindex bb20498cfd..5854dd4a7e 100644\n--- a/help.c\n+++ b/help.c\n@@ -791,6 +791,12 @@ void get_version_info(struct strbuf *buf, int show_build_options)\n \t\tstrbuf_addf(buf, \"shell-path: %s\\n\", SHELL_PATH);\n \t\t/* NEEDSWORK: also save and output GIT-BUILD_OPTIONS? */\n \n+#if defined WITH_RUST\n+\t\tstrbuf_addstr(buf, \"rust: enabled\\n\");\n+#else\n+\t\tstrbuf_addstr(buf, \"rust: disabled\\n\");\n+#endif\n+\n \t\tif (fsmonitor_ipc__is_supported())\n \t\t\tstrbuf_addstr(buf, \"feature: fsmonitor--daemon\\n\");\n #if defined LIBCURL_VERSION\n\n-- \n2.51.0.536.g15c5d4f767.dirty\n\n"},{"id":"527045","messageId":"20250923-b4-pks-rust-breaking-change-v6-5-59076fee486a@pks.im","threadId":"64091","inReplyTo":"20250923-b4-pks-rust-breaking-change-v6-0-59076fee486a@pks.im","subject":"[PATCH v6 5/9] varint: use explicit width for integers","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-23T09:45:24Z","receivedAt":"2025-09-23T09:45:47Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The varint subsystem currently uses implcit widths for integers. On the\none hand we use `uintmax_t` for the actual value. On the other hand, we\nuse `int` for the length of the encoded varint.\n\nBoth of these have known maximum vaules, as we only support at most 16\nbytes when encoding varints. Thus, we know that we won't ever exceed\n`uint64_t` for the actual value and `uint8_t` for the prefix length.\n\nRefactor the code to use explicit widths. Besides making the logic\nplatform-independent, it also makes our life a bit easier in the next\ncommit, where we reimplement \"varint.c\" in Rust.\n\nSuggested-by: Ezekiel Newren <ezekielnewren@gmail.com>\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n dir.c        | 18 ++++++++++--------\n read-cache.c |  6 ++++--\n varint.c     |  6 +++---\n varint.h     |  4 ++--\n 4 files changed, 19 insertions(+), 15 deletions(-)\n\ndiff --git a/dir.c b/dir.c\nindex 71108ac79b7..0a67a99cb3d 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -3579,7 +3579,8 @@ static void write_one_dir(struct untracked_cache_dir *untracked,\n \tstruct stat_data stat_data;\n \tstruct strbuf *out = &wd->out;\n \tunsigned char intbuf[16];\n-\tunsigned int intlen, value;\n+\tunsigned int value;\n+\tuint8_t intlen;\n \tint i = wd->index++;\n \n \t/*\n@@ -3632,7 +3633,7 @@ void write_untracked_extension(struct strbuf *out, struct untracked_cache *untra\n \tstruct ondisk_untracked_cache *ouc;\n \tstruct write_data wd;\n \tunsigned char varbuf[16];\n-\tint varint_len;\n+\tuint8_t varint_len;\n \tconst unsigned hashsz = the_hash_algo->rawsz;\n \n \tCALLOC_ARRAY(ouc, 1);\n@@ -3738,7 +3739,7 @@ static int read_one_dir(struct untracked_cache_dir **untracked_,\n \tstruct untracked_cache_dir ud, *untracked;\n \tconst unsigned char *data = rd->data, *end = rd->end;\n \tconst unsigned char *eos;\n-\tunsigned int value;\n+\tuint64_t value;\n \tint i;\n \n \tmemset(&ud, 0, sizeof(ud));\n@@ -3830,7 +3831,8 @@ struct untracked_cache *read_untracked_extension(const void *data, unsigned long\n \tstruct read_data rd;\n \tconst unsigned char *next = data, *end = (const unsigned char *)data + sz;\n \tconst char *ident;\n-\tint ident_len;\n+\tuint64_t ident_len;\n+\tuint64_t varint_len;\n \tssize_t len;\n \tconst char *exclude_per_dir;\n \tconst unsigned hashsz = the_hash_algo->rawsz;\n@@ -3867,8 +3869,8 @@ struct untracked_cache *read_untracked_extension(const void *data, unsigned long\n \tif (next >= end)\n \t\tgoto done2;\n \n-\tlen = decode_varint(&next);\n-\tif (next > end || len == 0)\n+\tvarint_len = decode_varint(&next);\n+\tif (next > end || varint_len == 0)\n \t\tgoto done2;\n \n \trd.valid      = ewah_new();\n@@ -3877,9 +3879,9 @@ struct untracked_cache *read_untracked_extension(const void *data, unsigned long\n \trd.data\t      = next;\n \trd.end\t      = end;\n \trd.index      = 0;\n-\tALLOC_ARRAY(rd.ucd, len);\n+\tALLOC_ARRAY(rd.ucd, varint_len);\n \n-\tif (read_one_dir(&uc->root, &rd) || rd.index != len)\n+\tif (read_one_dir(&uc->root, &rd) || rd.index != varint_len)\n \t\tgoto done;\n \n \tnext = rd.data;\ndiff --git a/read-cache.c b/read-cache.c\nindex 06ad74db228..41b44148b1e 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -1807,7 +1807,7 @@ static struct cache_entry *create_from_disk(struct mem_pool *ce_mem_pool,\n \n \tif (expand_name_field) {\n \t\tconst unsigned char *cp = (const unsigned char *)name;\n-\t\tsize_t strip_len, previous_len;\n+\t\tuint64_t strip_len, previous_len;\n \n \t\t/* If we're at the beginning of a block, ignore the previous name */\n \t\tstrip_len = decode_varint(&cp);\n@@ -2655,8 +2655,10 @@ static int ce_write_entry(struct hashfile *f, struct cache_entry *ce,\n \t\thashwrite(f, ce->name, len);\n \t\thashwrite(f, padding, align_padding_size(size, len));\n \t} else {\n-\t\tint common, to_remove, prefix_size;\n+\t\tint common, to_remove;\n+\t\tuint8_t prefix_size;\n \t\tunsigned char to_remove_vi[16];\n+\n \t\tfor (common = 0;\n \t\t     (common < previous_name->len &&\n \t\t      ce->name[common] &&\ndiff --git a/varint.c b/varint.c\nindex 409c4977a1e..03cd54416b6 100644\n--- a/varint.c\n+++ b/varint.c\n@@ -1,11 +1,11 @@\n #include \"git-compat-util.h\"\n #include \"varint.h\"\n \n-uintmax_t decode_varint(const unsigned char **bufp)\n+uint64_t decode_varint(const unsigned char **bufp)\n {\n \tconst unsigned char *buf = *bufp;\n \tunsigned char c = *buf++;\n-\tuintmax_t val = c & 127;\n+\tuint64_t val = c & 127;\n \twhile (c & 128) {\n \t\tval += 1;\n \t\tif (!val || MSB(val, 7))\n@@ -17,7 +17,7 @@ uintmax_t decode_varint(const unsigned char **bufp)\n \treturn val;\n }\n \n-int encode_varint(uintmax_t value, unsigned char *buf)\n+uint8_t encode_varint(uint64_t value, unsigned char *buf)\n {\n \tunsigned char varint[16];\n \tunsigned pos = sizeof(varint) - 1;\ndiff --git a/varint.h b/varint.h\nindex f78bb0ca528..eb401935bd2 100644\n--- a/varint.h\n+++ b/varint.h\n@@ -1,7 +1,7 @@\n #ifndef VARINT_H\n #define VARINT_H\n \n-int encode_varint(uintmax_t, unsigned char *);\n-uintmax_t decode_varint(const unsigned char **);\n+uint8_t encode_varint(uint64_t, unsigned char *);\n+uint64_t decode_varint(const unsigned char **);\n \n #endif /* VARINT_H */\n\n-- \n2.51.0.536.g15c5d4f767.dirty\n\n"},{"id":"527046","messageId":"20250923-b4-pks-rust-breaking-change-v6-6-59076fee486a@pks.im","threadId":"64091","inReplyTo":"20250923-b4-pks-rust-breaking-change-v6-0-59076fee486a@pks.im","subject":"[PATCH v6 6/9] varint: reimplement as test balloon for Rust","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-23T09:45:25Z","receivedAt":"2025-09-23T09:45:50Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Implement a trivial test balloon for our Rust build infrastructure by\nreimplementing the \"varint.c\" subsystem in Rust. This subsystem is\nchosen because it is trivial to convert and because it doesn't have any\ndependencies to other components of Git.\n\nIf support for Rust is enabled, we stop compiling \"varint.c\" and instead\ncompile and use \"src/varint.rs\".\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n Makefile        |  3 ++\n meson.build     |  5 +++-\n src/lib.rs      |  1 +\n src/meson.build |  1 +\n src/varint.rs   | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n 5 files changed, 101 insertions(+), 1 deletion(-)\n\ndiff --git a/Makefile b/Makefile\nindex e8518198fcb..d7d6f6eefcb 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -1307,7 +1307,9 @@ LIB_OBJS += urlmatch.o\n LIB_OBJS += usage.o\n LIB_OBJS += userdiff.o\n LIB_OBJS += utf8.o\n+ifndef WITH_RUST\n LIB_OBJS += varint.o\n+endif\n LIB_OBJS += version.o\n LIB_OBJS += versioncmp.o\n LIB_OBJS += walker.o\n@@ -1499,6 +1501,7 @@ CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/unit-test.o\n UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o\n \n RUST_SOURCES += src/lib.rs\n+RUST_SOURCES += src/varint.rs\n \n GIT-VERSION-FILE: FORCE\n \t@OLD=$$(cat $@ 2>/dev/null || :) && \\\ndiff --git a/meson.build b/meson.build\nindex 234a9e9d6fd..37dfa286017 100644\n--- a/meson.build\n+++ b/meson.build\n@@ -522,7 +522,6 @@ libgit_sources = [\n   'usage.c',\n   'userdiff.c',\n   'utf8.c',\n-  'varint.c',\n   'version.c',\n   'versioncmp.c',\n   'walker.c',\n@@ -1707,6 +1706,10 @@ rust_option = get_option('rust').disable_auto_if(not cargo.found())\n if rust_option.allowed()\n   subdir('src')\n   libgit_c_args += '-DWITH_RUST'\n+else\n+  libgit_sources += [\n+    'varint.c',\n+  ]\n endif\n \n libgit = declare_dependency(\ndiff --git a/src/lib.rs b/src/lib.rs\nindex e69de29bb2d..9da70d8b57d 100644\n--- a/src/lib.rs\n+++ b/src/lib.rs\n@@ -0,0 +1 @@\n+pub mod varint;\ndiff --git a/src/meson.build b/src/meson.build\nindex 734de0b4fa9..b19ef4c0b51 100644\n--- a/src/meson.build\n+++ b/src/meson.build\n@@ -1,5 +1,6 @@\n libgit_rs_sources = [\n   'lib.rs',\n+  'varint.rs',\n ]\n \n # Unfortunately we must use a wrapper command to move the output file into the\ndiff --git a/src/varint.rs b/src/varint.rs\nnew file mode 100644\nindex 00000000000..6e610bdd8e0\n--- /dev/null\n+++ b/src/varint.rs\n@@ -0,0 +1,92 @@\n+#[no_mangle]\n+pub unsafe extern \"C\" fn decode_varint(bufp: *mut *const u8) -> u64 {\n+    let mut buf = *bufp;\n+    let mut c = *buf;\n+    let mut val = u64::from(c & 127);\n+\n+    buf = buf.add(1);\n+\n+    while (c & 128) != 0 {\n+        val = val.wrapping_add(1);\n+        if val == 0 || val.leading_zeros() < 7 {\n+            return 0; // overflow\n+        }\n+\n+        c = *buf;\n+        buf = buf.add(1);\n+\n+        val = (val << 7) + u64::from(c & 127);\n+    }\n+\n+    *bufp = buf;\n+    val\n+}\n+\n+#[no_mangle]\n+pub unsafe extern \"C\" fn encode_varint(value: u64, buf: *mut u8) -> u8 {\n+    let mut varint: [u8; 16] = [0; 16];\n+    let mut pos = varint.len() - 1;\n+\n+    varint[pos] = (value & 127) as u8;\n+\n+    let mut value = value >> 7;\n+    while value != 0 {\n+        pos -= 1;\n+        value -= 1;\n+        varint[pos] = 128 | (value & 127) as u8;\n+        value >>= 7;\n+    }\n+\n+    if !buf.is_null() {\n+        std::ptr::copy_nonoverlapping(varint.as_ptr().add(pos), buf, varint.len() - pos);\n+    }\n+\n+    (varint.len() - pos) as u8\n+}\n+\n+#[cfg(test)]\n+mod tests {\n+    use super::*;\n+\n+    #[test]\n+    fn test_decode_varint() {\n+        unsafe {\n+            assert_eq!(decode_varint(&mut [0x00].as_slice().as_ptr()), 0);\n+            assert_eq!(decode_varint(&mut [0x01].as_slice().as_ptr()), 1);\n+            assert_eq!(decode_varint(&mut [0x7f].as_slice().as_ptr()), 127);\n+            assert_eq!(decode_varint(&mut [0x80, 0x00].as_slice().as_ptr()), 128);\n+            assert_eq!(decode_varint(&mut [0x80, 0x01].as_slice().as_ptr()), 129);\n+            assert_eq!(decode_varint(&mut [0x80, 0x7f].as_slice().as_ptr()), 255);\n+\n+            // Overflows are expected to return 0.\n+            assert_eq!(decode_varint(&mut [0x88; 16].as_slice().as_ptr()), 0);\n+        }\n+    }\n+\n+    #[test]\n+    fn test_encode_varint() {\n+        unsafe {\n+            let mut varint: [u8; 16] = [0; 16];\n+\n+            assert_eq!(encode_varint(0, std::ptr::null_mut()), 1);\n+\n+            assert_eq!(encode_varint(0, varint.as_mut_slice().as_mut_ptr()), 1);\n+            assert_eq!(varint, [0; 16]);\n+\n+            assert_eq!(encode_varint(10, varint.as_mut_slice().as_mut_ptr()), 1);\n+            assert_eq!(varint, [10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n+\n+            assert_eq!(encode_varint(127, varint.as_mut_slice().as_mut_ptr()), 1);\n+            assert_eq!(varint, [127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n+\n+            assert_eq!(encode_varint(128, varint.as_mut_slice().as_mut_ptr()), 2);\n+            assert_eq!(varint, [128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n+\n+            assert_eq!(encode_varint(129, varint.as_mut_slice().as_mut_ptr()), 2);\n+            assert_eq!(varint, [128, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n+\n+            assert_eq!(encode_varint(255, varint.as_mut_slice().as_mut_ptr()), 2);\n+            assert_eq!(varint, [128, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n+        }\n+    }\n+}\n\n-- \n2.51.0.536.g15c5d4f767.dirty\n\n"},{"id":"527047","messageId":"20250923-b4-pks-rust-breaking-change-v6-7-59076fee486a@pks.im","threadId":"64091","inReplyTo":"20250923-b4-pks-rust-breaking-change-v6-0-59076fee486a@pks.im","subject":"[PATCH v6 7/9] BreakingChanges: announce Rust becoming mandatory","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-23T09:45:26Z","receivedAt":"2025-09-23T09:45:53Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Over the last couple of years the appetite for bringing Rust into the\ncodebase has grown significantly across the developer base. Introducing\nRust is a major change though and has ramifications for the whole\necosystem:\n\n  - Some platforms have a Rust toolchain available, but have not yet\n    integrated it into their build infrastructure.\n\n  - Some platforms don't have any support for Rust at all.\n\n  - Some platforms may have to figure out how to fit Rust into their\n    bootstrapping sequence.\n\nDue to this, and given that Git is a critical piece of infrastructure\nfor the whole industry, we cannot just introduce such a heavyweight\ndependency without doing our due diligence.\n\nInstead, preceding commits have introduced a test balloon into our build\ninfrastructure that convert one tiny subsystem to use Rust. For now,\nusing Rust to build that subsystem is entirely optional -- if no Rust\nsupport is available, we continue to use the C implementation. This test\nballoon has the intention to give distributions time and let them ease\ninto our adoption of Rust.\n\nHaving multiple implementations of the same subsystem is not sustainable\nthough, and the plan is to eventually be able to use Rust freely all\nacross our codebase. As such, there is the intent to make Rust become a\nmandatory part of our build process.\n\nAdd an announcement to our breaking changes that Rust will become\nmandatory in Git 3.0. A (very careful and non-binding) estimate might be\nthat this major release might be released in the second half of next\nyear, which should give distributors enough time to prepare for the\nchange.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n Documentation/BreakingChanges.adoc | 45 ++++++++++++++++++++++++++++++++++++++\n 1 file changed, 45 insertions(+)\n\ndiff --git a/Documentation/BreakingChanges.adoc b/Documentation/BreakingChanges.adoc\nindex f8d2eba061..d249e604b5 100644\n--- a/Documentation/BreakingChanges.adoc\n+++ b/Documentation/BreakingChanges.adoc\n@@ -165,6 +165,51 @@ A prerequisite for this change is that the ecosystem is ready to support the\n \"reftable\" format. Most importantly, alternative implementations of Git like\n JGit, libgit2 and Gitoxide need to support it.\n \n+* Git will require Rust as a mandatory part of the build process. While Git\n+  already started to adopt Rust in Git 2.49, all parts written in Rust are\n+  optional for the time being. This includes:\n++\n+  ** The Rust wrapper around libgit.a that is part of \"contrib/\" and which has\n+     been introduced in Git 2.49.\n+  ** Subsystems that have an alternative implementation in Rust to test\n+     interoperability between our C and Rust codebase.\n+  ** Newly written features that are not mission critical for a fully functional\n+     Git client.\n++\n+These changes are meant as test balloons to allow distributors of Git to prepare\n+for Rust becoming a mandatory part of the build process. There will be multiple\n+milestones for the introduction of Rust:\n++\n+--\n+1. Initially, with Git 2.52, support for Rust will be auto-detected by Meson and\n+   disabled in our Makefile so that the project can sort out the initial\n+   infrastructure.\n+2. In Git 2.53, both build systems will default-enable support for Rust.\n+   Consequently, builds will break by default if Rust is not available on the\n+   build host. The use of Rust can still be explicitly disabled via build\n+   flags.\n+3. In Git 3.0, the build options will be removed and support for Rust is\n+   mandatory.\n+--\n++\n+You can explicitly ask both Meson and our Makefile-based system to enable Rust\n+by saying `meson configure -Drust=enabled` and `make WITH_RUST=YesPlease`,\n+respectively.\n++\n+The Git project will declare the last version before Git 3.0 to be a long-term\n+support release. This long-term release will receive important bug fixes for at\n+least four release cycles and security fixes for six release cycles. The Git\n+project will hand over maintainership of the long-term release to distributors\n+in case they need to extend the life of that long-term release even further. In\n+that case, the backporting process will be handled by these distributors, but\n+the long-term release tags will be created in the canonical Git repository.\n++\n+We will evaluate the impact on downstream distributions before making Rust\n+mandatory in Git 3.0. If we see that the impact on downstream distributions\n+would be significant, we may decide to defer this breaking change to a\n+subsequent minor release. This evaluation will also take into account our own\n+learnings with how painful it is to keep Rust an optional component.\n+\n === Removals\n \n * Support for grafting commits has long been superseded by git-replace(1).\n\n-- \n2.51.0.536.g15c5d4f767.dirty\n\n"},{"id":"527048","messageId":"20250923-b4-pks-rust-breaking-change-v6-8-59076fee486a@pks.im","threadId":"64091","inReplyTo":"20250923-b4-pks-rust-breaking-change-v6-0-59076fee486a@pks.im","subject":"[PATCH v6 8/9] ci: convert \"pedantic\" job into full build with breaking changes","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-23T09:45:27Z","receivedAt":"2025-09-23T09:45:56Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The \"pedantic\" CI job is building on Fedora with `DEVOPTS=pedantic`.\nThis build flag doesn't do anything anymore starting with 6a8cbc41ba\n(developer: enable pedantic by default, 2021-09-03), where we have\nflipped the default so that developers have to opt-out of pedantic\nbuilds via the \"no-pedantic\" option. As such, all this job really does\nis to do a normal build on Fedora, which isn't all that interesting.\n\nConvert that job into a full build-and-test job that uses Meson with\nbreaking changes enabled. This plugs two gaps:\n\n  - We now test on another distro that we didn't run tests on\n    beforehand.\n\n  - We verify that breaking changes work as expected with Meson.\n\nFurthermore, in a subsequent commit we'll modify both jobs that use\nbreaking changes to also enable Rust. By converting the Fedora job to\nuse Meson, we ensure that we test our Rust build infrastructure for both\nbuild systems.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n .github/workflows/main.yml |  4 ++--\n .gitlab-ci.yml             |  4 ++--\n ci/install-dependencies.sh |  6 +++++-\n ci/run-build-and-tests.sh  | 29 ++++++++---------------------\n 4 files changed, 17 insertions(+), 26 deletions(-)\n\ndiff --git a/.github/workflows/main.yml b/.github/workflows/main.yml\nindex d122e79415..393ea4d1cc 100644\n--- a/.github/workflows/main.yml\n+++ b/.github/workflows/main.yml\n@@ -379,6 +379,8 @@ jobs:\n         - jobname: linux-breaking-changes\n           cc: gcc\n           image: ubuntu:rolling\n+        - jobname: fedora-breaking-changes-meson\n+          image: fedora:latest\n         - jobname: linux-leaks\n           image: ubuntu:rolling\n           cc: gcc\n@@ -396,8 +398,6 @@ jobs:\n         # Supported until 2025-04-02.\n         - jobname: linux32\n           image: i386/ubuntu:focal\n-        - jobname: pedantic\n-          image: fedora:latest\n         # A RHEL 8 compatible distro.  Supported until 2029-05-31.\n         - jobname: almalinux-8\n           image: almalinux:8\ndiff --git a/.gitlab-ci.yml b/.gitlab-ci.yml\nindex af10ebb59a..4248506909 100644\n--- a/.gitlab-ci.yml\n+++ b/.gitlab-ci.yml\n@@ -45,6 +45,8 @@ test:linux:\n       - jobname: linux-breaking-changes\n         image: ubuntu:20.04\n         CC: gcc\n+      - jobname: fedora-breaking-changes-meson\n+        image: fedora:latest\n       - jobname: linux-TEST-vars\n         image: ubuntu:20.04\n         CC: gcc\n@@ -58,8 +60,6 @@ test:linux:\n       - jobname: linux-asan-ubsan\n         image: ubuntu:rolling\n         CC: clang\n-      - jobname: pedantic\n-        image: fedora:latest\n       - jobname: linux-musl-meson\n         image: alpine:latest\n       - jobname: linux32\ndiff --git a/ci/install-dependencies.sh b/ci/install-dependencies.sh\nindex d061a47293..35bd05b85b 100755\n--- a/ci/install-dependencies.sh\n+++ b/ci/install-dependencies.sh\n@@ -30,8 +30,12 @@ alpine-*)\n \t\tbash cvs gnupg perl-cgi perl-dbd-sqlite perl-io-tty >/dev/null\n \t;;\n fedora-*|almalinux-*)\n+\tcase \"$jobname\" in\n+\t*-meson)\n+\t\tMESON_DEPS=\"meson ninja\";;\n+\tesac\n \tdnf -yq update >/dev/null &&\n-\tdnf -yq install shadow-utils sudo make gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel >/dev/null\n+\tdnf -yq install shadow-utils sudo make pkg-config gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel $MESON_DEPS >/dev/null\n \t;;\n ubuntu-*|i386/ubuntu-*|debian-*)\n \t# Required so that apt doesn't wait for user input on certain packages.\ndiff --git a/ci/run-build-and-tests.sh b/ci/run-build-and-tests.sh\nindex 01823fd0f1..3680446649 100755\n--- a/ci/run-build-and-tests.sh\n+++ b/ci/run-build-and-tests.sh\n@@ -5,12 +5,11 @@\n \n . ${0%/*}/lib.sh\n \n-run_tests=t\n-\n case \"$jobname\" in\n-linux-breaking-changes)\n+fedora-breaking-changes-musl|linux-breaking-changes)\n \texport GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main\n \texport WITH_BREAKING_CHANGES=YesPlease\n+\tMESONFLAGS=\"$MESONFLAGS -Dbreaking_changes=true\"\n \t;;\n linux-TEST-vars)\n \texport OPENSSL_SHA1_UNSAFE=YesPlease\n@@ -36,12 +35,6 @@ linux-sha256)\n linux-reftable|linux-reftable-leaks|osx-reftable)\n \texport GIT_TEST_DEFAULT_REF_FORMAT=reftable\n \t;;\n-pedantic)\n-\t# Don't run the tests; we only care about whether Git can be\n-\t# built.\n-\texport DEVOPTS=pedantic\n-\trun_tests=\n-\t;;\n esac\n \n case \"$jobname\" in\n@@ -54,21 +47,15 @@ case \"$jobname\" in\n \t\t-Dtest_output_directory=\"${TEST_OUTPUT_DIRECTORY:-$(pwd)/t}\" \\\n \t\t$MESONFLAGS\n \tgroup \"Build\" meson compile -C build --\n-\tif test -n \"$run_tests\"\n-\tthen\n-\t\tgroup \"Run tests\" meson test -C build --print-errorlogs --test-args=\"$GIT_TEST_OPTS\" || (\n-\t\t\t./t/aggregate-results.sh \"${TEST_OUTPUT_DIRECTORY:-t}/test-results\"\n-\t\t\thandle_failed_tests\n-\t\t)\n-\tfi\n+\tgroup \"Run tests\" meson test -C build --print-errorlogs --test-args=\"$GIT_TEST_OPTS\" || (\n+\t\t./t/aggregate-results.sh \"${TEST_OUTPUT_DIRECTORY:-t}/test-results\"\n+\t\thandle_failed_tests\n+\t)\n \t;;\n *)\n \tgroup Build make\n-\tif test -n \"$run_tests\"\n-\tthen\n-\t\tgroup \"Run tests\" make test ||\n-\t\thandle_failed_tests\n-\tfi\n+\tgroup \"Run tests\" make test ||\n+\thandle_failed_tests\n \t;;\n esac\n \n\n-- \n2.51.0.536.g15c5d4f767.dirty\n\n"},{"id":"527049","messageId":"20250923-b4-pks-rust-breaking-change-v6-9-59076fee486a@pks.im","threadId":"64091","inReplyTo":"20250923-b4-pks-rust-breaking-change-v6-0-59076fee486a@pks.im","subject":"[PATCH v6 9/9] ci: enable Rust for breaking-changes jobs","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-23T09:45:28Z","receivedAt":"2025-09-23T09:45:59Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Enable Rust for our breaking-changes jobs so that we can verify that the\nbuild infrastructure and the converted Rust subsystems work as expected.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n ci/install-dependencies.sh | 4 ++--\n ci/run-build-and-tests.sh  | 2 ++\n 2 files changed, 4 insertions(+), 2 deletions(-)\n\ndiff --git a/ci/install-dependencies.sh b/ci/install-dependencies.sh\nindex 35bd05b85b..0d3aa496fc 100755\n--- a/ci/install-dependencies.sh\n+++ b/ci/install-dependencies.sh\n@@ -35,7 +35,7 @@ fedora-*|almalinux-*)\n \t\tMESON_DEPS=\"meson ninja\";;\n \tesac\n \tdnf -yq update >/dev/null &&\n-\tdnf -yq install shadow-utils sudo make pkg-config gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel $MESON_DEPS >/dev/null\n+\tdnf -yq install shadow-utils sudo make pkg-config gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel $MESON_DEPS cargo >/dev/null\n \t;;\n ubuntu-*|i386/ubuntu-*|debian-*)\n \t# Required so that apt doesn't wait for user input on certain packages.\n@@ -62,7 +62,7 @@ ubuntu-*|i386/ubuntu-*|debian-*)\n \t\tmake libssl-dev libcurl4-openssl-dev libexpat-dev wget sudo default-jre \\\n \t\ttcl tk gettext zlib1g-dev perl-modules liberror-perl libauthen-sasl-perl \\\n \t\tlibemail-valid-perl libio-pty-perl libio-socket-ssl-perl libnet-smtp-ssl-perl libdbd-sqlite3-perl libcgi-pm-perl \\\n-\t\tlibsecret-1-dev libpcre2-dev meson ninja-build pkg-config \\\n+\t\tlibsecret-1-dev libpcre2-dev meson ninja-build pkg-config cargo \\\n \t\t${CC_PACKAGE:-${CC:-gcc}} $PYTHON_PACKAGE\n \n \tcase \"$distro\" in\ndiff --git a/ci/run-build-and-tests.sh b/ci/run-build-and-tests.sh\nindex 3680446649..c718bd101a 100755\n--- a/ci/run-build-and-tests.sh\n+++ b/ci/run-build-and-tests.sh\n@@ -9,7 +9,9 @@ case \"$jobname\" in\n fedora-breaking-changes-musl|linux-breaking-changes)\n \texport GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main\n \texport WITH_BREAKING_CHANGES=YesPlease\n+\texport WITH_RUST=YesPlease\n \tMESONFLAGS=\"$MESONFLAGS -Dbreaking_changes=true\"\n+\tMESONFLAGS=\"$MESONFLAGS -Drust=enabled\"\n \t;;\n linux-TEST-vars)\n \texport OPENSSL_SHA1_UNSAFE=YesPlease\n\n-- \n2.51.0.536.g15c5d4f767.dirty\n\n"},{"id":"527078","messageId":"xmqqy0q5p82c.fsf@gitster.g","threadId":"64091","inReplyTo":"aNIoFePhTc5vGc_-@pks.im","subject":"Re: [PATCH v5 7/9] BreakingChanges: announce Rust becoming mandatory","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-09-23T14:17:15Z","receivedAt":"2025-09-23T14:17:18Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> We have made other breaking changes conditional on the wider ecosystem.\n> For example, using reftable by default is conditioned on the ecosystem\n> having catched up and supporting this new format.\n>\n> Do we maybe want to do the same with Rust? We can for example add\n> something like the following paragraph:\n>\n>     We will carefully evaluate the impact on downstream distributions\n>     before making Rust mandatory in Git 3.0. If we see that the impact\n>     on downstream distributions would be significant, we may decide to\n>     defer this breaking change. This will also take into account our own\n>     learnings with how painful it is to keep Rust an optional component.\n>\n> The intent would be to alert distributors, but not \"blindly\" pull the\n> trigger. Instead, we should take a step back and evaluate both how the\n> Rust ecosystem looks like at the Git 3.0 boundary and how painful it is\n> for us to keep it as an optional component.\n\nI have always been assuming that we are prepared to change course if\nthat is necessary and though that something like that goes without\nsaying, but if you want to add it to the document, I am perfectly\nfine.  It should apply not just Rust but all other entries we list.\n\nThanks.\n"},{"id":"527079","messageId":"xmqqqzvxp7ej.fsf@gitster.g","threadId":"64091","inReplyTo":"aNIw23JzQE1vz2JD@pks.im","subject":"Re: [PATCH RFC v4 7/9] BreakingChanges: announce Rust becoming mandatory","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-09-23T14:31:32Z","receivedAt":"2025-09-23T14:31:36Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> On Mon, Sep 22, 2025 at 09:24:26AM -0700, Junio C Hamano wrote:\n>> Patrick Steinhardt <ps@pks.im> writes:\n>> >\n>> > I think the most important part here is that this community-supported\n>> > LTS release should still live in the canonical repositories. We should\n>> > avoid the situation where we hand over maintainership to such a degree\n>> > that the end result (the tagged LTS release) lives somewhere else.\n>> \n>> Why is it a bad thing?  The official repository can have a README.md\n>> with a single entry \"maintenance releases for Git 2.98 LTS (most\n>> notably with no Rust requirements) are found at this separate site\".\n\nI've been hoping that the relationship between LTS and the main\nproject would be similar to the one between Git for Windows and the\nmain project.  A friendly fork, that is led by competent folks who\nare familiar with what is happening in the main project and are\ntrusted by their users.  They carry many changes on top of what the\nmain project has produced, many of them may not have been submit to\nthe main projecte for approval, and the main project does not even\nfeel the need to approve their changes, simply because it trust the\nfriendly fork.\n\nI was hoping that anybody who read my message, from a later\nreference to the coordinated disclosure example that lists the main\nproject, GfW, and LTS, as three friendly equals, would understand\nthat it was my assumption, but it seems that what you depict is\nvastly different.\n\n> There's a couple reasons:\n>\n>   - The LTS maintainer may not be as familiar with the Git codebase as\n>   - The LTS maintainer may not be as trusted as other regulars on the\n\nIf you assume that you can only get incompetent folks who would not\nbe trusted by their users by their own ability and dedication, I do\nnot think an endorsement by the main project would help them gain\ntrust at all.  All it would do to force the main project to blindly\nsign their output is to tarnish the brand of the main project.\n\nIn other words, you are assuming that no competent folks would want\nto be the \"LTS maintainer\"(s), and you are arguing that if we really\nwant a \"Rustless Git\", which will be used by the general public, to\nexist, we should be the ones that are working on it.\n\n>> edge.  Most importantly, a coordinated disclosure would say that the\n>> update to versions of\n>> \n>>  - Git 3.0 to Git 3.4 are found $HERE, \n>>  - Git for Windows 3.0, 3.2, and 3.4 are found $THERE\n>>  - Git 2.98 are found $COMMUNITY_LTS\n>> \n>> to make sure that people know where to find their updates.\n>> \n>> So, no, I do not think we should unnecessarily mix community LTS and\n>> the main project.\n>\n> How about the following tradeoff: the community LTS is developed outside\n> of the usual Git workflow, for example on a forge, so that the LTS\n> maintainers can work in their preferred flow. But eventually, once they\n> want to do a release they send a pull request to the Git mailing list\n> and then the tag lives in the canonical Git repository.\n\nI do not think, with your assumption that LTS maintainer(s) are\nincompetent ones that cannot gain users' trust by themselves, such\nan arrangement would work.  Its only effect would be to tarnish the\nbrand of the main project if we rubber stamp endorse their ware.\n\n"},{"id":"527090","messageId":"d323c453-a800-413d-82d6-b0db0a4b76c0@gmail.com","threadId":"64091","inReplyTo":"20250923-b4-pks-rust-breaking-change-v6-7-59076fee486a@pks.im","subject":"Re: [PATCH v6 7/9] BreakingChanges: announce Rust becoming mandatory","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2025-09-23T15:29:07Z","receivedAt":"2025-09-23T15:29:12Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Patrick\n\nOn 23/09/2025 10:45, Patrick Steinhardt wrote:\n> ++\n> +The Git project will declare the last version before Git 3.0 to be a long-term\n> +support release. This long-term release will receive important bug fixes for at\n> +least four release cycles and security fixes for six release cycles. The Git\n> +project will hand over maintainership of the long-term release to distributors\n> +in case they need to extend the life of that long-term release even further. In\n> +that case, the backporting process will be handled by these distributors, but\n> +the long-term release tags will be created in the canonical Git repository.\n> ++\n> +We will evaluate the impact on downstream distributions before making Rust\n> +mandatory in Git 3.0. If we see that the impact on downstream distributions\n> +would be significant, we may decide to defer this breaking change to a\n> +subsequent minor release. This evaluation will also take into account our own\n> +learnings with how painful it is to keep Rust an optional component.\n\nI think this last paragraph is a welcome addition as it makes it clear \nwe're not going to blindly pursue rust if it causes widespread problems. \nPersonally I'd say \"experience\" rather than \"learnings\" but that's \nprobably me being a grumpy pedant.\n\nThanks\n\nPhillip\n\n"},{"id":"527108","messageId":"xmqqecrxoz5h.fsf@gitster.g","threadId":"64091","inReplyTo":"d323c453-a800-413d-82d6-b0db0a4b76c0@gmail.com","subject":"Re: [PATCH v6 7/9] BreakingChanges: announce Rust becoming mandatory","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-09-23T17:29:46Z","receivedAt":"2025-09-23T17:29:51Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Phillip Wood <phillip.wood123@gmail.com> writes:\n\n>> +We will evaluate the impact on downstream distributions before making Rust\n>> +mandatory in Git 3.0. If we see that the impact on downstream distributions\n>> +would be significant, we may decide to defer this breaking change to a\n>> +subsequent minor release. This evaluation will also take into account our own\n>> +learnings with how painful it is to keep Rust an optional component.\n>\n> I think this last paragraph is a welcome addition as it makes it clear\n> we're not going to blindly pursue rust if it causes widespread\n> problems. Personally I'd say \"experience\" rather than \"learnings\" but\n> that's probably me being a grumpy pedant.\n\nIf this transition turns out to be way too disruptive even for the\n3.0 that promises big changes anyway, can \"this breaking change\"\nrealistically be \"deferred\" to a subsequent \"minor\" release?\n\nThe only way I can think of that is permissible in a minor release\nwould be to pear it down so much that it no longer is disruptive,\nbut that would be very different from \"this breaking change\"\nanymore.\n\nOr is this talking about waiting until the downstream distribions\neither die out without adding Rust support or start supporting Rust?\nThat, except for the risk of having to wait forever, might work, but\nthen to surviving distros, it would no longer be a \"breaking\" change\neven if we ship the same change as \"this breaking change\", right?\n\nI don't know.  To me, the last sentence sounds like reserving the\nright to later say \"we learned that trying to support opt-in Rust\ncomponent that we have to (partially) replicate in C is so painful,\nso we won't keep Rust an optional component\".\n\n"},{"id":"527137","messageId":"CAH=ZcbALjKY+=TQfv1L4PsAyC=-fxNdi8PhSFnXq9G5zcVtkCQ@mail.gmail.com","threadId":"64091","inReplyTo":"20250923-b4-pks-rust-breaking-change-v6-0-59076fee486a@pks.im","subject":"Re: [PATCH v6 0/9] Introduce Rust and announce that it will become mandatory","fromName":"Ezekiel Newren","fromEmail":"ezekielnewren@gmail.com","sentAt":"2025-09-23T20:15:35Z","receivedAt":"2025-09-23T20:15:48Z","isPatch":true,"sender":{"key":"ezekielnewren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/18313324?v=4"},"body":"On Tue, Sep 23, 2025 at 3:45 AM Patrick Steinhardt <ps@pks.im> wrote:\nYour patch series has 2 critical problems:\n  * meson doesn't check for \"is windows and using msvc\" -> <crate>.lib\nelse lib<crate>.a\n  * Using the name \"git\" for the crate is problematic because both\nMake and Meson already produce libgit.a which is different from the\nlibgit.a that cargo is producing. Change the name in Cargo.toml from\n\"git\" to \"gitcore\".\n\nI created some temporary patches on top of this patch series that\nalways forces Rust and then pushed it to GitHub. The only target that\nfailed was windows building with meson + msvc, everything else\nincluding the 32 bit linux target passed.\n\nI have some nitpicks about varint, but they're not worth mentioning\nhere. Fix those 2 points and you'll have my seal of approval for this\npatch series.\n"},{"id":"527170","messageId":"aNN7dG6oLrv2Mokq@pks.im","threadId":"64091","inReplyTo":"CAH=ZcbALjKY+=TQfv1L4PsAyC=-fxNdi8PhSFnXq9G5zcVtkCQ@mail.gmail.com","subject":"Re: [PATCH v6 0/9] Introduce Rust and announce that it will become mandatory","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-24T05:02:44Z","receivedAt":"2025-09-24T05:02:53Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Tue, Sep 23, 2025 at 02:15:35PM -0600, Ezekiel Newren wrote:\n> On Tue, Sep 23, 2025 at 3:45 AM Patrick Steinhardt <ps@pks.im> wrote:\n> Your patch series has 2 critical problems:\n>   * meson doesn't check for \"is windows and using msvc\" -> <crate>.lib\n> else lib<crate>.a\n\nI didn't wire Windows up yet, so this is a known omission. It's not\nhandled in the Makefile yet, either. My plan here was to tackle Windows\nsupport as the immediate next step once this patch series lands.\n\nWould that be fine with you?\n\n>   * Using the name \"git\" for the crate is problematic because both\n> Make and Meson already produce libgit.a which is different from the\n> libgit.a that cargo is producing. Change the name in Cargo.toml from\n> \"git\" to \"gitcore\".\n\nI wasn't quite happy with the \"git\" name anyway, so I'll happily take\n\"gitcore\" instead.\n\nThanks!\n\nPatrick\n"},{"id":"527171","messageId":"aNN7izfqBprtoAcK@pks.im","threadId":"64091","inReplyTo":"xmqqecrxoz5h.fsf@gitster.g","subject":"Re: [PATCH v6 7/9] BreakingChanges: announce Rust becoming mandatory","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-24T05:03:07Z","receivedAt":"2025-09-24T05:03:15Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Tue, Sep 23, 2025 at 10:29:46AM -0700, Junio C Hamano wrote:\n> Phillip Wood <phillip.wood123@gmail.com> writes:\n> \n> >> +We will evaluate the impact on downstream distributions before making Rust\n> >> +mandatory in Git 3.0. If we see that the impact on downstream distributions\n> >> +would be significant, we may decide to defer this breaking change to a\n> >> +subsequent minor release. This evaluation will also take into account our own\n> >> +learnings with how painful it is to keep Rust an optional component.\n> >\n> > I think this last paragraph is a welcome addition as it makes it clear\n> > we're not going to blindly pursue rust if it causes widespread\n> > problems. Personally I'd say \"experience\" rather than \"learnings\" but\n> > that's probably me being a grumpy pedant.\n> \n> If this transition turns out to be way too disruptive even for the\n> 3.0 that promises big changes anyway, can \"this breaking change\"\n> realistically be \"deferred\" to a subsequent \"minor\" release?\n> \n> The only way I can think of that is permissible in a minor release\n> would be to pear it down so much that it no longer is disruptive,\n> but that would be very different from \"this breaking change\"\n> anymore.\n> \n> Or is this talking about waiting until the downstream distribions\n> either die out without adding Rust support or start supporting Rust?\n> That, except for the risk of having to wait forever, might work, but\n> then to surviving distros, it would no longer be a \"breaking\" change\n> even if we ship the same change as \"this breaking change\", right?\n\nI guess the answer is \"it depends\". We're counting on tools like gccrs\nand rustc_codegen_c to become viable, as those tools may help us quite\nsignificantly to reduce the blast radius. But \"reduce\" doesn't\nnecessarily mean that there are no victims anymore.\n\nI'll slightly reword this to say \"this change\" instead of \"this breaking\nchange\" though.\n\n> I don't know.  To me, the last sentence sounds like reserving the\n> right to later say \"we learned that trying to support opt-in Rust\n> component that we have to (partially) replicate in C is so painful,\n> so we won't keep Rust an optional component\".\n\nWe haven't gained a lot of experience with Rust yet, so I think we\nshould keep all options open for now. I really want the Rust experiment\nto succeed (well, otherwise I wouldn't push this series), but we simply\ndon't know how it'll play out at this point.\n\nPatrick\n"},{"id":"527208","messageId":"aNPp5jA5k_nDNmyd@pks.im","threadId":"64091","inReplyTo":"xmqqqzvxp7ej.fsf@gitster.g","subject":"Re: [PATCH RFC v4 7/9] BreakingChanges: announce Rust becoming mandatory","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-24T12:53:58Z","receivedAt":"2025-09-24T12:54:06Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Tue, Sep 23, 2025 at 07:31:32AM -0700, Junio C Hamano wrote:\n> Patrick Steinhardt <ps@pks.im> writes:\n> > There's a couple reasons:\n> >\n> >   - The LTS maintainer may not be as familiar with the Git codebase as\n> >   - The LTS maintainer may not be as trusted as other regulars on the\n> \n> If you assume that you can only get incompetent folks who would not\n> be trusted by their users by their own ability and dedication, I do\n> not think an endorsement by the main project would help them gain\n> trust at all.  All it would do to force the main project to blindly\n> sign their output is to tarnish the brand of the main project.\n> \n> In other words, you are assuming that no competent folks would want\n> to be the \"LTS maintainer\"(s), and you are arguing that if we really\n> want a \"Rustless Git\", which will be used by the general public, to\n> exist, we should be the ones that are working on it.\n\nI think there's a wide range between \"competent\" and \"incompetent\". I\nwould generally assume for example distro maintainers to be competent,\nbut they probably don't have as much expertise in the Git codebase\ncompared to a frequent committer to Git. So there's nuances here, and I\nthink in such cases everyone would benefit if they had a helping hand\nfrom the Git project.\n\n> >> edge.  Most importantly, a coordinated disclosure would say that the\n> >> update to versions of\n> >> \n> >>  - Git 3.0 to Git 3.4 are found $HERE, \n> >>  - Git for Windows 3.0, 3.2, and 3.4 are found $THERE\n> >>  - Git 2.98 are found $COMMUNITY_LTS\n> >> \n> >> to make sure that people know where to find their updates.\n> >> \n> >> So, no, I do not think we should unnecessarily mix community LTS and\n> >> the main project.\n> >\n> > How about the following tradeoff: the community LTS is developed outside\n> > of the usual Git workflow, for example on a forge, so that the LTS\n> > maintainers can work in their preferred flow. But eventually, once they\n> > want to do a release they send a pull request to the Git mailing list\n> > and then the tag lives in the canonical Git repository.\n> \n> I do not think, with your assumption that LTS maintainer(s) are\n> incompetent ones that cannot gain users' trust by themselves, such\n> an arrangement would work.  Its only effect would be to tarnish the\n> brand of the main project if we rubber stamp endorse their ware.\n\nYeah, rubber-stamping doesn't really help indeed. The idea wasn't to do\nthat though, but to still do a sanity check of the new version.\n\nI guess ultimately we'll have to figure out the details along the way.\nThere's many questions we cannot answer at this point in time yet, like:\n\n  - When is the LTS maintainership handed over to the community?\n\n  - Who is the community member that takes over maintainership of the\n    LTS release?\n\n  - How long do we expect to require the LTS release?\n\n  - Will we even need it in the first place for Rustless builds?\n\nSo maybe it's premature at the current point in time to already spell\nout details. Should we maybe just defer that decision into the future?\nE.g. something like the below patch.\n\nPatrick\n\ndiff --git a/Documentation/BreakingChanges.adoc b/Documentation/BreakingChanges.adoc\nindex 3b54750621..bf3173013d 100644\n--- a/Documentation/BreakingChanges.adoc\n+++ b/Documentation/BreakingChanges.adoc\n@@ -200,9 +200,9 @@ The Git project will declare the last version before Git 3.0 to be a long-term\n support release. This long-term release will receive important bug fixes for at\n least four release cycles and security fixes for six release cycles. The Git\n project will hand over maintainership of the long-term release to distributors\n-in case they need to extend the life of that long-term release even further. In\n-that case, the backporting process will be handled by these distributors, but\n-the long-term release tags will be created in the canonical Git repository.\n+in case they need to extend the life of that long-term release even further.\n+Details of how this long-term release will be handed over to the community will\n+be decided once the Git project decides to stop officially supporting it.\n +\n We will evaluate the impact on downstream distributions before making Rust\n mandatory in Git 3.0. If we see that the impact on downstream distributions\n"},{"id":"527212","messageId":"aNP2ZWMbrbxa6ZFn@pks.im","threadId":"64091","inReplyTo":"61e4895a-415e-f2ba-97d7-23aa99334191@gmx.de","subject":"Re: LTS \"lieutenant\", was Re: [PATCH RFC v4 7/9] BreakingChanges: announce Rust becoming mandatory","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-24T13:47:17Z","receivedAt":"2025-09-24T13:47:26Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Tue, Sep 23, 2025 at 10:53:02AM +0200, Johannes Schindelin wrote:\n> Let me propose an alternative, one that is much more likely to be accepted\n> by actual Git users, including professional ones: How about assigning a\n> trusted, prolific Git contributor as LTS maintainer? One who is deeply\n> familiar with the Git project and can, if the need arises, help the Git\n> project steer clear of unnecessary conflict-making e.g. via\n> intentionally-incompatible bug fixes on the non-LTS branch? Kind of like\n> the lieutenants in the Linux kernel project.\n> \n> Naturally, I am thinking of you, Patrick. You have demonstrated diligent\n> work in the Git project, are highly trusted both inside and outside the\n> Git project, and you seem to genuinely care about the long-term success of\n> the Git project.\n> \n> An additional benefit of this would be to have a dependable release policy\n> for older release trains, just like other projects have. I have heard the\n> desire for such a policy many times.\n\nAs I mentioned in another part of this thread I think it's still a bit\npremature to talk about how all of this will play out, as the potential\nLTS release is still at least a year out, and then it'll be probably a\nwhile before we actually need to care about handing over to an LTS\nmaintainer.\n\nThat being said: I already mentioned somewhere (please don't ask me\nwhere, I don't know anymore and the threads are huge) that I would be\nwilling to do this. It certainly is not the most glorious or joyful\ntask, but hopefully this isn't too much work? Maybe I'm being naive\nand will regret it.\n\nI certainly don't insist on doing it -- if anyone else would feel like\nthey would really like to do it in my stead, then I wouldn't complain,\neither.\n\nIn the end I think we should discuss this more and finalize details once\nthe LTS release handover becomes more concrete. Right now, it's still\nthis distant thing in the future, and who knows what projects I'll find\nuntil then to fall into disfavor :)\n\nPatrick\n"},{"id":"527215","messageId":"CAH=ZcbBjL09Mk3AXBSgmZGvmFtU3Roc2P5rbQsZ-U5DBHYSs7w@mail.gmail.com","threadId":"64091","inReplyTo":"aNN7dG6oLrv2Mokq@pks.im","subject":"Re: [PATCH v6 0/9] Introduce Rust and announce that it will become mandatory","fromName":"Ezekiel Newren","fromEmail":"ezekielnewren@gmail.com","sentAt":"2025-09-24T14:34:54Z","receivedAt":"2025-09-24T14:35:08Z","isPatch":true,"sender":{"key":"ezekielnewren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/18313324?v=4"},"body":"On Tue, Sep 23, 2025 at 11:02 PM Patrick Steinhardt <ps@pks.im> wrote:\n>\n> On Tue, Sep 23, 2025 at 02:15:35PM -0600, Ezekiel Newren wrote:\n> > On Tue, Sep 23, 2025 at 3:45 AM Patrick Steinhardt <ps@pks.im> wrote:\n> > Your patch series has 2 critical problems:\n> >   * meson doesn't check for \"is windows and using msvc\" -> <crate>.lib\n> > else lib<crate>.a\n>\n> I didn't wire Windows up yet, so this is a known omission. It's not\n> handled in the Makefile yet, either. My plan here was to tackle Windows\n> support as the immediate next step once this patch series lands.\n>\n> Would that be fine with you?\n\nSo long as you're aware, I'm fine with it being fixed later. I believe\nthat Makefile doesn't ever use msvc in the github workflows and you'd\nonly need to tell meson to look for <crate>.lib since cargo will\nproduce that if it's using the Rust toolcahin x86_64-pc-windows-msvc.\nAlso you'd need to update your cargo-meson.sh script to merely look\nfor <crate>.lib instead of lib<crate>.a and move it.\n\n> >   * Using the name \"git\" for the crate is problematic because both\n> > Make and Meson already produce libgit.a which is different from the\n> > libgit.a that cargo is producing. Change the name in Cargo.toml from\n> > \"git\" to \"gitcore\".\n>\n> I wasn't quite happy with the \"git\" name anyway, so I'll happily take\n> \"gitcore\" instead.\n\nOk.\n\nThanks.\n\nEzekiel.\n"},{"id":"527242","messageId":"xmqqms6jlpal.fsf@gitster.g","threadId":"64091","inReplyTo":"aNPp5jA5k_nDNmyd@pks.im","subject":"Re: [PATCH RFC v4 7/9] BreakingChanges: announce Rust becoming mandatory","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-09-24T17:43:14Z","receivedAt":"2025-09-24T17:43:17Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> So maybe it's premature at the current point in time to already spell\n> out details. Should we maybe just defer that decision into the future?\n> E.g. something like the below patch.\n>\n> Patrick\n>\n> diff --git a/Documentation/BreakingChanges.adoc b/Documentation/BreakingChanges.adoc\n> index 3b54750621..bf3173013d 100644\n> --- a/Documentation/BreakingChanges.adoc\n> +++ b/Documentation/BreakingChanges.adoc\n> @@ -200,9 +200,9 @@ The Git project will declare the last version before Git 3.0 to be a long-term\n>  support release. This long-term release will receive important bug fixes for at\n>  least four release cycles and security fixes for six release cycles. The Git\n>  project will hand over maintainership of the long-term release to distributors\n> -in case they need to extend the life of that long-term release even further. In\n> -that case, the backporting process will be handled by these distributors, but\n> -the long-term release tags will be created in the canonical Git repository.\n> +in case they need to extend the life of that long-term release even further.\n> +Details of how this long-term release will be handed over to the community will\n> +be decided once the Git project decides to stop officially supporting it.\n>  +\n>  We will evaluate the impact on downstream distributions before making Rust\n>  mandatory in Git 3.0. If we see that the impact on downstream distributions\n\nYup, punting on this would not hurt our overall timeline, so let's\nachieve concensus on other parts of the document and the patches.\n\nThanks.\n"},{"id":"527277","messageId":"20250925011043.M401827@dcvr","threadId":"64091","inReplyTo":"20250915-b4-pks-rust-breaking-change-v5-0-dc3a32fbb216@pks.im","subject":"what's missing from newer C? [was: [PATCH v5 0/9] Introduce Rust ....]","fromName":"Eric Wong","fromEmail":"e@80x24.org","sentAt":"2025-09-25T01:10:43Z","receivedAt":"2025-09-25T01:16:40Z","isPatch":true,"sender":{"key":"e@80x24.org","avatar":null},"body":"Patrick Steinhardt <ps@pks.im> wrote:\n> this small patch series introduces Rust into the core of Git. This patch\n> series is designed as a test balloon, similar to how we introduced test\n> balloons for C99 features in the past. The goal is threefold:\n\n>   - Give distributors time to ease into the new toolchain requirements.\n>     Introducing Rust is impossible for some platforms and hard for\n>     others.\n> \n>   - Announce that Git 3.0 will make Rust a mandatory part of our build\n>     infrastructure.\n\nNewer (and perhaps experimental) C has some safety and ergonomic\nfeatures which Rust advocates might be overlooking:\n\n1. C23 has stdckdint.h for checked arithmetic to prevent overflows\n\n2. __counted_by__ attribute in clang 18 and gcc 15 for\n   guarding against buffer overflows:\n   https://people.kernel.org/gustavoars/how-to-use-the-new-counted_by-attribute-in-c-and-linux\n   It's easy to fall back to disabling it for unsupported compilers.\n\n3. __cleanup__ attribute is supported by TinyCC, gcc, and clang\n   for many years (even decades), now.  Auto cleanup makes managing\n   locks for parallelism much easier along with normal resource\n   management ergonomic improvement.  __cleanup__ should be trivial\n   for other compiler maintainers to add (even TinyCC supports it)\n\n4. Userspace RCU provides concurrent data structures even w/o\n   RCU (and AFAIK ConcurrencyKit, too, but I've never used CK)\n\n5. compilers check format strings nowadays (but I dislike format\n   strings for performance reasons unless using qrintf)\n\n6. regexps (POSIX ERE or PCRE2) are already used by git and can\n   be used more extensively to make safer parsers.  There's also\n   things like wuffs and re2c to generate C (I've yet to try\n   either).\n\nWe also have Valgrind, ASAN, TSAN, etc...\n\n__cleanup__ and __counted_by__ are the biggest deals to me and I\nhope they'll be standardized soon.  The rest of the other stuff\nis pretty well-known at this point...\n\n\nWhat else is missing from C?\n\n\nFWIW, I detest hacking in verbose AOT languages in general and\ndon't write a lot of C as a result.  However, I've spent a\nlarge part of this century fixing C code written by others for\nthe usual memory leaks, memory errors, races, overflows, etc.\n\nI'm not particularly a fan of the C code in git for a variety\nof reasons but have sought to improve it here and there\n(container_of, list.h, etc.)\n\nBuilding git nowadays is painful for me due to the (lack of)\nspeed from lld/gold/mold on my ancient hardware.  Rust's\nfamously slow compilation speeds would mean only developers\nwilling to work for and/or promote $MEGACORP interests would be\nable to afford to hack on code.\n\nThanks for reading.\n"},{"id":"527288","messageId":"20250925-b4-pks-rust-breaking-change-v7-0-4e49dcb904d5@pks.im","threadId":"64091","inReplyTo":"20250904-b4-pks-rust-breaking-change-v1-0-3af1d25e0be9@pks.im","subject":"[PATCH v7 0/9] Introduce Rust and announce that it will become mandatory","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-25T06:30:02Z","receivedAt":"2025-09-25T06:30:19Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Hi,\n\nthis small patch series introduces Rust into the core of Git. This patch\nseries is designed as a test balloon, similar to how we introduced test\nballoons for C99 features in the past. The goal is threefold:\n\n  - Give us some time to experiment with Rust and introduce proper build\n    infrastructure.\n\n  - Give distributors time to ease into the new toolchain requirements.\n    Introducing Rust is impossible for some platforms and hard for\n    others.\n\n  - Announce that Git 3.0 will make Rust a mandatory part of our build\n    infrastructure.\n\nThe test balloon itself is quite uninteresting: I've chosen to convert\nthe \"varint.c\" subsystem, mostly because it is trivial and does not have\nany dependencies. But it does allow us to verify that C to Rust interop\nworks as expected, and to play around with tooling. All tests pass with\nthe \"varint.rs\" implementation.\n\nFor now, the series only contains support for Meson. If we agree to go\ndown this route I'll also introduce support for Rust into our Makefiles\nat a later point in time.\n\nFurthermore missing is additional tooling:\n\n  - At least one CI job to verify that Rust builds and works as\n    expected.\n\n  - Tooling and CI jobs to ensure that we have consistent formatting via\n    `cargo format`.\n\nAnd probably lots more. As said, the entire goal is for us to have an\neasy playground that we can experiment on and develop the infrastructure\nincrementally without yet having to commit to anything.\n\nI'm mostly splitting out the topic of introducing Rust from the larger\nseries that introduce it into xdiff so that we can focus more on the\nactual process of introducing Rust into Git and less on the potential\nfeatures that we want to build on top of it.\n\nChanges in v2:\n  - Introduce support for building the Rust library via our Makefile.\n  - Introduce a '-DWITH_RUST' define. This define is used to print\n    whether or not Git is built with Rust via `git version\n    --build-options`.\n  - Adjust Meson to not depend on v1.9.0 and newer anymore.\n  - Introduce a roadmap into our BreakingChanges document to explain how\n    we'll iterate towards mandatory Rust support.\n  - Rework the Fedora job to do a full compile-and-test run with Meson\n    and breaking changes enabled.\n  - Adapt our breaking-changes jobs to enable Rust support.\n  - Link to v1: https://lore.kernel.org/r/20250904-b4-pks-rust-breaking-change-v1-0-3af1d25e0be9@pks.im\n\nChanges in v3:\n  - Reorder all uses of `WITH_RUST` after the include of \"config.mak\".\n  - Add a test to verify overflow behaviour in Rust and explicitly use\n    `add_wrapping()`.\n  - Use explicit dependencies for the Rust library in our Makefile.\n  - Fix Alma Linux CI job.\n  - Stop tying maintenance of our LTS release to the availability of\n    gcc-rs.\n  - Add a fallback to Meson to use cargo directly.\n  - I've fixed the Rust edition to 2018 for now. This is intentionally\n    conservative so that we might be able to use Rust 1.49. For now, we\n    don't have any reason to use a newer edition, either. So let's take\n    the oldest version we can live with for now and then bump it as\n    required.\n  - Link to v2: https://lore.kernel.org/r/20250905-b4-pks-rust-breaking-change-v2-0-6939cbf4a0b8@pks.im\n\nChanges in v4:\n  - Convert \"varint.c\" to use explicit integer width so that we don't\n    need to use C types in Rust.\n  - Adapt Meson to unconditionally use Cargo.\n  - Don't use the unstable `--out-dir` option in Cargo. Instead, we\n    resort to a wrapper script in Meson.\n  - Shorten the timeline a bit to drop the extra step that ties Rust\n    support to `-Dbreaking_changes=true`. This accelerates the timeline\n    until distros are made forcibly aware of the upcoming changes in\n    Rust.\n  - Link to v3: https://lore.kernel.org/r/20250908-b4-pks-rust-breaking-change-v3-0-1cd7189fed3b@pks.im\n\nChanges in v5:\n  - Fix indentation in the BreakingChanges document.\n  - Fix a commit message typo.\n  - Include \"Cargo.lock\" in the `make clean` target again.\n  - Link to v4: https://lore.kernel.org/r/20250910-b4-pks-rust-breaking-change-v4-0-4a63fc69278d@pks.im\n\nChanges in v6:\n  - Give attribution to Ezekiel for kickstarting the Rust adoption\n    again. I'm happy to change how I do the attribution.\n  - Fix \"varint.rs\" to use `u64` instead of `usize`. Issues like these\n    will eventually be catched by cbindgen.\n  - Adapt the breaking changes document to mention that we already have\n    Rust in our tree starting with Git 2.49.\n  - Mention that we won't blindly make Rust mandatory, but consider the\n    impact on downstream distributions.\n  - Slightly reword how we'll handle LTS maintainership. This probably\n    still is an ongoing discussion.\n  - Link to v5: https://lore.kernel.org/r/20250915-b4-pks-rust-breaking-change-v5-0-dc3a32fbb216@pks.im\n\nChanges in v7:\n  - Rename \"git\" crate to \"gitcore\".\n  - Some word smithing for the breaking changes doc.\n  - Punt on the exact details of how we hand over maintenance of the LTS\n    release to the community. This is something we can decide on in the\n    future.\n  - Link to v6: https://lore.kernel.org/r/20250923-b4-pks-rust-breaking-change-v6-0-59076fee486a@pks.im\n\nThanks!\n\nPatrick\n\n---\nPatrick Steinhardt (9):\n      meson: add infrastructure to build internal Rust library\n      Makefile: reorder sources after includes\n      Makefile: introduce infrastructure to build internal Rust library\n      help: report on whether or not Rust is enabled\n      varint: use explicit width for integers\n      varint: reimplement as test balloon for Rust\n      BreakingChanges: announce Rust becoming mandatory\n      ci: convert \"pedantic\" job into full build with breaking changes\n      ci: enable Rust for breaking-changes jobs\n\n .github/workflows/main.yml         |   4 +-\n .gitignore                         |   2 +\n .gitlab-ci.yml                     |   4 +-\n Cargo.toml                         |   9 ++\n Documentation/BreakingChanges.adoc |  45 ++++++++\n Makefile                           | 214 ++++++++++++++++++++++---------------\n ci/install-dependencies.sh         |   8 +-\n ci/run-build-and-tests.sh          |  31 ++----\n dir.c                              |  18 ++--\n help.c                             |   6 ++\n meson.build                        |  15 ++-\n meson_options.txt                  |   2 +\n read-cache.c                       |   6 +-\n shared.mak                         |   1 +\n src/cargo-meson.sh                 |  32 ++++++\n src/lib.rs                         |   1 +\n src/meson.build                    |  41 +++++++\n src/varint.rs                      |  92 ++++++++++++++++\n varint.c                           |   6 +-\n varint.h                           |   4 +-\n 20 files changed, 410 insertions(+), 131 deletions(-)\n\nRange-diff versus v6:\n\n 1:  bb793b71e3 !  1:  4c4b07ed93 meson: add infrastructure to build internal Rust library\n    @@ Commit message\n      ## Cargo.toml (new) ##\n     @@\n     +[package]\n    -+name = \"git\"\n    ++name = \"gitcore\"\n     +version = \"0.1.0\"\n     +edition = \"2018\"\n     +\n    @@ src/cargo-meson.sh (new)\n     +\texit $RET\n     +fi\n     +\n    -+if ! cmp \"$BUILD_DIR/$BUILD_TYPE/libgit.a\" \"$BUILD_DIR/libgit.a\" >/dev/null 2>&1\n    ++if ! cmp \"$BUILD_DIR/$BUILD_TYPE/libgitcore.a\" \"$BUILD_DIR/libgitcore.a\" >/dev/null 2>&1\n     +then\n    -+\tcp \"$BUILD_DIR/$BUILD_TYPE/libgit.a\" \"$BUILD_DIR/libgit.a\"\n    ++\tcp \"$BUILD_DIR/$BUILD_TYPE/libgitcore.a\" \"$BUILD_DIR/libgitcore.a\"\n     +fi\n     \n      ## src/lib.rs (new) ##\n    @@ src/meson.build (new)\n     +  input: libgit_rs_sources + [\n     +    meson.project_source_root() / 'Cargo.toml',\n     +  ],\n    -+  output: 'libgit.a',\n    ++  output: 'libgitcore.a',\n     +  command: cargo_command,\n     +)\n     +libgit_dependencies += declare_dependency(link_with: libgit_rs)\n 2:  e3f8101578 =  2:  58633be050 Makefile: reorder sources after includes\n 3:  66673f7ce5 !  3:  16300fbeba Makefile: introduce infrastructure to build internal Rust library\n    @@ Makefile: TEST_SHELL_PATH = $(SHELL_PATH)\n      XDIFF_LIB = xdiff/lib.a\n      REFTABLE_LIB = reftable/libreftable.a\n     +ifdef DEBUG\n    -+RUST_LIB = target/debug/libgit.a\n    ++RUST_LIB = target/debug/libgitcore.a\n     +else\n    -+RUST_LIB = target/release/libgit.a\n    ++RUST_LIB = target/release/libgitcore.a\n     +endif\n      \n      # xdiff and reftable libs may in turn depend on what is in libgit.a\n 4:  65bcb1233d =  4:  240bc33e56 help: report on whether or not Rust is enabled\n 5:  908150d3ea =  5:  43e1f96e06 varint: use explicit width for integers\n 6:  8f92ff1e13 =  6:  e9f421bfb6 varint: reimplement as test balloon for Rust\n 7:  5e88d4d553 !  7:  73f4a8e639 BreakingChanges: announce Rust becoming mandatory\n    @@ Documentation/BreakingChanges.adoc: A prerequisite for this change is that the e\n     +support release. This long-term release will receive important bug fixes for at\n     +least four release cycles and security fixes for six release cycles. The Git\n     +project will hand over maintainership of the long-term release to distributors\n    -+in case they need to extend the life of that long-term release even further. In\n    -+that case, the backporting process will be handled by these distributors, but\n    -+the long-term release tags will be created in the canonical Git repository.\n    ++in case they need to extend the life of that long-term release even further.\n    ++Details of how this long-term release will be handed over to the community will\n    ++be discussed once the Git project decides to stop officially supporting it.\n     ++\n     +We will evaluate the impact on downstream distributions before making Rust\n     +mandatory in Git 3.0. If we see that the impact on downstream distributions\n    -+would be significant, we may decide to defer this breaking change to a\n    -+subsequent minor release. This evaluation will also take into account our own\n    -+learnings with how painful it is to keep Rust an optional component.\n    ++would be significant, we may decide to defer this change to a subsequent minor\n    ++release. This evaluation will also take into account our own experience with\n    ++how painful it is to keep Rust an optional component.\n     +\n      === Removals\n      \n 8:  d7d7256a48 =  8:  c1d3c3fcab ci: convert \"pedantic\" job into full build with breaking changes\n 9:  a38eec0af9 =  9:  14271538e3 ci: enable Rust for breaking-changes jobs\n\n---\nbase-commit: 2462961280690837670d997bde64bd4ebf8ae66d\nchange-id: 20250904-b4-pks-rust-breaking-change-7167d9d3e37d\n\n"},{"id":"527289","messageId":"20250925-b4-pks-rust-breaking-change-v7-1-4e49dcb904d5@pks.im","threadId":"64091","inReplyTo":"20250925-b4-pks-rust-breaking-change-v7-0-4e49dcb904d5@pks.im","subject":"[PATCH v7 1/9] meson: add infrastructure to build internal Rust library","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-25T06:30:03Z","receivedAt":"2025-09-25T06:30:22Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Add the infrastructure into Meson to build an internal Rust library.\nBuilding the Rust parts of Git are for now entirely optional, as they\nare mostly intended as a test balloon for both Git developers, but also\nfor distributors of Git. So for now, they may contain:\n\n  - New features that are not mission critical to Git and that users can\n    easily live without.\n\n  - Alternative implementations of small subsystems.\n\nIf these test balloons are successful, we will eventually make Rust a\nmandatory dependency for our build process in Git 3.0.\n\nThe availability of a Rust toolchain will be auto-detected by Meson at\nsetup time. This behaviour can be tweaked via the `-Drust=` feature\ntoggle.\n\nNext to the linkable Rust library, also wire up tests that can be\nexecuted via `meson test`. This allows us to use the native unit testing\ncapabilities of Rust.\n\nNote that the Rust edition is currently set to 2018. This edition is\nsupported by Rust 1.49, which is the target for the upcoming gcc-rs\nbackend. For now we don't use any features of Rust that would require a\nnewer version, so settling on this old version makes sense so that\ngcc-rs may become an alternative backend for compiling Git. If we _do_\nwant to introduce features that were added in more recent editions of\nRust though we should reevaluate that choice.\n\nInspired-by: Ezekiel Newren <ezekielnewren@gmail.com>\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n Cargo.toml         |  9 +++++++++\n meson.build        | 10 +++++++++-\n meson_options.txt  |  2 ++\n src/cargo-meson.sh | 32 ++++++++++++++++++++++++++++++++\n src/lib.rs         |  0\n src/meson.build    | 40 ++++++++++++++++++++++++++++++++++++++++\n 6 files changed, 92 insertions(+), 1 deletion(-)\n\ndiff --git a/Cargo.toml b/Cargo.toml\nnew file mode 100644\nindex 00000000000..45c9b34981a\n--- /dev/null\n+++ b/Cargo.toml\n@@ -0,0 +1,9 @@\n+[package]\n+name = \"gitcore\"\n+version = \"0.1.0\"\n+edition = \"2018\"\n+\n+[lib]\n+crate-type = [\"staticlib\"]\n+\n+[dependencies]\ndiff --git a/meson.build b/meson.build\nindex e8ec0eca165..234a9e9d6fd 100644\n--- a/meson.build\n+++ b/meson.build\n@@ -220,7 +220,7 @@ project('git', 'c',\n   # learned to define __STDC_VERSION__ with C11 and later. We thus require\n   # GNU C99 and fall back to C11. Meson only learned to handle the fallback\n   # with version 1.3.0, so on older versions we use GNU C99 unconditionally.\n-  default_options: meson.version().version_compare('>=1.3.0') ? ['c_std=gnu99,c11'] : ['c_std=gnu99'],\n+  default_options: meson.version().version_compare('>=1.3.0') ? ['rust_std=2018', 'c_std=gnu99,c11'] : ['rust_std=2018', 'c_std=gnu99'],\n )\n \n fs = import('fs')\n@@ -1702,6 +1702,13 @@ version_def_h = custom_target(\n )\n libgit_sources += version_def_h\n \n+cargo = find_program('cargo', dirs: program_path, native: true, required: get_option('rust'))\n+rust_option = get_option('rust').disable_auto_if(not cargo.found())\n+if rust_option.allowed()\n+  subdir('src')\n+  libgit_c_args += '-DWITH_RUST'\n+endif\n+\n libgit = declare_dependency(\n   link_with: static_library('git',\n     sources: libgit_sources,\n@@ -2239,6 +2246,7 @@ summary({\n   'pcre2': pcre2,\n   'perl': perl_features_enabled,\n   'python': target_python.found(),\n+  'rust': rust_option.allowed(),\n }, section: 'Auto-detected features', bool_yn: true)\n \n summary({\ndiff --git a/meson_options.txt b/meson_options.txt\nindex 1668f260a18..143dee9237c 100644\n--- a/meson_options.txt\n+++ b/meson_options.txt\n@@ -71,6 +71,8 @@ option('zlib_backend', type: 'combo', choices: ['auto', 'zlib', 'zlib-ng'], valu\n # Build tweaks.\n option('breaking_changes', type: 'boolean', value: false,\n   description: 'Enable upcoming breaking changes.')\n+option('rust', type: 'feature', value: 'auto',\n+  description: 'Enable building with Rust.')\n option('macos_use_homebrew_gettext', type: 'boolean', value: true,\n   description: 'Use gettext from Homebrew instead of the slightly-broken system-provided one.')\n \ndiff --git a/src/cargo-meson.sh b/src/cargo-meson.sh\nnew file mode 100755\nindex 00000000000..99400986d93\n--- /dev/null\n+++ b/src/cargo-meson.sh\n@@ -0,0 +1,32 @@\n+#!/bin/sh\n+\n+if test \"$#\" -lt 2\n+then\n+\texit 1\n+fi\n+\n+SOURCE_DIR=\"$1\"\n+BUILD_DIR=\"$2\"\n+BUILD_TYPE=debug\n+\n+shift 2\n+\n+for arg\n+do\n+\tcase \"$arg\" in\n+\t--release)\n+\t\tBUILD_TYPE=release;;\n+\tesac\n+done\n+\n+cargo build --lib --quiet --manifest-path=\"$SOURCE_DIR/Cargo.toml\" --target-dir=\"$BUILD_DIR\" \"$@\"\n+RET=$?\n+if test $RET -ne 0\n+then\n+\texit $RET\n+fi\n+\n+if ! cmp \"$BUILD_DIR/$BUILD_TYPE/libgitcore.a\" \"$BUILD_DIR/libgitcore.a\" >/dev/null 2>&1\n+then\n+\tcp \"$BUILD_DIR/$BUILD_TYPE/libgitcore.a\" \"$BUILD_DIR/libgitcore.a\"\n+fi\ndiff --git a/src/lib.rs b/src/lib.rs\nnew file mode 100644\nindex 00000000000..e69de29bb2d\ndiff --git a/src/meson.build b/src/meson.build\nnew file mode 100644\nindex 00000000000..c8d874b2106\n--- /dev/null\n+++ b/src/meson.build\n@@ -0,0 +1,40 @@\n+libgit_rs_sources = [\n+  'lib.rs',\n+]\n+\n+# Unfortunately we must use a wrapper command to move the output file into the\n+# current build directory. This can fixed once `cargo build --artifact-dir`\n+# stabilizes. See https://github.com/rust-lang/cargo/issues/6790 for that\n+# effort.\n+cargo_command = [\n+  shell,\n+  meson.current_source_dir() / 'cargo-meson.sh',\n+  meson.project_source_root(),\n+  meson.current_build_dir(),\n+]\n+if get_option('buildtype') == 'release'\n+  cargo_command += '--release'\n+endif\n+\n+libgit_rs = custom_target('git_rs',\n+  input: libgit_rs_sources + [\n+    meson.project_source_root() / 'Cargo.toml',\n+  ],\n+  output: 'libgitcore.a',\n+  command: cargo_command,\n+)\n+libgit_dependencies += declare_dependency(link_with: libgit_rs)\n+\n+if get_option('tests')\n+  test('rust', cargo,\n+    args: [\n+      'test',\n+      '--manifest-path',\n+      meson.project_source_root() / 'Cargo.toml',\n+      '--target-dir',\n+      meson.current_build_dir() / 'target',\n+    ],\n+    timeout: 0,\n+    protocol: 'rust',\n+  )\n+endif\n\n-- \n2.51.0.618.g983fd99d29.dirty\n\n"},{"id":"527290","messageId":"20250925-b4-pks-rust-breaking-change-v7-2-4e49dcb904d5@pks.im","threadId":"64091","inReplyTo":"20250925-b4-pks-rust-breaking-change-v7-0-4e49dcb904d5@pks.im","subject":"[PATCH v7 2/9] Makefile: reorder sources after includes","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-25T06:30:04Z","receivedAt":"2025-09-25T06:30:25Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"In an upcoming change we'll make some of the sources compile\nconditionally based on whether or not `WITH_RUST` is defined. To let\ndevelopers specify that flag in their \"config.mak\" we'll thus have to\nreorder our sources so that they come after the include of that file.\n\nDo so.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n Makefile | 176 +++++++++++++++++++++++++++++++--------------------------------\n 1 file changed, 88 insertions(+), 88 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 555b7f4dc3..7e52625d75 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -919,6 +919,94 @@ LIB_FILE = libgit.a\n XDIFF_LIB = xdiff/lib.a\n REFTABLE_LIB = reftable/libreftable.a\n \n+# xdiff and reftable libs may in turn depend on what is in libgit.a\n+GITLIBS = common-main.o $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(LIB_FILE)\n+EXTLIBS =\n+\n+GIT_USER_AGENT = git/$(GIT_VERSION)\n+\n+ifeq ($(wildcard sha1collisiondetection/lib/sha1.h),sha1collisiondetection/lib/sha1.h)\n+DC_SHA1_SUBMODULE = auto\n+endif\n+\n+# Set CFLAGS, LDFLAGS and other *FLAGS variables. These might be\n+# tweaked by config.* below as well as the command-line, both of\n+# which'll override these defaults.\n+# Older versions of GCC may require adding \"-std=gnu99\" at the end.\n+CFLAGS = -g -O2 -Wall\n+LDFLAGS =\n+CC_LD_DYNPATH = -Wl,-rpath,\n+BASIC_CFLAGS = -I.\n+BASIC_LDFLAGS =\n+\n+# library flags\n+ARFLAGS = rcs\n+PTHREAD_CFLAGS =\n+\n+# For the 'sparse' target\n+SPARSE_FLAGS ?= -std=gnu99 -D__STDC_NO_VLA__\n+SP_EXTRA_FLAGS =\n+\n+# For informing GIT-BUILD-OPTIONS of the SANITIZE=leak,address targets\n+SANITIZE_LEAK =\n+SANITIZE_ADDRESS =\n+\n+# For the 'coccicheck' target\n+SPATCH_INCLUDE_FLAGS = --all-includes\n+SPATCH_FLAGS =\n+SPATCH_TEST_FLAGS =\n+\n+# If *.o files are present, have \"coccicheck\" depend on them, with\n+# COMPUTE_HEADER_DEPENDENCIES this will speed up the common-case of\n+# only needing to re-generate coccicheck results for the users of a\n+# given API if it's changed, and not all files in the project. If\n+# COMPUTE_HEADER_DEPENDENCIES=no this will be unset too.\n+SPATCH_USE_O_DEPENDENCIES = YesPlease\n+\n+# Set SPATCH_CONCAT_COCCI to concatenate the contrib/cocci/*.cocci\n+# files into a single contrib/cocci/ALL.cocci before running\n+# \"coccicheck\".\n+#\n+# Pros:\n+#\n+# - Speeds up a one-shot run of \"make coccicheck\", as we won't have to\n+#   parse *.[ch] files N times for the N *.cocci rules\n+#\n+# Cons:\n+#\n+# - Will make incremental development of *.cocci slower, as\n+#   e.g. changing strbuf.cocci will re-run all *.cocci.\n+#\n+# - Makes error and performance analysis harder, as rules will be\n+#   applied from a monolithic ALL.cocci, rather than\n+#   e.g. strbuf.cocci. To work around this either undefine this, or\n+#   generate a specific patch, e.g. this will always use strbuf.cocci,\n+#   not ALL.cocci:\n+#\n+#\tmake contrib/coccinelle/strbuf.cocci.patch\n+SPATCH_CONCAT_COCCI = YesPlease\n+\n+# Rebuild 'coccicheck' if $(SPATCH), its flags etc. change\n+TRACK_SPATCH_DEFINES =\n+TRACK_SPATCH_DEFINES += $(SPATCH)\n+TRACK_SPATCH_DEFINES += $(SPATCH_INCLUDE_FLAGS)\n+TRACK_SPATCH_DEFINES += $(SPATCH_FLAGS)\n+TRACK_SPATCH_DEFINES += $(SPATCH_TEST_FLAGS)\n+GIT-SPATCH-DEFINES: FORCE\n+\t@FLAGS='$(TRACK_SPATCH_DEFINES)'; \\\n+\t    if test x\"$$FLAGS\" != x\"`cat GIT-SPATCH-DEFINES 2>/dev/null`\" ; then \\\n+\t\techo >&2 \"    * new spatch flags\"; \\\n+\t\techo \"$$FLAGS\" >GIT-SPATCH-DEFINES; \\\n+            fi\n+\n+include config.mak.uname\n+-include config.mak.autogen\n+-include config.mak\n+\n+ifdef DEVELOPER\n+include config.mak.dev\n+endif\n+\n GENERATED_H += command-list.h\n GENERATED_H += config-list.h\n GENERATED_H += hook-list.h\n@@ -1387,94 +1475,6 @@ CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/unit-test.o\n \n UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o\n \n-# xdiff and reftable libs may in turn depend on what is in libgit.a\n-GITLIBS = common-main.o $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(LIB_FILE)\n-EXTLIBS =\n-\n-GIT_USER_AGENT = git/$(GIT_VERSION)\n-\n-ifeq ($(wildcard sha1collisiondetection/lib/sha1.h),sha1collisiondetection/lib/sha1.h)\n-DC_SHA1_SUBMODULE = auto\n-endif\n-\n-# Set CFLAGS, LDFLAGS and other *FLAGS variables. These might be\n-# tweaked by config.* below as well as the command-line, both of\n-# which'll override these defaults.\n-# Older versions of GCC may require adding \"-std=gnu99\" at the end.\n-CFLAGS = -g -O2 -Wall\n-LDFLAGS =\n-CC_LD_DYNPATH = -Wl,-rpath,\n-BASIC_CFLAGS = -I.\n-BASIC_LDFLAGS =\n-\n-# library flags\n-ARFLAGS = rcs\n-PTHREAD_CFLAGS =\n-\n-# For the 'sparse' target\n-SPARSE_FLAGS ?= -std=gnu99 -D__STDC_NO_VLA__\n-SP_EXTRA_FLAGS =\n-\n-# For informing GIT-BUILD-OPTIONS of the SANITIZE=leak,address targets\n-SANITIZE_LEAK =\n-SANITIZE_ADDRESS =\n-\n-# For the 'coccicheck' target\n-SPATCH_INCLUDE_FLAGS = --all-includes\n-SPATCH_FLAGS =\n-SPATCH_TEST_FLAGS =\n-\n-# If *.o files are present, have \"coccicheck\" depend on them, with\n-# COMPUTE_HEADER_DEPENDENCIES this will speed up the common-case of\n-# only needing to re-generate coccicheck results for the users of a\n-# given API if it's changed, and not all files in the project. If\n-# COMPUTE_HEADER_DEPENDENCIES=no this will be unset too.\n-SPATCH_USE_O_DEPENDENCIES = YesPlease\n-\n-# Set SPATCH_CONCAT_COCCI to concatenate the contrib/cocci/*.cocci\n-# files into a single contrib/cocci/ALL.cocci before running\n-# \"coccicheck\".\n-#\n-# Pros:\n-#\n-# - Speeds up a one-shot run of \"make coccicheck\", as we won't have to\n-#   parse *.[ch] files N times for the N *.cocci rules\n-#\n-# Cons:\n-#\n-# - Will make incremental development of *.cocci slower, as\n-#   e.g. changing strbuf.cocci will re-run all *.cocci.\n-#\n-# - Makes error and performance analysis harder, as rules will be\n-#   applied from a monolithic ALL.cocci, rather than\n-#   e.g. strbuf.cocci. To work around this either undefine this, or\n-#   generate a specific patch, e.g. this will always use strbuf.cocci,\n-#   not ALL.cocci:\n-#\n-#\tmake contrib/coccinelle/strbuf.cocci.patch\n-SPATCH_CONCAT_COCCI = YesPlease\n-\n-# Rebuild 'coccicheck' if $(SPATCH), its flags etc. change\n-TRACK_SPATCH_DEFINES =\n-TRACK_SPATCH_DEFINES += $(SPATCH)\n-TRACK_SPATCH_DEFINES += $(SPATCH_INCLUDE_FLAGS)\n-TRACK_SPATCH_DEFINES += $(SPATCH_FLAGS)\n-TRACK_SPATCH_DEFINES += $(SPATCH_TEST_FLAGS)\n-GIT-SPATCH-DEFINES: FORCE\n-\t@FLAGS='$(TRACK_SPATCH_DEFINES)'; \\\n-\t    if test x\"$$FLAGS\" != x\"`cat GIT-SPATCH-DEFINES 2>/dev/null`\" ; then \\\n-\t\techo >&2 \"    * new spatch flags\"; \\\n-\t\techo \"$$FLAGS\" >GIT-SPATCH-DEFINES; \\\n-            fi\n-\n-include config.mak.uname\n--include config.mak.autogen\n--include config.mak\n-\n-ifdef DEVELOPER\n-include config.mak.dev\n-endif\n-\n GIT-VERSION-FILE: FORCE\n \t@OLD=$$(cat $@ 2>/dev/null || :) && \\\n \t$(call version_gen,\"$(shell pwd)\",GIT-VERSION-FILE.in,$@) && \\\n\n-- \n2.51.0.618.g983fd99d29.dirty\n\n"},{"id":"527291","messageId":"20250925-b4-pks-rust-breaking-change-v7-3-4e49dcb904d5@pks.im","threadId":"64091","inReplyTo":"20250925-b4-pks-rust-breaking-change-v7-0-4e49dcb904d5@pks.im","subject":"[PATCH v7 3/9] Makefile: introduce infrastructure to build internal Rust library","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-25T06:30:05Z","receivedAt":"2025-09-25T06:30:28Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Introduce infrastructure to build the internal Rust library. This\nmirrors the infrastructure we have added to Meson in the preceding\ncommit. Developers can enable the infrastructure by passing the new\n`WITH_RUST` build toggle.\n\nInspired-by: Ezekiel Newren <ezekielnewren@gmail.com>\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n .gitignore |  2 ++\n Makefile   | 37 +++++++++++++++++++++++++++++++++++++\n shared.mak |  1 +\n 3 files changed, 40 insertions(+)\n\ndiff --git a/.gitignore b/.gitignore\nindex 1803023427..0833453cf6 100644\n--- a/.gitignore\n+++ b/.gitignore\n@@ -1,4 +1,6 @@\n /fuzz_corpora\n+/target/\n+/Cargo.lock\n /GIT-BUILD-DIR\n /GIT-BUILD-OPTIONS\n /GIT-CFLAGS\ndiff --git a/Makefile b/Makefile\nindex 7e52625d75..31e79342e1 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -483,6 +483,14 @@ include shared.mak\n # Define LIBPCREDIR=/foo/bar if your PCRE header and library files are\n # in /foo/bar/include and /foo/bar/lib directories.\n #\n+# == Optional Rust support ==\n+#\n+# Define WITH_RUST if you want to include features and subsystems written in\n+# Rust into Git. For now, Rust is still an optional feature of the build\n+# process. With Git 3.0 though, Rust will always be enabled.\n+#\n+# Building Rust code requires Cargo.\n+#\n # == SHA-1 and SHA-256 defines ==\n #\n # === SHA-1 backend ===\n@@ -683,6 +691,7 @@ OBJECTS =\n OTHER_PROGRAMS =\n PROGRAM_OBJS =\n PROGRAMS =\n+RUST_SOURCES =\n EXCLUDED_PROGRAMS =\n SCRIPT_PERL =\n SCRIPT_PYTHON =\n@@ -918,6 +927,11 @@ TEST_SHELL_PATH = $(SHELL_PATH)\n LIB_FILE = libgit.a\n XDIFF_LIB = xdiff/lib.a\n REFTABLE_LIB = reftable/libreftable.a\n+ifdef DEBUG\n+RUST_LIB = target/debug/libgitcore.a\n+else\n+RUST_LIB = target/release/libgitcore.a\n+endif\n \n # xdiff and reftable libs may in turn depend on what is in libgit.a\n GITLIBS = common-main.o $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(LIB_FILE)\n@@ -943,6 +957,15 @@ BASIC_LDFLAGS =\n ARFLAGS = rcs\n PTHREAD_CFLAGS =\n \n+# Rust flags\n+CARGO_ARGS =\n+ifndef V\n+CARGO_ARGS += --quiet\n+endif\n+ifndef DEBUG\n+CARGO_ARGS += --release\n+endif\n+\n # For the 'sparse' target\n SPARSE_FLAGS ?= -std=gnu99 -D__STDC_NO_VLA__\n SP_EXTRA_FLAGS =\n@@ -1475,6 +1498,8 @@ CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/unit-test.o\n \n UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o\n \n+RUST_SOURCES += src/lib.rs\n+\n GIT-VERSION-FILE: FORCE\n \t@OLD=$$(cat $@ 2>/dev/null || :) && \\\n \t$(call version_gen,\"$(shell pwd)\",GIT-VERSION-FILE.in,$@) && \\\n@@ -1504,6 +1529,11 @@ endif\n ALL_CFLAGS = $(DEVELOPER_CFLAGS) $(CPPFLAGS) $(CFLAGS) $(CFLAGS_APPEND)\n ALL_LDFLAGS = $(LDFLAGS) $(LDFLAGS_APPEND)\n \n+ifdef WITH_RUST\n+BASIC_CFLAGS += -DWITH_RUST\n+GITLIBS += $(RUST_LIB)\n+endif\n+\n ifdef SANITIZE\n SANITIZERS := $(foreach flag,$(subst $(comma),$(space),$(SANITIZE)),$(flag))\n BASIC_CFLAGS += -fsanitize=$(SANITIZE) -fno-sanitize-recover=$(SANITIZE)\n@@ -2918,6 +2948,12 @@ scalar$X: scalar.o GIT-LDFLAGS $(GITLIBS)\n $(LIB_FILE): $(LIB_OBJS)\n \t$(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^\n \n+$(RUST_LIB): Cargo.toml $(RUST_SOURCES)\n+\t$(QUIET_CARGO)cargo build $(CARGO_ARGS)\n+\n+.PHONY: rust\n+rust: $(RUST_LIB)\n+\n $(XDIFF_LIB): $(XDIFF_OBJS)\n \t$(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^\n \n@@ -3768,6 +3804,7 @@ clean: profile-clean coverage-clean cocciclean\n \t$(RM) $(FUZZ_PROGRAMS)\n \t$(RM) $(SP_OBJ)\n \t$(RM) $(HCC)\n+\t$(RM) -r Cargo.lock target/\n \t$(RM) version-def.h\n \t$(RM) -r $(dep_dirs) $(compdb_dir) compile_commands.json\n \t$(RM) $(test_bindir_programs)\ndiff --git a/shared.mak b/shared.mak\nindex 5c7bc94785..0e7492076e 100644\n--- a/shared.mak\n+++ b/shared.mak\n@@ -56,6 +56,7 @@ ifndef V\n \tQUIET_MKDIR_P_PARENT  = @echo '   ' MKDIR -p $(@D);\n \n ## Used in \"Makefile\"\n+\tQUIET_CARGO    = @echo '   ' CARGO $@;\n \tQUIET_CC       = @echo '   ' CC $@;\n \tQUIET_AR       = @echo '   ' AR $@;\n \tQUIET_LINK     = @echo '   ' LINK $@;\n\n-- \n2.51.0.618.g983fd99d29.dirty\n\n"},{"id":"527292","messageId":"20250925-b4-pks-rust-breaking-change-v7-4-4e49dcb904d5@pks.im","threadId":"64091","inReplyTo":"20250925-b4-pks-rust-breaking-change-v7-0-4e49dcb904d5@pks.im","subject":"[PATCH v7 4/9] help: report on whether or not Rust is enabled","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-25T06:30:06Z","receivedAt":"2025-09-25T06:30:31Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"We're about to introduce support for Rust into the core of Git, where\nsome (trivial) subsystems are converted to Rust. These subsystems will\nalso retain a C implementation though as Rust is not yet mandatory.\nConsequently, it now becomes possible for a Git version to have bugs\nthat are specific to whether or not it is built with Rust support\noverall.\n\nExpose information about whether or not Git was built with Rust via our\nbuild info. This means that both `git version --build-options`, but also\n`git bugreport` will now expose that bit of information. Hopefully, this\nshould make it easier for us to discover any Rust-specific issues.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n help.c | 6 ++++++\n 1 file changed, 6 insertions(+)\n\ndiff --git a/help.c b/help.c\nindex bb20498cfd..5854dd4a7e 100644\n--- a/help.c\n+++ b/help.c\n@@ -791,6 +791,12 @@ void get_version_info(struct strbuf *buf, int show_build_options)\n \t\tstrbuf_addf(buf, \"shell-path: %s\\n\", SHELL_PATH);\n \t\t/* NEEDSWORK: also save and output GIT-BUILD_OPTIONS? */\n \n+#if defined WITH_RUST\n+\t\tstrbuf_addstr(buf, \"rust: enabled\\n\");\n+#else\n+\t\tstrbuf_addstr(buf, \"rust: disabled\\n\");\n+#endif\n+\n \t\tif (fsmonitor_ipc__is_supported())\n \t\t\tstrbuf_addstr(buf, \"feature: fsmonitor--daemon\\n\");\n #if defined LIBCURL_VERSION\n\n-- \n2.51.0.618.g983fd99d29.dirty\n\n"},{"id":"527293","messageId":"20250925-b4-pks-rust-breaking-change-v7-5-4e49dcb904d5@pks.im","threadId":"64091","inReplyTo":"20250925-b4-pks-rust-breaking-change-v7-0-4e49dcb904d5@pks.im","subject":"[PATCH v7 5/9] varint: use explicit width for integers","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-25T06:30:07Z","receivedAt":"2025-09-25T06:30:35Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The varint subsystem currently uses implcit widths for integers. On the\none hand we use `uintmax_t` for the actual value. On the other hand, we\nuse `int` for the length of the encoded varint.\n\nBoth of these have known maximum vaules, as we only support at most 16\nbytes when encoding varints. Thus, we know that we won't ever exceed\n`uint64_t` for the actual value and `uint8_t` for the prefix length.\n\nRefactor the code to use explicit widths. Besides making the logic\nplatform-independent, it also makes our life a bit easier in the next\ncommit, where we reimplement \"varint.c\" in Rust.\n\nSuggested-by: Ezekiel Newren <ezekielnewren@gmail.com>\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n dir.c        | 18 ++++++++++--------\n read-cache.c |  6 ++++--\n varint.c     |  6 +++---\n varint.h     |  4 ++--\n 4 files changed, 19 insertions(+), 15 deletions(-)\n\ndiff --git a/dir.c b/dir.c\nindex 71108ac79b7..0a67a99cb3d 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -3579,7 +3579,8 @@ static void write_one_dir(struct untracked_cache_dir *untracked,\n \tstruct stat_data stat_data;\n \tstruct strbuf *out = &wd->out;\n \tunsigned char intbuf[16];\n-\tunsigned int intlen, value;\n+\tunsigned int value;\n+\tuint8_t intlen;\n \tint i = wd->index++;\n \n \t/*\n@@ -3632,7 +3633,7 @@ void write_untracked_extension(struct strbuf *out, struct untracked_cache *untra\n \tstruct ondisk_untracked_cache *ouc;\n \tstruct write_data wd;\n \tunsigned char varbuf[16];\n-\tint varint_len;\n+\tuint8_t varint_len;\n \tconst unsigned hashsz = the_hash_algo->rawsz;\n \n \tCALLOC_ARRAY(ouc, 1);\n@@ -3738,7 +3739,7 @@ static int read_one_dir(struct untracked_cache_dir **untracked_,\n \tstruct untracked_cache_dir ud, *untracked;\n \tconst unsigned char *data = rd->data, *end = rd->end;\n \tconst unsigned char *eos;\n-\tunsigned int value;\n+\tuint64_t value;\n \tint i;\n \n \tmemset(&ud, 0, sizeof(ud));\n@@ -3830,7 +3831,8 @@ struct untracked_cache *read_untracked_extension(const void *data, unsigned long\n \tstruct read_data rd;\n \tconst unsigned char *next = data, *end = (const unsigned char *)data + sz;\n \tconst char *ident;\n-\tint ident_len;\n+\tuint64_t ident_len;\n+\tuint64_t varint_len;\n \tssize_t len;\n \tconst char *exclude_per_dir;\n \tconst unsigned hashsz = the_hash_algo->rawsz;\n@@ -3867,8 +3869,8 @@ struct untracked_cache *read_untracked_extension(const void *data, unsigned long\n \tif (next >= end)\n \t\tgoto done2;\n \n-\tlen = decode_varint(&next);\n-\tif (next > end || len == 0)\n+\tvarint_len = decode_varint(&next);\n+\tif (next > end || varint_len == 0)\n \t\tgoto done2;\n \n \trd.valid      = ewah_new();\n@@ -3877,9 +3879,9 @@ struct untracked_cache *read_untracked_extension(const void *data, unsigned long\n \trd.data\t      = next;\n \trd.end\t      = end;\n \trd.index      = 0;\n-\tALLOC_ARRAY(rd.ucd, len);\n+\tALLOC_ARRAY(rd.ucd, varint_len);\n \n-\tif (read_one_dir(&uc->root, &rd) || rd.index != len)\n+\tif (read_one_dir(&uc->root, &rd) || rd.index != varint_len)\n \t\tgoto done;\n \n \tnext = rd.data;\ndiff --git a/read-cache.c b/read-cache.c\nindex 06ad74db228..41b44148b1e 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -1807,7 +1807,7 @@ static struct cache_entry *create_from_disk(struct mem_pool *ce_mem_pool,\n \n \tif (expand_name_field) {\n \t\tconst unsigned char *cp = (const unsigned char *)name;\n-\t\tsize_t strip_len, previous_len;\n+\t\tuint64_t strip_len, previous_len;\n \n \t\t/* If we're at the beginning of a block, ignore the previous name */\n \t\tstrip_len = decode_varint(&cp);\n@@ -2655,8 +2655,10 @@ static int ce_write_entry(struct hashfile *f, struct cache_entry *ce,\n \t\thashwrite(f, ce->name, len);\n \t\thashwrite(f, padding, align_padding_size(size, len));\n \t} else {\n-\t\tint common, to_remove, prefix_size;\n+\t\tint common, to_remove;\n+\t\tuint8_t prefix_size;\n \t\tunsigned char to_remove_vi[16];\n+\n \t\tfor (common = 0;\n \t\t     (common < previous_name->len &&\n \t\t      ce->name[common] &&\ndiff --git a/varint.c b/varint.c\nindex 409c4977a1e..03cd54416b6 100644\n--- a/varint.c\n+++ b/varint.c\n@@ -1,11 +1,11 @@\n #include \"git-compat-util.h\"\n #include \"varint.h\"\n \n-uintmax_t decode_varint(const unsigned char **bufp)\n+uint64_t decode_varint(const unsigned char **bufp)\n {\n \tconst unsigned char *buf = *bufp;\n \tunsigned char c = *buf++;\n-\tuintmax_t val = c & 127;\n+\tuint64_t val = c & 127;\n \twhile (c & 128) {\n \t\tval += 1;\n \t\tif (!val || MSB(val, 7))\n@@ -17,7 +17,7 @@ uintmax_t decode_varint(const unsigned char **bufp)\n \treturn val;\n }\n \n-int encode_varint(uintmax_t value, unsigned char *buf)\n+uint8_t encode_varint(uint64_t value, unsigned char *buf)\n {\n \tunsigned char varint[16];\n \tunsigned pos = sizeof(varint) - 1;\ndiff --git a/varint.h b/varint.h\nindex f78bb0ca528..eb401935bd2 100644\n--- a/varint.h\n+++ b/varint.h\n@@ -1,7 +1,7 @@\n #ifndef VARINT_H\n #define VARINT_H\n \n-int encode_varint(uintmax_t, unsigned char *);\n-uintmax_t decode_varint(const unsigned char **);\n+uint8_t encode_varint(uint64_t, unsigned char *);\n+uint64_t decode_varint(const unsigned char **);\n \n #endif /* VARINT_H */\n\n-- \n2.51.0.618.g983fd99d29.dirty\n\n"},{"id":"527294","messageId":"20250925-b4-pks-rust-breaking-change-v7-6-4e49dcb904d5@pks.im","threadId":"64091","inReplyTo":"20250925-b4-pks-rust-breaking-change-v7-0-4e49dcb904d5@pks.im","subject":"[PATCH v7 6/9] varint: reimplement as test balloon for Rust","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-25T06:30:08Z","receivedAt":"2025-09-25T06:30:39Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Implement a trivial test balloon for our Rust build infrastructure by\nreimplementing the \"varint.c\" subsystem in Rust. This subsystem is\nchosen because it is trivial to convert and because it doesn't have any\ndependencies to other components of Git.\n\nIf support for Rust is enabled, we stop compiling \"varint.c\" and instead\ncompile and use \"src/varint.rs\".\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n Makefile        |  3 ++\n meson.build     |  5 +++-\n src/lib.rs      |  1 +\n src/meson.build |  1 +\n src/varint.rs   | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n 5 files changed, 101 insertions(+), 1 deletion(-)\n\ndiff --git a/Makefile b/Makefile\nindex 31e79342e1d..2a7fc5cb1f3 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -1307,7 +1307,9 @@ LIB_OBJS += urlmatch.o\n LIB_OBJS += usage.o\n LIB_OBJS += userdiff.o\n LIB_OBJS += utf8.o\n+ifndef WITH_RUST\n LIB_OBJS += varint.o\n+endif\n LIB_OBJS += version.o\n LIB_OBJS += versioncmp.o\n LIB_OBJS += walker.o\n@@ -1499,6 +1501,7 @@ CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/unit-test.o\n UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o\n \n RUST_SOURCES += src/lib.rs\n+RUST_SOURCES += src/varint.rs\n \n GIT-VERSION-FILE: FORCE\n \t@OLD=$$(cat $@ 2>/dev/null || :) && \\\ndiff --git a/meson.build b/meson.build\nindex 234a9e9d6fd..37dfa286017 100644\n--- a/meson.build\n+++ b/meson.build\n@@ -522,7 +522,6 @@ libgit_sources = [\n   'usage.c',\n   'userdiff.c',\n   'utf8.c',\n-  'varint.c',\n   'version.c',\n   'versioncmp.c',\n   'walker.c',\n@@ -1707,6 +1706,10 @@ rust_option = get_option('rust').disable_auto_if(not cargo.found())\n if rust_option.allowed()\n   subdir('src')\n   libgit_c_args += '-DWITH_RUST'\n+else\n+  libgit_sources += [\n+    'varint.c',\n+  ]\n endif\n \n libgit = declare_dependency(\ndiff --git a/src/lib.rs b/src/lib.rs\nindex e69de29bb2d..9da70d8b57d 100644\n--- a/src/lib.rs\n+++ b/src/lib.rs\n@@ -0,0 +1 @@\n+pub mod varint;\ndiff --git a/src/meson.build b/src/meson.build\nindex c8d874b2106..25b9ad5a147 100644\n--- a/src/meson.build\n+++ b/src/meson.build\n@@ -1,5 +1,6 @@\n libgit_rs_sources = [\n   'lib.rs',\n+  'varint.rs',\n ]\n \n # Unfortunately we must use a wrapper command to move the output file into the\ndiff --git a/src/varint.rs b/src/varint.rs\nnew file mode 100644\nindex 00000000000..6e610bdd8e0\n--- /dev/null\n+++ b/src/varint.rs\n@@ -0,0 +1,92 @@\n+#[no_mangle]\n+pub unsafe extern \"C\" fn decode_varint(bufp: *mut *const u8) -> u64 {\n+    let mut buf = *bufp;\n+    let mut c = *buf;\n+    let mut val = u64::from(c & 127);\n+\n+    buf = buf.add(1);\n+\n+    while (c & 128) != 0 {\n+        val = val.wrapping_add(1);\n+        if val == 0 || val.leading_zeros() < 7 {\n+            return 0; // overflow\n+        }\n+\n+        c = *buf;\n+        buf = buf.add(1);\n+\n+        val = (val << 7) + u64::from(c & 127);\n+    }\n+\n+    *bufp = buf;\n+    val\n+}\n+\n+#[no_mangle]\n+pub unsafe extern \"C\" fn encode_varint(value: u64, buf: *mut u8) -> u8 {\n+    let mut varint: [u8; 16] = [0; 16];\n+    let mut pos = varint.len() - 1;\n+\n+    varint[pos] = (value & 127) as u8;\n+\n+    let mut value = value >> 7;\n+    while value != 0 {\n+        pos -= 1;\n+        value -= 1;\n+        varint[pos] = 128 | (value & 127) as u8;\n+        value >>= 7;\n+    }\n+\n+    if !buf.is_null() {\n+        std::ptr::copy_nonoverlapping(varint.as_ptr().add(pos), buf, varint.len() - pos);\n+    }\n+\n+    (varint.len() - pos) as u8\n+}\n+\n+#[cfg(test)]\n+mod tests {\n+    use super::*;\n+\n+    #[test]\n+    fn test_decode_varint() {\n+        unsafe {\n+            assert_eq!(decode_varint(&mut [0x00].as_slice().as_ptr()), 0);\n+            assert_eq!(decode_varint(&mut [0x01].as_slice().as_ptr()), 1);\n+            assert_eq!(decode_varint(&mut [0x7f].as_slice().as_ptr()), 127);\n+            assert_eq!(decode_varint(&mut [0x80, 0x00].as_slice().as_ptr()), 128);\n+            assert_eq!(decode_varint(&mut [0x80, 0x01].as_slice().as_ptr()), 129);\n+            assert_eq!(decode_varint(&mut [0x80, 0x7f].as_slice().as_ptr()), 255);\n+\n+            // Overflows are expected to return 0.\n+            assert_eq!(decode_varint(&mut [0x88; 16].as_slice().as_ptr()), 0);\n+        }\n+    }\n+\n+    #[test]\n+    fn test_encode_varint() {\n+        unsafe {\n+            let mut varint: [u8; 16] = [0; 16];\n+\n+            assert_eq!(encode_varint(0, std::ptr::null_mut()), 1);\n+\n+            assert_eq!(encode_varint(0, varint.as_mut_slice().as_mut_ptr()), 1);\n+            assert_eq!(varint, [0; 16]);\n+\n+            assert_eq!(encode_varint(10, varint.as_mut_slice().as_mut_ptr()), 1);\n+            assert_eq!(varint, [10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n+\n+            assert_eq!(encode_varint(127, varint.as_mut_slice().as_mut_ptr()), 1);\n+            assert_eq!(varint, [127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n+\n+            assert_eq!(encode_varint(128, varint.as_mut_slice().as_mut_ptr()), 2);\n+            assert_eq!(varint, [128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n+\n+            assert_eq!(encode_varint(129, varint.as_mut_slice().as_mut_ptr()), 2);\n+            assert_eq!(varint, [128, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n+\n+            assert_eq!(encode_varint(255, varint.as_mut_slice().as_mut_ptr()), 2);\n+            assert_eq!(varint, [128, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n+        }\n+    }\n+}\n\n-- \n2.51.0.618.g983fd99d29.dirty\n\n"},{"id":"527295","messageId":"20250925-b4-pks-rust-breaking-change-v7-7-4e49dcb904d5@pks.im","threadId":"64091","inReplyTo":"20250925-b4-pks-rust-breaking-change-v7-0-4e49dcb904d5@pks.im","subject":"[PATCH v7 7/9] BreakingChanges: announce Rust becoming mandatory","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-25T06:30:09Z","receivedAt":"2025-09-25T06:30:42Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Over the last couple of years the appetite for bringing Rust into the\ncodebase has grown significantly across the developer base. Introducing\nRust is a major change though and has ramifications for the whole\necosystem:\n\n  - Some platforms have a Rust toolchain available, but have not yet\n    integrated it into their build infrastructure.\n\n  - Some platforms don't have any support for Rust at all.\n\n  - Some platforms may have to figure out how to fit Rust into their\n    bootstrapping sequence.\n\nDue to this, and given that Git is a critical piece of infrastructure\nfor the whole industry, we cannot just introduce such a heavyweight\ndependency without doing our due diligence.\n\nInstead, preceding commits have introduced a test balloon into our build\ninfrastructure that convert one tiny subsystem to use Rust. For now,\nusing Rust to build that subsystem is entirely optional -- if no Rust\nsupport is available, we continue to use the C implementation. This test\nballoon has the intention to give distributions time and let them ease\ninto our adoption of Rust.\n\nHaving multiple implementations of the same subsystem is not sustainable\nthough, and the plan is to eventually be able to use Rust freely all\nacross our codebase. As such, there is the intent to make Rust become a\nmandatory part of our build process.\n\nAdd an announcement to our breaking changes that Rust will become\nmandatory in Git 3.0. A (very careful and non-binding) estimate might be\nthat this major release might be released in the second half of next\nyear, which should give distributors enough time to prepare for the\nchange.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n Documentation/BreakingChanges.adoc | 45 ++++++++++++++++++++++++++++++++++++++\n 1 file changed, 45 insertions(+)\n\ndiff --git a/Documentation/BreakingChanges.adoc b/Documentation/BreakingChanges.adoc\nindex f8d2eba061..c21f902134 100644\n--- a/Documentation/BreakingChanges.adoc\n+++ b/Documentation/BreakingChanges.adoc\n@@ -165,6 +165,51 @@ A prerequisite for this change is that the ecosystem is ready to support the\n \"reftable\" format. Most importantly, alternative implementations of Git like\n JGit, libgit2 and Gitoxide need to support it.\n \n+* Git will require Rust as a mandatory part of the build process. While Git\n+  already started to adopt Rust in Git 2.49, all parts written in Rust are\n+  optional for the time being. This includes:\n++\n+  ** The Rust wrapper around libgit.a that is part of \"contrib/\" and which has\n+     been introduced in Git 2.49.\n+  ** Subsystems that have an alternative implementation in Rust to test\n+     interoperability between our C and Rust codebase.\n+  ** Newly written features that are not mission critical for a fully functional\n+     Git client.\n++\n+These changes are meant as test balloons to allow distributors of Git to prepare\n+for Rust becoming a mandatory part of the build process. There will be multiple\n+milestones for the introduction of Rust:\n++\n+--\n+1. Initially, with Git 2.52, support for Rust will be auto-detected by Meson and\n+   disabled in our Makefile so that the project can sort out the initial\n+   infrastructure.\n+2. In Git 2.53, both build systems will default-enable support for Rust.\n+   Consequently, builds will break by default if Rust is not available on the\n+   build host. The use of Rust can still be explicitly disabled via build\n+   flags.\n+3. In Git 3.0, the build options will be removed and support for Rust is\n+   mandatory.\n+--\n++\n+You can explicitly ask both Meson and our Makefile-based system to enable Rust\n+by saying `meson configure -Drust=enabled` and `make WITH_RUST=YesPlease`,\n+respectively.\n++\n+The Git project will declare the last version before Git 3.0 to be a long-term\n+support release. This long-term release will receive important bug fixes for at\n+least four release cycles and security fixes for six release cycles. The Git\n+project will hand over maintainership of the long-term release to distributors\n+in case they need to extend the life of that long-term release even further.\n+Details of how this long-term release will be handed over to the community will\n+be discussed once the Git project decides to stop officially supporting it.\n++\n+We will evaluate the impact on downstream distributions before making Rust\n+mandatory in Git 3.0. If we see that the impact on downstream distributions\n+would be significant, we may decide to defer this change to a subsequent minor\n+release. This evaluation will also take into account our own experience with\n+how painful it is to keep Rust an optional component.\n+\n === Removals\n \n * Support for grafting commits has long been superseded by git-replace(1).\n\n-- \n2.51.0.618.g983fd99d29.dirty\n\n"},{"id":"527296","messageId":"20250925-b4-pks-rust-breaking-change-v7-8-4e49dcb904d5@pks.im","threadId":"64091","inReplyTo":"20250925-b4-pks-rust-breaking-change-v7-0-4e49dcb904d5@pks.im","subject":"[PATCH v7 8/9] ci: convert \"pedantic\" job into full build with breaking changes","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-25T06:30:10Z","receivedAt":"2025-09-25T06:30:45Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The \"pedantic\" CI job is building on Fedora with `DEVOPTS=pedantic`.\nThis build flag doesn't do anything anymore starting with 6a8cbc41ba\n(developer: enable pedantic by default, 2021-09-03), where we have\nflipped the default so that developers have to opt-out of pedantic\nbuilds via the \"no-pedantic\" option. As such, all this job really does\nis to do a normal build on Fedora, which isn't all that interesting.\n\nConvert that job into a full build-and-test job that uses Meson with\nbreaking changes enabled. This plugs two gaps:\n\n  - We now test on another distro that we didn't run tests on\n    beforehand.\n\n  - We verify that breaking changes work as expected with Meson.\n\nFurthermore, in a subsequent commit we'll modify both jobs that use\nbreaking changes to also enable Rust. By converting the Fedora job to\nuse Meson, we ensure that we test our Rust build infrastructure for both\nbuild systems.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n .github/workflows/main.yml |  4 ++--\n .gitlab-ci.yml             |  4 ++--\n ci/install-dependencies.sh |  6 +++++-\n ci/run-build-and-tests.sh  | 29 ++++++++---------------------\n 4 files changed, 17 insertions(+), 26 deletions(-)\n\ndiff --git a/.github/workflows/main.yml b/.github/workflows/main.yml\nindex d122e79415..393ea4d1cc 100644\n--- a/.github/workflows/main.yml\n+++ b/.github/workflows/main.yml\n@@ -379,6 +379,8 @@ jobs:\n         - jobname: linux-breaking-changes\n           cc: gcc\n           image: ubuntu:rolling\n+        - jobname: fedora-breaking-changes-meson\n+          image: fedora:latest\n         - jobname: linux-leaks\n           image: ubuntu:rolling\n           cc: gcc\n@@ -396,8 +398,6 @@ jobs:\n         # Supported until 2025-04-02.\n         - jobname: linux32\n           image: i386/ubuntu:focal\n-        - jobname: pedantic\n-          image: fedora:latest\n         # A RHEL 8 compatible distro.  Supported until 2029-05-31.\n         - jobname: almalinux-8\n           image: almalinux:8\ndiff --git a/.gitlab-ci.yml b/.gitlab-ci.yml\nindex af10ebb59a..4248506909 100644\n--- a/.gitlab-ci.yml\n+++ b/.gitlab-ci.yml\n@@ -45,6 +45,8 @@ test:linux:\n       - jobname: linux-breaking-changes\n         image: ubuntu:20.04\n         CC: gcc\n+      - jobname: fedora-breaking-changes-meson\n+        image: fedora:latest\n       - jobname: linux-TEST-vars\n         image: ubuntu:20.04\n         CC: gcc\n@@ -58,8 +60,6 @@ test:linux:\n       - jobname: linux-asan-ubsan\n         image: ubuntu:rolling\n         CC: clang\n-      - jobname: pedantic\n-        image: fedora:latest\n       - jobname: linux-musl-meson\n         image: alpine:latest\n       - jobname: linux32\ndiff --git a/ci/install-dependencies.sh b/ci/install-dependencies.sh\nindex d061a47293..35bd05b85b 100755\n--- a/ci/install-dependencies.sh\n+++ b/ci/install-dependencies.sh\n@@ -30,8 +30,12 @@ alpine-*)\n \t\tbash cvs gnupg perl-cgi perl-dbd-sqlite perl-io-tty >/dev/null\n \t;;\n fedora-*|almalinux-*)\n+\tcase \"$jobname\" in\n+\t*-meson)\n+\t\tMESON_DEPS=\"meson ninja\";;\n+\tesac\n \tdnf -yq update >/dev/null &&\n-\tdnf -yq install shadow-utils sudo make gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel >/dev/null\n+\tdnf -yq install shadow-utils sudo make pkg-config gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel $MESON_DEPS >/dev/null\n \t;;\n ubuntu-*|i386/ubuntu-*|debian-*)\n \t# Required so that apt doesn't wait for user input on certain packages.\ndiff --git a/ci/run-build-and-tests.sh b/ci/run-build-and-tests.sh\nindex 01823fd0f1..3680446649 100755\n--- a/ci/run-build-and-tests.sh\n+++ b/ci/run-build-and-tests.sh\n@@ -5,12 +5,11 @@\n \n . ${0%/*}/lib.sh\n \n-run_tests=t\n-\n case \"$jobname\" in\n-linux-breaking-changes)\n+fedora-breaking-changes-musl|linux-breaking-changes)\n \texport GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main\n \texport WITH_BREAKING_CHANGES=YesPlease\n+\tMESONFLAGS=\"$MESONFLAGS -Dbreaking_changes=true\"\n \t;;\n linux-TEST-vars)\n \texport OPENSSL_SHA1_UNSAFE=YesPlease\n@@ -36,12 +35,6 @@ linux-sha256)\n linux-reftable|linux-reftable-leaks|osx-reftable)\n \texport GIT_TEST_DEFAULT_REF_FORMAT=reftable\n \t;;\n-pedantic)\n-\t# Don't run the tests; we only care about whether Git can be\n-\t# built.\n-\texport DEVOPTS=pedantic\n-\trun_tests=\n-\t;;\n esac\n \n case \"$jobname\" in\n@@ -54,21 +47,15 @@ case \"$jobname\" in\n \t\t-Dtest_output_directory=\"${TEST_OUTPUT_DIRECTORY:-$(pwd)/t}\" \\\n \t\t$MESONFLAGS\n \tgroup \"Build\" meson compile -C build --\n-\tif test -n \"$run_tests\"\n-\tthen\n-\t\tgroup \"Run tests\" meson test -C build --print-errorlogs --test-args=\"$GIT_TEST_OPTS\" || (\n-\t\t\t./t/aggregate-results.sh \"${TEST_OUTPUT_DIRECTORY:-t}/test-results\"\n-\t\t\thandle_failed_tests\n-\t\t)\n-\tfi\n+\tgroup \"Run tests\" meson test -C build --print-errorlogs --test-args=\"$GIT_TEST_OPTS\" || (\n+\t\t./t/aggregate-results.sh \"${TEST_OUTPUT_DIRECTORY:-t}/test-results\"\n+\t\thandle_failed_tests\n+\t)\n \t;;\n *)\n \tgroup Build make\n-\tif test -n \"$run_tests\"\n-\tthen\n-\t\tgroup \"Run tests\" make test ||\n-\t\thandle_failed_tests\n-\tfi\n+\tgroup \"Run tests\" make test ||\n+\thandle_failed_tests\n \t;;\n esac\n \n\n-- \n2.51.0.618.g983fd99d29.dirty\n\n"},{"id":"527297","messageId":"20250925-b4-pks-rust-breaking-change-v7-9-4e49dcb904d5@pks.im","threadId":"64091","inReplyTo":"20250925-b4-pks-rust-breaking-change-v7-0-4e49dcb904d5@pks.im","subject":"[PATCH v7 9/9] ci: enable Rust for breaking-changes jobs","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-09-25T06:30:11Z","receivedAt":"2025-09-25T06:30:48Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Enable Rust for our breaking-changes jobs so that we can verify that the\nbuild infrastructure and the converted Rust subsystems work as expected.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n ci/install-dependencies.sh | 4 ++--\n ci/run-build-and-tests.sh  | 2 ++\n 2 files changed, 4 insertions(+), 2 deletions(-)\n\ndiff --git a/ci/install-dependencies.sh b/ci/install-dependencies.sh\nindex 35bd05b85b..0d3aa496fc 100755\n--- a/ci/install-dependencies.sh\n+++ b/ci/install-dependencies.sh\n@@ -35,7 +35,7 @@ fedora-*|almalinux-*)\n \t\tMESON_DEPS=\"meson ninja\";;\n \tesac\n \tdnf -yq update >/dev/null &&\n-\tdnf -yq install shadow-utils sudo make pkg-config gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel $MESON_DEPS >/dev/null\n+\tdnf -yq install shadow-utils sudo make pkg-config gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel $MESON_DEPS cargo >/dev/null\n \t;;\n ubuntu-*|i386/ubuntu-*|debian-*)\n \t# Required so that apt doesn't wait for user input on certain packages.\n@@ -62,7 +62,7 @@ ubuntu-*|i386/ubuntu-*|debian-*)\n \t\tmake libssl-dev libcurl4-openssl-dev libexpat-dev wget sudo default-jre \\\n \t\ttcl tk gettext zlib1g-dev perl-modules liberror-perl libauthen-sasl-perl \\\n \t\tlibemail-valid-perl libio-pty-perl libio-socket-ssl-perl libnet-smtp-ssl-perl libdbd-sqlite3-perl libcgi-pm-perl \\\n-\t\tlibsecret-1-dev libpcre2-dev meson ninja-build pkg-config \\\n+\t\tlibsecret-1-dev libpcre2-dev meson ninja-build pkg-config cargo \\\n \t\t${CC_PACKAGE:-${CC:-gcc}} $PYTHON_PACKAGE\n \n \tcase \"$distro\" in\ndiff --git a/ci/run-build-and-tests.sh b/ci/run-build-and-tests.sh\nindex 3680446649..c718bd101a 100755\n--- a/ci/run-build-and-tests.sh\n+++ b/ci/run-build-and-tests.sh\n@@ -9,7 +9,9 @@ case \"$jobname\" in\n fedora-breaking-changes-musl|linux-breaking-changes)\n \texport GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main\n \texport WITH_BREAKING_CHANGES=YesPlease\n+\texport WITH_RUST=YesPlease\n \tMESONFLAGS=\"$MESONFLAGS -Dbreaking_changes=true\"\n+\tMESONFLAGS=\"$MESONFLAGS -Drust=enabled\"\n \t;;\n linux-TEST-vars)\n \texport OPENSSL_SHA1_UNSAFE=YesPlease\n\n-- \n2.51.0.618.g983fd99d29.dirty\n\n"},{"id":"527335","messageId":"xmqqikh6h4ma.fsf@gitster.g","threadId":"64091","inReplyTo":"20250925-b4-pks-rust-breaking-change-v7-0-4e49dcb904d5@pks.im","subject":"Re: [PATCH v7 0/9] Introduce Rust and announce that it will become mandatory","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-09-25T16:35:41Z","receivedAt":"2025-09-25T16:35:45Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> Hi,\n>\n> this small patch series introduces Rust into the core of Git. This patch\n> series is designed as a test balloon, similar to how we introduced test\n> balloons for C99 features in the past. The goal is threefold:\n>\n>   - Give us some time to experiment with Rust and introduce proper build\n>     infrastructure.\n>\n>   - Give distributors time to ease into the new toolchain requirements.\n>     Introducing Rust is impossible for some platforms and hard for\n>     others.\n>\n>   - Announce that Git 3.0 will make Rust a mandatory part of our build\n>     infrastructure.\n>\n> The test balloon itself is quite uninteresting: I've chosen to convert\n> the \"varint.c\" subsystem, mostly because it is trivial and does not have\n> any dependencies. But it does allow us to verify that C to Rust interop\n> works as expected, and to play around with tooling. All tests pass with\n> the \"varint.rs\" implementation.\n>\n> For now, the series only contains support for Meson. If we agree to go\n> down this route I'll also introduce support for Rust into our Makefiles\n> at a later point in time.\n>\n> Furthermore missing is additional tooling:\n>\n>   - At least one CI job to verify that Rust builds and works as\n>     expected.\n>\n>   - Tooling and CI jobs to ensure that we have consistent formatting via\n>     `cargo format`.\n>\n> And probably lots more. As said, the entire goal is for us to have an\n> easy playground that we can experiment on and develop the infrastructure\n> incrementally without yet having to commit to anything.\n>\n> I'm mostly splitting out the topic of introducing Rust from the larger\n> series that introduce it into xdiff so that we can focus more on the\n> actual process of introducing Rust into Git and less on the potential\n> features that we want to build on top of it.\n> ...\n> Changes in v7:\n>   - Rename \"git\" crate to \"gitcore\".\n>   - Some word smithing for the breaking changes doc.\n>   - Punt on the exact details of how we hand over maintenance of the LTS\n>     release to the community. This is something we can decide on in the\n>     future.\n>   - Link to v6: https://lore.kernel.org/r/20250923-b4-pks-rust-breaking-change-v6-0-59076fee486a@pks.im\n\nOK, I see that this is with minimum changes relative to earlier\neditions (like clarifying in BreakingChanges the release number in\nwhich we started toying with Rust, and renamibng <libgit> to\n<libgitcore>).  Hopefully we are getting at the end of the tunnel?\n\nIf I recall the coordination discussion correctly, when people are\nhappy with this series, Ezekiel's stuff (not the \"xdiff clean-up\"\nthat is to improve/adjust code that is purely in C without any Rust\ncomponent, which can independently advance without waiting for any\nof these) will be rebuilt on top.\n\nWill replace; I am hoping to hear positive reactions as well as\n\"here we want to improve it this way\" comments.\n\nThanks.\n"},{"id":"527358","messageId":"06de5ccc-98e5-4bb6-bb09-e67be906ff6d@ramsayjones.plus.com","threadId":"64091","inReplyTo":"20250925-b4-pks-rust-breaking-change-v7-2-4e49dcb904d5@pks.im","subject":"Re: [PATCH v7 2/9] Makefile: reorder sources after includes","fromName":"Ramsay Jones","fromEmail":"ramsay@ramsayjones.plus.com","sentAt":"2025-09-25T21:33:22Z","receivedAt":"2025-09-25T21:36:37Z","isPatch":true,"sender":{"key":"ramsay@ramsayjones.plus.com","avatar":"https://avatars.githubusercontent.com/u/33702710?v=4"},"body":"\n\nOn 25/09/2025 7:30 am, Patrick Steinhardt wrote:\n> In an upcoming change we'll make some of the sources compile\n> conditionally based on whether or not `WITH_RUST` is defined. To let\n> developers specify that flag in their \"config.mak\" we'll thus have to\n> reorder our sources so that they come after the include of that file.\n> \n> Do so.\n\nYep, I have a very similar patch which I used recently on cygwin so that\nI could just 'make' git - having to remember to type 'make WITH_RUST=false'\nall the time (and always forgetting) was somewhat annoying! :)\n\nSo, thanks for that!\n\nATB,\nRamsay Jones\n\n\n"},{"id":"527448","messageId":"CAH=ZcbCEioNGaksTKnYyakABWGwTWv4WQZCnOtARydtLrx11MQ@mail.gmail.com","threadId":"64091","inReplyTo":"20250925011043.M401827@dcvr","subject":"Re: what's missing from newer C? [was: [PATCH v5 0/9] Introduce Rust ....]","fromName":"Ezekiel Newren","fromEmail":"ezekielnewren@gmail.com","sentAt":"2025-09-26T22:17:49Z","receivedAt":"2025-09-26T22:18:03Z","isPatch":true,"sender":{"key":"ezekielnewren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/18313324?v=4"},"body":"On Wed, Sep 24, 2025 at 7:10 PM Eric Wong <e@80x24.org> wrote:\n> What else is missing from C?\n\n1. Checked Arithmetic\n  * C23: <stdckdint.h> for checked integer operations.\n  * Rust: built-ins like checked_add, wrapping_add.\n2. __counted_by__ attribute\n  * Clang 18 / GCC 15: experimental, helps catch buffer overflows.\n  * Rust: slices already carry length, preventing out-of-bounds by design.\n3. __cleanup__ attribute\n  * GCC, Clang, TinyCC: long-standing extension for RAII-like cleanup.\n  * Rust: Drop trait ensures deterministic cleanup.\n4. RCU / concurrency libraries\n  * Userspace RCU, ConcurrencyKit, etc. available in C.\n  * Rust: crossbeam, Arc, lock-free crates.\n5. Format string checking\n  * GCC/Clang/MSVC check format strings at compile time.\n  * Rust: format! macros type-check arguments.\n6. Regex and parsing\n  * C: POSIX regex, PCRE2, re2c, wuffs.\n  * Rust: regex crate (safe, no unchecked buffer access).\n7. Dynamic analysis\n  * C: Valgrind, ASan, TSan, UBSan, MSan.\n  * Rust: Miri, LLVM sanitizers.\n\nWhat else is missing in C?\n\nCompared to Rust, here's where C still falls short at the language\nlevel (not just tooling):\n\n1. Ownership and lifetimes\n  * No borrow checker; compiler can't prevent use-after-free, double\nfree, or aliasing bugs.\n2. Async/await coroutines\n  * No language support. Async requires threads, callbacks, or libraries.\n  * Rust: async fn / .await integrated into the language.\n3. Explicit numeric conversions\n  * C silently promotes between ints/floats/signed/unsigned.\n  * Rust requires explicit casts (down and up), reducing surprises.\n4. Sum types with exhaustiveness checks\n  * C: enum + union is manual, compiler won’t enforce full handling.\n  * Rust: enum + match requires covering all variants.\n5. Safer error handling\n  * C: errno, return codes, ad hoc conventions.\n  * Rust: Result<T, E> + ? operator, forcing handling.\n6. Concurrency safety by design\n  * C11 added atomics, but race conditions are unchecked.\n  * Rust: Send / Sync traits enforce thread-safety at compile time.\n7. Namespaces / modules\n  * C: relies on foo_bar() prefixes and headers.\n  * Rust: mod and crate system.\n8. Default immutability\n  * C: everything mutable unless marked const.\n  * Rust: immutable by default, opt into mut. You have a choice of 1\nmutable reference xor many immutable references to something.\n9. Package management\n  * C: out of scope for the language\n  * Rust: built in with Cargo dependencies\n\nIn Rust there is a difference between concurrency and parallelism.\nConcurrency in Rust is about running multiple tasks with a single\nsystem thread. Whereas parallelism is about assigning tasks to\nmultiple threads. I highly doubt that C will ever get coroutines\nbecause it requires the compiler to create a state machine out of each\nfunction that uses async or await keywords. The C language just isn't\nrobust enough for that in my opinion.\n\nAnd there's probably more that I haven't covered here.\n"},{"id":"527630","messageId":"037d8685-6521-4ac1-8251-d93e8a1d7081@app.fastmail.com","threadId":"64091","inReplyTo":"20250925-b4-pks-rust-breaking-change-v7-5-4e49dcb904d5@pks.im","subject":"Re: [PATCH v7 5/9] varint: use explicit width for integers","fromName":"Kristoffer Haugsbakk","fromEmail":"kristofferhaugsbakk@fastmail.com","sentAt":"2025-09-30T13:34:01Z","receivedAt":"2025-09-30T13:34:23Z","isPatch":true,"sender":{"key":"kristofferhaugsbakk@fastmail.com","avatar":null},"body":"On Thu, Sep 25, 2025, at 08:30, Patrick Steinhardt wrote:\n> The varint subsystem currently uses implcit widths for integers. On the\n\ns/implcit/implicit/\n\n> one hand we use `uintmax_t` for the actual value. On the other hand, we\n> use `int` for the length of the encoded varint.\n>\n> Both of these have known maximum vaules, as we only support at most 16\n\ns/vaules/values/\n\n> bytes when encoding varints. Thus, we know that we won't ever exceed\n> `uint64_t` for the actual value and `uint8_t` for the prefix length.\n>[snip]\n"},{"id":"527705","messageId":"CAH=ZcbC6jMUBMLrmwzksAzLM3t=XH+hBnf+=wLdjAcAiWTx7vw@mail.gmail.com","threadId":"64091","inReplyTo":"20250925-b4-pks-rust-breaking-change-v7-6-4e49dcb904d5@pks.im","subject":"Re: [PATCH v7 6/9] varint: reimplement as test balloon for Rust","fromName":"Ezekiel Newren","fromEmail":"ezekielnewren@gmail.com","sentAt":"2025-10-01T17:21:25Z","receivedAt":"2025-10-01T17:21:39Z","isPatch":true,"sender":{"key":"ezekielnewren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/18313324?v=4"},"body":"On Thu, Sep 25, 2025 at 12:30 AM Patrick Steinhardt <ps@pks.im> wrote:\n>  Makefile        |  3 ++\n>  meson.build     |  5 +++-\n>  src/lib.rs      |  1 +\n>  src/meson.build |  1 +\n>  src/varint.rs   | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n>  5 files changed, 101 insertions(+), 1 deletion(-)\n>\n> diff --git a/Makefile b/Makefile\n> index 31e79342e1d..2a7fc5cb1f3 100644\n> --- a/Makefile\n> +++ b/Makefile\n> @@ -1307,7 +1307,9 @@ LIB_OBJS += urlmatch.o\n>  LIB_OBJS += usage.o\n>  LIB_OBJS += userdiff.o\n>  LIB_OBJS += utf8.o\n> +ifndef WITH_RUST\n>  LIB_OBJS += varint.o\n> +endif\n>  LIB_OBJS += version.o\n>  LIB_OBJS += versioncmp.o\n>  LIB_OBJS += walker.o\n> @@ -1499,6 +1501,7 @@ CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/unit-test.o\n>  UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o\n>\n>  RUST_SOURCES += src/lib.rs\n> +RUST_SOURCES += src/varint.rs\n>\n>  GIT-VERSION-FILE: FORCE\n>         @OLD=$$(cat $@ 2>/dev/null || :) && \\\n> diff --git a/meson.build b/meson.build\n> index 234a9e9d6fd..37dfa286017 100644\n> --- a/meson.build\n> +++ b/meson.build\n> @@ -522,7 +522,6 @@ libgit_sources = [\n>    'usage.c',\n>    'userdiff.c',\n>    'utf8.c',\n> -  'varint.c',\n>    'version.c',\n>    'versioncmp.c',\n>    'walker.c',\n> @@ -1707,6 +1706,10 @@ rust_option = get_option('rust').disable_auto_if(not cargo.found())\n>  if rust_option.allowed()\n>    subdir('src')\n>    libgit_c_args += '-DWITH_RUST'\n> +else\n> +  libgit_sources += [\n> +    'varint.c',\n> +  ]\n>  endif\n>\n>  libgit = declare_dependency(\n> diff --git a/src/lib.rs b/src/lib.rs\n> index e69de29bb2d..9da70d8b57d 100644\n> --- a/src/lib.rs\n> +++ b/src/lib.rs\n> @@ -0,0 +1 @@\n> +pub mod varint;\n> diff --git a/src/meson.build b/src/meson.build\n> index c8d874b2106..25b9ad5a147 100644\n> --- a/src/meson.build\n> +++ b/src/meson.build\n> @@ -1,5 +1,6 @@\n>  libgit_rs_sources = [\n>    'lib.rs',\n> +  'varint.rs',\n>  ]\n>\n>  # Unfortunately we must use a wrapper command to move the output file into the\n> diff --git a/src/varint.rs b/src/varint.rs\n> new file mode 100644\n> index 00000000000..6e610bdd8e0\n> --- /dev/null\n> +++ b/src/varint.rs\n> @@ -0,0 +1,92 @@\n> +#[no_mangle]\n> +pub unsafe extern \"C\" fn decode_varint(bufp: *mut *const u8) -> u64 {\n> +    let mut buf = *bufp;\n> +    let mut c = *buf;\n> +    let mut val = u64::from(c & 127);\n> +\n> +    buf = buf.add(1);\n> +\n> +    while (c & 128) != 0 {\n> +        val = val.wrapping_add(1);\n> +        if val == 0 || val.leading_zeros() < 7 {\n> +            return 0; // overflow\n> +        }\n> +\n> +        c = *buf;\n> +        buf = buf.add(1);\n> +\n> +        val = (val << 7) + u64::from(c & 127);\n> +    }\n> +\n> +    *bufp = buf;\n> +    val\n> +}\n> +\n> +#[no_mangle]\n> +pub unsafe extern \"C\" fn encode_varint(value: u64, buf: *mut u8) -> u8 {\n> +    let mut varint: [u8; 16] = [0; 16];\n> +    let mut pos = varint.len() - 1;\n> +\n> +    varint[pos] = (value & 127) as u8;\n> +\n> +    let mut value = value >> 7;\n> +    while value != 0 {\n> +        pos -= 1;\n> +        value -= 1;\n> +        varint[pos] = 128 | (value & 127) as u8;\n> +        value >>= 7;\n> +    }\n> +\n> +    if !buf.is_null() {\n> +        std::ptr::copy_nonoverlapping(varint.as_ptr().add(pos), buf, varint.len() - pos);\n> +    }\n> +\n> +    (varint.len() - pos) as u8\n> +}\n> +\n> +#[cfg(test)]\n> +mod tests {\n> +    use super::*;\n> +\n> +    #[test]\n> +    fn test_decode_varint() {\n> +        unsafe {\n> +            assert_eq!(decode_varint(&mut [0x00].as_slice().as_ptr()), 0);\n> +            assert_eq!(decode_varint(&mut [0x01].as_slice().as_ptr()), 1);\n> +            assert_eq!(decode_varint(&mut [0x7f].as_slice().as_ptr()), 127);\n> +            assert_eq!(decode_varint(&mut [0x80, 0x00].as_slice().as_ptr()), 128);\n> +            assert_eq!(decode_varint(&mut [0x80, 0x01].as_slice().as_ptr()), 129);\n> +            assert_eq!(decode_varint(&mut [0x80, 0x7f].as_slice().as_ptr()), 255);\n> +\n> +            // Overflows are expected to return 0.\n> +            assert_eq!(decode_varint(&mut [0x88; 16].as_slice().as_ptr()), 0);\n> +        }\n> +    }\n> +\n> +    #[test]\n> +    fn test_encode_varint() {\n> +        unsafe {\n> +            let mut varint: [u8; 16] = [0; 16];\n> +\n> +            assert_eq!(encode_varint(0, std::ptr::null_mut()), 1);\n> +\n> +            assert_eq!(encode_varint(0, varint.as_mut_slice().as_mut_ptr()), 1);\n> +            assert_eq!(varint, [0; 16]);\n> +\n> +            assert_eq!(encode_varint(10, varint.as_mut_slice().as_mut_ptr()), 1);\n> +            assert_eq!(varint, [10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n> +\n> +            assert_eq!(encode_varint(127, varint.as_mut_slice().as_mut_ptr()), 1);\n> +            assert_eq!(varint, [127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n> +\n> +            assert_eq!(encode_varint(128, varint.as_mut_slice().as_mut_ptr()), 2);\n> +            assert_eq!(varint, [128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n> +\n> +            assert_eq!(encode_varint(129, varint.as_mut_slice().as_mut_ptr()), 2);\n> +            assert_eq!(varint, [128, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n> +\n> +            assert_eq!(encode_varint(255, varint.as_mut_slice().as_mut_ptr()), 2);\n> +            assert_eq!(varint, [128, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n> +        }\n> +    }\n> +}\n\nLooks good.\n"},{"id":"527706","messageId":"CAH=ZcbBQk9xmTF-m6tX6F+PRmnUSoevyFFvK-fAc3uzL3NvqSQ@mail.gmail.com","threadId":"64091","inReplyTo":"037d8685-6521-4ac1-8251-d93e8a1d7081@app.fastmail.com","subject":"Re: [PATCH v7 5/9] varint: use explicit width for integers","fromName":"Ezekiel Newren","fromEmail":"ezekielnewren@gmail.com","sentAt":"2025-10-01T17:22:44Z","receivedAt":"2025-10-01T17:22:57Z","isPatch":true,"sender":{"key":"ezekielnewren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/18313324?v=4"},"body":"On Tue, Sep 30, 2025 at 7:34 AM Kristoffer Haugsbakk\n<kristofferhaugsbakk@fastmail.com> wrote:\n>\n> On Thu, Sep 25, 2025, at 08:30, Patrick Steinhardt wrote:\n> > The varint subsystem currently uses implcit widths for integers. On the\n>\n> s/implcit/implicit/\n>\n> > one hand we use `uintmax_t` for the actual value. On the other hand, we\n> > use `int` for the length of the encoded varint.\n> >\n> > Both of these have known maximum vaules, as we only support at most 16\n>\n> s/vaules/values/\n\nOther than the typos this looks good.\n"},{"id":"527714","messageId":"CAH=ZcbAF6k-=k2K6Zi6a=igsCt=aDmmA7UXUw-PVL1WJNif2-Q@mail.gmail.com","threadId":"64091","inReplyTo":"xmqqikh6h4ma.fsf@gitster.g","subject":"Re: [PATCH v7 0/9] Introduce Rust and announce that it will become mandatory","fromName":"Ezekiel Newren","fromEmail":"ezekielnewren@gmail.com","sentAt":"2025-10-01T18:43:30Z","receivedAt":"2025-10-01T18:43:44Z","isPatch":true,"sender":{"key":"ezekielnewren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/18313324?v=4"},"body":"On Thu, Sep 25, 2025 at 10:35 AM Junio C Hamano <gitster@pobox.com> wrote:\n> If I recall the coordination discussion correctly, when people are\n> happy with this series, Ezekiel's stuff (not the \"xdiff clean-up\"\n> that is to improve/adjust code that is purely in C without any Rust\n> component, which can independently advance without waiting for any\n> of these) will be rebuilt on top.\n\nYour understanding is correct. I've dropped my \"Introduce Rust\" patch\nseries in favor of Patrick's. Once Patrick's stuff gets merged I'll\nwork on rebasing my Rust stuff on top.\n\nAside from a few typos, this patch series looks good to me.\n"},{"id":"527719","messageId":"xmqqo6qq1k68.fsf@gitster.g","threadId":"64091","inReplyTo":"CAH=ZcbC6jMUBMLrmwzksAzLM3t=XH+hBnf+=wLdjAcAiWTx7vw@mail.gmail.com","subject":"Re: [PATCH v7 6/9] varint: reimplement as test balloon for Rust","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-10-01T19:44:31Z","receivedAt":"2025-10-01T19:44:35Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ezekiel Newren <ezekielnewren@gmail.com> writes:\n\n> On Thu, Sep 25, 2025 at 12:30 AM Patrick Steinhardt <ps@pks.im> wrote:\n>>  Makefile        |  3 ++\n>>  meson.build     |  5 +++-\n>>  src/lib.rs      |  1 +\n>>  src/meson.build |  1 +\n>>  src/varint.rs   | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n>>  5 files changed, 101 insertions(+), 1 deletion(-)\n>...\n>\n> Looks good.\n\nThanks.\n"},{"id":"527759","messageId":"aN4qDbvN10nvNMOo@pks.im","threadId":"64091","inReplyTo":"CAH=ZcbBQk9xmTF-m6tX6F+PRmnUSoevyFFvK-fAc3uzL3NvqSQ@mail.gmail.com","subject":"Re: [PATCH v7 5/9] varint: use explicit width for integers","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-10-02T07:30:21Z","receivedAt":"2025-10-02T07:30:30Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Wed, Oct 01, 2025 at 11:22:44AM -0600, Ezekiel Newren wrote:\n> On Tue, Sep 30, 2025 at 7:34 AM Kristoffer Haugsbakk\n> <kristofferhaugsbakk@fastmail.com> wrote:\n> >\n> > On Thu, Sep 25, 2025, at 08:30, Patrick Steinhardt wrote:\n> > > The varint subsystem currently uses implcit widths for integers. On the\n> >\n> > s/implcit/implicit/\n> >\n> > > one hand we use `uintmax_t` for the actual value. On the other hand, we\n> > > use `int` for the length of the encoded varint.\n> > >\n> > > Both of these have known maximum vaules, as we only support at most 16\n> >\n> > s/vaules/values/\n> \n> Other than the typos this looks good.\n\nThanks, both of you! I'll send another (hopefully the last) iteration\nnow. Guess we'll now have to decide whether we want to try this Rust\nexperiment or not.\n\nPatrick\n"},{"id":"527760","messageId":"20251002-b4-pks-rust-breaking-change-v8-0-3a89fd5b1ce7@pks.im","threadId":"64091","inReplyTo":"20250904-b4-pks-rust-breaking-change-v1-0-3af1d25e0be9@pks.im","subject":"[PATCH v8 0/9] Introduce Rust and announce that it will become mandatory","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-10-02T07:29:25Z","receivedAt":"2025-10-02T07:30:34Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Hi,\n\nthis small patch series introduces Rust into the core of Git. This patch\nseries is designed as a test balloon, similar to how we introduced test\nballoons for C99 features in the past. The goal is threefold:\n\n  - Give us some time to experiment with Rust and introduce proper build\n    infrastructure.\n\n  - Give distributors time to ease into the new toolchain requirements.\n    Introducing Rust is impossible for some platforms and hard for\n    others.\n\n  - Announce that Git 3.0 will make Rust a mandatory part of our build\n    infrastructure.\n\nThe test balloon itself is quite uninteresting: I've chosen to convert\nthe \"varint.c\" subsystem, mostly because it is trivial and does not have\nany dependencies. But it does allow us to verify that C to Rust interop\nworks as expected, and to play around with tooling. All tests pass with\nthe \"varint.rs\" implementation.\n\nFor now, the series only contains support for Meson. If we agree to go\ndown this route I'll also introduce support for Rust into our Makefiles\nat a later point in time.\n\nFurthermore missing is additional tooling:\n\n  - At least one CI job to verify that Rust builds and works as\n    expected.\n\n  - Tooling and CI jobs to ensure that we have consistent formatting via\n    `cargo format`.\n\nAnd probably lots more. As said, the entire goal is for us to have an\neasy playground that we can experiment on and develop the infrastructure\nincrementally without yet having to commit to anything.\n\nI'm mostly splitting out the topic of introducing Rust from the larger\nseries that introduce it into xdiff so that we can focus more on the\nactual process of introducing Rust into Git and less on the potential\nfeatures that we want to build on top of it.\n\nChanges in v2:\n  - Introduce support for building the Rust library via our Makefile.\n  - Introduce a '-DWITH_RUST' define. This define is used to print\n    whether or not Git is built with Rust via `git version\n    --build-options`.\n  - Adjust Meson to not depend on v1.9.0 and newer anymore.\n  - Introduce a roadmap into our BreakingChanges document to explain how\n    we'll iterate towards mandatory Rust support.\n  - Rework the Fedora job to do a full compile-and-test run with Meson\n    and breaking changes enabled.\n  - Adapt our breaking-changes jobs to enable Rust support.\n  - Link to v1: https://lore.kernel.org/r/20250904-b4-pks-rust-breaking-change-v1-0-3af1d25e0be9@pks.im\n\nChanges in v3:\n  - Reorder all uses of `WITH_RUST` after the include of \"config.mak\".\n  - Add a test to verify overflow behaviour in Rust and explicitly use\n    `add_wrapping()`.\n  - Use explicit dependencies for the Rust library in our Makefile.\n  - Fix Alma Linux CI job.\n  - Stop tying maintenance of our LTS release to the availability of\n    gcc-rs.\n  - Add a fallback to Meson to use cargo directly.\n  - I've fixed the Rust edition to 2018 for now. This is intentionally\n    conservative so that we might be able to use Rust 1.49. For now, we\n    don't have any reason to use a newer edition, either. So let's take\n    the oldest version we can live with for now and then bump it as\n    required.\n  - Link to v2: https://lore.kernel.org/r/20250905-b4-pks-rust-breaking-change-v2-0-6939cbf4a0b8@pks.im\n\nChanges in v4:\n  - Convert \"varint.c\" to use explicit integer width so that we don't\n    need to use C types in Rust.\n  - Adapt Meson to unconditionally use Cargo.\n  - Don't use the unstable `--out-dir` option in Cargo. Instead, we\n    resort to a wrapper script in Meson.\n  - Shorten the timeline a bit to drop the extra step that ties Rust\n    support to `-Dbreaking_changes=true`. This accelerates the timeline\n    until distros are made forcibly aware of the upcoming changes in\n    Rust.\n  - Link to v3: https://lore.kernel.org/r/20250908-b4-pks-rust-breaking-change-v3-0-1cd7189fed3b@pks.im\n\nChanges in v5:\n  - Fix indentation in the BreakingChanges document.\n  - Fix a commit message typo.\n  - Include \"Cargo.lock\" in the `make clean` target again.\n  - Link to v4: https://lore.kernel.org/r/20250910-b4-pks-rust-breaking-change-v4-0-4a63fc69278d@pks.im\n\nChanges in v6:\n  - Give attribution to Ezekiel for kickstarting the Rust adoption\n    again. I'm happy to change how I do the attribution.\n  - Fix \"varint.rs\" to use `u64` instead of `usize`. Issues like these\n    will eventually be catched by cbindgen.\n  - Adapt the breaking changes document to mention that we already have\n    Rust in our tree starting with Git 2.49.\n  - Mention that we won't blindly make Rust mandatory, but consider the\n    impact on downstream distributions.\n  - Slightly reword how we'll handle LTS maintainership. This probably\n    still is an ongoing discussion.\n  - Link to v5: https://lore.kernel.org/r/20250915-b4-pks-rust-breaking-change-v5-0-dc3a32fbb216@pks.im\n\nChanges in v7:\n  - Rename \"git\" crate to \"gitcore\".\n  - Some word smithing for the breaking changes doc.\n  - Punt on the exact details of how we hand over maintenance of the LTS\n    release to the community. This is something we can decide on in the\n    future.\n  - Link to v6: https://lore.kernel.org/r/20250923-b4-pks-rust-breaking-change-v6-0-59076fee486a@pks.im\n\nChanges in v8:\n  - Some final typo fixes.\n  - Link to v7: https://lore.kernel.org/r/20250925-b4-pks-rust-breaking-change-v7-0-4e49dcb904d5@pks.im\n\nThanks!\n\nPatrick\n\n---\nPatrick Steinhardt (9):\n      meson: add infrastructure to build internal Rust library\n      Makefile: reorder sources after includes\n      Makefile: introduce infrastructure to build internal Rust library\n      help: report on whether or not Rust is enabled\n      varint: use explicit width for integers\n      varint: reimplement as test balloon for Rust\n      BreakingChanges: announce Rust becoming mandatory\n      ci: convert \"pedantic\" job into full build with breaking changes\n      ci: enable Rust for breaking-changes jobs\n\n .github/workflows/main.yml         |   4 +-\n .gitignore                         |   2 +\n .gitlab-ci.yml                     |   4 +-\n Cargo.toml                         |   9 ++\n Documentation/BreakingChanges.adoc |  45 ++++++++\n Makefile                           | 214 ++++++++++++++++++++++---------------\n ci/install-dependencies.sh         |   8 +-\n ci/run-build-and-tests.sh          |  31 ++----\n dir.c                              |  18 ++--\n help.c                             |   6 ++\n meson.build                        |  15 ++-\n meson_options.txt                  |   2 +\n read-cache.c                       |   6 +-\n shared.mak                         |   1 +\n src/cargo-meson.sh                 |  32 ++++++\n src/lib.rs                         |   1 +\n src/meson.build                    |  41 +++++++\n src/varint.rs                      |  92 ++++++++++++++++\n varint.c                           |   6 +-\n varint.h                           |   4 +-\n 20 files changed, 410 insertions(+), 131 deletions(-)\n\nRange-diff versus v7:\n\n 1:  3f916bebd4 =  1:  bf7b33291d meson: add infrastructure to build internal Rust library\n 2:  ed849dcfed =  2:  59e7879c63 Makefile: reorder sources after includes\n 3:  955f262ef5 =  3:  635cebc0a6 Makefile: introduce infrastructure to build internal Rust library\n 4:  7a90192b5a =  4:  43b50563cc help: report on whether or not Rust is enabled\n 5:  9365a78efd !  5:  37d03d7774 varint: use explicit width for integers\n    @@ Metadata\n      ## Commit message ##\n         varint: use explicit width for integers\n     \n    -    The varint subsystem currently uses implcit widths for integers. On the\n    +    The varint subsystem currently uses implicit widths for integers. On the\n         one hand we use `uintmax_t` for the actual value. On the other hand, we\n         use `int` for the length of the encoded varint.\n     \n    -    Both of these have known maximum vaules, as we only support at most 16\n    +    Both of these have known maximum values, as we only support at most 16\n         bytes when encoding varints. Thus, we know that we won't ever exceed\n         `uint64_t` for the actual value and `uint8_t` for the prefix length.\n     \n 6:  e7e0621b68 =  6:  0d265f9675 varint: reimplement as test balloon for Rust\n 7:  8d8e9cb8a8 =  7:  a6e0d668f0 BreakingChanges: announce Rust becoming mandatory\n 8:  07dc8171ac =  8:  79470835fd ci: convert \"pedantic\" job into full build with breaking changes\n 9:  708a0d3c67 =  9:  67f8dea13f ci: enable Rust for breaking-changes jobs\n\n---\nbase-commit: 2462961280690837670d997bde64bd4ebf8ae66d\nchange-id: 20250904-b4-pks-rust-breaking-change-7167d9d3e37d\n\n"},{"id":"527761","messageId":"20251002-b4-pks-rust-breaking-change-v8-1-3a89fd5b1ce7@pks.im","threadId":"64091","inReplyTo":"20251002-b4-pks-rust-breaking-change-v8-0-3a89fd5b1ce7@pks.im","subject":"[PATCH v8 1/9] meson: add infrastructure to build internal Rust library","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-10-02T07:29:26Z","receivedAt":"2025-10-02T07:30:37Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Add the infrastructure into Meson to build an internal Rust library.\nBuilding the Rust parts of Git are for now entirely optional, as they\nare mostly intended as a test balloon for both Git developers, but also\nfor distributors of Git. So for now, they may contain:\n\n  - New features that are not mission critical to Git and that users can\n    easily live without.\n\n  - Alternative implementations of small subsystems.\n\nIf these test balloons are successful, we will eventually make Rust a\nmandatory dependency for our build process in Git 3.0.\n\nThe availability of a Rust toolchain will be auto-detected by Meson at\nsetup time. This behaviour can be tweaked via the `-Drust=` feature\ntoggle.\n\nNext to the linkable Rust library, also wire up tests that can be\nexecuted via `meson test`. This allows us to use the native unit testing\ncapabilities of Rust.\n\nNote that the Rust edition is currently set to 2018. This edition is\nsupported by Rust 1.49, which is the target for the upcoming gcc-rs\nbackend. For now we don't use any features of Rust that would require a\nnewer version, so settling on this old version makes sense so that\ngcc-rs may become an alternative backend for compiling Git. If we _do_\nwant to introduce features that were added in more recent editions of\nRust though we should reevaluate that choice.\n\nInspired-by: Ezekiel Newren <ezekielnewren@gmail.com>\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n Cargo.toml         |  9 +++++++++\n meson.build        | 10 +++++++++-\n meson_options.txt  |  2 ++\n src/cargo-meson.sh | 32 ++++++++++++++++++++++++++++++++\n src/lib.rs         |  0\n src/meson.build    | 40 ++++++++++++++++++++++++++++++++++++++++\n 6 files changed, 92 insertions(+), 1 deletion(-)\n\ndiff --git a/Cargo.toml b/Cargo.toml\nnew file mode 100644\nindex 00000000000..45c9b34981a\n--- /dev/null\n+++ b/Cargo.toml\n@@ -0,0 +1,9 @@\n+[package]\n+name = \"gitcore\"\n+version = \"0.1.0\"\n+edition = \"2018\"\n+\n+[lib]\n+crate-type = [\"staticlib\"]\n+\n+[dependencies]\ndiff --git a/meson.build b/meson.build\nindex e8ec0eca165..234a9e9d6fd 100644\n--- a/meson.build\n+++ b/meson.build\n@@ -220,7 +220,7 @@ project('git', 'c',\n   # learned to define __STDC_VERSION__ with C11 and later. We thus require\n   # GNU C99 and fall back to C11. Meson only learned to handle the fallback\n   # with version 1.3.0, so on older versions we use GNU C99 unconditionally.\n-  default_options: meson.version().version_compare('>=1.3.0') ? ['c_std=gnu99,c11'] : ['c_std=gnu99'],\n+  default_options: meson.version().version_compare('>=1.3.0') ? ['rust_std=2018', 'c_std=gnu99,c11'] : ['rust_std=2018', 'c_std=gnu99'],\n )\n \n fs = import('fs')\n@@ -1702,6 +1702,13 @@ version_def_h = custom_target(\n )\n libgit_sources += version_def_h\n \n+cargo = find_program('cargo', dirs: program_path, native: true, required: get_option('rust'))\n+rust_option = get_option('rust').disable_auto_if(not cargo.found())\n+if rust_option.allowed()\n+  subdir('src')\n+  libgit_c_args += '-DWITH_RUST'\n+endif\n+\n libgit = declare_dependency(\n   link_with: static_library('git',\n     sources: libgit_sources,\n@@ -2239,6 +2246,7 @@ summary({\n   'pcre2': pcre2,\n   'perl': perl_features_enabled,\n   'python': target_python.found(),\n+  'rust': rust_option.allowed(),\n }, section: 'Auto-detected features', bool_yn: true)\n \n summary({\ndiff --git a/meson_options.txt b/meson_options.txt\nindex 1668f260a18..143dee9237c 100644\n--- a/meson_options.txt\n+++ b/meson_options.txt\n@@ -71,6 +71,8 @@ option('zlib_backend', type: 'combo', choices: ['auto', 'zlib', 'zlib-ng'], valu\n # Build tweaks.\n option('breaking_changes', type: 'boolean', value: false,\n   description: 'Enable upcoming breaking changes.')\n+option('rust', type: 'feature', value: 'auto',\n+  description: 'Enable building with Rust.')\n option('macos_use_homebrew_gettext', type: 'boolean', value: true,\n   description: 'Use gettext from Homebrew instead of the slightly-broken system-provided one.')\n \ndiff --git a/src/cargo-meson.sh b/src/cargo-meson.sh\nnew file mode 100755\nindex 00000000000..99400986d93\n--- /dev/null\n+++ b/src/cargo-meson.sh\n@@ -0,0 +1,32 @@\n+#!/bin/sh\n+\n+if test \"$#\" -lt 2\n+then\n+\texit 1\n+fi\n+\n+SOURCE_DIR=\"$1\"\n+BUILD_DIR=\"$2\"\n+BUILD_TYPE=debug\n+\n+shift 2\n+\n+for arg\n+do\n+\tcase \"$arg\" in\n+\t--release)\n+\t\tBUILD_TYPE=release;;\n+\tesac\n+done\n+\n+cargo build --lib --quiet --manifest-path=\"$SOURCE_DIR/Cargo.toml\" --target-dir=\"$BUILD_DIR\" \"$@\"\n+RET=$?\n+if test $RET -ne 0\n+then\n+\texit $RET\n+fi\n+\n+if ! cmp \"$BUILD_DIR/$BUILD_TYPE/libgitcore.a\" \"$BUILD_DIR/libgitcore.a\" >/dev/null 2>&1\n+then\n+\tcp \"$BUILD_DIR/$BUILD_TYPE/libgitcore.a\" \"$BUILD_DIR/libgitcore.a\"\n+fi\ndiff --git a/src/lib.rs b/src/lib.rs\nnew file mode 100644\nindex 00000000000..e69de29bb2d\ndiff --git a/src/meson.build b/src/meson.build\nnew file mode 100644\nindex 00000000000..c8d874b2106\n--- /dev/null\n+++ b/src/meson.build\n@@ -0,0 +1,40 @@\n+libgit_rs_sources = [\n+  'lib.rs',\n+]\n+\n+# Unfortunately we must use a wrapper command to move the output file into the\n+# current build directory. This can fixed once `cargo build --artifact-dir`\n+# stabilizes. See https://github.com/rust-lang/cargo/issues/6790 for that\n+# effort.\n+cargo_command = [\n+  shell,\n+  meson.current_source_dir() / 'cargo-meson.sh',\n+  meson.project_source_root(),\n+  meson.current_build_dir(),\n+]\n+if get_option('buildtype') == 'release'\n+  cargo_command += '--release'\n+endif\n+\n+libgit_rs = custom_target('git_rs',\n+  input: libgit_rs_sources + [\n+    meson.project_source_root() / 'Cargo.toml',\n+  ],\n+  output: 'libgitcore.a',\n+  command: cargo_command,\n+)\n+libgit_dependencies += declare_dependency(link_with: libgit_rs)\n+\n+if get_option('tests')\n+  test('rust', cargo,\n+    args: [\n+      'test',\n+      '--manifest-path',\n+      meson.project_source_root() / 'Cargo.toml',\n+      '--target-dir',\n+      meson.current_build_dir() / 'target',\n+    ],\n+    timeout: 0,\n+    protocol: 'rust',\n+  )\n+endif\n\n-- \n2.51.0.700.g236ee7b076.dirty\n\n"},{"id":"527762","messageId":"20251002-b4-pks-rust-breaking-change-v8-2-3a89fd5b1ce7@pks.im","threadId":"64091","inReplyTo":"20251002-b4-pks-rust-breaking-change-v8-0-3a89fd5b1ce7@pks.im","subject":"[PATCH v8 2/9] Makefile: reorder sources after includes","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-10-02T07:29:27Z","receivedAt":"2025-10-02T07:30:41Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"In an upcoming change we'll make some of the sources compile\nconditionally based on whether or not `WITH_RUST` is defined. To let\ndevelopers specify that flag in their \"config.mak\" we'll thus have to\nreorder our sources so that they come after the include of that file.\n\nDo so.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n Makefile | 176 +++++++++++++++++++++++++++++++--------------------------------\n 1 file changed, 88 insertions(+), 88 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 555b7f4dc3..7e52625d75 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -919,6 +919,94 @@ LIB_FILE = libgit.a\n XDIFF_LIB = xdiff/lib.a\n REFTABLE_LIB = reftable/libreftable.a\n \n+# xdiff and reftable libs may in turn depend on what is in libgit.a\n+GITLIBS = common-main.o $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(LIB_FILE)\n+EXTLIBS =\n+\n+GIT_USER_AGENT = git/$(GIT_VERSION)\n+\n+ifeq ($(wildcard sha1collisiondetection/lib/sha1.h),sha1collisiondetection/lib/sha1.h)\n+DC_SHA1_SUBMODULE = auto\n+endif\n+\n+# Set CFLAGS, LDFLAGS and other *FLAGS variables. These might be\n+# tweaked by config.* below as well as the command-line, both of\n+# which'll override these defaults.\n+# Older versions of GCC may require adding \"-std=gnu99\" at the end.\n+CFLAGS = -g -O2 -Wall\n+LDFLAGS =\n+CC_LD_DYNPATH = -Wl,-rpath,\n+BASIC_CFLAGS = -I.\n+BASIC_LDFLAGS =\n+\n+# library flags\n+ARFLAGS = rcs\n+PTHREAD_CFLAGS =\n+\n+# For the 'sparse' target\n+SPARSE_FLAGS ?= -std=gnu99 -D__STDC_NO_VLA__\n+SP_EXTRA_FLAGS =\n+\n+# For informing GIT-BUILD-OPTIONS of the SANITIZE=leak,address targets\n+SANITIZE_LEAK =\n+SANITIZE_ADDRESS =\n+\n+# For the 'coccicheck' target\n+SPATCH_INCLUDE_FLAGS = --all-includes\n+SPATCH_FLAGS =\n+SPATCH_TEST_FLAGS =\n+\n+# If *.o files are present, have \"coccicheck\" depend on them, with\n+# COMPUTE_HEADER_DEPENDENCIES this will speed up the common-case of\n+# only needing to re-generate coccicheck results for the users of a\n+# given API if it's changed, and not all files in the project. If\n+# COMPUTE_HEADER_DEPENDENCIES=no this will be unset too.\n+SPATCH_USE_O_DEPENDENCIES = YesPlease\n+\n+# Set SPATCH_CONCAT_COCCI to concatenate the contrib/cocci/*.cocci\n+# files into a single contrib/cocci/ALL.cocci before running\n+# \"coccicheck\".\n+#\n+# Pros:\n+#\n+# - Speeds up a one-shot run of \"make coccicheck\", as we won't have to\n+#   parse *.[ch] files N times for the N *.cocci rules\n+#\n+# Cons:\n+#\n+# - Will make incremental development of *.cocci slower, as\n+#   e.g. changing strbuf.cocci will re-run all *.cocci.\n+#\n+# - Makes error and performance analysis harder, as rules will be\n+#   applied from a monolithic ALL.cocci, rather than\n+#   e.g. strbuf.cocci. To work around this either undefine this, or\n+#   generate a specific patch, e.g. this will always use strbuf.cocci,\n+#   not ALL.cocci:\n+#\n+#\tmake contrib/coccinelle/strbuf.cocci.patch\n+SPATCH_CONCAT_COCCI = YesPlease\n+\n+# Rebuild 'coccicheck' if $(SPATCH), its flags etc. change\n+TRACK_SPATCH_DEFINES =\n+TRACK_SPATCH_DEFINES += $(SPATCH)\n+TRACK_SPATCH_DEFINES += $(SPATCH_INCLUDE_FLAGS)\n+TRACK_SPATCH_DEFINES += $(SPATCH_FLAGS)\n+TRACK_SPATCH_DEFINES += $(SPATCH_TEST_FLAGS)\n+GIT-SPATCH-DEFINES: FORCE\n+\t@FLAGS='$(TRACK_SPATCH_DEFINES)'; \\\n+\t    if test x\"$$FLAGS\" != x\"`cat GIT-SPATCH-DEFINES 2>/dev/null`\" ; then \\\n+\t\techo >&2 \"    * new spatch flags\"; \\\n+\t\techo \"$$FLAGS\" >GIT-SPATCH-DEFINES; \\\n+            fi\n+\n+include config.mak.uname\n+-include config.mak.autogen\n+-include config.mak\n+\n+ifdef DEVELOPER\n+include config.mak.dev\n+endif\n+\n GENERATED_H += command-list.h\n GENERATED_H += config-list.h\n GENERATED_H += hook-list.h\n@@ -1387,94 +1475,6 @@ CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/unit-test.o\n \n UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o\n \n-# xdiff and reftable libs may in turn depend on what is in libgit.a\n-GITLIBS = common-main.o $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(LIB_FILE)\n-EXTLIBS =\n-\n-GIT_USER_AGENT = git/$(GIT_VERSION)\n-\n-ifeq ($(wildcard sha1collisiondetection/lib/sha1.h),sha1collisiondetection/lib/sha1.h)\n-DC_SHA1_SUBMODULE = auto\n-endif\n-\n-# Set CFLAGS, LDFLAGS and other *FLAGS variables. These might be\n-# tweaked by config.* below as well as the command-line, both of\n-# which'll override these defaults.\n-# Older versions of GCC may require adding \"-std=gnu99\" at the end.\n-CFLAGS = -g -O2 -Wall\n-LDFLAGS =\n-CC_LD_DYNPATH = -Wl,-rpath,\n-BASIC_CFLAGS = -I.\n-BASIC_LDFLAGS =\n-\n-# library flags\n-ARFLAGS = rcs\n-PTHREAD_CFLAGS =\n-\n-# For the 'sparse' target\n-SPARSE_FLAGS ?= -std=gnu99 -D__STDC_NO_VLA__\n-SP_EXTRA_FLAGS =\n-\n-# For informing GIT-BUILD-OPTIONS of the SANITIZE=leak,address targets\n-SANITIZE_LEAK =\n-SANITIZE_ADDRESS =\n-\n-# For the 'coccicheck' target\n-SPATCH_INCLUDE_FLAGS = --all-includes\n-SPATCH_FLAGS =\n-SPATCH_TEST_FLAGS =\n-\n-# If *.o files are present, have \"coccicheck\" depend on them, with\n-# COMPUTE_HEADER_DEPENDENCIES this will speed up the common-case of\n-# only needing to re-generate coccicheck results for the users of a\n-# given API if it's changed, and not all files in the project. If\n-# COMPUTE_HEADER_DEPENDENCIES=no this will be unset too.\n-SPATCH_USE_O_DEPENDENCIES = YesPlease\n-\n-# Set SPATCH_CONCAT_COCCI to concatenate the contrib/cocci/*.cocci\n-# files into a single contrib/cocci/ALL.cocci before running\n-# \"coccicheck\".\n-#\n-# Pros:\n-#\n-# - Speeds up a one-shot run of \"make coccicheck\", as we won't have to\n-#   parse *.[ch] files N times for the N *.cocci rules\n-#\n-# Cons:\n-#\n-# - Will make incremental development of *.cocci slower, as\n-#   e.g. changing strbuf.cocci will re-run all *.cocci.\n-#\n-# - Makes error and performance analysis harder, as rules will be\n-#   applied from a monolithic ALL.cocci, rather than\n-#   e.g. strbuf.cocci. To work around this either undefine this, or\n-#   generate a specific patch, e.g. this will always use strbuf.cocci,\n-#   not ALL.cocci:\n-#\n-#\tmake contrib/coccinelle/strbuf.cocci.patch\n-SPATCH_CONCAT_COCCI = YesPlease\n-\n-# Rebuild 'coccicheck' if $(SPATCH), its flags etc. change\n-TRACK_SPATCH_DEFINES =\n-TRACK_SPATCH_DEFINES += $(SPATCH)\n-TRACK_SPATCH_DEFINES += $(SPATCH_INCLUDE_FLAGS)\n-TRACK_SPATCH_DEFINES += $(SPATCH_FLAGS)\n-TRACK_SPATCH_DEFINES += $(SPATCH_TEST_FLAGS)\n-GIT-SPATCH-DEFINES: FORCE\n-\t@FLAGS='$(TRACK_SPATCH_DEFINES)'; \\\n-\t    if test x\"$$FLAGS\" != x\"`cat GIT-SPATCH-DEFINES 2>/dev/null`\" ; then \\\n-\t\techo >&2 \"    * new spatch flags\"; \\\n-\t\techo \"$$FLAGS\" >GIT-SPATCH-DEFINES; \\\n-            fi\n-\n-include config.mak.uname\n--include config.mak.autogen\n--include config.mak\n-\n-ifdef DEVELOPER\n-include config.mak.dev\n-endif\n-\n GIT-VERSION-FILE: FORCE\n \t@OLD=$$(cat $@ 2>/dev/null || :) && \\\n \t$(call version_gen,\"$(shell pwd)\",GIT-VERSION-FILE.in,$@) && \\\n\n-- \n2.51.0.700.g236ee7b076.dirty\n\n"},{"id":"527763","messageId":"20251002-b4-pks-rust-breaking-change-v8-3-3a89fd5b1ce7@pks.im","threadId":"64091","inReplyTo":"20251002-b4-pks-rust-breaking-change-v8-0-3a89fd5b1ce7@pks.im","subject":"[PATCH v8 3/9] Makefile: introduce infrastructure to build internal Rust library","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-10-02T07:29:28Z","receivedAt":"2025-10-02T07:30:44Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Introduce infrastructure to build the internal Rust library. This\nmirrors the infrastructure we have added to Meson in the preceding\ncommit. Developers can enable the infrastructure by passing the new\n`WITH_RUST` build toggle.\n\nInspired-by: Ezekiel Newren <ezekielnewren@gmail.com>\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n .gitignore |  2 ++\n Makefile   | 37 +++++++++++++++++++++++++++++++++++++\n shared.mak |  1 +\n 3 files changed, 40 insertions(+)\n\ndiff --git a/.gitignore b/.gitignore\nindex 1803023427..0833453cf6 100644\n--- a/.gitignore\n+++ b/.gitignore\n@@ -1,4 +1,6 @@\n /fuzz_corpora\n+/target/\n+/Cargo.lock\n /GIT-BUILD-DIR\n /GIT-BUILD-OPTIONS\n /GIT-CFLAGS\ndiff --git a/Makefile b/Makefile\nindex 7e52625d75..31e79342e1 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -483,6 +483,14 @@ include shared.mak\n # Define LIBPCREDIR=/foo/bar if your PCRE header and library files are\n # in /foo/bar/include and /foo/bar/lib directories.\n #\n+# == Optional Rust support ==\n+#\n+# Define WITH_RUST if you want to include features and subsystems written in\n+# Rust into Git. For now, Rust is still an optional feature of the build\n+# process. With Git 3.0 though, Rust will always be enabled.\n+#\n+# Building Rust code requires Cargo.\n+#\n # == SHA-1 and SHA-256 defines ==\n #\n # === SHA-1 backend ===\n@@ -683,6 +691,7 @@ OBJECTS =\n OTHER_PROGRAMS =\n PROGRAM_OBJS =\n PROGRAMS =\n+RUST_SOURCES =\n EXCLUDED_PROGRAMS =\n SCRIPT_PERL =\n SCRIPT_PYTHON =\n@@ -918,6 +927,11 @@ TEST_SHELL_PATH = $(SHELL_PATH)\n LIB_FILE = libgit.a\n XDIFF_LIB = xdiff/lib.a\n REFTABLE_LIB = reftable/libreftable.a\n+ifdef DEBUG\n+RUST_LIB = target/debug/libgitcore.a\n+else\n+RUST_LIB = target/release/libgitcore.a\n+endif\n \n # xdiff and reftable libs may in turn depend on what is in libgit.a\n GITLIBS = common-main.o $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(LIB_FILE)\n@@ -943,6 +957,15 @@ BASIC_LDFLAGS =\n ARFLAGS = rcs\n PTHREAD_CFLAGS =\n \n+# Rust flags\n+CARGO_ARGS =\n+ifndef V\n+CARGO_ARGS += --quiet\n+endif\n+ifndef DEBUG\n+CARGO_ARGS += --release\n+endif\n+\n # For the 'sparse' target\n SPARSE_FLAGS ?= -std=gnu99 -D__STDC_NO_VLA__\n SP_EXTRA_FLAGS =\n@@ -1475,6 +1498,8 @@ CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/unit-test.o\n \n UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o\n \n+RUST_SOURCES += src/lib.rs\n+\n GIT-VERSION-FILE: FORCE\n \t@OLD=$$(cat $@ 2>/dev/null || :) && \\\n \t$(call version_gen,\"$(shell pwd)\",GIT-VERSION-FILE.in,$@) && \\\n@@ -1504,6 +1529,11 @@ endif\n ALL_CFLAGS = $(DEVELOPER_CFLAGS) $(CPPFLAGS) $(CFLAGS) $(CFLAGS_APPEND)\n ALL_LDFLAGS = $(LDFLAGS) $(LDFLAGS_APPEND)\n \n+ifdef WITH_RUST\n+BASIC_CFLAGS += -DWITH_RUST\n+GITLIBS += $(RUST_LIB)\n+endif\n+\n ifdef SANITIZE\n SANITIZERS := $(foreach flag,$(subst $(comma),$(space),$(SANITIZE)),$(flag))\n BASIC_CFLAGS += -fsanitize=$(SANITIZE) -fno-sanitize-recover=$(SANITIZE)\n@@ -2918,6 +2948,12 @@ scalar$X: scalar.o GIT-LDFLAGS $(GITLIBS)\n $(LIB_FILE): $(LIB_OBJS)\n \t$(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^\n \n+$(RUST_LIB): Cargo.toml $(RUST_SOURCES)\n+\t$(QUIET_CARGO)cargo build $(CARGO_ARGS)\n+\n+.PHONY: rust\n+rust: $(RUST_LIB)\n+\n $(XDIFF_LIB): $(XDIFF_OBJS)\n \t$(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^\n \n@@ -3768,6 +3804,7 @@ clean: profile-clean coverage-clean cocciclean\n \t$(RM) $(FUZZ_PROGRAMS)\n \t$(RM) $(SP_OBJ)\n \t$(RM) $(HCC)\n+\t$(RM) -r Cargo.lock target/\n \t$(RM) version-def.h\n \t$(RM) -r $(dep_dirs) $(compdb_dir) compile_commands.json\n \t$(RM) $(test_bindir_programs)\ndiff --git a/shared.mak b/shared.mak\nindex 5c7bc94785..0e7492076e 100644\n--- a/shared.mak\n+++ b/shared.mak\n@@ -56,6 +56,7 @@ ifndef V\n \tQUIET_MKDIR_P_PARENT  = @echo '   ' MKDIR -p $(@D);\n \n ## Used in \"Makefile\"\n+\tQUIET_CARGO    = @echo '   ' CARGO $@;\n \tQUIET_CC       = @echo '   ' CC $@;\n \tQUIET_AR       = @echo '   ' AR $@;\n \tQUIET_LINK     = @echo '   ' LINK $@;\n\n-- \n2.51.0.700.g236ee7b076.dirty\n\n"},{"id":"527764","messageId":"20251002-b4-pks-rust-breaking-change-v8-4-3a89fd5b1ce7@pks.im","threadId":"64091","inReplyTo":"20251002-b4-pks-rust-breaking-change-v8-0-3a89fd5b1ce7@pks.im","subject":"[PATCH v8 4/9] help: report on whether or not Rust is enabled","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-10-02T07:29:29Z","receivedAt":"2025-10-02T07:30:48Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"We're about to introduce support for Rust into the core of Git, where\nsome (trivial) subsystems are converted to Rust. These subsystems will\nalso retain a C implementation though as Rust is not yet mandatory.\nConsequently, it now becomes possible for a Git version to have bugs\nthat are specific to whether or not it is built with Rust support\noverall.\n\nExpose information about whether or not Git was built with Rust via our\nbuild info. This means that both `git version --build-options`, but also\n`git bugreport` will now expose that bit of information. Hopefully, this\nshould make it easier for us to discover any Rust-specific issues.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n help.c | 6 ++++++\n 1 file changed, 6 insertions(+)\n\ndiff --git a/help.c b/help.c\nindex bb20498cfd..5854dd4a7e 100644\n--- a/help.c\n+++ b/help.c\n@@ -791,6 +791,12 @@ void get_version_info(struct strbuf *buf, int show_build_options)\n \t\tstrbuf_addf(buf, \"shell-path: %s\\n\", SHELL_PATH);\n \t\t/* NEEDSWORK: also save and output GIT-BUILD_OPTIONS? */\n \n+#if defined WITH_RUST\n+\t\tstrbuf_addstr(buf, \"rust: enabled\\n\");\n+#else\n+\t\tstrbuf_addstr(buf, \"rust: disabled\\n\");\n+#endif\n+\n \t\tif (fsmonitor_ipc__is_supported())\n \t\t\tstrbuf_addstr(buf, \"feature: fsmonitor--daemon\\n\");\n #if defined LIBCURL_VERSION\n\n-- \n2.51.0.700.g236ee7b076.dirty\n\n"},{"id":"527765","messageId":"20251002-b4-pks-rust-breaking-change-v8-5-3a89fd5b1ce7@pks.im","threadId":"64091","inReplyTo":"20251002-b4-pks-rust-breaking-change-v8-0-3a89fd5b1ce7@pks.im","subject":"[PATCH v8 5/9] varint: use explicit width for integers","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-10-02T07:29:30Z","receivedAt":"2025-10-02T07:30:51Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The varint subsystem currently uses implicit widths for integers. On the\none hand we use `uintmax_t` for the actual value. On the other hand, we\nuse `int` for the length of the encoded varint.\n\nBoth of these have known maximum values, as we only support at most 16\nbytes when encoding varints. Thus, we know that we won't ever exceed\n`uint64_t` for the actual value and `uint8_t` for the prefix length.\n\nRefactor the code to use explicit widths. Besides making the logic\nplatform-independent, it also makes our life a bit easier in the next\ncommit, where we reimplement \"varint.c\" in Rust.\n\nSuggested-by: Ezekiel Newren <ezekielnewren@gmail.com>\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n dir.c        | 18 ++++++++++--------\n read-cache.c |  6 ++++--\n varint.c     |  6 +++---\n varint.h     |  4 ++--\n 4 files changed, 19 insertions(+), 15 deletions(-)\n\ndiff --git a/dir.c b/dir.c\nindex 71108ac79b7..0a67a99cb3d 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -3579,7 +3579,8 @@ static void write_one_dir(struct untracked_cache_dir *untracked,\n \tstruct stat_data stat_data;\n \tstruct strbuf *out = &wd->out;\n \tunsigned char intbuf[16];\n-\tunsigned int intlen, value;\n+\tunsigned int value;\n+\tuint8_t intlen;\n \tint i = wd->index++;\n \n \t/*\n@@ -3632,7 +3633,7 @@ void write_untracked_extension(struct strbuf *out, struct untracked_cache *untra\n \tstruct ondisk_untracked_cache *ouc;\n \tstruct write_data wd;\n \tunsigned char varbuf[16];\n-\tint varint_len;\n+\tuint8_t varint_len;\n \tconst unsigned hashsz = the_hash_algo->rawsz;\n \n \tCALLOC_ARRAY(ouc, 1);\n@@ -3738,7 +3739,7 @@ static int read_one_dir(struct untracked_cache_dir **untracked_,\n \tstruct untracked_cache_dir ud, *untracked;\n \tconst unsigned char *data = rd->data, *end = rd->end;\n \tconst unsigned char *eos;\n-\tunsigned int value;\n+\tuint64_t value;\n \tint i;\n \n \tmemset(&ud, 0, sizeof(ud));\n@@ -3830,7 +3831,8 @@ struct untracked_cache *read_untracked_extension(const void *data, unsigned long\n \tstruct read_data rd;\n \tconst unsigned char *next = data, *end = (const unsigned char *)data + sz;\n \tconst char *ident;\n-\tint ident_len;\n+\tuint64_t ident_len;\n+\tuint64_t varint_len;\n \tssize_t len;\n \tconst char *exclude_per_dir;\n \tconst unsigned hashsz = the_hash_algo->rawsz;\n@@ -3867,8 +3869,8 @@ struct untracked_cache *read_untracked_extension(const void *data, unsigned long\n \tif (next >= end)\n \t\tgoto done2;\n \n-\tlen = decode_varint(&next);\n-\tif (next > end || len == 0)\n+\tvarint_len = decode_varint(&next);\n+\tif (next > end || varint_len == 0)\n \t\tgoto done2;\n \n \trd.valid      = ewah_new();\n@@ -3877,9 +3879,9 @@ struct untracked_cache *read_untracked_extension(const void *data, unsigned long\n \trd.data\t      = next;\n \trd.end\t      = end;\n \trd.index      = 0;\n-\tALLOC_ARRAY(rd.ucd, len);\n+\tALLOC_ARRAY(rd.ucd, varint_len);\n \n-\tif (read_one_dir(&uc->root, &rd) || rd.index != len)\n+\tif (read_one_dir(&uc->root, &rd) || rd.index != varint_len)\n \t\tgoto done;\n \n \tnext = rd.data;\ndiff --git a/read-cache.c b/read-cache.c\nindex 06ad74db228..41b44148b1e 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -1807,7 +1807,7 @@ static struct cache_entry *create_from_disk(struct mem_pool *ce_mem_pool,\n \n \tif (expand_name_field) {\n \t\tconst unsigned char *cp = (const unsigned char *)name;\n-\t\tsize_t strip_len, previous_len;\n+\t\tuint64_t strip_len, previous_len;\n \n \t\t/* If we're at the beginning of a block, ignore the previous name */\n \t\tstrip_len = decode_varint(&cp);\n@@ -2655,8 +2655,10 @@ static int ce_write_entry(struct hashfile *f, struct cache_entry *ce,\n \t\thashwrite(f, ce->name, len);\n \t\thashwrite(f, padding, align_padding_size(size, len));\n \t} else {\n-\t\tint common, to_remove, prefix_size;\n+\t\tint common, to_remove;\n+\t\tuint8_t prefix_size;\n \t\tunsigned char to_remove_vi[16];\n+\n \t\tfor (common = 0;\n \t\t     (common < previous_name->len &&\n \t\t      ce->name[common] &&\ndiff --git a/varint.c b/varint.c\nindex 409c4977a1e..03cd54416b6 100644\n--- a/varint.c\n+++ b/varint.c\n@@ -1,11 +1,11 @@\n #include \"git-compat-util.h\"\n #include \"varint.h\"\n \n-uintmax_t decode_varint(const unsigned char **bufp)\n+uint64_t decode_varint(const unsigned char **bufp)\n {\n \tconst unsigned char *buf = *bufp;\n \tunsigned char c = *buf++;\n-\tuintmax_t val = c & 127;\n+\tuint64_t val = c & 127;\n \twhile (c & 128) {\n \t\tval += 1;\n \t\tif (!val || MSB(val, 7))\n@@ -17,7 +17,7 @@ uintmax_t decode_varint(const unsigned char **bufp)\n \treturn val;\n }\n \n-int encode_varint(uintmax_t value, unsigned char *buf)\n+uint8_t encode_varint(uint64_t value, unsigned char *buf)\n {\n \tunsigned char varint[16];\n \tunsigned pos = sizeof(varint) - 1;\ndiff --git a/varint.h b/varint.h\nindex f78bb0ca528..eb401935bd2 100644\n--- a/varint.h\n+++ b/varint.h\n@@ -1,7 +1,7 @@\n #ifndef VARINT_H\n #define VARINT_H\n \n-int encode_varint(uintmax_t, unsigned char *);\n-uintmax_t decode_varint(const unsigned char **);\n+uint8_t encode_varint(uint64_t, unsigned char *);\n+uint64_t decode_varint(const unsigned char **);\n \n #endif /* VARINT_H */\n\n-- \n2.51.0.700.g236ee7b076.dirty\n\n"},{"id":"527766","messageId":"20251002-b4-pks-rust-breaking-change-v8-6-3a89fd5b1ce7@pks.im","threadId":"64091","inReplyTo":"20251002-b4-pks-rust-breaking-change-v8-0-3a89fd5b1ce7@pks.im","subject":"[PATCH v8 6/9] varint: reimplement as test balloon for Rust","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-10-02T07:29:31Z","receivedAt":"2025-10-02T07:30:54Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Implement a trivial test balloon for our Rust build infrastructure by\nreimplementing the \"varint.c\" subsystem in Rust. This subsystem is\nchosen because it is trivial to convert and because it doesn't have any\ndependencies to other components of Git.\n\nIf support for Rust is enabled, we stop compiling \"varint.c\" and instead\ncompile and use \"src/varint.rs\".\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n Makefile        |  3 ++\n meson.build     |  5 +++-\n src/lib.rs      |  1 +\n src/meson.build |  1 +\n src/varint.rs   | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n 5 files changed, 101 insertions(+), 1 deletion(-)\n\ndiff --git a/Makefile b/Makefile\nindex 31e79342e1d..2a7fc5cb1f3 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -1307,7 +1307,9 @@ LIB_OBJS += urlmatch.o\n LIB_OBJS += usage.o\n LIB_OBJS += userdiff.o\n LIB_OBJS += utf8.o\n+ifndef WITH_RUST\n LIB_OBJS += varint.o\n+endif\n LIB_OBJS += version.o\n LIB_OBJS += versioncmp.o\n LIB_OBJS += walker.o\n@@ -1499,6 +1501,7 @@ CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/unit-test.o\n UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o\n \n RUST_SOURCES += src/lib.rs\n+RUST_SOURCES += src/varint.rs\n \n GIT-VERSION-FILE: FORCE\n \t@OLD=$$(cat $@ 2>/dev/null || :) && \\\ndiff --git a/meson.build b/meson.build\nindex 234a9e9d6fd..37dfa286017 100644\n--- a/meson.build\n+++ b/meson.build\n@@ -522,7 +522,6 @@ libgit_sources = [\n   'usage.c',\n   'userdiff.c',\n   'utf8.c',\n-  'varint.c',\n   'version.c',\n   'versioncmp.c',\n   'walker.c',\n@@ -1707,6 +1706,10 @@ rust_option = get_option('rust').disable_auto_if(not cargo.found())\n if rust_option.allowed()\n   subdir('src')\n   libgit_c_args += '-DWITH_RUST'\n+else\n+  libgit_sources += [\n+    'varint.c',\n+  ]\n endif\n \n libgit = declare_dependency(\ndiff --git a/src/lib.rs b/src/lib.rs\nindex e69de29bb2d..9da70d8b57d 100644\n--- a/src/lib.rs\n+++ b/src/lib.rs\n@@ -0,0 +1 @@\n+pub mod varint;\ndiff --git a/src/meson.build b/src/meson.build\nindex c8d874b2106..25b9ad5a147 100644\n--- a/src/meson.build\n+++ b/src/meson.build\n@@ -1,5 +1,6 @@\n libgit_rs_sources = [\n   'lib.rs',\n+  'varint.rs',\n ]\n \n # Unfortunately we must use a wrapper command to move the output file into the\ndiff --git a/src/varint.rs b/src/varint.rs\nnew file mode 100644\nindex 00000000000..6e610bdd8e0\n--- /dev/null\n+++ b/src/varint.rs\n@@ -0,0 +1,92 @@\n+#[no_mangle]\n+pub unsafe extern \"C\" fn decode_varint(bufp: *mut *const u8) -> u64 {\n+    let mut buf = *bufp;\n+    let mut c = *buf;\n+    let mut val = u64::from(c & 127);\n+\n+    buf = buf.add(1);\n+\n+    while (c & 128) != 0 {\n+        val = val.wrapping_add(1);\n+        if val == 0 || val.leading_zeros() < 7 {\n+            return 0; // overflow\n+        }\n+\n+        c = *buf;\n+        buf = buf.add(1);\n+\n+        val = (val << 7) + u64::from(c & 127);\n+    }\n+\n+    *bufp = buf;\n+    val\n+}\n+\n+#[no_mangle]\n+pub unsafe extern \"C\" fn encode_varint(value: u64, buf: *mut u8) -> u8 {\n+    let mut varint: [u8; 16] = [0; 16];\n+    let mut pos = varint.len() - 1;\n+\n+    varint[pos] = (value & 127) as u8;\n+\n+    let mut value = value >> 7;\n+    while value != 0 {\n+        pos -= 1;\n+        value -= 1;\n+        varint[pos] = 128 | (value & 127) as u8;\n+        value >>= 7;\n+    }\n+\n+    if !buf.is_null() {\n+        std::ptr::copy_nonoverlapping(varint.as_ptr().add(pos), buf, varint.len() - pos);\n+    }\n+\n+    (varint.len() - pos) as u8\n+}\n+\n+#[cfg(test)]\n+mod tests {\n+    use super::*;\n+\n+    #[test]\n+    fn test_decode_varint() {\n+        unsafe {\n+            assert_eq!(decode_varint(&mut [0x00].as_slice().as_ptr()), 0);\n+            assert_eq!(decode_varint(&mut [0x01].as_slice().as_ptr()), 1);\n+            assert_eq!(decode_varint(&mut [0x7f].as_slice().as_ptr()), 127);\n+            assert_eq!(decode_varint(&mut [0x80, 0x00].as_slice().as_ptr()), 128);\n+            assert_eq!(decode_varint(&mut [0x80, 0x01].as_slice().as_ptr()), 129);\n+            assert_eq!(decode_varint(&mut [0x80, 0x7f].as_slice().as_ptr()), 255);\n+\n+            // Overflows are expected to return 0.\n+            assert_eq!(decode_varint(&mut [0x88; 16].as_slice().as_ptr()), 0);\n+        }\n+    }\n+\n+    #[test]\n+    fn test_encode_varint() {\n+        unsafe {\n+            let mut varint: [u8; 16] = [0; 16];\n+\n+            assert_eq!(encode_varint(0, std::ptr::null_mut()), 1);\n+\n+            assert_eq!(encode_varint(0, varint.as_mut_slice().as_mut_ptr()), 1);\n+            assert_eq!(varint, [0; 16]);\n+\n+            assert_eq!(encode_varint(10, varint.as_mut_slice().as_mut_ptr()), 1);\n+            assert_eq!(varint, [10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n+\n+            assert_eq!(encode_varint(127, varint.as_mut_slice().as_mut_ptr()), 1);\n+            assert_eq!(varint, [127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n+\n+            assert_eq!(encode_varint(128, varint.as_mut_slice().as_mut_ptr()), 2);\n+            assert_eq!(varint, [128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n+\n+            assert_eq!(encode_varint(129, varint.as_mut_slice().as_mut_ptr()), 2);\n+            assert_eq!(varint, [128, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n+\n+            assert_eq!(encode_varint(255, varint.as_mut_slice().as_mut_ptr()), 2);\n+            assert_eq!(varint, [128, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n+        }\n+    }\n+}\n\n-- \n2.51.0.700.g236ee7b076.dirty\n\n"},{"id":"527767","messageId":"20251002-b4-pks-rust-breaking-change-v8-7-3a89fd5b1ce7@pks.im","threadId":"64091","inReplyTo":"20251002-b4-pks-rust-breaking-change-v8-0-3a89fd5b1ce7@pks.im","subject":"[PATCH v8 7/9] BreakingChanges: announce Rust becoming mandatory","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-10-02T07:29:32Z","receivedAt":"2025-10-02T07:30:58Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Over the last couple of years the appetite for bringing Rust into the\ncodebase has grown significantly across the developer base. Introducing\nRust is a major change though and has ramifications for the whole\necosystem:\n\n  - Some platforms have a Rust toolchain available, but have not yet\n    integrated it into their build infrastructure.\n\n  - Some platforms don't have any support for Rust at all.\n\n  - Some platforms may have to figure out how to fit Rust into their\n    bootstrapping sequence.\n\nDue to this, and given that Git is a critical piece of infrastructure\nfor the whole industry, we cannot just introduce such a heavyweight\ndependency without doing our due diligence.\n\nInstead, preceding commits have introduced a test balloon into our build\ninfrastructure that convert one tiny subsystem to use Rust. For now,\nusing Rust to build that subsystem is entirely optional -- if no Rust\nsupport is available, we continue to use the C implementation. This test\nballoon has the intention to give distributions time and let them ease\ninto our adoption of Rust.\n\nHaving multiple implementations of the same subsystem is not sustainable\nthough, and the plan is to eventually be able to use Rust freely all\nacross our codebase. As such, there is the intent to make Rust become a\nmandatory part of our build process.\n\nAdd an announcement to our breaking changes that Rust will become\nmandatory in Git 3.0. A (very careful and non-binding) estimate might be\nthat this major release might be released in the second half of next\nyear, which should give distributors enough time to prepare for the\nchange.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n Documentation/BreakingChanges.adoc | 45 ++++++++++++++++++++++++++++++++++++++\n 1 file changed, 45 insertions(+)\n\ndiff --git a/Documentation/BreakingChanges.adoc b/Documentation/BreakingChanges.adoc\nindex f8d2eba061..c21f902134 100644\n--- a/Documentation/BreakingChanges.adoc\n+++ b/Documentation/BreakingChanges.adoc\n@@ -165,6 +165,51 @@ A prerequisite for this change is that the ecosystem is ready to support the\n \"reftable\" format. Most importantly, alternative implementations of Git like\n JGit, libgit2 and Gitoxide need to support it.\n \n+* Git will require Rust as a mandatory part of the build process. While Git\n+  already started to adopt Rust in Git 2.49, all parts written in Rust are\n+  optional for the time being. This includes:\n++\n+  ** The Rust wrapper around libgit.a that is part of \"contrib/\" and which has\n+     been introduced in Git 2.49.\n+  ** Subsystems that have an alternative implementation in Rust to test\n+     interoperability between our C and Rust codebase.\n+  ** Newly written features that are not mission critical for a fully functional\n+     Git client.\n++\n+These changes are meant as test balloons to allow distributors of Git to prepare\n+for Rust becoming a mandatory part of the build process. There will be multiple\n+milestones for the introduction of Rust:\n++\n+--\n+1. Initially, with Git 2.52, support for Rust will be auto-detected by Meson and\n+   disabled in our Makefile so that the project can sort out the initial\n+   infrastructure.\n+2. In Git 2.53, both build systems will default-enable support for Rust.\n+   Consequently, builds will break by default if Rust is not available on the\n+   build host. The use of Rust can still be explicitly disabled via build\n+   flags.\n+3. In Git 3.0, the build options will be removed and support for Rust is\n+   mandatory.\n+--\n++\n+You can explicitly ask both Meson and our Makefile-based system to enable Rust\n+by saying `meson configure -Drust=enabled` and `make WITH_RUST=YesPlease`,\n+respectively.\n++\n+The Git project will declare the last version before Git 3.0 to be a long-term\n+support release. This long-term release will receive important bug fixes for at\n+least four release cycles and security fixes for six release cycles. The Git\n+project will hand over maintainership of the long-term release to distributors\n+in case they need to extend the life of that long-term release even further.\n+Details of how this long-term release will be handed over to the community will\n+be discussed once the Git project decides to stop officially supporting it.\n++\n+We will evaluate the impact on downstream distributions before making Rust\n+mandatory in Git 3.0. If we see that the impact on downstream distributions\n+would be significant, we may decide to defer this change to a subsequent minor\n+release. This evaluation will also take into account our own experience with\n+how painful it is to keep Rust an optional component.\n+\n === Removals\n \n * Support for grafting commits has long been superseded by git-replace(1).\n\n-- \n2.51.0.700.g236ee7b076.dirty\n\n"},{"id":"527768","messageId":"20251002-b4-pks-rust-breaking-change-v8-8-3a89fd5b1ce7@pks.im","threadId":"64091","inReplyTo":"20251002-b4-pks-rust-breaking-change-v8-0-3a89fd5b1ce7@pks.im","subject":"[PATCH v8 8/9] ci: convert \"pedantic\" job into full build with breaking changes","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-10-02T07:29:33Z","receivedAt":"2025-10-02T07:31:01Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The \"pedantic\" CI job is building on Fedora with `DEVOPTS=pedantic`.\nThis build flag doesn't do anything anymore starting with 6a8cbc41ba\n(developer: enable pedantic by default, 2021-09-03), where we have\nflipped the default so that developers have to opt-out of pedantic\nbuilds via the \"no-pedantic\" option. As such, all this job really does\nis to do a normal build on Fedora, which isn't all that interesting.\n\nConvert that job into a full build-and-test job that uses Meson with\nbreaking changes enabled. This plugs two gaps:\n\n  - We now test on another distro that we didn't run tests on\n    beforehand.\n\n  - We verify that breaking changes work as expected with Meson.\n\nFurthermore, in a subsequent commit we'll modify both jobs that use\nbreaking changes to also enable Rust. By converting the Fedora job to\nuse Meson, we ensure that we test our Rust build infrastructure for both\nbuild systems.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n .github/workflows/main.yml |  4 ++--\n .gitlab-ci.yml             |  4 ++--\n ci/install-dependencies.sh |  6 +++++-\n ci/run-build-and-tests.sh  | 29 ++++++++---------------------\n 4 files changed, 17 insertions(+), 26 deletions(-)\n\ndiff --git a/.github/workflows/main.yml b/.github/workflows/main.yml\nindex d122e79415..393ea4d1cc 100644\n--- a/.github/workflows/main.yml\n+++ b/.github/workflows/main.yml\n@@ -379,6 +379,8 @@ jobs:\n         - jobname: linux-breaking-changes\n           cc: gcc\n           image: ubuntu:rolling\n+        - jobname: fedora-breaking-changes-meson\n+          image: fedora:latest\n         - jobname: linux-leaks\n           image: ubuntu:rolling\n           cc: gcc\n@@ -396,8 +398,6 @@ jobs:\n         # Supported until 2025-04-02.\n         - jobname: linux32\n           image: i386/ubuntu:focal\n-        - jobname: pedantic\n-          image: fedora:latest\n         # A RHEL 8 compatible distro.  Supported until 2029-05-31.\n         - jobname: almalinux-8\n           image: almalinux:8\ndiff --git a/.gitlab-ci.yml b/.gitlab-ci.yml\nindex af10ebb59a..4248506909 100644\n--- a/.gitlab-ci.yml\n+++ b/.gitlab-ci.yml\n@@ -45,6 +45,8 @@ test:linux:\n       - jobname: linux-breaking-changes\n         image: ubuntu:20.04\n         CC: gcc\n+      - jobname: fedora-breaking-changes-meson\n+        image: fedora:latest\n       - jobname: linux-TEST-vars\n         image: ubuntu:20.04\n         CC: gcc\n@@ -58,8 +60,6 @@ test:linux:\n       - jobname: linux-asan-ubsan\n         image: ubuntu:rolling\n         CC: clang\n-      - jobname: pedantic\n-        image: fedora:latest\n       - jobname: linux-musl-meson\n         image: alpine:latest\n       - jobname: linux32\ndiff --git a/ci/install-dependencies.sh b/ci/install-dependencies.sh\nindex d061a47293..35bd05b85b 100755\n--- a/ci/install-dependencies.sh\n+++ b/ci/install-dependencies.sh\n@@ -30,8 +30,12 @@ alpine-*)\n \t\tbash cvs gnupg perl-cgi perl-dbd-sqlite perl-io-tty >/dev/null\n \t;;\n fedora-*|almalinux-*)\n+\tcase \"$jobname\" in\n+\t*-meson)\n+\t\tMESON_DEPS=\"meson ninja\";;\n+\tesac\n \tdnf -yq update >/dev/null &&\n-\tdnf -yq install shadow-utils sudo make gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel >/dev/null\n+\tdnf -yq install shadow-utils sudo make pkg-config gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel $MESON_DEPS >/dev/null\n \t;;\n ubuntu-*|i386/ubuntu-*|debian-*)\n \t# Required so that apt doesn't wait for user input on certain packages.\ndiff --git a/ci/run-build-and-tests.sh b/ci/run-build-and-tests.sh\nindex 01823fd0f1..3680446649 100755\n--- a/ci/run-build-and-tests.sh\n+++ b/ci/run-build-and-tests.sh\n@@ -5,12 +5,11 @@\n \n . ${0%/*}/lib.sh\n \n-run_tests=t\n-\n case \"$jobname\" in\n-linux-breaking-changes)\n+fedora-breaking-changes-musl|linux-breaking-changes)\n \texport GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main\n \texport WITH_BREAKING_CHANGES=YesPlease\n+\tMESONFLAGS=\"$MESONFLAGS -Dbreaking_changes=true\"\n \t;;\n linux-TEST-vars)\n \texport OPENSSL_SHA1_UNSAFE=YesPlease\n@@ -36,12 +35,6 @@ linux-sha256)\n linux-reftable|linux-reftable-leaks|osx-reftable)\n \texport GIT_TEST_DEFAULT_REF_FORMAT=reftable\n \t;;\n-pedantic)\n-\t# Don't run the tests; we only care about whether Git can be\n-\t# built.\n-\texport DEVOPTS=pedantic\n-\trun_tests=\n-\t;;\n esac\n \n case \"$jobname\" in\n@@ -54,21 +47,15 @@ case \"$jobname\" in\n \t\t-Dtest_output_directory=\"${TEST_OUTPUT_DIRECTORY:-$(pwd)/t}\" \\\n \t\t$MESONFLAGS\n \tgroup \"Build\" meson compile -C build --\n-\tif test -n \"$run_tests\"\n-\tthen\n-\t\tgroup \"Run tests\" meson test -C build --print-errorlogs --test-args=\"$GIT_TEST_OPTS\" || (\n-\t\t\t./t/aggregate-results.sh \"${TEST_OUTPUT_DIRECTORY:-t}/test-results\"\n-\t\t\thandle_failed_tests\n-\t\t)\n-\tfi\n+\tgroup \"Run tests\" meson test -C build --print-errorlogs --test-args=\"$GIT_TEST_OPTS\" || (\n+\t\t./t/aggregate-results.sh \"${TEST_OUTPUT_DIRECTORY:-t}/test-results\"\n+\t\thandle_failed_tests\n+\t)\n \t;;\n *)\n \tgroup Build make\n-\tif test -n \"$run_tests\"\n-\tthen\n-\t\tgroup \"Run tests\" make test ||\n-\t\thandle_failed_tests\n-\tfi\n+\tgroup \"Run tests\" make test ||\n+\thandle_failed_tests\n \t;;\n esac\n \n\n-- \n2.51.0.700.g236ee7b076.dirty\n\n"},{"id":"527769","messageId":"20251002-b4-pks-rust-breaking-change-v8-9-3a89fd5b1ce7@pks.im","threadId":"64091","inReplyTo":"20251002-b4-pks-rust-breaking-change-v8-0-3a89fd5b1ce7@pks.im","subject":"[PATCH v8 9/9] ci: enable Rust for breaking-changes jobs","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-10-02T07:29:34Z","receivedAt":"2025-10-02T07:31:04Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Enable Rust for our breaking-changes jobs so that we can verify that the\nbuild infrastructure and the converted Rust subsystems work as expected.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n ci/install-dependencies.sh | 4 ++--\n ci/run-build-and-tests.sh  | 2 ++\n 2 files changed, 4 insertions(+), 2 deletions(-)\n\ndiff --git a/ci/install-dependencies.sh b/ci/install-dependencies.sh\nindex 35bd05b85b..0d3aa496fc 100755\n--- a/ci/install-dependencies.sh\n+++ b/ci/install-dependencies.sh\n@@ -35,7 +35,7 @@ fedora-*|almalinux-*)\n \t\tMESON_DEPS=\"meson ninja\";;\n \tesac\n \tdnf -yq update >/dev/null &&\n-\tdnf -yq install shadow-utils sudo make pkg-config gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel $MESON_DEPS >/dev/null\n+\tdnf -yq install shadow-utils sudo make pkg-config gcc findutils diffutils perl python3 gawk gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel $MESON_DEPS cargo >/dev/null\n \t;;\n ubuntu-*|i386/ubuntu-*|debian-*)\n \t# Required so that apt doesn't wait for user input on certain packages.\n@@ -62,7 +62,7 @@ ubuntu-*|i386/ubuntu-*|debian-*)\n \t\tmake libssl-dev libcurl4-openssl-dev libexpat-dev wget sudo default-jre \\\n \t\ttcl tk gettext zlib1g-dev perl-modules liberror-perl libauthen-sasl-perl \\\n \t\tlibemail-valid-perl libio-pty-perl libio-socket-ssl-perl libnet-smtp-ssl-perl libdbd-sqlite3-perl libcgi-pm-perl \\\n-\t\tlibsecret-1-dev libpcre2-dev meson ninja-build pkg-config \\\n+\t\tlibsecret-1-dev libpcre2-dev meson ninja-build pkg-config cargo \\\n \t\t${CC_PACKAGE:-${CC:-gcc}} $PYTHON_PACKAGE\n \n \tcase \"$distro\" in\ndiff --git a/ci/run-build-and-tests.sh b/ci/run-build-and-tests.sh\nindex 3680446649..c718bd101a 100755\n--- a/ci/run-build-and-tests.sh\n+++ b/ci/run-build-and-tests.sh\n@@ -9,7 +9,9 @@ case \"$jobname\" in\n fedora-breaking-changes-musl|linux-breaking-changes)\n \texport GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main\n \texport WITH_BREAKING_CHANGES=YesPlease\n+\texport WITH_RUST=YesPlease\n \tMESONFLAGS=\"$MESONFLAGS -Dbreaking_changes=true\"\n+\tMESONFLAGS=\"$MESONFLAGS -Drust=enabled\"\n \t;;\n linux-TEST-vars)\n \texport OPENSSL_SHA1_UNSAFE=YesPlease\n\n-- \n2.51.0.700.g236ee7b076.dirty\n\n"},{"id":"527811","messageId":"xmqq4ishxnr8.fsf@gitster.g","threadId":"64091","inReplyTo":"20251002-b4-pks-rust-breaking-change-v8-0-3a89fd5b1ce7@pks.im","subject":"Re: [PATCH v8 0/9] Introduce Rust and announce that it will become mandatory","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-10-02T16:38:19Z","receivedAt":"2025-10-02T16:38:23Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> this small patch series introduces Rust into the core of Git. This patch\n> series is designed as a test balloon, similar to how we introduced test\n> balloons for C99 features in the past. The goal is threefold:\n>\n>   - Give us some time to experiment with Rust and introduce proper build\n>     infrastructure.\n>\n>   - Give distributors time to ease into the new toolchain requirements.\n>     Introducing Rust is impossible for some platforms and hard for\n>     others.\n>\n>   - Announce that Git 3.0 will make Rust a mandatory part of our build\n>     infrastructure.\n>\n> The test balloon itself is quite uninteresting: I've chosen to convert\n> the \"varint.c\" subsystem, mostly because it is trivial and does not have\n> any dependencies. But it does allow us to verify that C to Rust interop\n> works as expected, and to play around with tooling. All tests pass with\n> the \"varint.rs\" implementation.\n>\n> For now, the series only contains support for Meson. If we agree to go\n> down this route I'll also introduce support for Rust into our Makefiles\n> at a later point in time.\n\nKeeping the initial part of the cover letter verbatim is a bit\nconfusing for those who have forgotten what they read in previous\niterations ;-) I think a more recent iterations did have Makefile\nsupport, and this (hopefully final) one, too.\n\n> Furthermore missing is additional tooling:\n>\n>   - At least one CI job to verify that Rust builds and works as\n>     expected.\n>\n>   - Tooling and CI jobs to ensure that we have consistent formatting via\n>     `cargo format`.\n>\n> And probably lots more. As said, the entire goal is for us to have an\n> easy playground that we can experiment on and develop the infrastructure\n> incrementally without yet having to commit to anything.\n>\n> I'm mostly splitting out the topic of introducing Rust from the larger\n> series that introduce it into xdiff so that we can focus more on the\n> actual process of introducing Rust into Git and less on the potential\n> features that we want to build on top of it.\n\nOK.\n\n> Changes in v2:\n> ...\n> Changes in v3:\n> ...\n> Changes in v4:\n> ...\n> Changes in v5:\n> ...\n> Changes in v6:\n> ...\n> Changes in v7:\n> ...\n> Changes in v8:\n>   - Some final typo fixes.\n>   - Link to v7: https://lore.kernel.org/r/20250925-b4-pks-rust-breaking-change-v7-0-4e49dcb904d5@pks.im\n\nIndeed.  I have a slight preference to see these \"deltas\" in reverse\norder but it may be just me.  I can read backwards, especially if\neach item is small ;-)\n\nThanks.\n"},{"id":"527860","messageId":"CAH=ZcbA9mXxVU4RWVe-fw7bJa4_BpPSZKUBqGLKqGTWM04gw4g@mail.gmail.com","threadId":"64091","inReplyTo":"20251002-b4-pks-rust-breaking-change-v8-0-3a89fd5b1ce7@pks.im","subject":"Re: [PATCH v8 0/9] Introduce Rust and announce that it will become mandatory","fromName":"Ezekiel Newren","fromEmail":"ezekielnewren@gmail.com","sentAt":"2025-10-02T23:35:27Z","receivedAt":"2025-10-02T23:35:40Z","isPatch":true,"sender":{"key":"ezekielnewren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/18313324?v=4"},"body":"On Thu, Oct 2, 2025 at 1:30 AM Patrick Steinhardt <ps@pks.im> wrote:\n> Range-diff versus v7:\n>\n>  1:  3f916bebd4 =  1:  bf7b33291d meson: add infrastructure to build internal Rust library\n>  2:  ed849dcfed =  2:  59e7879c63 Makefile: reorder sources after includes\n>  3:  955f262ef5 =  3:  635cebc0a6 Makefile: introduce infrastructure to build internal Rust library\n>  4:  7a90192b5a =  4:  43b50563cc help: report on whether or not Rust is enabled\n>  5:  9365a78efd !  5:  37d03d7774 varint: use explicit width for integers\n>     @@ Metadata\n>       ## Commit message ##\n>          varint: use explicit width for integers\n>\n>     -    The varint subsystem currently uses implcit widths for integers. On the\n>     +    The varint subsystem currently uses implicit widths for integers. On the\n>          one hand we use `uintmax_t` for the actual value. On the other hand, we\n>          use `int` for the length of the encoded varint.\n>\n>     -    Both of these have known maximum vaules, as we only support at most 16\n>     +    Both of these have known maximum values, as we only support at most 16\n>          bytes when encoding varints. Thus, we know that we won't ever exceed\n>          `uint64_t` for the actual value and `uint8_t` for the prefix length.\n>\n>  6:  e7e0621b68 =  6:  0d265f9675 varint: reimplement as test balloon for Rust\n>  7:  8d8e9cb8a8 =  7:  a6e0d668f0 BreakingChanges: announce Rust becoming mandatory\n>  8:  07dc8171ac =  8:  79470835fd ci: convert \"pedantic\" job into full build with breaking changes\n>  9:  708a0d3c67 =  9:  67f8dea13f ci: enable Rust for breaking-changes jobs\n>\n> ---\n> base-commit: 2462961280690837670d997bde64bd4ebf8ae66d\n> change-id: 20250904-b4-pks-rust-breaking-change-7167d9d3e37d\n\nI think it's ready to be merged.\n"},{"id":"527914","messageId":"20251004010201.M85772@dcvr","threadId":"64091","inReplyTo":"CAH=ZcbCEioNGaksTKnYyakABWGwTWv4WQZCnOtARydtLrx11MQ@mail.gmail.com","subject":"Re: what's missing from newer C? [was: [PATCH v5 0/9] Introduce Rust ....]","fromName":"Eric Wong","fromEmail":"e@80x24.org","sentAt":"2025-10-04T01:02:01Z","receivedAt":"2025-10-04T01:09:35Z","isPatch":true,"sender":{"key":"e@80x24.org","avatar":null},"body":"Ezekiel Newren <ezekielnewren@gmail.com> wrote:\n> On Wed, Sep 24, 2025 at 7:10 PM Eric Wong <e@80x24.org> wrote:\n> > What else is missing from C?\n> \n> 1. Checked Arithmetic\n>   * C23: <stdckdint.h> for checked integer operations.\n>   * Rust: built-ins like checked_add, wrapping_add.\n> 2. __counted_by__ attribute\n>   * Clang 18 / GCC 15: experimental, helps catch buffer overflows.\n>   * Rust: slices already carry length, preventing out-of-bounds by design.\n> 3. __cleanup__ attribute\n>   * GCC, Clang, TinyCC: long-standing extension for RAII-like cleanup.\n>   * Rust: Drop trait ensures deterministic cleanup.\n> 4. RCU / concurrency libraries\n>   * Userspace RCU, ConcurrencyKit, etc. available in C.\n>   * Rust: crossbeam, Arc, lock-free crates.\n> 5. Format string checking\n>   * GCC/Clang/MSVC check format strings at compile time.\n>   * Rust: format! macros type-check arguments.\n> 6. Regex and parsing\n>   * C: POSIX regex, PCRE2, re2c, wuffs.\n>   * Rust: regex crate (safe, no unchecked buffer access).\n> 7. Dynamic analysis\n>   * C: Valgrind, ASan, TSan, UBSan, MSan.\n>   * Rust: Miri, LLVM sanitizers.\n> \n> What else is missing in C?\n> \n> Compared to Rust, here's where C still falls short at the language\n> level (not just tooling):\n> \n> 1. Ownership and lifetimes\n>   * No borrow checker; compiler can't prevent use-after-free, double\n> free, or aliasing bugs.\n\nAs I understand it, the borrow checker is a big part of the slow\ncompile times which makes it impractical for poor (and/or\nanti-consumerist) folks to contribute.  At least Rc/Arc exists\nbut we can also rely on __cleanup__ to do RC in C.\n\nRCU also has GC-like properties for resource management\nwith less overhead than a full-blown GC.\n\n> 2. Async/await coroutines\n>   * No language support. Async requires threads, callbacks, or libraries.\n>   * Rust: async fn / .await integrated into the language.\n\nAs someone who's worked on implementing async/green threads for\na VM; I find myself disagreeing with async/green-threads these\ndays because stacks end up eating large amounts of memory in\nless-than-obvious ways.  Memory used by a pure event loop (or\nevent loop combined w/ native threads|processes) is a sunk cost\nin either design.  However, (last I checked,) even Golang ends\nup growing stacks in giant 2KB increments whereas event systems\nonly need dozens or hundreds of bytes (not KB) per FD.\n\n> 3. Explicit numeric conversions\n>   * C silently promotes between ints/floats/signed/unsigned.\n>   * Rust requires explicit casts (down and up), reducing surprises.\n\nI think the \"new\" -Wconversion switch can help\n<https://gcc.gnu.org/wiki/NewWconversion>, but I haven't tried it.\nUsing C23 ckd_* functions and wrappers can also help, of course.\n\n> 4. Sum types with exhaustiveness checks\n>   * C: enum + union is manual, compiler won’t enforce full handling.\n>   * Rust: enum + match requires covering all variants.\n\nNot sure what you mean by \"full handling\" (banning the\n`default:' label?), but C switch + enums do a pretty good job\nof warning, already.\n\nI certainly wish enums were more widely used in C projects.\n\n> 5. Safer error handling\n>   * C: errno, return codes, ad hoc conventions.\n>   * Rust: Result<T, E> + ? operator, forcing handling.\n\nIt's down to coding style, yes, but it's not bad.  Linux kernel\nuses __attribute__((__warn_unused_result__)) (aka\n`__must_check') to force error checking.\n\n> 6. Concurrency safety by design\n>   * C11 added atomics, but race conditions are unchecked.\n>   * Rust: Send / Sync traits enforce thread-safety at compile time.\n\nI assume you mean \"parallelism\" safety? (referencing our\nterminology below).  It's never been a big problem to me\nwith RCU and proper understanding of POSIX semantics.\n\n> 7. Namespaces / modules\n>   * C: relies on foo_bar() prefixes and headers.\n>   * Rust: mod and crate system.\n\nI don't miss namespaces; it seems to be mainly dealing with\ncolons vs underscores. (Side note: underscores tend to be\ncheaper for Xapian (and presumably other search engines)\nto deal with :>).\n\nAFAIK, Rust modules + crates are centrally controlled and\npublishing requires an account on a proprietary service owned\nand operated by a convicted monopolist.  That doesn't fly with\nsome folks such as myself.\n\n> 8. Default immutability\n>   * C: everything mutable unless marked const.\n>   * Rust: immutable by default, opt into mut. You have a choice of 1\n> mutable reference xor many immutable references to something.\n\nSure mistakes were made ~50 years ago, but const exists and we\ncan enforce that via coding style.\n\n> 9. Package management\n>   * C: out of scope for the language\n>   * Rust: built in with Cargo dependencies\n\nAs a Perl user who has avoided CPAN for ~25 years, I prefer\nto let distros manage packages and ignore language-specific\nmanagers.  This seems out-of-scope for this discussion,\nso more in footnote[1]\n\n> In Rust there is a difference between concurrency and parallelism.\n> Concurrency in Rust is about running multiple tasks with a single\n> system thread. Whereas parallelism is about assigning tasks to\n> multiple threads. I highly doubt that C will ever get coroutines\n> because it requires the compiler to create a state machine out of each\n> function that uses async or await keywords. The C language just isn't\n> robust enough for that in my opinion.\n\nYour terminology matches mine even outside of Rust (IOW,\n\"ConcurrencyKit\" probably should've been named \"ParallelismKit\").\n\nThere's certainly been attempts at coroutines for C.  From what\nI've seen in headlines, it certainly seems async + function\ncoloring in Rust has its fair share of problems and growing\npains.  Again, I really don't think async is worth the problems\nand surprises, especially in a low-level(?) language.\n\n> And there's probably more that I haven't covered here.\n\nAgain, I would've been much happier if git used more very\nhigh-level language(s) instead of rewriting things to C years\nago.  Given that ship has long sailed, an evolutionary approach\ntowards improving C would be less exclusionary than a\nrevolutionary one such as Rust.\n\nRust seems to try to be a replacement for C++ (with even slower\nbuild times) rather than a thin layer to interface with the OS +\nhardware.  C++ mixes high-level and low-level concepts too much\nfor my liking (and Rust the same).  This is down to personal\ntaste, but I prefer a good distinction between high and\nlow-level languages.\n\n\n[1] - I strongly prefer to only use distro package managers due\n      to multi-language projects, distro-specific quirks, extra\n      review, ethics/license checks, etc.  I also strongly prefer\n      NOT having a central entity affecting users across all\n      distros.\n"},{"id":"527965","messageId":"9eea6006-1dfb-4822-adfc-3af1222b1e01@embecosm.com","threadId":"64091","inReplyTo":"20251004010201.M85772@dcvr","subject":"Re: what's missing from newer C? [was: [PATCH v5 0/9] Introduce Rust ....]","fromName":"Pierre-Emmanuel Patry","fromEmail":"pierre-emmanuel.patry@embecosm.com","sentAt":"2025-10-06T09:13:50Z","receivedAt":"2025-10-06T09:13:53Z","isPatch":true,"sender":{"key":"pierre-emmanuel.patry@embecosm.com","avatar":null},"body":"> As I understand it, the borrow checker is a big part of the slow\n> compile times\n\n From what can been observed in benchmarks (perf.rust-lang.org) the \nborrow checker is not the biggest part of the slow compile times. It \ncertainly isn't the quickest one but I wouldn't make it the culprit.\n\n> As someone who's worked on implementing async/green threads for\n> a VM\n\nYou seems to be mixing async and green threads within the same point. \nGreen threads were removed almost ten years ago before rust 1.0. You may \nlearn more about that removal from RFC 230.\n\n>  It's never been a big problem to me\n> with RCU and proper understanding of POSIX semantics.\n\nBut it has been a problem with less experienced people and that kind of \nproblem easily slip through a review.\n\n> it seems to be mainly dealing with colons vs underscores\n\nIt doesn't. This is only true when dealing from a C perspective where \neverything can be seen from everywhere. Huge identifiers are harder to \nread. Namespaces offer context dependent short identifiers that won't \nleak in the whole TU.\n\n> AFAIK, Rust modules + crates are centrally controlled and\n> publishing requires an account on a proprietary service owned\n> and operated by a convicted monopolist.\n\nPublishing on that platform indeed requires an account on GitHub. It's \nprobably worth mentioning they're willing to change it but do not have \nthe resources nor the bandwidth to do so.\n\ncrates.io is not a mandatory step, it's the default and easiest way to \npublish or retrieve a dependencies just like cargo is with building. \nMore services like this one may appear but it looks very expensive to \nrun and maintain.\n\n\nPierre-Emmanuel\n\n"},{"id":"528060","messageId":"aOTkezur2PO9Pr4x@pks.im","threadId":"64091","inReplyTo":"xmqq4ishxnr8.fsf@gitster.g","subject":"Re: [PATCH v8 0/9] Introduce Rust and announce that it will become mandatory","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-10-07T09:59:23Z","receivedAt":"2025-10-07T09:59:31Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Thu, Oct 02, 2025 at 09:38:19AM -0700, Junio C Hamano wrote:\n> Patrick Steinhardt <ps@pks.im> writes:\n> > Changes in v2:\n> > ...\n> > Changes in v3:\n> > ...\n> > Changes in v4:\n> > ...\n> > Changes in v5:\n> > ...\n> > Changes in v6:\n> > ...\n> > Changes in v7:\n> > ...\n> > Changes in v8:\n> >   - Some final typo fixes.\n> >   - Link to v7: https://lore.kernel.org/r/20250925-b4-pks-rust-breaking-change-v7-0-4e49dcb904d5@pks.im\n> \n> Indeed.  I have a slight preference to see these \"deltas\" in reverse\n> order but it may be just me.  I can read backwards, especially if\n> each item is small ;-)\n\nI can change that ordering going forward. I don't really mind it much\neither way.\n\nPatrick\n"},{"id":"534303","messageId":"20260120221844.6085-1-ben.knoble+github@gmail.com","threadId":"64091","inReplyTo":"20250910-b4-pks-rust-breaking-change-v4-1-4a63fc69278d@pks.im","subject":"RE: [PATCH RFC v4 1/9] meson: add infrastructure to build internal","fromName":"D. Ben Knoble","fromEmail":"ben.knoble+github@gmail.com","sentAt":"2026-01-20T22:18:42Z","receivedAt":"2026-01-20T22:18:59Z","isPatch":true,"sender":{"key":"ben.knoble@gmail.com","avatar":"https://avatars.githubusercontent.com/u/22802209?v=4"},"body":"Hi Patrick,\n\n> diff --git a/src/cargo-meson.sh b/src/cargo-meson.sh\n> new file mode 100755\n> index 00000000000..f29745beb36\n> --- /dev/null\n> +++ b/src/cargo-meson.sh\n> @@ -0,0 +1,32 @@\n> +#!/bin/sh\n> +\n> +if test \"$#\" -lt 2\n> +then\n> +\texit 1\n> +fi\n> +\n> +SOURCE_DIR=\"$1\"\n> +BUILD_DIR=\"$2\"\n> +BUILD_TYPE=debug\n> +\n> +shift 2\n> +\n> +for arg\n> +do\n> +\tcase \"$arg\" in\n> +\t--release)\n> +\t\tBUILD_TYPE=release;;\n> +\tesac\n> +done\n> +\n> +cargo build --lib --quiet --manifest-path=\"$SOURCE_DIR/Cargo.toml\" --target-dir=\"$BUILD_DIR\" \"$@\"\n> +RET=$?\n> +if test $RET -ne 0\n> +then\n> +\texit $RET\n> +fi\n\nAs far as I can tell, v4 of the Rust series introduced this script [1]. I didn't\nnotice any comments on or about the use of \"--quiet\" here, and Gentoo's been\ncarrying a patch to remove it [2] (also attached below). I don't think it's been\nsent upstream, but we could… any thoughts on \"why --quiet\" or objections to such\na patch?\n\n---- 8< ----\nFrom 35f637fbabb3b8181a29ba7d96a505b49ea0ba0d Mon Sep 17 00:00:00 2001\nMessage-ID: <35f637fbabb3b8181a29ba7d96a505b49ea0ba0d.1763489487.git.sam@gentoo.org>\nFrom: Sam James <sam@gentoo.org>\nDate: Tue, 18 Nov 2025 18:10:03 +0000\nSubject: [PATCH 1/2] rust: don't pass --quiet to cargo\n\nThis obscures that cargo is being invoked at all and it means even\nninja --verbose has no mention of it other than invoking the target.\n\nSigned-off-by: Sam James <sam@gentoo.org>\n---\n src/cargo-meson.sh | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/src/cargo-meson.sh b/src/cargo-meson.sh\nindex 3998db0435..63a5e7c6ac 100755\n--- a/src/cargo-meson.sh\n+++ b/src/cargo-meson.sh\n@@ -19,7 +19,7 @@ do\n \tesac\n done\n \n-cargo build --lib --quiet --manifest-path=\"$SOURCE_DIR/Cargo.toml\" --target-dir=\"$BUILD_DIR\" \"$@\"\n+cargo build --lib --manifest-path=\"$SOURCE_DIR/Cargo.toml\" --target-dir=\"$BUILD_DIR\" \"$@\"\n RET=$?\n if test $RET -ne 0\n then\n\nbase-commit: 9a2fb147f2c61d0cab52c883e7e26f5b7948e3ed\n-- \n2.51.2\n---- >8 ----\n\n(While I'm thinking of it, we also have a patch to allow specifying CARGO [3],\nin case there are comments on that.)\n\n---- 8< ----\nFrom 1eba2788aab9f63ff55ac453b0d885aaa60c77af Mon Sep 17 00:00:00 2001\nMessage-ID: <1eba2788aab9f63ff55ac453b0d885aaa60c77af.1763489487.git.sam@gentoo.org>\nIn-Reply-To: <35f637fbabb3b8181a29ba7d96a505b49ea0ba0d.1763489487.git.sam@gentoo.org>\nReferences: <35f637fbabb3b8181a29ba7d96a505b49ea0ba0d.1763489487.git.sam@gentoo.org>\nFrom: Sam James <sam@gentoo.org>\nDate: Tue, 18 Nov 2025 18:10:47 +0000\nSubject: [PATCH 2/2] rust: respect $CARGO environment variable\n\nRespect the CARGO environment variable if set. Gentoo uses this to\ncontrol the version of rust/cargo for a build.\n\nSigned-off-by: Sam James <sam@gentoo.org>\n---\n src/cargo-meson.sh | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/src/cargo-meson.sh b/src/cargo-meson.sh\nindex 63a5e7c6ac..bbf3f91178 100755\n--- a/src/cargo-meson.sh\n+++ b/src/cargo-meson.sh\n@@ -19,7 +19,7 @@ do\n \tesac\n done\n \n-cargo build --lib --manifest-path=\"$SOURCE_DIR/Cargo.toml\" --target-dir=\"$BUILD_DIR\" \"$@\"\n+${CARGO:-cargo} build --lib --manifest-path=\"$SOURCE_DIR/Cargo.toml\" --target-dir=\"$BUILD_DIR\" \"$@\"\n RET=$?\n if test $RET -ne 0\n then\n-- \n2.51.2\n---- >8 ----\n\n[1]: https://lore.kernel.org/git/20250910-b4-pks-rust-breaking-change-v4-1-4a63fc69278d@pks.im/\n[2]: https://github.com/gentoo/gentoo/blob/master/dev-vcs/git/files/git-2.52.0-0001-rust-don-t-pass-quiet-to-cargo.patch\n[3]: https://github.com/gentoo/gentoo/blob/master/dev-vcs/git/files/git-2.52.0-0002-rust-respect-CARGO-environment-variable.patch\n"},{"id":"534306","messageId":"aXAOhTx07g4LVTNo@fruit.crustytoothpaste.net","threadId":"64091","inReplyTo":"20260120221844.6085-1-ben.knoble+github@gmail.com","subject":"Re: [PATCH RFC v4 1/9] meson: add infrastructure to build internalg","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2026-01-20T23:23:49Z","receivedAt":"2026-01-20T23:23:57Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On 2026-01-20 at 22:18:42, D. Ben Knoble wrote:\n> As far as I can tell, v4 of the Rust series introduced this script [1]. I didn't\n> notice any comments on or about the use of \"--quiet\" here, and Gentoo's been\n> carrying a patch to remove it [2] (also attached below). I don't think it's been\n> sent upstream, but we could… any thoughts on \"why --quiet\" or objections to such\n> a patch?\n\nI have no objections to either of these patches.  We'd want `--quiet` by\ndefault for the Makefile due to the output format, but I don't know why\nwe'd need it for meson.\n\nTo be clear, I don't use the meson format at all, so someone who cares\nabout it and can speak to it should definitely chime in, but I would say\nthat given the explanations in the patches, they seem reasonable.\n-- \nbrian m. carlson (they/them)\nToronto, Ontario, CA\n"},{"id":"534317","messageId":"aXCHmFcwmOLxSJeo@pks.im","threadId":"64091","inReplyTo":"aXAOhTx07g4LVTNo@fruit.crustytoothpaste.net","subject":"Re: [PATCH RFC v4 1/9] meson: add infrastructure to build internalg","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-01-21T08:00:24Z","receivedAt":"2026-01-21T08:00:36Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Tue, Jan 20, 2026 at 11:23:49PM +0000, brian m. carlson wrote:\n> On 2026-01-20 at 22:18:42, D. Ben Knoble wrote:\n> > As far as I can tell, v4 of the Rust series introduced this script [1]. I didn't\n> > notice any comments on or about the use of \"--quiet\" here, and Gentoo's been\n> > carrying a patch to remove it [2] (also attached below). I don't think it's been\n> > sent upstream, but we could… any thoughts on \"why --quiet\" or objections to such\n> > a patch?\n> \n> I have no objections to either of these patches.  We'd want `--quiet` by\n> default for the Makefile due to the output format, but I don't know why\n> we'd need it for meson.\n\nFor Meson it's kind of the same reasoning -- not having \"--quiet\" breaks\nthe format for the default non-verbose build.\n\nWe could of course introduce a build option that makes the Cargo command\nitself be verbose? It feels a bit heavy-handed, but maybe that's fine.\n\nPatrick\n"}]}