mirror of
https://github.com/git/git.git
synced 2026-01-11 21:33:13 +09:00
Merge branch 'ps/ci-rust' into dk/ci-rust-fix
* 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` t8020: fix test failure due to indeterministic tag sorting gitlab-ci: upload Meson test logs as JUnit reports gitlab-ci: drop workaround for Python certificate store on Windows gitlab-ci: ignore failures to disable realtime monitoring gitlab-ci: dedup instructions to disable realtime monitoring ci: enable Rust for breaking-changes jobs ci: convert "pedantic" job into full build with breaking changes BreakingChanges: announce Rust becoming mandatory varint: reimplement as test balloon for Rust varint: use explicit width for integers help: report on whether or not Rust is enabled Makefile: introduce infrastructure to build internal Rust library Makefile: reorder sources after includes meson: add infrastructure to build internal Rust library
This commit is contained in:
commit
beb1789f08
19
.github/workflows/main.yml
vendored
19
.github/workflows/main.yml
vendored
@ -379,6 +379,8 @@ jobs:
|
||||
- jobname: linux-breaking-changes
|
||||
cc: gcc
|
||||
image: ubuntu:rolling
|
||||
- jobname: fedora-breaking-changes-meson
|
||||
image: fedora:latest
|
||||
- jobname: linux-leaks
|
||||
image: ubuntu:rolling
|
||||
cc: gcc
|
||||
@ -396,8 +398,6 @@ jobs:
|
||||
# Supported until 2025-04-02.
|
||||
- jobname: linux32
|
||||
image: i386/ubuntu:focal
|
||||
- jobname: pedantic
|
||||
image: fedora:latest
|
||||
# A RHEL 8 compatible distro. Supported until 2029-05-31.
|
||||
- jobname: almalinux-8
|
||||
image: almalinux:8
|
||||
@ -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'
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,4 +1,6 @@
|
||||
/fuzz_corpora
|
||||
/target/
|
||||
/Cargo.lock
|
||||
/GIT-BUILD-DIR
|
||||
/GIT-BUILD-OPTIONS
|
||||
/GIT-CFLAGS
|
||||
|
||||
@ -45,6 +45,8 @@ test:linux:
|
||||
- jobname: linux-breaking-changes
|
||||
image: ubuntu:20.04
|
||||
CC: gcc
|
||||
- jobname: fedora-breaking-changes-meson
|
||||
image: fedora:latest
|
||||
- jobname: linux-TEST-vars
|
||||
image: ubuntu:20.04
|
||||
CC: gcc
|
||||
@ -58,8 +60,6 @@ test:linux:
|
||||
- jobname: linux-asan-ubsan
|
||||
image: ubuntu:rolling
|
||||
CC: clang
|
||||
- jobname: pedantic
|
||||
image: fedora:latest
|
||||
- jobname: linux-musl-meson
|
||||
image: alpine:latest
|
||||
- jobname: linux32
|
||||
@ -70,6 +70,8 @@ test:linux:
|
||||
artifacts:
|
||||
paths:
|
||||
- t/failed-test-artifacts
|
||||
reports:
|
||||
junit: build/meson-logs/testlog.junit.xml
|
||||
when: on_failure
|
||||
|
||||
test:osx:
|
||||
@ -110,8 +112,16 @@ test:osx:
|
||||
artifacts:
|
||||
paths:
|
||||
- t/failed-test-artifacts
|
||||
reports:
|
||||
junit: build/meson-logs/testlog.junit.xml
|
||||
when: on_failure
|
||||
|
||||
.windows_before_script: &windows_before_script
|
||||
# Disabling realtime monitoring fails on some of the runners, but it
|
||||
# significantly speeds up test execution in the case where it works. We thus
|
||||
# try our luck, but ignore any failures.
|
||||
- Set-MpPreference -DisableRealtimeMonitoring $true; $true
|
||||
|
||||
build:mingw64:
|
||||
stage: build
|
||||
tags:
|
||||
@ -119,7 +129,7 @@ build:mingw64:
|
||||
variables:
|
||||
NO_PERL: 1
|
||||
before_script:
|
||||
- Set-MpPreference -DisableRealtimeMonitoring $true
|
||||
- *windows_before_script
|
||||
- ./ci/install-sdk.ps1 -directory "git-sdk"
|
||||
script:
|
||||
- git-sdk/usr/bin/bash.exe -l -c 'ci/make-test-artifacts.sh artifacts'
|
||||
@ -136,7 +146,7 @@ test:mingw64:
|
||||
- job: "build:mingw64"
|
||||
artifacts: true
|
||||
before_script:
|
||||
- Set-MpPreference -DisableRealtimeMonitoring $true
|
||||
- *windows_before_script
|
||||
- git-sdk/usr/bin/bash.exe -l -c 'tar xf artifacts/artifacts.tar.gz'
|
||||
- New-Item -Path .git/info -ItemType Directory
|
||||
- New-Item .git/info/exclude -ItemType File -Value "/git-sdk"
|
||||
@ -150,18 +160,10 @@ test:mingw64:
|
||||
tags:
|
||||
- saas-windows-medium-amd64
|
||||
before_script:
|
||||
- Set-MpPreference -DisableRealtimeMonitoring $true
|
||||
- choco install -y git meson ninja openssl
|
||||
- *windows_before_script
|
||||
- choco install -y git meson ninja rust-ms
|
||||
- Import-Module $env:ChocolateyInstall\helpers\chocolateyProfile.psm1
|
||||
- refreshenv
|
||||
# The certificate store for Python on Windows is broken and fails to fetch
|
||||
# certificates, see https://bugs.python.org/issue36011. This seems to
|
||||
# mostly be an issue with how the GitLab image is set up as it is a
|
||||
# non-issue on GitHub Actions. Work around the issue by importing
|
||||
# cetrificates manually.
|
||||
- Invoke-WebRequest https://curl.haxx.se/ca/cacert.pem -OutFile cacert.pem
|
||||
- openssl pkcs12 -export -nokeys -in cacert.pem -out certs.pfx -passout "pass:"
|
||||
- Import-PfxCertificate -CertStoreLocation Cert:\LocalMachine\Root -FilePath certs.pfx
|
||||
|
||||
build:msvc-meson:
|
||||
extends: .msvc-meson
|
||||
@ -183,6 +185,9 @@ test:msvc-meson:
|
||||
script:
|
||||
- meson test -C build --no-rebuild --print-errorlogs --slice $Env:CI_NODE_INDEX/$Env:CI_NODE_TOTAL
|
||||
parallel: 10
|
||||
artifacts:
|
||||
reports:
|
||||
junit: build/meson-logs/testlog.junit.xml
|
||||
|
||||
test:fuzz-smoke-tests:
|
||||
image: ubuntu:latest
|
||||
@ -207,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
|
||||
|
||||
10
Cargo.toml
Normal file
10
Cargo.toml
Normal file
@ -0,0 +1,10 @@
|
||||
[package]
|
||||
name = "gitcore"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
rust-version = "1.49.0"
|
||||
|
||||
[lib]
|
||||
crate-type = ["staticlib"]
|
||||
|
||||
[dependencies]
|
||||
@ -171,6 +171,51 @@ JGit, libgit2 and Gitoxide need to support it.
|
||||
matches the default branch name used in new repositories by many of the
|
||||
big Git forges.
|
||||
|
||||
* Git will require Rust as a mandatory part of the build process. While Git
|
||||
already started to adopt Rust in Git 2.49, all parts written in Rust are
|
||||
optional for the time being. This includes:
|
||||
+
|
||||
** The Rust wrapper around libgit.a that is part of "contrib/" and which has
|
||||
been introduced in Git 2.49.
|
||||
** Subsystems that have an alternative implementation in Rust to test
|
||||
interoperability between our C and Rust codebase.
|
||||
** Newly written features that are not mission critical for a fully functional
|
||||
Git client.
|
||||
+
|
||||
These changes are meant as test balloons to allow distributors of Git to prepare
|
||||
for Rust becoming a mandatory part of the build process. There will be multiple
|
||||
milestones for the introduction of Rust:
|
||||
+
|
||||
--
|
||||
1. Initially, with Git 2.52, support for Rust will be auto-detected by Meson and
|
||||
disabled in our Makefile so that the project can sort out the initial
|
||||
infrastructure.
|
||||
2. In Git 2.53, both build systems will default-enable support for Rust.
|
||||
Consequently, builds will break by default if Rust is not available on the
|
||||
build host. The use of Rust can still be explicitly disabled via build
|
||||
flags.
|
||||
3. In Git 3.0, the build options will be removed and support for Rust is
|
||||
mandatory.
|
||||
--
|
||||
+
|
||||
You can explicitly ask both Meson and our Makefile-based system to enable Rust
|
||||
by saying `meson configure -Drust=enabled` and `make WITH_RUST=YesPlease`,
|
||||
respectively.
|
||||
+
|
||||
The Git project will declare the last version before Git 3.0 to be a long-term
|
||||
support release. This long-term release will receive important bug fixes for at
|
||||
least four release cycles and security fixes for six release cycles. The Git
|
||||
project will hand over maintainership of the long-term release to distributors
|
||||
in case they need to extend the life of that long-term release even further.
|
||||
Details of how this long-term release will be handed over to the community will
|
||||
be discussed once the Git project decides to stop officially supporting it.
|
||||
+
|
||||
We will evaluate the impact on downstream distributions before making Rust
|
||||
mandatory in Git 3.0. If we see that the impact on downstream distributions
|
||||
would be significant, we may decide to defer this change to a subsequent minor
|
||||
release. This evaluation will also take into account our own experience with
|
||||
how painful it is to keep Rust an optional component.
|
||||
|
||||
=== Removals
|
||||
|
||||
* Support for grafting commits has long been superseded by git-replace(1).
|
||||
|
||||
224
Makefile
224
Makefile
@ -483,6 +483,14 @@ include shared.mak
|
||||
# Define LIBPCREDIR=/foo/bar if your PCRE header and library files are
|
||||
# in /foo/bar/include and /foo/bar/lib directories.
|
||||
#
|
||||
# == Optional Rust support ==
|
||||
#
|
||||
# Define WITH_RUST if you want to include features and subsystems written in
|
||||
# Rust into Git. For now, Rust is still an optional feature of the build
|
||||
# process. With Git 3.0 though, Rust will always be enabled.
|
||||
#
|
||||
# Building Rust code requires Cargo.
|
||||
#
|
||||
# == SHA-1 and SHA-256 defines ==
|
||||
#
|
||||
# === SHA-1 backend ===
|
||||
@ -683,6 +691,7 @@ OBJECTS =
|
||||
OTHER_PROGRAMS =
|
||||
PROGRAM_OBJS =
|
||||
PROGRAMS =
|
||||
RUST_SOURCES =
|
||||
EXCLUDED_PROGRAMS =
|
||||
SCRIPT_PERL =
|
||||
SCRIPT_PYTHON =
|
||||
@ -921,6 +930,115 @@ LIB_FILE = libgit.a
|
||||
XDIFF_LIB = xdiff/lib.a
|
||||
REFTABLE_LIB = reftable/libreftable.a
|
||||
|
||||
ifdef DEBUG
|
||||
RUST_TARGET_DIR = target/debug
|
||||
else
|
||||
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
|
||||
|
||||
# xdiff and reftable libs may in turn depend on what is in libgit.a
|
||||
GITLIBS = common-main.o $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(LIB_FILE)
|
||||
EXTLIBS =
|
||||
|
||||
GIT_USER_AGENT = git/$(GIT_VERSION)
|
||||
|
||||
ifeq ($(wildcard sha1collisiondetection/lib/sha1.h),sha1collisiondetection/lib/sha1.h)
|
||||
DC_SHA1_SUBMODULE = auto
|
||||
endif
|
||||
|
||||
# Set CFLAGS, LDFLAGS and other *FLAGS variables. These might be
|
||||
# tweaked by config.* below as well as the command-line, both of
|
||||
# which'll override these defaults.
|
||||
# Older versions of GCC may require adding "-std=gnu99" at the end.
|
||||
CFLAGS = -g -O2 -Wall
|
||||
LDFLAGS =
|
||||
CC_LD_DYNPATH = -Wl,-rpath,
|
||||
BASIC_CFLAGS = -I.
|
||||
BASIC_LDFLAGS =
|
||||
|
||||
# library flags
|
||||
ARFLAGS = rcs
|
||||
PTHREAD_CFLAGS =
|
||||
|
||||
# Rust flags
|
||||
CARGO_ARGS =
|
||||
ifndef V
|
||||
CARGO_ARGS += --quiet
|
||||
endif
|
||||
ifndef DEBUG
|
||||
CARGO_ARGS += --release
|
||||
endif
|
||||
|
||||
# For the 'sparse' target
|
||||
SPARSE_FLAGS ?= -std=gnu99 -D__STDC_NO_VLA__
|
||||
SP_EXTRA_FLAGS =
|
||||
|
||||
# For informing GIT-BUILD-OPTIONS of the SANITIZE=leak,address targets
|
||||
SANITIZE_LEAK =
|
||||
SANITIZE_ADDRESS =
|
||||
|
||||
# For the 'coccicheck' target
|
||||
SPATCH_INCLUDE_FLAGS = --all-includes
|
||||
SPATCH_FLAGS =
|
||||
SPATCH_TEST_FLAGS =
|
||||
|
||||
# If *.o files are present, have "coccicheck" depend on them, with
|
||||
# COMPUTE_HEADER_DEPENDENCIES this will speed up the common-case of
|
||||
# only needing to re-generate coccicheck results for the users of a
|
||||
# given API if it's changed, and not all files in the project. If
|
||||
# COMPUTE_HEADER_DEPENDENCIES=no this will be unset too.
|
||||
SPATCH_USE_O_DEPENDENCIES = YesPlease
|
||||
|
||||
# Set SPATCH_CONCAT_COCCI to concatenate the contrib/cocci/*.cocci
|
||||
# files into a single contrib/cocci/ALL.cocci before running
|
||||
# "coccicheck".
|
||||
#
|
||||
# Pros:
|
||||
#
|
||||
# - Speeds up a one-shot run of "make coccicheck", as we won't have to
|
||||
# parse *.[ch] files N times for the N *.cocci rules
|
||||
#
|
||||
# Cons:
|
||||
#
|
||||
# - Will make incremental development of *.cocci slower, as
|
||||
# e.g. changing strbuf.cocci will re-run all *.cocci.
|
||||
#
|
||||
# - Makes error and performance analysis harder, as rules will be
|
||||
# applied from a monolithic ALL.cocci, rather than
|
||||
# e.g. strbuf.cocci. To work around this either undefine this, or
|
||||
# generate a specific patch, e.g. this will always use strbuf.cocci,
|
||||
# not ALL.cocci:
|
||||
#
|
||||
# make contrib/coccinelle/strbuf.cocci.patch
|
||||
SPATCH_CONCAT_COCCI = YesPlease
|
||||
|
||||
# Rebuild 'coccicheck' if $(SPATCH), its flags etc. change
|
||||
TRACK_SPATCH_DEFINES =
|
||||
TRACK_SPATCH_DEFINES += $(SPATCH)
|
||||
TRACK_SPATCH_DEFINES += $(SPATCH_INCLUDE_FLAGS)
|
||||
TRACK_SPATCH_DEFINES += $(SPATCH_FLAGS)
|
||||
TRACK_SPATCH_DEFINES += $(SPATCH_TEST_FLAGS)
|
||||
GIT-SPATCH-DEFINES: FORCE
|
||||
@FLAGS='$(TRACK_SPATCH_DEFINES)'; \
|
||||
if test x"$$FLAGS" != x"`cat GIT-SPATCH-DEFINES 2>/dev/null`" ; then \
|
||||
echo >&2 " * new spatch flags"; \
|
||||
echo "$$FLAGS" >GIT-SPATCH-DEFINES; \
|
||||
fi
|
||||
|
||||
include config.mak.uname
|
||||
-include config.mak.autogen
|
||||
-include config.mak
|
||||
|
||||
ifdef DEVELOPER
|
||||
include config.mak.dev
|
||||
endif
|
||||
|
||||
GENERATED_H += command-list.h
|
||||
GENERATED_H += config-list.h
|
||||
GENERATED_H += hook-list.h
|
||||
@ -1198,7 +1316,9 @@ LIB_OBJS += urlmatch.o
|
||||
LIB_OBJS += usage.o
|
||||
LIB_OBJS += userdiff.o
|
||||
LIB_OBJS += utf8.o
|
||||
ifndef WITH_RUST
|
||||
LIB_OBJS += varint.o
|
||||
endif
|
||||
LIB_OBJS += version.o
|
||||
LIB_OBJS += versioncmp.o
|
||||
LIB_OBJS += walker.o
|
||||
@ -1390,93 +1510,8 @@ CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/unit-test.o
|
||||
|
||||
UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o
|
||||
|
||||
# xdiff and reftable libs may in turn depend on what is in libgit.a
|
||||
GITLIBS = common-main.o $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(LIB_FILE)
|
||||
EXTLIBS =
|
||||
|
||||
GIT_USER_AGENT = git/$(GIT_VERSION)
|
||||
|
||||
ifeq ($(wildcard sha1collisiondetection/lib/sha1.h),sha1collisiondetection/lib/sha1.h)
|
||||
DC_SHA1_SUBMODULE = auto
|
||||
endif
|
||||
|
||||
# Set CFLAGS, LDFLAGS and other *FLAGS variables. These might be
|
||||
# tweaked by config.* below as well as the command-line, both of
|
||||
# which'll override these defaults.
|
||||
# Older versions of GCC may require adding "-std=gnu99" at the end.
|
||||
CFLAGS = -g -O2 -Wall
|
||||
LDFLAGS =
|
||||
CC_LD_DYNPATH = -Wl,-rpath,
|
||||
BASIC_CFLAGS = -I.
|
||||
BASIC_LDFLAGS =
|
||||
|
||||
# library flags
|
||||
ARFLAGS = rcs
|
||||
PTHREAD_CFLAGS =
|
||||
|
||||
# For the 'sparse' target
|
||||
SPARSE_FLAGS ?= -std=gnu99 -D__STDC_NO_VLA__
|
||||
SP_EXTRA_FLAGS =
|
||||
|
||||
# For informing GIT-BUILD-OPTIONS of the SANITIZE=leak,address targets
|
||||
SANITIZE_LEAK =
|
||||
SANITIZE_ADDRESS =
|
||||
|
||||
# For the 'coccicheck' target
|
||||
SPATCH_INCLUDE_FLAGS = --all-includes
|
||||
SPATCH_FLAGS =
|
||||
SPATCH_TEST_FLAGS =
|
||||
|
||||
# If *.o files are present, have "coccicheck" depend on them, with
|
||||
# COMPUTE_HEADER_DEPENDENCIES this will speed up the common-case of
|
||||
# only needing to re-generate coccicheck results for the users of a
|
||||
# given API if it's changed, and not all files in the project. If
|
||||
# COMPUTE_HEADER_DEPENDENCIES=no this will be unset too.
|
||||
SPATCH_USE_O_DEPENDENCIES = YesPlease
|
||||
|
||||
# Set SPATCH_CONCAT_COCCI to concatenate the contrib/cocci/*.cocci
|
||||
# files into a single contrib/cocci/ALL.cocci before running
|
||||
# "coccicheck".
|
||||
#
|
||||
# Pros:
|
||||
#
|
||||
# - Speeds up a one-shot run of "make coccicheck", as we won't have to
|
||||
# parse *.[ch] files N times for the N *.cocci rules
|
||||
#
|
||||
# Cons:
|
||||
#
|
||||
# - Will make incremental development of *.cocci slower, as
|
||||
# e.g. changing strbuf.cocci will re-run all *.cocci.
|
||||
#
|
||||
# - Makes error and performance analysis harder, as rules will be
|
||||
# applied from a monolithic ALL.cocci, rather than
|
||||
# e.g. strbuf.cocci. To work around this either undefine this, or
|
||||
# generate a specific patch, e.g. this will always use strbuf.cocci,
|
||||
# not ALL.cocci:
|
||||
#
|
||||
# make contrib/coccinelle/strbuf.cocci.patch
|
||||
SPATCH_CONCAT_COCCI = YesPlease
|
||||
|
||||
# Rebuild 'coccicheck' if $(SPATCH), its flags etc. change
|
||||
TRACK_SPATCH_DEFINES =
|
||||
TRACK_SPATCH_DEFINES += $(SPATCH)
|
||||
TRACK_SPATCH_DEFINES += $(SPATCH_INCLUDE_FLAGS)
|
||||
TRACK_SPATCH_DEFINES += $(SPATCH_FLAGS)
|
||||
TRACK_SPATCH_DEFINES += $(SPATCH_TEST_FLAGS)
|
||||
GIT-SPATCH-DEFINES: FORCE
|
||||
@FLAGS='$(TRACK_SPATCH_DEFINES)'; \
|
||||
if test x"$$FLAGS" != x"`cat GIT-SPATCH-DEFINES 2>/dev/null`" ; then \
|
||||
echo >&2 " * new spatch flags"; \
|
||||
echo "$$FLAGS" >GIT-SPATCH-DEFINES; \
|
||||
fi
|
||||
|
||||
include config.mak.uname
|
||||
-include config.mak.autogen
|
||||
-include config.mak
|
||||
|
||||
ifdef DEVELOPER
|
||||
include config.mak.dev
|
||||
endif
|
||||
RUST_SOURCES += src/lib.rs
|
||||
RUST_SOURCES += src/varint.rs
|
||||
|
||||
GIT-VERSION-FILE: FORCE
|
||||
@OLD=$$(cat $@ 2>/dev/null || :) && \
|
||||
@ -1507,6 +1542,14 @@ endif
|
||||
ALL_CFLAGS = $(DEVELOPER_CFLAGS) $(CPPFLAGS) $(CFLAGS) $(CFLAGS_APPEND)
|
||||
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
|
||||
SANITIZERS := $(foreach flag,$(subst $(comma),$(space),$(SANITIZE)),$(flag))
|
||||
BASIC_CFLAGS += -fsanitize=$(SANITIZE) -fno-sanitize-recover=$(SANITIZE)
|
||||
@ -2921,6 +2964,12 @@ scalar$X: scalar.o GIT-LDFLAGS $(GITLIBS)
|
||||
$(LIB_FILE): $(LIB_OBJS)
|
||||
$(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^
|
||||
|
||||
$(RUST_LIB): Cargo.toml $(RUST_SOURCES)
|
||||
$(QUIET_CARGO)cargo build $(CARGO_ARGS)
|
||||
|
||||
.PHONY: rust
|
||||
rust: $(RUST_LIB)
|
||||
|
||||
$(XDIFF_LIB): $(XDIFF_OBJS)
|
||||
$(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^
|
||||
|
||||
@ -3771,6 +3820,7 @@ clean: profile-clean coverage-clean cocciclean
|
||||
$(RM) $(FUZZ_PROGRAMS)
|
||||
$(RM) $(SP_OBJ)
|
||||
$(RM) $(HCC)
|
||||
$(RM) -r Cargo.lock target/
|
||||
$(RM) version-def.h
|
||||
$(RM) -r $(dep_dirs) $(compdb_dir) compile_commands.json
|
||||
$(RM) $(test_bindir_programs)
|
||||
|
||||
@ -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,
|
||||
@ -30,8 +32,12 @@ alpine-*)
|
||||
bash cvs gnupg perl-cgi perl-dbd-sqlite perl-io-tty >/dev/null
|
||||
;;
|
||||
fedora-*|almalinux-*)
|
||||
case "$jobname" in
|
||||
*-meson)
|
||||
MESON_DEPS="meson ninja";;
|
||||
esac
|
||||
dnf -yq update >/dev/null &&
|
||||
dnf -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
|
||||
dnf -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
|
||||
;;
|
||||
ubuntu-*|i386/ubuntu-*|debian-*)
|
||||
# Required so that apt doesn't wait for user input on certain packages.
|
||||
@ -58,7 +64,7 @@ ubuntu-*|i386/ubuntu-*|debian-*)
|
||||
make libssl-dev libcurl4-openssl-dev libexpat-dev wget sudo default-jre \
|
||||
tcl tk gettext zlib1g-dev perl-modules liberror-perl libauthen-sasl-perl \
|
||||
libemail-valid-perl libio-pty-perl libio-socket-ssl-perl libnet-smtp-ssl-perl libdbd-sqlite3-perl libcgi-pm-perl \
|
||||
libsecret-1-dev libpcre2-dev meson ninja-build pkg-config \
|
||||
libsecret-1-dev libpcre2-dev meson ninja-build pkg-config cargo \
|
||||
${CC_PACKAGE:-${CC:-gcc}} $PYTHON_PACKAGE
|
||||
|
||||
case "$distro" in
|
||||
@ -116,21 +122,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" ||
|
||||
|
||||
@ -5,11 +5,12 @@
|
||||
|
||||
. ${0%/*}/lib.sh
|
||||
|
||||
run_tests=t
|
||||
|
||||
case "$jobname" in
|
||||
linux-breaking-changes)
|
||||
fedora-breaking-changes-musl|linux-breaking-changes)
|
||||
export WITH_BREAKING_CHANGES=YesPlease
|
||||
export WITH_RUST=YesPlease
|
||||
MESONFLAGS="$MESONFLAGS -Dbreaking_changes=true"
|
||||
MESONFLAGS="$MESONFLAGS -Drust=enabled"
|
||||
;;
|
||||
linux-TEST-vars)
|
||||
export OPENSSL_SHA1_UNSAFE=YesPlease
|
||||
@ -35,12 +36,6 @@ linux-sha256)
|
||||
linux-reftable|linux-reftable-leaks|osx-reftable)
|
||||
export GIT_TEST_DEFAULT_REF_FORMAT=reftable
|
||||
;;
|
||||
pedantic)
|
||||
# Don't run the tests; we only care about whether Git can be
|
||||
# built.
|
||||
export DEVOPTS=pedantic
|
||||
run_tests=
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$jobname" in
|
||||
@ -53,21 +48,15 @@ case "$jobname" in
|
||||
-Dtest_output_directory="${TEST_OUTPUT_DIRECTORY:-$(pwd)/t}" \
|
||||
$MESONFLAGS
|
||||
group "Build" meson compile -C build --
|
||||
if test -n "$run_tests"
|
||||
then
|
||||
group "Run tests" meson test -C build --print-errorlogs --test-args="$GIT_TEST_OPTS" || (
|
||||
./t/aggregate-results.sh "${TEST_OUTPUT_DIRECTORY:-t}/test-results"
|
||||
handle_failed_tests
|
||||
)
|
||||
fi
|
||||
group "Run tests" meson test -C build --print-errorlogs --test-args="$GIT_TEST_OPTS" || (
|
||||
./t/aggregate-results.sh "${TEST_OUTPUT_DIRECTORY:-t}/test-results"
|
||||
handle_failed_tests
|
||||
)
|
||||
;;
|
||||
*)
|
||||
group Build make
|
||||
if test -n "$run_tests"
|
||||
then
|
||||
group "Run tests" make test ||
|
||||
handle_failed_tests
|
||||
fi
|
||||
group "Run tests" make test ||
|
||||
handle_failed_tests
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
22
ci/run-rust-checks.sh
Executable file
22
ci/run-rust-checks.sh
Executable 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
|
||||
18
dir.c
18
dir.c
@ -3579,7 +3579,8 @@ static void write_one_dir(struct untracked_cache_dir *untracked,
|
||||
struct stat_data stat_data;
|
||||
struct strbuf *out = &wd->out;
|
||||
unsigned char intbuf[16];
|
||||
unsigned int intlen, value;
|
||||
unsigned int value;
|
||||
uint8_t intlen;
|
||||
int i = wd->index++;
|
||||
|
||||
/*
|
||||
@ -3632,7 +3633,7 @@ void write_untracked_extension(struct strbuf *out, struct untracked_cache *untra
|
||||
struct ondisk_untracked_cache *ouc;
|
||||
struct write_data wd;
|
||||
unsigned char varbuf[16];
|
||||
int varint_len;
|
||||
uint8_t varint_len;
|
||||
const unsigned hashsz = the_hash_algo->rawsz;
|
||||
|
||||
CALLOC_ARRAY(ouc, 1);
|
||||
@ -3738,7 +3739,7 @@ static int read_one_dir(struct untracked_cache_dir **untracked_,
|
||||
struct untracked_cache_dir ud, *untracked;
|
||||
const unsigned char *data = rd->data, *end = rd->end;
|
||||
const unsigned char *eos;
|
||||
unsigned int value;
|
||||
uint64_t value;
|
||||
int i;
|
||||
|
||||
memset(&ud, 0, sizeof(ud));
|
||||
@ -3830,7 +3831,8 @@ struct untracked_cache *read_untracked_extension(const void *data, unsigned long
|
||||
struct read_data rd;
|
||||
const unsigned char *next = data, *end = (const unsigned char *)data + sz;
|
||||
const char *ident;
|
||||
int ident_len;
|
||||
uint64_t ident_len;
|
||||
uint64_t varint_len;
|
||||
ssize_t len;
|
||||
const char *exclude_per_dir;
|
||||
const unsigned hashsz = the_hash_algo->rawsz;
|
||||
@ -3867,8 +3869,8 @@ struct untracked_cache *read_untracked_extension(const void *data, unsigned long
|
||||
if (next >= end)
|
||||
goto done2;
|
||||
|
||||
len = decode_varint(&next);
|
||||
if (next > end || len == 0)
|
||||
varint_len = decode_varint(&next);
|
||||
if (next > end || varint_len == 0)
|
||||
goto done2;
|
||||
|
||||
rd.valid = ewah_new();
|
||||
@ -3877,9 +3879,9 @@ struct untracked_cache *read_untracked_extension(const void *data, unsigned long
|
||||
rd.data = next;
|
||||
rd.end = end;
|
||||
rd.index = 0;
|
||||
ALLOC_ARRAY(rd.ucd, len);
|
||||
ALLOC_ARRAY(rd.ucd, varint_len);
|
||||
|
||||
if (read_one_dir(&uc->root, &rd) || rd.index != len)
|
||||
if (read_one_dir(&uc->root, &rd) || rd.index != varint_len)
|
||||
goto done;
|
||||
|
||||
next = rd.data;
|
||||
|
||||
6
help.c
6
help.c
@ -791,6 +791,12 @@ void get_version_info(struct strbuf *buf, int show_build_options)
|
||||
strbuf_addf(buf, "shell-path: %s\n", SHELL_PATH);
|
||||
/* NEEDSWORK: also save and output GIT-BUILD_OPTIONS? */
|
||||
|
||||
#if defined WITH_RUST
|
||||
strbuf_addstr(buf, "rust: enabled\n");
|
||||
#else
|
||||
strbuf_addstr(buf, "rust: disabled\n");
|
||||
#endif
|
||||
|
||||
if (fsmonitor_ipc__is_supported())
|
||||
strbuf_addstr(buf, "feature: fsmonitor--daemon\n");
|
||||
#if defined LIBCURL_VERSION
|
||||
|
||||
19
meson.build
19
meson.build
@ -220,7 +220,7 @@ project('git', 'c',
|
||||
# learned to define __STDC_VERSION__ with C11 and later. We thus require
|
||||
# GNU C99 and fall back to C11. Meson only learned to handle the fallback
|
||||
# with version 1.3.0, so on older versions we use GNU C99 unconditionally.
|
||||
default_options: meson.version().version_compare('>=1.3.0') ? ['c_std=gnu99,c11'] : ['c_std=gnu99'],
|
||||
default_options: meson.version().version_compare('>=1.3.0') ? ['rust_std=2018', 'c_std=gnu99,c11'] : ['rust_std=2018', 'c_std=gnu99'],
|
||||
)
|
||||
|
||||
fs = import('fs')
|
||||
@ -522,7 +522,6 @@ libgit_sources = [
|
||||
'usage.c',
|
||||
'userdiff.c',
|
||||
'utf8.c',
|
||||
'varint.c',
|
||||
'version.c',
|
||||
'versioncmp.c',
|
||||
'walker.c',
|
||||
@ -1703,6 +1702,21 @@ version_def_h = custom_target(
|
||||
)
|
||||
libgit_sources += version_def_h
|
||||
|
||||
cargo = find_program('cargo', dirs: program_path, native: true, required: get_option('rust'))
|
||||
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',
|
||||
]
|
||||
endif
|
||||
|
||||
libgit = declare_dependency(
|
||||
link_with: static_library('git',
|
||||
sources: libgit_sources,
|
||||
@ -2249,6 +2263,7 @@ summary({
|
||||
'pcre2': pcre2,
|
||||
'perl': perl_features_enabled,
|
||||
'python': target_python.found(),
|
||||
'rust': rust_option.allowed(),
|
||||
}, section: 'Auto-detected features', bool_yn: true)
|
||||
|
||||
summary({
|
||||
|
||||
@ -71,6 +71,8 @@ option('zlib_backend', type: 'combo', choices: ['auto', 'zlib', 'zlib-ng'], valu
|
||||
# Build tweaks.
|
||||
option('breaking_changes', type: 'boolean', value: false,
|
||||
description: 'Enable upcoming breaking changes.')
|
||||
option('rust', type: 'feature', value: 'auto',
|
||||
description: 'Enable building with Rust.')
|
||||
option('macos_use_homebrew_gettext', type: 'boolean', value: true,
|
||||
description: 'Use gettext from Homebrew instead of the slightly-broken system-provided one.')
|
||||
|
||||
|
||||
@ -1806,7 +1806,7 @@ static struct cache_entry *create_from_disk(struct mem_pool *ce_mem_pool,
|
||||
|
||||
if (expand_name_field) {
|
||||
const unsigned char *cp = (const unsigned char *)name;
|
||||
size_t strip_len, previous_len;
|
||||
uint64_t strip_len, previous_len;
|
||||
|
||||
/* If we're at the beginning of a block, ignore the previous name */
|
||||
strip_len = decode_varint(&cp);
|
||||
@ -2654,8 +2654,10 @@ static int ce_write_entry(struct hashfile *f, struct cache_entry *ce,
|
||||
hashwrite(f, ce->name, len);
|
||||
hashwrite(f, padding, align_padding_size(size, len));
|
||||
} else {
|
||||
int common, to_remove, prefix_size;
|
||||
int common, to_remove;
|
||||
uint8_t prefix_size;
|
||||
unsigned char to_remove_vi[16];
|
||||
|
||||
for (common = 0;
|
||||
(common < previous_name->len &&
|
||||
ce->name[common] &&
|
||||
|
||||
@ -56,6 +56,7 @@ ifndef V
|
||||
QUIET_MKDIR_P_PARENT = @echo ' ' MKDIR -p $(@D);
|
||||
|
||||
## Used in "Makefile"
|
||||
QUIET_CARGO = @echo ' ' CARGO $@;
|
||||
QUIET_CC = @echo ' ' CC $@;
|
||||
QUIET_AR = @echo ' ' AR $@;
|
||||
QUIET_LINK = @echo ' ' LINK $@;
|
||||
|
||||
39
src/cargo-meson.sh
Executable file
39
src/cargo-meson.sh
Executable file
@ -0,0 +1,39 @@
|
||||
#!/bin/sh
|
||||
|
||||
if test "$#" -lt 2
|
||||
then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SOURCE_DIR="$1"
|
||||
BUILD_DIR="$2"
|
||||
BUILD_TYPE=debug
|
||||
|
||||
shift 2
|
||||
|
||||
for arg
|
||||
do
|
||||
case "$arg" in
|
||||
--release)
|
||||
BUILD_TYPE=release;;
|
||||
esac
|
||||
done
|
||||
|
||||
cargo build --lib --quiet --manifest-path="$SOURCE_DIR/Cargo.toml" --target-dir="$BUILD_DIR" "$@"
|
||||
RET=$?
|
||||
if test $RET -ne 0
|
||||
then
|
||||
exit $RET
|
||||
fi
|
||||
|
||||
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/$LIBNAME" "$BUILD_DIR/libgitcore.a"
|
||||
fi
|
||||
1
src/lib.rs
Normal file
1
src/lib.rs
Normal file
@ -0,0 +1 @@
|
||||
pub mod varint;
|
||||
41
src/meson.build
Normal file
41
src/meson.build
Normal file
@ -0,0 +1,41 @@
|
||||
libgit_rs_sources = [
|
||||
'lib.rs',
|
||||
'varint.rs',
|
||||
]
|
||||
|
||||
# Unfortunately we must use a wrapper command to move the output file into the
|
||||
# current build directory. This can fixed once `cargo build --artifact-dir`
|
||||
# stabilizes. See https://github.com/rust-lang/cargo/issues/6790 for that
|
||||
# effort.
|
||||
cargo_command = [
|
||||
shell,
|
||||
meson.current_source_dir() / 'cargo-meson.sh',
|
||||
meson.project_source_root(),
|
||||
meson.current_build_dir(),
|
||||
]
|
||||
if get_option('buildtype') == 'release'
|
||||
cargo_command += '--release'
|
||||
endif
|
||||
|
||||
libgit_rs = custom_target('git_rs',
|
||||
input: libgit_rs_sources + [
|
||||
meson.project_source_root() / 'Cargo.toml',
|
||||
],
|
||||
output: 'libgitcore.a',
|
||||
command: cargo_command,
|
||||
)
|
||||
libgit_dependencies += declare_dependency(link_with: libgit_rs)
|
||||
|
||||
if get_option('tests')
|
||||
test('rust', cargo,
|
||||
args: [
|
||||
'test',
|
||||
'--manifest-path',
|
||||
meson.project_source_root() / 'Cargo.toml',
|
||||
'--target-dir',
|
||||
meson.current_build_dir() / 'target',
|
||||
],
|
||||
timeout: 0,
|
||||
protocol: 'rust',
|
||||
)
|
||||
endif
|
||||
107
src/varint.rs
Normal file
107
src/varint.rs
Normal file
@ -0,0 +1,107 @@
|
||||
/// 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;
|
||||
let mut c = *buf;
|
||||
let mut val = u64::from(c & 127);
|
||||
|
||||
buf = buf.add(1);
|
||||
|
||||
while (c & 128) != 0 {
|
||||
val = val.wrapping_add(1);
|
||||
if val == 0 || val.leading_zeros() < 7 {
|
||||
return 0; // overflow
|
||||
}
|
||||
|
||||
c = *buf;
|
||||
buf = buf.add(1);
|
||||
|
||||
val = (val << 7) + u64::from(c & 127);
|
||||
}
|
||||
|
||||
*bufp = buf;
|
||||
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];
|
||||
let mut pos = varint.len() - 1;
|
||||
|
||||
varint[pos] = (value & 127) as u8;
|
||||
|
||||
let mut value = value >> 7;
|
||||
while value != 0 {
|
||||
pos -= 1;
|
||||
value -= 1;
|
||||
varint[pos] = 128 | (value & 127) as u8;
|
||||
value >>= 7;
|
||||
}
|
||||
|
||||
if !buf.is_null() {
|
||||
std::ptr::copy_nonoverlapping(varint.as_ptr().add(pos), buf, varint.len() - pos);
|
||||
}
|
||||
|
||||
(varint.len() - pos) as u8
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_decode_varint() {
|
||||
unsafe {
|
||||
assert_eq!(decode_varint(&mut [0x00].as_slice().as_ptr()), 0);
|
||||
assert_eq!(decode_varint(&mut [0x01].as_slice().as_ptr()), 1);
|
||||
assert_eq!(decode_varint(&mut [0x7f].as_slice().as_ptr()), 127);
|
||||
assert_eq!(decode_varint(&mut [0x80, 0x00].as_slice().as_ptr()), 128);
|
||||
assert_eq!(decode_varint(&mut [0x80, 0x01].as_slice().as_ptr()), 129);
|
||||
assert_eq!(decode_varint(&mut [0x80, 0x7f].as_slice().as_ptr()), 255);
|
||||
|
||||
// Overflows are expected to return 0.
|
||||
assert_eq!(decode_varint(&mut [0x88; 16].as_slice().as_ptr()), 0);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_encode_varint() {
|
||||
unsafe {
|
||||
let mut varint: [u8; 16] = [0; 16];
|
||||
|
||||
assert_eq!(encode_varint(0, std::ptr::null_mut()), 1);
|
||||
|
||||
assert_eq!(encode_varint(0, varint.as_mut_slice().as_mut_ptr()), 1);
|
||||
assert_eq!(varint, [0; 16]);
|
||||
|
||||
assert_eq!(encode_varint(10, varint.as_mut_slice().as_mut_ptr()), 1);
|
||||
assert_eq!(varint, [10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
||||
|
||||
assert_eq!(encode_varint(127, varint.as_mut_slice().as_mut_ptr()), 1);
|
||||
assert_eq!(varint, [127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
||||
|
||||
assert_eq!(encode_varint(128, varint.as_mut_slice().as_mut_ptr()), 2);
|
||||
assert_eq!(varint, [128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
||||
|
||||
assert_eq!(encode_varint(129, varint.as_mut_slice().as_mut_ptr()), 2);
|
||||
assert_eq!(varint, [128, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
||||
|
||||
assert_eq!(encode_varint(255, varint.as_mut_slice().as_mut_ptr()), 2);
|
||||
assert_eq!(varint, [128, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -33,7 +33,6 @@ check_last_modified() {
|
||||
done &&
|
||||
|
||||
cat >expect &&
|
||||
test_when_finished "rm -f tmp.*" &&
|
||||
git ${indir:+-C "$indir"} last-modified "$@" >tmp.1 &&
|
||||
git name-rev --annotate-stdin --name-only --tags \
|
||||
<tmp.1 >tmp.2 &&
|
||||
@ -128,20 +127,25 @@ test_expect_success 'only last-modified files in the current tree' '
|
||||
EOF
|
||||
'
|
||||
|
||||
test_expect_success 'last-modified with subdir and criss-cross merge' '
|
||||
git checkout -b branch-k1 1 &&
|
||||
mkdir -p a k &&
|
||||
test_commit k1 a/file2 &&
|
||||
git checkout -b branch-k2 &&
|
||||
test_commit k2 k/file2 &&
|
||||
git checkout branch-k1 &&
|
||||
test_merge km2 branch-k2 &&
|
||||
test_merge km3 3 &&
|
||||
check_last_modified <<-\EOF
|
||||
km3 a
|
||||
k2 k
|
||||
1 file
|
||||
EOF
|
||||
test_expect_success 'subdirectory modified via merge' '
|
||||
test_when_finished rm -rf repo &&
|
||||
git init repo &&
|
||||
(
|
||||
cd repo &&
|
||||
test_commit base &&
|
||||
git switch --create left &&
|
||||
mkdir subdir &&
|
||||
test_commit left subdir/left &&
|
||||
git switch --create right base &&
|
||||
mkdir subdir &&
|
||||
test_commit right subdir/right &&
|
||||
git switch - &&
|
||||
test_merge merge right &&
|
||||
check_last_modified <<-\EOF
|
||||
merge subdir
|
||||
base base.t
|
||||
EOF
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'cross merge boundaries in blaming' '
|
||||
|
||||
6
varint.c
6
varint.c
@ -1,11 +1,11 @@
|
||||
#include "git-compat-util.h"
|
||||
#include "varint.h"
|
||||
|
||||
uintmax_t decode_varint(const unsigned char **bufp)
|
||||
uint64_t decode_varint(const unsigned char **bufp)
|
||||
{
|
||||
const unsigned char *buf = *bufp;
|
||||
unsigned char c = *buf++;
|
||||
uintmax_t val = c & 127;
|
||||
uint64_t val = c & 127;
|
||||
while (c & 128) {
|
||||
val += 1;
|
||||
if (!val || MSB(val, 7))
|
||||
@ -17,7 +17,7 @@ uintmax_t decode_varint(const unsigned char **bufp)
|
||||
return val;
|
||||
}
|
||||
|
||||
int encode_varint(uintmax_t value, unsigned char *buf)
|
||||
uint8_t encode_varint(uint64_t value, unsigned char *buf)
|
||||
{
|
||||
unsigned char varint[16];
|
||||
unsigned pos = sizeof(varint) - 1;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user