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`

+15
.github/workflows/main.yml
··· 458 458 - run: ci/install-dependencies.sh 459 459 - run: ci/run-static-analysis.sh 460 460 - run: ci/check-directional-formatting.bash 461 + rust-analysis: 462 + needs: ci-config 463 + if: needs.ci-config.outputs.enabled == 'yes' 464 + env: 465 + jobname: RustAnalysis 466 + CI_JOB_IMAGE: ubuntu:rolling 467 + runs-on: ubuntu-latest 468 + container: ubuntu:rolling 469 + concurrency: 470 + group: rust-analysis-${{ github.ref }} 471 + cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }} 472 + steps: 473 + - uses: actions/checkout@v4 474 + - run: ci/install-dependencies.sh 475 + - run: ci/run-rust-checks.sh 461 476 sparse: 462 477 needs: ci-config 463 478 if: needs.ci-config.outputs.enabled == 'yes'
+12 -1
.gitlab-ci.yml
··· 161 161 - saas-windows-medium-amd64 162 162 before_script: 163 163 - *windows_before_script 164 - - choco install -y git meson ninja 164 + - choco install -y git meson ninja rust-ms 165 165 - Import-Module $env:ChocolateyInstall\helpers\chocolateyProfile.psm1 166 166 - refreshenv 167 167 ··· 211 211 script: 212 212 - ./ci/run-static-analysis.sh 213 213 - ./ci/check-directional-formatting.bash 214 + 215 + rust-analysis: 216 + image: ubuntu:rolling 217 + stage: analyze 218 + needs: [ ] 219 + variables: 220 + jobname: RustAnalysis 221 + before_script: 222 + - ./ci/install-dependencies.sh 223 + script: 224 + - ./ci/run-rust-checks.sh 214 225 215 226 check-whitespace: 216 227 image: ubuntu:latest
+1
Cargo.toml
··· 2 2 name = "gitcore" 3 3 version = "0.1.0" 4 4 edition = "2018" 5 + rust-version = "1.49.0" 5 6 6 7 [lib] 7 8 crate-type = ["staticlib"]
+12 -2
Makefile
··· 927 927 TEST_SHELL_PATH = $(SHELL_PATH) 928 928 929 929 LIB_FILE = libgit.a 930 + 930 931 ifdef DEBUG 931 - RUST_LIB = target/debug/libgitcore.a 932 + RUST_TARGET_DIR = target/debug 933 + else 934 + RUST_TARGET_DIR = target/release 935 + endif 936 + 937 + ifeq ($(uname_S),Windows) 938 + RUST_LIB = $(RUST_TARGET_DIR)/gitcore.lib 932 939 else 933 - RUST_LIB = target/release/libgitcore.a 940 + RUST_LIB = $(RUST_TARGET_DIR)/libgitcore.a 934 941 endif 935 942 936 943 GITLIBS = common-main.o $(LIB_FILE) ··· 1556 1563 ifdef WITH_RUST 1557 1564 BASIC_CFLAGS += -DWITH_RUST 1558 1565 GITLIBS += $(RUST_LIB) 1566 + ifeq ($(uname_S),Windows) 1567 + EXTLIBS += -luserenv 1568 + endif 1559 1569 endif 1560 1570 1561 1571 ifdef SANITIZE
+13 -4
ci/install-dependencies.sh
··· 10 10 P4WHENCE=https://cdist2.perforce.com/perforce/r23.2 11 11 LFSWHENCE=https://github.com/github/git-lfs/releases/download/v$LINUX_GIT_LFS_VERSION 12 12 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 13 + CARGO_MSRV_VERSION=0.18.4 14 + 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 13 15 14 16 # Make sudo a no-op and execute the command directly when running as root. 15 17 # While using sudo would be fine on most platforms when we are root already, ··· 129 131 130 132 case "$jobname" in 131 133 ClangFormat) 132 - sudo apt-get -q update 133 134 sudo apt-get -q -y install clang-format 134 135 ;; 135 136 StaticAnalysis) 136 - sudo apt-get -q update 137 137 sudo apt-get -q -y install coccinelle libcurl4-openssl-dev libssl-dev \ 138 138 libexpat-dev gettext make 139 139 ;; 140 + RustAnalysis) 141 + sudo apt-get -q -y install rustup 142 + rustup default stable 143 + rustup component add clippy rustfmt 144 + 145 + wget -q "$CARGO_MSRV_WHENCE" -O "cargo-msvc.tgz" 146 + sudo mkdir -p "$CUSTOM_PATH" 147 + sudo tar -xf "cargo-msvc.tgz" --strip-components=1 \ 148 + --directory "$CUSTOM_PATH" --wildcards "*/cargo-msrv" 149 + sudo chmod a+x "$CUSTOM_PATH/cargo-msrv" 150 + ;; 140 151 sparse) 141 - sudo apt-get -q update -q 142 152 sudo apt-get -q -y install libssl-dev libcurl4-openssl-dev \ 143 153 libexpat-dev gettext zlib1g-dev sparse 144 154 ;; 145 155 Documentation) 146 - sudo apt-get -q update 147 156 sudo apt-get -q -y install asciidoc xmlto docbook-xsl-ns make 148 157 149 158 test -n "$ALREADY_HAVE_ASCIIDOCTOR" ||
+22
ci/run-rust-checks.sh
··· 1 + #!/bin/sh 2 + 3 + . ${0%/*}/lib.sh 4 + 5 + set +x 6 + 7 + if ! group "Check Rust formatting" cargo fmt --all --check 8 + then 9 + RET=1 10 + fi 11 + 12 + if ! group "Check for common Rust mistakes" cargo clippy --all-targets --all-features -- -Dwarnings 13 + then 14 + RET=1 15 + fi 16 + 17 + if ! group "Check for minimum required Rust version" cargo msrv verify 18 + then 19 + RET=1 20 + fi 21 + 22 + exit $RET
+4
meson.build
··· 1708 1708 if rust_option.allowed() 1709 1709 subdir('src') 1710 1710 libgit_c_args += '-DWITH_RUST' 1711 + 1712 + if host_machine.system() == 'windows' 1713 + libgit_dependencies += compiler.find_library('userenv') 1714 + endif 1711 1715 else 1712 1716 libgit_sources += [ 1713 1717 'varint.c',
+9 -2
src/cargo-meson.sh
··· 26 26 exit $RET 27 27 fi 28 28 29 - if ! cmp "$BUILD_DIR/$BUILD_TYPE/libgitcore.a" "$BUILD_DIR/libgitcore.a" >/dev/null 2>&1 29 + case "$(cargo -vV | sed -s 's/^host: \(.*\)$/\1/')" in 30 + *-windows-*) 31 + LIBNAME=gitcore.lib;; 32 + *) 33 + LIBNAME=libgitcore.a;; 34 + esac 35 + 36 + if ! cmp "$BUILD_DIR/$BUILD_TYPE/$LIBNAME" "$BUILD_DIR/libgitcore.a" >/dev/null 2>&1 30 37 then 31 - cp "$BUILD_DIR/$BUILD_TYPE/libgitcore.a" "$BUILD_DIR/libgitcore.a" 38 + cp "$BUILD_DIR/$BUILD_TYPE/$LIBNAME" "$BUILD_DIR/libgitcore.a" 32 39 fi
+15
src/varint.rs
··· 1 + /// Decode the variable-length integer stored in `bufp` and return the decoded value. 2 + /// 3 + /// Returns 0 in case the decoded integer would overflow u64::MAX. 4 + /// 5 + /// # Safety 6 + /// 7 + /// The buffer must be NUL-terminated to ensure safety. 1 8 #[no_mangle] 2 9 pub unsafe extern "C" fn decode_varint(bufp: *mut *const u8) -> u64 { 3 10 let mut buf = *bufp; ··· 22 29 val 23 30 } 24 31 32 + /// Encode `value` into `buf` as a variable-length integer unless `buf` is null. 33 + /// 34 + /// Returns the number of bytes written, or, if `buf` is null, the number of bytes that would be 35 + /// written to encode the integer. 36 + /// 37 + /// # Safety 38 + /// 39 + /// `buf` must either be null or point to at least 16 bytes of memory. 25 40 #[no_mangle] 26 41 pub unsafe extern "C" fn encode_varint(value: u64, buf: *mut u8) -> u8 { 27 42 let mut varint: [u8; 16] = [0; 16];