Merge branch 'ps/ci-rust'

CI improvements to handle the recent Rust integration better.

* ps/ci-rust:
  rust: support for Windows
  ci: verify minimum supported Rust version
  ci: check for common Rust mistakes via Clippy
  rust/varint: add safety comments
  ci: check formatting of our Rust code
  ci: deduplicate calls to `apt-get update`
This commit is contained in:
Junio C Hamano
2025-10-28 10:29:09 -07:00
9 changed files with 103 additions and 9 deletions

View File

@@ -458,6 +458,21 @@ jobs:
- run: ci/install-dependencies.sh
- run: ci/run-static-analysis.sh
- run: ci/check-directional-formatting.bash
rust-analysis:
needs: ci-config
if: needs.ci-config.outputs.enabled == 'yes'
env:
jobname: RustAnalysis
CI_JOB_IMAGE: ubuntu:rolling
runs-on: ubuntu-latest
container: ubuntu:rolling
concurrency:
group: rust-analysis-${{ github.ref }}
cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }}
steps:
- uses: actions/checkout@v4
- run: ci/install-dependencies.sh
- run: ci/run-rust-checks.sh
sparse:
needs: ci-config
if: needs.ci-config.outputs.enabled == 'yes'

View File

@@ -161,7 +161,7 @@ test:mingw64:
- saas-windows-medium-amd64
before_script:
- *windows_before_script
- choco install -y git meson ninja
- choco install -y git meson ninja rust-ms
- Import-Module $env:ChocolateyInstall\helpers\chocolateyProfile.psm1
- refreshenv
@@ -212,6 +212,17 @@ static-analysis:
- ./ci/run-static-analysis.sh
- ./ci/check-directional-formatting.bash
rust-analysis:
image: ubuntu:rolling
stage: analyze
needs: [ ]
variables:
jobname: RustAnalysis
before_script:
- ./ci/install-dependencies.sh
script:
- ./ci/run-rust-checks.sh
check-whitespace:
image: ubuntu:latest
stage: analyze

View File

@@ -2,6 +2,7 @@
name = "gitcore"
version = "0.1.0"
edition = "2018"
rust-version = "1.49.0"
[lib]
crate-type = ["staticlib"]

View File

@@ -927,10 +927,17 @@ export PYTHON_PATH
TEST_SHELL_PATH = $(SHELL_PATH)
LIB_FILE = libgit.a
ifdef DEBUG
RUST_LIB = target/debug/libgitcore.a
RUST_TARGET_DIR = target/debug
else
RUST_LIB = target/release/libgitcore.a
RUST_TARGET_DIR = target/release
endif
ifeq ($(uname_S),Windows)
RUST_LIB = $(RUST_TARGET_DIR)/gitcore.lib
else
RUST_LIB = $(RUST_TARGET_DIR)/libgitcore.a
endif
GITLIBS = common-main.o $(LIB_FILE)
@@ -1556,6 +1563,9 @@ ALL_LDFLAGS = $(LDFLAGS) $(LDFLAGS_APPEND)
ifdef WITH_RUST
BASIC_CFLAGS += -DWITH_RUST
GITLIBS += $(RUST_LIB)
ifeq ($(uname_S),Windows)
EXTLIBS += -luserenv
endif
endif
ifdef SANITIZE

View File

