Git fork

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`

+103 -9
+15
.github/workflows/main.yml
··· 458 - run: ci/install-dependencies.sh 459 - run: ci/run-static-analysis.sh 460 - run: ci/check-directional-formatting.bash 461 sparse: 462 needs: ci-config 463 if: needs.ci-config.outputs.enabled == 'yes'
··· 458 - run: ci/install-dependencies.sh 459 - run: ci/run-static-analysis.sh 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 476 sparse: 477 needs: ci-config 478 if: needs.ci-config.outputs.enabled == 'yes'
+12 -1
.gitlab-ci.yml
··· 161 - saas-windows-medium-amd64 162 before_script: 163 - *windows_before_script 164 - - choco install -y git meson ninja 165 - Import-Module $env:ChocolateyInstall\helpers\chocolateyProfile.psm1 166 - refreshenv 167 ··· 211 script: 212 - ./ci/run-static-analysis.sh 213 - ./ci/check-directional-formatting.bash 214 215 check-whitespace: 216 image: ubuntu:latest
··· 161 - saas-windows-medium-amd64 162 before_script: 163 - *windows_before_script 164 + - choco install -y git meson ninja rust-ms 165 - Import-Module $env:ChocolateyInstall\helpers\chocolateyProfile.psm1 166 - refreshenv 167 ··· 211 script: 212 - ./ci/run-static-analysis.sh 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 225 226 check-whitespace: 227 image: ubuntu:latest
+1
Cargo.toml
··· 2 name = "gitcore" 3 version = "0.1.0" 4 edition = "2018" 5 6 [lib] 7 crate-type = ["staticlib"]
··· 2 name = "gitcore" 3 version = "0.1.0" 4 edition = "2018" 5 + rust-version = "1.49.0" 6 7 [lib] 8 crate-type = ["staticlib"]
+12 -2
Makefile
··· 927 TEST_SHELL_PATH = $(SHELL_PATH) 928 929 LIB_FILE = libgit.a 930 ifdef DEBUG 931 - RUST_LIB = target/debug/libgitcore.a 932 else 933 - RUST_LIB = target/release/libgitcore.a 934 endif 935 936 GITLIBS = common-main.o $(LIB_FILE) ··· 1556 ifdef WITH_RUST 1557 BASIC_CFLAGS += -DWITH_RUST 1558 GITLIBS += $(RUST_LIB) 1559 endif 1560 1561 ifdef SANITIZE
··· 927 TEST_SHELL_PATH = $(SHELL_PATH) 928 929 LIB_FILE = libgit.a 930 + 931 ifdef DEBUG 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 939 else 940 + RUST_LIB = $(RUST_TARGET_DIR)/libgitcore.a 941 endif 942 943 GITLIBS = common-main.o $(LIB_FILE) ··· 1563 ifdef WITH_RUST 1564 BASIC_CFLAGS += -DWITH_RUST 1565 GITLIBS += $(RUST_LIB) 1566 + ifeq ($(uname_S),Windows) 1567 + EXTLIBS += -luserenv 1568 + endif 1569 endif 1570 1571 ifdef SANITIZE
+13 -4
ci/install-dependencies.sh
··· 10 P4WHENCE=https://cdist2.perforce.com/perforce/r23.2 11 LFSWHENCE=https://github.com/github/git-lfs/releases/download/v$LINUX_GIT_LFS_VERSION 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 14 # Make sudo a no-op and execute the command directly when running as root. 15 # While using sudo would be fine on most platforms when we are root already, ··· 129 130 case "$jobname" in 131 ClangFormat) 132 - sudo apt-get -q update 133 sudo apt-get -q -y install clang-format 134 ;; 135 StaticAnalysis) 136 - sudo apt-get -q update 137 sudo apt-get -q -y install coccinelle libcurl4-openssl-dev libssl-dev \ 138 libexpat-dev gettext make 139 ;; 140 sparse) 141 - sudo apt-get -q update -q 142 sudo apt-get -q -y install libssl-dev libcurl4-openssl-dev \ 143 libexpat-dev gettext zlib1g-dev sparse 144 ;; 145 Documentation) 146 - sudo apt-get -q update 147 sudo apt-get -q -y install asciidoc xmlto docbook-xsl-ns make 148 149 test -n "$ALREADY_HAVE_ASCIIDOCTOR" ||
··· 10 P4WHENCE=https://cdist2.perforce.com/perforce/r23.2 11 LFSWHENCE=https://github.com/github/git-lfs/releases/download/v$LINUX_GIT_LFS_VERSION 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 15 16 # Make sudo a no-op and execute the command directly when running as root. 17 # While using sudo would be fine on most platforms when we are root already, ··· 131 132 case "$jobname" in 133 ClangFormat) 134 sudo apt-get -q -y install clang-format 135 ;; 136 StaticAnalysis) 137 sudo apt-get -q -y install coccinelle libcurl4-openssl-dev libssl-dev \ 138 libexpat-dev gettext make 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 + ;; 151 sparse) 152 sudo apt-get -q -y install libssl-dev libcurl4-openssl-dev \ 153 libexpat-dev gettext zlib1g-dev sparse 154 ;; 155 Documentation) 156 sudo apt-get -q -y install asciidoc xmlto docbook-xsl-ns make 157 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 if rust_option.allowed() 1709 subdir('src') 1710 libgit_c_args += '-DWITH_RUST' 1711 else 1712 libgit_sources += [ 1713 'varint.c',
··· 1708 if rust_option.allowed() 1709 subdir('src') 1710 libgit_c_args += '-DWITH_RUST' 1711 + 1712 + if host_machine.system() == 'windows' 1713 + libgit_dependencies += compiler.find_library('userenv') 1714 + endif 1715 else 1716 libgit_sources += [ 1717 'varint.c',
+9 -2
src/cargo-meson.sh
··· 26 exit $RET 27 fi 28 29 - if ! cmp "$BUILD_DIR/$BUILD_TYPE/libgitcore.a" "$BUILD_DIR/libgitcore.a" >/dev/null 2>&1 30 then 31 - cp "$BUILD_DIR/$BUILD_TYPE/libgitcore.a" "$BUILD_DIR/libgitcore.a" 32 fi
··· 26 exit $RET 27 fi 28 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 37 then 38 + cp "$BUILD_DIR/$BUILD_TYPE/$LIBNAME" "$BUILD_DIR/libgitcore.a" 39 fi
+15
src/varint.rs
··· 1 #[no_mangle] 2 pub unsafe extern "C" fn decode_varint(bufp: *mut *const u8) -> u64 { 3 let mut buf = *bufp; ··· 22 val 23 } 24 25 #[no_mangle] 26 pub unsafe extern "C" fn encode_varint(value: u64, buf: *mut u8) -> u8 { 27 let mut varint: [u8; 16] = [0; 16];
··· 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. 8 #[no_mangle] 9 pub unsafe extern "C" fn decode_varint(bufp: *mut *const u8) -> u64 { 10 let mut buf = *bufp; ··· 29 val 30 } 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. 40 #[no_mangle] 41 pub unsafe extern "C" fn encode_varint(value: u64, buf: *mut u8) -> u8 { 42 let mut varint: [u8; 16] = [0; 16];