@@ -10,6 +10,8 @@ begin_group "Install dependencies"
P4WHENCE=https://cdist2.perforce.com/perforce/r23.2
LFSWHENCE=https://github.com/github/git-lfs/releases/download/v$LINUX_GIT_LFS_VERSION
JGITWHENCE=https://repo1.maven.org/maven2/org/eclipse/jgit/org.eclipse.jgit.pgm/6.8.0.202311291450-r/org.eclipse.jgit.pgm-6.8.0.202311291450-r.sh
CARGO_MSRV_VERSION=0.18.4
CARGO_MSRV_WHENCE=https://github.com/foresterre/cargo-msrv/releases/download/v$CARGO_MSRV_VERSION/cargo-msrv-x86_64-unknown-linux-musl-v$CARGO_MSRV_VERSION.tgz
# Make sudo a no-op and execute the command directly when running as root.
# While using sudo would be fine on most platforms when we are root already,
@@ -129,21 +131,28 @@ esac
case "$jobname" in
ClangFormat)
sudo apt-get -q update
sudo apt-get -q -y install clang-format
;;
StaticAnalysis)
sudo apt-get -q update
sudo apt-get -q -y install coccinelle libcurl4-openssl-dev libssl-dev \
libexpat-dev gettext make
;;
RustAnalysis)
sudo apt-get -q -y install rustup
rustup default stable
rustup component add clippy rustfmt
wget -q "$CARGO_MSRV_WHENCE" -O "cargo-msvc.tgz"
sudo mkdir -p "$CUSTOM_PATH"
sudo tar -xf "cargo-msvc.tgz" --strip-components=1 \
--directory "$CUSTOM_PATH" --wildcards "*/cargo-msrv"
sudo chmod a+x "$CUSTOM_PATH/cargo-msrv"
;;
sparse)
sudo apt-get -q update -q
sudo apt-get -q -y install libssl-dev libcurl4-openssl-dev \
libexpat-dev gettext zlib1g-dev sparse
;;
Documentation)
sudo apt-get -q update
sudo apt-get -q -y install asciidoc xmlto docbook-xsl-ns make
test -n "$ALREADY_HAVE_ASCIIDOCTOR" ||

22
ci/run-rust-checks.sh Executable file
View File

@@ -0,0 +1,22 @@
#!/bin/sh
. ${0%/*}/lib.sh
set +x
if ! group "Check Rust formatting" cargo fmt --all --check
then
RET=1
fi
if ! group "Check for common Rust mistakes" cargo clippy --all-targets --all-features -- -Dwarnings
then
RET=1
fi
if ! group "Check for minimum required Rust version" cargo msrv verify
then
RET=1
fi
exit $RET

View File

@@ -1708,6 +1708,10 @@ rust_option = get_option('rust').disable_auto_if(not cargo.found())
if rust_option.allowed()
subdir('src')
libgit_c_args += '-DWITH_RUST'
if host_machine.system() == 'windows'
libgit_dependencies += compiler.find_library('userenv')
endif
else
libgit_sources += [
'varint.c',

View File

@@ -26,7 +26,14 @@ then
exit $RET
fi
if ! cmp "$BUILD_DIR/$BUILD_TYPE/libgitcore.a" "$BUILD_DIR/libgitcore.a" >/dev/null 2>&1
case "$(cargo -vV | sed -s 's/^host: \(.*\)$/\1/')" in
*-windows-*)
LIBNAME=gitcore.lib;;
*)
LIBNAME=libgitcore.a;;
esac
if ! cmp "$BUILD_DIR/$BUILD_TYPE/$LIBNAME" "$BUILD_DIR/libgitcore.a" >/dev/null 2>&1
then
cp "$BUILD_DIR/$BUILD_TYPE/libgitcore.a" "$BUILD_DIR/libgitcore.a"
cp "$BUILD_DIR/$BUILD_TYPE/$LIBNAME" "$BUILD_DIR/libgitcore.a"
fi

View File

@@ -1,3 +1,10 @@
/// Decode the variable-length integer stored in `bufp` and return the decoded value.
///
/// Returns 0 in case the decoded integer would overflow u64::MAX.
///
/// # Safety
///
/// The buffer must be NUL-terminated to ensure safety.
#[no_mangle]
pub unsafe extern "C" fn decode_varint(bufp: *mut *const u8) -> u64 {
let mut buf = *bufp;
@@ -22,6 +29,14 @@ pub unsafe extern "C" fn decode_varint(bufp: *mut *const u8) -> u64 {
val
}
/// Encode `value` into `buf` as a variable-length integer unless `buf` is null.
///
/// Returns the number of bytes written, or, if `buf` is null, the number of bytes that would be
/// written to encode the integer.
///
/// # Safety
///
/// `buf` must either be null or point to at least 16 bytes of memory.
#[no_mangle]
pub unsafe extern "C" fn encode_varint(value: u64, buf: *mut u8) -> u8 {
let mut varint: [u8; 16] = [0; 16];